aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuc Donnet2018-02-19 11:04:29 +0100
committerLuc Donnet2018-02-19 11:04:29 +0100
commit7b17deff51545358009cb417cbb9d796565e7540 (patch)
treea43a5586ad39d838dd607e600dbc15ff18a58ab3
parent89428163fc93a7e09ebb0ca47939f8558afeb5eb (diff)
parent5f6008d165df4499319a2121a71842657d6ac3c9 (diff)
downloadchouette-core-7b17deff51545358009cb417cbb9d796565e7540.tar.bz2
Merge branch 'master' into 0000-docker
-rw-r--r--.gitignore6
-rw-r--r--DEVNOTES.md2
-rw-r--r--Gemfile10
-rw-r--r--Gemfile.lock71
-rw-r--r--Gruntfile.coffee47
-rw-r--r--INSTALL.md188
-rw-r--r--README.md162
-rw-r--r--app/assets/javascripts/application.js3
-rw-r--r--app/assets/javascripts/forms.coffee19
-rw-r--r--app/assets/javascripts/i18n/extended.coffee24
-rw-r--r--app/assets/javascripts/main_menu.coffee44
-rw-r--r--app/assets/javascripts/select2.coffee17
-rw-r--r--app/assets/stylesheets/OpenLayers/custom.sass20
-rw-r--r--app/assets/stylesheets/_layout.sass1
-rw-r--r--app/assets/stylesheets/application.sass2
-rw-r--r--app/assets/stylesheets/base/_config.sass2
-rw-r--r--app/assets/stylesheets/base/_utilities.sass2
-rw-r--r--app/assets/stylesheets/components/_breadcrumb.sass5
-rw-r--r--app/assets/stylesheets/components/_buttons.sass45
-rw-r--r--app/assets/stylesheets/components/_color_selector.sass21
-rw-r--r--app/assets/stylesheets/components/_dropdown.sass22
-rw-r--r--app/assets/stylesheets/components/_forms.sass54
-rw-r--r--app/assets/stylesheets/components/_lists.sass5
-rw-r--r--app/assets/stylesheets/components/_main_nav.sass45
-rw-r--r--app/assets/stylesheets/components/_panels.sass1
-rw-r--r--app/assets/stylesheets/components/_referential_overview.sass346
-rw-r--r--app/assets/stylesheets/components/_referentials.sass4
-rw-r--r--app/assets/stylesheets/components/_select2.sass8
-rw-r--r--app/assets/stylesheets/components/_tables.sass35
-rw-r--r--app/assets/stylesheets/components/_toolbar.sass49
-rw-r--r--app/assets/stylesheets/modules/_jp_collection.sass230
-rw-r--r--app/assets/stylesheets/modules/_timetables.sass2
-rw-r--r--app/assets/stylesheets/modules/_vj_collection.sass6
-rw-r--r--app/assets/stylesheets/modules/import_messages.sass5
-rw-r--r--app/assets/stylesheets/typography/_sboiv.sass4
-rw-r--r--app/controllers/api_keys_controller.rb7
-rw-r--r--app/controllers/application_controller.rb19
-rw-r--r--app/controllers/autocomplete_purchase_windows_controller.rb12
-rw-r--r--app/controllers/autocomplete_stop_areas_controller.rb11
-rw-r--r--app/controllers/calendars_controller.rb75
-rw-r--r--app/controllers/companies_controller.rb10
-rw-r--r--app/controllers/compliance_check_messages_controller.rb34
-rw-r--r--app/controllers/compliance_check_sets_controller.rb22
-rw-r--r--app/controllers/compliance_control_sets_controller.rb50
-rw-r--r--app/controllers/compliance_controls_controller.rb6
-rw-r--r--app/controllers/concerns/activatable.rb11
-rw-r--r--app/controllers/concerns/feature_checker.rb42
-rw-r--r--app/controllers/concerns/ransack_date_filter.rb28
-rw-r--r--app/controllers/development_toolbar_controller.rb11
-rw-r--r--app/controllers/group_of_lines_controller.rb5
-rw-r--r--app/controllers/import_messages_controller.rb2
-rw-r--r--app/controllers/import_resources_controller.rb8
-rw-r--r--app/controllers/imports_controller.rb3
-rw-r--r--app/controllers/journey_patterns_collections_controller.rb67
-rw-r--r--app/controllers/line_referentials_controller.rb1
-rw-r--r--app/controllers/lines_controller.rb10
-rw-r--r--app/controllers/merges_controller.rb40
-rw-r--r--app/controllers/networks_controller.rb7
-rw-r--r--app/controllers/purchase_windows_controller.rb74
-rw-r--r--app/controllers/referential_companies_controller.rb10
-rw-r--r--app/controllers/referential_lines_controller.rb3
-rw-r--r--app/controllers/referential_networks_controller.rb7
-rw-r--r--app/controllers/referential_vehicle_journeys_controller.rb30
-rw-r--r--app/controllers/referentials_controller.rb29
-rw-r--r--app/controllers/routes_controller.rb5
-rw-r--r--app/controllers/routing_constraint_zones_controller.rb3
-rw-r--r--app/controllers/snapshots_controller.rb14
-rw-r--r--app/controllers/statuses_controller.rb20
-rw-r--r--app/controllers/stop_area_referentials_controller.rb1
-rw-r--r--app/controllers/stop_areas_controller.rb56
-rw-r--r--app/controllers/time_tables_controller.rb5
-rw-r--r--app/controllers/vehicle_journeys_controller.rb129
-rw-r--r--app/controllers/workbench_outputs_controller.rb9
-rw-r--r--app/controllers/workbenches_controller.rb3
-rw-r--r--app/decorators/api_key_decorator.rb30
-rw-r--r--app/decorators/calendar_decorator.rb23
-rw-r--r--app/decorators/company_decorator.rb52
-rw-r--r--app/decorators/compliance_check_decorator.rb8
-rw-r--r--app/decorators/compliance_check_set_decorator.rb21
-rw-r--r--app/decorators/compliance_control_decorator.rb51
-rw-r--r--app/decorators/compliance_control_set_decorator.rb43
-rw-r--r--app/decorators/import_decorator.rb42
-rw-r--r--app/decorators/import_resource_decorator.rb10
-rw-r--r--app/decorators/import_resources_decorator.rb2
-rw-r--r--app/decorators/line_decorator.rb105
-rw-r--r--app/decorators/network_decorator.rb46
-rw-r--r--app/decorators/purchase_window_decorator.rb28
-rw-r--r--app/decorators/referential_decorator.rb94
-rw-r--r--app/decorators/referential_line_decorator.rb73
-rw-r--r--app/decorators/referential_network_decorator.rb47
-rw-r--r--app/decorators/route_decorator.rb89
-rw-r--r--app/decorators/routing_constraint_zone_decorator.rb45
-rw-r--r--app/decorators/stop_area_decorator.rb69
-rw-r--r--app/decorators/stop_point_decorator.rb34
-rw-r--r--app/decorators/time_table_decorator.rb66
-rw-r--r--app/errors/table_lock_timeout_error.rb1
-rw-r--r--app/helpers/application_helper.rb21
-rw-r--r--app/helpers/breadcrumb_helper.rb9
-rw-r--r--app/helpers/common_helpers.rb26
-rw-r--r--app/helpers/compliance_check_resources_helper.rb12
-rw-r--r--app/helpers/compliance_check_sets_helper.rb6
-rw-r--r--app/helpers/compliance_control_sets_helper.rb3
-rw-r--r--app/helpers/imports_helper.rb14
-rw-r--r--app/helpers/links_helper.rb15
-rw-r--r--app/helpers/newapplication_helper.rb3
-rw-r--r--app/helpers/pagination_helper.rb2
-rw-r--r--app/helpers/referentials_helper.rb5
-rw-r--r--app/helpers/routes_helper.rb8
-rw-r--r--app/helpers/search_helper.rb15
-rw-r--r--app/helpers/stop_areas_helper.rb6
-rw-r--r--app/helpers/table_builder_helper.rb200
-rw-r--r--app/helpers/table_builder_helper/custom_links.rb7
-rw-r--r--app/helpers/table_builder_helper/url.rb5
-rw-r--r--app/helpers/time_tables_helper.rb2
-rw-r--r--app/helpers/vehicle_journeys_helper.rb24
-rw-r--r--app/inputs/color_select_input.rb44
-rw-r--r--app/javascript/date_filters/index.js2
-rw-r--r--app/javascript/date_filters/purchase_window.js5
-rw-r--r--app/javascript/helpers/master_slave.coffee16
-rw-r--r--app/javascript/helpers/routes_map.coffee161
-rw-r--r--app/javascript/helpers/save_button.js47
-rw-r--r--app/javascript/helpers/stop_area_header_manager.js56
-rw-r--r--app/javascript/journey_patterns/actions/index.js23
-rw-r--r--app/javascript/journey_patterns/components/ConfirmModal.js4
-rw-r--r--app/javascript/journey_patterns/components/CreateModal.js3
-rw-r--r--app/javascript/journey_patterns/components/EditModal.js16
-rw-r--r--app/javascript/journey_patterns/components/JourneyPattern.js131
-rw-r--r--app/javascript/journey_patterns/components/JourneyPatterns.js42
-rw-r--r--app/javascript/journey_patterns/components/Navigate.js3
-rw-r--r--app/javascript/journey_patterns/components/SaveJourneyPattern.js41
-rw-r--r--app/javascript/journey_patterns/containers/JourneyPatternList.js5
-rw-r--r--app/javascript/journey_patterns/reducers/journeyPatterns.js16
-rw-r--r--app/javascript/packs/calendars/edit.js74
-rw-r--r--app/javascript/packs/journey_patterns/index.js1
-rw-r--r--app/javascript/packs/referential_lines/show.js10
-rw-r--r--app/javascript/packs/referential_overview/overview.js1
-rw-r--r--app/javascript/packs/routes/edit.js6
-rw-r--r--app/javascript/packs/routes/show.js104
-rw-r--r--app/javascript/packs/stop_areas/new.js3
-rw-r--r--app/javascript/packs/vehicle_journeys/index.js12
-rw-r--r--app/javascript/referential_overview/index.coffee113
-rw-r--r--app/javascript/routes/components/App.js7
-rw-r--r--app/javascript/routes/components/BSelect2.js30
-rw-r--r--app/javascript/routes/components/OlMap.js27
-rw-r--r--app/javascript/routes/components/StopPoint.js16
-rw-r--r--app/javascript/routes/components/StopPointList.js16
-rw-r--r--app/javascript/routes/form_helper.js17
-rw-r--r--app/javascript/routes/reducers/stopPoints.js10
-rw-r--r--app/javascript/time_tables/actions/index.js27
-rw-r--r--app/javascript/time_tables/components/ConfirmModal.js14
-rw-r--r--app/javascript/time_tables/components/ErrorModal.js10
-rw-r--r--app/javascript/time_tables/components/ExceptionsInDay.js3
-rw-r--r--app/javascript/time_tables/components/Metas.js28
-rw-r--r--app/javascript/time_tables/components/Navigate.js9
-rw-r--r--app/javascript/time_tables/components/PeriodForm.js18
-rw-r--r--app/javascript/time_tables/components/PeriodManager.js3
-rw-r--r--app/javascript/time_tables/components/PeriodsInDay.js3
-rw-r--r--app/javascript/time_tables/components/SaveTimetable.js3
-rw-r--r--app/javascript/time_tables/components/TagsSelect2.js7
-rw-r--r--app/javascript/time_tables/components/TimeTableDay.js3
-rw-r--r--app/javascript/time_tables/components/Timetable.js11
-rw-r--r--app/javascript/time_tables/containers/App.js3
-rw-r--r--app/javascript/vehicle_journeys/actions/index.js156
-rw-r--r--app/javascript/vehicle_journeys/components/App.js3
-rw-r--r--app/javascript/vehicle_journeys/components/ConfirmModal.js9
-rw-r--r--app/javascript/vehicle_journeys/components/Filters.js28
-rw-r--r--app/javascript/vehicle_journeys/components/Navigate.js8
-rw-r--r--app/javascript/vehicle_journeys/components/SaveVehicleJourneys.js42
-rw-r--r--app/javascript/vehicle_journeys/components/ToggleArrivals.js8
-rw-r--r--app/javascript/vehicle_journeys/components/Tools.js28
-rw-r--r--app/javascript/vehicle_journeys/components/VehicleJourney.js70
-rw-r--r--app/javascript/vehicle_journeys/components/VehicleJourneys.js97
-rw-r--r--app/javascript/vehicle_journeys/components/tools/CreateModal.js46
-rw-r--r--app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js50
-rw-r--r--app/javascript/vehicle_journeys/components/tools/DeleteVehicleJourneys.js4
-rw-r--r--app/javascript/vehicle_journeys/components/tools/DuplicateVehicleJourney.js3
-rw-r--r--app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js118
-rw-r--r--app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js3
-rw-r--r--app/javascript/vehicle_journeys/components/tools/PurchaseWindowsEditVehicleJourney.js153
-rw-r--r--app/javascript/vehicle_journeys/components/tools/ShiftVehicleJourney.js3
-rw-r--r--app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js20
-rw-r--r--app/javascript/vehicle_journeys/components/tools/VehicleJourneyInfoButton.js30
-rw-r--r--app/javascript/vehicle_journeys/components/tools/select2s/CompanySelect2.js7
-rw-r--r--app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js141
-rw-r--r--app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js19
-rw-r--r--app/javascript/vehicle_journeys/components/tools/select2s/VJSelect2.js5
-rw-r--r--app/javascript/vehicle_journeys/containers/Filters.js3
-rw-r--r--app/javascript/vehicle_journeys/containers/SaveVehicleJourneys.js7
-rw-r--r--app/javascript/vehicle_journeys/containers/VehicleJourneysList.js8
-rw-r--r--app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js5
-rw-r--r--app/javascript/vehicle_journeys/containers/tools/PurchaseWindowsEditVehicleJourney.js38
-rw-r--r--app/javascript/vehicle_journeys/containers/tools/VehicleJourneyInfoButton.js20
-rw-r--r--app/javascript/vehicle_journeys/reducers/custom_fields.js6
-rw-r--r--app/javascript/vehicle_journeys/reducers/index.js9
-rw-r--r--app/javascript/vehicle_journeys/reducers/missions.js6
-rw-r--r--app/javascript/vehicle_journeys/reducers/modal.js76
-rw-r--r--app/javascript/vehicle_journeys/reducers/returnVehicleJourneys.js11
-rw-r--r--app/javascript/vehicle_journeys/reducers/vehicleJourneys.js83
-rw-r--r--app/jobs/mailer_job.rb3
-rw-r--r--app/models/calendar.rb185
-rw-r--r--app/models/calendar/period.rb7
-rw-r--r--app/models/chouette/area_type.rb55
-rw-r--r--app/models/chouette/company.rb2
-rw-r--r--app/models/chouette/journey_pattern.rb33
-rw-r--r--app/models/chouette/line.rb14
-rw-r--r--app/models/chouette/network.rb2
-rw-r--r--app/models/chouette/purchase_window.rb45
-rw-r--r--app/models/chouette/route.rb2
-rw-r--r--app/models/chouette/routing_constraint_zone.rb10
-rw-r--r--app/models/chouette/stop_area.rb77
-rw-r--r--app/models/chouette/time_table.rb254
-rw-r--r--app/models/chouette/time_table_period.rb7
-rw-r--r--app/models/chouette/vehicle_journey.rb106
-rw-r--r--app/models/chouette/vehicle_journey_at_stop.rb39
-rw-r--r--app/models/compliance_check_block.rb6
-rw-r--r--app/models/compliance_check_message_export.rb46
-rw-r--r--app/models/compliance_check_set.rb24
-rw-r--r--app/models/compliance_control.rb8
-rw-r--r--app/models/compliance_control_block.rb6
-rw-r--r--app/models/compliance_control_set.rb2
-rw-r--r--app/models/concerns/application_days_support.rb107
-rw-r--r--app/models/concerns/checksum_support.rb56
-rw-r--r--app/models/concerns/date_support.rb83
-rw-r--r--app/models/concerns/min_max_values_validation.rb6
-rw-r--r--app/models/concerns/objectid_support.rb5
-rw-r--r--app/models/concerns/period_support.rb80
-rw-r--r--app/models/concerns/timetable_support.rb149
-rw-r--r--app/models/custom_field.rb9
-rw-r--r--app/models/generic_attribute_control/min_max.rb6
-rw-r--r--app/models/generic_attribute_control/pattern.rb2
-rw-r--r--app/models/generic_attribute_control/uniqueness.rb2
-rw-r--r--app/models/import.rb11
-rw-r--r--app/models/import_message_export.rb4
-rw-r--r--app/models/line_control/route.rb2
-rw-r--r--app/models/merge.rb435
-rw-r--r--app/models/organisation.rb66
-rw-r--r--app/models/public_version.rb4
-rw-r--r--app/models/referential.rb188
-rw-r--r--app/models/referential_cloning.rb27
-rw-r--r--app/models/referential_suite.rb6
-rw-r--r--app/models/route_control/opposite_route.rb2
-rw-r--r--app/models/route_control/opposite_route_terminus.rb2
-rw-r--r--app/models/user.rb2
-rw-r--r--app/models/vehicle_journey_control/delta.rb5
-rw-r--r--app/models/vehicle_journey_control/speed.rb6
-rw-r--r--app/models/vehicle_journey_control/waiting_time.rb5
-rw-r--r--app/models/workbench.rb9
-rw-r--r--app/models/workgroup.rb20
-rw-r--r--app/policies/access_link_policy.rb6
-rw-r--r--app/policies/access_point_policy.rb6
-rw-r--r--app/policies/application_policy.rb14
-rw-r--r--app/policies/calendar_policy.rb19
-rw-r--r--app/policies/connection_link_policy.rb6
-rw-r--r--app/policies/journey_pattern_policy.rb6
-rw-r--r--app/policies/line_policy.rb15
-rw-r--r--app/policies/line_referential_policy.rb14
-rw-r--r--app/policies/merge_policy.rb15
-rw-r--r--app/policies/network_policy.rb11
-rw-r--r--app/policies/purchase_window_policy.rb20
-rw-r--r--app/policies/referential_policy.rb12
-rw-r--r--app/policies/route_policy.rb6
-rw-r--r--app/policies/routing_constraint_zone_policy.rb6
-rw-r--r--app/policies/stop_area_policy.rb16
-rw-r--r--app/policies/stop_area_referential_policy.rb14
-rw-r--r--app/policies/time_table_combination_policy.rb2
-rw-r--r--app/policies/time_table_policy.rb10
-rw-r--r--app/policies/vehicle_journey_policy.rb6
-rw-r--r--app/services/parent_import_notifier.rb15
-rw-r--r--app/services/parent_notifier.rb19
-rw-r--r--app/services/referential_overview.rb256
-rw-r--r--app/services/zip_service.rb31
-rw-r--r--app/uploaders/import_uploader.rb6
-rw-r--r--app/views/api/v1/journey_patterns/show.rabl14
-rw-r--r--app/views/autocomplete_purchase_windows/index.rabl12
-rw-r--r--app/views/autocomplete_stop_areas/around.rabl2
-rw-r--r--app/views/autocomplete_stop_areas/index.rabl5
-rw-r--r--app/views/calendar_mailer/created.html.slim4
-rw-r--r--app/views/calendar_mailer/updated.html.slim2
-rw-r--r--app/views/calendars/_filters.html.slim10
-rw-r--r--app/views/calendars/_form.html.slim53
-rw-r--r--app/views/calendars/_form_advanced.html.slim8
-rw-r--r--app/views/calendars/_form_simple.html.slim56
-rw-r--r--app/views/calendars/edit.html.slim9
-rw-r--r--app/views/calendars/index.html.slim8
-rw-r--r--app/views/calendars/month.rabl9
-rw-r--r--app/views/calendars/new.html.slim6
-rw-r--r--app/views/calendars/show.html.slim35
-rw-r--r--app/views/calendars/show.rabl22
-rw-r--r--app/views/companies/index.html.slim4
-rw-r--r--app/views/companies/show.html.slim18
-rw-r--r--app/views/compliance_check_sets/_filters.html.slim8
-rw-r--r--app/views/compliance_check_sets/executed.html.slim2
-rw-r--r--app/views/compliance_check_sets/index.html.slim17
-rw-r--r--app/views/compliance_check_sets/show.html.slim52
-rw-r--r--app/views/compliance_checks/_filters.html.slim8
-rw-r--r--app/views/compliance_control_sets/_filters.html.slim10
-rw-r--r--app/views/compliance_control_sets/index.html.slim6
-rw-r--r--app/views/compliance_control_sets/show.html.slim12
-rw-r--r--app/views/compliance_controls/_filters.html.slim8
-rw-r--r--app/views/compliance_controls/new.html.slim4
-rw-r--r--app/views/compliance_controls/show.html.slim6
-rw-r--r--app/views/dashboards/_dashboard.html.slim41
-rw-r--r--app/views/devise/invitations/edit.html.slim33
-rw-r--r--app/views/devise/mailer/invitation_instructions.fr.html.slim4
-rw-r--r--app/views/devise/passwords/edit.html.slim28
-rw-r--r--app/views/devise/passwords/new.html.slim24
-rw-r--r--app/views/devise/sessions/new.html.slim2
-rw-r--r--app/views/errors/forbidden.html.slim2
-rw-r--r--app/views/errors/server_error.html.slim2
-rw-r--r--app/views/import_resources/index.html.slim3
-rw-r--r--app/views/imports/_filters.html.slim6
-rw-r--r--app/views/imports/_import_messages.html.slim8
-rw-r--r--app/views/imports/index.html.slim3
-rw-r--r--app/views/imports/show.html.slim100
-rw-r--r--app/views/journey_patterns_collections/show.html.slim3
-rw-r--r--app/views/layouts/application.html.slim5
-rw-r--r--app/views/layouts/mailer.html.erb22
-rw-r--r--app/views/layouts/mailer.html.slim7
-rw-r--r--app/views/layouts/navigation/_main_nav_left_content_stif.html.slim2
-rw-r--r--app/views/layouts/navigation/_main_nav_top.html.slim8
-rw-r--r--app/views/layouts/navigation/_page_header.html.slim29
-rw-r--r--app/views/layouts/snapshots/actions_links.html.slim21
-rw-r--r--app/views/layouts/snapshots/default.html.slim19
-rw-r--r--app/views/line_footnotes/show.html.slim4
-rw-r--r--app/views/line_referentials/show.html.slim5
-rw-r--r--app/views/lines/_filters.html.slim10
-rw-r--r--app/views/lines/_form.html.slim3
-rw-r--r--app/views/lines/index.html.slim6
-rw-r--r--app/views/lines/show.html.slim10
-rw-r--r--app/views/merges/_form.html.slim12
-rw-r--r--app/views/merges/new.html.slim7
-rw-r--r--app/views/merges/show.html.slim17
-rw-r--r--app/views/networks/_form.html.slim10
-rw-r--r--app/views/networks/index.html.slim3
-rw-r--r--app/views/networks/show.html.slim16
-rw-r--r--app/views/purchase_windows/_date_value_fields.html.slim13
-rw-r--r--app/views/purchase_windows/_filters.html.slim15
-rw-r--r--app/views/purchase_windows/_form.html.slim29
-rw-r--r--app/views/purchase_windows/_period_fields.html.slim15
-rw-r--r--app/views/purchase_windows/edit.html.slim7
-rw-r--r--app/views/purchase_windows/index.html.slim41
-rw-r--r--app/views/purchase_windows/new.html.slim6
-rw-r--r--app/views/purchase_windows/show.html.slim12
-rw-r--r--app/views/referential_companies/index.html.slim4
-rw-r--r--app/views/referential_lines/_filters.html.slim4
-rw-r--r--app/views/referential_lines/show.html.slim21
-rw-r--r--app/views/referential_networks/index.html.slim3
-rw-r--r--app/views/referential_networks/show.html.slim9
-rw-r--r--app/views/referential_stop_areas/_form.html.slim2
-rw-r--r--app/views/referential_stop_areas/show.html.slim9
-rw-r--r--app/views/referential_vehicle_journeys/_filters.html.slim62
-rw-r--r--app/views/referential_vehicle_journeys/index.html.slim59
-rw-r--r--app/views/referentials/_filters.html.slim12
-rw-r--r--app/views/referentials/_form.html.slim8
-rw-r--r--app/views/referentials/_overview.html.slim75
-rw-r--r--app/views/referentials/new.html.slim2
-rw-r--r--app/views/referentials/show.html.slim37
-rw-r--r--app/views/routes/_form.html.slim2
-rw-r--r--app/views/routes/show.html.slim22
-rw-r--r--app/views/routing_constraint_zones/_filters.html.slim4
-rw-r--r--app/views/routing_constraint_zones/index.html.slim3
-rw-r--r--app/views/routing_constraint_zones/show.html.slim12
-rw-r--r--app/views/shared/_development_toolbar.html.slim53
-rw-r--r--app/views/stif/dashboards/_dashboard.html.slim9
-rw-r--r--app/views/stop_area_referentials/show.html.slim7
-rw-r--r--app/views/stop_areas/_filters.html.slim10
-rw-r--r--app/views/stop_areas/_form.html.slim30
-rw-r--r--app/views/stop_areas/autocomplete.rabl24
-rw-r--r--app/views/stop_areas/index.html.slim8
-rw-r--r--app/views/stop_areas/show.html.slim28
-rw-r--r--app/views/stop_points/_stop_point.html.slim4
-rw-r--r--app/views/time_tables/_filter.html.slim6
-rw-r--r--app/views/time_tables/_form.html.slim2
-rw-r--r--app/views/time_tables/_show_time_table.html.slim28
-rw-r--r--app/views/time_tables/edit.html.slim2
-rw-r--r--app/views/time_tables/index.html.slim6
-rw-r--r--app/views/time_tables/show.html.slim20
-rw-r--r--app/views/vehicle_journeys/index.html.slim19
-rw-r--r--app/views/vehicle_journeys/show.rabl23
-rw-r--r--app/views/workbench_outputs/show.html.slim40
-rw-r--r--app/views/workbenches/_filters.html.slim18
-rw-r--r--app/views/workbenches/show.html.slim15
-rw-r--r--app/workers/clean_up_worker.rb1
-rw-r--r--app/workers/line_referential_sync_worker.rb2
-rw-r--r--app/workers/merge_worker.rb7
-rw-r--r--app/workers/referential_cloning_worker.rb27
-rw-r--r--app/workers/stop_area_referential_sync_worker.rb2
-rw-r--r--app/workers/workbench_import_worker.rb92
-rw-r--r--app/workers/workbench_import_worker/object_state_updater.rb36
-rw-r--r--config/application.rb6
-rw-r--r--config/breadcrumbs.rb50
-rw-r--r--config/deploy.rb18
-rw-r--r--config/deploy/staging.rb2
-rw-r--r--config/development_toolbar.rb.tpl2
-rw-r--r--config/environments/development.rb16
-rw-r--r--config/initializers/apartment.rb5
-rw-r--r--config/initializers/apartment_null_db.rb25
-rw-r--r--config/initializers/countries.rb3
-rw-r--r--config/initializers/sidekiq.rb6
-rw-r--r--config/initializers/simple_form/safe_submit.rb12
-rw-r--r--config/initializers/stif.rb18
-rw-r--r--config/locales/actions.en.yml4
-rw-r--r--config/locales/actions.fr.yml4
-rw-r--r--config/locales/area_types.en.yml7
-rw-r--r--config/locales/area_types.fr.yml6
-rw-r--r--config/locales/calendars.en.yml14
-rw-r--r--config/locales/calendars.fr.yml34
-rw-r--r--config/locales/carrier_wave.yml4
-rw-r--r--config/locales/companies.en.yml1
-rw-r--r--config/locales/companies.fr.yml1
-rw-r--r--config/locales/compliance_check_messages.en.yml31
-rw-r--r--config/locales/compliance_check_messages.fr.yml31
-rw-r--r--config/locales/compliance_check_results.en.yml2
-rw-r--r--config/locales/compliance_check_results.fr.yml2
-rw-r--r--config/locales/compliance_check_sets.en.yml15
-rw-r--r--config/locales/compliance_check_sets.fr.yml25
-rw-r--r--config/locales/compliance_controls.en.yml12
-rw-r--r--config/locales/compliance_controls.fr.yml22
-rw-r--r--config/locales/dashboard.en.yml16
-rw-r--r--config/locales/dashboard.fr.yml12
-rw-r--r--config/locales/devise.fr.yml2
-rw-r--r--config/locales/en.yml5
-rw-r--r--config/locales/enumerize.en.yml13
-rw-r--r--config/locales/enumerize.fr.yml12
-rw-r--r--config/locales/footnotes.en.yml1
-rw-r--r--config/locales/footnotes.fr.yml1
-rw-r--r--config/locales/fr.yml4
-rw-r--r--config/locales/import_messages.en.yml103
-rw-r--r--config/locales/import_messages.fr.yml103
-rw-r--r--config/locales/imports.en.yml9
-rw-r--r--config/locales/imports.fr.yml9
-rw-r--r--config/locales/journey_patterns.en.yml1
-rw-r--r--config/locales/lines.en.yml14
-rw-r--r--config/locales/lines.fr.yml12
-rw-r--r--config/locales/merges.yml23
-rw-r--r--config/locales/purchase_windows.en.yml79
-rw-r--r--config/locales/purchase_windows.fr.yml80
-rw-r--r--config/locales/referentials.en.yml13
-rw-r--r--config/locales/referentials.fr.yml21
-rw-r--r--config/locales/routes.en.yml2
-rw-r--r--config/locales/routes.fr.yml2
-rw-r--r--config/locales/routing_constraint_zones.en.yml1
-rw-r--r--config/locales/routing_constraint_zones.fr.yml1
-rw-r--r--config/locales/simple_form.en.yml1
-rw-r--r--config/locales/simple_form.fr.yml1
-rw-r--r--config/locales/stop_areas.en.yml17
-rw-r--r--config/locales/stop_areas.fr.yml21
-rw-r--r--config/locales/stop_points.en.yml1
-rw-r--r--config/locales/stop_points.fr.yml3
-rw-r--r--config/locales/time_tables.en.yml1
-rw-r--r--config/locales/time_tables.fr.yml1
-rw-r--r--config/locales/vehicle_journeys.en.yml126
-rw-r--r--config/locales/vehicle_journeys.fr.yml127
-rw-r--r--config/locales/workbench_outputs.en.yml7
-rw-r--r--config/locales/workbench_outputs.fr.yml7
-rw-r--r--config/locales/workbenches.fr.yml2
-rw-r--r--config/routes.rb43
-rw-r--r--config/schedule.rb6
-rw-r--r--config/webpack/environment.js4
-rw-r--r--config/webpack/loaders/coffee.js6
-rw-r--r--config/webpack/production.js2
-rw-r--r--config/webpack/staging.js2
-rw-r--r--db/migrate/20171212152452_create_merges.rb16
-rw-r--r--db/migrate/20171214130636_enable_unaccent_extension.rb9
-rw-r--r--db/migrate/20171214131755_create_business_calendars.rb14
-rw-r--r--db/migrate/20171215144543_rename_business_calendars_to_purchase_windows.rb5
-rw-r--r--db/migrate/20171215145023_update_purchase_windows_attributes.rb13
-rw-r--r--db/migrate/20171218174509_change_compliance_control_compliance_check_control_attributes_format_from_hstore_to_json.rb33
-rw-r--r--db/migrate/20171219170128_add_features_to_organisations.rb5
-rw-r--r--db/migrate/20171220164059_add_waiting_time_to_stop_areas.rb5
-rw-r--r--db/migrate/20171227113809_create_join_table_purchase_windows_vehicle_journeys.rb8
-rw-r--r--db/migrate/20180103084612_add_costs_to_journey_patterns.rb5
-rw-r--r--db/migrate/20180108132310_create_workgroups.rb11
-rw-r--r--db/migrate/20180109133022_add_workgroup_id_to_workbenches.rb6
-rw-r--r--db/migrate/20180109144120_create_custom_fields.rb14
-rw-r--r--db/migrate/20180109173815_add_index_resource_type_on_custom_fields.rb5
-rw-r--r--db/migrate/20180109180350_add_custom_field_values_to_vehicle_journeys.rb5
-rw-r--r--db/migrate/20180111200406_add_merged_at_to_referentials.rb5
-rw-r--r--db/migrate/20180123174450_add_workgroup_id_to_calendars.rb6
-rw-r--r--db/migrate/20180124061955_add_int_day_types_to_calendars.rb5
-rw-r--r--db/migrate/20180124124215_add_excluded_dates_to_calendars.rb5
-rw-r--r--db/migrate/20180126134944_add_kind_to_stop_areas.rb6
-rw-r--r--db/migrate/20180129141656_add_localized_names_to_stop_areas.rb5
-rw-r--r--db/migrate/20180202170009_set_stop_areas_kind_to_commercial_on_existing_records.rb11
-rw-r--r--db/schema.rb79
-rw-r--r--db/seeds/stif.seeds.rb41
-rw-r--r--lib/af83/decorator.rb131
-rw-r--r--lib/af83/decorator/enhanced_decorator.rb159
-rw-r--r--lib/af83/decorator/link.rb156
-rw-r--r--lib/line_periods.rb35
-rw-r--r--lib/link.rb6
-rw-r--r--lib/range_ext.rb18
-rw-r--r--lib/stif/codifligne_line_id.rb19
-rw-r--r--lib/stif/dashboard.rb6
-rw-r--r--lib/stif/my_workbench_scopes.rb3
-rw-r--r--lib/stif/netex_file.rb93
-rw-r--r--lib/stif/permission_translator.rb16
-rw-r--r--lib/stif/reflex_synchronization.rb1
-rw-r--r--lib/tasks/ci.rake16
-rw-r--r--lib/tasks/compliance_check_sets.rb11
-rw-r--r--lib/tasks/erd.rake4
-rw-r--r--lib/tasks/imports.rake7
-rw-r--r--lib/tasks/referential.rake43
-rw-r--r--package-lock.json12274
-rw-r--r--package.json60
-rw-r--r--spec/controllers/api/v1/stop_area_controller_spec.rb9
-rw-r--r--spec/controllers/autocomplete_purchase_windows_controller_spec.rb33
-rw-r--r--spec/controllers/autocomplete_stop_areas_controller_spec.rb61
-rw-r--r--spec/controllers/concerns/feature_checker_spec.rb37
-rw-r--r--spec/controllers/imports_controller_spec.rb14
-rw-r--r--spec/controllers/journey_patterns_collections_controller_spec.rb17
-rw-r--r--spec/controllers/line_referentials_controller_spec.rb16
-rw-r--r--spec/controllers/lines_controller_spec.rb38
-rw-r--r--spec/controllers/referential_vehicle_journeys_controller_spec.rb98
-rw-r--r--spec/controllers/referentials_controller_spec.rb29
-rw-r--r--spec/controllers/statuses_controller_spec.rb50
-rw-r--r--spec/controllers/stop_area_referentials_controller_spec.rb17
-rw-r--r--spec/controllers/stop_areas_controller_spec.rb38
-rw-r--r--spec/controllers/time_tables_controller_spec.rb29
-rw-r--r--spec/controllers/vehicle_journeys_controller_spec.rb25
-rw-r--r--spec/db/schema_spec.rb2
-rw-r--r--spec/decorators/api_key_decorator_spec.rb4
-rw-r--r--spec/decorators/referential_decorator_spec.rb54
-rw-r--r--spec/decorators/stop_area_decorator_spec.rb25
-rw-r--r--spec/factories/calendars.rb1
-rw-r--r--spec/factories/chouette_journey_pattern.rb8
-rw-r--r--spec/factories/chouette_lines.rb4
-rw-r--r--spec/factories/chouette_purchase_windows.rb12
-rw-r--r--spec/factories/chouette_routes.rb8
-rw-r--r--spec/factories/chouette_stop_areas.rb15
-rw-r--r--spec/factories/chouette_stop_points.rb2
-rw-r--r--spec/factories/chouette_time_table.rb18
-rw-r--r--spec/factories/chouette_vehicle_journey.rb1
-rw-r--r--spec/factories/chouette_vehicle_journey_at_stop.rb2
-rw-r--r--spec/factories/compliance_controls/generic_factories.rb2
-rw-r--r--spec/factories/compliance_controls/vehicle_journey_control_factories.rb4
-rw-r--r--spec/factories/custom_fields.rb9
-rw-r--r--spec/factories/import_messages.rb12
-rw-r--r--spec/factories/line_referentials.rb9
-rw-r--r--spec/factories/organisations.rb3
-rw-r--r--spec/factories/stop_area_referentials.rb9
-rw-r--r--spec/factories/workbenches.rb1
-rw-r--r--spec/factories/workgroups.rb7
-rw-r--r--spec/features/access_points_spec.rb2
-rw-r--r--spec/features/calendars_permissions_spec.rb7
-rw-r--r--spec/features/companies_spec.rb2
-rw-r--r--spec/features/compliance_check_sets_spec.rb22
-rw-r--r--spec/features/group_of_lines_permissions_spec.rb4
-rw-r--r--spec/features/group_of_lines_spec.rb2
-rw-r--r--spec/features/lines_spec.rb23
-rw-r--r--spec/features/networks_spec.rb16
-rw-r--r--spec/features/purchase_windows_permission_spec.rb59
-rw-r--r--spec/features/purchase_windows_spec.rb69
-rw-r--r--spec/features/referential_stop_areas_spec.rb2
-rw-r--r--spec/features/safe_submit_spec.rb9
-rw-r--r--spec/features/stop_areas_spec.rb2
-rw-r--r--spec/features/users/user_delete_spec.rb2
-rw-r--r--spec/features/workbenches/workbenches_show_spec.rb72
-rw-r--r--spec/fixtures/OFFRE_WITH_EXTRA.zipbin5586 -> 0 bytes
-rw-r--r--spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/SPURIOUS/spurious.xml1
-rw-r--r--spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/calendriers.xml (renamed from spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/calendriers.xml)0
-rw-r--r--spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/commun.xml (renamed from spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/commun.xml)0
-rw-r--r--spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/offre_C00108_9.xml (renamed from spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml)0
-rw-r--r--spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/offre_C00109_10.xml (renamed from spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml)0
-rw-r--r--spec/fixtures/foreign_and_spurious/FOREIGN_LINE/calendriers.xml86
-rw-r--r--spec/fixtures/foreign_and_spurious/FOREIGN_LINE/commun.xml33
-rw-r--r--spec/fixtures/foreign_and_spurious/FOREIGN_LINE/offre_C00107_10.xml204
-rw-r--r--spec/fixtures/foreign_and_spurious/FOREIGN_LINE/offre_C00108_9.xml202
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/calendriers.xml86
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/commun.xml33
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml202
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml204
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/calendriers.xml (renamed from spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/calendriers.xml)0
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/commun.xml (renamed from spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/commun.xml)0
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml (renamed from spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml)0
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml (renamed from spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml)0
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/SPURIOUS/spurious.xml1
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/calendriers.xml86
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/commun.xml33
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/offre_C00108_9.xml202
-rw-r--r--spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/offre_C00109_10.xml204
-rw-r--r--spec/fixtures/meta_zip/one/alpha1
-rw-r--r--spec/fixtures/meta_zip/two/beta1
-rw-r--r--spec/fixtures/meta_zip/two/subdir/gamma1
-rw-r--r--spec/fixtures/nozip.zip1
-rw-r--r--spec/fixtures/regression-5281.zipbin0 -> 21642 bytes
-rw-r--r--spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/calendriers.xml145
-rw-r--r--spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/commun.xml30
-rw-r--r--spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00166_05.xml459
-rw-r--r--spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00168_08.xml667
-rw-r--r--spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00171_11.xml473
-rw-r--r--spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/calendriers.xml145
-rw-r--r--spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/commun.xml30
-rw-r--r--spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00163_01.xml497
-rw-r--r--spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00164_03.xml951
-rw-r--r--spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00165_04.xml803
-rw-r--r--spec/fixtures/some_foreign_mixed/FOREIGN_LINE/calendriers.xml86
-rw-r--r--spec/fixtures/some_foreign_mixed/FOREIGN_LINE/commun.xml33
-rw-r--r--spec/fixtures/some_foreign_mixed/FOREIGN_LINE/offre_C00107_10.xml204
-rw-r--r--spec/fixtures/some_foreign_mixed/FOREIGN_LINE/offre_C00108_9.xml202
-rw-r--r--spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/calendriers.xml86
-rw-r--r--spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/commun.xml33
-rw-r--r--spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml202
-rw-r--r--spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml204
-rw-r--r--spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/calendriers.xml80
-rw-r--r--spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/commun.xml32
-rw-r--r--spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml172
-rw-r--r--spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml172
-rw-r--r--spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/calendriers.xml86
-rw-r--r--spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/commun.xml33
-rw-r--r--spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml202
-rw-r--r--spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml204
-rw-r--r--spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/calendriers.xml80
-rw-r--r--spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/commun.xml32
-rw-r--r--spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml172
-rw-r--r--spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml172
-rw-r--r--spec/helpers/table_builder_helper_spec.rb156
-rw-r--r--spec/javascript/journey_patterns/actions_spec.js16
-rw-r--r--spec/javascript/journey_patterns/components/JourneyPattern_spec.js63
-rw-r--r--spec/javascript/journey_patterns/components/JourneyPatterns_spec.js77
-rw-r--r--spec/javascript/journey_patterns/components/__snapshots__/JourneyPattern_spec.js.snap143
-rw-r--r--spec/javascript/journey_patterns/components/__snapshots__/JourneyPatterns_spec.js.snap169
-rw-r--r--spec/javascript/journey_patterns/reducers/journey_patterns_spec.js38
-rw-r--r--spec/javascript/preprocessor.js15
-rw-r--r--spec/javascript/routes/reducers/stop_points_spec.js588
-rw-r--r--spec/javascript/time_table/reducers/timetable_spec.js3
-rw-r--r--spec/javascript/vehicle_journeys/actions_spec.js274
-rw-r--r--spec/javascript/vehicle_journeys/components/CustomFieldsInputs_spec.js41
-rw-r--r--spec/javascript/vehicle_journeys/components/VehicleJourneys_spec.js87
-rw-r--r--spec/javascript/vehicle_journeys/components/__snapshots__/CustomFieldsInputs_spec.js.snap3
-rw-r--r--spec/javascript/vehicle_journeys/components/__snapshots__/VehicleJourneys_spec.js.snap181
-rw-r--r--spec/javascript/vehicle_journeys/reducers/modal_spec.js91
-rw-r--r--spec/javascript/vehicle_journeys/reducers/vehicleJourneys_spec.js (renamed from spec/javascript/vehicle_journeys/reducers/vehicle_journeys_spec.js)233
-rw-r--r--spec/lib/af83/decorator/decorator_link_spec.rb79
-rw-r--r--spec/lib/af83/decorator/decorator_spec.rb824
-rw-r--r--spec/lib/range_ext_spec.rb51
-rw-r--r--spec/lib/stif/netex_file/frame_spec.rb13
-rw-r--r--spec/lib/stif/netex_file_spec.rb4
-rw-r--r--spec/lib/stif/permission_translator_spec.rb16
-rw-r--r--spec/mailers/calendar_mailer_spec.rb2
-rw-r--r--spec/models/calendar_spec.rb122
-rw-r--r--spec/models/chouette/access_point_spec.rb2
-rw-r--r--spec/models/chouette/area_type_spec.rb43
-rw-r--r--spec/models/chouette/footnote_spec.rb12
-rw-r--r--spec/models/chouette/journey_pattern_spec.rb50
-rw-r--r--spec/models/chouette/purchase_window_spec.rb27
-rw-r--r--spec/models/chouette/route/route_base_spec.rb4
-rw-r--r--spec/models/chouette/route/route_duplication_spec.rb11
-rw-r--r--spec/models/chouette/routing_constraint_zone_spec.rb9
-rw-r--r--spec/models/chouette/stop_area_spec.rb80
-rw-r--r--spec/models/chouette/time_table_period_spec.rb2
-rw-r--r--spec/models/chouette/time_table_spec.rb134
-rw-r--r--spec/models/chouette/vehicle_journey_at_stop_spec.rb39
-rw-r--r--spec/models/chouette/vehicle_journey_spec.rb256
-rw-r--r--spec/models/compliance_check_spec.rb32
-rw-r--r--spec/models/compliance_control_class_level_defaults/generic_attribute_control/pattern_cccld_spec.rb3
-rw-r--r--spec/models/compliance_control_class_level_defaults/generic_attribute_control/uniqueness_cccld_spec.rb1
-rw-r--r--spec/models/compliance_control_spec.rb10
-rw-r--r--spec/models/compliance_control_validations/genric_attribute_validation/min_max_validation_spec.rb1
-rw-r--r--spec/models/custom_field_spec.rb35
-rw-r--r--spec/models/import_spec.rb57
-rw-r--r--spec/models/merge_spec.rb58
-rw-r--r--spec/models/organisation_spec.rb37
-rw-r--r--spec/models/referential/referential_lock_during_creation_spec.rb198
-rw-r--r--spec/models/referential_cloning_spec.rb73
-rw-r--r--spec/models/referential_spec.rb43
-rw-r--r--spec/models/workbench_spec.rb3
-rw-r--r--spec/models/workgroup_spec.rb30
-rw-r--r--spec/policies/access_link_policy_spec.rb10
-rw-r--r--spec/policies/access_point_policy_spec.rb10
-rw-r--r--spec/policies/calendar_policy_spec.rb16
-rw-r--r--spec/policies/company_policy_spec.rb5
-rw-r--r--spec/policies/connection_link_policy_spec.rb10
-rw-r--r--spec/policies/group_of_line_policy_spec.rb14
-rw-r--r--spec/policies/journey_pattern_policy_spec.rb10
-rw-r--r--spec/policies/line_policy_spec.rb11
-rw-r--r--spec/policies/line_referential_policy_spec.rb9
-rw-r--r--spec/policies/network_policy_spec.rb14
-rw-r--r--spec/policies/purchase_window_policy_spec.rb15
-rw-r--r--spec/policies/referential_policy_spec.rb13
-rw-r--r--spec/policies/route_policy_spec.rb12
-rw-r--r--spec/policies/routing_constraint_zone_policy_spec.rb10
-rw-r--r--spec/policies/sto_area_referential_policy_spec.rb9
-rw-r--r--spec/policies/stop_area_policy_spec.rb4
-rw-r--r--spec/policies/time_table_policy_spec.rb10
-rw-r--r--spec/rails_helper.rb5
-rw-r--r--spec/requests/api/v1/netex_import_spec.rb47
-rw-r--r--spec/services/meta_zip_data_spec.rb55
-rw-r--r--spec/services/parent_notifier_spec.rb (renamed from spec/services/parent_import_notifier_spec.rb)16
-rw-r--r--spec/services/referential_overview_spec.rb154
-rw-r--r--spec/services/zip_service_spec.rb185
-rw-r--r--spec/spec_helper.rb11
-rw-r--r--spec/support/checksum_support.rb67
-rw-r--r--spec/support/controller_spec_helper.rb33
-rw-r--r--spec/support/decorator_helpers.rb28
-rw-r--r--spec/support/helpers/tree_walker.rb15
-rw-r--r--spec/support/integration_spec_helper.rb78
-rw-r--r--spec/support/journey_pattern_helper.rb19
-rw-r--r--spec/support/permissions.rb1
-rw-r--r--spec/support/pundit/policies.rb5
-rw-r--r--spec/support/pundit/pundit_view_policy.rb27
-rw-r--r--spec/support/pundit/shared_examples.rb51
-rw-r--r--spec/support/referential.rb7
-rw-r--r--spec/support/shared_examples/compliance_control_validation.rb55
-rw-r--r--spec/support/snapshot_support.rb60
-rw-r--r--spec/support/zip_support.rb25
-rw-r--r--spec/support/zip_support/create_zip_data.rb70
-rw-r--r--spec/views/companies/__snapshots__/companies/index.snap4
-rw-r--r--spec/views/companies/__snapshots__/companies/index_create.snap4
-rw-r--r--spec/views/companies/__snapshots__/companies/index_destroy.snap4
-rw-r--r--spec/views/companies/__snapshots__/companies/index_update.snap4
-rw-r--r--spec/views/companies/__snapshots__/companies/show.snap4
-rw-r--r--spec/views/companies/__snapshots__/companies/show_create.snap4
-rw-r--r--spec/views/companies/__snapshots__/companies/show_destroy.snap7
-rw-r--r--spec/views/companies/__snapshots__/companies/show_update.snap7
-rw-r--r--spec/views/companies/index.html.erb_spec.rb29
-rw-r--r--spec/views/companies/show.html.erb_spec.rb29
-rw-r--r--spec/views/connection_links/index.html.erb_spec.rb8
-rw-r--r--spec/views/connection_links/show.html.erb_spec.rb35
-rw-r--r--spec/views/connection_links/show.html.slim_spec.rb32
-rw-r--r--spec/views/imports/show.html.slim_spec.rb35
-rw-r--r--spec/views/line_referentials/show.html.slim_spec.rb22
-rw-r--r--spec/views/line_referentials/stop_area_referentials/show.html.slim_spec.rb22
-rw-r--r--spec/views/lines/__snapshots__/lines/index.snap4
-rw-r--r--spec/views/lines/__snapshots__/lines/index_create.snap4
-rw-r--r--spec/views/lines/__snapshots__/lines/index_destroy.snap4
-rw-r--r--spec/views/lines/__snapshots__/lines/index_update.snap4
-rw-r--r--spec/views/lines/__snapshots__/lines/show.snap9
-rw-r--r--spec/views/lines/__snapshots__/lines/show_create.snap9
-rw-r--r--spec/views/lines/__snapshots__/lines/show_destroy.snap9
-rw-r--r--spec/views/lines/__snapshots__/lines/show_update.snap9
-rw-r--r--spec/views/lines/index.html.erb_spec.rb27
-rw-r--r--spec/views/lines/index.html.slim_spec.rb93
-rw-r--r--spec/views/lines/show.html.erb_spec.rb26
-rw-r--r--spec/views/networks/__snapshots__/networks/index.snap4
-rw-r--r--spec/views/networks/__snapshots__/networks/index_create.snap4
-rw-r--r--spec/views/networks/__snapshots__/networks/index_destroy.snap4
-rw-r--r--spec/views/networks/__snapshots__/networks/index_update.snap4
-rw-r--r--spec/views/networks/__snapshots__/networks/show.snap4
-rw-r--r--spec/views/networks/__snapshots__/networks/show_create.snap4
-rw-r--r--spec/views/networks/__snapshots__/networks/show_destroy.snap7
-rw-r--r--spec/views/networks/__snapshots__/networks/show_update.snap7
-rw-r--r--spec/views/networks/index.html.erb_spec.rb28
-rw-r--r--spec/views/networks/show.html.erb_spec.rb30
-rw-r--r--spec/views/offer_workbenches/show.html.erb_spec.rb61
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_create.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_destroy.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_purchase_windows.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_purchase_windows_create.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_purchase_windows_destroy.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_purchase_windows_update.snap12
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_readonly.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_readonly_create.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_readonly_destroy.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_readonly_update.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_create.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_destroy.snap9
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_update.snap12
-rw-r--r--spec/views/referentials/__snapshots__/referentials/show_update.snap12
-rw-r--r--spec/views/referentials/show.html.erb_spec.rb69
-rw-r--r--spec/views/stop_areas/edit.html.erb_spec.rb5
-rw-r--r--spec/views/stop_areas/index.html.erb_spec.rb25
-rw-r--r--spec/views/stop_areas/index.html.slim_spec.rb77
-rw-r--r--spec/views/stop_areas/new.html.erb_spec.rb4
-rw-r--r--spec/views/vehicle_journeys/index.html.slim_spec.rb31
-rw-r--r--spec/views/vehicle_journeys/new.html.erb_spec.rb3
-rw-r--r--spec/workers/referential_cloning_worker_spec.rb53
-rw-r--r--spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb47
-rw-r--r--spec/workers/workbench_import/workbench_import_worker_spec.rb169
-rw-r--r--spec/workers/workbench_import_worker_spec.rb102
-rw-r--r--yarn.lock2057
773 files changed, 38684 insertions, 5335 deletions
diff --git a/.gitignore b/.gitignore
index 03a39be90..dd4d057ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,8 @@
/tmp
*~
public/assets/
+public/javascripts/i18n.js
+public/javascripts/translations.js
# for vim users
*.swp
@@ -48,5 +50,5 @@ coverage
/bin/rspec
/bin/spring
-# FIXME Ignore ./spec/services/zip_service/regression_4273_spec.rb files
-/spec/fixtures/target_*.zip
+spec/fixtures/target_*
+config/development_toolbar.rb
diff --git a/DEVNOTES.md b/DEVNOTES.md
index 2a3915ed2..bcdd37f5e 100644
--- a/DEVNOTES.md
+++ b/DEVNOTES.md
@@ -37,7 +37,7 @@ They are overriden as follows
```ruby
def <destructive>?
- !archived? && organisation_match? && user.has_permission('<resource in plural form>.<action>')
+ !referential_read_only? && organisation_match? && user.has_permission('<resource in plural form>.<action>')
end
```
diff --git a/Gemfile b/Gemfile
index cb2234728..75298659f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,3 +1,4 @@
+# coding: utf-8
source 'https://rubygems.org'
# Use https for github
@@ -15,7 +16,7 @@ gem 'uglifier', '~> 2.7.2'
gem 'coffee-rails', '~> 4.0.0'
# Webpacker
-gem 'webpacker', '~> 3.0'
+gem 'webpacker', '3.2.1'
# Use jquery as the JavaScript library
gem 'jquery-rails', '~> 3.1.4' # Update to v4 for Rails 4.2
@@ -65,6 +66,7 @@ end
gem 'activerecord-postgis-adapter', "~> 3.0.0"
gem 'polylines'
+gem 'activerecord-nulldb-adapter', require: false
# Codifligne API
gem 'codifligne', af83: 'stif-codifline-api'
@@ -99,6 +101,9 @@ gem 'simple_form', '~> 3.1.0'
gem 'font-awesome-sass', '~> 4.7'
gem 'will_paginate-bootstrap'
gem 'gretel'
+gem 'country_select'
+gem 'flag-icons-rails'
+gem 'i18n-js'
# Format Output
gem 'json'
@@ -126,7 +131,6 @@ gem 'acts-as-taggable-on', '~> 4.0.0'
gem 'acts_as_list', '~> 0.6.0'
gem 'acts_as_tree', '~> 2.1.0', require: 'acts_as_tree'
-gem "hstore_accessor", "~> 1.1"
gem 'rabl'
gem 'carrierwave', '~> 1.0'
@@ -159,6 +163,7 @@ group :development do
gem 'bundler-audit'
gem 'spring-commands-rspec'
gem 'dbshell-rails'
+ gem 'rack-livereload'
platforms :ruby_20, :ruby_21, :ruby_22 do
gem 'better_errors'
@@ -173,6 +178,7 @@ group :test do
gem 'simplecov-rcov', :require => false
gem 'htmlbeautifier'
gem 'timecop'
+ gem 'rspec-snapshot'
end
group :test, :development, :dev do
diff --git a/Gemfile.lock b/Gemfile.lock
index def02b6ed..046167e69 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -16,10 +16,11 @@ GIT
GIT
remote: git@github.com:af83/stif-reflex-api.git
- revision: 7c517b98c3900c9bb0b81dd0ccab97f8e8f5f249
+ revision: 7edaeddd971a1ed366bf6def1513bf8808ab2d1d
specs:
- reflex (0.0.1)
- nokogiri (~> 1.6)
+ reflex (0.0.2)
+ nokogiri (>= 1.7.2)
+ ruby-filemagic
GIT
remote: https://github.com/af83/language_engine.git
@@ -146,8 +147,17 @@ GEM
coffee-script-source (1.12.2)
concurrent-ruby (1.0.5)
connection_pool (2.2.1)
+ countries (2.1.3)
+ i18n_data (~> 0.8.0)
+ money (~> 6.9)
+ sixarm_ruby_unaccent (~> 1.1)
+ unicode_utils (~> 1.4)
+ country_select (3.1.1)
+ countries (~> 2.0)
+ sort_alphabetical (~> 1.0)
crack (0.4.3)
safe_yaml (~> 1.0.0)
+ crass (1.0.3)
cucumber (2.4.0)
builder (>= 2.1.2)
cucumber-core (~> 1.5.0)
@@ -227,6 +237,8 @@ GEM
ffi (1.9.18)
ffi-geos (1.2.0)
ffi (>= 1.0.0)
+ flag-icons-rails (2.5.0)
+ sass (~> 3.2)
font-awesome-sass (4.7.0)
sass (>= 3.2)
formtastic (3.1.5)
@@ -254,13 +266,13 @@ GEM
hashdiff (0.3.4)
highline (1.7.8)
hike (1.2.3)
- hstore_accessor (1.1.0)
- activerecord (>= 4.0.0)
htmlbeautifier (1.3.1)
httparty (0.14.0)
multi_xml (>= 0.5.2)
- i18n (0.9.0)
+ i18n (0.9.4)
concurrent-ruby (~> 1.0)
+ i18n-js (3.0.4)
+ i18n (~> 0.6, >= 0.6.6)
i18n-tasks (0.9.15)
activesupport (>= 4.0.2)
ast (>= 2.1.0)
@@ -271,6 +283,7 @@ GEM
parser (>= 2.2.3.0)
rainbow (~> 2.2)
terminal-table (>= 1.5.1)
+ i18n_data (0.8.0)
inherited_resources (1.7.1)
actionpack (>= 3.2, < 5.1)
has_scope (~> 0.6)
@@ -295,7 +308,8 @@ GEM
thor
with_env (> 1.0)
xml-simple
- loofah (2.0.3)
+ loofah (2.1.1)
+ crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.6.4)
mime-types (>= 1.16, < 4)
@@ -306,7 +320,9 @@ GEM
mime-types-data (3.2016.0521)
mimemagic (0.3.2)
mini_portile2 (2.3.0)
- minitest (5.10.3)
+ minitest (5.11.3)
+ money (6.10.1)
+ i18n (>= 0.6.4, < 1.0)
multi_json (1.12.1)
multi_test (0.1.2)
multi_xml (0.6.0)
@@ -319,7 +335,7 @@ GEM
net-ssh-gateway (2.0.0)
net-ssh (>= 4.0.0)
newrelic_rpm (4.0.0.332)
- nokogiri (1.8.1)
+ nokogiri (1.8.2)
mini_portile2 (~> 2.3.0)
open4 (1.3.4)
orm_adapter (0.5.0)
@@ -355,9 +371,11 @@ GEM
rabl (0.13.1)
activesupport (>= 2.3.14)
rack (1.6.8)
+ rack-livereload (0.3.16)
+ rack
rack-protection (1.5.3)
rack
- rack-proxy (0.6.2)
+ rack-proxy (0.6.3)
rack
rack-test (0.6.3)
rack (>= 1.0)
@@ -385,8 +403,8 @@ GEM
rails-assets-jquery (>= 1.0.0)
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
- rails-dom-testing (1.0.8)
- activesupport (>= 4.2.0.beta, < 5.0)
+ rails-dom-testing (1.0.9)
+ activesupport (>= 4.2.0, < 5.0)
nokogiri (~> 1.6)
rails-deprecated_sanitizer (>= 1.0.1)
rails-erd (1.5.2)
@@ -408,7 +426,7 @@ GEM
thor (>= 0.18.1, < 2.0)
rainbow (2.2.2)
rake
- rake (12.0.0)
+ rake (12.3.0)
ransack (1.8.3)
actionpack (>= 3.0)
activerecord (>= 3.0)
@@ -431,6 +449,10 @@ GEM
roo (2.7.1)
nokogiri (~> 1)
rubyzip (~> 1.1, < 2.0.0)
+ rspec (3.5.0)
+ rspec-core (~> 3.5.0)
+ rspec-expectations (~> 3.5.0)
+ rspec-mocks (~> 3.5.0)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
rspec-expectations (3.5.0)
@@ -447,7 +469,10 @@ GEM
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-support (~> 3.5.0)
+ rspec-snapshot (0.1.1)
+ rspec (> 3.0.0)
rspec-support (3.5.0)
+ ruby-filemagic (0.7.2)
ruby-graphviz (1.2.3)
rubycas-client (2.3.9)
activesupport
@@ -490,6 +515,7 @@ GEM
rack (~> 1.5)
rack-protection (~> 1.4)
tilt (>= 1.3, < 3)
+ sixarm_ruby_unaccent (1.2.0)
slim (3.0.7)
temple (~> 0.7.6)
tilt (>= 1.3.3, < 2.1)
@@ -498,6 +524,8 @@ GEM
railties (>= 3.1)
slim (~> 3.0)
slop (3.6.0)
+ sort_alphabetical (1.1.0)
+ unicode_utils (>= 1.2.2)
spring (2.0.1)
activesupport (>= 4.2)
spring-commands-rspec (1.0.4)
@@ -521,7 +549,7 @@ GEM
therubyracer (0.12.3)
libv8 (~> 3.16.14.15)
ref
- thor (0.19.4)
+ thor (0.20.0)
thread (0.2.2)
thread_safe (0.3.6)
tilt (1.4.1)
@@ -533,19 +561,20 @@ GEM
json (>= 1.8, < 3.0)
parser (>= 2.3.0.7)
rainbow (>= 1.99.1, < 3.0)
- tzinfo (1.2.3)
+ tzinfo (1.2.5)
thread_safe (~> 0.1)
uglifier (2.7.2)
execjs (>= 0.3.0)
json (>= 1.8.0)
unicode-display_width (1.3.0)
+ unicode_utils (1.4.0)
warden (1.2.7)
rack (>= 1.0)
webmock (3.0.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
- webpacker (3.0.2)
+ webpacker (3.2.1)
activesupport (>= 4.2)
rack-proxy (>= 0.6.1)
railties (>= 4.2)
@@ -586,6 +615,7 @@ DEPENDENCIES
cocoon
codifligne!
coffee-rails (~> 4.0.0)
+ country_select
cucumber-rails
daemons
database_cleaner
@@ -607,6 +637,7 @@ DEPENDENCIES
faraday (~> 0.9.1)
faraday_middleware (~> 0.9.1)
ffaker (~> 2.1.0)
+ flag-icons-rails
font-awesome-sass (~> 4.7)
formtastic (= 3.1.5)
georuby (= 2.3.0)
@@ -614,8 +645,8 @@ DEPENDENCIES
google-analytics-rails
gretel
has_array_of!
- hstore_accessor (~> 1.1)
htmlbeautifier
+ i18n-js
i18n-tasks
inherited_resources
jbuilder (~> 2.0)
@@ -639,6 +670,7 @@ DEPENDENCIES
pundit
quiet_assets
rabl
+ rack-livereload
rails (~> 4.2.8)
rails-assets-bootstrap-sass-official (~> 3.3.0)!
rails-assets-footable (~> 2.0.3)!
@@ -658,6 +690,7 @@ DEPENDENCIES
rgeo (~> 0.5.2)
roo
rspec-rails (~> 3.5.0)
+ rspec-snapshot
rubyzip
sass-rails (~> 4.0.3)
sawyer (~> 0.6.0)
@@ -680,10 +713,10 @@ DEPENDENCIES
transpec
uglifier (~> 2.7.2)
webmock
- webpacker (~> 3.0)
+ webpacker (= 3.2.1)
whenever!
will_paginate
will_paginate-bootstrap
BUNDLED WITH
- 1.15.4
+ 1.16.1
diff --git a/Gruntfile.coffee b/Gruntfile.coffee
new file mode 100644
index 000000000..958ff81f8
--- /dev/null
+++ b/Gruntfile.coffee
@@ -0,0 +1,47 @@
+module.exports = (grunt) =>
+ javascriptSpecPath = (path) ->
+ grunt.log.debug "IN: " + path
+ path = path.replace 'app/javascript', 'spec/javascript'
+ if path.match /actions/
+ path = path.replace /actions.*/, 'actions_spec.js'
+ if path.match /reducers/
+ path = path.replace '.js', '_spec.js'
+ grunt.log.debug "OUT: " + path
+ path
+
+ grunt.initConfig
+ pkg: grunt.file.readJSON('package.json')
+ watch:
+ javascripts:
+ files: ['app/javascript/**/*', 'spec/javascript/**/*']
+ tasks: []
+ options:
+ spawn: false
+
+ watchchange:
+ javascript:
+ match: ['app/javascript/**/*', 'spec/javascript/**/*']
+ setConfig: ['jest.run.src']
+ preprocess: javascriptSpecPath
+ tasks: ['jest:run']
+
+ jest:
+ run:
+ files: []
+
+ grunt.loadNpmTasks('grunt-contrib-watch')
+ grunt.loadNpmTasks('grunt-watch-change')
+
+ # Default task(s).
+ grunt.registerMultiTask 'jest', 'run javascript specs', () ->
+ files = []
+ this.files.forEach (file) ->
+ files.push file.src
+ grunt.log.debug files
+ grunt.util.spawn
+ cmd: 'node_modules/.bin/jest'
+ args: files
+ opts: {stdio: 'inherit'}
+ , -> {}
+
+ grunt.registerTask 'default', ['watchchange', 'watch']
diff --git a/INSTALL.md b/INSTALL.md
index 45624e30b..e44b072f4 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,31 +1,40 @@
# Installation Guide
-This guide is based on mac/OS with [Homebrew](https://brew.sh/) and [RVM](https://rvm.io/)
-
## Ruby
-Get a correct `.ruby-version` (Can we remove it from `.gitignore`?)
-and install that version.
+Example with [rvm](https://rvm.io/) (other solutions : rbenv, packages..):
-Example with [rvm](https://rvm.io/):
+```sh
+rvm install 2.3.1
+```
- rvm install 2.3.1
+## Node and Yarn
-Add the bundler gem
+Yarn needs node. If you use Node Version Manager [NVM](https://github.com/creationix/nvm) you can rely on the content of `.nvmrc`. Otherwise please make sure to use a compatible version, still best to use the same as indicated by `.nvrmc`.
- gem install bundler
+* Install node
-Go into your local repro and install the gems
+```sh
+nvm install 6.12.0
+```
- bundle
+* Install [yarn](https://yarnpkg.com/lang/en/docs/install/)
-## Node and Yarn
+```sh
+// On macOS
+brew install yarn
-Yarn needs a node version ≥ 6, if you use Node Version Manager [NVM](https://github.com/creationix/nvm) you can rely on the content of `.nvmrc`.
+// On Debian/ubuntu
+curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
+echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
+sudo apt-get update && sudo apt-get install yarn
+```
-Otherwise please make sure to use a compatible version, still best to use the same as indicated by `.nvrmc`.
+* Install nodes packages
-Then install yarn (`brew install yarn` does nicely on macOS).
+```sh
+yarn install
+```
### Installation Caveats
@@ -33,13 +42,17 @@ Then install yarn (`brew install yarn` does nicely on macOS).
`libv8` might cause you troubles, depending on your local configuration. If you have `libv8` installed (probably because of `node.js`) you might need to tell bundler/Rubygems to use the system version.
-
- bundle config build.libv8 --with-system-v8
- bundle
+```sh
+bundle config build.libv8 --with-system-v8
+bundle
+```
or
- gem install libv8 -v '<version>' -- --with-system-v8
- bundle
+
+```sh
+gem install libv8 -v '<version>' -- --with-system-v8
+bundle
+```
You will get the correct value of `<version>` from bundler's error message.
@@ -49,35 +62,18 @@ Even after `libv8` installation working, the gem `therubyracer` might not like t
In that case however we can let the gem make its own choice:
- gem uninstall libv8
- gem install therubyracer -v '<version>'
+```sh
+gem uninstall libv8
+gem install therubyracer -v '<version>'
+```
The version to be installed is indicated in the error message bundler gave us in the first place.
This will install an appropriate `libv8` version and we can continue with `bundle`.
-## Rails
-
-### Dependencies
-
-As documented [here](https://github.com/dryade/georuby-ext/issues/2) we need some more libs before we can start the `rake` setup tasks. On mac/OS the easiest way is just to install `postgis` now with `homebrew` as this will
-install all needed libraries.
-
-Also if on Linux you might discover a problem as late as when launching `rake`.
-In case of a stacktrace similar to this one
-
-```
-$ bundle exec rake --trace -T
-rake aborted!
-LoadError: library names list must not be empty
-```
-
-you need to install `libproj4-dev` on your system.
-
-
-### Postgres
+## Postgres
-#### Create user
+### Create user
createuser -s -U $USER -P chouette
^ ^ ^
@@ -87,19 +83,20 @@ you need to install `libproj4-dev` on your system.
When promted for the password enter the highly secure string `chouette`.
+## Rails
-#### Create database
+### Dependencies
- bundle exec rake db:create
- bundle exec rake db:migrate
+As documented [here](https://github.com/dryade/georuby-ext/issues/2) we need some more libs before we can start the `rake` setup tasks.
- RAILS_ENV=test bundle exec rake db:create
- RAILS_ENV=test bundle exec rake db:migrate
-#### Install node.js packages
+On mac/OS :
- bundle exec rake npm:install
+```sh
+brew install postgis
+```
+<<<<<<< HEAD
### Authentication
See `config.chouette_authentication_settings`.
@@ -138,46 +135,105 @@ If PG complains about illegal type `hstore` in your tests that is probably becau
bundle exec rails server
+=======
+On debian/ubuntu system :
-#### Synchronize With STIF
+```sh
+sudo apt-get install libproj-dev postgis
+```
-If you have access to STIF CodifLigne and Reflex :
+### Install gems
+
+Add the bundler gem
+
+```sh
+gem install bundler
+```
+
+Go into your local repository and install the gems
+
+```sh
+bundle install
+```
+
+#### Nokogiri on macOS
+
+http://www.nokogiri.org/tutorials/installing_nokogiri.html tells us that `xz` can cause troubles, here is what to do
+
+```
+brew unlink xz
+gem install nokogiri # or bundle install
+brew link xz
+```
+
+### Database
+
+#### Create database
+
+```sh
+bundle exec rake db:create db:migrate
+RAILS_ENV=test bundle exec rake db:create db:migrate
+```
+
+#### Load seed datas
+>>>>>>> master
+
+```sh
+bundle exec rake db:seed:stif
+```
+
+#### Synchronise datas with lines and stop areas referentials
* Launch Sidekiq
- bundle exec sidekiq
+```sh
+bundle exec sidekiq
+```
* Execute the Synchronization Tasks
- bundle exec rake codifligne:sync
- bundle exec rake reflex:sync
+```sh
+bundle exec rake codifligne:sync
+bundle exec rake reflex:sync
+```
**N.B.** These are asynchronious tasks, you can observe the launched jobs in your [Sidekiq Console](http://localhost:3000/sidekiq)
#### Data in various Apartments (Referentials)
-To create `Referential` objects with some data (`Route`, `JourneyPattern`, `VehicleJourney`, etc) :
+To create `Referential` objects with some data (`Route`, `JourneyPattern`, `VehicleJourney`, etc), you need to wait codifligne and reflex jobs finished. And then you can launch :
- bundle exec rake referential:create
+```sh
+bundle exec rake referential:create
+```
-# Troubleshooting
+### Check installation
-## Postgres
+#### Run tests
-If Postgres complains about illegal type `hstore` in your tests that is probably because the shared extension is not installed, here is what to do:
+#### Rspec
+
+```sh
+bundle exec rake spec
+bundle exec rake teaspoon
+```
+
+If Postgres complains about illegal type `hstore` or `unaccent` in your tests that is probably because the shared extension is not installed, here is what to do:
bundle exec rake db:test:purge
Thanks to `lib/tasks/extensions.rake`.
-## macOS
+#### Jest (React integration specs)
-### Nokogiri
+`grunt jest` to run the whole specs.
-http://www.nokogiri.org/tutorials/installing_nokogiri.html tells us that `xz` can cause troubles, here is what to do
+`grunt` to watch for changes and automatically run corresponding tests.
+#### Start local server
+
+```sh
+bin/webpack-dev-server // Launch webpack server to compile assets on the fly
+bundle exec rails server // Launch rails server
```
-brew unlink xz
-gem install nokogiri # or bundle install
-brew link xz
-```
+You need to have an account on [STIF Portail](http://stif-portail-dev.af83.priv/) to connect to the Rails application.
diff --git a/README.md b/README.md
index c7dd6d333..83ede1b13 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,15 @@
# Chouette2 [![Build Status](https://travis-ci.org/afimb/chouette2.svg?branch=master)](https://travis-ci.org/afimb/chouette2) [![Dependency Status](https://gemnasium.com/afimb/chouette2.png)](https://gemnasium.com/afimb/chouette2) [![Code Climate](https://codeclimate.com/github/afimb/chouette2.png)](https://codeclimate.com/github/afimb/chouette2)
Chouette2 is an open source web project in Ruby/Rails to edit and view transport offer data. It is designed as an [SaaS](http://en.wikipedia.org/wiki/Software_as_a_service) platform and can :
-* Exchange transport data : [Neptune](http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/neptune/), [GTFS](https://developers.google.com/transit/gtfs/reference?hl=fr), [NeTEx](http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/netex/), CSV
+* Exchange transport data
+ * [Neptune](http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/neptune/),
+ * [GTFS](https://developers.google.com/transit/gtfs/reference?hl=fr),
+ * [NeTEx](http://www.normes-donnees-tc.org/format-dechange/donnees-theoriques/netex/)
* Edit transport data
* Be requested via a read-only [Restful API](https://en.wikipedia.org/wiki/Representational_state_transfer)
* [Import, Export and Validate transport data asynchronously](http://github.com/afimb/chouette)
* Use a [multi-tenancy database](http://en.wikipedia.org/wiki/Multitenancy)
-Chouette2 uses Rest Web Service API from [chouette](http://github.com/afimb/chouette) (another git project) to import, export and validate various transport data.
-
-Feel free to test and access to the free SaaS web site at [http://appli.chouette.mobi](http://appli.chouette.mobi/chouette2/users/sign_in). Two types of access are granted :
-* A demo organisation with an existing Public Transport dataset
- * login : demo@chouette.mobi
- * password : chouette
-* Create your own organisation : follow the link "Sign up" ("S'inscrire")
-
Release Notes
-------------
@@ -23,162 +18,28 @@ The release notes (in French) can be found in the [CHANGELOG](./CHANGELOG.md) fi
Requirements
------------
-* [Chouette IEV 3.X Web Service](https://github.com/afimb/chouette) (requires Postgresql and Java)
-* Ruby 1.9.3 or 2.1.6
-* Bundler 1.10.3
-* Proj 4.8.0
-
-External Deps
--------------
-
-Install Chouette IEV 3.X Web Service [see how to](https://github.com/afimb/chouette/readme.md)
-Next steps assumes that :
-* a Chouette IEV Web Service is running (on localhost, port 8080)
-* a Postgres database exists (chouette2 on localhost, port 5432) with a postgres user (chouette, with password chouette)
-
-On Debian/Ubuntu/Kubuntu OS : assumes that the depot contains the correct version
-```sh
-sudo apt-get install libpq-dev
-sudo apt-get install git
-sudo apt-get install unzip
-sudo apt-get install proj-bin
-sudo apt-get install libproj-dev
-sudo apt-get install make
-sudo apt-get install libmagic-dev
-```
-
-If Linux distribution doesn't publish an RVM package,
-install [RVM from sources](./doc/install/rvm.md)
-
-Install ruby 2.1.6
-```sh
-rvm install ruby-2.1.6
-rvm --default use 2.1.6
-```
-
-Install bundler 1.10.3
-```sh
-gem install bundler -v 1.10.3
-```
-
-Installation
-------------
-
-On Debian, chouette can also be installed as a package : see [debian packages](http://packages.chouette.cityway.fr/debian/chouette)
-
-Install web application
-
-Get git source code :
-```sh
-cd
-git clone -b V3_1 git://github.com/afimb/chouette2
-cd chouette2
-```
-Download gem librairies
-```sh
-bundle install
-```
-Update database schema
-```sh
-RAILS_ENV=production bundle exec rake db:migrate
-```
-Prepare static resources (assets)
-```sh
-RAILS_ENV=production bundle exec rake assets:clobber assets:precompile
-```
-
-Configuration
--------------
-
-Configure for Generating URLs in Action Mailer Views.
-* Edit [production.rb](./config/environments/production.rb) and change ```config.action_mailer.default_url_options```
-* see [Action Mailer Configuration documentation](http://guides.rubyonrails.org/action_mailer_basics.html)
-
-Configure assets access (Must be true if you use Webrick, or false if you use Apache or Nginx).
-* Edit [production.rb](./config/environments/production.rb) and change ```config.serve_static_files```
-
-Configure SMTP settings.
-* Edit [production.rb](./config/environments/production.rb) and change ```ActionMailer::Base.smtp_settings```
-* see [Action Mailer Configuration documentation](http://guides.rubyonrails.org/action_mailer_basics.html)
-
-Configure e-mail send address visible on the e-mail sent when a user registers, re-initialises its password, ...
-* Edit [production.rb](./config/environments/production.rb) and change ```config.mailer_sender```
-
-Configure Rails secret key.
-* Edit [secrets.yml](./config/secrets.yml) and uncomment and set```secret_key_base```
-* see [Rails documentation](http://guides.rubyonrails.org/4_1_release_notes.html#config-secrets-yml)
-
-Configure address of the Chouette IEV Web Service.
-* Edit [secrets.yml](./config/secrets.yml) and uncomment and set```api_endpoint```
-
-Configure Google Analytics Key.
-* Edit [secrets.yml](./config/secrets.yml) and change```google_analytic_tracker```
-* see [Google Analytics](https://www.google.fr/intl/fr/analytics/)
+* [Import, Export and Validation Operations](https://github.com/af83/stif-boiv-iev) are in another project in Java
-Configure IGN Géoportail Key.
-* Edit [secrets.yml](./config/secrets.yml) and uncomment and set```geoportail_api_key```
-* see [API Géoportail documentation](http://api.ign.fr/accueil)
-
-Configure the way that Chouette2 sends e-mail.
-* Edit [devise_async.rb](./config/initializer/devise_async.rb) and uncomment and set```Devise::Async.enabled``` ( true if you want to use asynchronously and false otherwise )
-* see [Devise Async specification](https://github.com/mhfs/devise-async)
-
-Configure OSRM Backend URL
-* Edit [secrets.yml](./config/secrets.yml) and change```osrm_endpoint```
-* see [Project-OSRM](https://github.com/Project-OSRM/osrm-backend/wiki/Api-usage-policy)
-
-Run
----
-
-Launch the task if you want to send mail asynchronously (See previous chapter to desactivate it)
-```sh
-RAILS_ENV=production bundle exec rake jobs:work
-```
-This task may be added in system start-up configuration
-
-Launch rails server with [WEBrick](http://guides.rubyonrails.org/command_line.html#server-with-different-backends) ( default RoR web server, note: webrick runs on default port 3000)
-```sh
-RAILS_ENV=production bundle exec rails server
-```
-
-This task may be added in system start-up configuration.
-Instead of using WEBrick, Rails application may be deployed on [Phusion Passenger](https://www.phusionpassenger.com/) with an [Apache](http://httpd.apache.org/) or [NGinx](http://nginx.com/) front-end, to make server faster and more robust.
-
-Apache like NGinx can serve static resources,
-so change parameter ```serve_static_files``` to false in [production.rb](./config/environments/production.rb)
-
-Test
-----
+Install
+-------
-```sh
-bundle exec rake db:create
-bundle exec rake db:migrate
-bundle exec rake spec
-```
+See [installation manual](./INSTALL.md)
More Information
----------------
-Complete docs (in French) can be found on the [project website](http://www.chouette.mobi/developpeurs).
Some technical articles are available [on the wiki](../../wiki) too.
API Documentation
-----------------
-The description (in French) of the read-only restful API is described in :
-* [User manual file](./doc/interfaces/Chouette_API_REST_v1.2.pdf)
-* [XSD file](./doc/interfaces/api_rest_v1.xsd)
+TODO
License
-------
This project is licensed under the CeCILL-B license, a copy of which can be found in the [LICENSE](./LICENSE.md) file.
-Project-OSRM Licence
--------------------------
-
-Project-OSRM is licensed under the [ODbL](http://opendatacommons.org/licenses/odbl/) licence.
-
Release Notes
-------------
@@ -188,8 +49,3 @@ Support
-------
Users looking for support should file an issue on the GitHub [issue tracking page](../../issues), or file a [pull request](../../pulls) if you have a fix available.
-
-Credits
--------
-
-Thanks to Ingolf for his [photo](https://www.flickr.com/photos/ingolfbln/7663851694) under CC BY-SA 2.0 license
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 4c5aff22f..6a79f7e8e 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -22,3 +22,6 @@
//= require_directory .
// require('whatwg-fetch')
// require('babel-polyfill')
+//= require "i18n"
+//= require "i18n/extended"
+//= require "i18n/translations"
diff --git a/app/assets/javascripts/forms.coffee b/app/assets/javascripts/forms.coffee
index 12d82fef1..b7ae3c6ca 100644
--- a/app/assets/javascripts/forms.coffee
+++ b/app/assets/javascripts/forms.coffee
@@ -32,14 +32,25 @@ isEdge = !isIE && !!window.StyleMedia
@colorSelector = ->
$('.form-group .dropdown.color_selector').each ->
- selectedStatus = $(this).children('.dropdown-toggle').children('.fa-circle')
-
+ selectedStatusColor = $(this).children('.dropdown-toggle').children('.fa-circle')
+ selectedStatusLabel = $(this).children('.dropdown-toggle')
+ self = this
$(this).on 'click', "input[type='radio']", (e) ->
selectedValue = e.currentTarget.value
+ selectedText = $(e.currentTarget).parent()[0].textContent
+ if e.currentTarget.getAttribute("data-for")
+ hidden = $("[name=\"#{e.currentTarget.getAttribute("data-for")}\"]")
+
if selectedValue == ''
- $(selectedStatus).css('color', 'transparent')
+ $(selectedStatusColor).css('color', 'transparent')
+ $(selectedStatusLabel).contents().filter( -> this.nodeType == 3 ).filter(':first').text = ""
+ hidden?.val ""
else
- $(selectedStatus).css('color', selectedValue)
+ $(selectedStatusColor).css('color', selectedValue)
+ $(selectedStatusLabel).contents().filter( -> this.nodeType == 3 ).first().replaceWith selectedText
+ hidden?.val selectedValue
+
+ $(self).find('.dropdown-toggle').click()
$ ->
togglableFilter()
diff --git a/app/assets/javascripts/i18n/extended.coffee b/app/assets/javascripts/i18n/extended.coffee
new file mode 100644
index 000000000..aeb67bd09
--- /dev/null
+++ b/app/assets/javascripts/i18n/extended.coffee
@@ -0,0 +1,24 @@
+#= require i18n
+
+decorateI18n = (_i18n)->
+ _i18n.tc = (key, opts={}) ->
+ out = _i18n.t(key, opts)
+ out += " " if _i18n.locale == "fr"
+ out + ":"
+
+ _i18n.model_name = (model, opts={}) ->
+ last_key = if opts.plural then "other" else "one"
+ _i18n.t("activerecord.models.#{model}.#{last_key}")
+
+ _i18n.attribute_name = (model, attribute, opts={}) ->
+ _i18n.t("activerecord.attributes.#{model}.#{attribute}")
+
+ _i18n.enumerize = (enumerize, key, opts={}) ->
+ I18n.t("enumerize.#{enumerize}.#{key}")
+
+ _i18n
+
+module?.exports = decorateI18n
+
+if I18n?
+ decorateI18n(I18n)
diff --git a/app/assets/javascripts/main_menu.coffee b/app/assets/javascripts/main_menu.coffee
index a12c47576..e943f448a 100644
--- a/app/assets/javascripts/main_menu.coffee
+++ b/app/assets/javascripts/main_menu.coffee
@@ -1,12 +1,11 @@
$ ->
- link = []
+ stickyActions = []
ptitleCont = ""
$(document).on 'page:before-change', ->
- link = []
+ stickyActions = []
ptitleCont = ""
-
$el = $('#main_nav')
# Opening/closing left-side menu
$el.find('.openMenu').on 'click', (e) ->
@@ -24,34 +23,45 @@ $ ->
limit = 51
if $(window).scrollTop() >= limit
- if ($('.page-action .small').length > 0)
- data = $('.page-action .small')[0].innerHTML
+ if stickyActions.length == 0
+ if ($('.page-action .small').length > 0)
+ stickyActions.push
+ content: [
+ $('.page-action .small'),
+ $('.page-action .small').first().next()
+ ]
+ originalParent: $('.page-action .small').parent()
+
+ for action in $(".sticky-action, .sticky-actions")
+ stickyActions.push
+ class: "small",
+ content: [$(action)]
+ originalParent: $(action).parent()
- if ($(".page-title").length > 0)
+ if $(".page-title").length > 0
ptitleCont = $(".page-title").html()
- stickyContent = '<div class="sticky-content">'
- stickyContent += '<div class="sticky-ptitle">' + ptitleCont + '</div>'
- stickyContent += '<div class="sticky-paction"><div class="small">' + data + '</div></div>'
- stickyContent += '</div>'
+ stickyContent = $('<div class="sticky-content"></div>')
+ stickyContent.append $("<div class='sticky-ptitle'>#{ptitleCont}</div>")
+ stickyContent.append $('<div class="sticky-paction"></div>')
$('#main_nav').addClass 'sticky'
if $('#menu_top').find('.sticky-content').length == 0
if ptitleCont.length > 0
$('#menu_top').children('.menu-content').after(stickyContent)
- if link.length == 0
- link = $('.page-action .small').next()
-
- $('.sticky-paction .small').after(link)
+ for item in stickyActions
+ for child in item.content
+ child.appendTo $('.sticky-paction')
else
$('#main_nav').removeClass 'sticky'
if $('#menu_top').find('.sticky-content').length > 0
- if !$('.page-action').find('.formSubmitr').length
- $('.page-action .small').after(link)
+ for item in stickyActions
+ for child in item.content
+ child.appendTo item.originalParent
$('.sticky-content').remove()
- sticker();
+ sticker()
# Sticky behavior
$(document).on 'scroll', sticker
diff --git a/app/assets/javascripts/select2.coffee b/app/assets/javascripts/select2.coffee
index 2e3884d7f..05b73dc6b 100644
--- a/app/assets/javascripts/select2.coffee
+++ b/app/assets/javascripts/select2.coffee
@@ -9,18 +9,18 @@ bind_select2 = (el, cfg = {}) ->
target.select2 $.extend({}, default_cfg, cfg)
bind_select2_ajax = (el, cfg = {}) ->
- target = $(el)
+ _this = $(el)
cfg =
ajax:
data: (params) ->
- q:
- "#{target.data('term')}": params.term
- url: target.data('url'),
+ if _this.data('term')
+ { q: "#{_this.data('term')}": params.term }
+ else
+ { q: params.term }
+ url: _this.data('url'),
dataType: 'json',
delay: 125,
processResults: (data, params) -> results: data
- minimumInputLength: 1
- placeholder: target.data('select2ed-placeholder')
templateResult: (item) ->
item.text
templateSelection: (item) ->
@@ -28,6 +28,9 @@ bind_select2_ajax = (el, cfg = {}) ->
escapeMarkup: (markup) ->
markup
+ if _this.data('initvalue')
+ cfg["initSelection"] = (item, callback) -> callback(_this.data('initvalue'))
+
bind_select2(el, cfg)
@select_2 = ->
@@ -40,7 +43,5 @@ bind_select2_ajax = (el, cfg = {}) ->
$('select.form-control.tags').each ->
bind_select2(this, {tags: true})
-
-
$ ->
select_2()
diff --git a/app/assets/stylesheets/OpenLayers/custom.sass b/app/assets/stylesheets/OpenLayers/custom.sass
index 7a5b4baf1..fa874d924 100644
--- a/app/assets/stylesheets/OpenLayers/custom.sass
+++ b/app/assets/stylesheets/OpenLayers/custom.sass
@@ -2,6 +2,26 @@
.list-group-item &
margin-top: 15px
+ .routes-labels
+ padding: 0
+ display: flex
+ justify-content: space-between
+ flex-wrap: wrap
+ margin: 5px -5px
+ li
+ list-style-type: none
+ flex: 1 0 25%
+ border: 1px solid $lightgrey
+ padding: 5px
+ margin: 5px
+ border-radius: 5px
+ cursor: pointer
+ color: $blue
+ white-space: nowrap
+
+ &:hover
+ background: $orange
+ color: white
.ol-scale-line
background-color: transparent
diff --git a/app/assets/stylesheets/_layout.sass b/app/assets/stylesheets/_layout.sass
index b6b91b2a5..340467e77 100644
--- a/app/assets/stylesheets/_layout.sass
+++ b/app/assets/stylesheets/_layout.sass
@@ -28,6 +28,7 @@ body
// width: 75%
border-bottom: 1px solid rgba($blue, 0.5)
margin: 30px auto 45px auto
+ clear: both
.content_header
font-size: 2.2rem
diff --git a/app/assets/stylesheets/application.sass b/app/assets/stylesheets/application.sass
index 50f8b64cb..3f8467efe 100644
--- a/app/assets/stylesheets/application.sass
+++ b/app/assets/stylesheets/application.sass
@@ -19,3 +19,5 @@
@import 'modules/vj_collection'
@import 'modules/timetables'
@import 'modules/import_messages'
+
+@import 'flag-icon'
diff --git a/app/assets/stylesheets/base/_config.sass b/app/assets/stylesheets/base/_config.sass
index 65444479f..0fff1dd9c 100644
--- a/app/assets/stylesheets/base/_config.sass
+++ b/app/assets/stylesheets/base/_config.sass
@@ -16,6 +16,8 @@ $blue: #007fbb
$darkgrey: #4b4b4b
$grey: #a4a4a4
+$lightgrey: lighten($grey, 25)
+$lightergrey: lighten($lightgrey,5)
$green: #70b12b
$red: #da2f36
diff --git a/app/assets/stylesheets/base/_utilities.sass b/app/assets/stylesheets/base/_utilities.sass
index 24f2038f0..fbda5630d 100644
--- a/app/assets/stylesheets/base/_utilities.sass
+++ b/app/assets/stylesheets/base/_utilities.sass
@@ -44,7 +44,7 @@
// Empty zones
=emptyzone($col1, $col2)
- background-image: linear-gradient(-45deg, $col1 25%, $col2 25%, $col2 50%, $col1 50%, $col1 75%, $col2 75%, transparent)
+ background-image: linear-gradient(-45deg, $col1 25%, $col2 25%, $col2 50%, $col1 50%, $col1 75%, $col2 75%, $col2)
background-size: 40px 40px
.cellwrap
diff --git a/app/assets/stylesheets/components/_breadcrumb.sass b/app/assets/stylesheets/components/_breadcrumb.sass
index 62f167eb4..1b30ca42b 100644
--- a/app/assets/stylesheets/components/_breadcrumb.sass
+++ b/app/assets/stylesheets/components/_breadcrumb.sass
@@ -1,3 +1,6 @@
.breadcrumbs
+ white-space: nowrap
+ text-overflow: ellipsis
+ overflow: hidden
a
- color: white \ No newline at end of file
+ color: white
diff --git a/app/assets/stylesheets/components/_buttons.sass b/app/assets/stylesheets/components/_buttons.sass
index a59699383..2881cee3e 100644
--- a/app/assets/stylesheets/components/_buttons.sass
+++ b/app/assets/stylesheets/components/_buttons.sass
@@ -143,28 +143,49 @@ table, .table
border-radius: 0
box-shadow: 0 0 3px rgba($darkgrey, 0.25)
+ & > ul:not(:first-child)
+ position: relative
+ margin-top: 11px
+ &:before
+ content: ''
+ display: block
+ position: absolute
+ left: 15px
+ right: 15px
+ top: -6px
+ height: 1px
+ background-color: $grey
+
+ ul.dropdown-menu, .dropdown-menu > ul
+ padding: 0
+ margin: 0
> li > a, > li > button
padding: 5px 15px
+ white-space: nowrap
+ padding: 5px 15px
+ font-weight: normal
+ line-height: $line-height
+ display: block
+ font-size: 14px
+ &:hover, &:focus
+ text-decoration: none
+ background-color: whitesmoke
+ outline: none
> li.delete-action
> a, > button
display: block
position: relative
- margin-top: 11px
-
- &:before
- content: ''
- display: block
- position: absolute
- left: 15px
- right: 15px
- top: -6px
- height: 1px
- background-color: $grey
-
.fa:first-child
margin-right: 0.5em
+ & + li.delete-action
+ > a, > button
+ margin-top: 0
+ &:before
+ display: none
+
+
&.table-2entries .t2e-item
> .th
position: relative
diff --git a/app/assets/stylesheets/components/_color_selector.sass b/app/assets/stylesheets/components/_color_selector.sass
new file mode 100644
index 000000000..07bfa0c80
--- /dev/null
+++ b/app/assets/stylesheets/components/_color_selector.sass
@@ -0,0 +1,21 @@
+select.color_selector
+ option[value='#9B9B9B']
+ background-color: #9B9B9B
+ option[value='#FFA070']
+ background-color: #FFA070
+ option[value='#C67300']
+ background-color: #C67300
+ option[value='#7F551B']
+ background-color: #7F551B
+ option[value='#41CCE3']
+ background-color: #41CCE3
+ option[value='#09B09C']
+ background-color: #09B09C
+ option[value='#3655D7']
+ background-color: #3655D7
+ option[value='#6321A0']
+ background-color: #6321A0
+ option[value='#E796C6']
+ background-color: #E796C6
+ option[value='#DD2DAA']
+ background-color: #DD2DAA \ No newline at end of file
diff --git a/app/assets/stylesheets/components/_dropdown.sass b/app/assets/stylesheets/components/_dropdown.sass
index 8a8d69063..a0d217b14 100644
--- a/app/assets/stylesheets/components/_dropdown.sass
+++ b/app/assets/stylesheets/components/_dropdown.sass
@@ -18,9 +18,19 @@
background-color: whitesmoke
outline: none
- > .disabled > a, > .disabled > button
- cursor: not-allowed
- &, &:hover, &:focus
- color: rgba($darkgrey, 0.5)
- background-color: transparent
- outline: none
+ &, & > ul
+ > .disabled > a, > .disabled > button
+ cursor: not-allowed
+ &, &:hover, &:focus
+ color: rgba($darkgrey, 0.5)
+ background-color: transparent
+ outline: none
+
+ > ul > li > a
+ display: block
+ padding: 3px 20px
+ clear: both
+ font-weight: normal
+ line-height: 1.42857
+ color: #333333
+ white-space: nowrap
diff --git a/app/assets/stylesheets/components/_forms.sass b/app/assets/stylesheets/components/_forms.sass
index 9a363ab97..caa8ac0e4 100644
--- a/app/assets/stylesheets/components/_forms.sass
+++ b/app/assets/stylesheets/components/_forms.sass
@@ -85,9 +85,15 @@ input
// BS horizontal form label positionning fix
.form-horizontal
+ input[type="radio"].form-control
+ height: auto
+ width: auto
.form-group
position: relative
-
+ .radio-inline
+ padding-top: 4px
+ &:first-child
+ padding-left: 0
> .control-label
&[class*='col-sm-']
float: none
@@ -229,6 +235,13 @@ $cbx-size-xs: 15px
&[type='checkbox']:checked + label:before
background-color: $blue
+ &[type='checkbox']:disabled + label
+ &:before
+ border-color: $grey
+ background-color: $lightgrey
+ cursor: not-allowed
+ &:after
+ display: none
// Table adjustments
table, .table
.td, td, .th, th
@@ -243,8 +256,15 @@ table, .table
&.table-2entries .t2e-item
> .th
position: relative
-
- > .checkbox
+ > .st_action
+ list-style-type: none
+ button
+ border-radius: 50%
+ background: $blue
+ color: white
+ border: none
+
+ > .checkbox, > .st_action
position: absolute
right: 0
top: 0
@@ -277,6 +297,7 @@ table, .table
height: $cbx-size
width: $cbx-size
margin: 0 auto
+ transition: transform 0.2s, background-color 0.2s
> input[type='checkbox']
&:not(:checked), &:checked
@@ -436,6 +457,19 @@ table, .table
margin: 0
min-height: 41px
padding: 5px 15px
+ &.active
+ &:after
+ position: absolute
+ top: 0
+ left: 0
+ right: 0
+ height: 4px
+ background: $blue
+ content: ""
+ &.per-page-select
+ padding-top: 10px
+ .selected
+ font-weight: bold
.control-label
font-weight: 700
@@ -454,6 +488,20 @@ table, .table
> .form-group.select2ed
width: 300px
+ &.name-filter
+ .checkbox_list
+ .form-group
+ padding: 10px
+ width: 100px
+ &.to
+ width: 20px
+ color: $grey
+ text-align: center
+ input
+ width: 100%
+ & + .form-group
+ padding-left: 0px
+
> .actions
position: absolute
right: 15px
diff --git a/app/assets/stylesheets/components/_lists.sass b/app/assets/stylesheets/components/_lists.sass
index d8f83d72b..3cce20021 100644
--- a/app/assets/stylesheets/components/_lists.sass
+++ b/app/assets/stylesheets/components/_lists.sass
@@ -54,3 +54,8 @@ $dlWidth: 40%
// Definition
.dl-def
width: 100% - $dlWidth
+
+ ul
+ list-style: none
+ padding-left: 0
+ margin-bottom: 0 \ No newline at end of file
diff --git a/app/assets/stylesheets/components/_main_nav.sass b/app/assets/stylesheets/components/_main_nav.sass
index fdbf5836a..2af070389 100644
--- a/app/assets/stylesheets/components/_main_nav.sass
+++ b/app/assets/stylesheets/components/_main_nav.sass
@@ -17,6 +17,9 @@ $menuW: 300px
line-height: $menuH
padding-left: 10px
opacity: 0.6
+ > a
+ color: rgba(#fff, 0.9)
+ text-decoration: none
#menu_left
position: absolute
@@ -240,6 +243,9 @@ $menuW: 300px
left: 0
top: 13px
+ & > .menu-item
+ max-width: 75%
+
.menu-item
padding: 0 10px
@@ -321,54 +327,45 @@ $menuW: 300px
height: $menuH * 2
transition: 0.1s
- #menu_top > .menu-content > .menu-item-group
- display: none
+ #menu_top > .menu-content
+ & > .menu-item
+ max-width: 90%
+ & > .menu-item-group
+ display: none
.sticky-content
height: $menuH
padding: 0 50px 0 75px
margin-top: -4px
+ display: flex
> *
display: inline-block
&.sticky-ptitle
- width: 60%
+ flex: 1 1
height: $menuH
+ position: relative
h1
- position: relative
+ position: absolute
+ left: 0
+ right: 10px
+ top: 0
line-height: 1.1
white-space: nowrap
max-height: 1.1em
margin: 0 -1.4em 0 0
- padding: 0 1.4em 0 0
+ padding: 0 1.4em 5px 0
overflow: hidden
-
- &:before
- content: '[...]'
- font-size: 0.65em
- position: absolute
- z-index: 5
- right: 0
- bottom: 4px
-
- &:after
- content: ''
- position: absolute
- z-index: 5
- right: 0
- width: 1.4em
- height: 1em
- margin-top: 0.2em
- background-color: $blue
+ text-overflow: ellipsis
.small.fa
color: #fff
margin-left: 0.5em
&.sticky-paction
- width: 40%
+ flex: 0 0 auto
text-align: right
vertical-align: top
diff --git a/app/assets/stylesheets/components/_panels.sass b/app/assets/stylesheets/components/_panels.sass
index e9f615081..ab25d8184 100644
--- a/app/assets/stylesheets/components/_panels.sass
+++ b/app/assets/stylesheets/components/_panels.sass
@@ -34,6 +34,7 @@
a
text-decoration: none
color: $blue
+ text-transform: capitalize
&:hover, &:focus
color: $darkblue
diff --git a/app/assets/stylesheets/components/_referential_overview.sass b/app/assets/stylesheets/components/_referential_overview.sass
new file mode 100644
index 000000000..0beb8ab67
--- /dev/null
+++ b/app/assets/stylesheets/components/_referential_overview.sass
@@ -0,0 +1,346 @@
+.referential-overview
+ $left-size: 100px
+ $line-height: 60px
+ margin-top: 50px
+ overflow: hidden
+ .time-travel, .filters
+ background-color: $lightergrey
+ padding: 10px
+ float: right
+ border-top-left-radius: 4px
+ border-top-right-radius: 4px
+ border: 1px solid $lightgrey
+ border-bottom: none
+ position: relative
+ &:after
+ position: absolute
+ content: ""
+ left: 0
+ top: 100%
+ right: 0
+ height: 10px
+ box-shadow: 0 0 10px rgba(0,0,0,0.5)
+ z-index: 1
+ .time-travel
+ padding-top: 4px
+ padding-bottom: 4px
+ a.btn:first-child
+ margin-right: 1px
+ a.btn:last-child
+ margin-right: 1px
+
+ max-width: 33%
+ .btn-group, .form-group
+ position: relative
+ z-index: 2
+ .form-group
+ margin-left: 10px
+ margin-bottom: 0
+ display: inline-block
+ input
+ padding: 6px 5px
+ border: 1px solid $lightgrey
+ outline: none
+ height: 34px
+ border-radius: 4px
+ padding-right: 25px
+ a
+ padding: 4px
+ margin-top: 2px
+ margin-left: -25px
+ .filters
+ float: left
+ max-width: 66%
+ padding: 0
+ form
+ background: transparent
+ display: flex
+ .ffg-row
+ border-color: $grey
+ .form-group
+ border-color: $grey
+ width: auto
+ flex: 1 1
+ padding: 4px 11px 5px
+ .input-group-btn
+ right: 10px
+ &.togglable
+ padding-top: 6px
+ padding-bottom: 5px
+ &:before
+ top: 0px
+
+ .overview-table
+ position: relative
+ z-index: 2
+ border: 1px solid $grey
+ clear: both
+ display: flex
+ +emptyzone($lightgrey, $lightergrey)
+ .head
+
+ height: $left-size
+ .line
+ height: $line-height
+ .left
+ flex: 0 0
+ background: $lightergrey
+ min-width: $left-size
+ overflow: hidden
+ border-right: 1px solid white
+ .head
+ position: relative
+ border-bottom: 1px solid $grey
+ border-right: 1px solid $lightgrey
+ .dates, .lines
+ position: absolute
+ font-size: 0.8em
+ z-index: 2
+ .dates
+ right: 20px
+ top: 20px
+ .lines
+ left: 20px
+ bottom: 20px
+ &:after
+ position: absolute
+ border-left: ($left-size - 2px)/2 solid transparent
+ border-bottom: ($left-size - 2px)/2 solid transparent
+ border-right: ($left-size - 2px)/2 solid white
+ border-top: ($left-size - 2px)/2 solid white
+ z-index: 1
+ top: 0
+ right: 0
+ width: 0
+ content: ""
+ .line
+ padding: 7px 10px
+ border-bottom: 1px solid $grey
+ font-size: 0.8em
+ &:last-child
+ border-bottom: none
+ .number
+ border-radius: 100px
+ display: inline-block
+ min-width: 20px
+ height: 20px
+ text-align: center
+ padding: 1px 4px
+ text-decoration: none
+ color: black
+ border: 1px solid $grey
+ max-width: 100%
+ white-space: nowrap
+ text-overflow: ellipsis
+ overflow: hidden
+ .name
+ display: inline-block
+ width: $left-size - 50px()
+ white-space: nowrap
+ line-height: 20px
+ margin-left: 5px
+ text-overflow: ellipsis
+ overflow: hidden
+ vertical-align: bottom
+ color: black
+ text-decoration: none
+
+ .company, .mode
+ font-size: 0.9em
+ white-space: nowrap
+ text-overflow: ellipsis
+ overflow: hidden
+ margin-top: -2px
+ .mode
+ text-transform: uppercase
+ color: $grey
+ font-weight: bold
+ .right
+ flex: 1 1
+ overflow: hidden
+ .inner .lines
+ transition: margin-left 0.5s
+ .head
+ white-space: nowrap
+ position: relative
+ z-index: 3
+ &:after, &:before
+ opacity: 0
+ // transition: opacity 0.5s
+ content: ""
+ position: absolute
+ left: -1000px
+ right: 100%
+ top: 0px
+ bottom: 0
+ background: $darkblue
+ z-index: 11
+ border-top: 1px solid white
+ .week
+ display: inline-block
+ position: relative
+ height: 100%
+ transition: margin 0.5s
+ background: white
+ &:last-child
+ box-shadow: 0 -10px 10px rgba(0,0,0,0.5)
+ .week-span
+ left: 15px
+ top: 15px
+ right: 30px
+ white-space: nowrap
+ overflow: hidden
+ text-overflow: ellipsis
+ position: absolute
+
+ .week-number
+ background-color: $lightgrey
+ color: $grey
+ position: absolute
+ top: 0
+ right: 0
+ padding: 2px 4px
+
+ &:after
+ position: absolute
+ right: 0
+ top: 0
+ bottom: 0
+ background: $grey
+ width: 1px
+ content: ""
+
+ &:last-child:after
+ display: none
+
+ .days
+ position: relative
+ top: 50%
+ height: 50%
+ border-top: 1px solid $grey
+ border-bottom: 1px solid $grey
+
+ .day
+ float: left
+ border-left: 1px solid $grey
+ box-sizing: border-box
+ padding-left: 5px
+ padding-top: 3px
+ position: relative
+ height: 100%
+ .name, .number
+ position: absolute
+ left: 10px
+ right: 10px
+ top: 50%
+ transform: translateY(-50%)
+ margin-top: 10px
+ .name
+ font-weight: bold
+ font-size: 0.8em
+ margin-top: -10px
+ &:first-child
+ border: none
+ &.weekend
+ background: $lightergrey
+ &.selected, &:hover
+ color: $blue
+ background-color: transparentize($blue, 0.7)
+ &:after
+ content: ""
+ left: -1px
+ right: -1px
+ top: 100%
+ height: 10000px
+ background-color: transparentize($blue, 0.7)
+ position: absolute
+ z-index: 4
+ &:hover
+ background-color: transparentize(white, 0.7)
+ &:after
+ background-color: transparentize(white, 0.7)
+
+ .line
+ border-bottom: 1px solid $grey
+ position: relative
+ overflow: hidden
+ box-shadow: 0 -10px 10px rgba(0,0,0,0.5)
+
+ &:last-child
+ border-bottom: none
+
+ .period
+ height: 100%
+ top: 0
+ background: #aedd8a
+ position: absolute
+ box-shadow: 0 0 10px rgba(0,0,0,0.5)
+ z-index: 2
+ .title
+ position: absolute
+ left: 12px
+ top: 50%
+ margin-top: -6px
+ transform: translateY(-50%)
+ background-color: transparentize(white, 0.25)
+ padding: 5px
+ font-size: 0.7em
+ border-radius: 5px
+ transition: margin-left 0.5s
+ max-width: calc(100% - 24px)
+ margin-right: 12px
+ &:after
+ content: ""
+ position: absolute
+ bottom: 1px
+ left: 0
+ right: 0
+ height: 10px
+ background: white
+ opacity: 0.25
+ z-index: 3
+ &.empty
+ z-index: 1
+ background: rgb(244, 67, 67)
+ background: repeating-linear-gradient(-45deg, #f5e1cf,#f5e1cf 12px,#e49393 12px,#e49393 25px)
+ &.accepted
+ background: #f19039
+ background: repeating-linear-gradient(-45deg, #f5e1cf,#f5e1cf 12px,#f19039 12px,#f19039 25px)
+ &:hover
+ z-index: 3
+ &:after
+ opacity: 0.5
+ .title
+ background-color: transparentize(white, 0.1)
+
+ &.sticky
+ .time-travel
+ position: fixed
+ bottom: 0
+ z-index: 15
+ right: 35px
+ box-shadow: 0 0 10px rgba(0,0,0,0.5)
+
+ .overview-table .right
+ .lines
+ margin-top: $left-size
+ .head
+ position: fixed
+ top: 80px
+ z-index: 10
+ background: white
+ height: 50px
+ right: 51px
+ left: 51px + $left-size
+ // overflow-x: hidden
+ &:after, &:before
+ opacity: 1
+ &:after
+ left: 100%
+ right: -1000px
+ .week-span, .week-number
+ display: none
+ .days
+ height: 100%
+ top: 0
+ border-top: 1px solid white
diff --git a/app/assets/stylesheets/components/_referentials.sass b/app/assets/stylesheets/components/_referentials.sass
new file mode 100644
index 000000000..0bbb18f2b
--- /dev/null
+++ b/app/assets/stylesheets/components/_referentials.sass
@@ -0,0 +1,4 @@
+#referential_form
+ .metadatas-errors
+ margin-top: -20px
+ margin-bottom: 20px
diff --git a/app/assets/stylesheets/components/_select2.sass b/app/assets/stylesheets/components/_select2.sass
index 332af16cd..f31387c9f 100644
--- a/app/assets/stylesheets/components/_select2.sass
+++ b/app/assets/stylesheets/components/_select2.sass
@@ -7,6 +7,11 @@
// .select2-results__message, .loading-results
// display: none
+.select2-results__option, .select2-selection__rendered
+ .label
+ font-size: 0.8em
+ margin-right: 0.5em
+
.select2-container, .select2-container--bootstrap
.select2-selection--single .select2-selection__rendered
height: 100%
@@ -74,6 +79,9 @@
.select2-search--inline .select2-search__field
height: 28px
+ .select2-selection__rendered
+ padding-right: 20px
+
.select2-container--bootstrap .select2-selection
border-color: rgba($grey, 0.3)
diff --git a/app/assets/stylesheets/components/_tables.sass b/app/assets/stylesheets/components/_tables.sass
index 178ec2f36..1e02ad586 100644
--- a/app/assets/stylesheets/components/_tables.sass
+++ b/app/assets/stylesheets/components/_tables.sass
@@ -9,7 +9,6 @@
font-weight: 700
border-bottom: 2px solid $darkgrey
vertical-align: middle
-
> a
position: relative
display: block
@@ -211,6 +210,18 @@
top: 50%
margin-top: -8px
+ .zdlp
+ background: url( image-path('map/zdlp.png') ) no-repeat left 50%
+ padding-left: 30px
+
+ .lda
+ background: url( image-path('map/lda.png') ) no-repeat left 50%
+ padding-left: 30px
+
+ .gdl
+ background: url( image-path('map/lda.png') ) no-repeat left 50%
+ padding-left: 30px
+
// select_toolbox
.select_toolbox
@@ -314,6 +325,26 @@
padding: 6px 8px
border-bottom: 2px solid rgba($grey, 0.5)
border-top: 1px solid rgba($grey, 0.5)
+ text-transform: capitalize
+
+ .info-button
+ position: absolute
+ width: 20px
+ height: 20px
+ top: 0
+ right: 0
+ margin: 6px 8px
+ button
+ border: none
+ background: $blue
+ border-radius: 20px
+ width: 100%
+ height: 100%
+ font-size: 12px
+ line-height: 14px
+ color: white
+ outline: none
+
.td
position: relative
padding: 6px 8px
@@ -360,7 +391,7 @@
white-space: nowrap
// border-right: 1px solid rgba($grey, 0.5)
max-width: 100%
- min-width: 280px
+ min-width: 330px
padding-right: 1px
.t2e-item
diff --git a/app/assets/stylesheets/components/_toolbar.sass b/app/assets/stylesheets/components/_toolbar.sass
new file mode 100644
index 000000000..86a32bd82
--- /dev/null
+++ b/app/assets/stylesheets/components/_toolbar.sass
@@ -0,0 +1,49 @@
+#development-toolbar
+ .inner
+ overflow: scroll
+ padding: 10px
+ max-height: 70vh
+ display: flex
+ flex-direction: row
+ .toggles
+ font-size: 0.7em
+ float: right
+ a:first-child
+ padding-right: 3px
+ margin-right: 3px
+ border-right: 1px solid $lightgrey
+
+ .col
+ flex: 1 1
+ padding-right: 10px
+ padding-left: 10px
+ border-right: 1px solid $lightgrey
+ &:last-child
+ padding-right: 0
+ border-right: none
+
+ ul
+ padding: 0
+ li
+ list-style-type: none
+ label
+ padding-left: 5px
+ font-weight: normal
+ & + a
+ float: right
+ h5
+ font-weight: bold
+ &.permissions
+ ul
+ overflow: hidden
+ li
+ float: left
+ width: 33%
+ label
+ font-size: 0.8em
+ max-width: calc(100% - 15px)
+ text-overflow: ellipsis
+ overflow: hidden
+ padding-top: 3px
+ input
+ vertical-align: top
diff --git a/app/assets/stylesheets/modules/_jp_collection.sass b/app/assets/stylesheets/modules/_jp_collection.sass
index f579cf87b..46ea3fb6e 100644
--- a/app/assets/stylesheets/modules/_jp_collection.sass
+++ b/app/assets/stylesheets/modules/_jp_collection.sass
@@ -99,32 +99,204 @@
top: 50%
margin-top: -8px
- // Errors
- .table-2entries .t2e-item-list
- .t2e-item
- position: relative
-
- .th .vj_tt
- display: inline-block
- vertical-align: top
-
- + .vj_tt
- margin-left: 5px
-
- &.has-error
- &:before
- content: ''
- position: absolute
- top: 0
- left: 0
- right: 0
- bottom: 0
- border: 2px solid $red
-
- > .th
- > div:first-child, > div:first-child + div
- color: $red
-
- // Reset default behaviour
- .form-control
- border-color: #ccc
+ .table-2entries
+ .t2e-item-list
+ .td
+ overflow: hidden
+
+ .t2e-item
+ position: relative
+
+ .th .vj_tt
+ display: inline-block
+ vertical-align: top
+
+ + .vj_tt
+ margin-left: 5px
+
+ &.with-costs
+ .td
+ padding: 15px 8px
+
+ .totals
+ color: $blue
+ padding-top: 4px
+ margin-left: -5px
+ margin-right: -5px
+ span
+ white-space: nowrap
+ padding: 0 5px
+ i
+ padding-right: 3px
+
+ $link-size: 10px
+ .link
+ position: absolute
+ left: 50px
+ width: 10px
+ top: -15px
+ bottom: -15px
+ background: $blue
+ z-index: 3
+ opacity: 0.5
+ &:after
+ content: ""
+ width: $link-size
+ height: $link-size
+ position: absolute
+ top: 50%
+ bottom: 50%
+ margin-top: -$link-size/2
+ border-top: $link-size/2 solid transparent
+ border-left: $link-size/2 solid transparent
+ border-right: $link-size/2 solid $blue
+ border-bottom: $link-size/2 solid $blue
+ transform: rotate(135deg)
+ left: 0%
+ opacity: 0
+ transition: left 0.2s, opacity 0.2s
+
+ .headlined .link
+ top: 0
+ bottom: -15px
+
+ &:after
+ top: 75%
+ margin-top: -$link-size/2 - 1px
+
+ .activated .link
+ &:after
+ left: -50%
+ opacity: 1
+
+ & > div
+ position: relative
+
+ .link
+ left: 35px
+
+ .has_radio
+ margin-right: 150px
+
+ .costs
+ background: $blue
+ opacity: 0.5
+ padding: 5px
+ color: white
+ position: absolute
+ cursor: not-allowed
+ left: 75px
+ top: -1px
+ transform: translateY(-50%)
+ font-size: 0.75em
+ transition: background 0.1s
+ border: 1px solid white
+
+ &:hover
+ opacity: 1
+ &:after
+ opacity: 1
+
+ &:after
+ opacity: 0.5
+ content: ""
+ height: 2px
+ position: absolute
+ left: -23px
+ background: $blue
+ right: 100%
+ top: 50%
+ transition: background 0.1s
+
+ p
+ display: block
+ border: none
+ margin-bottom: 0
+ i
+ margin-right: 3px
+ width: 12px
+ & + p
+ position: relative
+ z-index: 2
+ padding-right: 0
+ margin: 0
+ border-right: none
+
+ input
+ display: inline-block
+ width: 50px
+ border: none
+ margin-right: 5px
+ color: black
+
+ .edit-mode
+ .costs
+ cursor: pointer
+ p
+ margin-bottom: 5px
+ & + p
+ margin-bottom: 0
+
+ opacity: 1
+ &:after
+ opacity: 1
+
+ .link
+ opacity: 1
+
+ .with-headline + .costs
+ top: 25%
+
+ .deactivated .costs
+ display: none
+
+ &.has-error
+ &:before
+ content: ''
+ position: absolute
+ top: 0
+ left: 0
+ right: 0
+ bottom: 0
+ border: 2px solid $red
+
+ > .th
+ > div:first-child, > div:first-child + div
+ color: $red
+
+ // Reset default behaviour
+ .form-control
+ border-color: #ccc
+
+ .t2e-head
+ .td.with-costs
+ & > div
+ &:not(.headlined)
+ height: calc(100% + 6px)
+ & > span
+ &:after
+ top: -15px
+ bottom: -9px
+
+ div.headlined
+ &:before
+ margin-bottom: 0
+ & > span
+ height: calc(100% - (1.4em + 15px))
+ &:after
+ top: calc((1.4em + 30px) * -1)
+ bottom: 0
+
+ .td.with-costs, .with-costs .td
+ padding-top: 15px
+ padding-bottom: 15px
+
+ & > div
+ height: calc(100% + 15px)
+ &.headlined
+ &:before
+ padding-top: 15px
+ padding-bottom: 15px
+ height: calc(1.4em + 30px)
+ margin-top: -15px
+ margin-bottom: 15px
diff --git a/app/assets/stylesheets/modules/_timetables.sass b/app/assets/stylesheets/modules/_timetables.sass
index b06972ef9..8999456ec 100644
--- a/app/assets/stylesheets/modules/_timetables.sass
+++ b/app/assets/stylesheets/modules/_timetables.sass
@@ -30,7 +30,7 @@
.t2e-item
.th
- padding: 6px 0 0 0
+ padding: 4px 0 0 0
border-color: $darkgrey
border-top-width: 2px
diff --git a/app/assets/stylesheets/modules/_vj_collection.sass b/app/assets/stylesheets/modules/_vj_collection.sass
index 56769e52b..d99c67bd7 100644
--- a/app/assets/stylesheets/modules/_vj_collection.sass
+++ b/app/assets/stylesheets/modules/_vj_collection.sass
@@ -9,6 +9,9 @@
position: relative
padding-left: 25px
+ .fa
+ margin-left: 5px
+
> .headlined
&:before
margin-left: -25px
@@ -113,6 +116,9 @@
margin-left: 5px
&.has-error
+ .errors
+ color: $red
+ font-size: 0.8em
&:before
content: ''
position: absolute
diff --git a/app/assets/stylesheets/modules/import_messages.sass b/app/assets/stylesheets/modules/import_messages.sass
index e5666cbcd..cde903b00 100644
--- a/app/assets/stylesheets/modules/import_messages.sass
+++ b/app/assets/stylesheets/modules/import_messages.sass
@@ -2,4 +2,7 @@
.status_icon
padding-right: 20px
h1
- padding-bottom: 20px
+ padding-bottom: 20px
+
+ul.list-unstyled
+ padding-bottom: 20px
diff --git a/app/assets/stylesheets/typography/_sboiv.sass b/app/assets/stylesheets/typography/_sboiv.sass
index f694306c4..f0943f843 100644
--- a/app/assets/stylesheets/typography/_sboiv.sass
+++ b/app/assets/stylesheets/typography/_sboiv.sass
@@ -52,6 +52,8 @@
&.sb-5x
font-size: 5em
+ &.sb-strong
+ font-weight: bold
.sb-ZDLR:before
content: '\e904'
@@ -89,7 +91,7 @@
.sb-OAS:before
content: '\e90f'
-.sb-calendar:before
+.sb-calendar:before, .sb-purchase_window:before
content: '\e910'
.sb-journey_pattern:before
diff --git a/app/controllers/api_keys_controller.rb b/app/controllers/api_keys_controller.rb
index 9706c5961..a03a67481 100644
--- a/app/controllers/api_keys_controller.rb
+++ b/app/controllers/api_keys_controller.rb
@@ -31,11 +31,4 @@ class ApiKeysController < ChouetteController
def api_key_params
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 97f5548ae..8bd3da2f9 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,6 +1,7 @@
class ApplicationController < ActionController::Base
include PaperTrailSupport
include Pundit
+ include FeatureChecker
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
@@ -40,12 +41,30 @@ class ApplicationController < ActionController::Base
end
helper_method :current_offer_workbench
+ def current_workgroup
+ current_offer_workbench.workgroup
+ end
+ helper_method :current_workgroup
+
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 collection_name
+ self.class.name.split("::").last.gsub('Controller', '').underscore
+ end
+
+ def decorated_collection
+ if instance_variable_defined?("@#{collection_name}")
+ instance_variable_get("@#{collection_name}")
+ else
+ nil
+ end
+ end
+ helper_method :decorated_collection
+
def begin_of_association_chain
current_organisation
end
diff --git a/app/controllers/autocomplete_purchase_windows_controller.rb b/app/controllers/autocomplete_purchase_windows_controller.rb
new file mode 100644
index 000000000..70dc5a346
--- /dev/null
+++ b/app/controllers/autocomplete_purchase_windows_controller.rb
@@ -0,0 +1,12 @@
+class AutocompletePurchaseWindowsController < ChouetteController
+ respond_to :json, :only => [:index]
+
+ requires_feature :purchase_windows
+
+ include ReferentialSupport
+
+ protected
+ def collection
+ @purchase_windows = referential.purchase_windows.search(params[:q]).result.paginate(page: params[:page])
+ end
+end
diff --git a/app/controllers/autocomplete_stop_areas_controller.rb b/app/controllers/autocomplete_stop_areas_controller.rb
index 233012028..79154a6e0 100644
--- a/app/controllers/autocomplete_stop_areas_controller.rb
+++ b/app/controllers/autocomplete_stop_areas_controller.rb
@@ -17,13 +17,20 @@ class AutocompleteStopAreasController < ChouetteController
scope = scope.possible_parents if relation_parent?
scope = scope.possible_parents if relation_children?
end
+ if search_scope.present?
+ scope = StopAreaPolicy::Scope.new(current_user, scope).search_scope(search_scope)
+ end
args = [].tap{|arg| 4.times{arg << "%#{params[:q]}%"}}
- @stop_areas = scope.where("name ILIKE ? OR city_name ILIKE ? OR registration_number ILIKE ? OR objectid ILIKE ?", *args).limit(50)
+ @stop_areas = scope.where("unaccent(stop_areas.name) ILIKE unaccent(?) OR unaccent(stop_areas.city_name) ILIKE unaccent(?) OR stop_areas.registration_number ILIKE ? OR stop_areas.objectid ILIKE ?", *args).limit(50)
@stop_areas
end
def target_type?
- params.has_key?( :target_type)
+ params.has_key?(:target_type)
+ end
+
+ def search_scope
+ params[:scope]
end
def relation_parent?
diff --git a/app/controllers/calendars_controller.rb b/app/controllers/calendars_controller.rb
index 2ed10a111..75d4cbd09 100644
--- a/app/controllers/calendars_controller.rb
+++ b/app/controllers/calendars_controller.rb
@@ -1,25 +1,69 @@
class CalendarsController < ChouetteController
include PolicyChecker
+ include TimeTablesHelper
+
defaults resource_class: Calendar
before_action :ransack_contains_date, only: [:index]
respond_to :html
+ respond_to :json, only: :show
respond_to :js, only: :index
+ belongs_to :workgroup
+
def index
index! do
- @calendars = ModelDecorator.decorate(@calendars, with: CalendarDecorator)
+ @calendars = decorate_calendars(@calendars)
end
end
def show
show! do
- @calendar = @calendar.decorate
+ @year = params[:year] ? params[:year].to_i : Date.today.cwyear
+ @calendar = @calendar.decorate(context: {
+ workgroup: workgroup
+ })
+ end
+ end
+
+ def month
+ @date = params['date'] ? Date.parse(params['date']) : Date.today
+ @calendar = resource
+ end
+
+ def create
+ create! do
+ if @calendar.valid? && has_feature?('application_days_on_calendars')
+ redirect_to([:edit, @calendar])
+ return
+ end
+ end
+ end
+
+ def update
+ if params[:calendar]
+ super
+ else
+ state = JSON.parse request.raw_post
+ resource.state_update state
+ respond_to do |format|
+ format.json { render json: state, status: state['errors'] ? :unprocessable_entity : :ok }
+ end
end
end
private
+
+ def decorate_calendars(calendars)
+ CalendarDecorator.decorate(
+ calendars,
+ context: {
+ workgroup: workgroup
+ }
+ )
+ end
+
def calendar_params
- permitted_params = [:id, :name, :short_name, periods_attributes: [:id, :begin, :end, :_destroy], date_values_attributes: [:id, :value, :_destroy]]
+ permitted_params = [:id, :name, :short_name, :shared, periods_attributes: [:id, :begin, :end, :_destroy], date_values_attributes: [:id, :value, :_destroy]]
permitted_params << :shared if policy(Calendar).share?
params.require(:calendar).permit(*permitted_params)
end
@@ -33,25 +77,30 @@ class CalendarsController < ChouetteController
end
protected
+
+ alias_method :workgroup, :parent
+ helper_method :workgroup
+
def resource
- @calendar = Calendar.where('organisation_id = ? OR shared = true', current_organisation.id).find_by_id(params[:id])
+ @calendar ||= workgroup.calendars.where('(organisation_id = ? OR shared = ?)', current_organisation.id, true).find_by_id(params[:id])
end
def build_resource
super.tap do |calendar|
+ calendar.workgroup = workgroup
calendar.organisation = current_organisation
end
end
def collection
- return @calendars if @calendars
- scope = Calendar.where('organisation_id = ? OR shared = ?', current_organisation.id, true)
- scope = shared_scope(scope)
- @q = scope.ransack(params[:q])
-
- calendars = @q.result
- calendars = calendars.order(sort_column + ' ' + sort_direction) if sort_column && sort_direction
- @calendars = calendars.paginate(page: params[:page])
+ @calendars ||= begin
+ scope = workgroup.calendars.where('(organisation_id = ? OR shared = ?)', current_organisation.id, true)
+ scope = shared_scope(scope)
+ @q = scope.ransack(params[:q])
+ calendars = @q.result
+ calendars = calendars.order(sort_column + ' ' + sort_direction) if sort_column && sort_direction
+ calendars = calendars.paginate(page: params[:page])
+ end
end
def ransack_contains_date
@@ -76,4 +125,4 @@ class CalendarsController < ChouetteController
scope
end
-end
+end \ No newline at end of file
diff --git a/app/controllers/companies_controller.rb b/app/controllers/companies_controller.rb
index 931d846c5..4afd12be1 100644
--- a/app/controllers/companies_controller.rb
+++ b/app/controllers/companies_controller.rb
@@ -47,6 +47,9 @@ class CompaniesController < ChouetteController
end
end
+ def resource
+ super.decorate(context: { referential: line_referential })
+ end
def resource_url(company = nil)
line_referential_company_path(line_referential, company || resource)
@@ -61,6 +64,10 @@ class CompaniesController < ChouetteController
alias_method :current_referential, :line_referential
helper_method :current_referential
+ def begin_of_association_chain
+ current_organisation
+ end
+
def company_params
params.require(:company).permit( :objectid, :object_version, :name, :short_name, :organizational_unit, :operating_department_name, :code, :phone, :fax, :email, :registration_number, :url, :time_zone )
end
@@ -75,9 +82,8 @@ class CompaniesController < ChouetteController
end
def decorate_companies(companies)
- ModelDecorator.decorate(
+ CompanyDecorator.decorate(
companies,
- with: CompanyDecorator,
context: {
referential: line_referential
}
diff --git a/app/controllers/compliance_check_messages_controller.rb b/app/controllers/compliance_check_messages_controller.rb
new file mode 100644
index 000000000..7c416584e
--- /dev/null
+++ b/app/controllers/compliance_check_messages_controller.rb
@@ -0,0 +1,34 @@
+class ComplianceCheckMessagesController < ChouetteController
+ defaults resource_class: ComplianceCheckMessage, collection_name: 'compliance_check_messages', instance_name: 'compliance_check_message'
+ respond_to :csv
+ belongs_to :compliance_check_set, :parent_class => ComplianceCheckSet
+
+
+ def index
+ index! do |format|
+ format.csv {
+ send_data ComplianceCheckMessageExport.new(compliance_check_messages: collection).to_csv(:col_sep => "\;", :quote_char=>'"', force_quotes: true, server_url: request.base_url) , :filename => "compliance_check_set_errors_#{line_code}_#{Time.now.to_i}.csv"
+ }
+ end
+ end
+
+ protected
+ def collection
+ parent.compliance_check_messages.where(compliance_check_resource_id: params[:compliance_check_resource_id])
+ end
+
+ def parent
+ @compliance_check_set ||= ComplianceCheckSet.find(params[:compliance_check_set_id])
+ end
+
+ def compliance_check_resource
+ ComplianceCheckResource.find(params[:compliance_check_resource_id])
+ end
+
+ private
+
+ def line_code
+ Chouette::Line.find_by_objectid("#{compliance_check_resource.reference}").get_objectid.local_id
+ end
+
+end
diff --git a/app/controllers/compliance_check_sets_controller.rb b/app/controllers/compliance_check_sets_controller.rb
index 600c69126..271598428 100644
--- a/app/controllers/compliance_check_sets_controller.rb
+++ b/app/controllers/compliance_check_sets_controller.rb
@@ -11,9 +11,8 @@ class ComplianceCheckSetsController < ChouetteController
scope = self.ransack_period_range(scope: @compliance_check_sets, error_message: t('compliance_check_sets.filters.error_period_filter'), query: :where_created_at_between)
@q_for_form = scope.ransack(params[:q])
format.html {
- @compliance_check_sets = ModelDecorator.decorate(
- @q_for_form.result.order(created_at: :desc),
- with: ComplianceCheckSetDecorator
+ @compliance_check_sets = ComplianceCheckSetDecorator.decorate(
+ @q_for_form.result.order(created_at: :desc)
)
}
end
@@ -21,9 +20,7 @@ class ComplianceCheckSetsController < ChouetteController
def show
show! do
- @compliance_check_set = @compliance_check_set.decorate(context: {
- compliance_check_set: @compliance_check_set
- })
+ @compliance_check_set = @compliance_check_set.decorate
end
end
@@ -43,18 +40,9 @@ class ComplianceCheckSetsController < ChouetteController
def executed_for_html
@q_checks_form = @compliance_check_set.compliance_checks.ransack(params[:q])
@compliance_check_set = @compliance_check_set.decorate
- compliance_checks =
- decorate_compliance_checks( @q_checks_form.result)
- .group_by(&:compliance_check_block)
+ compliance_checks = @q_checks_form.result
+ .group_by(&:compliance_check_block)
@direct_compliance_checks = compliance_checks.delete nil
@blocks_to_compliance_checks_map = compliance_checks
end
-
- # Decoration
- # ----------
- def decorate_compliance_checks(compliance_checks)
- ModelDecorator.decorate(
- compliance_checks,
- with: ComplianceCheckDecorator)
- end
end
diff --git a/app/controllers/compliance_control_sets_controller.rb b/app/controllers/compliance_control_sets_controller.rb
index 2d3d03ad0..8f9251155 100644
--- a/app/controllers/compliance_control_sets_controller.rb
+++ b/app/controllers/compliance_control_sets_controller.rb
@@ -7,10 +7,8 @@ class ComplianceControlSetsController < ChouetteController
def index
index! do |format|
- scope = self.ransack_period_range(scope: @compliance_control_sets, error_message: t('imports.filters.error_period_filter'), query: :where_updated_at_between)
- @q_for_form = scope.ransack(params[:q])
format.html {
- @compliance_control_sets = decorate_compliance_control_sets(@q_for_form.result.paginate(page: params[:page], per_page: 30))
+ @compliance_control_sets = decorate_compliance_control_sets(@compliance_control_sets)
}
end
end
@@ -37,18 +35,20 @@ class ComplianceControlSetsController < ChouetteController
private
+ def collection
+ scope = self.ransack_period_range(scope: ComplianceControlSet.all, error_message: t('imports.filters.error_period_filter'), query: :where_updated_at_between)
+ @q_for_form = scope.ransack(params[:q])
+ compliance_control_sets = @q_for_form.result
+ compliance_control_sets = joins_with_associated_objects(compliance_control_sets).order(sort_column + ' ' + sort_direction) if sort_column && sort_direction
+ @compliance_control_sets = compliance_control_sets.paginate(page: params[:page], per_page: 30)
+ end
+
def decorate_compliance_control_sets(compliance_control_sets)
- ModelDecorator.decorate(
- compliance_control_sets,
- with: ComplianceControlSetDecorator
- )
+ ComplianceControlSetDecorator.decorate(compliance_control_sets)
end
def decorate_compliance_controls(compliance_controls)
- ModelDecorator.decorate(
- compliance_controls,
- with: ComplianceControlDecorator,
- )
+ ComplianceControlDecorator.decorate(compliance_controls)
end
def compliance_control_set_params
@@ -64,4 +64,32 @@ class ComplianceControlSetsController < ChouetteController
@direct_compliance_controls = compliance_controls.delete nil
@blocks_to_compliance_controls_map = compliance_controls
end
+
+ def sort_column
+ case params[:sort]
+ when 'name' then 'lower(compliance_control_sets.name)'
+ when 'owner_jdc' then 'lower(organisations.name)'
+ when 'control_numbers' then 'COUNT(compliance_controls.id)'
+ else
+ ComplianceControlSet.column_names.include?(params[:sort]) ? params[:sort] : 'lower(compliance_control_sets.name)'
+ end
+ end
+
+ def joins_with_associated_objects(collection)
+
+ # dont know if this is the right way to do it but since we need to join table deoending of the params
+ # it was to avoid loading associated objects if we don't need them
+ case params[:sort]
+ when 'owner_jdc'
+ collection.joins("LEFT JOIN organisations ON compliance_control_sets.organisation_id = organisations.id")
+ when 'control_numbers'
+ collection.joins("LEFT JOIN compliance_controls ON compliance_controls.compliance_control_set_id = compliance_control_sets.id").group(:id)
+ else
+ collection
+ end
+ end
+
+ def sort_direction
+ %w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
+ end
end
diff --git a/app/controllers/compliance_controls_controller.rb b/app/controllers/compliance_controls_controller.rb
index dfbecaa71..73dc18f59 100644
--- a/app/controllers/compliance_controls_controller.rb
+++ b/app/controllers/compliance_controls_controller.rb
@@ -8,6 +8,12 @@ class ComplianceControlsController < ChouetteController
@sti_subclasses = ComplianceControl.subclasses
end
+ def show
+ show! do
+ @compliance_control = @compliance_control.decorate
+ end
+ end
+
def new
if params[:sti_class].blank?
flash[:notice] = I18n.t("compliance_controls.errors.mandatory_control_type")
diff --git a/app/controllers/concerns/activatable.rb b/app/controllers/concerns/activatable.rb
new file mode 100644
index 000000000..1a34551a9
--- /dev/null
+++ b/app/controllers/concerns/activatable.rb
@@ -0,0 +1,11 @@
+module Activatable
+ extend ActiveSupport::Concern
+
+ %w(activate deactivate).each do |action|
+ define_method action do
+ authorize resource, "#{action}?"
+ resource.send "#{action}!"
+ redirect_to request.referer || [current_referential, resource]
+ end
+ end
+end
diff --git a/app/controllers/concerns/feature_checker.rb b/app/controllers/concerns/feature_checker.rb
new file mode 100644
index 000000000..9ca5ed0a7
--- /dev/null
+++ b/app/controllers/concerns/feature_checker.rb
@@ -0,0 +1,42 @@
+# Check availability of optional features
+#
+# In your controller, use :
+#
+# requires_feature :test
+# requires_feature :test, only: [:show]
+#
+# In your view, use :
+#
+# has_feature? :test
+#
+module FeatureChecker
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ def requires_feature(feature, options = {})
+ before_action options do
+ check_feature! feature
+ end
+ end
+ end
+
+ included do
+ helper_method :has_feature?
+ end
+
+ protected
+
+ def has_feature?(*features)
+ features.all? do |feature|
+ current_organisation.has_feature? feature
+ end
+ end
+
+ def check_feature!(*features)
+ unless has_feature?(*features)
+ raise NotAuthorizedError, "Feature not autorized"
+ end
+ end
+
+ class NotAuthorizedError < StandardError; end
+end
diff --git a/app/controllers/concerns/ransack_date_filter.rb b/app/controllers/concerns/ransack_date_filter.rb
index 0fbde91d3..055c01130 100644
--- a/app/controllers/concerns/ransack_date_filter.rb
+++ b/app/controllers/concerns/ransack_date_filter.rb
@@ -3,7 +3,15 @@ module RansackDateFilter
included do
- def set_date_time_params(param_name, klass)
+ def begin_range_var prefix
+ "@#{[prefix, "begin_range"].compact.join('_')}"
+ end
+
+ def end_range_var prefix
+ "@#{[prefix, "end_range"].compact.join('_')}"
+ end
+
+ def set_date_time_params(param_name, klass, prefix: nil)
start_date = []
end_date = []
@@ -16,26 +24,28 @@ module RansackDateFilter
params[:q].delete([param_name])
if klass == DateTime
- @begin_range = klass.new(*start_date,0,0,0) rescue nil
- @end_range = klass.new(*end_date,23,59,59) rescue nil
+ instance_variable_set begin_range_var(prefix), klass.new(*start_date,0,0,0) rescue nil
+ instance_variable_set end_range_var(prefix), klass.new(*end_date,23,59,59) rescue nil
else
- @begin_range = klass.new(*start_date) rescue nil
- @end_range = klass.new(*end_date) rescue nil
+ instance_variable_set begin_range_var(prefix), klass.new(*start_date) rescue nil
+ instance_variable_set end_range_var(prefix), klass.new(*end_date) rescue nil
end
end
end
# Fake ransack filter
def ransack_period_range **options
- return options[:scope] unless !!@begin_range && !!@end_range
+ prefix = options[:prefix]
+ return options[:scope] unless !!instance_variable_get(begin_range_var(prefix)) && !!instance_variable_get(end_range_var(prefix))
- if @begin_range > @end_range
+ scope = options[:scope]
+ if instance_variable_get(begin_range_var(prefix)) > instance_variable_get(end_range_var(prefix))
flash.now[:error] = options[:error_message]
else
- scope = options[:scope].send options[:query], @begin_range..@end_range
+ scope = scope.send options[:query], instance_variable_get(begin_range_var(prefix))..instance_variable_get(end_range_var(prefix))
end
scope
end
end
-end \ No newline at end of file
+end
diff --git a/app/controllers/development_toolbar_controller.rb b/app/controllers/development_toolbar_controller.rb
new file mode 100644
index 000000000..20349f7b8
--- /dev/null
+++ b/app/controllers/development_toolbar_controller.rb
@@ -0,0 +1,11 @@
+class DevelopmentToolbarController < ApplicationController
+ def update_settings
+ return unless Rails.application.config.development_toolbar.present?
+ organisation = current_user.organisation
+ organisation.features = params[:features].keys.select{|k| params[:features][k] == "true"}
+ organisation.save
+ current_user.permissions = params[:permissions].keys.select{|k| params[:permissions][k] == "true"}
+ current_user.save
+ redirect_to request.referrer || "/"
+ end
+end
diff --git a/app/controllers/group_of_lines_controller.rb b/app/controllers/group_of_lines_controller.rb
index 5762108dc..46d9d077f 100644
--- a/app/controllers/group_of_lines_controller.rb
+++ b/app/controllers/group_of_lines_controller.rb
@@ -42,7 +42,6 @@ class GroupOfLinesController < ChouetteController
end
end
-
protected
def filtered_group_of_lines_maps
@@ -70,6 +69,10 @@ class GroupOfLinesController < ChouetteController
alias_method :line_referential, :parent
+ def begin_of_association_chain
+ current_organisation
+ end
+
private
def group_of_line_params
diff --git a/app/controllers/import_messages_controller.rb b/app/controllers/import_messages_controller.rb
index 6546b25f8..286bb0ce8 100644
--- a/app/controllers/import_messages_controller.rb
+++ b/app/controllers/import_messages_controller.rb
@@ -9,7 +9,7 @@ class ImportMessagesController < ChouetteController
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"
+ send_data ImportMessageExport.new(:import_messages => @import_messages).to_csv(:col_sep => "\;", :quote_char=>'"', force_quotes: true) , :filename => "import_errors_#{@import_resource.name.gsub('.xml', '')}_#{Time.now.to_i}.csv"
}
end
end
diff --git a/app/controllers/import_resources_controller.rb b/app/controllers/import_resources_controller.rb
index c83721310..ea78394a1 100644
--- a/app/controllers/import_resources_controller.rb
+++ b/app/controllers/import_resources_controller.rb
@@ -27,12 +27,6 @@ class ImportResourcesController < ChouetteController
private
def decorate_import_resources(import_resources)
- ImportResourcesDecorator.decorate(
- import_resources,
- with: ImportResourceDecorator,
- context: {
- import: @import
- }
- )
+ ImportResourcesDecorator.decorate(import_resources)
end
end
diff --git a/app/controllers/imports_controller.rb b/app/controllers/imports_controller.rb
index 46d34efda..7a999d657 100644
--- a/app/controllers/imports_controller.rb
+++ b/app/controllers/imports_controller.rb
@@ -84,9 +84,8 @@ class ImportsController < ChouetteController
end
def decorate_imports(imports)
- ModelDecorator.decorate(
+ ImportDecorator.decorate(
imports,
- with: ImportDecorator,
context: {
workbench: @workbench
}
diff --git a/app/controllers/journey_patterns_collections_controller.rb b/app/controllers/journey_patterns_collections_controller.rb
index 736fb1441..da567779e 100644
--- a/app/controllers/journey_patterns_collections_controller.rb
+++ b/app/controllers/journey_patterns_collections_controller.rb
@@ -17,38 +17,53 @@ class JourneyPatternsCollectionsController < ChouetteController
alias_method :vehicle_journey, :resource
def show
- @q = route.journey_patterns.search(params[:q]).result(distinct: true).includes(:stop_points)
+ @q = route.journey_patterns
+ if params[:q].present?
+ ids = @q.search(params[:q]).result(distinct: true).pluck(:id)
+ @q = @q.where(id: ids)
+ end
+ @q = @q.includes(:stop_points)
@ppage = 10
@journey_patterns ||= @q.paginate(page: params[:page], per_page: @ppage).order(:name)
-
- @stop_points_list = []
- route.stop_points.each do |sp|
- @stop_points_list << {
- :id => sp.stop_area.id,
- :route_id => sp.try(:route_id),
- :object_id => sp.try(:objectid),
- :position => sp.try(:position),
- :for_boarding => sp.try(:for_boarding),
- :for_alighting => sp.try(:for_alighting),
- :name => sp.stop_area.try(:name),
- :zip_code => sp.stop_area.try(:zip_code),
- :city_name => sp.stop_area.try(:city_name),
- :comment => sp.stop_area.try(:comment),
- :area_type => sp.stop_area.try(:area_type),
- :registration_number => sp.stop_area.try(:registration_number),
- :nearest_topic_name => sp.stop_area.try(:nearest_topic_name),
- :fare_code => sp.stop_area.try(:fare_code),
- :longitude => sp.stop_area.try(:longitude),
- :latitude => sp.stop_area.try(:latitude),
- :long_lat_type => sp.stop_area.try(:long_lat_type),
- :country_code => sp.stop_area.try(:country_code),
- :street_name => sp.stop_area.try(:street_name)
- }
+ respond_to do |format|
+ format.json do
+ @journey_patterns = @journey_patterns.includes(stop_points: {stop_area: :stop_area_referential})
+ end
+ format.html do
+ @stop_points_list = []
+ route.stop_points.includes(:stop_area).each do |sp|
+ @stop_points_list << {
+ :id => sp.stop_area.id,
+ :route_id => sp.try(:route_id),
+ :object_id => sp.try(:objectid),
+ :stop_area_object_id => sp.stop_area.try(:objectid),
+ :position => sp.try(:position),
+ :for_boarding => sp.try(:for_boarding),
+ :for_alighting => sp.try(:for_alighting),
+ :name => sp.stop_area.try(:name),
+ :zip_code => sp.stop_area.try(:zip_code),
+ :city_name => sp.stop_area.try(:city_name),
+ :country_name => sp.stop_area.try(:country_name),
+ :time_zone_formatted_offset => sp.stop_area.try(:time_zone_formatted_offset),
+ :comment => sp.stop_area.try(:comment),
+ :area_type => sp.stop_area.try(:area_type),
+ :registration_number => sp.stop_area.try(:registration_number),
+ :nearest_topic_name => sp.stop_area.try(:nearest_topic_name),
+ :fare_code => sp.stop_area.try(:fare_code),
+ :longitude => sp.stop_area.try(:longitude),
+ :latitude => sp.stop_area.try(:latitude),
+ :long_lat_type => sp.stop_area.try(:long_lat_type),
+ :country_code => sp.stop_area.try(:country_code),
+ :street_name => sp.stop_area.try(:street_name)
+ }
+ end
+ @stop_points_list = @stop_points_list.sort_by {|a| a[:position] }
+ end
end
- @stop_points_list = @stop_points_list.sort_by {|a| a[:position] }
end
def user_permissions
+ @features = Hash[*current_organisation.features.map{|f| [f, true]}.flatten].to_json
policy = policy(:journey_pattern)
@perms =
%w{create destroy update}.inject({}) do | permissions, action |
diff --git a/app/controllers/line_referentials_controller.rb b/app/controllers/line_referentials_controller.rb
index 39c2cdb89..03dab3f8f 100644
--- a/app/controllers/line_referentials_controller.rb
+++ b/app/controllers/line_referentials_controller.rb
@@ -3,6 +3,7 @@ class LineReferentialsController < ChouetteController
defaults :resource_class => LineReferential
def sync
+ authorize resource, :synchronize?
@sync = resource.line_referential_syncs.build
if @sync.save
flash[:notice] = t('notice.line_referential_sync.created')
diff --git a/app/controllers/lines_controller.rb b/app/controllers/lines_controller.rb
index 571c73f4a..27a9bf9be 100644
--- a/app/controllers/lines_controller.rb
+++ b/app/controllers/lines_controller.rb
@@ -1,6 +1,8 @@
class LinesController < ChouetteController
include ApplicationHelper
+ include Activatable
include PolicyChecker
+
defaults :resource_class => Chouette::Line
respond_to :html
respond_to :xml
@@ -13,9 +15,8 @@ class LinesController < ChouetteController
def index
@hide_group_of_line = line_referential.group_of_lines.empty?
index! do |format|
- @lines = ModelDecorator.decorate(
+ @lines = LineDecorator.decorate(
@lines,
- with: LineDecorator,
context: {
line_referential: @line_referential,
current_organisation: current_organisation
@@ -67,7 +68,6 @@ class LinesController < ChouetteController
respond_to do |format|
format.json { render :json => filtered_lines_maps}
end
-
end
protected
@@ -112,6 +112,10 @@ class LinesController < ChouetteController
alias_method :current_referential, :line_referential
helper_method :current_referential
+ def begin_of_association_chain
+ current_organisation
+ end
+
def line_params
params.require(:line).permit(
:transport_mode,
diff --git a/app/controllers/merges_controller.rb b/app/controllers/merges_controller.rb
new file mode 100644
index 000000000..1ce64ed58
--- /dev/null
+++ b/app/controllers/merges_controller.rb
@@ -0,0 +1,40 @@
+class MergesController < ChouetteController
+ # include PolicyChecker
+
+ defaults resource_class: Merge
+ belongs_to :workbench
+
+ respond_to :html
+
+ before_action :set_mergeable_controllers, only: [:new]
+
+ private
+
+ def set_mergeable_controllers
+ @mergeable_referentials ||= parent.referentials.mergeable
+ Rails.logger.debug "Mergeables: #{@mergeable_referentials.inspect}"
+ end
+
+ def build_resource
+ super.tap do |merge|
+ merge.creator = current_user.name
+ end
+ end
+
+ # def build_resource
+ # @import ||= WorkbenchImport.new(*resource_params) do |import|
+ # import.workbench = parent
+ # import.creator = current_user.name
+ # end
+ # end
+
+ def merge_params
+ params.require(:merge).permit(
+ referentials: []
+ # :name,
+ # :file,
+ # :type,
+ # :referential_id
+ )
+ end
+end
diff --git a/app/controllers/networks_controller.rb b/app/controllers/networks_controller.rb
index 494d1e69f..1c69b1240 100644
--- a/app/controllers/networks_controller.rb
+++ b/app/controllers/networks_controller.rb
@@ -71,6 +71,10 @@ class NetworksController < ChouetteController
alias_method :current_referential, :line_referential
helper_method :current_referential
+ def begin_of_association_chain
+ current_organisation
+ end
+
def network_params
params.require(:network).permit(:objectid, :object_version, :version_date, :description, :name, :registration_number, :source_name, :source_type_name, :source_identifier, :comment )
end
@@ -85,9 +89,8 @@ class NetworksController < ChouetteController
end
def decorate_networks(networks)
- ModelDecorator.decorate(
+ NetworkDecorator.decorate(
networks,
- with: NetworkDecorator,
context: {
line_referential: line_referential
}
diff --git a/app/controllers/purchase_windows_controller.rb b/app/controllers/purchase_windows_controller.rb
new file mode 100644
index 000000000..293a7d8e4
--- /dev/null
+++ b/app/controllers/purchase_windows_controller.rb
@@ -0,0 +1,74 @@
+class PurchaseWindowsController < ChouetteController
+ include ReferentialSupport
+ include RansackDateFilter
+ include PolicyChecker
+ before_action :ransack_contains_date, only: [:index]
+ defaults :resource_class => Chouette::PurchaseWindow, collection_name: 'purchase_windows', instance_name: 'purchase_window'
+ belongs_to :referential
+
+ requires_feature :purchase_windows
+
+ def index
+ index! do
+ @purchase_windows = decorate_purchase_windows(@purchase_windows)
+ end
+ end
+
+ def show
+ show! do
+ @purchase_window = @purchase_window.decorate(context: {
+ referential: @referential
+ })
+ end
+ end
+
+ protected
+
+ def create_resource(purchase_window)
+ purchase_window.referential = @referential
+ super
+ end
+
+ private
+
+ def purchase_window_params
+ params.require(:purchase_window).permit(:id, :name, :color, :referential_id, periods_attributes: [:id, :begin, :end, :_destroy])
+ end
+
+ def decorate_purchase_windows(purchase_windows)
+ PurchaseWindowDecorator.decorate(
+ purchase_windows,
+ context: {
+ referential: @referential
+ }
+ )
+ end
+
+ def sort_column
+ Chouette::PurchaseWindow.column_names.include?(params[:sort]) ? params[:sort] : 'name'
+ end
+
+ def sort_direction
+ %w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
+ end
+
+ def collection
+ return @purchase_windows if @purchase_windows
+ @q = Chouette::PurchaseWindow.ransack(params[:q])
+
+ purchase_windows = @q.result
+ purchase_windows = purchase_windows.order(sort_column + ' ' + sort_direction) if sort_column && sort_direction
+ @purchase_windows = purchase_windows.paginate(page: params[:page])
+ end
+
+ def ransack_contains_date
+ date =[]
+ if params[:q] && params[:q]['contains_date(1i)'].present?
+ ['contains_date(1i)', 'contains_date(2i)', 'contains_date(3i)'].each do |key|
+ date << params[:q][key].to_i
+ params[:q].delete(key)
+ end
+ params[:q]['contains_date'] = @date = Date.new(*date) rescue nil
+ end
+ end
+end
diff --git a/app/controllers/referential_companies_controller.rb b/app/controllers/referential_companies_controller.rb
index ca1ff67db..806a70c8f 100644
--- a/app/controllers/referential_companies_controller.rb
+++ b/app/controllers/referential_companies_controller.rb
@@ -35,7 +35,8 @@ class ReferentialCompaniesController < ChouetteController
def collection
scope = referential.line_referential.companies
if params[:line_id]
- scope = referential.line_referential.lines.find(params[:line_id]).companies
+ line_scope = referential.line_referential.lines.find(params[:line_id]).companies
+ scope = line_scope if line_scope.exists?
end
@q = scope.search(params[:q])
@@ -68,10 +69,13 @@ class ReferentialCompaniesController < ChouetteController
%w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
end
+ def collection_name
+ "companies"
+ end
+
def decorate_companies(companies)
- ModelDecorator.decorate(
+ CompanyDecorator.decorate(
companies,
- with: CompanyDecorator,
context: {
referential: referential
}
diff --git a/app/controllers/referential_lines_controller.rb b/app/controllers/referential_lines_controller.rb
index 9e8f5c512..37051faeb 100644
--- a/app/controllers/referential_lines_controller.rb
+++ b/app/controllers/referential_lines_controller.rb
@@ -28,9 +28,8 @@ class ReferentialLinesController < ChouetteController
@routes = @routes.paginate(page: params[:page], per_page: 10)
- @routes = ModelDecorator.decorate(
+ @routes = RouteDecorator.decorate(
@routes,
- with: RouteDecorator,
context: {
referential: referential,
line: @line
diff --git a/app/controllers/referential_networks_controller.rb b/app/controllers/referential_networks_controller.rb
index b2d83f953..fe00a99df 100644
--- a/app/controllers/referential_networks_controller.rb
+++ b/app/controllers/referential_networks_controller.rb
@@ -56,6 +56,10 @@ class ReferentialNetworksController < ChouetteController
end
end
+ def collection_name
+ 'networks'
+ end
+
def resource_url(network = nil)
referential_network_path(referential, network || resource)
end
@@ -78,9 +82,8 @@ class ReferentialNetworksController < ChouetteController
end
def decorate_networks(networks)
- ModelDecorator.decorate(
+ ReferentialNetworkDecorator.decorate(
networks,
- with: ReferentialNetworkDecorator,
context: {
referential: referential
}
diff --git a/app/controllers/referential_vehicle_journeys_controller.rb b/app/controllers/referential_vehicle_journeys_controller.rb
new file mode 100644
index 000000000..2ce28a5cc
--- /dev/null
+++ b/app/controllers/referential_vehicle_journeys_controller.rb
@@ -0,0 +1,30 @@
+#
+# Browse all VehicleJourneys of the Referential
+#
+class ReferentialVehicleJourneysController < ChouetteController
+ include ReferentialSupport
+ include RansackDateFilter
+
+ before_action only: [:index] { set_date_time_params("purchase_window", Date, prefix: :purchase_window) }
+ before_action only: [:index] { set_date_time_params("time_table", Date, prefix: :time_table) }
+
+ defaults :resource_class => Chouette::VehicleJourney, collection_name: :vehicle_journeys
+
+ requires_feature :referential_vehicle_journeys
+
+ private
+
+ def collection
+ @q ||= end_of_association_chain
+ @q = @q.with_stop_area_ids(params[:q][:stop_area_ids]) if params[:q] && params[:q][:stop_area_ids]
+ @q = ransack_period_range(scope: @q, error_message: t('vehicle_journeys.errors.purchase_window'), query: :in_purchase_window, prefix: :purchase_window)
+ @q = ransack_period_range(scope: @q, error_message: t('vehicle_journeys.errors.time_table'), query: :with_matching_timetable, prefix: :time_table)
+ @q = @q.ransack(params[:q])
+ @vehicle_journeys ||= @q.result.order(:published_journey_name).includes(:vehicle_journey_at_stops).paginate page: params[:page], per_page: params[:per_page] || 10
+ @all_companies = Chouette::Company.where("id IN (#{@referential.vehicle_journeys.select(:company_id).to_sql})").distinct
+ @all_stop_areas = Chouette::StopArea.where("id IN (#{@referential.vehicle_journeys.joins(:stop_areas).select("stop_areas.id").to_sql})").distinct
+ stop_area_ids = params[:q].try(:[], :stop_area_ids).try(:select, &:present?)
+ @filters_stop_areas = Chouette::StopArea.find(stop_area_ids) if stop_area_ids.present? && stop_area_ids.size <= 2
+ end
+
+end
diff --git a/app/controllers/referentials_controller.rb b/app/controllers/referentials_controller.rb
index ee1236912..0ed3f75dd 100644
--- a/app/controllers/referentials_controller.rb
+++ b/app/controllers/referentials_controller.rb
@@ -8,16 +8,21 @@ class ReferentialsController < ChouetteController
def new
new! do
- build_referenial
+ build_referential
end
end
def create
- create! do |format|
- build_referenial
-
- if !!@referential.created_from_id
- format.html { redirect_to workbench_path(@referential.workbench) }
+ create! do |success, failure|
+ success.html do
+ if @referential.created_from_id.present?
+ flash[:notice] = t('notice.referentials.duplicate')
+ end
+ redirect_to workbench_path(@referential.workbench)
+ end
+ failure.html do
+ Rails.logger.info "Can't create Referential : #{@referential.errors.inspect}"
+ render :new
end
end
end
@@ -27,9 +32,8 @@ class ReferentialsController < ChouetteController
show! do |format|
@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 = ReferentialLineDecorator.decorate(
@reflines,
- with: ReferentialLineDecorator,
context: {
referential: referential,
current_organisation: current_organisation
@@ -60,8 +64,8 @@ class ReferentialsController < ChouetteController
def validate
ComplianceControlSetCopyWorker.perform_async(params[:compliance_control_set], params[:id])
- flash[:notice] = I18n.t("referentials.operation_in_progress")
- redirect_to(referential_path)
+ flash[:notice] = t('notice.referentials.validate')
+ redirect_to workbench_compliance_check_sets_path(referential.workbench_id)
end
def destroy
@@ -75,6 +79,7 @@ class ReferentialsController < ChouetteController
referential.archive!
redirect_to workbench_path(referential.workbench_id), notice: t('notice.referential.archived')
end
+
def unarchive
if referential.unarchive!
flash[:notice] = t('notice.referential.unarchived')
@@ -92,7 +97,7 @@ class ReferentialsController < ChouetteController
helper_method :current_referential
def resource
- @referential ||= current_organisation.find_referential(params[:id])
+ @referential ||= current_organisation.find_referential(params[:id]).decorate
end
def collection
@@ -132,7 +137,7 @@ class ReferentialsController < ChouetteController
super
end
- def build_referenial
+ def build_referential
if params[:from]
source_referential = Referential.find(params[:from])
@referential = Referential.new_from(source_referential, current_functional_scope)
diff --git a/app/controllers/routes_controller.rb b/app/controllers/routes_controller.rb
index 79f49143a..af5a9a91b 100644
--- a/app/controllers/routes_controller.rb
+++ b/app/controllers/routes_controller.rb
@@ -47,10 +47,7 @@ class RoutesController < ChouetteController
line: @line
})
- @route_sp = ModelDecorator.decorate(
- @route_sp,
- with: StopPointDecorator
- )
+ @route_sp = StopPointDecorator.decorate(@route_sp)
end
end
diff --git a/app/controllers/routing_constraint_zones_controller.rb b/app/controllers/routing_constraint_zones_controller.rb
index a72b288b8..47df211d0 100644
--- a/app/controllers/routing_constraint_zones_controller.rb
+++ b/app/controllers/routing_constraint_zones_controller.rb
@@ -13,9 +13,8 @@ class RoutingConstraintZonesController < ChouetteController
def index
index! do |format|
- @routing_constraint_zones = ModelDecorator.decorate(
+ @routing_constraint_zones = RoutingConstraintZoneDecorator.decorate(
@routing_constraint_zones,
- with: RoutingConstraintZoneDecorator,
context: {
referential: referential,
line: parent
diff --git a/app/controllers/snapshots_controller.rb b/app/controllers/snapshots_controller.rb
new file mode 100644
index 000000000..e453b4965
--- /dev/null
+++ b/app/controllers/snapshots_controller.rb
@@ -0,0 +1,14 @@
+class SnapshotsController < ApplicationController
+ if Rails.env.development? || Rails.env.test?
+ layout :which_layout
+ def show
+ tpl = params[:snap]
+ tpl = tpl.gsub Rails.root.to_s, ''
+ render file: tpl
+ end
+
+ def which_layout
+ "snapshots/#{params[:layout] || "default"}"
+ end
+ end
+end
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
new file mode 100644
index 000000000..e38a92982
--- /dev/null
+++ b/app/controllers/statuses_controller.rb
@@ -0,0 +1,20 @@
+class StatusesController < ChouetteController
+ respond_to :json
+
+ def index
+
+ status = {
+ referentials_blocked: Referential.blocked.count,
+ imports_blocked: Import.blocked.count,
+ compliance_check_sets_blocked: ComplianceCheckSet.blocked.count
+ }
+ status[:status] = global_status status
+ render json: status.to_json
+ end
+
+ private
+
+ def global_status status
+ status.values.all?(&:zero?) ? 'ok' : 'ko'
+ end
+end
diff --git a/app/controllers/stop_area_referentials_controller.rb b/app/controllers/stop_area_referentials_controller.rb
index 85541230d..f2d375e49 100644
--- a/app/controllers/stop_area_referentials_controller.rb
+++ b/app/controllers/stop_area_referentials_controller.rb
@@ -2,6 +2,7 @@ class StopAreaReferentialsController < ChouetteController
defaults :resource_class => StopAreaReferential
def sync
+ authorize resource, :synchronize?
@sync = resource.stop_area_referential_syncs.build
if @sync.save
flash[:notice] = t('notice.stop_area_referential_sync.created')
diff --git a/app/controllers/stop_areas_controller.rb b/app/controllers/stop_areas_controller.rb
index 133518324..41a1a8c6d 100644
--- a/app/controllers/stop_areas_controller.rb
+++ b/app/controllers/stop_areas_controller.rb
@@ -1,5 +1,6 @@
class StopAreasController < ChouetteController
include ApplicationHelper
+ include Activatable
defaults :resource_class => Chouette::StopArea
@@ -13,10 +14,12 @@ class StopAreasController < ChouetteController
respond_to :html, :kml, :xml, :json
respond_to :js, :only => :index
- # def complete
- # @stop_areas = line.stop_areas
- # render :layout => false
- # end
+ def autocomplete
+ scope = stop_area_referential.stop_areas.where(deleted_at: nil)
+ args = [].tap{|arg| 4.times{arg << "%#{params[:q]}%"}}
+ @stop_areas = scope.where("unaccent(name) ILIKE unaccent(?) OR unaccent(city_name) ILIKE unaccent(?) OR registration_number ILIKE ? OR objectid ILIKE ?", *args).limit(50)
+ @stop_areas
+ end
def select_parent
@stop_area = stop_area
@@ -54,10 +57,7 @@ class StopAreasController < ChouetteController
redirect_to params.merge(:page => 1)
end
- @stop_areas = ModelDecorator.decorate(
- @stop_areas,
- with: StopAreaDecorator
- )
+ @stop_areas = StopAreaDecorator.decorate(@stop_areas)
}
end
end
@@ -95,9 +95,8 @@ class StopAreasController < ChouetteController
def edit
authorize stop_area
edit! do
- stop_area.position ||= stop_area.default_position
map.editable = true
- end
+ end
end
def destroy
@@ -107,7 +106,6 @@ class StopAreasController < ChouetteController
def update
authorize stop_area
- stop_area.position ||= stop_area.default_position
map.editable = true
update!
@@ -154,6 +152,10 @@ class StopAreasController < ChouetteController
end
end
+ def begin_of_association_chain
+ current_organisation
+ end
+
private
def sort_column
@@ -171,7 +173,37 @@ class StopAreasController < ChouetteController
helper_method :current_referential
def stop_area_params
- params.require(:stop_area).permit( :routing_stop_ids, :routing_line_ids, :children_ids, :stop_area_type, :parent_id, :objectid, :object_version, :name, :comment, :area_type, :registration_number, :nearest_topic_name, :fare_code, :longitude, :latitude, :long_lat_type, :country_code, :street_name, :zip_code, :city_name, :mobility_restricted_suitability, :stairs_availability, :lift_availability, :int_user_needs, :coordinates, :url, :time_zone )
+ params.require(:stop_area).permit(
+ :area_type,
+ :children_ids,
+ :city_name,
+ :comment,
+ :coordinates,
+ :country_code,
+ :fare_code,
+ :int_user_needs,
+ :latitude,
+ :lift_availability,
+ :long_lat_type,
+ :longitude,
+ :mobility_restricted_suitability,
+ :name,
+ :nearest_topic_name,
+ :object_version,
+ :objectid,
+ :parent_id,
+ :registration_number,
+ :routing_line_ids,
+ :routing_stop_ids,
+ :stairs_availability,
+ :street_name,
+ :time_zone,
+ :url,
+ :waiting_time,
+ :zip_code,
+ :kind,
+ localized_names: Chouette::StopArea::AVAILABLE_LOCALIZATIONS
+ )
end
end
diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb
index a0fa168f0..0dcadad1e 100644
--- a/app/controllers/time_tables_controller.rb
+++ b/app/controllers/time_tables_controller.rb
@@ -36,7 +36,6 @@ class TimeTablesController < ChouetteController
def create
tt_params = time_table_params
if tt_params[:calendar_id] && tt_params[:calendar_id] != ""
- %i(monday tuesday wednesday thursday friday saturday sunday).map { |d| tt_params[d] = true }
calendar = Calendar.find(tt_params[:calendar_id])
tt_params[:calendar_id] = nil if tt_params.has_key?(:dates_attributes) || tt_params.has_key?(:periods_attributes)
end
@@ -45,6 +44,7 @@ class TimeTablesController < ChouetteController
@time_table = created_from ? created_from.duplicate : Chouette::TimeTable.new(tt_params)
if calendar
+ @time_table.int_day_types = calendar.int_day_types
calendar.dates.each_with_index do |date, i|
@time_table.dates << Chouette::TimeTableDate.new(date: date, position: i, in_out: true)
end
@@ -167,9 +167,8 @@ class TimeTablesController < ChouetteController
end
def decorate_time_tables(time_tables)
- ModelDecorator.decorate(
+ TimeTableDecorator.decorate(
time_tables,
- with: TimeTableDecorator,
context: {
referential: @referential
}
diff --git a/app/controllers/vehicle_journeys_controller.rb b/app/controllers/vehicle_journeys_controller.rb
index c941aeae4..e031e4952 100644
--- a/app/controllers/vehicle_journeys_controller.rb
+++ b/app/controllers/vehicle_journeys_controller.rb
@@ -40,43 +40,26 @@ class VehicleJourneysController < ChouetteController
end
def index
- @stop_points_list = []
- route.stop_points.each do |sp|
- @stop_points_list << {
- :id => sp.stop_area.id,
- :route_id => sp.try(:route_id),
- :object_id => sp.try(:objectid),
- :position => sp.try(:position),
- :for_boarding => sp.try(:for_boarding),
- :for_alighting => sp.try(:for_alighting),
- :name => sp.stop_area.try(:name),
- :zip_code => sp.stop_area.try(:zip_code),
- :city_name => sp.stop_area.try(:city_name),
- :comment => sp.stop_area.try(:comment),
- :area_type => sp.stop_area.try(:area_type),
- :registration_number => sp.stop_area.try(:registration_number),
- :nearest_topic_name => sp.stop_area.try(:nearest_topic_name),
- :fare_code => sp.stop_area.try(:fare_code),
- :longitude => sp.stop_area.try(:longitude),
- :latitude => sp.stop_area.try(:latitude),
- :long_lat_type => sp.stop_area.try(:long_lat_type),
- :country_code => sp.stop_area.try(:country_code),
- :street_name => sp.stop_area.try(:street_name)
- }
- end
-
- @transport_mode = route.line['transport_mode']
- @transport_submode = route.line['transport_submode']
-
- if params[:jp]
- @jp_origin = Chouette::JourneyPattern.find_by(objectid: params[:jp])
- @jp_origin_stop_points = @jp_origin.stop_points
- end
-
- index! do
+ index! do |format|
if collection.out_of_bounds?
redirect_to params.merge(:page => 1)
end
+ format.json do
+ @vehicle_journeys = @vehicle_journeys.includes({stop_points: :stop_area})
+ end
+ format.html do
+ load_missions
+ load_custom_fields
+ @stop_points_list = map_stop_points(route.stop_points)
+ @return_stop_points_list = map_stop_points(route.opposite_route&.stop_points) if has_feature?(:vehicle_journeys_return_route)
+ @transport_mode = route.line['transport_mode']
+ @transport_submode = route.line['transport_submode']
+
+ if params[:jp]
+ @jp_origin = Chouette::JourneyPattern.find_by(objectid: params[:jp])
+ @jp_origin_stop_points = @jp_origin.stop_points
+ end
+ end
end
end
@@ -92,13 +75,15 @@ class VehicleJourneysController < ChouetteController
scope = maybe_filter_by_departure_time(scope)
scope = maybe_filter_out_journeys_with_time_tables(scope)
- @q = scope.search filtered_ransack_params
+ @vehicle_journeys ||= begin
+ @q = scope.search filtered_ransack_params
- @ppage = 20
- @vehicle_journeys = @q.result.paginate(:page => params[:page], :per_page => @ppage)
- @footnotes = route.line.footnotes.to_json
- @matrix = resource_class.matrix(@vehicle_journeys)
- @vehicle_journeys
+ @ppage = 20
+ vehicle_journeys = @q.result.paginate(:page => params[:page], :per_page => @ppage)
+ @footnotes = route.line.footnotes.to_json
+ @matrix = resource_class.matrix(vehicle_journeys)
+ vehicle_journeys
+ end
end
def maybe_filter_by_departure_time(scope)
@@ -159,6 +144,7 @@ class VehicleJourneysController < ChouetteController
end
def user_permissions
+ @features = Hash[*current_organisation.features.map{|f| [f, true]}.flatten].to_json
policy = policy(:vehicle_journey)
@perms =
%w{create destroy update}.inject({}) do | permissions, action |
@@ -167,6 +153,69 @@ class VehicleJourneysController < ChouetteController
end
private
+ def load_custom_fields
+ @custom_fields = current_workgroup.custom_fields_definitions
+ end
+
+ def map_stop_points points
+ (points&.includes(:stop_area) || []).map do |sp|
+ {
+ :id => sp.stop_area.id,
+ :route_id => sp.try(:route_id),
+ :object_id => sp.try(:objectid),
+ :area_object_id => sp.stop_area.try(:objectid),
+ :position => sp.try(:position),
+ :for_boarding => sp.try(:for_boarding),
+ :for_alighting => sp.try(:for_alighting),
+ :name => sp.stop_area.try(:name),
+ :time_zone_offset => sp.stop_area.try(:time_zone_offset),
+ :time_zone_formatted_offset => sp.stop_area.try(:time_zone_formatted_offset),
+ :zip_code => sp.stop_area.try(:zip_code),
+ :city_name => sp.stop_area.try(:city_name),
+ :comment => sp.stop_area.try(:comment),
+ :area_type => sp.stop_area.try(:area_type),
+ :area_type_i18n => I18n.t(sp.stop_area.try(:area_type), scope: 'area_types.label'),
+ :area_kind => sp.stop_area.try(:kind),
+ :stop_area_id => sp.stop_area_id,
+ :registration_number => sp.stop_area.try(:registration_number),
+ :nearest_topic_name => sp.stop_area.try(:nearest_topic_name),
+ :fare_code => sp.stop_area.try(:fare_code),
+ :longitude => sp.stop_area.try(:longitude),
+ :latitude => sp.stop_area.try(:latitude),
+ :long_lat_type => sp.stop_area.try(:long_lat_type),
+ :country_code => sp.stop_area.try(:country_code),
+ :country_name => sp.stop_area.try(:country_name),
+ :street_name => sp.stop_area.try(:street_name)
+ }
+ end
+ end
+
+ def load_missions
+ @all_missions = route.journey_patterns.count > 10 ? [] : route.journey_patterns.map do |item|
+ {
+ id: item.id,
+ "data-item": {
+ id: item.id,
+ name: item.name,
+ published_name: item.published_name,
+ object_id: item.objectid,
+ short_id: item.get_objectid.short_id,
+ full_schedule: item.full_schedule?,
+ costs: item.costs,
+ stop_area_short_descriptions: item.stop_areas.map do |stop|
+ {
+ stop_area_short_description: {
+ id: stop.id,
+ name: stop.name,
+ object_id: item.objectid
+ }
+ }
+ end
+ }.to_json,
+ text: "<strong>#{item.published_name} - #{item.get_objectid.short_id}</strong><br/><small>#{item.registration_number}</small>"
+ }
+ end
+ end
def vehicle_journey_params
params.require(:vehicle_journey).permit(
{ footnote_ids: [] },
diff --git a/app/controllers/workbench_outputs_controller.rb b/app/controllers/workbench_outputs_controller.rb
new file mode 100644
index 000000000..67ed7569e
--- /dev/null
+++ b/app/controllers/workbench_outputs_controller.rb
@@ -0,0 +1,9 @@
+class WorkbenchOutputsController < ChouetteController
+ respond_to :html, only: [:show]
+ defaults resource_class: Workbench
+
+ def show
+ @workbench = current_organisation.workbenches.find params[:workbench_id]
+ @workbench_merges = @workbench.merges.order("created_at desc").paginate(page: params[:page], per_page: 10)
+ end
+end
diff --git a/app/controllers/workbenches_controller.rb b/app/controllers/workbenches_controller.rb
index b2dac9e67..2a71fe811 100644
--- a/app/controllers/workbenches_controller.rb
+++ b/app/controllers/workbenches_controller.rb
@@ -18,9 +18,8 @@ class WorkbenchesController < ChouetteController
@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 = ReferentialDecorator.decorate(
@wbench_refs,
- with: ReferentialDecorator,
context: {
current_workbench_id: params[:id]
}
diff --git a/app/decorators/api_key_decorator.rb b/app/decorators/api_key_decorator.rb
deleted file mode 100644
index def3a6a01..000000000
--- a/app/decorators/api_key_decorator.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-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/calendar_decorator.rb b/app/decorators/calendar_decorator.rb
index 37e2cfe80..4c6088e8e 100644
--- a/app/decorators/calendar_decorator.rb
+++ b/app/decorators/calendar_decorator.rb
@@ -1,18 +1,13 @@
-class CalendarDecorator < Draper::Decorator
- delegate_all
+class CalendarDecorator < AF83::Decorator
+ decorates Calendar
+ set_scope { context[:workgroup] }
+ create_action_link
- def action_links
- links = []
-
- if h.policy(object).destroy?
- links << Link.new(
- content: h.destroy_link_content,
- href: h.calendar_path(object),
- method: :delete,
- data: { confirm: h.t('calendars.actions.destroy_confirm') }
- )
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link
+ instance_decorator.edit_action_link
+ instance_decorator.destroy_action_link do |l|
+ l.data {{ confirm: h.t('calendars.actions.destroy_confirm') }}
end
-
- links
end
end
diff --git a/app/decorators/company_decorator.rb b/app/decorators/company_decorator.rb
index 9416c73ae..5580e0d4a 100644
--- a/app/decorators/company_decorator.rb
+++ b/app/decorators/company_decorator.rb
@@ -1,52 +1,22 @@
-class CompanyDecorator < Draper::Decorator
+class CompanyDecorator < AF83::Decorator
decorates Chouette::Company
- delegate_all
+ set_scope { context[:referential] }
- def self.collection_decorator_class
- PaginatingDecorator
+ create_action_link do |l|
+ l.content { h.t('companies.actions.new') }
end
- def linecount
- object.lines.count
- end
-
- # Requires:
- # context: {
- # referential:
- # }
- def action_links
- links = []
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link
- if h.policy(Chouette::Company).create?
- links << Link.new(
- content: h.t('companies.actions.new'),
- href: h.new_line_referential_company_path(context[:referential])
- )
+ instance_decorator.edit_action_link do |l|
+ l.content {|l| l.action == "show" ? h.t('actions.edit') : h.t('companies.actions.edit') }
end
- if h.policy(object).update?
- links << Link.new(
- content: h.t('companies.actions.edit'),
- href: h.edit_line_referential_company_path(
- context[:referential],
- object
- )
- )
+ instance_decorator.destroy_action_link do |l|
+ l.content { h.destroy_link_content('companies.actions.destroy') }
+ l.data {{ confirm: h.t('companies.actions.destroy_confirm') }}
end
-
- if h.policy(object).destroy?
- links << Link.new(
- content: t('companies.actions.destroy'),
- href: h.line_referential_company_path(
- context[:referential],
- object
- ),
- method: :delete,
- data: { confirm: h.t('companies.actions.destroy_confirm') }
- )
- end
-
- links
end
end
diff --git a/app/decorators/compliance_check_decorator.rb b/app/decorators/compliance_check_decorator.rb
deleted file mode 100644
index 5431f5796..000000000
--- a/app/decorators/compliance_check_decorator.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class ComplianceCheckDecorator < Draper::Decorator
- delegate_all
-
- def action_links
- []
- end
-
-end
diff --git a/app/decorators/compliance_check_set_decorator.rb b/app/decorators/compliance_check_set_decorator.rb
index 096596b19..334f39e88 100644
--- a/app/decorators/compliance_check_set_decorator.rb
+++ b/app/decorators/compliance_check_set_decorator.rb
@@ -1,24 +1,15 @@
-class ComplianceCheckSetDecorator < Draper::Decorator
- delegate_all
+class ComplianceCheckSetDecorator < AF83::Decorator
+ decorates ComplianceCheckSet
- def action_links
- links = []
-
- links << Link.new(
- content: h.destroy_link_content,
- href: h.workbench_compliance_check_sets_path(object.id),
- method: :delete,
- data: {confirm: h.t('imports.actions.destroy_confirm')}
- )
-
- links
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link
end
- def lines_status
+ define_instance_method :lines_status do
object.compliance_check_resources.where(status: :OK, resource_type: :line).count
end
- def lines_in_compliance_check_set
+ define_instance_method :lines_in_compliance_check_set do
object.compliance_check_resources.where(resource_type: :line).count
end
diff --git a/app/decorators/compliance_control_decorator.rb b/app/decorators/compliance_control_decorator.rb
index f56e80417..fd2dbd9ce 100644
--- a/app/decorators/compliance_control_decorator.rb
+++ b/app/decorators/compliance_control_decorator.rb
@@ -1,30 +1,35 @@
-class ComplianceControlDecorator < Draper::Decorator
- delegate_all
+class ComplianceControlDecorator < AF83::Decorator
+ decorates ComplianceControl
- def action_links
- policy = h.policy(object)
- links = []
+ set_scope { object.compliance_control_set }
- links << Link.new(
- content: h.t('compliance_control_sets.actions.show'),
- href: h.compliance_control_set_compliance_control_path(object.compliance_control_set.id, object.id)
- )
-
- if policy.edit?
- links << Link.new(
- content: h.t('compliance_controls.actions.edit'),
- href: h.edit_compliance_control_set_compliance_control_path(object.compliance_control_set.id, object.id)
- )
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link do |l|
+ l.content h.t('compliance_control_sets.actions.show')
+ l.href do
+ h.compliance_control_set_compliance_control_path(
+ object.compliance_control_set.id,
+ object.id
+ )
+ end
end
- if policy.destroy?
- links << Link.new(
- content: h.destroy_link_content,
- href: h.compliance_control_set_compliance_control_path(object.compliance_control_set.id, object.id),
- method: :delete,
- data: { confirm: h.t('compliance_controls.actions.destroy_confirm') }
- )
+ instance_decorator.edit_action_link
+
+ instance_decorator.destroy_action_link do |l|
+ l.data confirm: h.t('compliance_controls.actions.destroy_confirm')
end
- links
+ end
+
+ define_instance_class_method :predicate do
+ object_class.predicate
+ end
+
+ define_instance_class_method :prerequisite do
+ object_class.prerequisite
+ end
+
+ define_instance_class_method :dynamic_attributes do
+ object_class.dynamic_attributes
end
end
diff --git a/app/decorators/compliance_control_set_decorator.rb b/app/decorators/compliance_control_set_decorator.rb
index 73d65d54a..b16a06886 100644
--- a/app/decorators/compliance_control_set_decorator.rb
+++ b/app/decorators/compliance_control_set_decorator.rb
@@ -1,35 +1,26 @@
-class ComplianceControlSetDecorator < Draper::Decorator
- delegate_all
+class ComplianceControlSetDecorator < AF83::Decorator
+ decorates ComplianceControlSet
- def action_links
- policy = h.policy(object)
- links = []
+ create_action_link do |l|
+ l.content t('compliance_control_sets.actions.new')
+ end
- if policy.edit?
- links << Link.new(
- content: h.t('compliance_control_sets.actions.edit'),
- href: h.edit_compliance_control_set_path(object.id)
- )
- end
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link
- if policy.clone?
- links << Link.new(
- content: h.t('actions.clone'),
- href: h.clone_compliance_control_set_path(object.id)
- )
+ instance_decorator.edit_action_link do |l|
+ l.content t('compliance_control_sets.actions.edit')
end
- if policy.destroy?
- links << Link.new(
- content: h.destroy_link_content,
- href: h.compliance_control_set_path(object.id),
- method: :delete,
- data: { confirm: h.t('compliance_control_sets.actions.destroy_confirm') }
- )
+ instance_decorator.action_link policy: :clone, secondary: :show do |l|
+ l.content t('actions.clone')
+ l.href { h.clone_compliance_control_set_path(object.id) }
end
- links
+ instance_decorator.destroy_action_link do |l|
+ l.content h.destroy_link_content
+ l.href { h.compliance_control_set_path(object.id) }
+ l.data confirm: h.t('compliance_control_sets.actions.destroy_confirm')
+ end
end
-
end
-
diff --git a/app/decorators/import_decorator.rb b/app/decorators/import_decorator.rb
index e748f830d..1964365ae 100644
--- a/app/decorators/import_decorator.rb
+++ b/app/decorators/import_decorator.rb
@@ -1,9 +1,9 @@
-class ImportDecorator < Draper::Decorator
+class ImportDecorator < AF83::Decorator
decorates Import
- delegate_all
+ set_scope { context[:workbench] }
- def import_status_css_class
+ define_instance_method :import_status_css_class do
cls =''
cls = 'overheaded-success' if object.status == 'successful'
cls = 'overheaded-warning' if object.status == 'warning'
@@ -11,36 +11,16 @@ class ImportDecorator < Draper::Decorator
cls
end
- def action_links
- policy = h.policy(object)
- links = []
-
- links << Link.new(
- content: h.t('imports.actions.show'),
- href: h.workbench_import_path(
- context[:workbench],
- object
- )
- )
+ create_action_link do |l|
+ l.content t('imports.actions.new')
+ end
- links << Link.new(
- content: h.t('imports.actions.download'),
- href: object.file.url
- )
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link
- if policy.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') }
- )
+ instance_decorator.action_link secondary: :show do |l|
+ l.content t('imports.actions.download')
+ l.href { object.file.url }
end
-
- links
end
-
end
diff --git a/app/decorators/import_resource_decorator.rb b/app/decorators/import_resource_decorator.rb
deleted file mode 100644
index 9bfd1f757..000000000
--- a/app/decorators/import_resource_decorator.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-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
index 2b1a25ef9..88a8057cf 100644
--- a/app/decorators/import_resources_decorator.rb
+++ b/app/decorators/import_resources_decorator.rb
@@ -1,4 +1,4 @@
-class ImportResourcesDecorator < ModelDecorator
+class ImportResourcesDecorator < AF83::Decorator
delegate :where
def lines_imported
diff --git a/app/decorators/line_decorator.rb b/app/decorators/line_decorator.rb
index ede670cbd..0e7b6b9ae 100644
--- a/app/decorators/line_decorator.rb
+++ b/app/decorators/line_decorator.rb
@@ -1,55 +1,70 @@
-class LineDecorator < Draper::Decorator
+class LineDecorator < AF83::Decorator
decorates Chouette::Line
- delegate_all
-
- # Requires:
- # context: {
- # line_referential: ,
- # current_organisation:
- # }
- def action_links
- links = []
-
- links << Link.new(
- content: h.t('lines.actions.show_network'),
- href: [context[:line_referential], object.network]
- )
-
- links << Link.new(
- content: h.t('lines.actions.show_company'),
- href: [context[:line_referential], object.company]
- )
-
- if h.policy(Chouette::Line).create? &&
- context[:line_referential].organisations.include?(
- context[:current_organisation]
- )
- links << Link.new(
- content: h.t('lines.actions.edit'),
- href: h.edit_line_referential_line_path(context[:line_referential], object.id)
- )
+ set_scope { context[:line_referential] }
+
+ create_action_link do |l|
+ l.content t('lines.actions.new')
+ end
+
+ with_instance_decorator do |instance_decorator|
+ ### primary (and secondary) can be
+ ### - a single action
+ ### - an array of actions
+ ### - a boolean
+
+ instance_decorator.show_action_link do |l|
+ l.content t('lines.actions.show')
+ end
+
+ instance_decorator.action_link secondary: :show do |l|
+ l.content t('lines.actions.show_network')
+ l.href { [scope, object.network] }
+ l.disabled { object.network.nil? }
+ end
+
+ instance_decorator.action_link secondary: :show do |l|
+ l.content t('lines.actions.show_company')
+ l.href { [scope, object.company] }
+ l.disabled { object.company.nil? }
end
- if h.policy(Chouette::Line).create? &&
- context[:line_referential].organisations.include?(
- context[:current_organisation]
- )
- links << Link.new(
- content: h.t('lines.actions.new'),
- href: h.new_line_referential_line_path(context[:line_referential])
- )
+ can_edit_line = ->(){ h.policy(Chouette::Line).create? && context[:line_referential].organisations.include?(context[:current_organisation]) }
+
+ instance_decorator.with_condition can_edit_line do
+ edit_action_link do |l|
+ l.content {|l| l.primary? ? h.t('actions.edit') : h.t('lines.actions.edit') }
+ end
+
+ action_link on: :index, secondary: :index do |l|
+ l.content t('lines.actions.new')
+ l.href { h.new_line_referential_line_path(context[:line_referential]) }
+ end
end
- if h.policy(object).destroy?
- links << Link.new(
- content: h.destroy_link_content('lines.actions.destroy'),
- href: h.line_referential_line_path(context[:line_referential], object),
- method: :delete,
- data: {confirm: h.t('lines.actions.destroy_confirm')}
- )
+ ### the option :policy will automatically check for the corresponding method
+ ### on the object's policy
+
+ instance_decorator.action_link policy: :deactivate, secondary: :show, footer: :index do |l|
+ l.content { h.deactivate_link_content('lines.actions.deactivate') }
+ l.href { h.deactivate_line_referential_line_path(context[:line_referential], object) }
+ l.method :put
+ l.data confirm: h.t('lines.actions.deactivate_confirm')
+ l.add_class "delete-action"
end
- links
+ instance_decorator.action_link policy: :activate, secondary: :show, footer: :index do |l|
+ l.content { h.activate_link_content('lines.actions.activate') }
+ l.href { h.activate_line_referential_line_path(context[:line_referential], object) }
+ l.method :put
+ l.data confirm: h.t('lines.actions.activate_confirm')
+ l.add_class "delete-action"
+ end
+
+ instance_decorator.destroy_action_link do |l|
+ l.content { h.destroy_link_content('lines.actions.destroy') }
+ l.data confirm: h.t('lines.actions.destroy_confirm')
+ l.add_class "delete-action"
+ end
end
end
diff --git a/app/decorators/network_decorator.rb b/app/decorators/network_decorator.rb
index 1f62fe512..ea0f73dc2 100644
--- a/app/decorators/network_decorator.rb
+++ b/app/decorators/network_decorator.rb
@@ -1,44 +1,32 @@
-class NetworkDecorator < Draper::Decorator
+class NetworkDecorator < AF83::Decorator
decorates Chouette::Network
- delegate_all
-
- # Requires:
+ set_scope { context[:line_referential] }
+ # Action links require:
# context: {
# line_referential: ,
# }
- def action_links
- links = []
- if h.policy(Chouette::Network).create?
- links << Link.new(
- content: h.t('networks.actions.new'),
- href: h.new_line_referential_network_path(context[:line_referential])
- )
- end
+ create_action_link do |l|
+ l.content t('networks.actions.new')
+ end
+
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link
- if h.policy(object).update?
- links << Link.new(
- content: h.t('networks.actions.edit'),
- href: h.edit_line_referential_network_path(
+ instance_decorator.action_link secondary: true, policy: :edit do |l|
+ l.content t('networks.actions.edit')
+ l.href do
+ h.edit_line_referential_network_path(
context[:line_referential],
object
)
- )
+ end
end
- if h.policy(object).destroy?
- links << Link.new(
- content: h.destroy_link_content('networks.actions.destroy'),
- href: h.line_referential_network_path(
- context[:line_referential],
- object
- ),
- method: :delete,
- data: { confirm: t('networks.actions.destroy_confirm') }
- )
+ instance_decorator.destroy_action_link do |l|
+ l.content h.destroy_link_content('networks.actions.destroy')
+ l.data confirm: h.t('networks.actions.destroy_confirm')
end
-
- links
end
end
diff --git a/app/decorators/purchase_window_decorator.rb b/app/decorators/purchase_window_decorator.rb
new file mode 100644
index 000000000..9b58577b2
--- /dev/null
+++ b/app/decorators/purchase_window_decorator.rb
@@ -0,0 +1,28 @@
+class PurchaseWindowDecorator < AF83::Decorator
+ decorates Chouette::PurchaseWindow
+
+ set_scope { context[:referential] }
+
+ create_action_link do |l|
+ l.content t('purchase_windows.actions.new')
+ end
+
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link do |l|
+ l.content t('purchase_windows.actions.show')
+ end
+
+ instance_decorator.edit_action_link
+
+ instance_decorator.destroy_action_link do |l|
+ l.data confirm: h.t('purchase_windows.actions.destroy_confirm')
+ end
+ end
+
+ define_instance_method :bounding_dates do
+ unless object.date_ranges.empty?
+ object.date_ranges.map(&:min).min..object.date_ranges.map(&:max).max
+ end
+ end
+
+end
diff --git a/app/decorators/referential_decorator.rb b/app/decorators/referential_decorator.rb
index 4103790aa..3132cbf92 100644
--- a/app/decorators/referential_decorator.rb
+++ b/app/decorators/referential_decorator.rb
@@ -1,66 +1,60 @@
-class ReferentialDecorator < Draper::Decorator
- delegate_all
+class ReferentialDecorator < AF83::Decorator
+ decorates Referential
- def action_links
- policy = h.policy(object)
- links = [
- Link.new(
- content: h.t('time_tables.index.title'),
- href: h.referential_time_tables_path(object)
- )
- ]
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link
+ instance_decorator.edit_action_link
- if policy.clone?
- links << Link.new(
- content: h.t('actions.clone'),
- href: h.new_referential_path(from: object.id, current_workbench_id: context[:current_workbench_id])
- )
+ instance_decorator.action_link feature: :referential_vehicle_journeys, secondary: :show, on: :show do |l|
+ l.content t('referential_vehicle_journeys.index.title')
+ l.href { h.referential_vehicle_journeys_path(object) }
end
- if policy.validate?
- links << Link.new(
- content: h.t('actions.validate'),
- href: h.referential_select_compliance_control_set_path(object.id)
- )
+ instance_decorator.action_link feature: :purchase_windows, secondary: :show, on: :show do |l|
+ l.content t('purchase_windows.index.title')
+ l.href { h.referential_purchase_windows_path(object) }
end
- if policy.archive?
- links << Link.new(
- content: h.t('actions.archive'),
- href: h.archive_referential_path(object.id),
- method: :put
- )
+ instance_decorator.action_link secondary: :show do |l|
+ l.content t('time_tables.index.title')
+ l.href { h.referential_time_tables_path(object) }
end
- if policy.unarchive?
- links << Link.new(
- content: h.t('actions.unarchive'),
- href: h.unarchive_referential_path(object.id),
- method: :put
- )
+ instance_decorator.action_link policy: :clone, secondary: :show do |l|
+ l.content t('actions.clone')
+ l.href { h.new_referential_path(from: object.id, current_workbench_id: context[:current_workbench_id]) }
end
- if policy.edit?
- links << HTMLElement.new(
- :button,
- 'Purger',
- type: 'button',
- data: {
- toggle: 'modal',
- target: '#purgeModal'
- }
- )
+ instance_decorator.action_link policy: :validate, secondary: :show do |l|
+ l.content t('actions.validate')
+ l.href { h.referential_select_compliance_control_set_path(object.id) }
end
- if policy.destroy?
- links << Link.new(
- content: h.destroy_link_content,
- href: h.referential_path(object),
- method: :delete,
- data: { confirm: h.t('referentials.actions.destroy_confirm') }
- )
+ instance_decorator.action_link policy: :archive, secondary: :show do |l|
+ l.content t('actions.archive')
+ l.href { h.archive_referential_path(object.id) }
+ l.method :put
end
- links
+ instance_decorator.action_link policy: :unarchive, secondary: :show, on: :show do |l|
+ l.content t('actions.unarchive')
+ l.href { h.unarchive_referential_path(object.id) }
+ l.method :put
+ end
+
+ instance_decorator.action_link policy: :edit, secondary: :show, on: :show do |l|
+ l.content 'Purger'
+ l.href '#'
+ l.type 'button'
+ l.data {{
+ toggle: 'modal',
+ target: '#purgeModal'
+ }}
+ end
+
+ instance_decorator.destroy_action_link do |l|
+ l.href { h.referential_path(object) }
+ l.data {{ confirm: h.t('referentials.actions.destroy_confirm') }}
+ end
end
end
diff --git a/app/decorators/referential_line_decorator.rb b/app/decorators/referential_line_decorator.rb
index 55acf7ed9..3ac846d76 100644
--- a/app/decorators/referential_line_decorator.rb
+++ b/app/decorators/referential_line_decorator.rb
@@ -1,64 +1,43 @@
-class ReferentialLineDecorator < Draper::Decorator
+class ReferentialLineDecorator < AF83::Decorator
decorates Chouette::Line
- delegate_all
+ set_scope { context[:referential] }
- # Requires:
+ # Action links require:
# context: {
# referential: ,
# current_organisation:
# }
- def action_links
- links = []
- links << Link.new(
- content: Chouette::Line.human_attribute_name(:footnotes),
- href: h.referential_line_footnotes_path(context[:referential], object)
- )
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link
- links << Link.new(
- content: h.t('routing_constraint_zones.index.title'),
- href: h.referential_line_routing_constraint_zones_path(
- context[:referential],
- object
- )
- )
-
- if h.policy(Chouette::Line).create? &&
- context[:referential].organisation == context[:current_organisation]
- links << Link.new(
- content: h.t('actions.new'),
- href: h.new_referential_line_path(context[:referential])
- )
- end
-
- if h.policy(object).update?
- links << Link.new(
- content: h.t('actions.edit'),
- href: h.edit_referential_line_path(context[:referential], object)
- )
+ instance_decorator.action_link secondary: true do |l|
+ l.content Chouette::Line.human_attribute_name(:footnotes)
+ l.href { h.referential_line_footnotes_path(context[:referential], object) }
end
- if h.policy(object).destroy?
- links << Link.new(
- content: h.destroy_link_content('actions.destroy'),
- href: h.referential_line_path(context[:referential], object),
- method: :delete,
- data: { confirm: t('lines.actions.destroy_confirm') }
- )
- end
-
- if !object.hub_restricted? ||
- (object.hub_restricted? && object.routes.size < 2)
- if h.policy(Chouette::Route).create? &&
- context[:referential].organisation == context[:current_organisation]
- links << Link.new(
- content: h.t('routes.actions.new'),
- href: h.new_referential_line_route_path(context[:referential], object)
+ instance_decorator.action_link secondary: true do |l|
+ l.content h.t('routing_constraint_zones.index.title')
+ l.href do
+ h.referential_line_routing_constraint_zones_path(
+ scope,
+ object
)
end
end
- links
+ instance_decorator.action_link(
+ if: ->() {
+ (!object.hub_restricted? ||
+ (object.hub_restricted? && object.routes.size < 2)) &&
+ (h.policy(Chouette::Route).create? &&
+ context[:referential].organisation == context[:current_organisation])
+ },
+ secondary: true
+ ) do |l|
+ l.content h.t('routes.actions.new')
+ l.href { h.new_referential_line_route_path(scope, object) }
+ end
end
end
diff --git a/app/decorators/referential_network_decorator.rb b/app/decorators/referential_network_decorator.rb
index 1260a38cb..c508452c0 100644
--- a/app/decorators/referential_network_decorator.rb
+++ b/app/decorators/referential_network_decorator.rb
@@ -1,38 +1,27 @@
-class ReferentialNetworkDecorator < Draper::Decorator
+class ReferentialNetworkDecorator < AF83::Decorator
decorates Chouette::Network
- delegate_all
+ set_scope { context[:referential] }
-# Requires:
-# context: {
-# referential: ,
-# }
-def action_links
- links = []
+ # Action links require:
+ # context: {
+ # referential: ,
+ # }
- if h.policy(Chouette::Network).create?
- links << Link.new(
- content: h.t('networks.actions.new'),
- href: h.new_referential_network_path(context[:referential])
- )
+ create_action_link do |l|
+ l.content t('networks.actions.new')
end
- if h.policy(object).update?
- links << Link.new(
- content: h.t('networks.actions.edit'),
- href: h.edit_referential_network_path(context[:referential], object)
- )
- end
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link
- if h.policy(object).destroy?
- links << Link.new(
- content: h.destroy_link_content('networks.actions.destroy'),
- href: h.referential_network_path(context[:referential], object),
- method: :delete,
- data: { confirm: t('networks.actions.destroy_confirm') }
- )
- end
+ instance_decorator.edit_action_link do |l|
+ l.content t('networks.actions.edit')
+ end
- links
+ instance_decorator.destroy_action_link do |l|
+ l.content h.destroy_link_content('networks.actions.destroy')
+ l.data confirm: h.t('networks.actions.destroy_confirm')
+ end
end
-end \ No newline at end of file
+end
diff --git a/app/decorators/route_decorator.rb b/app/decorators/route_decorator.rb
index ec7f0d6aa..fa6367924 100644
--- a/app/decorators/route_decorator.rb
+++ b/app/decorators/route_decorator.rb
@@ -1,75 +1,78 @@
-class RouteDecorator < Draper::Decorator
+class RouteDecorator < AF83::Decorator
decorates Chouette::Route
- delegate_all
-
- # Requires:
+ # Action links require:
# context: {
# referential: ,
# line:
# }
- def action_links
- links = []
- if object.stop_points.any?
- links << Link.new(
- content: h.t('journey_patterns.actions.index'),
- href: [
+ set_scope { [context[:referential], context[:line]] }
+
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link
+
+ instance_decorator.edit_action_link
+
+ instance_decorator.action_link(
+ if: ->() { object.stop_points.any? },
+ secondary: :show
+ ) do |l|
+ l.content h.t('journey_patterns.actions.index')
+ l.href do
+ [
context[:referential],
context[:line],
object,
:journey_patterns_collection
]
- )
+ end
end
- if object.journey_patterns.present?
- links << Link.new(
- content: h.t('vehicle_journeys.actions.index'),
- href: [
+ instance_decorator.action_link(
+ if: ->() { object.journey_patterns.present? },
+ secondary: :show
+ ) do |l|
+ l.content h.t('vehicle_journeys.actions.index')
+ l.href do
+ [
context[:referential],
context[:line],
object,
:vehicle_journeys
]
- )
+ end
end
- links << Link.new(
- content: h.t('vehicle_journey_exports.new.title'),
- href: h.referential_line_route_vehicle_journey_exports_path(
- context[:referential],
- context[:line],
- object,
- format: :zip
- )
- )
-
- if h.policy(object).duplicate?
- links << Link.new(
- content: h.t('routes.duplicate.title'),
- href: h.duplicate_referential_line_route_path(
+ instance_decorator.action_link secondary: :show do |l|
+ l.content h.t('vehicle_journey_exports.new.title')
+ l.href do
+ h.referential_line_route_vehicle_journey_exports_path(
context[:referential],
context[:line],
- object
- ),
- method: :post
- )
+ object,
+ format: :zip
+ )
+ end
end
- if h.policy(object).destroy?
- links << Link.new(
- content: h.destroy_link_content,
- href: h.referential_line_route_path(
+ instance_decorator.action_link(
+ secondary: :show,
+ policy: :duplicate
+ ) do |l|
+ l.content h.t('routes.duplicate.title')
+ l.method :post
+ l.href do
+ h.duplicate_referential_line_route_path(
context[:referential],
context[:line],
object
- ),
- method: :delete,
- data: { confirm: h.t('routes.actions.destroy_confirm') }
- )
+ )
+ end
end
- links
+ instance_decorator.destroy_action_link do |l|
+ l.data confirm: h.t('routes.actions.destroy_confirm')
+ end
end
end
diff --git a/app/decorators/routing_constraint_zone_decorator.rb b/app/decorators/routing_constraint_zone_decorator.rb
index 0b438a554..de73068be 100644
--- a/app/decorators/routing_constraint_zone_decorator.rb
+++ b/app/decorators/routing_constraint_zone_decorator.rb
@@ -1,42 +1,27 @@
-class RoutingConstraintZoneDecorator < Draper::Decorator
+class RoutingConstraintZoneDecorator < AF83::Decorator
decorates Chouette::RoutingConstraintZone
- delegate_all
+ set_scope { [context[:referential], context[:line]] }
- # Requires:
+ # Action links require:
# context: {
# referential: ,
# line:
# }
- def action_links
- links = []
- if h.policy(object).update?
- links << Link.new(
- content: h.t('actions.edit'),
- href: h.edit_referential_line_routing_constraint_zone_path(
- context[:referential],
- context[:line],
- object
- )
- )
- end
+ create_action_link(
+ if: ->() {
+ h.policy(Chouette::RoutingConstraintZone).create? &&
+ context[:referential].organisation == h.current_organisation
+ }
+ )
- if h.policy(object).destroy?
- links << Link.new(
- content: h.destroy_link_content,
- href: h.referential_line_routing_constraint_zone_path(
- context[:referential],
- context[:line],
- object
- ),
- method: :delete,
- data: {
- confirm: h.t('routing_constraint_zones.actions.destroy_confirm')
- }
- )
- end
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link
+ instance_decorator.edit_action_link
- links
+ instance_decorator.destroy_action_link do |l|
+ l.data confirm: h.t('routing_constraint_zones.actions.destroy_confirm')
+ end
end
end
diff --git a/app/decorators/stop_area_decorator.rb b/app/decorators/stop_area_decorator.rb
index 4e777292d..525681971 100644
--- a/app/decorators/stop_area_decorator.rb
+++ b/app/decorators/stop_area_decorator.rb
@@ -1,43 +1,54 @@
-class StopAreaDecorator < Draper::Decorator
+class StopAreaDecorator < AF83::Decorator
decorates Chouette::StopArea
- delegate_all
+ create_action_link do |l|
+ l.content t('stop_areas.actions.new')
+ l.href { h.new_stop_area_referential_stop_area_path }
+ end
+
+ with_instance_decorator do |instance_decorator|
+ set_scope { object.stop_area_referential }
+ instance_decorator.show_action_link
- def action_links(stop_area = nil)
- links = []
- stop_area ||= object
+ instance_decorator.edit_action_link do |l|
+ l.content h.t('stop_areas.actions.edit')
+ end
- if h.policy(Chouette::StopArea).new?
- links << Link.new(
- content: h.t('stop_areas.actions.new'),
- href: h.new_stop_area_referential_stop_area_path(
- stop_area.stop_area_referential
+ instance_decorator.action_link policy: :deactivate, secondary: true do |l|
+ l.content h.deactivate_link_content('stop_areas.actions.deactivate')
+ l.href do
+ h.deactivate_stop_area_referential_stop_area_path(
+ object.stop_area_referential,
+ object
)
- )
+ end
+ l.method :put
+ l.data confirm: h.t('stop_areas.actions.deactivate_confirm')
+ l.add_class 'delete-action'
end
- if h.policy(stop_area).update?
- links << Link.new(
- content: h.t('stop_areas.actions.edit'),
- href: h.edit_stop_area_referential_stop_area_path(
- stop_area.stop_area_referential,
- stop_area
+ instance_decorator.action_link policy: :activate, secondary: true do |l|
+ l.content h.activate_link_content('stop_areas.actions.activate')
+ l.href do
+ h.activate_stop_area_referential_stop_area_path(
+ object.stop_area_referential,
+ object
)
- )
+ end
+ l.method :put
+ l.data confirm: h.t('stop_areas.actions.activate_confirm')
+ l.add_class 'delete-action'
end
- if h.policy(stop_area).destroy?
- links << Link.new(
- content: h.destroy_link_content('stop_areas.actions.destroy'),
- href: h.stop_area_referential_stop_area_path(
- stop_area.stop_area_referential,
- stop_area
- ),
- method: :delete,
- data: { confirm: t('stop_areas.actions.destroy_confirm') }
- )
+ instance_decorator.destroy_action_link do |l|
+ l.content h.destroy_link_content('stop_areas.actions.destroy')
+ l.data confirm: h.t('stop_areas.actions.destroy_confirm')
end
+ end
- links
+ define_instance_method :waiting_time_text do
+ return '-' if [nil, 0].include? waiting_time
+ h.t('stop_areas.waiting_time_format', value: waiting_time)
end
+
end
diff --git a/app/decorators/stop_point_decorator.rb b/app/decorators/stop_point_decorator.rb
index 196d6d490..e777e2b56 100644
--- a/app/decorators/stop_point_decorator.rb
+++ b/app/decorators/stop_point_decorator.rb
@@ -1,9 +1,35 @@
-class StopPointDecorator < StopAreaDecorator
+class StopPointDecorator < AF83::Decorator
decorates Chouette::StopPoint
- delegate_all
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link do |l|
+ l.href do
+ h.referential_stop_area_path(
+ object.referential,
+ object.stop_area
+ )
+ end
+ end
- def action_links
- super(object.stop_area)
+ instance_decorator.edit_action_link do |l|
+ l.content h.t('stop_points.actions.edit')
+ l.href do
+ h.edit_stop_area_referential_stop_area_path(
+ object.stop_area.stop_area_referential,
+ object.stop_area
+ )
+ end
+ end
+
+ instance_decorator.destroy_action_link do |l|
+ l.content h.destroy_link_content('stop_points.actions.destroy')
+ l.href do
+ h.referential_stop_area_path(
+ object.referential,
+ object.stop_area
+ )
+ end
+ l.data confirm: h.t('stop_points.actions.destroy_confirm')
+ end
end
end
diff --git a/app/decorators/time_table_decorator.rb b/app/decorators/time_table_decorator.rb
index c6eeac176..e4f9d7dbc 100644
--- a/app/decorators/time_table_decorator.rb
+++ b/app/decorators/time_table_decorator.rb
@@ -1,55 +1,53 @@
-class TimeTableDecorator < Draper::Decorator
+class TimeTableDecorator < AF83::Decorator
decorates Chouette::TimeTable
- delegate_all
+ create_action_link if: ->{ h.policy(Chouette::TimeTable).create? && context[:referential].organisation == h.current_organisation } do |l|
+ l.href { h.new_referential_time_table_path(context[:referential]) }
+ end
+
+ with_instance_decorator do |instance_decorator|
+ instance_decorator.show_action_link do |l|
+ l.href { [context[:referential], object] }
+ end
- # Requires:
- # context: {
- # referential: ,
- # }
- def action_links
- links = []
+ instance_decorator.edit_action_link do |l|
+ l.href { [:edit, context[:referential], object] }
+ end
- if object.calendar
- links << Link.new(
- content: h.t('actions.actualize'),
- href: h.actualize_referential_time_table_path(
+ instance_decorator.action_link policy: :actualize, if: ->{ object.calendar }, secondary: true do |l|
+ l.content t('actions.actualize')
+ l.href do
+ h.actualize_referential_time_table_path(
context[:referential],
object
- ),
- method: :post
- )
+ )
+ end
+ l.method :post
end
- if h.policy(object).edit?
- links << Link.new(
- content: h.t('actions.combine'),
- href: h.new_referential_time_table_time_table_combination_path(
+ instance_decorator.action_link policy: :edit, secondary: true do |l|
+ l.content t('actions.combine')
+ l.href do
+ h.new_referential_time_table_time_table_combination_path(
context[:referential],
object
)
- )
+ end
end
- if h.policy(object).duplicate?
- links << Link.new(
- content: h.t('actions.duplicate'),
- href: h.duplicate_referential_time_table_path(
+ instance_decorator.action_link policy: :duplicate, secondary: true do |l|
+ l.content t('actions.duplicate')
+ l.href do
+ h.duplicate_referential_time_table_path(
context[:referential],
object
)
- )
+ end
end
- if h.policy(object).destroy?
- links << Link.new(
- content: h.destroy_link_content,
- href: h.referential_time_table_path(context[:referential], object),
- method: :delete,
- data: { confirm: h.t('time_tables.actions.destroy_confirm') }
- )
+ instance_decorator.destroy_action_link do |l|
+ l.href { h.referential_time_table_path(context[:referential], object) }
+ l.data {{ confirm: h.t('time_tables.actions.destroy_confirm') }}
end
-
- links
end
end
diff --git a/app/errors/table_lock_timeout_error.rb b/app/errors/table_lock_timeout_error.rb
new file mode 100644
index 000000000..102f3a4a0
--- /dev/null
+++ b/app/errors/table_lock_timeout_error.rb
@@ -0,0 +1 @@
+class TableLockTimeoutError < ActiveRecord::StatementInvalid; end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 124604cd9..0058c210d 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -14,6 +14,11 @@ module ApplicationHelper
def page_header_title(object)
# Unwrap from decorator, we want to know the object model name
object = object.object if object.try(:object)
+
+ if Referential === object
+ return object.full_name
+ end
+
local = "#{object.model_name.name.underscore.pluralize}.#{params[:action]}.title"
if object.try(:name)
t(local, name: object.name || object.id)
@@ -23,12 +28,18 @@ module ApplicationHelper
end
def page_header_meta(object)
- info = t('last_update', time: l(object.updated_at, format: :short))
- if object.try(:versions)
- author = object.versions.try(:last).try(:whodunnit) || t('default_whodunnit')
- info = "#{info} <br/> #{t('whodunnit', author: author)}"
+ out = ""
+ display = true
+ display = policy(object).synchronize? if policy(object).respond_to?(:synchronize?) rescue false
+ if display
+ info = t('last_update', time: l(object.updated_at, format: :short))
+ if object.try(:versions)
+ author = object.versions.try(:last).try(:whodunnit) || t('default_whodunnit')
+ info = "#{info} <br/> #{t('whodunnit', author: author)}"
+ end
+ out += content_tag :div, info.html_safe, class: 'small last-update'
end
- content_tag :div, info.html_safe, class: 'small'
+ out.html_safe
end
def page_header_content_for(object)
diff --git a/app/helpers/breadcrumb_helper.rb b/app/helpers/breadcrumb_helper.rb
index 3da119247..2175e0be4 100644
--- a/app/helpers/breadcrumb_helper.rb
+++ b/app/helpers/breadcrumb_helper.rb
@@ -1,5 +1,12 @@
module BreadcrumbHelper
def breadcrumb_name(object, prop='name')
- "#{object.class.model_name.human} #{object.public_send(prop)}".truncate(50)
+ name =
+ if prop == 'name' && object.respond_to?(:full_name)
+ object.full_name
+ else
+ "#{object.class.model_name.human} #{object.public_send(prop)}"
+ end
+
+ name.truncate(40)
end
end
diff --git a/app/helpers/common_helpers.rb b/app/helpers/common_helpers.rb
deleted file mode 100644
index 29cabddac..000000000
--- a/app/helpers/common_helpers.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-
-module CommonHelpers
- # TODO: Needs refactoring, but does not seem to be under test
- # so let us refactor this **after** test coverage.
- def access_links_pairs(access_links)
- hpairs = Hash.new
- pairs = Array.new
- access_links.each do |link|
- key = pair_key(link)
- pair = nil
- if (hpairs.has_key? key)
- pair = hpairs[key]
- else
- pair = AccessLinkPair.new
- pairs << pair
- hpairs[key] = pair
- end
- if (link.link_orientation_type == "access_point_to_stop_area")
- pair.from_access_point = link
- else
- pair.to_access_point = link
- end
- end
- pairs
- end
-end
diff --git a/app/helpers/compliance_check_resources_helper.rb b/app/helpers/compliance_check_resources_helper.rb
new file mode 100644
index 000000000..95cabed88
--- /dev/null
+++ b/app/helpers/compliance_check_resources_helper.rb
@@ -0,0 +1,12 @@
+module ComplianceCheckResourcesHelper
+
+ # Comlpiance Check Resources statuses helper
+ def compliance_check_resource_status(status)
+ cls = ''
+ cls = 'success' if status == 'OK'
+ cls = 'warning' if status == 'WARNING'
+ cls = 'danger' if %w[ERROR IGNORED].include? status
+
+ content_tag :span, '', class: "fa fa-circle text-#{cls}"
+ end
+end
diff --git a/app/helpers/compliance_check_sets_helper.rb b/app/helpers/compliance_check_sets_helper.rb
index b255aee63..690bee80e 100644
--- a/app/helpers/compliance_check_sets_helper.rb
+++ b/app/helpers/compliance_check_sets_helper.rb
@@ -20,9 +20,9 @@ module ComplianceCheckSetsHelper
content_tag :span, '', class: "fa fa-clock-o"
else
cls =''
- cls = 'success' if status == 'OK'
- cls = 'warning' if status == 'WARNING'
- cls = 'danger' if %w[ERROR IGNORED].include? status
+ 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
diff --git a/app/helpers/compliance_control_sets_helper.rb b/app/helpers/compliance_control_sets_helper.rb
index 57e6d9608..448d5c008 100644
--- a/app/helpers/compliance_control_sets_helper.rb
+++ b/app/helpers/compliance_control_sets_helper.rb
@@ -100,7 +100,8 @@ module ComplianceControlSetsHelper
],
sortable: true,
cls: 'table has-filter has-search',
- model: ComplianceControl
+ model: ComplianceControl,
+ action: :index
end
metas = content_tag :div, I18n.t('compliance_control_blocks.metas.control', count: compliance_controls.count), class: 'pull-right'
table + metas
diff --git a/app/helpers/imports_helper.rb b/app/helpers/imports_helper.rb
index 1c4549e50..140660153 100644
--- a/app/helpers/imports_helper.rb
+++ b/app/helpers/imports_helper.rb
@@ -15,6 +15,20 @@ module ImportsHelper
end
end
+ # Compliance check set messages
+ def bootstrap_class_for_message_criticity message_criticity
+ case message_criticity
+ when "error"
+ "alert alert-danger"
+ when "warning"
+ "alert alert-warning"
+ when "info"
+ "alert alert-info"
+ else
+ message_criticity.to_s
+ end
+ end
+
##############################
#      TO CLEAN!!!
##############################
diff --git a/app/helpers/links_helper.rb b/app/helpers/links_helper.rb
index 4fb7a797d..088415dc3 100644
--- a/app/helpers/links_helper.rb
+++ b/app/helpers/links_helper.rb
@@ -1,5 +1,18 @@
module LinksHelper
+ def custom_link_content(translation_key, klass, extra_class: nil)
+ klass = ["fa", "fa-#{klass}", "mr-xs", extra_class].compact.join(" ")
+ content_tag(:span, nil, class: klass) + t(translation_key)
+ end
+
def destroy_link_content(translation_key = 'actions.destroy')
- content_tag(:span, nil, class: 'fa fa-trash mr-xs') + t(translation_key)
+ custom_link_content translation_key, 'trash'
+ end
+
+ def deactivate_link_content(translation_key = 'actions.deactivate')
+ custom_link_content translation_key, 'power-off', extra_class: "text-danger"
+ end
+
+ def activate_link_content(translation_key = 'actions.activate')
+ custom_link_content translation_key, 'power-off', extra_class: "text-success"
end
end
diff --git a/app/helpers/newapplication_helper.rb b/app/helpers/newapplication_helper.rb
index df19113db..6600a03f7 100644
--- a/app/helpers/newapplication_helper.rb
+++ b/app/helpers/newapplication_helper.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
module NewapplicationHelper
# Table Builder
@@ -147,7 +148,7 @@ module NewapplicationHelper
content_tag :li, link_to(t("actions.#{action}"), polymorph_url)
end
elsif action == :archive
- unless item.archived?
+ unless item.referential_read_only?
content_tag :li, link_to(t("actions.#{action}"), polymorph_url, method: :put)
end
elsif action == :unarchive
diff --git a/app/helpers/pagination_helper.rb b/app/helpers/pagination_helper.rb
index 02eec39dc..9b6042377 100644
--- a/app/helpers/pagination_helper.rb
+++ b/app/helpers/pagination_helper.rb
@@ -25,7 +25,7 @@ module PaginationHelper
if collection.total_pages > 1
links = content_tag :div, '', class: 'page_links' do
- will_paginate collection, container: false, page_links: false, previous_label: '', next_label: ''
+ will_paginate collection, container: false, page_links: false, previous_label: '', next_label: '', param_name: collection.try(:pagination_param_name)
end
content_tag :div, pinfos.concat(links).html_safe, class: "pagination #{cls}"
diff --git a/app/helpers/referentials_helper.rb b/app/helpers/referentials_helper.rb
index 01e5a5879..8251377aa 100644
--- a/app/helpers/referentials_helper.rb
+++ b/app/helpers/referentials_helper.rb
@@ -10,4 +10,9 @@ module ReferentialsHelper
t('true')
end
end
+
+ def referential_overview referential
+ service = ReferentialOverview.new referential, self
+ render partial: "referentials/overview", locals: {referential: referential, overview: service}
+ end
end
diff --git a/app/helpers/routes_helper.rb b/app/helpers/routes_helper.rb
index 4bffa99d4..61714a066 100644
--- a/app/helpers/routes_helper.rb
+++ b/app/helpers/routes_helper.rb
@@ -19,13 +19,15 @@ module RoutesHelper
css
end
- def route_json_for_edit(route)
- route.stop_points.includes(:stop_area).order(:position).map do |stop_point|
+ def route_json_for_edit(route, serialize: true)
+ data = route.stop_points.includes(:stop_area).order(:position).map do |stop_point|
stop_area_attributes = stop_point.stop_area.attributes.slice("name","city_name", "zip_code", "registration_number", "longitude", "latitude", "area_type", "comment")
stop_area_attributes["short_name"] = truncate(stop_area_attributes["name"], :length => 30) || ""
stop_point_attributes = stop_point.attributes.slice("for_boarding","for_alighting")
stop_area_attributes.merge(stop_point_attributes).merge(stoppoint_id: stop_point.id, stoparea_id: stop_point.stop_area.id).merge(user_objectid: stop_point.stop_area.user_objectid)
- end.to_json
+ end
+ data = data.to_json if serialize
+ data
end
end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index f4976ea53..be70d974d 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -8,4 +8,19 @@ module SearchHelper
link_to name, params.deep_merge("q" => search,:page => 1), html_options
end
+ def filter_item_class q, key
+ active = false
+ if q.present? && q[key].present?
+ val = q[key]
+ if val.is_a?(Array)
+ active = val.any? &:present?
+ elsif val.is_a?(Hash)
+ active = val.values.any? &:present?
+ else
+ active = true
+ end
+ end
+ active ? 'active' : 'inactive'
+ end
+
end
diff --git a/app/helpers/stop_areas_helper.rb b/app/helpers/stop_areas_helper.rb
index 3e04fac7d..05ae042f5 100644
--- a/app/helpers/stop_areas_helper.rb
+++ b/app/helpers/stop_areas_helper.rb
@@ -11,6 +11,10 @@ module StopAreasHelper
( "<img src='#{stop_area_picture_url(stop_area)}'/>" + " <span style='height:25px; line-height:25px; margin-left: 5px; '>" + name + " <small style='height:25px; line-height:25px; margin-left: 10px; color: #555;'>" + localization + "</small></span>").html_safe
end
+ def label_for_country country, txt=nil
+ "#{txt} <span title='#{ISO3166::Country[country]&.translation(I18n.locale)}' class='flag-icon flag-icon-#{country}'></span>".html_safe
+ end
+
def genealogical_title
return t("stop_areas.genealogical.genealogical_routing") if @stop_area.stop_area_type == 'itl'
t("stop_areas.genealogical.genealogical")
@@ -33,12 +37,10 @@ module StopAreasHelper
@stop_area.stop_area_type == 'stop_place' || @stop_area.stop_area_type == 'commercial_stop_point'
end
-
def pair_key(access_link)
"#{access_link.access_point.id}-#{access_link.stop_area.id}"
end
-
def geo_data(sa, sar)
if sa.long_lat_type.nil?
content_tag :span, '-'
diff --git a/app/helpers/table_builder_helper.rb b/app/helpers/table_builder_helper.rb
index 37f01ce0d..2068dd23c 100644
--- a/app/helpers/table_builder_helper.rb
+++ b/app/helpers/table_builder_helper.rb
@@ -86,18 +86,36 @@ module TableBuilderHelper
overhead: [],
# Possibility to override the result of collection.model
- model: nil
+ model: nil,
+
+ #overrides the params[:action] value
+ action: nil
)
content_tag :table,
- thead(collection, columns, sortable, selectable, links.any?, overhead, model || collection.model) +
- tbody(collection, columns, selectable, links, overhead),
+ thead(collection, columns, sortable, selectable, links.any?, overhead, model || collection.model, action || params[:action]) +
+ tbody(collection, columns, selectable, links, overhead, model, action || params[:action]),
class: cls
end
+ def self.item_row_class_name collection, model=nil
+ model_name = model&.name
+
+ model_name ||=
+ if collection.respond_to?(:model)
+ collection.model.name
+ elsif collection.respond_to?(:first)
+ collection.first.class.name
+ else
+ "item"
+ end
+
+ model_name.split("::").last.parameterize
+ end
+
private
- def thead(collection, columns, sortable, selectable, has_links, overhead, model )
+ def thead(collection, columns, sortable, selectable, has_links, overhead, model, action)
content_tag :thead do
# Inserts overhead content if any specified
over_head = ''
@@ -176,7 +194,9 @@ module TableBuilderHelper
end
# Inserts a blank column for the gear menu
- if has_links || collection.last.try(:action_links).try(:any?)
+ last_item = collection.last
+ action_links = last_item && last_item.respond_to?(:action_links) && (last_item&.action_links&.is_a?(AF83::Decorator::ActionLinks) ? last_item.action_links(action) : last_item.action_links)
+ if has_links || action_links.try(:any?)
hcont << content_tag(:th, '')
end
@@ -187,86 +207,94 @@ module TableBuilderHelper
end
end
- def tbody(collection, columns, selectable, links, overhead)
- content_tag :tbody do
- collection.map do |item|
+ def tr item, columns, selectable, links, overhead, model_name, action
+ klass = "#{model_name}-#{item.id}"
+ content_tag :tr, class: klass do
+ bcont = []
+ if selectable
+ disabled = selectable.respond_to?(:call) && !selectable.call(item)
+ bcont << content_tag(
+ :td,
+ checkbox(id_name: item.try(:id), value: item.try(:id), disabled: disabled)
+ )
+ end
- content_tag :tr do
- bcont = []
+ columns.each do |column|
+ value = column.value(item)
- if selectable
- bcont << content_tag(
- :td,
- checkbox(id_name: item.try(:id), value: item.try(:id))
- )
- end
+ if column.linkable?
+ path = column.link_to(item)
+ link = link_to(value, path)
- columns.each do |column|
- value = column.value(item)
+ if overhead.empty?
+ bcont << content_tag(:td, link, title: 'Voir')
- if column.linkable?
- path = column.link_to(item)
- link = link_to(value, path)
+ else
+ i = columns.index(column)
- if overhead.empty?
- bcont << content_tag(:td, link, title: 'Voir')
+ 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
- i = columns.index(column)
+ bcont << content_tag(:td, link, title: 'Voir')
+ end
- if overhead[i].blank?
- if (i > 0) && (overhead[i - 1][:width] > 1)
- clsArrayAlt = overhead[i - 1][:cls].split
+ else
+ clsArray = overhead[columns.index(column)][:cls].split
- bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArrayAlt))
+ bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArray))
+ end
+ end
- else
- bcont << content_tag(:td, link, title: 'Voir')
- end
+ else
+ if overhead.empty?
+ bcont << content_tag(:td, value)
- else
- clsArray = overhead[columns.index(column)][:cls].split
+ else
+ i = columns.index(column)
- bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArray))
- end
- end
+ if overhead[i].blank?
+ if (i > 0) && (overhead[i - 1][:width] > 1)
+ clsArrayAlt = overhead[i - 1][:cls].split
- else
- if overhead.empty?
- bcont << content_tag(:td, value)
+ bcont << content_tag(:td, value, class: td_cls(clsArrayAlt))
else
- i = columns.index(column)
+ bcont << content_tag(:td, value)
+ end
- if overhead[i].blank?
- if (i > 0) && (overhead[i - 1][:width] > 1)
- clsArrayAlt = overhead[i - 1][:cls].split
+ else
+ clsArray = overhead[i][:cls].split
- bcont << content_tag(:td, value, class: td_cls(clsArrayAlt))
+ bcont << content_tag(:td, value, class: td_cls(clsArray))
+ end
+ end
+ end
+ end
- else
- bcont << content_tag(:td, value)
- end
+ action_links = item && item.respond_to?(:action_links) && (item.action_links.is_a?(AF83::Decorator::ActionLinks) ? item.action_links(action) : item.action_links)
- else
- clsArray = overhead[i][:cls].split
+ if links.any? || action_links.try(:any?)
+ bcont << content_tag(
+ :td,
+ build_links(item, links, action),
+ class: 'actions'
+ )
+ end
- bcont << content_tag(:td, value, class: td_cls(clsArray))
- end
- end
- end
- end
+ bcont.join.html_safe
+ end
+ end
- if links.any? || item.try(:action_links).try(:any?)
- bcont << content_tag(
- :td,
- build_links(item, links),
- class: 'actions'
- )
- end
+ def tbody(collection, columns, selectable, links, overhead, model = nil, action)
+ model_name = TableBuilderHelper.item_row_class_name collection, model
- bcont.join.html_safe
- end
+ content_tag :tbody do
+ collection.map do |item|
+ tr item, columns, selectable, links, overhead, model_name, action
end.join.html_safe
end
end
@@ -279,7 +307,7 @@ module TableBuilderHelper
end
end
- def build_links(item, links)
+ def build_links(item, links, action)
trigger = content_tag(
:div,
class: 'btn dropdown-toggle',
@@ -288,13 +316,26 @@ module TableBuilderHelper
content_tag :span, '', class: 'fa fa-cog'
end
- menu = content_tag :ul, class: 'dropdown-menu' do
- (
- CustomLinks.new(item, pundit_user, links, referential).links +
- item.action_links.select { |link| link.is_a?(Link) }
- ).map do |link|
- gear_menu_link(link)
- end.join.html_safe
+ action_links = item.action_links
+ if action_links.is_a?(AF83::Decorator::ActionLinks)
+ menu = content_tag :div, class: 'dropdown-menu' do
+ item.action_links(action).grouped_by(:primary, :secondary, :footer).map do |group, _links|
+ if _links.any?
+ content_tag :ul, class: group do
+ _links.map{|link| gear_menu_link(link)}.join.html_safe
+ end
+ end
+ end.join.html_safe
+ end
+ else
+ menu = content_tag :ul, class: 'dropdown-menu' do
+ (
+ CustomLinks.new(item, pundit_user, links, referential, workgroup).links +
+ action_links.select { |link| link.is_a?(Link) }
+ ).map do |link|
+ gear_menu_link(link)
+ end.join.html_safe
+ end
end
content_tag :div, trigger + menu, class: 'btn-group'
@@ -341,14 +382,19 @@ module TableBuilderHelper
end
end
- def checkbox(id_name:, value:)
+ def checkbox(id_name:, value:, disabled: false)
content_tag :div, '', class: 'checkbox' do
- check_box_tag(id_name, value).concat(
+ check_box_tag(id_name, value, nil, disabled: disabled).concat(
content_tag(:label, '', for: id_name)
)
end
end
+
def gear_menu_link(link)
+ klass = []
+ klass << link.extra_class if link.extra_class
+ klass << 'delete-action' if link.method == :delete
+ klass << 'disabled' if link.disabled
content_tag(
:li,
link_to(
@@ -358,7 +404,7 @@ module TableBuilderHelper
) do
link.content
end,
- class: ('delete-action' if link.method == :delete)
+ class: (klass.join(' ') if klass.present?)
)
end
@@ -367,4 +413,10 @@ module TableBuilderHelper
# cases, avoid a `NoMethodError`.
@__referential__ ||= try(:current_referential)
end
+
+ def workgroup
+ # Certain controllers don't define a `#current_referential`. In these
+ # cases, avoid a `NoMethodError`.
+ @__workgroup__ ||= try(:current_workgroup)
+ end
end
diff --git a/app/helpers/table_builder_helper/custom_links.rb b/app/helpers/table_builder_helper/custom_links.rb
index b1bb11f10..e09078be0 100644
--- a/app/helpers/table_builder_helper/custom_links.rb
+++ b/app/helpers/table_builder_helper/custom_links.rb
@@ -8,13 +8,14 @@ module TableBuilderHelper
unarchive: :put
}
- attr_reader :actions, :object, :user_context, :referential
+ attr_reader :actions, :object, :user_context, :referential, :workgroup
- def initialize(object, user_context, actions, referential = nil)
+ def initialize(object, user_context, actions, referential = nil, workgroup = nil)
@object = object
@user_context = user_context
@actions = actions
@referential = referential
+ @workgroup = workgroup
end
def links
@@ -34,7 +35,7 @@ module TableBuilderHelper
polymorph_url << action
end
- polymorph_url += URL.polymorphic_url_parts(object, referential)
+ polymorph_url += URL.polymorphic_url_parts(object, referential, workgroup)
end
def method_for_action(action)
diff --git a/app/helpers/table_builder_helper/url.rb b/app/helpers/table_builder_helper/url.rb
index a53ac5620..0e3dce0aa 100644
--- a/app/helpers/table_builder_helper/url.rb
+++ b/app/helpers/table_builder_helper/url.rb
@@ -1,6 +1,6 @@
module TableBuilderHelper
class URL
- def self.polymorphic_url_parts(item, referential)
+ def self.polymorphic_url_parts(item, referential, workgroup)
polymorph_url = []
unless item.is_a?(Calendar) || item.is_a?(Referential) || item.is_a?(ComplianceControlSet)
@@ -10,7 +10,7 @@ module TableBuilderHelper
polymorph_url << item.route.line if item.is_a?(Chouette::RoutingConstraintZone)
polymorph_url << item if item.respond_to? :line_referential
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)
+ polymorph_url << item if item.respond_to?(:stop_points) || item.is_a?(Chouette::TimeTable) || item.is_a?(Chouette::PurchaseWindow)
elsif item.respond_to? :referential
if item.respond_to? :workbench
polymorph_url << item.workbench
@@ -20,6 +20,7 @@ module TableBuilderHelper
end
end
else
+ polymorph_url << item.workgroup if item.respond_to? :workgroup
polymorph_url << item
end
diff --git a/app/helpers/time_tables_helper.rb b/app/helpers/time_tables_helper.rb
index b380a2b0a..1be1fa5a1 100644
--- a/app/helpers/time_tables_helper.rb
+++ b/app/helpers/time_tables_helper.rb
@@ -84,7 +84,7 @@ module TimeTablesHelper
end unless first.wday == first_weekday
first.upto(last) do |cur|
- cell_text, cell_attrs = block.call(cur)
+ cell_text, cell_attrs = yield cur
cell_text ||= cur.mday
cell_attrs ||= {}
cell_attrs[:headers] = th_id(cur, options[:table_id])
diff --git a/app/helpers/vehicle_journeys_helper.rb b/app/helpers/vehicle_journeys_helper.rb
index 6877abd11..1cc865c62 100644
--- a/app/helpers/vehicle_journeys_helper.rb
+++ b/app/helpers/vehicle_journeys_helper.rb
@@ -1,5 +1,5 @@
module VehicleJourneysHelper
-
+
def vehicle_name( vehicle)
if !vehicle.published_journey_name.blank?
vehicle.published_journey_name.first(8)
@@ -11,11 +11,11 @@ module VehicleJourneysHelper
vehicle.id
end
end
-
+
def missing_time_check( is_present)
return "missing" if (is_present && is_present.departure_time.nil?)
end
-
+
def vehicle_departure(vehicle, departure_time=nil)
unless departure_time
first_vjas = vehicle.vehicle_journey_at_stops.first
@@ -24,7 +24,7 @@ module VehicleJourneysHelper
end
l(departure_time, :format => :hour).gsub( / /, ' ')
end
-
+
def vehicle_title(vehicle, journey_frequency=nil)
return t("vehicle_journeys.vehicle_journey#{'_frequency' if vehicle.frequency?}.title_stopless", :name => vehicle_name( vehicle)) if vehicle.vehicle_journey_at_stops.empty?
first_vjas = vehicle.vehicle_journey_at_stops.first
@@ -40,7 +40,7 @@ module VehicleJourneysHelper
:time => vehicle_departure(vehicle, (journey_frequency ? journey_frequency.first_departure_time : nil )))
end
end
-
+
def route_journey_pattern_label_pairs route
route
.journey_patterns
@@ -50,7 +50,7 @@ module VehicleJourneysHelper
def edit_vehicle_title( vehicle)
return t('vehicle_journeys.edit.title_stopless', :name => vehicle_name( vehicle)) if vehicle.vehicle_journey_at_stops.empty?
first_vjas = vehicle.vehicle_journey_at_stops.first
- t('vehicle_journeys.edit.title',
+ t('vehicle_journeys.edit.title',
:name => vehicle_name( vehicle),
:stop => first_vjas.stop_point.stop_area.name,
:time => vehicle_departure(vehicle))
@@ -59,6 +59,14 @@ module VehicleJourneysHelper
def exist_vehicle_journeys?(route)
route.vehicle_journeys.count > 0
end
-
-end
+ def table_builder_column_for_stop_area stop_area
+ return nil unless stop_area
+ TableBuilderHelper::Column.new(
+ name: stop_area.name,
+ attribute: Proc.new {|v| v.vehicle_journey_at_stops.find{|vjas| vjas.stop_point.stop_area_id == stop_area.id}&.departure },
+ sortable: false
+ )
+ end
+
+end
diff --git a/app/inputs/color_select_input.rb b/app/inputs/color_select_input.rb
new file mode 100644
index 000000000..f92c80a22
--- /dev/null
+++ b/app/inputs/color_select_input.rb
@@ -0,0 +1,44 @@
+class ColorSelectInput < SimpleForm::Inputs::CollectionInput
+ enable :placeholder
+
+ def input(wrapper_options = {})
+ selected_color = object.send(attribute_name)
+ label = if selected_color
+ collection.find{|i| i.is_a?(Enumerable) && i.last == selected_color}.try(:first)
+ end
+
+ out = @builder.hidden_field attribute_name, value: selected_color
+ tag_name = ActionView::Helpers::Tags::Base.new( ActiveModel::Naming.param_key(object), attribute_name, :dummy ).send(:tag_name)
+ select = <<-eos
+ <div class="dropdown color_selector">
+ <button type='button' class="btn btn-default dropdown-toggle" data-toggle='dropdown' aria-haspopup='true' aria-expanded='true'
+ ><span
+ class='fa fa-circle mr-xs'
+ style='color: #{selected_color == nil ? 'transparent' : selected_color}'
+ >
+ </span>
+ #{label}
+ <span class='caret'></span>
+ </button>
+
+ <div class="form-group dropdown-menu" aria-labelledby='dpdwn_color'>
+ eos
+
+ collection.each do |color|
+ name = nil
+ name, color = color if color.is_a?(Enumerable)
+ select += <<-eos
+ <span class="radio" key=#{color} >
+ <label>
+ <input type='radio' class='color_selector' value='#{color}' data-for='#{tag_name}'/>
+ <span class='fa fa-circle mr-xs' style='color: #{color == nil ? 'transparent' : color}'></span>
+ #{name}
+ </label>
+ </span>
+ eos
+ end
+ select += "</div></div>"
+
+ out + select.html_safe
+ end
+end
diff --git a/app/javascript/date_filters/index.js b/app/javascript/date_filters/index.js
index ee892a7fe..432166008 100644
--- a/app/javascript/date_filters/index.js
+++ b/app/javascript/date_filters/index.js
@@ -3,6 +3,7 @@ import complianceControlSetDF from './compliance_control_set'
import complianceCheckSetDF from './compliance_check_set'
import timetableDF from './time_table'
import importDF from './import'
+import purchaseWindowDF from './purchase_window'
import workbenchDF from './workbench'
const DateFilters = {
@@ -11,6 +12,7 @@ const DateFilters = {
complianceControlSetDF,
importDF,
timetableDF,
+ purchaseWindowDF,
workbenchDF
}
diff --git a/app/javascript/date_filters/purchase_window.js b/app/javascript/date_filters/purchase_window.js
new file mode 100644
index 000000000..2c46b6d52
--- /dev/null
+++ b/app/javascript/date_filters/purchase_window.js
@@ -0,0 +1,5 @@
+import DateFilter from '../helpers/date_filters'
+
+const purchaseWindowDF = new DateFilter("purchase_window_filter_btn", "Tous les champs du filtre de date doivent être remplis", "q_contains_date_NUMi")
+
+export default purchaseWindowDF \ No newline at end of file
diff --git a/app/javascript/helpers/master_slave.coffee b/app/javascript/helpers/master_slave.coffee
new file mode 100644
index 000000000..81bebe36a
--- /dev/null
+++ b/app/javascript/helpers/master_slave.coffee
@@ -0,0 +1,16 @@
+class MasterSlave
+ constructor: (selector)->
+ $(selector).find('[data-master]').each (i, slave)->
+ $slave = $(slave)
+ master = $($slave.data().master)
+ $slave.find("input:disabled, select:disabled").attr "data-slave-force-disabled", "true"
+ toggle = ->
+ val = master.filter(":checked").val() if master.filter("[type=radio]").length > 0
+ val ||= master.val()
+ selected = val == $slave.data().value
+ $slave.toggle selected
+ $slave.find("input, select").filter(":not([data-slave-force-disabled])").attr "disabled", !selected
+ master.change toggle
+ toggle()
+
+export default MasterSlave
diff --git a/app/javascript/helpers/routes_map.coffee b/app/javascript/helpers/routes_map.coffee
new file mode 100644
index 000000000..6834406fc
--- /dev/null
+++ b/app/javascript/helpers/routes_map.coffee
@@ -0,0 +1,161 @@
+class RoutesMap
+ constructor: (@target)->
+ @initMap()
+ @area = []
+ @seenStopIds = []
+ @routes = {}
+
+ initMap: ->
+ @map = new ol.Map
+ target: @target,
+ layers: [ new ol.layer.Tile(source: new ol.source.OSM()) ]
+ controls: [ new ol.control.ScaleLine(), new ol.control.Zoom(), new ol.control.ZoomSlider() ],
+ interactions: ol.interaction.defaults(zoom: true)
+ view: new ol.View()
+
+ addRoutes: (routes)->
+ for route in routes
+ @addRoute route
+
+ addRoute: (route)->
+ geoColPts = []
+ geoColLns = []
+ @routes[route.id] = route if route.id
+ stops = route.stops || route
+ geoColEdges = [
+ new ol.Feature({
+ geometry: new ol.geom.Point(ol.proj.fromLonLat([parseFloat(stops[0].longitude), parseFloat(stops[0].latitude)]))
+ }),
+ new ol.Feature({
+ geometry: new ol.geom.Point(ol.proj.fromLonLat([parseFloat(stops[stops.length - 1].longitude), parseFloat(stops[stops.length - 1].latitude)]))
+ })
+ ]
+
+ prevStop = null
+ stops.forEach (stop, i) =>
+ if stop.longitude && stop.latitude
+ if prevStop
+ geoColLns.push new ol.Feature
+ geometry: new ol.geom.LineString([
+ ol.proj.fromLonLat([parseFloat(prevStop.longitude), parseFloat(prevStop.latitude)]),
+ ol.proj.fromLonLat([parseFloat(stop.longitude), parseFloat(stop.latitude)])
+ ])
+ prevStop = stop
+
+ geoColPts.push(new ol.Feature({
+ geometry: new ol.geom.Point(ol.proj.fromLonLat([parseFloat(stop.longitude), parseFloat(stop.latitude)]))
+ }))
+ unless @seenStopIds.indexOf(stop.stoparea_id) > 0
+ @area.push [parseFloat(stop.longitude), parseFloat(stop.latitude)]
+ @seenStopIds.push stop.stoparea_id
+
+ vectorPtsLayer = new ol.layer.Vector({
+ source: new ol.source.Vector({
+ features: geoColPts
+ }),
+ style: @defaultStyles(),
+ zIndex: 2
+ })
+ route.vectorPtsLayer = vectorPtsLayer if route.id
+ vectorEdgesLayer = new ol.layer.Vector({
+ source: new ol.source.Vector({
+ features: geoColEdges
+ }),
+ style: @edgeStyles(),
+ zIndex: 3
+ })
+ route.vectorEdgesLayer = vectorEdgesLayer if route.id
+ vectorLnsLayer = new ol.layer.Vector({
+ source: new ol.source.Vector({
+ features: geoColLns
+ }),
+ style: [@lineStyle()],
+ zIndex: 1
+ })
+ route.vectorLnsLayer = vectorLnsLayer if route.id
+ @map.addLayer vectorPtsLayer
+ @map.addLayer vectorEdgesLayer
+ @map.addLayer vectorLnsLayer
+
+ lineStyle: (highlighted=false)->
+ new ol.style.Style
+ stroke: new ol.style.Stroke
+ color: if highlighted then "#ed7f00" else '#007fbb'
+ width: 3
+
+ edgeStyles: (highlighted=false)->
+ new ol.style.Style
+ image: new ol.style.Circle
+ radius: 5
+ stroke: new ol.style.Stroke
+ color: if highlighted then "#ed7f00" else '#007fbb'
+ width: 2
+ fill: new ol.style.Fill
+ color: if highlighted then "#ed7f00" else '#007fbb'
+ width: 2
+
+ defaultStyles: (highlighted=false)->
+ new ol.style.Style
+ image: new ol.style.Circle
+ radius: 4
+ stroke: new ol.style.Stroke
+ color: if highlighted then "#ed7f00" else '#007fbb'
+ width: 2
+ fill: new ol.style.Fill
+ color: '#ffffff'
+ width: 2
+
+ addRoutesLabels: ->
+ labelsContainer = $("<ul class='routes-labels'></ul>")
+ labelsContainer.appendTo $("##{@target}")
+ @vectorPtsLayer = null
+ @vectorEdgesLayer = null
+ @vectorLnsLayer = null
+ Object.keys(@routes).forEach (id)=>
+ route = @routes[id]
+ label = $("<li>#{route.name}</ul>")
+ label.appendTo labelsContainer
+ label.mouseleave =>
+ route.vectorPtsLayer.setStyle @defaultStyles(false)
+ route.vectorEdgesLayer.setStyle @edgeStyles(false)
+ route.vectorLnsLayer.setStyle @lineStyle(false)
+ route.vectorPtsLayer.setZIndex 2
+ route.vectorEdgesLayer.setZIndex 3
+ route.vectorLnsLayer.setZIndex 1
+ @fitZoom()
+ label.mouseenter =>
+ route.vectorPtsLayer.setStyle @defaultStyles(true)
+ route.vectorEdgesLayer.setStyle @edgeStyles(true)
+ route.vectorLnsLayer.setStyle @lineStyle(true)
+ route.vectorPtsLayer.setZIndex 11
+ route.vectorEdgesLayer.setZIndex 12
+ route.vectorLnsLayer.setZIndex 10
+ @fitZoom(route)
+
+ fitZoom: (route)->
+ if route
+ area = []
+ route.stops.forEach (stop, i) =>
+ area.push [parseFloat(stop.longitude), parseFloat(stop.latitude)]
+ else
+ area = @area
+ boundaries = ol.extent.applyTransform(
+ ol.extent.boundingExtent(area), ol.proj.getTransform('EPSG:4326', 'EPSG:3857')
+ )
+ @map.getView().fit boundaries, @map.getSize()
+ tooCloseToBounds = false
+ mapBoundaries = @map.getView().calculateExtent @map.getSize()
+ mapWidth = mapBoundaries[2] - mapBoundaries[0]
+ mapHeight = mapBoundaries[3] - mapBoundaries[1]
+ marginSize = 0.1
+ heightMargin = marginSize * mapHeight
+ widthMargin = marginSize * mapWidth
+ tooCloseToBounds = tooCloseToBounds || (boundaries[0] - mapBoundaries[0]) < widthMargin
+ tooCloseToBounds = tooCloseToBounds || (mapBoundaries[2] - boundaries[2]) < widthMargin
+ tooCloseToBounds = tooCloseToBounds || (boundaries[1] - mapBoundaries[1]) < heightMargin
+ tooCloseToBounds = tooCloseToBounds || (mapBoundaries[3] - boundaries[3]) < heightMargin
+ if tooCloseToBounds
+ @map.getView().setZoom(@map.getView().getZoom() - 1)
+
+
+export default RoutesMap
diff --git a/app/javascript/helpers/save_button.js b/app/javascript/helpers/save_button.js
new file mode 100644
index 000000000..7e0bd5bbe
--- /dev/null
+++ b/app/javascript/helpers/save_button.js
@@ -0,0 +1,47 @@
+import React, { PropTypes, Component } from 'react'
+
+export default class SaveButton extends Component{
+ constructor(props){
+ super(props)
+ }
+
+ btnDisabled(){
+ return !this.props.status.fetchSuccess || this.props.status.isFetching
+ }
+
+ btnClass(){
+ let className = ['btn btn-default']
+ if(this.btnDisabled()){
+ className.push('disabled')
+ }
+ return className.join(' ')
+ }
+
+ render() {
+ if (!this.hasPolicy()) {
+ return false
+ }else{
+ return (
+ <div className='row mt-md'>
+ <div className='col-lg-12 text-right'>
+ <form className={this.formClassName() + ' formSubmitr ml-xs'} onSubmit={e => {e.preventDefault()}}>
+ <div className="btn-group sticky-actions">
+ <button
+ className={this.btnClass()}
+ type='button'
+ disabled={this.btnDisabled()}
+ onClick={e => {
+ e.preventDefault()
+ this.props.editMode ? this.submitForm() : this.props.onEnterEditMode()
+ }}
+ >
+ {this.props.editMode ? "Valider" : "Editer"}
+ </button>
+ </div>
+ </form>
+ </div>
+ </div>
+ )
+ }
+ }
+}
diff --git a/app/javascript/helpers/stop_area_header_manager.js b/app/javascript/helpers/stop_area_header_manager.js
new file mode 100644
index 000000000..5b18e2f63
--- /dev/null
+++ b/app/javascript/helpers/stop_area_header_manager.js
@@ -0,0 +1,56 @@
+import React, { Component } from 'react'
+
+export default class StopAreaHeaderManager {
+ constructor(ids_list, stopPointsList, features) {
+ this.ids_list = ids_list
+ this.stopPointsList = stopPointsList
+ this.features = features
+ }
+
+ hasFeature(key) {
+ return this.features[key]
+ }
+
+ stopPointHeader(object_id) {
+ let index = this.ids_list.indexOf(object_id)
+ let sp = this.stopPointsList[index]
+ let showHeadline = this.showHeader(object_id)
+ return (
+ <div
+ className={(showHeadline) ? 'headlined' : ''}
+ data-headline={showHeadline}
+ title={sp.city_name ? sp.city_name + ' (' + sp.zip_code +')' : ""}
+ >
+ <span>
+ <span>
+ {sp.name}
+ {sp.time_zone_formatted_offset && <span className="small">
+ &nbsp;({sp.time_zone_formatted_offset})
+ </span>}
+ {sp.area_kind == 'non_commercial' && <span className="fa fa-question-circle" title={sp.area_type_i18n}>
+ </span>}
+ </span>
+ </span>
+ </div>
+ )
+ }
+
+ showHeader(object_id) {
+ let showHeadline = false
+ let headline = ""
+ let attribute_to_check = this.hasFeature('long_distance_routes') ? "country_code" : "city_name"
+ let index = this.ids_list.indexOf(object_id)
+ let sp = this.stopPointsList[index]
+ let previousBreakpoint = this.stopPointsList[index - 1]
+ if(sp == undefined){
+ console.log("STOP_POINT NOT FOUND: " + object_id)
+ console.log("AVAILABLE IDS:" + this.ids_list)
+ return
+ }
+ if(index == 0 || (sp[attribute_to_check] != previousBreakpoint[attribute_to_check])){
+ showHeadline = true
+ headline = this.hasFeature('long_distance_routes') ? sp.country_name : sp.city_name
+ }
+ return showHeadline ? headline : ""
+ }
+}
diff --git a/app/javascript/journey_patterns/actions/index.js b/app/javascript/journey_patterns/actions/index.js
index 4ff3f77ea..a70a2e6f2 100644
--- a/app/javascript/journey_patterns/actions/index.js
+++ b/app/javascript/journey_patterns/actions/index.js
@@ -64,6 +64,11 @@ const actions = {
type : 'DELETE_JOURNEYPATTERN',
index,
}),
+ updateJourneyPatternCosts : (index, costs) => ({
+ type : 'UPDATE_JOURNEYPATTERN_COSTS',
+ index,
+ costs
+ }),
closeModal : () => ({
type : 'CLOSE_MODAL'
}),
@@ -194,15 +199,13 @@ const actions = {
}
})
}
- journeyPatterns.push({
- name: val.name,
- object_id: val.object_id,
- short_id: val.short_id,
- published_name: val.published_name,
- registration_number: val.registration_number,
- stop_points: val.route_short_description.stop_points,
- deletable: false
- })
+ journeyPatterns.push(
+ _.assign({}, val, {
+ stop_points: val.route_short_description.stop_points,
+ costs: val.costs || {},
+ deletable: false
+ })
+ )
}
}
window.currentItemsLength = journeyPatterns.length
@@ -217,4 +220,4 @@ const actions = {
}
}
-export default actions \ No newline at end of file
+export default actions
diff --git a/app/javascript/journey_patterns/components/ConfirmModal.js b/app/javascript/journey_patterns/components/ConfirmModal.js
index 2cc1bef44..ccd0a9384 100644
--- a/app/javascript/journey_patterns/components/ConfirmModal.js
+++ b/app/javascript/journey_patterns/components/ConfirmModal.js
@@ -1,4 +1,6 @@
-import React, { PropTypes } from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
+
export default function ConfirmModal({dispatch, modal, onModalAccept, onModalCancel, journeyPatterns}) {
return (
diff --git a/app/javascript/journey_patterns/components/CreateModal.js b/app/javascript/journey_patterns/components/CreateModal.js
index d0eff6e57..a6c1b608a 100644
--- a/app/javascript/journey_patterns/components/CreateModal.js
+++ b/app/javascript/journey_patterns/components/CreateModal.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../actions'
export default class CreateModal extends Component {
diff --git a/app/javascript/journey_patterns/components/EditModal.js b/app/javascript/journey_patterns/components/EditModal.js
index e7ce24aa1..c960cb41c 100644
--- a/app/javascript/journey_patterns/components/EditModal.js
+++ b/app/javascript/journey_patterns/components/EditModal.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../actions'
export default class EditModal extends Component {
@@ -36,7 +37,6 @@ export default class EditModal extends Component {
{this.renderModalTitle()}
<span type="button" className="close modal-close" data-dismiss="modal">&times;</span>
</div>
-
{(this.props.modal.type == 'edit') && (
<form>
<div className='modal-body'>
@@ -85,6 +85,16 @@ export default class EditModal extends Component {
</div>
</div>
</div>
+ <div>
+ <label className='control-label'>Signature métier</label>
+ <input
+ type='text'
+ ref='checksum'
+ className='form-control'
+ disabled='disabled'
+ defaultValue={this.props.modal.modalProps.journeyPattern.checksum}
+ />
+ </div>
</div>
{
this.props.editMode &&
@@ -121,4 +131,4 @@ EditModal.propTypes = {
modal: PropTypes.object,
onModalClose: PropTypes.func.isRequired,
saveModal: PropTypes.func.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/journey_patterns/components/JourneyPattern.js b/app/javascript/journey_patterns/components/JourneyPattern.js
index d4c9816ec..35765b99a 100644
--- a/app/javascript/journey_patterns/components/JourneyPattern.js
+++ b/app/javascript/journey_patterns/components/JourneyPattern.js
@@ -1,10 +1,21 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../actions'
export default class JourneyPattern extends Component{
constructor(props){
super(props)
- this.previousCity = undefined
+ this.previousSpId = undefined
+ this.updateCosts = this.updateCosts.bind(this)
+ }
+
+ updateCosts(e) {
+ let costs = {
+ [e.target.dataset.costsKey]: {
+ [e.target.name]: parseFloat(e.target.value)
+ }
+ }
+ this.props.onUpdateJourneyPatternCosts(costs)
}
vehicleJourneyURL(jpOid) {
@@ -16,16 +27,20 @@ export default class JourneyPattern extends Component{
)
}
- cityNameChecker(sp) {
- let bool = false
- if(sp.city_name != this.previousCity){
- bool = true
- this.previousCity = sp.city_name
- }
+ hasFeature(key) {
+ return this.props.status.features[key]
+ }
+
+ cityNameChecker(sp, i) {
+ return this.props.journeyPatterns.showHeader((sp.stop_area_object_id || sp.object_id) + "-" + i)
+ }
+
+ spNode(sp, headlined){
return (
<div
- className={(bool) ? 'headlined' : ''}
+ className={(headlined) ? 'headlined' : ''}
>
+ <div className={'link '}></div>
<span className='has_radio'>
<input
onChange = {(e) => this.props.onCheckboxChange(e)}
@@ -59,19 +74,60 @@ export default class JourneyPattern extends Component{
return !this.props.status.policy[`journey_patterns.${action}`]
}
- render() {
- this.previousCity = undefined
+ totals(){
+ let totalTime = 0
+ let totalDistance = 0
+ let from = null
+ this.props.value.stop_points.map((stopPoint, i) =>{
+ if(from && stopPoint.checked){
+ let [costsKey, costs, time, distance] = this.getTimeAndDistanceBetweenStops(from, stopPoint.id)
+ totalTime += time
+ totalDistance += distance
+ }
+ if(stopPoint.checked){
+ from = stopPoint.id
+ }
+ })
+ return [this.formatTime(totalTime), this.formatDistance(totalDistance)]
+ }
- return (
- <div className={'t2e-item' + (this.props.value.deletable ? ' disabled' : '') + (this.props.value.object_id ? '' : ' to_record') + (this.props.value.errors ? ' has-error': '')}>
- {/* Errors */}
- {/* this.props.value.errors ? this.getErrors(this.props.value.errors) : '' */}
+ getTimeAndDistanceBetweenStops(from, to){
+ let costsKey = from + "-" + to
+ let costs = this.props.value.costs[costsKey] || {distance: 0, time: 0}
+ let time = costs['time'] || 0
+ let distance = costs['distance'] || 0
+ return [costsKey, costs, time, distance]
+ }
+
+ formatDistance(distance){
+ return parseFloat(Math.round(distance * 100) / 100).toFixed(2) + " km"
+ }
+
+ formatTime(time){
+ if(time < 60){
+ return time + " min"
+ }
+ else{
+ let hours = parseInt(time/60)
+ return hours + " h " + (time - 60*hours)
+ }
+ }
+ render() {
+ this.previousSpId = undefined
+ let [totalTime, totalDistance] = this.totals()
+ return (
+ <div className={'t2e-item' + (this.props.value.deletable ? ' disabled' : '') + (this.props.value.object_id ? '' : ' to_record') + (this.props.value.errors ? ' has-error': '') + (this.hasFeature('costs_in_journey_patterns') ? ' with-costs' : '')}>
<div className='th'>
<div className='strong mb-xs'>{this.props.value.object_id ? this.props.value.short_id : '-'}</div>
<div>{this.props.value.registration_number}</div>
<div>{actions.getChecked(this.props.value.stop_points).length} arrêt(s)</div>
-
+ {this.hasFeature('costs_in_journey_patterns') &&
+ <div className="small row totals">
+ <span className="col-md-6"><i className="fa fa-arrows-h"></i>{totalDistance}</span>
+ <span className="col-md-6"><i className="fa fa-clock-o"></i>{totalTime}</span>
+ </div>
+ }
<div className={this.props.value.deletable ? 'btn-group disabled' : 'btn-group'}>
<div
className={this.props.value.deletable ? 'btn dropdown-toggle disabled' : 'btn dropdown-toggle'}
@@ -80,10 +136,9 @@ export default class JourneyPattern extends Component{
<span className='fa fa-cog'></span>
</div>
<ul className='dropdown-menu'>
- <li className={this.isDisabled('update') ? 'disabled' : ''}>
+ <li>
<button
type='button'
- disabled={this.isDisabled('update')}
onClick={this.props.onOpenEditModal}
data-toggle='modal'
data-target='#JourneyPatternModal'
@@ -112,9 +167,40 @@ export default class JourneyPattern extends Component{
</div>
{this.props.value.stop_points.map((stopPoint, i) =>{
+ let costs = null
+ let costsKey = null
+ let time = null
+ let distance = null
+ let time_in_words = null
+ if(this.previousSpId && stopPoint.checked){
+ [costsKey, costs, time, distance] = this.getTimeAndDistanceBetweenStops(this.previousSpId, stopPoint.id)
+ time_in_words = this.formatTime(time)
+ }
+ if(stopPoint.checked){
+ this.previousSpId = stopPoint.id
+ }
+ let headlined = this.cityNameChecker(stopPoint, i)
return (
- <div key={i} className='td'>
- {this.cityNameChecker(stopPoint)}
+ <div key={i} className={(stopPoint.checked ? 'activated' : 'deactivated') + (this.props.editMode ? ' edit-mode' : '')}>
+ <div className={'td' + (headlined ? ' with-headline' : '')}>
+ {this.spNode(stopPoint, headlined)}
+ </div>
+ {this.hasFeature('costs_in_journey_patterns') && costs && <div className='costs' id={'costs-' + this.props.value.id + '-' + costsKey }>
+ {this.props.editMode && <div>
+ <p>
+ <input type="number" value={costs['distance'] || 0} min='0' name="distance" step="0.01" onChange={this.updateCosts} data-costs-key={costsKey}/>
+ <span>km</span>
+ </p>
+ <p>
+ <input type="number" value={costs['time'] || 0} min='0' name="time" onChange={this.updateCosts} data-costs-key={costsKey}/>
+ <span>min</span>
+ </p>
+ </div>}
+ {!this.props.editMode && <div>
+ <p><i className="fa fa-arrows-h"></i>{this.formatDistance(costs['distance'] || 0)}</p>
+ <p><i className="fa fa-clock-o"></i>{time_in_words}</p>
+ </div>}
+ </div>}
</div>
)
})}
@@ -128,5 +214,6 @@ JourneyPattern.propTypes = {
index: PropTypes.number,
onCheckboxChange: PropTypes.func.isRequired,
onOpenEditModal: PropTypes.func.isRequired,
- onDeleteJourneyPattern: PropTypes.func.isRequired
-} \ No newline at end of file
+ onDeleteJourneyPattern: PropTypes.func.isRequired,
+ journeyPatterns: PropTypes.object.isRequired
+}
diff --git a/app/javascript/journey_patterns/components/JourneyPatterns.js b/app/javascript/journey_patterns/components/JourneyPatterns.js
index 4b2badabb..31727fefc 100644
--- a/app/javascript/journey_patterns/components/JourneyPatterns.js
+++ b/app/javascript/journey_patterns/components/JourneyPatterns.js
@@ -1,16 +1,23 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import JourneyPattern from './JourneyPattern'
-
+import StopAreaHeaderManager from '../../helpers/stop_area_header_manager'
export default class JourneyPatterns extends Component {
constructor(props){
super(props)
- this.previousCity = undefined
+ this.headerManager = new StopAreaHeaderManager(
+ _.map(this.props.stopPointsList, (sp, i)=>{return sp.stop_area_object_id + "-" + i}),
+ this.props.stopPointsList,
+ this.props.status.features
+ )
}
+
componentDidMount() {
this.props.onLoadFirstPage()
}
+
componentDidUpdate(prevProps, prevState) {
if(this.props.status.isFetching == false){
$('.table-2entries').each(function() {
@@ -54,21 +61,12 @@ export default class JourneyPatterns extends Component {
}
}
- cityNameChecker(sp) {
- let bool = false
- if(sp.city_name != this.previousCity){
- bool = true
- this.previousCity = sp.city_name
- }
- return (
- <div
- className={(bool) ? 'headlined' : ''}
- data-headline={(bool) ? sp.city_name : ''}
- title={sp.city_name + ' (' + sp.zip_code +')'}
- >
- <span><span>{sp.name}</span></span>
- </div>
- )
+ showHeader(object_id) {
+ return this.headerManager.showHeader(object_id)
+ }
+
+ hasFeature(key) {
+ return this.props.status.features[key]
}
render() {
@@ -115,8 +113,8 @@ export default class JourneyPatterns extends Component {
</div>
{this.props.stopPointsList.map((sp, i) =>{
return (
- <div key={i} className='td'>
- {this.cityNameChecker(sp)}
+ <div key={i} className={'td' + (this.hasFeature('costs_in_journey_patterns') ? ' with-costs' : '')}>
+ {this.headerManager.stopPointHeader(sp.stop_area_object_id + "-" + i)}
</div>
)
})}
@@ -131,8 +129,10 @@ export default class JourneyPatterns extends Component {
onCheckboxChange= {(e) => this.props.onCheckboxChange(e, index)}
onOpenEditModal= {() => this.props.onOpenEditModal(index, journeyPattern)}
onDeleteJourneyPattern={() => this.props.onDeleteJourneyPattern(index)}
+ onUpdateJourneyPatternCosts={(costs) => this.props.onUpdateJourneyPatternCosts(index, costs)}
status= {this.props.status}
editMode= {this.props.editMode}
+ journeyPatterns= {this}
/>
)}
</div>
@@ -152,4 +152,4 @@ JourneyPatterns.propTypes = {
onCheckboxChange: PropTypes.func.isRequired,
onLoadFirstPage: PropTypes.func.isRequired,
onOpenEditModal: PropTypes.func.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/journey_patterns/components/Navigate.js b/app/javascript/journey_patterns/components/Navigate.js
index f2fdd668f..78f324a7d 100644
--- a/app/javascript/journey_patterns/components/Navigate.js
+++ b/app/javascript/journey_patterns/components/Navigate.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../actions'
export default function Navigate({ dispatch, journeyPatterns, pagination, status }) {
diff --git a/app/javascript/journey_patterns/components/SaveJourneyPattern.js b/app/javascript/journey_patterns/components/SaveJourneyPattern.js
index d071fa542..4bb6a73a0 100644
--- a/app/javascript/journey_patterns/components/SaveJourneyPattern.js
+++ b/app/javascript/journey_patterns/components/SaveJourneyPattern.js
@@ -1,34 +1,19 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import SaveButton from '../../helpers/save_button'
import actions from '../actions'
-export default class SaveJourneyPattern extends Component {
- constructor(props){
- super(props)
+export default class SaveJourneyPattern extends SaveButton {
+ hasPolicy(){
+ return this.props.status.policy['journey_patterns.update'] == true
}
- render() {
- if(this.props.status.policy['journey_patterns.update'] == false) {
- return false
- }else{
- return (
- <div className='row mt-md'>
- <div className='col-lg-12 text-right'>
- <form className='jp_collection formSubmitr ml-xs' onSubmit={e => {e.preventDefault()}}>
- <button
- className='btn btn-default'
- type='button'
- onClick={e => {
- e.preventDefault()
- this.props.editMode ? this.props.onSubmitJourneyPattern(this.props.dispatch, this.props.journeyPatterns) : this.props.onEnterEditMode()
- }}
- >
- {this.props.editMode ? "Valider" : "Editer"}
- </button>
- </form>
- </div>
- </div>
- )
- }
+ formClassName(){
+ return 'jp_collection'
+ }
+
+ submitForm(){
+ this.props.onSubmitJourneyPattern(this.props.dispatch, this.props.journeyPatterns)
}
}
@@ -36,4 +21,4 @@ SaveJourneyPattern.propTypes = {
journeyPatterns: PropTypes.array.isRequired,
status: PropTypes.object.isRequired,
page: PropTypes.number.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/journey_patterns/containers/JourneyPatternList.js b/app/javascript/journey_patterns/containers/JourneyPatternList.js
index d98734407..d338345f2 100644
--- a/app/javascript/journey_patterns/containers/JourneyPatternList.js
+++ b/app/javascript/journey_patterns/containers/JourneyPatternList.js
@@ -25,7 +25,10 @@ const mapDispatchToProps = (dispatch) => {
},
onDeleteJourneyPattern: (index) =>{
dispatch(actions.deleteJourneyPattern(index))
- }
+ },
+ onUpdateJourneyPatternCosts: (index, costs) =>{
+ dispatch(actions.updateJourneyPatternCosts(index, costs))
+ },
}
}
diff --git a/app/javascript/journey_patterns/reducers/journeyPatterns.js b/app/javascript/journey_patterns/reducers/journeyPatterns.js
index 0bbcba976..1ce069522 100644
--- a/app/javascript/journey_patterns/reducers/journeyPatterns.js
+++ b/app/javascript/journey_patterns/reducers/journeyPatterns.js
@@ -17,6 +17,7 @@ const journeyPattern = (state = {}, action) =>{
published_name: action.data.published_name.value,
registration_number: action.data.registration_number.value,
stop_points: stopPoints,
+ costs: {},
deletable: false
}
case 'UPDATE_CHECKBOX_VALUE':
@@ -67,6 +68,19 @@ export default function journeyPatterns (state = [], action) {
return j
}
})
+ case 'UPDATE_JOURNEYPATTERN_COSTS':
+ return state.map((j, i) =>{
+ if(i == action.index) {
+ const new_costs = Object.assign({}, j.costs)
+ Object.keys(action.costs).map((key) => {
+ let new_costs_for_key = Object.assign({}, j.costs[key] || {}, action.costs[key])
+ new_costs[key] = new_costs_for_key
+ })
+ return _.assign({}, j, {costs: new_costs})
+ } else {
+ return j
+ }
+ })
case 'ADD_JOURNEYPATTERN':
return [
journeyPattern(state, action),
@@ -87,4 +101,4 @@ export default function journeyPatterns (state = [], action) {
default:
return state
}
-} \ No newline at end of file
+}
diff --git a/app/javascript/packs/calendars/edit.js b/app/javascript/packs/calendars/edit.js
new file mode 100644
index 000000000..bd09657ec
--- /dev/null
+++ b/app/javascript/packs/calendars/edit.js
@@ -0,0 +1,74 @@
+import React from 'react'
+import { render } from 'react-dom'
+import { Provider } from 'react-redux'
+import { createStore } from 'redux'
+import timeTablesApp from '../../time_tables/reducers'
+import App from '../../time_tables/containers/App'
+import clone from '../../helpers/clone'
+
+const actionType = clone(window, "actionType", true)
+
+// logger, DO NOT REMOVE
+// var applyMiddleware = require('redux').applyMiddleware
+// var createLogger = require('redux-logger')
+// var thunkMiddleware = require('redux-thunk').default
+// var promise = require('redux-promise')
+
+let initialState = {
+ status: {
+ actionType: actionType,
+ policy: window.perms,
+ fetchSuccess: true,
+ isFetching: false
+ },
+ timetable: {
+ current_month: [],
+ current_periode_range: '',
+ periode_range: [],
+ time_table_periods: [],
+ time_table_dates: []
+ },
+ metas: {
+ comment: '',
+ day_types: [],
+ initial_tags: []
+ },
+ pagination: {
+ stateChanged: false,
+ currentPage: '',
+ periode_range: []
+ },
+ modal: {
+ type: '',
+ modalProps: {
+ active: false,
+ begin: {
+ day: '01',
+ month: '01',
+ year: String(new Date().getFullYear())
+ },
+ end: {
+ day: '01',
+ month: '01',
+ year: String(new Date().getFullYear())
+ },
+ index: false,
+ error: ''
+ },
+ confirmModal: {}
+ }
+}
+// const loggerMiddleware = createLogger()
+
+let store = createStore(
+ timeTablesApp,
+ initialState,
+ // applyMiddleware(thunkMiddleware, promise, loggerMiddleware)
+)
+
+render(
+ <Provider store={store}>
+ <App />
+ </Provider>,
+ document.getElementById('periods')
+)
diff --git a/app/javascript/packs/journey_patterns/index.js b/app/javascript/packs/journey_patterns/index.js
index fde28b45d..367a8830f 100644
--- a/app/javascript/packs/journey_patterns/index.js
+++ b/app/javascript/packs/journey_patterns/index.js
@@ -16,6 +16,7 @@ var initialState = {
editMode: false,
status: {
policy: window.perms,
+ features: window.features,
fetchSuccess: true,
isFetching: false
},
diff --git a/app/javascript/packs/referential_lines/show.js b/app/javascript/packs/referential_lines/show.js
new file mode 100644
index 000000000..542188018
--- /dev/null
+++ b/app/javascript/packs/referential_lines/show.js
@@ -0,0 +1,10 @@
+import clone from '../../helpers/clone'
+import RoutesMap from '../../helpers/routes_map'
+
+let routes = clone(window, "routes", true)
+routes = JSON.parse(decodeURIComponent(routes))
+
+var map = new RoutesMap('routes_map')
+map.addRoutes(routes)
+// map.addRoutesLabels()
+map.fitZoom()
diff --git a/app/javascript/packs/referential_overview/overview.js b/app/javascript/packs/referential_overview/overview.js
new file mode 100644
index 000000000..59c326e9a
--- /dev/null
+++ b/app/javascript/packs/referential_overview/overview.js
@@ -0,0 +1 @@
+import ReferentialOverview from '../../referential_overview'
diff --git a/app/javascript/packs/routes/edit.js b/app/javascript/packs/routes/edit.js
index d6ceed60f..b787bec97 100644
--- a/app/javascript/packs/routes/edit.js
+++ b/app/javascript/packs/routes/edit.js
@@ -1,4 +1,6 @@
-import React, { PropTypes } from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
+
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
@@ -12,7 +14,7 @@ datas = JSON.parse(decodeURIComponent(datas))
// logger, DO NOT REMOVE
var applyMiddleware = require('redux').applyMiddleware
-var createLogger = require('redux-logger')
+import {createLogger} from 'redux-logger';
var thunkMiddleware = require('redux-thunk').default
var promise = require('redux-promise')
diff --git a/app/javascript/packs/routes/show.js b/app/javascript/packs/routes/show.js
index 7f14a6f11..c20de0800 100644
--- a/app/javascript/packs/routes/show.js
+++ b/app/javascript/packs/routes/show.js
@@ -1,102 +1,8 @@
import clone from '../../helpers/clone'
+import RoutesMap from '../../helpers/routes_map'
+
let route = clone(window, "route", true)
route = JSON.parse(decodeURIComponent(route))
-
-const geoColPts = []
-const geoColLns = []
-const geoColEdges = [
- new ol.Feature({
- geometry: new ol.geom.Point(ol.proj.fromLonLat([parseFloat(route[0].longitude), parseFloat(route[0].latitude)]))
- }),
- new ol.Feature({
- geometry: new ol.geom.Point(ol.proj.fromLonLat([parseFloat(route[route.length - 1].longitude), parseFloat(route[route.length - 1].latitude)]))
- })
-]
-route.forEach(function (stop, i) {
- if (i < route.length - 1) {
- geoColLns.push(new ol.Feature({
- geometry: new ol.geom.LineString([
- ol.proj.fromLonLat([parseFloat(route[i].longitude), parseFloat(route[i].latitude)]),
- ol.proj.fromLonLat([parseFloat(route[i + 1].longitude), parseFloat(route[i + 1].latitude)])
- ])
- }))
- }
- geoColPts.push(new ol.Feature({
- geometry: new ol.geom.Point(ol.proj.fromLonLat([parseFloat(stop.longitude), parseFloat(stop.latitude)]))
- })
- )
-})
-var edgeStyles = new ol.style.Style({
- image: new ol.style.Circle(({
- radius: 5,
- stroke: new ol.style.Stroke({
- color: '#007fbb',
- width: 2
- }),
- fill: new ol.style.Fill({
- color: '#007fbb',
- width: 2
- })
- }))
-})
-var defaultStyles = new ol.style.Style({
- image: new ol.style.Circle(({
- radius: 4,
- stroke: new ol.style.Stroke({
- color: '#007fbb',
- width: 2
- }),
- fill: new ol.style.Fill({
- color: '#ffffff',
- width: 2
- })
- }))
-})
-var lineStyle = new ol.style.Style({
- stroke: new ol.style.Stroke({
- color: '#007fbb',
- width: 3
- })
-})
-
-var vectorPtsLayer = new ol.layer.Vector({
- source: new ol.source.Vector({
- features: geoColPts
- }),
- style: defaultStyles,
- zIndex: 2
-})
-var vectorEdgesLayer = new ol.layer.Vector({
- source: new ol.source.Vector({
- features: geoColEdges
- }),
- style: edgeStyles,
- zIndex: 3
-})
-var vectorLnsLayer = new ol.layer.Vector({
- source: new ol.source.Vector({
- features: geoColLns
- }),
- style: [lineStyle],
- zIndex: 1
-})
-
-var map = new ol.Map({
- target: 'route_map',
- layers: [
- new ol.layer.Tile({
- source: new ol.source.OSM()
- }),
- vectorPtsLayer,
- vectorEdgesLayer,
- vectorLnsLayer
- ],
- controls: [new ol.control.ScaleLine(), new ol.control.Zoom(), new ol.control.ZoomSlider()],
- interactions: ol.interaction.defaults({
- zoom: true
- }),
- view: new ol.View({
- center: ol.proj.fromLonLat([parseFloat(route[0].longitude), parseFloat(route[0].latitude)]),
- zoom: 13
- })
-});
+var map = new RoutesMap('route_map')
+map.addRoute(route)
+map.fitZoom()
diff --git a/app/javascript/packs/stop_areas/new.js b/app/javascript/packs/stop_areas/new.js
new file mode 100644
index 000000000..ffe702cdb
--- /dev/null
+++ b/app/javascript/packs/stop_areas/new.js
@@ -0,0 +1,3 @@
+import MasterSlave from "../../helpers/master_slave"
+
+new MasterSlave("form")
diff --git a/app/javascript/packs/vehicle_journeys/index.js b/app/javascript/packs/vehicle_journeys/index.js
index 38431af1d..e6867cb17 100644
--- a/app/javascript/packs/vehicle_journeys/index.js
+++ b/app/javascript/packs/vehicle_journeys/index.js
@@ -23,6 +23,7 @@ var initialState = {
filters: {
selectedJourneyPatterns : selectedJP,
policy: window.perms,
+ features: window.features,
toggleArrivals: false,
queryString: '',
query: {
@@ -54,11 +55,12 @@ var initialState = {
},
status: {
- fetchSuccess: true,
+ fetchSuccess: false,
isFetching: false
},
vehicleJourneys: [],
stopPointsList: window.stopPoints,
+ returnStopPointsList: window.returnStopPoints,
pagination: {
page : 1,
totalCount: 0,
@@ -69,7 +71,9 @@ var initialState = {
type: '',
modalProps: {},
confirmModal: {}
- }
+ },
+ missions: window.all_missions,
+ custom_fields: window.custom_fields
}
if (window.jpOrigin){
@@ -96,7 +100,7 @@ let store = createStore(
render(
<Provider store={store}>
- <App />
+ <App returnRouteUrl={window.returnRouteUrl} />
</Provider>,
document.getElementById('vehicle_journeys_wip')
-) \ No newline at end of file
+)
diff --git a/app/javascript/referential_overview/index.coffee b/app/javascript/referential_overview/index.coffee
new file mode 100644
index 000000000..0e6541421
--- /dev/null
+++ b/app/javascript/referential_overview/index.coffee
@@ -0,0 +1,113 @@
+class TimeTravel
+ constructor: (@overview)->
+ @container = @overview.container.find('.time-travel')
+ @todayBt = @container.find(".today")
+ @prevBt = @container.find(".prev-page")
+ @nextBt = @container.find(".next-page")
+ @searchDateBt = @container.find("a.search-date")
+ @searchDateInput = @container.find("input.date-search")
+ @initButtons()
+
+ initButtons: ->
+ @prevBt.click (e)=>
+ @overview.prevPage()
+ e.preventDefault()
+ false
+
+ @nextBt.click (e)=>
+ @overview.nextPage()
+ e.preventDefault()
+ false
+
+ @todayBt.click (e)=>
+ today = new Date()
+ month = today.getMonth() + 1
+ month = "0#{month}" if month < 10
+ day = today.getDate()
+ day = "0#{month}" if day < 10
+ @overview.showDay "#{today.getFullYear()}-#{month}-#{day}"
+ e.preventDefault()
+ false
+
+ @searchDateBt.click (e)=>
+ @overview.showDay @searchDateInput.val() if @searchDateInput.val().length > 0
+ e.preventDefault()
+ false
+
+ scrolledTo: (progress)->
+ @prevBt.removeClass 'disabled'
+ @nextBt.removeClass 'disabled'
+ @prevBt.addClass 'disabled' if progress == 0
+ @nextBt.addClass 'disabled' if progress == 1
+
+class window.ReferentialOverview
+ constructor: (selector)->
+ @container = $(selector)
+ @timeTravel = new TimeTravel(this)
+ @currentOffset = 0
+ $(document).scroll (e)=>
+ @documentScroll(e)
+ @documentScroll pageY: $(document).scrollTop()
+
+ showDay: (date)->
+ day = @container.find(".day.#{date}")
+ @container.find(".day.selected").removeClass('selected')
+ day.addClass "selected"
+ offset = day.offset().left
+ parentOffset = @currentOffset + @container.find(".right").offset().left
+ @scrollTo parentOffset - offset
+
+ currentOffset: ->
+ @container.find(".right .inner").offset().left
+
+ top: ->
+ @_top ||= @container.find('.days').offset().top - 80
+ bottom: ->
+ @_bottom ||= @top() + @container.height() - 50
+
+ prevPage: ->
+ @scrollTo @currentOffset + @container.find(".right").width()
+
+ nextPage: ->
+ @scrollTo @currentOffset - @container.find(".right").width()
+
+ minOffset: ->
+ @_minOffset ||= @container.find(".right").width() - @container.find(".right .line").width()
+ @_minOffset
+
+ scrollTo: (offset)->
+ @currentOffset = offset
+ @currentOffset = Math.max(@currentOffset, @minOffset())
+ @currentOffset = Math.min(@currentOffset, 0)
+ @container.find(".right .inner .lines").css "margin-left": "#{@currentOffset}px"
+ @container.find(".head .week:first-child").css "margin-left", "#{@currentOffset}px"
+ @timeTravel.scrolledTo 1 - (@minOffset() - @currentOffset) / @minOffset()
+ setTimeout =>
+ @movePeriodTitles()
+ , 600
+
+ movePeriodTitles: ->
+ @_right_offset ||= @container.find('.right').offset().left
+ @container.find(".shifted").removeClass("shifted").css "margin-left", 0
+ @container.find(".right .line").each (i, l) =>
+ $(l).find(".period").each (i, _p) =>
+ p = $(_p)
+ offset = parseInt(p.css("left")) + @currentOffset
+ if offset < 0 && - offset < p.width()
+ offset = Math.min(-offset, p.width() - 100)
+ p.find(".title").addClass("shifted").css "margin-left", offset + "px"
+ return
+
+ documentScroll: (e)->
+ if @sticky
+ if e.pageY < @top() || e.pageY > @bottom()
+ @container.removeClass "sticky"
+ @sticky = false
+ else
+ if e.pageY > @top() && e.pageY < @bottom()
+ @sticky = true
+ @container.addClass "sticky"
+
+
+
+export default ReferentialOverview
diff --git a/app/javascript/routes/components/App.js b/app/javascript/routes/components/App.js
index 0f5786407..26e69bf53 100644
--- a/app/javascript/routes/components/App.js
+++ b/app/javascript/routes/components/App.js
@@ -1,4 +1,5 @@
-import React, { Component, PropTypes } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import AddStopPoint from '../containers/AddStopPoint'
import VisibleStopPoints from'../containers/VisibleStopPoints'
import clone from '../../helpers/clone'
@@ -16,8 +17,8 @@ export default class App extends Component {
<VisibleStopPoints />
<AddStopPoint />
</div>
- )
- }
+ )
+ }
}
App.childContextTypes = {
diff --git a/app/javascript/routes/components/BSelect2.js b/app/javascript/routes/components/BSelect2.js
index 340d9df95..035bce155 100644
--- a/app/javascript/routes/components/BSelect2.js
+++ b/app/javascript/routes/components/BSelect2.js
@@ -1,6 +1,7 @@
import _ from'lodash'
-import React, { Component, PropTypes } from 'react'
-import Select2 from 'react-select2'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import Select2 from 'react-select2-wrapper'
// get JSON full path
@@ -84,7 +85,7 @@ class BSelect2 extends Component{
onSelect={ this.props.onSelect }
ref='newSelect'
options={{
- placeholder: this.context.I18n.routes.edit.select2.placeholder,
+ placeholder: this.context.I18n.t("routes.edit.select2.placeholder"),
allowClear: true,
language: 'fr', /* Doesn't seem to work... :( */
theme: 'bootstrap',
@@ -96,17 +97,26 @@ class BSelect2 extends Component{
data: function(params) {
return {
q: params.term,
- target_type: 'zdep'
+ scope: 'route_editor'
};
},
processResults: function(data, params) {
return {
- results: data.map(
- item => _.assign(
- {},
- item,
- { text: item.name + ", " + item.zip_code + " " + item.short_city_name + " <small><em>(" + item.user_objectid + ")</em></small>" }
- )
+ results: data.map(
+ function(item) {
+ var text = item.name;
+ if (item.zip_code || item.short_city_name) {
+ text += ","
+ }
+ if (item.zip_code) {
+ text += ` ${item.zip_code}`
+ }
+ if (item.short_city_name) {
+ text += ` ${item.short_city_name}`
+ }
+ text += ` <small><em>(${item.area_type.toUpperCase()}, ${item.user_objectid})</em></small>`;
+ return _.assign({}, item, { text: text });
+ }
)
};
},
diff --git a/app/javascript/routes/components/OlMap.js b/app/javascript/routes/components/OlMap.js
index 2c01dfa7f..4beb02872 100644
--- a/app/javascript/routes/components/OlMap.js
+++ b/app/javascript/routes/components/OlMap.js
@@ -1,5 +1,6 @@
import _ from 'lodash'
-import React, { Component, PropTypes } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
export default class OlMap extends Component{
constructor(props, context){
@@ -114,40 +115,40 @@ export default class OlMap extends Component{
<strong>{this.props.value.olMap.json.name}</strong>
</p>
<p>
- <strong>{this.context.I18n.routes.edit.stop_point_type} : </strong>
+ <strong>{this.context.I18n.t('routes.edit.map.stop_point_type')} : </strong>
{this.props.value.olMap.json.area_type}
</p>
<p>
- <strong>{this.context.I18n.routes.edit.short_name} : </strong>
+ <strong>{this.context.I18n.t('routes.edit.map.short_name')} : </strong>
{this.props.value.olMap.json.short_name}
</p>
<p>
- <strong>{this.context.I18n.id_reflex} : </strong>
+ <strong>{this.context.I18n.t('id_reflex')} : </strong>
{this.props.value.olMap.json.user_objectid}
</p>
- <p><strong>{this.context.I18n.routes.edit.map.coordinates} : </strong></p>
+ <p><strong>{this.context.I18n.t('routes.edit.map.coordinates')} : </strong></p>
<p style={{paddingLeft: 10, marginTop: 0}}>
- <em>{this.context.I18n.routes.edit.map.proj}.: </em>WSG84<br/>
- <em>{this.context.I18n.routes.edit.map.lat}.: </em>{this.props.value.olMap.json.latitude} <br/>
- <em>{this.context.I18n.routes.edit.map.lon}.: </em>{this.props.value.olMap.json.longitude}
+ <em>{this.context.I18n.t('routes.edit.map.proj')}.: </em>WSG84<br/>
+ <em>{this.context.I18n.t('routes.edit.map.lat')}.: </em>{this.props.value.olMap.json.latitude} <br/>
+ <em>{this.context.I18n.t('routes.edit.map.lon')}.: </em>{this.props.value.olMap.json.longitude}
</p>
<p>
- <strong>{this.context.I18n.routes.edit.map.postal_code} : </strong>
+ <strong>{this.context.I18n.t('routes.edit.map.postal_code')} : </strong>
{this.props.value.olMap.json.zip_code}
</p>
<p>
- <strong>{this.context.I18n.routes.edit.map.city} : </strong>
+ <strong>{this.context.I18n.t('routes.edit.map.city')} : </strong>
{this.props.value.olMap.json.city_name}
</p>
<p>
- <strong>{this.context.I18n.routes.edit.map.comment} : </strong>
+ <strong>{this.context.I18n.t('routes.edit.map.comment')} : </strong>
{this.props.value.olMap.json.comment}
</p>
{(this.props.value.stoparea_id != this.props.value.olMap.json.stoparea_id) &&(
<div className='btn btn-outline-primary btn-sm'
onClick= {() => {this.props.onUpdateViaOlMap(this.props.index, this.props.value.olMap.json)}}
- >{this.context.I18n.actions.select}</div>
+ >{this.context.I18n.t('actions.select')}</div>
)}
</div>
<div className='map_content'>
@@ -161,7 +162,7 @@ export default class OlMap extends Component{
}
}
-OlMap.PropTypes = {
+OlMap.propTypes = {
}
OlMap.contextTypes = {
diff --git a/app/javascript/routes/components/StopPoint.js b/app/javascript/routes/components/StopPoint.js
index 606121f99..af51a6bb4 100644
--- a/app/javascript/routes/components/StopPoint.js
+++ b/app/javascript/routes/components/StopPoint.js
@@ -1,4 +1,6 @@
-import React, { PropTypes } from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
+
import BSelect2 from './BSelect2'
import OlMap from './OlMap'
@@ -16,15 +18,15 @@ export default function StopPoint(props, {I18n}) {
<div>
<select className='form-control' value={props.value.for_boarding} id="for_boarding" onChange={props.onSelectChange}>
- <option value="normal">{I18n.routes.edit.stop_point.boarding.normal}</option>
- <option value="forbidden">{I18n.routes.edit.stop_point.boarding.forbidden}</option>
+ <option value="normal">{I18n.t('routes.edit.stop_point.boarding.normal')}</option>
+ <option value="forbidden">{I18n.t('routes.edit.stop_point.boarding.forbidden')}</option>
</select>
</div>
<div>
<select className='form-control' value={props.value.for_alighting} id="for_alighting" onChange={props.onSelectChange}>
- <option value="normal">{I18n.routes.edit.stop_point.alighting.normal}</option>
- <option value="forbidden">{I18n.routes.edit.stop_point.alighting.forbidden}</option>
+ <option value="normal">{I18n.t('routes.edit.stop_point.alighting.normal')}</option>
+ <option value="forbidden">{I18n.t('routes.edit.stop_point.alighting.forbidden')}</option>
</select>
</div>
@@ -75,7 +77,7 @@ export default function StopPoint(props, {I18n}) {
)
}
-StopPoint.PropTypes = {
+StopPoint.propTypes = {
onToggleMap: PropTypes.func.isRequired,
onToggleEdit: PropTypes.func.isRequired,
onDeleteClick: PropTypes.func.isRequired,
@@ -91,4 +93,4 @@ StopPoint.PropTypes = {
StopPoint.contextTypes = {
I18n: PropTypes.object
-} \ No newline at end of file
+}
diff --git a/app/javascript/routes/components/StopPointList.js b/app/javascript/routes/components/StopPointList.js
index 68af16f57..b227abdea 100644
--- a/app/javascript/routes/components/StopPointList.js
+++ b/app/javascript/routes/components/StopPointList.js
@@ -1,4 +1,6 @@
-import React, { PropTypes } from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
+
import StopPoint from './StopPoint'
export default function StopPointList({ stopPoints, onDeleteClick, onMoveUpClick, onMoveDownClick, onChange, onSelectChange, onToggleMap, onToggleEdit, onSelectMarker, onUnselectMarker, onUpdateViaOlMap }, {I18n}) {
@@ -8,22 +10,22 @@ export default function StopPointList({ stopPoints, onDeleteClick, onMoveUpClick
<div className="wrapper">
<div style={{width: 100}}>
<div className="form-group">
- <label className="control-label">{I18n.reflex_id}</label>
+ <label className="control-label">{I18n.t('simple_form.labels.stop_point.reflex_id')}</label>
</div>
</div>
<div>
<div className="form-group">
- <label className="control-label">{I18n.simple_form.labels.stop_point.name}</label>
+ <label className="control-label">{I18n.t('simple_form.labels.stop_point.name')}</label>
</div>
</div>
<div>
<div className="form-group">
- <label className="control-label">{I18n.simple_form.labels.stop_point.for_boarding}</label>
+ <label className="control-label">{I18n.t('simple_form.labels.stop_point.for_boarding')}</label>
</div>
</div>
<div>
<div className="form-group">
- <label className="control-label">{I18n.simple_form.labels.stop_point.for_alighting}</label>
+ <label className="control-label">{I18n.t('simple_form.labels.stop_point.for_alighting')}</label>
</div>
</div>
<div className='actions-5'></div>
@@ -54,7 +56,7 @@ export default function StopPointList({ stopPoints, onDeleteClick, onMoveUpClick
)
}
-StopPointList.PropTypes = {
+StopPointList.propTypes = {
stopPoints: PropTypes.array.isRequired,
onDeleteClick: PropTypes.func.isRequired,
onMoveUpClick: PropTypes.func.isRequired,
@@ -66,4 +68,4 @@ StopPointList.PropTypes = {
StopPointList.contextTypes = {
I18n: PropTypes.object
-} \ No newline at end of file
+}
diff --git a/app/javascript/routes/form_helper.js b/app/javascript/routes/form_helper.js
index 8a3277234..865722fb6 100644
--- a/app/javascript/routes/form_helper.js
+++ b/app/javascript/routes/form_helper.js
@@ -7,14 +7,14 @@ const formHelper = {
input.setAttribute('name', formatedName)
input.setAttribute('value', value)
form.appendChild(input)
- },
+ },
addError: (ids) => {
ids.forEach((id) => {
if (!$(id).parents('.form-group').hasClass('has-error')) {
$(id).parents('.form-group').addClass('has-error')
$(id).parent().append(`<span class='help-block small'>${'doit être rempli(e)'}</span>`)
}
- })
+ })
},
cleanInputs: (ids) => {
ids.forEach((id) =>{
@@ -28,21 +28,22 @@ const formHelper = {
ids.forEach(id => {
$(id).val() == "" ? blankInputs.push(id) : filledInputs.push(id)
})
-
+
if (filledInputs.length > 0) formHelper.cleanInputs(filledInputs)
- if (blankInputs.length > 0) formHelper.addError(blankInputs)
+ if (blankInputs.length > 0) formHelper.addError(blankInputs)
},
handleStopPoints: (event, state) => {
if (state.stopPoints.length >= 2) {
state.stopPoints.map((stopPoint, i) => {
formHelper.addInput('id', stopPoint.stoppoint_id ? stopPoint.stoppoint_id : '', i)
formHelper.addInput('stop_area_id', stopPoint.stoparea_id, i)
- formHelper.addInput('position', i, i)
+ formHelper.addInput('position', stopPoint.index, i)
formHelper.addInput('for_boarding', stopPoint.for_boarding, i)
formHelper.addInput('for_alighting', stopPoint.for_alighting, i)
})
- if ($('.alert.alert-danger').length > 0) $('.alert.alert-danger').remove()
- } else {
+ if ($('.alert.alert-danger').length > 0) $('.alert.alert-danger').remove()
+ }
+ else {
event.preventDefault()
let msg = "L'itinéraire doit comporter au moins deux arrêts"
if ($('.alert.alert-danger').length == 0) {
@@ -52,4 +53,4 @@ const formHelper = {
}
}
-export default formHelper \ No newline at end of file
+export default formHelper
diff --git a/app/javascript/routes/reducers/stopPoints.js b/app/javascript/routes/reducers/stopPoints.js
index eeec06327..0b42b504f 100644
--- a/app/javascript/routes/reducers/stopPoints.js
+++ b/app/javascript/routes/reducers/stopPoints.js
@@ -38,15 +38,15 @@ const stopPoints = (state = [], action) => {
case 'MOVE_STOP_UP':
return [
...state.slice(0, action.index - 1),
- _.assign({}, state[action.index], { stoppoint_id: state[action.index - 1].stoppoint_id }),
- _.assign({}, state[action.index - 1], { stoppoint_id: state[action.index].stoppoint_id }),
+ _.assign({}, state[action.index], { index: action.index - 1 }),
+ _.assign({}, state[action.index - 1], { index: action.index }),
...state.slice(action.index + 1)
]
case 'MOVE_STOP_DOWN':
return [
...state.slice(0, action.index),
- _.assign({}, state[action.index + 1], { stoppoint_id: state[action.index].stoppoint_id }),
- _.assign({}, state[action.index], { stoppoint_id: state[action.index + 1].stoppoint_id }),
+ _.assign({}, state[action.index + 1], { index: action.index }),
+ _.assign({}, state[action.index], { index: action.index + 1 }),
...state.slice(action.index + 2)
]
case 'DELETE_STOP':
@@ -141,4 +141,4 @@ const stopPoints = (state = [], action) => {
}
}
-export default stopPoints \ No newline at end of file
+export default stopPoints
diff --git a/app/javascript/time_tables/actions/index.js b/app/javascript/time_tables/actions/index.js
index 13cb96b64..98b9eab4b 100644
--- a/app/javascript/time_tables/actions/index.js
+++ b/app/javascript/time_tables/actions/index.js
@@ -1,5 +1,5 @@
-import range from 'lodash/range'
import assign from 'lodash/assign'
+import range from 'lodash/range'
import reject from 'lodash/reject'
import some from 'lodash/some'
import every from 'lodash/every'
@@ -8,7 +8,7 @@ const I18n = clone(window, "I18n")
const actions = {
weekDays: (index) => {
- return range(1, 8).map(n => I18n.time_tables.edit.metas.days[n])
+ return range(1, 8).map(n => I18n.t('time_tables.edit.metas.days')[n])
},
strToArrayDayTypes: (str) =>{
return actions.weekDays().map(day => str.indexOf(day) !== -1)
@@ -155,9 +155,9 @@ const actions = {
type : 'CLOSE_MODAL'
}),
monthName(strDate) {
- let monthList = range(1,13).map(n => I18n.calendars.months[n])
+ let monthList = range(1,13).map(n => I18n.t('calendars.months.'+ n ))
let date = new Date(strDate)
- return monthList[date.getMonth()]
+ return monthList[date.getUTCMonth()]
},
getHumanDate(strDate, mLimit) {
let origin = strDate.split('-')
@@ -173,7 +173,7 @@ const actions = {
},
getLocaleDate(strDate) {
let date = new Date(strDate)
- return date.toLocaleDateString()
+ return date.toLocaleDateString(undefined, { timeZone: 'UTC' })
},
updateSynthesis: ({current_month, time_table_dates: dates, time_table_periods: periods}) => {
let newPeriods = reject(periods, 'deleted')
@@ -194,7 +194,7 @@ const actions = {
for (let period of periods) {
let begin = new Date(period.period_start)
- let end = new Date(period.period_end)
+ let end = new Date(period.period_end)
if (date >= begin && date <= end) return true
}
@@ -225,7 +225,7 @@ const actions = {
let period = periods[i]
if (index !== i && !period.deleted) {
if (new Date(period.period_start) <= end && new Date(period.period_end) >= start) {
- error = I18n.time_tables.edit.error_submit.periods_overlaps
+ error = I18n.t('time_tables.edit.error_submit.periods_overlaps')
break
}
}
@@ -239,14 +239,15 @@ const actions = {
for (let day of in_days) {
if (start <= new Date(day.date) && end >= new Date(day.date)) {
- error = I18n.time_tables.edit.error_submit.dates_overlaps
+ error = I18n.t('time_tables.edit.error_submit.dates_overlaps')
break
}
}
return error
},
fetchTimeTables: (dispatch, nextPage) => {
- let urlJSON = window.location.pathname.split('/', 5).join('/')
+ let urlJSON = window.timetablesUrl || window.location.pathname.split('/', 5).join('/')
+
if(nextPage) {
urlJSON += "/month.json?date=" + nextPage
}else{
@@ -277,7 +278,7 @@ const actions = {
let strDayTypes = actions.arrayToStrDayTypes(metas.day_types)
metas.day_types = strDayTypes
let sentState = assign({}, timetable, metas)
- let urlJSON = window.location.pathname.split('/', 5).join('/')
+ let urlJSON = window.timetablesUrl || window.location.pathname.split('/', 5).join('/')
let hasError = false
fetch(urlJSON + '.json', {
credentials: 'same-origin',
@@ -315,9 +316,9 @@ const actions = {
errorModalMessage: (errorKey) => {
switch (errorKey) {
case "withoutPeriodsWithDaysTypes":
- return I18n.time_tables.edit.error_modal.withoutPeriodsWithDaysTypes
+ return I18n.t('time_tables.edit.error_modal.withoutPeriodsWithDaysTypes')
case "withPeriodsWithoutDayTypes":
- return I18n.time_tables.edit.error_modal.withPeriodsWithoutDayTypes
+ return I18n.t('time_tables.edit.error_modal.withPeriodsWithoutDayTypes')
default:
return errorKey
@@ -325,4 +326,4 @@ const actions = {
}
}
-export default actions \ No newline at end of file
+export default actions
diff --git a/app/javascript/time_tables/components/ConfirmModal.js b/app/javascript/time_tables/components/ConfirmModal.js
index d89170ee7..4e8583bc0 100644
--- a/app/javascript/time_tables/components/ConfirmModal.js
+++ b/app/javascript/time_tables/components/ConfirmModal.js
@@ -1,4 +1,6 @@
-import React, { PropTypes } from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
+
export default function ConfirmModal({dispatch, modal, onModalAccept, onModalCancel, timetable, metas}, {I18n}) {
return (
@@ -7,11 +9,11 @@ export default function ConfirmModal({dispatch, modal, onModalAccept, onModalCan
<div className='modal-dialog'>
<div className='modal-content'>
<div className='modal-header'>
- <h4 className='modal-title'>{I18n.time_tables.edit.confirm_modal.title}</h4>
+ <h4 className='modal-title'>{I18n.t('time_tables.edit.confirm_modal.title')}</h4>
</div>
<div className='modal-body'>
<div className='mt-md mb-md'>
- <p>{I18n.time_tables.edit.confirm_modal.message}</p>
+ <p>{I18n.t('time_tables.edit.confirm_modal.message')}</p>
</div>
</div>
<div className='modal-footer'>
@@ -21,7 +23,7 @@ export default function ConfirmModal({dispatch, modal, onModalAccept, onModalCan
type='button'
onClick={() => { onModalCancel(modal.confirmModal.callback) }}
>
- {I18n.cancel}
+ {I18n.t('cancel')}
</button>
<button
className='btn btn-primary'
@@ -29,7 +31,7 @@ export default function ConfirmModal({dispatch, modal, onModalAccept, onModalCan
type='button'
onClick={() => { onModalAccept(modal.confirmModal.callback, timetable, metas) }}
>
- {I18n.actions.submit}
+ {I18n.t('actions.submit')}
</button>
</div>
</div>
@@ -47,4 +49,4 @@ ConfirmModal.propTypes = {
ConfirmModal.contextTypes = {
I18n: PropTypes.object
-} \ No newline at end of file
+}
diff --git a/app/javascript/time_tables/components/ErrorModal.js b/app/javascript/time_tables/components/ErrorModal.js
index e810f49ab..8af12f1d1 100644
--- a/app/javascript/time_tables/components/ErrorModal.js
+++ b/app/javascript/time_tables/components/ErrorModal.js
@@ -1,4 +1,6 @@
-import React, { PropTypes } from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
+
import actions from '../actions'
export default function ErrorModal({dispatch, modal, onModalClose}, {I18n}) {
@@ -8,7 +10,7 @@ export default function ErrorModal({dispatch, modal, onModalClose}, {I18n}) {
<div className='modal-dialog'>
<div className='modal-content'>
<div className='modal-header'>
- <h4 className='modal-title'>{I18n.time_tables.edit.error_modal.title}</h4>
+ <h4 className='modal-title'>{I18n.t('time_tables.edit.error_modal.title')}</h4>
</div>
<div className='modal-body'>
<div className='mt-md mb-md'>
@@ -22,7 +24,7 @@ export default function ErrorModal({dispatch, modal, onModalClose}, {I18n}) {
type='button'
onClick={() => { onModalClose() }}
>
- {I18n.back}
+ {I18n.t('back')}
</button>
</div>
</div>
@@ -39,4 +41,4 @@ ErrorModal.propTypes = {
ErrorModal.contextTypes = {
I18n: PropTypes.object
-} \ No newline at end of file
+}
diff --git a/app/javascript/time_tables/components/ExceptionsInDay.js b/app/javascript/time_tables/components/ExceptionsInDay.js
index 3335ee89d..f5ed625be 100644
--- a/app/javascript/time_tables/components/ExceptionsInDay.js
+++ b/app/javascript/time_tables/components/ExceptionsInDay.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../actions'
export default class ExceptionsInDay extends Component {
diff --git a/app/javascript/time_tables/components/Metas.js b/app/javascript/time_tables/components/Metas.js
index 7098d2b82..08a6e26fe 100644
--- a/app/javascript/time_tables/components/Metas.js
+++ b/app/javascript/time_tables/components/Metas.js
@@ -1,4 +1,6 @@
-import React, { PropTypes } from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
+
import actions from '../actions'
import TagsSelect2 from './TagsSelect2'
@@ -11,7 +13,7 @@ export default function Metas({metas, onUpdateDayTypes, onUpdateComment, onUpdat
{/* comment (name) */}
<div className="form-group">
<label htmlFor="" className="control-label col-sm-4 required">
- {I18n.time_tables.edit.metas.name} <abbr title="">*</abbr>
+ {I18n.t('time_tables.edit.metas.name')} <abbr title="">*</abbr>
</label>
<div className="col-sm-8">
<input
@@ -25,8 +27,8 @@ export default function Metas({metas, onUpdateDayTypes, onUpdateComment, onUpdat
</div>
{/* color */}
- <div className="form-group">
- <label htmlFor="" className="control-label col-sm-4">{I18n.activerecord.attributes.time_table.color}</label>
+ {metas.color !== undefined && <div className="form-group">
+ <label htmlFor="" className="control-label col-sm-4">{I18n.attribute_name('time_table', 'color')}</label>
<div className="col-sm-8">
<div className="dropdown color_selector">
<button
@@ -67,11 +69,11 @@ export default function Metas({metas, onUpdateDayTypes, onUpdateComment, onUpdat
</div>
</div>
</div>
- </div>
+ </div>}
{/* tags */}
- <div className="form-group">
- <label htmlFor="" className="control-label col-sm-4">{I18n.activerecord.attributes.time_table.tag_list}</label>
+ {metas.tags !== undefined && <div className="form-group">
+ <label htmlFor="" className="control-label col-sm-4">{I18n.attribute_name('time_table', 'tag_list')}</label>
<div className="col-sm-8">
<TagsSelect2
initialTags={metas.initial_tags}
@@ -80,20 +82,20 @@ export default function Metas({metas, onUpdateDayTypes, onUpdateComment, onUpdat
onUnselect2Tags={(e) => onUnselect2Tags(e)}
/>
</div>
- </div>
+ </div>}
{/* calendar */}
- <div className="form-group">
- <label htmlFor="" className="control-label col-sm-4">{I18n.activerecord.attributes.time_table.calendar}</label>
+ {metas.calendar !== null && <div className="form-group">
+ <label htmlFor="" className="control-label col-sm-4">{I18n.attribute_name('time_table', 'calendar')}</label>
<div className="col-sm-8">
- <span>{metas.calendar ? metas.calendar.name : I18n.time_tables.edit.metas.no_calendar}</span>
+ <span>{metas.calendar ? metas.calendar.name : I18n.t('time_tables.edit.metas.no_calendar')}</span>
</div>
- </div>
+ </div>}
{/* day_types */}
<div className="form-group">
<label htmlFor="" className="control-label col-sm-4">
- {I18n.time_tables.edit.metas.day_types}
+ {I18n.t('time_tables.edit.metas.day_types')}
</label>
<div className="col-sm-8">
<div className="form-group labelled-checkbox-group">
diff --git a/app/javascript/time_tables/components/Navigate.js b/app/javascript/time_tables/components/Navigate.js
index 7307d819b..1467fffe9 100644
--- a/app/javascript/time_tables/components/Navigate.js
+++ b/app/javascript/time_tables/components/Navigate.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import map from 'lodash/map'
import actions from '../actions'
@@ -23,7 +24,7 @@ export default function Navigate({ dispatch, metas, timetable, pagination, statu
aria-haspopup='true'
aria-expanded='true'
>
- {pagination.currentPage ? (actions.monthName(pagination.currentPage) + ' ' + new Date(pagination.currentPage).getFullYear()) : ''}
+ {pagination.currentPage ? (actions.monthName(pagination.currentPage) + ' ' + new Date(pagination.currentPage).getUTCFullYear()) : ''}
<span className='caret'></span>
</div>
<ul
@@ -40,7 +41,7 @@ export default function Navigate({ dispatch, metas, timetable, pagination, statu
dispatch(actions.checkConfirmModal(e, actions.changePage(dispatch, e.currentTarget.value), pagination.stateChanged, dispatch, metas, timetable))
}}
>
- {actions.monthName(month) + ' ' + new Date(month).getFullYear()}
+ {actions.monthName(month) + ' ' + new Date(month).getUTCFullYear()}
</button>
</li>
))}
@@ -85,4 +86,4 @@ Navigate.propTypes = {
status: PropTypes.object.isRequired,
pagination: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/time_tables/components/PeriodForm.js b/app/javascript/time_tables/components/PeriodForm.js
index d9f1d3437..d17a246f7 100644
--- a/app/javascript/time_tables/components/PeriodForm.js
+++ b/app/javascript/time_tables/components/PeriodForm.js
@@ -1,4 +1,6 @@
-import React, { PropTypes } from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
+
import filter from 'lodash/filter'
let monthsArray = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']
@@ -44,7 +46,7 @@ export default function PeriodForm({modal, timetable, metas, onOpenAddPeriodForm
<div>
<div className="form-group">
<label htmlFor="" className="control-label required">
- {I18n.time_tables.edit.period_form.begin}
+ {I18n.t('time_tables.edit.period_form.begin')}
<abbr title="requis">*</abbr>
</label>
</div>
@@ -52,7 +54,7 @@ export default function PeriodForm({modal, timetable, metas, onOpenAddPeriodForm
<div>
<div className="form-group">
<label htmlFor="" className="control-label required">
- {I18n.time_tables.edit.period_form.end}
+ {I18n.t('time_tables.edit.period_form.end')}
<abbr title="requis">*</abbr>
</label>
</div>
@@ -103,14 +105,14 @@ export default function PeriodForm({modal, timetable, metas, onOpenAddPeriodForm
className='btn btn-link'
onClick={onClosePeriodForm}
>
- {I18n.cancel}
+ {I18n.t('cancel')}
</button>
<button
type='button'
className='btn btn-outline-primary mr-sm'
onClick={() => onValidatePeriodForm(modal.modalProps, timetable.time_table_periods, metas, filter(timetable.time_table_dates, ['in_out', true]))}
>
- {I18n.actions.submit}
+ {I18n.t('actions.submit')}
</button>
</div>
</div>
@@ -122,7 +124,7 @@ export default function PeriodForm({modal, timetable, metas, onOpenAddPeriodForm
className='btn btn-outline-primary'
onClick={onOpenAddPeriodForm}
>
- {I18n.time_tables.actions.add_period}
+ {I18n.t('time_tables.actions.add_period')}
</button>
</div>
}
@@ -130,7 +132,7 @@ export default function PeriodForm({modal, timetable, metas, onOpenAddPeriodForm
</div>
</div>
</div>
- )
+ )
}
PeriodForm.propTypes = {
@@ -145,4 +147,4 @@ PeriodForm.propTypes = {
PeriodForm.contextTypes = {
I18n: PropTypes.object
-} \ No newline at end of file
+}
diff --git a/app/javascript/time_tables/components/PeriodManager.js b/app/javascript/time_tables/components/PeriodManager.js
index 9922ce2c4..6b817fe73 100644
--- a/app/javascript/time_tables/components/PeriodManager.js
+++ b/app/javascript/time_tables/components/PeriodManager.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../actions'
export default class PeriodManager extends Component {
diff --git a/app/javascript/time_tables/components/PeriodsInDay.js b/app/javascript/time_tables/components/PeriodsInDay.js
index 888537579..1aed5c969 100644
--- a/app/javascript/time_tables/components/PeriodsInDay.js
+++ b/app/javascript/time_tables/components/PeriodsInDay.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import PeriodManager from './PeriodManager'
export default class PeriodsInDay extends Component {
diff --git a/app/javascript/time_tables/components/SaveTimetable.js b/app/javascript/time_tables/components/SaveTimetable.js
index d5a57bd1c..704590abd 100644
--- a/app/javascript/time_tables/components/SaveTimetable.js
+++ b/app/javascript/time_tables/components/SaveTimetable.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../actions'
export default class SaveTimetable extends Component{
diff --git a/app/javascript/time_tables/components/TagsSelect2.js b/app/javascript/time_tables/components/TagsSelect2.js
index 70a748a04..43cf59fdf 100644
--- a/app/javascript/time_tables/components/TagsSelect2.js
+++ b/app/javascript/time_tables/components/TagsSelect2.js
@@ -1,9 +1,10 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import mapKeys from 'lodash/mapKeys'
import map from 'lodash/map'
import filter from 'lodash/filter'
import assign from 'lodash/assign'
-import Select2 from 'react-select2'
+import Select2 from 'react-select2-wrapper'
// get JSON full path
let origin = window.location.origin
@@ -39,7 +40,7 @@ export default class TagsSelect2 extends Component {
allowClear: true,
theme: 'bootstrap',
width: '100%',
- placeholder: this.context.I18n.time_tables.edit.select2.tag.placeholder,
+ placeholder: this.context.I18n.t('time_tables.edit.select2.tag.placeholder'),
ajax: {
url: origin + path + '/tags.json',
dataType: 'json',
diff --git a/app/javascript/time_tables/components/TimeTableDay.js b/app/javascript/time_tables/components/TimeTableDay.js
index 165c7b848..498e7d0cd 100644
--- a/app/javascript/time_tables/components/TimeTableDay.js
+++ b/app/javascript/time_tables/components/TimeTableDay.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
export default class TimeTableDay extends Component {
constructor(props) {
diff --git a/app/javascript/time_tables/components/Timetable.js b/app/javascript/time_tables/components/Timetable.js
index df6e6016b..991f31435 100644
--- a/app/javascript/time_tables/components/Timetable.js
+++ b/app/javascript/time_tables/components/Timetable.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../actions'
import TimeTableDay from './TimeTableDay'
import PeriodsInDay from './PeriodsInDay'
@@ -30,11 +31,11 @@ export default class Timetable extends Component {
<div className="table table-2entries mb-sm">
<div className="t2e-head w20">
<div className="th">
- <div className="strong">{this.context.I18n.time_tables.synthesis}</div>
+ <div className="strong">{this.context.I18n.t('time_tables.edit.synthesis')}</div>
</div>
- <div className="td"><span>{this.context.I18n.time_tables.edit.day_types}</span></div>
- <div className="td"><span>{this.context.I18n.time_tables.edit.periods}</span></div>
- <div className="td"><span>{this.context.I18n.time_tables.edit.exceptions}</span></div>
+ <div className="td"><span>{this.context.I18n.t('time_tables.edit.day_types')}</span></div>
+ <div className="td"><span>{this.context.I18n.t('time_tables.edit.periods')}</span></div>
+ <div className="td"><span>{this.context.I18n.t('time_tables.edit.exceptions')}</span></div>
</div>
<div className="t2e-item-list w80">
<div>
diff --git a/app/javascript/time_tables/containers/App.js b/app/javascript/time_tables/containers/App.js
index 235dccb50..5963f8f1d 100644
--- a/app/javascript/time_tables/containers/App.js
+++ b/app/javascript/time_tables/containers/App.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import { connect } from'react-redux'
import actions from '../actions'
import Metas from './Metas'
diff --git a/app/javascript/vehicle_journeys/actions/index.js b/app/javascript/vehicle_journeys/actions/index.js
index ce4b9209d..4ca8bd73b 100644
--- a/app/javascript/vehicle_journeys/actions/index.js
+++ b/app/javascript/vehicle_journeys/actions/index.js
@@ -13,8 +13,8 @@ const actions = {
exitEditMode: () => ({
type: "EXIT_EDIT_MODE"
}),
- receiveVehicleJourneys : (json) => ({
- type: "RECEIVE_VEHICLE_JOURNEYS",
+ receiveVehicleJourneys : (json, returnJourneys) => ({
+ type: (returnJourneys ? "RECEIVE_RETURN_VEHICLE_JOURNEYS" : "RECEIVE_VEHICLE_JOURNEYS"),
json
}),
receiveErrors : (json) => ({
@@ -57,15 +57,22 @@ const actions = {
selectedItem: {
id: selectedJP.id,
objectid: selectedJP.object_id,
+ short_id: selectedJP.short_id,
name: selectedJP.name,
published_name: selectedJP.published_name,
- stop_areas: selectedJP.stop_area_short_descriptions
+ stop_areas: selectedJP.stop_area_short_descriptions,
+ costs: selectedJP.costs,
+ full_schedule: selectedJP.full_schedule
}
}),
openEditModal : (vehicleJourney) => ({
type : 'EDIT_VEHICLEJOURNEY_MODAL',
vehicleJourney
}),
+ openInfoModal : (vehicleJourney) => ({
+ type : 'INFO_VEHICLEJOURNEY_MODAL',
+ vehicleJourney
+ }),
openNotesEditModal : (vehicleJourney) => ({
type : 'EDIT_NOTES_VEHICLEJOURNEY_MODAL',
vehicleJourney
@@ -84,7 +91,8 @@ const actions = {
selectedItem:{
id: selectedTT.id,
comment: selectedTT.comment,
- objectid: selectedTT.objectid
+ objectid: selectedTT.objectid,
+ color: selectedTT.color
}
}),
addSelectedTimetable: () => ({
@@ -99,6 +107,31 @@ const actions = {
vehicleJourneys,
timetables
}),
+ openPurchaseWindowsEditModal : (vehicleJourneys) => ({
+ type : 'EDIT_PURCHASE_WINDOWS_VEHICLEJOURNEY_MODAL',
+ vehicleJourneys
+ }),
+ selectPurchaseWindowsModal: (selectedWindow) =>({
+ type: 'SELECT_PURCHASE_WINDOW_MODAL',
+ selectedItem:{
+ id: selectedWindow.id,
+ name: selectedWindow.name,
+ color: selectedWindow.color,
+ objectid: selectedWindow.objectid
+ }
+ }),
+ addSelectedPurchaseWindow: () => ({
+ type: 'ADD_SELECTED_PURCHASE_WINDOW'
+ }),
+ deletePurchaseWindowsModal : (purchaseWindow) => ({
+ type : 'DELETE_PURCHASE_WINDOW_MODAL',
+ purchaseWindow
+ }),
+ editVehicleJourneyPurchaseWindows : (vehicleJourneys, purchase_windows) => ({
+ type: 'EDIT_VEHICLEJOURNEYS_PURCHASE_WINDOWS',
+ vehicleJourneys,
+ purchase_windows
+ }),
openShiftModal : () => ({
type : 'SHIFT_VEHICLEJOURNEY_MODAL'
}),
@@ -162,26 +195,18 @@ const actions = {
resetValidation: (target) => {
$(target).parent().removeClass('has-error').children('.help-block').remove()
},
- validateFields : (...fields) => {
- const test = []
-
- Object.keys(fields).map(function(key) {
- test.push(fields[key].validity.valid)
+ validateFields : (fields) => {
+ let valid = true
+ Object.keys(fields).forEach((key) => {
+ let field = fields[key]
+ if(field.validity && !field.validity.valid){
+ valid = false
+ $(field).parent().addClass('has-error').children('.help-block').remove()
+ $(field).parent().append("<span class='small help-block'>" + field.validationMessage + "</span>")
+ }
})
- if(test.indexOf(false) >= 0) {
- // Form is invalid
- test.map(function(item, i) {
- if(item == false) {
- const k = Object.keys(fields)[i]
- $(fields[k]).parent().addClass('has-error').children('.help-block').remove()
- $(fields[k]).parent().append("<span class='small help-block'>" + fields[k].validationMessage + "</span>")
- }
- })
- return false
- } else {
- // Form is valid
- return true
- }
+
+ return valid
},
toggleArrivals : () => ({
type: 'TOGGLE_ARRIVALS',
@@ -269,10 +294,17 @@ const actions = {
type: 'RECEIVE_TOTAL_COUNT',
total
}),
- fetchVehicleJourneys : (dispatch, currentPage, nextPage, queryString) => {
+ fetchVehicleJourneys : (dispatch, currentPage, nextPage, queryString, url) => {
+ let returnJourneys = false
if(currentPage == undefined){
currentPage = 1
}
+ if(url == undefined){
+ url = window.location.pathname
+ }
+ else{
+ returnJourneys = true
+ }
let vehicleJourneys = []
let page
switch (nextPage) {
@@ -294,7 +326,7 @@ const actions = {
str = '.json?page=' + page.toString()
sep = '&'
}
- let urlJSON = window.location.pathname + str
+ let urlJSON = url + str
if (queryString){
urlJSON = urlJSON + sep + queryString
}
@@ -313,6 +345,7 @@ const actions = {
let val
for (val of json.vehicle_journeys){
var timeTables = []
+ var purchaseWindows = []
let tt
for (tt of val.time_tables){
timeTables.push({
@@ -322,33 +355,56 @@ const actions = {
color: tt.color
})
}
+ if(val.purchase_windows){
+ for (tt of val.purchase_windows){
+ purchaseWindows.push({
+ objectid: tt.objectid,
+ name: tt.name,
+ id: tt.id,
+ color: tt.color
+ })
+ }
+ }
let vjasWithDelta = val.vehicle_journey_at_stops.map((vjas, i) => {
actions.fillEmptyFields(vjas)
return actions.getDelta(vjas)
})
- vehicleJourneys.push({
- journey_pattern: val.journey_pattern,
- published_journey_name: val.published_journey_name,
- objectid: val.objectid,
- short_id: val.short_id,
- footnotes: val.footnotes,
- time_tables: timeTables,
- vehicle_journey_at_stops: vjasWithDelta,
- deletable: false,
- selected: false,
- published_journey_name: val.published_journey_name || 'non renseigné',
- published_journey_identifier: val.published_journey_identifier || 'non renseigné',
- company: val.company || 'non renseigné',
- transport_mode: val.route.line.transport_mode || 'undefined',
- transport_submode: val.route.line.transport_submode || 'undefined'
- })
+
+ vehicleJourneys.push(
+ _.assign({}, val, {
+ time_tables: timeTables,
+ purchase_windows: purchaseWindows,
+ vehicle_journey_at_stops: vjasWithDelta,
+ deletable: false,
+ selected: false,
+ published_journey_name: val.published_journey_name || 'non renseigné',
+ published_journey_identifier: val.published_journey_identifier || 'non renseigné',
+ company: val.company || {name: 'non renseigné'},
+ transport_mode: val.route.line.transport_mode || 'undefined',
+ transport_submode: val.route.line.transport_submode || 'undefined'
+ })
+ )
}
window.currentItemsLength = vehicleJourneys.length
- dispatch(actions.receiveVehicleJourneys(vehicleJourneys))
- dispatch(actions.receiveTotalCount(json.total))
+ dispatch(actions.receiveVehicleJourneys(vehicleJourneys, returnJourneys))
+ if(!returnJourneys){
+ dispatch(actions.receiveTotalCount(json.total))
+ }
}
})
},
+
+ validate : (dispatch, vehicleJourneys, next) => {
+ dispatch(actions.didValidateVehicleJourneys(vehicleJourneys))
+ actions.submitVehicleJourneys(dispatch, vehicleJourneys, next)
+ return true
+ },
+
+ didValidateVehicleJourneys : (vehicleJourneys) => ({
+ type: 'DID_VALIDATE_VEHICLE_JOURNEYS',
+ vehicleJourneys
+ }),
+
submitVehicleJourneys : (dispatch, state, next) => {
dispatch(actions.fetchingApi())
let urlJSON = window.location.pathname + "_collection.json"
@@ -439,6 +495,20 @@ const actions = {
vjas.delta = delta
return vjas
},
+ adjustSchedule: (action, schedule) => {
+ // we enforce that the departure time remains after the arrival time
+ actions.getDelta(schedule)
+ if(schedule.delta < 0){
+ if(action.isDeparture){
+ schedule.arrival_time = schedule.departure_time
+ }
+ else{
+ schedule.departure_time = schedule.arrival_time
+ }
+ actions.getDelta(schedule)
+ }
+ return schedule
+ },
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)))
diff --git a/app/javascript/vehicle_journeys/components/App.js b/app/javascript/vehicle_journeys/components/App.js
index 8e5f7aa9d..5ac284438 100644
--- a/app/javascript/vehicle_journeys/components/App.js
+++ b/app/javascript/vehicle_journeys/components/App.js
@@ -22,6 +22,7 @@ export default function App() {
<Filters />
<VehicleJourneysList />
+ {window.returnRouteUrl && <VehicleJourneysList routeUrl={window.returnRouteUrl}/>}
<div className='row'>
<div className='col-lg-12 text-right'>
@@ -35,4 +36,4 @@ export default function App() {
<ConfirmModal />
</div>
)
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/ConfirmModal.js b/app/javascript/vehicle_journeys/components/ConfirmModal.js
index df3c96c48..75e8a3932 100644
--- a/app/javascript/vehicle_journeys/components/ConfirmModal.js
+++ b/app/javascript/vehicle_journeys/components/ConfirmModal.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
export default function ConfirmModal({dispatch, modal, onModalAccept, onModalCancel, vehicleJourneys}) {
return (
@@ -6,7 +7,7 @@ export default function ConfirmModal({dispatch, modal, onModalAccept, onModalCan
<div className='modal-dialog'>
<div className='modal-content'>
<div className='modal-body'>
- <p> Voulez-vous valider vos modifications avant de changer de page? </p>
+ <p> {I18n.t('vehicle_journeys.vehicle_journeys_matrix.modal_confirm')} </p>
</div>
<div className='modal-footer'>
<button
@@ -30,11 +31,11 @@ export default function ConfirmModal({dispatch, modal, onModalAccept, onModalCan
</div>
</div>
)
-}
+}
ConfirmModal.propTypes = {
vehicleJourneys: PropTypes.array.isRequired,
modal: PropTypes.object.isRequired,
onModalAccept: PropTypes.func.isRequired,
onModalCancel: PropTypes.func.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/Filters.js b/app/javascript/vehicle_journeys/components/Filters.js
index db6707520..f8697c930 100644
--- a/app/javascript/vehicle_journeys/components/Filters.js
+++ b/app/javascript/vehicle_journeys/components/Filters.js
@@ -1,9 +1,11 @@
-import React, { PropTypes } from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
+
import MissionSelect2 from'./tools/select2s/MissionSelect2'
import VJSelect2 from'./tools/select2s/VJSelect2'
import TimetableSelect2 from'./tools/select2s/TimetableSelect2'
-export default function Filters({filters, pagination, onFilter, onResetFilters, onUpdateStartTimeFilter, onUpdateEndTimeFilter, onToggleWithoutSchedule, onToggleWithoutTimeTable, onSelect2Timetable, onSelect2JourneyPattern, onSelect2VehicleJourney}) {
+export default function Filters({filters, pagination, missions, onFilter, onResetFilters, onUpdateStartTimeFilter, onUpdateEndTimeFilter, onToggleWithoutSchedule, onToggleWithoutTimeTable, onSelect2Timetable, onSelect2JourneyPattern, onSelect2VehicleJourney}) {
return (
<div className='row'>
<div className='col-lg-12'>
@@ -24,6 +26,7 @@ export default function Filters({filters, pagination, onFilter, onResetFilters,
onSelect2JourneyPattern={onSelect2JourneyPattern}
filters={filters}
isFilter={true}
+ values={missions}
/>
</div>
@@ -33,6 +36,7 @@ export default function Filters({filters, pagination, onFilter, onResetFilters,
onSelect2Timetable={onSelect2Timetable}
hasRoute={true}
chunkURL={("/autocomplete_time_tables.json?route_id=" + String(window.route_id))}
+ searchKey={"comment_or_objectid_cont_any"}
filters={filters}
isFilter={true}
/>
@@ -42,10 +46,10 @@ export default function Filters({filters, pagination, onFilter, onResetFilters,
<div className='ffg-row'>
{/* Plage horaire */}
<div className='form-group togglable'>
- <label className='control-label'>Plage horaire au départ de la course</label>
+ <label className='control-label'>{I18n.t("vehicle_journeys.form.departure_range.label")}</label>
<div className='filter_menu'>
<div className='form-group time filter_menu-item'>
- <label className='control-label time'>Début</label>
+ <label className='control-label time'>{I18n.t("vehicle_journeys.form.departure_range.start")}</label>
<div className='form-inline'>
<div className='input-group time'>
<input
@@ -69,7 +73,7 @@ export default function Filters({filters, pagination, onFilter, onResetFilters,
</div>
</div>
<div className='form-group time filter_menu-item'>
- <label className='control-label time'>Fin</label>
+ <label className='control-label time'>{I18n.t("vehicle_journeys.form.departure_range.end")}</label>
<div className='form-inline'>
<div className='input-group time'>
<input
@@ -97,7 +101,7 @@ export default function Filters({filters, pagination, onFilter, onResetFilters,
{/* Switch avec/sans horaires */}
<div className='form-group has_switch'>
- <label className='control-label pull-left'>Afficher les courses sans horaires</label>
+ <label className='control-label pull-left'>{I18n.t("vehicle_journeys.form.show_journeys_without_schedule")}</label>
<div className='form-group pull-left' style={{padding: 0}}>
<div className='checkbox'>
<label>
@@ -106,8 +110,8 @@ export default function Filters({filters, pagination, onFilter, onResetFilters,
onChange={onToggleWithoutSchedule}
checked={filters.query.withoutSchedule}
></input>
- <span className='switch-label' data-checkedvalue='Non' data-uncheckedvalue='Oui'>
- {filters.query.withoutSchedule ? 'Oui' : 'Non'}
+ <span className='switch-label' data-checkedvalue={I18n.t("no")} data-uncheckedvalue={I18n.t("yes")}>
+ {filters.query.withoutSchedule ? I18n.t("yes") : I18n.t("no")}
</span>
</label>
</div>
@@ -118,7 +122,7 @@ export default function Filters({filters, pagination, onFilter, onResetFilters,
<div className="ffg-row">
{/* Switch avec/sans calendrier */}
<div className='form-group has_switch'>
- <label className='control-label pull-left'>Afficher les courses avec calendrier</label>
+ <label className='control-label pull-left'>{I18n.t("vehicle_journeys.form.show_journeys_with_calendar")}</label>
<div className='form-group pull-left' style={{padding: 0}}>
<div className='checkbox'>
<label>
@@ -127,8 +131,8 @@ export default function Filters({filters, pagination, onFilter, onResetFilters,
onChange={onToggleWithoutTimeTable}
checked={filters.query.withoutTimeTable}
></input>
- <span className='switch-label' data-checkedvalue='Non' data-uncheckedvalue='Oui'>
- {filters.query.withoutTimeTable ? 'Oui' : 'Non'}
+ <span className='switch-label' data-checkedvalue={I18n.t("no")} data-uncheckedvalue={I18n.t("yes")}>
+ {filters.query.withoutTimeTable ? I18n.t("yes") : I18n.t("no")}
</span>
</label>
</div>
@@ -165,4 +169,4 @@ Filters.propTypes = {
onSelect2Timetable: PropTypes.func.isRequired,
onSelect2JourneyPattern: PropTypes.func.isRequired,
onSelect2VehicleJourney: PropTypes.func.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/Navigate.js b/app/javascript/vehicle_journeys/components/Navigate.js
index 7493b705b..24843babc 100644
--- a/app/javascript/vehicle_journeys/components/Navigate.js
+++ b/app/javascript/vehicle_journeys/components/Navigate.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from'../actions'
export default function Navigate({ dispatch, vehicleJourneys, pagination, status, filters}) {
@@ -16,8 +17,7 @@ export default function Navigate({ dispatch, vehicleJourneys, pagination, status
if(status.fetchSuccess == true) {
return (
<div className="pagination">
- Liste des horaires {minVJ} à {maxVJ} sur {pagination.totalCount}
-
+ {I18n.t("vehicle_journeys.vehicle_journeys_matrix.pagination", {minVJ, maxVJ, total:pagination.totalCount})}
<form className='page_links' onSubmit={e => {e.preventDefault()}}>
<button
onClick={e => {
@@ -52,4 +52,4 @@ Navigate.propTypes = {
status: PropTypes.object.isRequired,
pagination: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/SaveVehicleJourneys.js b/app/javascript/vehicle_journeys/components/SaveVehicleJourneys.js
index e8c27f92e..fb921df9c 100644
--- a/app/javascript/vehicle_journeys/components/SaveVehicleJourneys.js
+++ b/app/javascript/vehicle_journeys/components/SaveVehicleJourneys.js
@@ -1,34 +1,19 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import SaveButton from '../../helpers/save_button'
import actions from '../actions'
-export default class SaveVehicleJourneys extends Component{
- constructor(props){
- super(props)
+export default class SaveVehicleJourneys extends SaveButton{
+ hasPolicy(){
+ return this.props.filters.policy['vehicle_journeys.update'] == true
}
- render() {
- if (this.props.filters.policy['vehicle_journeys.update'] == false) {
- return false
- }else{
- return (
- <div className='row mt-md'>
- <div className='col-lg-12 text-right'>
- <form className='vehicle_journeys formSubmitr ml-xs' onSubmit={e => {e.preventDefault()}}>
- <button
- className='btn btn-default'
- type='button'
- onClick={e => {
- e.preventDefault()
- this.props.editMode ? this.props.onSubmitVehicleJourneys(this.props.dispatch, this.props.vehicleJourneys) : this.props.onEnterEditMode()
- }}
- >
- {this.props.editMode ? "Valider" : "Editer"}
- </button>
- </form>
- </div>
- </div>
- )
- }
+ formClassName(){
+ return 'vehicle_journeys'
+ }
+
+ submitForm(){
+ this.props.validate(this.props.vehicleJourneys, this.props.dispatch)
}
}
@@ -38,5 +23,6 @@ SaveVehicleJourneys.propTypes = {
status: PropTypes.object.isRequired,
filters: PropTypes.object.isRequired,
onEnterEditMode: PropTypes.func.isRequired,
+ onExitEditMode: PropTypes.func.isRequired,
onSubmitVehicleJourneys: PropTypes.func.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/ToggleArrivals.js b/app/javascript/vehicle_journeys/components/ToggleArrivals.js
index e26ceec3a..9a2b0097f 100644
--- a/app/javascript/vehicle_journeys/components/ToggleArrivals.js
+++ b/app/javascript/vehicle_journeys/components/ToggleArrivals.js
@@ -1,9 +1,11 @@
-import React, { PropTypes } from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
+
export default function ToggleArrivals({filters, onToggleArrivals}) {
return (
<div className='has_switch form-group inline'>
- <label htmlFor='toggleArrivals' className='control-label'>Afficher et éditer les horaires d'arrivée</label>
+ <label htmlFor='toggleArrivals' className='control-label'>{I18n.t('vehicle_journeys.form.show_arrival_time')}</label>
<div className='form-group'>
<div className='checkbox'>
<label>
@@ -24,4 +26,4 @@ export default function ToggleArrivals({filters, onToggleArrivals}) {
ToggleArrivals.propTypes = {
filters : PropTypes.object.isRequired,
onToggleArrivals: PropTypes.func.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/Tools.js b/app/javascript/vehicle_journeys/components/Tools.js
index 7621dfc10..22ea44283 100644
--- a/app/javascript/vehicle_journeys/components/Tools.js
+++ b/app/javascript/vehicle_journeys/components/Tools.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../actions'
import AddVehicleJourney from '../containers/tools/AddVehicleJourney'
import DeleteVehicleJourneys from '../containers/tools/DeleteVehicleJourneys'
@@ -7,6 +8,7 @@ import DuplicateVehicleJourney from '../containers/tools/DuplicateVehicleJourney
import EditVehicleJourney from '../containers/tools/EditVehicleJourney'
import NotesEditVehicleJourney from '../containers/tools/NotesEditVehicleJourney'
import TimetablesEditVehicleJourney from '../containers/tools/TimetablesEditVehicleJourney'
+import PurchaseWindowsEditVehicleJourney from '../containers/tools/PurchaseWindowsEditVehicleJourney'
export default class Tools extends Component {
@@ -17,7 +19,12 @@ export default class Tools extends Component {
hasPolicy(key) {
// Check if the user has the policy to disable or not the action
- return this.props.filters.policy[`vehicle_journeys.${key}`]
+ return this.props.filters.policy[`vehicle_journeys.${key}`]
+ }
+
+ hasFeature(key) {
+ // Check if the organisation has the given feature
+ return this.props.filters.features[key]
}
render() {
@@ -25,17 +32,20 @@ export default class Tools extends Component {
return (
<div className='select_toolbox'>
<ul>
- <AddVehicleJourney disabled={this.hasPolicy("create") && !editMode} />
- <DuplicateVehicleJourney disabled={this.hasPolicy("create") && this.hasPolicy("update") && !editMode}/>
- <ShiftVehicleJourney disabled={this.hasPolicy("update") && !editMode}/>
+ <AddVehicleJourney disabled={!this.hasPolicy("create") || !editMode} />
+ <DuplicateVehicleJourney disabled={!this.hasPolicy("create") || !this.hasPolicy("update") || !editMode}/>
+ <ShiftVehicleJourney disabled={!this.hasPolicy("update") || !editMode}/>
<EditVehicleJourney disabled={!this.hasPolicy("update")}/>
<TimetablesEditVehicleJourney disabled={!this.hasPolicy("update")}/>
+ { this.hasFeature('purchase_windows') &&
+ <PurchaseWindowsEditVehicleJourney disabled={!this.hasPolicy("update")}/>
+ }
<NotesEditVehicleJourney disabled={!this.hasPolicy("update")}/>
- <DeleteVehicleJourneys disabled={this.hasPolicy("destroy") && !editMode}/>
+ <DeleteVehicleJourneys disabled={!this.hasPolicy("destroy") || !editMode}/>
</ul>
- <span className='info-msg'>{actions.getSelected(vehicleJourneys).length} course(s) sélectionnée(s)</span>
- <button className='btn btn-xs btn-link pull-right' onClick={onCancelSelection}>Annuler la sélection</button>
+ <span className='info-msg'>{I18n.t('vehicle_journeys.vehicle_journeys_matrix.selected_journeys', {count: actions.getSelected(vehicleJourneys).length})}</span>
+ <button className='btn btn-xs btn-link pull-right' onClick={onCancelSelection}>{I18n.t('vehicle_journeys.vehicle_journeys_matrix.cancel_selection')}</button>
</div>
)
}
@@ -45,4 +55,4 @@ Tools.propTypes = {
vehicleJourneys : PropTypes.array.isRequired,
onCancelSelection: PropTypes.func.isRequired,
filters: PropTypes.object.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/VehicleJourney.js b/app/javascript/vehicle_journeys/components/VehicleJourney.js
index 929cbc5c4..4a9432231 100644
--- a/app/javascript/vehicle_journeys/components/VehicleJourney.js
+++ b/app/javascript/vehicle_journeys/components/VehicleJourney.js
@@ -1,5 +1,8 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../actions'
+import EditVehicleJourney from '../containers/tools/EditVehicleJourney'
+import VehicleJourneyInfoButton from '../containers/tools/VehicleJourneyInfoButton'
export default class VehicleJourney extends Component {
constructor(props) {
@@ -8,13 +11,11 @@ export default class VehicleJourney extends Component {
}
cityNameChecker(sp) {
- let bool = false
- if(sp.stop_area_cityname != this.previousCity){
- bool = true
- this.previousCity = sp.stop_area_cityname
- }
+ return this.props.vehicleJourneys.showHeader(sp.stop_point_objectid)
+ }
- return bool
+ hasFeature(key) {
+ return this.props.filters.features[key]
}
timeTableURL(tt) {
@@ -22,7 +23,16 @@ export default class VehicleJourney extends Component {
let ttURL = refURL + '/time_tables/' + tt.id
return (
- <a href={ttURL} title='Voir le calendrier'><span className='fa fa-calendar' style={{color: (tt.color ? tt.color : '')}}></span></a>
+ <a href={ttURL} title={I18n.t('vehicle_journeys.vehicle_journeys_matrix.show_timetable')}><span className='fa fa-calendar' style={{ color: (tt.color ? tt.color : '#4B4B4B')}}></span></a>
+ )
+ }
+
+ purchaseWindowURL(tt) {
+ let refURL = window.location.pathname.split('/', 3).join('/')
+ let ttURL = refURL + '/purchase_windows/' + tt.id
+
+ return (
+ <a href={ttURL} title={I18n.t('vehicle_journeys.vehicle_journeys_matrix.show_purchase_window')}><span className='fa fa-calendar' style={{color: (tt.color ? tt.color : '')}}></span></a>
)
}
@@ -44,20 +54,35 @@ export default class VehicleJourney extends Component {
render() {
this.previousCity = undefined
- let {time_tables} = this.props.value
+ let {time_tables, purchase_windows} = this.props.value
return (
<div className={'t2e-item' + (this.props.value.deletable ? ' disabled' : '') + (this.props.value.errors ? ' has-error': '')}>
- <div className='th'>
+ <div
+ className='th'
+ onClick={(e) =>
+ !this.props.disabled && ($(e.target).parents("a").length == 0) && this.props.onSelectVehicleJourney(this.props.index)
+ }
+ >
<div className='strong mb-xs'>{this.props.value.short_id || '-'}</div>
+ <div>{this.props.value.published_journey_name && this.props.value.published_journey_name != I18n.t('undefined') ? this.props.value.published_journey_name : '-'}</div>
<div>{this.props.value.journey_pattern.short_id || '-'}</div>
+ <div>{this.props.value.company ? this.props.value.company.name : '-'}</div>
<div>
{time_tables.slice(0,3).map((tt, i)=>
<span key={i} className='vj_tt'>{this.timeTableURL(tt)}</span>
)}
{time_tables.length > 3 && <span className='vj_tt'> + {time_tables.length - 3}</span>}
</div>
- <div className={(this.props.value.deletable ? 'disabled ' : '') + 'checkbox'}>
+ { this.hasFeature('purchase_windows') &&
+ <div>
+ {purchase_windows.slice(0,3).map((tt, i)=>
+ <span key={i} className='vj_tt'>{this.purchaseWindowURL(tt)}</span>
+ )}
+ {purchase_windows.length > 3 && <span className='vj_tt'> + {purchase_windows.length - 3}</span>}
+ </div>
+ }
+ {!this.props.disabled && <div className={(this.props.value.deletable ? 'disabled ' : '') + 'checkbox'}>
<input
id={this.props.index}
name={this.props.index}
@@ -68,20 +93,21 @@ export default class VehicleJourney extends Component {
checked={this.props.value.selected}
></input>
<label htmlFor={this.props.index}></label>
- </div>
+ </div>}
+ {this.props.disabled && <VehicleJourneyInfoButton vehicleJourney={this.props.value} />}
</div>
{this.props.value.vehicle_journey_at_stops.map((vj, i) =>
<div key={i} className='td text-center'>
<div className={'cellwrap' + (this.cityNameChecker(vj) ? ' headlined' : '')}>
{this.props.filters.toggleArrivals &&
- <div data-headline='Arrivée à'>
+ <div data-headline={I18n.t("vehicle_journeys.form.arrival_at")}>
<span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false) ? 'disabled ' : '') + 'input-group time'}>
<input
type='number'
min='00'
max='23'
className='form-control'
- disabled={this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false}
+ disabled={!this.props.editMode || this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false}
readOnly={!this.props.editMode && !vj.dummy}
onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'hour', false, false)}}
value={vj.arrival_time['hour']}
@@ -92,7 +118,7 @@ export default class VehicleJourney extends Component {
min='00'
max='59'
className='form-control'
- disabled={this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false}
+ disabled={!this.props.editMode || this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false}
readOnly={!this.props.editMode && !vj.dummy}
onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'minute', false, false)}}
value={vj.arrival_time['minute']}
@@ -105,14 +131,14 @@ export default class VehicleJourney extends Component {
<span className='sb sb-chrono sb-lg text-warning' data-textinside={vj.delta}></span>
}
</div>
- <div data-headline='Départ à'>
+ <div data-headline={I18n.t("vehicle_journeys.form.departure_at")}>
<span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false) ? 'disabled ' : '') + 'input-group time'}>
<input
type='number'
min='00'
max='23'
className='form-control'
- disabled={this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false}
+ disabled={!this.props.editMode || this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false}
readOnly={!this.props.editMode && !vj.dummy}
onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'hour', true, this.props.filters.toggleArrivals)}}
value={vj.departure_time['hour']}
@@ -123,13 +149,16 @@ export default class VehicleJourney extends Component {
min='00'
max='59'
className='form-control'
- disabled={this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false}
+ disabled={!this.props.editMode || this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.update'] == false}
readOnly={!this.props.editMode && !vj.dummy}
onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, "minute", true, this.props.filters.toggleArrivals)}}
value={vj.departure_time['minute']}
/>
</span>
</div>
+ {vj.errors && <div className="errors">
+ {vj.errors}
+ </div>}
</div>
</div>
)}
@@ -143,5 +172,6 @@ VehicleJourney.propTypes = {
filters: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
onUpdateTime: PropTypes.func.isRequired,
- onSelectVehicleJourney: PropTypes.func.isRequired
-} \ No newline at end of file
+ onSelectVehicleJourney: PropTypes.func.isRequired,
+ vehicleJourneys: PropTypes.object.isRequired,
+}
diff --git a/app/javascript/vehicle_journeys/components/VehicleJourneys.js b/app/javascript/vehicle_journeys/components/VehicleJourneys.js
index 6bce9766b..01e07ee0c 100644
--- a/app/javascript/vehicle_journeys/components/VehicleJourneys.js
+++ b/app/javascript/vehicle_journeys/components/VehicleJourneys.js
@@ -1,15 +1,51 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import _ from 'lodash'
import VehicleJourney from './VehicleJourney'
-
+import StopAreaHeaderManager from '../../helpers/stop_area_header_manager'
export default class VehicleJourneys extends Component {
constructor(props){
super(props)
- this.previousCity = undefined
+ this.headerManager = new StopAreaHeaderManager(
+ _.map(this.stopPoints(), (sp)=>{return sp.object_id}),
+ this.stopPoints(),
+ this.props.filters.features
+ )
+ }
+
+ isReturn() {
+ return this.props.routeUrl != undefined
+ }
+
+ vehicleJourneysList() {
+ if(this.isReturn()){
+ return this.props.returnVehicleJourneys
+ }
+ else{
+ return this.props.vehicleJourneys
+ }
+ }
+
+ stopPoints() {
+ if(this.isReturn()){
+ return this.props.returnStopPointsList
+ }
+ else{
+ return this.props.stopPointsList
+ }
}
+
componentDidMount() {
- this.props.onLoadFirstPage(this.props.filters)
+ this.props.onLoadFirstPage(this.props.filters, this.props.routeUrl)
+ }
+
+ hasFeature(key) {
+ return this.props.filters.features[key]
+ }
+
+ showHeader(object_id) {
+ return this.headerManager.showHeader(object_id)
}
componentDidUpdate(prevProps, prevState) {
@@ -55,25 +91,8 @@ export default class VehicleJourneys extends Component {
}
}
- cityNameChecker(sp) {
- let bool = false
- if(sp.city_name != this.previousCity){
- bool = true
- this.previousCity = sp.city_name
- }
- return (
- <div
- className={(bool) ? 'headlined' : ''}
- data-headline={(bool) ? sp.city_name : ''}
- title={sp.city_name + ' (' + sp.zip_code +')'}
- >
- <span><span>{sp.name}</span></span>
- </div>
- )
- }
-
render() {
- this.previousCity = undefined
+ this.previousBreakpoint = undefined
if(this.props.status.isFetching == true) {
return (
@@ -87,15 +106,15 @@ export default class VehicleJourneys extends Component {
<div className='col-lg-12'>
{(this.props.status.fetchSuccess == false) && (
<div className='alert alert-danger mt-sm'>
- <strong>Erreur : </strong>
- la récupération des missions a rencontré un problème. Rechargez la page pour tenter de corriger le problème.
+ <strong>{I18n.tc("error")}</strong>
+ {I18n.t("vehicle_journeys.vehicle_journeys_matrix.fetching_error")}
</div>
)}
- { _.some(this.props.vehicleJourneys, 'errors') && (
+ { this.vehicleJourneysList().errors && this.vehicleJourneysList().errors.length && _.some(this.vehicleJourneysList(), 'errors') && (
<div className="alert alert-danger mt-sm">
- <strong>Erreur : </strong>
- {this.props.vehicleJourneys.map((vj, index) =>
+ <strong>{I18n.tc("error")}</strong>
+ {this.vehicleJourneysList().map((vj, index) =>
vj.errors && vj.errors.map((err, i) => {
return (
<ul key={i}>
@@ -107,17 +126,20 @@ export default class VehicleJourneys extends Component {
</div>
)}
- <div className={'table table-2entries mt-sm mb-sm' + ((this.props.vehicleJourneys.length > 0) ? '' : ' no_result')}>
+ <div className={'table table-2entries mt-sm mb-sm' + ((this.vehicleJourneysList().length > 0) ? '' : ' no_result')}>
<div className='t2e-head w20'>
<div className='th'>
- <div className='strong mb-xs'>ID course</div>
- <div>ID mission</div>
- <div>Calendriers</div>
+ <div className='strong mb-xs'>{I18n.attribute_name("vehicle_journey", "id")}</div>
+ <div>{I18n.attribute_name("vehicle_journey", "name")}</div>
+ <div>{I18n.attribute_name("vehicle_journey", "journey_pattern_id")}</div>
+ <div>{I18n.model_name("company")}</div>
+ <div>{I18n.model_name("time_table", "plural": true)}</div>
+ { this.hasFeature('purchase_windows') && <div>{I18n.model_name("purchase_window", "plural": true)}</div> }
</div>
- {this.props.stopPointsList.map((sp, i) =>{
+ {this.stopPoints().map((sp, i) =>{
return (
<div key={i} className='td'>
- {this.cityNameChecker(sp)}
+ {this.headerManager.stopPointHeader(sp.object_id)}
</div>
)
})}
@@ -125,15 +147,18 @@ export default class VehicleJourneys extends Component {
<div className='t2e-item-list w80'>
<div>
- {this.props.vehicleJourneys.map((vj, index) =>
+ {this.vehicleJourneysList().map((vj, index) =>
<VehicleJourney
value={vj}
key={index}
index={index}
- editMode={this.props.editMode}
+ editMode={this.isReturn() ? false : this.props.editMode}
filters={this.props.filters}
+ features={this.props.features}
onUpdateTime={this.props.onUpdateTime}
onSelectVehicleJourney={this.props.onSelectVehicleJourney}
+ vehicleJourneys={this}
+ disabled={this.isReturn()}
/>
)}
</div>
@@ -153,4 +178,4 @@ VehicleJourneys.propTypes = {
onLoadFirstPage: PropTypes.func.isRequired,
onUpdateTime: PropTypes.func.isRequired,
onSelectVehicleJourney: PropTypes.func.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/tools/CreateModal.js b/app/javascript/vehicle_journeys/components/tools/CreateModal.js
index 33873219c..8536f66e6 100644
--- a/app/javascript/vehicle_journeys/components/tools/CreateModal.js
+++ b/app/javascript/vehicle_journeys/components/tools/CreateModal.js
@@ -1,16 +1,19 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../../actions'
import MissionSelect2 from './select2s/MissionSelect2'
import CompanySelect2 from './select2s/CompanySelect2'
+import CustomFieldsInputs from './CustomFieldsInputs'
export default class CreateModal extends Component {
constructor(props) {
super(props)
+ this.custom_fields = _.assign({}, this.props.custom_fields)
}
handleSubmit() {
if (actions.validateFields(...this.refs, $('.vjCreateSelectJP')[0]) && this.props.modal.modalProps.selectedJPModal) {
- this.props.onAddVehicleJourney(this.refs, this.props.modal.modalProps.selectedJPModal, this.props.stopPointsList, this.props.modal.modalProps.selectedCompany)
+ this.props.onAddVehicleJourney(_.assign({}, this.refs, {custom_fields: this.custom_fields}), this.props.modal.modalProps.selectedJPModal, this.props.stopPointsList, this.props.modal.modalProps.vehicleJourney && this.props.modal.modalProps.vehicleJourney.company)
this.props.onModalClose()
$('#NewVehicleJourneyModal').modal('hide')
}
@@ -61,8 +64,9 @@ export default class CreateModal extends Component {
<div className='form-group'>
<label className='control-label'>Nom du transporteur</label>
<CompanySelect2
- company = {undefined}
+ company = {this.props.modal.modalProps.vehicleJourney && this.props.modal.modalProps.vehicleJourney.company || undefined}
onSelect2Company = {(e) => this.props.onSelect2Company(e)}
+ onUnselect2Company = {() => this.props.onUnselect2Company()}
/>
</div>
</div>
@@ -72,6 +76,7 @@ export default class CreateModal extends Component {
<MissionSelect2
selection={this.props.modal.modalProps}
onSelect2JourneyPattern={this.props.onSelect2JourneyPattern}
+ values={this.props.missions}
isFilter={false}
/>
</div>
@@ -87,6 +92,36 @@ export default class CreateModal extends Component {
/>
</div>
</div>
+ <CustomFieldsInputs
+ values={this.props.custom_fields}
+ onUpdate={(code, value) => this.custom_fields[code]["value"] = value}
+ disabled={false}
+ />
+ { this.props.modal.modalProps.selectedJPModal && this.props.modal.modalProps.selectedJPModal.full_schedule && <div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'>
+ <div className='form-group'>
+ <label className='control-label'>Heure de départ</label>
+ <div className='input-group time'>
+ <input
+ type='number'
+ min='00'
+ max='23'
+ ref='start_time.hour'
+ className='form-control'
+ onKeyDown={(e) => actions.resetValidation(e.currentTarget)}
+ />
+ <input
+ type='number'
+ min='00'
+ max='59'
+ ref='start_time.minute'
+ className='form-control'
+ onKeyDown={(e) => actions.resetValidation(e.currentTarget)}
+ />
+ </div>
+ </div>
+ </div>
+ }
+
</div>
</div>
<div className='modal-footer'>
@@ -129,5 +164,6 @@ CreateModal.propTypes = {
onModalClose: PropTypes.func.isRequired,
onAddVehicleJourney: PropTypes.func.isRequired,
onSelect2JourneyPattern: PropTypes.func.isRequired,
- disabled: PropTypes.bool.isRequired
-} \ No newline at end of file
+ disabled: PropTypes.bool.isRequired,
+ missions: PropTypes.array.isRequired
+}
diff --git a/app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js b/app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js
new file mode 100644
index 000000000..90d72a801
--- /dev/null
+++ b/app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js
@@ -0,0 +1,50 @@
+import _ from 'lodash'
+import Select2 from 'react-select2-wrapper'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+
+export default class CustomFieldsInputs extends Component {
+ constructor(props) {
+ super(props)
+ }
+
+ listInput(cf){
+ return(
+ <Select2
+ data={_.map(cf.options.list_values, (v, k) => {
+ return {id: k, text: (v.length > 0 ? v : '\u00A0')}
+ })}
+ ref={'custom_fields.' + cf.code}
+ className='form-control'
+ defaultValue={cf.value}
+ disabled={this.props.disabled}
+ options={{
+ theme: 'bootstrap',
+ width: '100%'
+ }}
+ onSelect={(e) => this.props.onUpdate(cf.code, e.params.data.id) }
+ />
+ )
+ }
+
+ render() {
+ return (
+ <div>
+ {_.map(this.props.values, (cf, code) =>
+ <div className='col-lg-6 col-md-6 col-sm-6 col-xs-12' key={code}>
+ <div className='form-group'>
+ <label className='control-label'>{cf.name}</label>
+ {this[cf.field_type + "Input"](cf)}
+ </div>
+ </div>
+ )}
+ </div>
+ )
+ }
+}
+
+CustomFieldsInputs.propTypes = {
+ onUpdate: PropTypes.func.isRequired,
+ values: PropTypes.object.isRequired,
+ disabled: PropTypes.bool.isRequired
+}
diff --git a/app/javascript/vehicle_journeys/components/tools/DeleteVehicleJourneys.js b/app/javascript/vehicle_journeys/components/tools/DeleteVehicleJourneys.js
index fc13ae964..4815003d3 100644
--- a/app/javascript/vehicle_journeys/components/tools/DeleteVehicleJourneys.js
+++ b/app/javascript/vehicle_journeys/components/tools/DeleteVehicleJourneys.js
@@ -1,4 +1,6 @@
-import React, { PropTypes } from 'react'
+import React from 'react'
+import PropTypes from 'prop-types'
+
import actions from '../../actions'
export default function DeleteVehicleJourneys({onDeleteVehicleJourneys, vehicleJourneys, disabled}) {
diff --git a/app/javascript/vehicle_journeys/components/tools/DuplicateVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/DuplicateVehicleJourney.js
index 8083defb9..102a87d85 100644
--- a/app/javascript/vehicle_journeys/components/tools/DuplicateVehicleJourney.js
+++ b/app/javascript/vehicle_journeys/components/tools/DuplicateVehicleJourney.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../../actions'
import _ from 'lodash'
diff --git a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js
index f8d6add03..d3c01f154 100644
--- a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js
+++ b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js
@@ -1,33 +1,47 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../../actions'
import CompanySelect2 from './select2s/CompanySelect2'
+import CustomFieldsInputs from './CustomFieldsInputs'
export default class EditVehicleJourney extends Component {
constructor(props) {
super(props)
+ this.updateValue = this.updateValue.bind(this)
}
handleSubmit() {
if(actions.validateFields(this.refs) == true) {
- var company;
+ var company = undefined
if(this.props.modal.modalProps.selectedCompany) {
company = this.props.modal.modalProps.selectedCompany
- } else if (typeof this.props.modal.modalProps.vehicleJourney.company === Object) {
+ } 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.onEditVehicleJourney(_.assign({}, this.refs, {custom_fields: this.custom_fields}), company)
this.props.onModalClose()
$('#EditVehicleJourneyModal').modal('hide')
}
}
+ updateValue(attribute, e) {
+ this.props.modal.modalProps.vehicleJourney[attribute] = e.target.value
+ actions.resetValidation(e.currentTarget)
+ this.forceUpdate()
+ }
+
+ editMode() {
+ return !this.props.modal.modalProps.info && this.props.editMode
+ }
+
render() {
if(this.props.status.isFetching == true) {
return false
}
if(this.props.status.fetchSuccess == true) {
+ if(this.props.modal.modalProps.vehicleJourney){
+ this.custom_fields = _.assign({}, this.props.modal.modalProps.vehicleJourney.custom_fields)
+ }
return (
<li className='st_action'>
<button
@@ -45,60 +59,60 @@ export default class EditVehicleJourney extends Component {
<div className='modal-dialog'>
<div className='modal-content'>
<div className='modal-header'>
- <h4 className='modal-title'>Informations</h4>
+ <h4 className='modal-title'>{I18n.t('vehicle_journeys.form.infos')}</h4>
<span type="button" className="close modal-close" data-dismiss="modal">&times;</span>
</div>
{(this.props.modal.type == 'edit') && (
<form>
<div className='modal-body'>
- <div className='row'>
- <div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'>
- <div className='form-group'>
- <label className='control-label'>Nom de la course</label>
- <input
- type='text'
- ref='published_journey_name'
- className='form-control'
- disabled={!this.props.editMode}
- defaultValue={this.props.modal.modalProps.vehicleJourney.published_journey_name}
- onKeyDown={(e) => actions.resetValidation(e.currentTarget)}
- />
+ <div className='row'>
+ <div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'>
+ <div className='form-group'>
+ <label className='control-label'>{I18n.attribute_name('vehicle_journey', 'journey_name')}</label>
+ <input
+ type='text'
+ ref='published_journey_name'
+ className='form-control'
+ disabled={!this.editMode()}
+ value={this.props.modal.modalProps.vehicleJourney.published_journey_name}
+ onChange={(e) => this.updateValue('published_journey_name', e)}
+ />
+ </div>
</div>
- </div>
- <div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'>
- <div className='form-group'>
- <label className='control-label'>Mission</label>
- <input
- type='text'
- className='form-control'
- value={this.props.modal.modalProps.vehicleJourney.journey_pattern.short_id + ' - ' + (this.props.modal.modalProps.vehicleJourney.journey_pattern.name)}
- disabled={true}
- />
+ <div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'>
+ <div className='form-group'>
+ <label className='control-label'>{I18n.attribute_name('vehicle_journey', 'journey_pattern')}</label>
+ <input
+ type='text'
+ className='form-control'
+ value={this.props.modal.modalProps.vehicleJourney.journey_pattern.short_id + ' - ' + (this.props.modal.modalProps.vehicleJourney.journey_pattern.name)}
+ disabled={true}
+ />
+ </div>
</div>
</div>
- </div>
<div className='row'>
<div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'>
<div className='form-group'>
- <label className='control-label'>Numéro de train</label>
+ <label className='control-label'>{I18n.attribute_name('vehicle_journey', 'company')}</label>
<input
type='text'
ref='published_journey_identifier'
className='form-control'
- disabled={!this.props.editMode}
- defaultValue={this.props.modal.modalProps.vehicleJourney.published_journey_identifier}
- onKeyDown={(e) => actions.resetValidation(e.currentTarget)}
+ disabled={!this.editMode()}
+ value={this.props.modal.modalProps.vehicleJourney.published_journey_identifier}
+ onChange={(e) => this.updateValue('published_journey_identifier', e)}
/>
</div>
</div>
<div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'>
<div className='form-group'>
- <label className='control-label'>Transporteur</label>
+ <label className='control-label'>{I18n.attribute_name('vehicle_journey', 'company')}</label>
<CompanySelect2
editModal={this.props.modal.type == "edit"}
- editMode={this.props.editMode}
+ editMode={this.editMode()}
company = {this.props.modal.modalProps.vehicleJourney.company}
onSelect2Company = {(e) => this.props.onSelect2Company(e)}
onUnselect2Company = {() => this.props.onUnselect2Company()}
@@ -110,30 +124,48 @@ export default class EditVehicleJourney extends Component {
<div className='row'>
<div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'>
<div className='form-group'>
- <label className='control-label'>Mode de transport</label>
+ <label className='control-label'>{I18n.attribute_name('vehicle_journey', 'transport_mode')}</label>
<input
type='text'
className='form-control'
- value={window.I18n.fr.enumerize.transport_mode[this.props.modal.modalProps.vehicleJourney.transport_mode]}
+ value={I18n.enumerize('transport_mode', this.props.modal.modalProps.vehicleJourney.transport_mode)}
disabled={true}
/>
</div>
</div>
<div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'>
<div className='form-group'>
- <label className='control-label'>Sous mode de transport</label>
+ <label className='control-label'>{I18n.attribute_name('vehicle_journey', 'transport_submode')}</label>
<input
type='text'
className='form-control'
- value={window.I18n.fr.enumerize.transport_submode[this.props.modal.modalProps.vehicleJourney.transport_submode]}
+ value={I18n.enumerize('transport_submode', this.props.modal.modalProps.vehicleJourney.transport_submode)}
disabled={true}
/>
</div>
</div>
</div>
+ <div className='form-group'>
+ <label className='control-label'>{I18n.attribute_name('vehicle_journey', 'checksum')}</label>
+ <input
+ type='text'
+ ref='checksum'
+ className='form-control'
+ disabled='disabled'
+ defaultValue={this.props.modal.modalProps.vehicleJourney.checksum}
+ />
+ </div>
+ <div className='row'>
+ <CustomFieldsInputs
+ values={this.props.modal.modalProps.vehicleJourney.custom_fields}
+ onUpdate={(code, value) => this.custom_fields[code]["value"] = value}
+ disabled={!this.editMode()}
+ />
+ </div>
</div>
+
{
- this.props.editMode &&
+ this.editMode() &&
<div className='modal-footer'>
<button
className='btn btn-link'
@@ -151,7 +183,7 @@ export default class EditVehicleJourney extends Component {
Valider
</button>
</div>
- }
+ }
</form>
)}
@@ -171,4 +203,4 @@ EditVehicleJourney.propTypes = {
onOpenEditModal: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired,
disabled: PropTypes.bool.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js
index de97bc403..880542216 100644
--- a/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js
+++ b/app/javascript/vehicle_journeys/components/tools/NotesEditVehicleJourney.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../../actions'
import _ from 'lodash'
diff --git a/app/javascript/vehicle_journeys/components/tools/PurchaseWindowsEditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/PurchaseWindowsEditVehicleJourney.js
new file mode 100644
index 000000000..ce9a4cde9
--- /dev/null
+++ b/app/javascript/vehicle_journeys/components/tools/PurchaseWindowsEditVehicleJourney.js
@@ -0,0 +1,153 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import actions from '../../actions'
+import TimetableSelect2 from './select2s/TimetableSelect2'
+
+export default class PurchaseWindowsEditVehicleJourney extends Component {
+ constructor(props) {
+ super(props)
+ this.handleSubmit = this.handleSubmit.bind(this)
+ this.purchaseWindowURL = this.purchaseWindowURL.bind(this)
+ }
+
+ handleSubmit() {
+ this.props.onShoppingWindowsEditVehicleJourney(this.props.modal.modalProps.vehicleJourneys, this.props.modal.modalProps.purchase_windows)
+ this.props.onModalClose()
+ $('#PurchaseWindowsEditVehicleJourneyModal').modal('hide')
+ }
+
+ purchaseWindowURL(tt) {
+ let refURL = window.location.pathname.split('/', 3).join('/')
+ return refURL + '/purchase_windows/' + tt.id
+ }
+
+ render() {
+ if(this.props.status.isFetching == true) {
+ return false
+ }
+ if(this.props.status.fetchSuccess == true) {
+ return (
+ <li className='st_action'>
+ <button
+ type='button'
+ disabled={(actions.getSelected(this.props.vehicleJourneys).length < 1 || this.props.disabled)}
+ data-toggle='modal'
+ data-target='#PurchaseWindowsEditVehicleJourneyModal'
+ onClick={() => this.props.onOpenCalendarsEditModal(actions.getSelected(this.props.vehicleJourneys))}
+ title='Calendriers commerciaux'
+ >
+ <span className='sb sb-purchase_window sb-strong'></span>
+ </button>
+
+ <div className={ 'modal fade ' + ((this.props.modal.type == 'duplicate') ? 'in' : '') } id='PurchaseWindowsEditVehicleJourneyModal'>
+ <div className='modal-container'>
+ <div className='modal-dialog'>
+ <div className='modal-content'>
+ <div className='modal-header'>
+ <h4 className='modal-title'>Calendriers commerciaux associés</h4>
+ <span type="button" className="close modal-close" data-dismiss="modal">&times;</span>
+ </div>
+
+ {(this.props.modal.type == 'purchase_windows_edit') && (
+ <form>
+ <div className='modal-body'>
+ <div className='row'>
+ <div className='col-lg-12'>
+ <div className='subform'>
+ <div className='nested-head'>
+ <div className='wrapper'>
+ <div>
+ <div className='form-group'>
+ <label className='control-label'>{this.props.modal.modalProps.purchase_windows.length == 0 ? "Aucun calendrier commercial associé" : "Calendriers commerciaux associés"}</label>
+ </div>
+ </div>
+ <div></div>
+ </div>
+ </div>
+ {this.props.modal.modalProps.purchase_windows.map((tt, i) =>
+ <div className='nested-fields' key={i}>
+ <div className='wrapper'>
+ <div> <a href={this.purchaseWindowURL(tt)} target="_blank">
+ <span className="fa fa-circle mr-xs" style={{color: tt.color}}></span>
+ {tt.name}
+ </a> </div>
+ {
+ this.props.editMode &&
+ <div>
+ <a
+ href='#'
+ title='Supprimer'
+ className='fa fa-trash remove_fields'
+ style={{ height: 'auto', lineHeight: 'normal' }}
+ onClick={(e) => {
+ e.preventDefault()
+ this.props.onDeleteCalendarModal(tt)
+ }}
+ ></a>
+ </div>
+ }
+ </div>
+ </div>
+ )}
+ {
+ this.props.editMode &&
+ <div className='nested-fields'>
+ <div className='wrapper'>
+ <div>
+ <TimetableSelect2
+ onSelect2Timetable={this.props.onSelect2Timetable}
+ chunkURL={'/autocomplete_purchase_windows.json'}
+ searchKey={"name_or_objectid_cont_any"}
+ isFilter={false}
+ />
+ </div>
+ </div>
+ </div>
+ }
+ </div>
+ </div>
+ </div>
+ </div>
+ {
+ this.props.editMode &&
+ <div className='modal-footer'>
+ <button
+ className='btn btn-link'
+ data-dismiss='modal'
+ type='button'
+ onClick={this.props.onModalClose}
+ >
+ Annuler
+ </button>
+ <button
+ className='btn btn-primary'
+ type='button'
+ onClick={this.handleSubmit}
+ >
+ Valider
+ </button>
+ </div>
+ }
+ </form>
+ )}
+
+ </div>
+ </div>
+ </div>
+ </div>
+ </li>
+ )
+ } else {
+ return false
+ }
+ }
+}
+
+PurchaseWindowsEditVehicleJourney.propTypes = {
+ onOpenCalendarsEditModal: PropTypes.func.isRequired,
+ onModalClose: PropTypes.func.isRequired,
+ onShoppingWindowsEditVehicleJourney: PropTypes.func.isRequired,
+ onDeleteCalendarModal: PropTypes.func.isRequired,
+ onSelect2Timetable: PropTypes.func.isRequired,
+ disabled: PropTypes.bool.isRequired
+}
diff --git a/app/javascript/vehicle_journeys/components/tools/ShiftVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/ShiftVehicleJourney.js
index a54e40502..6574bfa2d 100644
--- a/app/javascript/vehicle_journeys/components/tools/ShiftVehicleJourney.js
+++ b/app/javascript/vehicle_journeys/components/tools/ShiftVehicleJourney.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../../actions'
export default class ShiftVehicleJourney extends Component {
diff --git a/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js
index 6629135dd..e2fcd27d5 100644
--- a/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js
+++ b/app/javascript/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js
@@ -1,4 +1,5 @@
-import React, { PropTypes, Component } from 'react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
import actions from '../../actions'
import TimetableSelect2 from './select2s/TimetableSelect2'
@@ -33,6 +34,7 @@ export default class TimetablesEditVehicleJourney extends Component {
data-toggle='modal'
data-target='#CalendarsEditVehicleJourneyModal'
onClick={() => this.props.onOpenCalendarsEditModal(actions.getSelected(this.props.vehicleJourneys))}
+ title='Calendriers'
>
<span className='fa fa-calendar'></span>
</button>
@@ -65,9 +67,14 @@ export default class TimetablesEditVehicleJourney extends Component {
{this.props.modal.modalProps.timetables.map((tt, i) =>
<div className='nested-fields' key={i}>
<div className='wrapper'>
- <div> <a href={this.timeTableURL(tt)} target="_blank">{tt.comment}</a> </div>
+ <div>
+ <a href={this.timeTableURL(tt)} target="_blank">
+ <span className="fa fa-circle mr-xs" style={{color: tt.color || 'black'}}></span>
+ {tt.comment}
+ </a>
+ </div>
{
- this.props.editMode &&
+ this.props.editMode &&
<div>
<a
href='#'
@@ -85,13 +92,14 @@ export default class TimetablesEditVehicleJourney extends Component {
</div>
)}
{
- this.props.editMode &&
+ this.props.editMode &&
<div className='nested-fields'>
<div className='wrapper'>
<div>
<TimetableSelect2
onSelect2Timetable={this.props.onSelect2Timetable}
chunkURL={'/autocomplete_time_tables.json'}
+ searchKey={"comment_or_objectid_cont_any"}
isFilter={false}
/>
</div>
@@ -103,7 +111,7 @@ export default class TimetablesEditVehicleJourney extends Component {
</div>
</div>
{
- this.props.editMode &&
+ this.props.editMode &&
<div className='modal-footer'>
<button
className='btn btn-link'
@@ -144,4 +152,4 @@ TimetablesEditVehicleJourney.propTypes = {
onDeleteCalendarModal: PropTypes.func.isRequired,
onSelect2Timetable: PropTypes.func.isRequired,
disabled: PropTypes.bool.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/tools/VehicleJourneyInfoButton.js b/app/javascript/vehicle_journeys/components/tools/VehicleJourneyInfoButton.js
new file mode 100644
index 000000000..538bbdbd6
--- /dev/null
+++ b/app/javascript/vehicle_journeys/components/tools/VehicleJourneyInfoButton.js
@@ -0,0 +1,30 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import actions from '../../actions'
+
+export default class VehicleJourneyInfoButton extends Component {
+ constructor(props) {
+ super(props)
+ }
+
+
+ render() {
+ return (
+ <div className='info-button'>
+ <button
+ type='button'
+ data-toggle='modal'
+ data-target='#EditVehicleJourneyModal'
+ onClick={() => this.props.onOpenEditModal(this.props.vehicleJourney)}
+ >
+ <span className='fa fa-info'></span>
+ </button>
+ </div>
+ )
+ }
+}
+
+VehicleJourneyInfoButton.propTypes = {
+ onOpenEditModal: PropTypes.func.isRequired,
+ vehicleJourney: PropTypes.object.isRequired,
+}
diff --git a/app/javascript/vehicle_journeys/components/tools/select2s/CompanySelect2.js b/app/javascript/vehicle_journeys/components/tools/select2s/CompanySelect2.js
index 79ba8f094..5c7f75d99 100644
--- a/app/javascript/vehicle_journeys/components/tools/select2s/CompanySelect2.js
+++ b/app/javascript/vehicle_journeys/components/tools/select2s/CompanySelect2.js
@@ -1,6 +1,7 @@
import _ from 'lodash'
-import React, { PropTypes, Component } from 'react'
-import Select2 from 'react-select2'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import Select2 from 'react-select2-wrapper'
import actions from '../../../actions'
// get JSON full path
@@ -25,7 +26,7 @@ export default class BSelect4 extends Component {
multiple={false}
ref='company_id'
options={{
- allowClear: this.props.editMode,
+ allowClear: true,
theme: 'bootstrap',
width: '100%',
placeholder: 'Filtrer par transporteur...',
diff --git a/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js b/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js
index fa847886c..7ab85a1ea 100644
--- a/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js
+++ b/app/javascript/vehicle_journeys/components/tools/select2s/MissionSelect2.js
@@ -1,6 +1,7 @@
import _ from 'lodash'
-import React, { PropTypes, Component } from 'react'
-import Select2 from 'react-select2'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import Select2 from 'react-select2-wrapper'
import actions from '../../../actions'
// get JSON full path
@@ -11,50 +12,114 @@ let path = window.location.pathname.split('/', 7).join('/')
export default class BSelect4 extends Component {
constructor(props) {
super(props)
+ this.onSelect = this.onSelect.bind(this)
+ }
+
+ useAjax(){
+ return this.props.values == undefined || this.props.values.length == 0
+ }
+
+ value(){
+ let val = undefined
+ if(this.props.isFilter) {
+ val = this.props.filters.query.journeyPattern
+ }
+ else{
+ if(this.props.selection.selectedJPModal){
+ val = this.props.selection.selectedJPModal
+ }
+ }
+ if(this.useAjax()){
+ val = val.published_name
+ }
+ else{
+ if(val){
+ val = val.id
+ }
+ }
+ return val
+ }
+
+ data(){
+ if(!this.useAjax()){
+ let values = [{}]
+ values.push(...this.props.values)
+ return values
+ }
+ if(this.props.isFilter){
+ return [this.props.filters.query.journeyPattern.published_name]
+ }
+
+ return (this.props.selection.selectedJPModal) ? [this.props.selection.selectedJPModal.published_name] : undefined
+ }
+
+ onSelect(e){
+ if(this.useAjax()){
+ this.props.onSelect2JourneyPattern(e)
+ }
+ else{
+ let data = JSON.parse(e.currentTarget.selectedOptions[0].dataset.item)
+
+ this.props.onSelect2JourneyPattern({params:
+ {
+ data: _.assign({}, e.params.data, data)
+ }
+ })
+ }
+ }
+
+ options(){
+ let options = {
+ theme: 'bootstrap',
+ width: '100%',
+ escapeMarkup: function (markup) { return markup; },
+ templateResult: formatRepo,
+ placeholder: 'Filtrer par code, nom ou OID de mission...',
+ language: require('./fr'),
+ allowClear: false,
+ escapeMarkup: function (markup) { return markup; },
+ }
+ if(this.useAjax()){
+ options = _.assign({}, options, {
+ ajax: {
+ url: origin + path + '/journey_patterns_collection.json',
+ dataType: 'json',
+ delay: '500',
+ data: function(params) {
+ return {
+ q: { published_name_or_objectid_or_registration_number_cont: params.term},
+ };
+ },
+ processResults: function(data, params) {
+ return {
+ results: data.map(
+ item => _.assign(
+ {},
+ item,
+ { text: "<strong>" + item.published_name + " - " + item.short_id + "</strong><br/><small>" + item.registration_number + "</small>" }
+ )
+ )
+ };
+ },
+ cache: true
+ },
+ minimumInputLength: 1
+ })
+ }
+ return options
}
render() {
return (
<Select2
- data={(this.props.isFilter) ? [this.props.filters.query.journeyPattern.published_name] : ((this.props.selection.selectedJPModal) ? [this.props.selection.selectedJPModal.published_name] : undefined)}
- value={(this.props.isFilter) ? this.props.filters.query.journeyPattern.published_name : ((this.props.selection.selectedJPModal) ? this.props.selection.selectedJPModal.published_name : undefined) }
- onSelect={(e) => this.props.onSelect2JourneyPattern(e)}
+ data={this.data()}
+ value={this.value()}
+ onSelect={this.onSelect}
multiple={false}
ref='journey_pattern_id'
className={!this.props.isFilter ? "vjCreateSelectJP" : null}
required={!this.props.isFilter}
- options={{
- allowClear: false,
- theme: 'bootstrap',
- placeholder: 'Filtrer par code, nom ou OID de mission...',
- language: require('./fr'),
- width: '100%',
- ajax: {
- url: origin + path + '/journey_patterns_collection.json',
- dataType: 'json',
- delay: '500',
- data: function(params) {
- return {
- q: { published_name_or_objectid_or_registration_number_cont: params.term},
- };
- },
- processResults: function(data, params) {
- return {
- results: data.map(
- item => _.assign(
- {},
- item,
- { text: "<strong>" + item.published_name + " - " + item.short_id + "</strong><br/><small>" + item.registration_number + "</small>" }
- )
- )
- };
- },
- cache: true
- },
- minimumInputLength: 1,
- escapeMarkup: function (markup) { return markup; },
- templateResult: formatRepo
- }}
+ options={this.options()}
/>
)
}
@@ -62,4 +127,4 @@ export default class BSelect4 extends Component {
const formatRepo = (props) => {
if(props.text) return props.text
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js b/app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
index 19c183839..0339455ca 100644
--- a/app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
+++ b/app/javascript/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
@@ -1,6 +1,7 @@
import _ from 'lodash'
-import React, { PropTypes, Component } from 'react'
-import Select2 from 'react-select2'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import Select2 from 'react-select2-wrapper'
import actions from '../../../actions'
// get JSON full path
@@ -31,12 +32,10 @@ export default class BSelect4 extends Component {
url: origin + path + this.props.chunkURL,
dataType: 'json',
delay: '500',
- data: function(params) {
- return {
- q: {
- comment_or_objectid_cont_any: params.term
- }
- };
+ data: (params) => {
+ let q = {}
+ q[this.props.searchKey] = params.term
+ return {q}
},
processResults: function(data, params) {
return {
@@ -44,7 +43,7 @@ export default class BSelect4 extends Component {
item => _.assign(
{},
item,
- {text: '<strong>' + "<span class='fa fa-circle' style='color:" + (item.color ? item.color : '#4B4B4B') + "'></span> " + item.comment + ' - ' + item.short_id + '</strong><br/><small>' + (item.day_types ? item.day_types.match(/[A-Z]?[a-z]+/g).join(', ') : "") + '</small>'}
+ {text: '<strong>' + "<span class='fa fa-circle' style='color:" + (item.color ? item.color : '#4B4B4B') + "'></span> " + (item.comment || item.name) + ' - ' + item.short_id + '</strong><br/><small>' + (item.day_types ? item.day_types.match(/[A-Z]?[a-z]+/g).join(', ') : "") + '</small>'}
)
)
};
@@ -62,4 +61,4 @@ export default class BSelect4 extends Component {
const formatRepo = (props) => {
if(props.text) return props.text
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/components/tools/select2s/VJSelect2.js b/app/javascript/vehicle_journeys/components/tools/select2s/VJSelect2.js
index b063abeca..ccb4c9595 100644
--- a/app/javascript/vehicle_journeys/components/tools/select2s/VJSelect2.js
+++ b/app/javascript/vehicle_journeys/components/tools/select2s/VJSelect2.js
@@ -1,6 +1,7 @@
import _ from 'lodash'
-import React, { PropTypes, Component } from 'react'
-import Select2 from 'react-select2'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import Select2 from 'react-select2-wrapper'
import actions from '../../../actions'
// get JSON full path
diff --git a/app/javascript/vehicle_journeys/containers/Filters.js b/app/javascript/vehicle_journeys/containers/Filters.js
index bec3527f4..a41c599f7 100644
--- a/app/javascript/vehicle_journeys/containers/Filters.js
+++ b/app/javascript/vehicle_journeys/containers/Filters.js
@@ -5,7 +5,8 @@ import Filters from '../components/Filters'
const mapStateToProps = (state) => {
return {
filters: state.filters,
- pagination: state.pagination
+ pagination: state.pagination,
+ missions: state.missions,
}
}
diff --git a/app/javascript/vehicle_journeys/containers/SaveVehicleJourneys.js b/app/javascript/vehicle_journeys/containers/SaveVehicleJourneys.js
index 18f9e994e..3daf831f8 100644
--- a/app/javascript/vehicle_journeys/containers/SaveVehicleJourneys.js
+++ b/app/javascript/vehicle_journeys/containers/SaveVehicleJourneys.js
@@ -17,8 +17,15 @@ const mapDispatchToProps = (dispatch) => {
onEnterEditMode: () => {
dispatch(actions.enterEditMode())
},
+ onExitEditMode: () => {
+ dispatch(actions.cancelSelection())
+ dispatch(actions.exitEditMode())
+ },
onSubmitVehicleJourneys: (next, state) => {
actions.submitVehicleJourneys(dispatch, state, next)
+ },
+ validate: (state) =>{
+ actions.validate(dispatch, state)
}
}
}
diff --git a/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js b/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js
index 38ab9f6d3..76d1c3a78 100644
--- a/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js
+++ b/app/javascript/vehicle_journeys/containers/VehicleJourneysList.js
@@ -6,17 +6,19 @@ const mapStateToProps = (state) => {
return {
editMode: state.editMode,
vehicleJourneys: state.vehicleJourneys,
+ returnVehicleJourneys: state.returnVehicleJourneys,
status: state.status,
filters: state.filters,
- stopPointsList: state.stopPointsList
+ stopPointsList: state.stopPointsList,
+ returnStopPointsList: state.returnStopPointsList
}
}
const mapDispatchToProps = (dispatch) => {
return {
- onLoadFirstPage: (filters) =>{
+ onLoadFirstPage: (filters, routeUrl) =>{
dispatch(actions.fetchingApi())
- actions.fetchVehicleJourneys(dispatch, undefined, undefined, filters.queryString)
+ actions.fetchVehicleJourneys(dispatch, undefined, undefined, filters.queryString, routeUrl)
},
onUpdateTime: (e, subIndex, index, timeUnit, isDeparture, isArrivalsToggled) => {
dispatch(actions.updateTime(e.target.value, subIndex, index, timeUnit, isDeparture, isArrivalsToggled))
diff --git a/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js b/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js
index 5da0bd3e9..d982f5a5f 100644
--- a/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js
+++ b/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js
@@ -9,6 +9,8 @@ const mapStateToProps = (state, ownProps) => {
vehicleJourneys: state.vehicleJourneys,
status: state.status,
stopPointsList: state.stopPointsList,
+ missions: state.missions,
+ custom_fields: state.custom_fields,
}
}
@@ -28,6 +30,9 @@ const mapDispatchToProps = (dispatch) => {
},
onSelect2Company: (e) => {
dispatch(actions.select2Company(e.params.data))
+ },
+ onUnselect2Company: () => {
+ dispatch(actions.unselect2Company())
}
}
}
diff --git a/app/javascript/vehicle_journeys/containers/tools/PurchaseWindowsEditVehicleJourney.js b/app/javascript/vehicle_journeys/containers/tools/PurchaseWindowsEditVehicleJourney.js
new file mode 100644
index 000000000..3fef44489
--- /dev/null
+++ b/app/javascript/vehicle_journeys/containers/tools/PurchaseWindowsEditVehicleJourney.js
@@ -0,0 +1,38 @@
+import actions from '../../actions'
+import { connect } from 'react-redux'
+import PurchaseWindowsEditVehicleJourneyComponent from '../../components/tools/PurchaseWindowsEditVehicleJourney'
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ editMode: state.editMode,
+ modal: state.modal,
+ vehicleJourneys: state.vehicleJourneys,
+ status: state.status,
+ disabled: ownProps.disabled
+ }
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ onModalClose: () =>{
+ dispatch(actions.closeModal())
+ },
+ onOpenCalendarsEditModal: (vehicleJourneys) =>{
+ dispatch(actions.openPurchaseWindowsEditModal(vehicleJourneys))
+ },
+ onDeleteCalendarModal: (timetable) => {
+ dispatch(actions.deletePurchaseWindowsModal(timetable))
+ },
+ onShoppingWindowsEditVehicleJourney: (vehicleJourneys, timetables) =>{
+ dispatch(actions.editVehicleJourneyPurchaseWindows(vehicleJourneys, timetables))
+ },
+ onSelect2Timetable: (e) =>{
+ dispatch(actions.selectPurchaseWindowsModal(e.params.data))
+ dispatch(actions.addSelectedPurchaseWindow())
+ }
+ }
+}
+
+const PurchaseWindowsEditVehicleJourney = connect(mapStateToProps, mapDispatchToProps)(PurchaseWindowsEditVehicleJourneyComponent)
+
+export default PurchaseWindowsEditVehicleJourney
diff --git a/app/javascript/vehicle_journeys/containers/tools/VehicleJourneyInfoButton.js b/app/javascript/vehicle_journeys/containers/tools/VehicleJourneyInfoButton.js
new file mode 100644
index 000000000..19010c312
--- /dev/null
+++ b/app/javascript/vehicle_journeys/containers/tools/VehicleJourneyInfoButton.js
@@ -0,0 +1,20 @@
+import actions from '../../actions'
+import { connect } from 'react-redux'
+import VehicleJourneyInfoButtonComponent from '../../components/tools/VehicleJourneyInfoButton'
+
+const mapStateToProps = (state, ownProps) => {
+ return {
+ }
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ onOpenEditModal: (vj) =>{
+ dispatch(actions.openInfoModal(vj))
+ },
+ }
+}
+
+const VehicleJourneyInfoButton = connect(mapStateToProps, mapDispatchToProps)(VehicleJourneyInfoButtonComponent)
+
+export default VehicleJourneyInfoButton
diff --git a/app/javascript/vehicle_journeys/reducers/custom_fields.js b/app/javascript/vehicle_journeys/reducers/custom_fields.js
new file mode 100644
index 000000000..482fd91cb
--- /dev/null
+++ b/app/javascript/vehicle_journeys/reducers/custom_fields.js
@@ -0,0 +1,6 @@
+export default function custom_fields(state = [], action) {
+ switch (action.type) {
+ default:
+ return state
+ }
+}
diff --git a/app/javascript/vehicle_journeys/reducers/index.js b/app/javascript/vehicle_journeys/reducers/index.js
index bb24aa185..95ac9c7e1 100644
--- a/app/javascript/vehicle_journeys/reducers/index.js
+++ b/app/javascript/vehicle_journeys/reducers/index.js
@@ -1,20 +1,27 @@
import { combineReducers } from 'redux'
import vehicleJourneys from './vehicleJourneys'
+import returnVehicleJourneys from './returnVehicleJourneys'
import pagination from './pagination'
import modal from './modal'
import status from './status'
import filters from './filters'
import editMode from './editMode'
import stopPointsList from './stopPointsList'
+import missions from './missions'
+import custom_fields from './custom_fields'
const vehicleJourneysApp = combineReducers({
vehicleJourneys,
+ returnVehicleJourneys,
pagination,
modal,
status,
filters,
editMode,
- stopPointsList
+ stopPointsList,
+ returnStopPointsList: stopPointsList,
+ missions,
+ custom_fields
})
export default vehicleJourneysApp
diff --git a/app/javascript/vehicle_journeys/reducers/missions.js b/app/javascript/vehicle_journeys/reducers/missions.js
new file mode 100644
index 000000000..7c1a355c7
--- /dev/null
+++ b/app/javascript/vehicle_journeys/reducers/missions.js
@@ -0,0 +1,6 @@
+export default function missions(state = [], action) {
+ switch (action.type) {
+ default:
+ return state
+ }
+}
diff --git a/app/javascript/vehicle_journeys/reducers/modal.js b/app/javascript/vehicle_journeys/reducers/modal.js
index 57f54a144..bcfc6ea0b 100644
--- a/app/javascript/vehicle_journeys/reducers/modal.js
+++ b/app/javascript/vehicle_journeys/reducers/modal.js
@@ -1,6 +1,6 @@
import _ from 'lodash'
-let vehicleJourneysModal, newModalProps
+let vehicleJourneysModal, newModalProps, vehicleJourney
export default function modal(state = {}, action) {
switch (action.type) {
@@ -37,10 +37,18 @@ export default function modal(state = {}, action) {
},
confirmModal: {}
}
+ case 'INFO_VEHICLEJOURNEY_MODAL':
+ return {
+ type: 'edit',
+ modalProps: {
+ vehicleJourney: action.vehicleJourney,
+ info: true
+ },
+ confirmModal: {}
+ }
case 'EDIT_CALENDARS_VEHICLEJOURNEY_MODAL':
vehicleJourneysModal = JSON.parse(JSON.stringify(action.vehicleJourneys))
let uniqTimetables = []
- let timetable = {}
vehicleJourneysModal.map((vj, i) => {
vj.time_tables.map((tt, j) =>{
if(!(_.find(uniqTimetables, tt))){
@@ -56,15 +64,38 @@ export default function modal(state = {}, action) {
},
confirmModal: {}
}
+ case 'EDIT_PURCHASE_WINDOWS_VEHICLEJOURNEY_MODAL':
+ var vehicleJourneys = JSON.parse(JSON.stringify(action.vehicleJourneys))
+ let uniqPurchaseWindows = []
+ vehicleJourneys.map((vj, i) => {
+ vj.purchase_windows.map((pw, j) =>{
+ if(!(_.find(uniqPurchaseWindows, pw))){
+ uniqPurchaseWindows.push(pw)
+ }
+ })
+ })
+ return {
+ type: 'purchase_windows_edit',
+ modalProps: {
+ vehicleJourneys: vehicleJourneys,
+ purchase_windows: uniqPurchaseWindows
+ },
+ confirmModal: {}
+ }
case 'SELECT_CP_EDIT_MODAL':
- newModalProps = _.assign({}, state.modalProps, {selectedCompany : action.selectedItem})
+ vehicleJourney = _.assign({}, state.modalProps.vehicleJourney, {company: action.selectedItem})
+ newModalProps = _.assign({}, state.modalProps, {vehicleJourney})
return _.assign({}, state, {modalProps: newModalProps})
case 'UNSELECT_CP_EDIT_MODAL':
- newModalProps = _.assign({}, state.modalProps, {selectedCompany : undefined})
+ vehicleJourney = _.assign({}, state.modalProps.vehicleJourney, {company: undefined})
+ newModalProps = _.assign({}, state.modalProps, {vehicleJourney})
return _.assign({}, state, {modalProps: newModalProps})
case 'SELECT_TT_CALENDAR_MODAL':
newModalProps = _.assign({}, state.modalProps, {selectedTimetable : action.selectedItem})
return _.assign({}, state, {modalProps: newModalProps})
+ case 'SELECT_PURCHASE_WINDOW_MODAL':
+ newModalProps = _.assign({}, state.modalProps, {selectedPurchaseWindow : action.selectedItem})
+ return _.assign({}, state, {modalProps: newModalProps})
case 'ADD_SELECTED_TIMETABLE':
if(state.modalProps.selectedTimetable){
newModalProps = JSON.parse(JSON.stringify(state.modalProps))
@@ -73,6 +104,14 @@ export default function modal(state = {}, action) {
}
return _.assign({}, state, {modalProps: newModalProps})
}
+ case 'ADD_SELECTED_PURCHASE_WINDOW':
+ if(state.modalProps.selectedPurchaseWindow){
+ newModalProps = JSON.parse(JSON.stringify(state.modalProps))
+ if (!_.find(newModalProps.purchase_windows, newModalProps.selectedPurchaseWindow)){
+ newModalProps.purchase_windows.push(newModalProps.selectedPurchaseWindow)
+ }
+ return _.assign({}, state, {modalProps: newModalProps})
+ }
case 'DELETE_CALENDAR_MODAL':
newModalProps = JSON.parse(JSON.stringify(state.modalProps))
let timetablesModal = state.modalProps.timetables.slice(0)
@@ -92,19 +131,32 @@ export default function modal(state = {}, action) {
newModalProps.vehicleJourneys = vehicleJourneysModal
newModalProps.timetables = timetablesModal
return _.assign({}, state, {modalProps: newModalProps})
+ case 'DELETE_PURCHASE_WINDOW_MODAL':
+ newModalProps = JSON.parse(JSON.stringify(state.modalProps))
+ let purchase_windows = state.modalProps.purchase_windows.slice(0)
+ purchase_windows.map((tt, i) =>{
+ if(tt == action.purchaseWindow){
+ purchase_windows.splice(i, 1)
+ }
+ })
+ vehicleJourneysModal = state.modalProps.vehicleJourneys.slice(0)
+ vehicleJourneysModal.map((vj) =>{
+ vj.purchase_windows.map((tt, i) =>{
+ if (_.isEqual(tt, action.purchaseWindow)){
+ vj.purchase_windows.splice(i, 1)
+ }
+ })
+ })
+ newModalProps.vehicleJourneys = vehicleJourneysModal
+ newModalProps.purchase_windows = purchase_windows
+ return _.assign({}, state, {modalProps: newModalProps})
case 'CREATE_VEHICLEJOURNEY_MODAL':
let selectedJP = {}
if (window.jpOrigin){
let stopAreas = _.map(window.jpOriginStopPoints, (sa, i) =>{
return _.assign({}, {stop_area_short_description : {id : sa.stop_area_id}})
})
- selectedJP = {
- id: window.jpOrigin.id,
- name: window.jpOrigin.name,
- published_name: window.jpOrigin.published_name,
- objectid: window.jpOrigin.objectid,
- stop_areas: stopAreas
- }
+ selectedJP = _.assign({}, window.jpOrigin, {stop_areas: stopAreas})
}
return {
type: 'create',
@@ -135,4 +187,4 @@ export default function modal(state = {}, action) {
default:
return state
}
-} \ No newline at end of file
+}
diff --git a/app/javascript/vehicle_journeys/reducers/returnVehicleJourneys.js b/app/javascript/vehicle_journeys/reducers/returnVehicleJourneys.js
new file mode 100644
index 000000000..db3c71d17
--- /dev/null
+++ b/app/javascript/vehicle_journeys/reducers/returnVehicleJourneys.js
@@ -0,0 +1,11 @@
+import _ from 'lodash'
+import actions from '../actions'
+
+export default function returnVehicleJourneys(state = [], action) {
+ switch (action.type) {
+ case 'RECEIVE_RETURN_VEHICLE_JOURNEYS':
+ return [...action.json]
+ default:
+ return state
+ }
+}
diff --git a/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js b/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js
index 136e1b41a..1a15ec46d 100644
--- a/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js
+++ b/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js
@@ -9,29 +9,68 @@ const vehicleJourney= (state = {}, action, keep) => {
return _.assign({}, state, {selected: false})
case 'ADD_VEHICLEJOURNEY':
let pristineVjasList = []
+ let prevSp = action.stopPointsList[0]
+ let current_time = {
+ hour: 0,
+ minute: 0
+ }
+ if(action.data["start_time.hour"] && action.data["start_time.minute"] && action.selectedJourneyPattern.full_schedule){
+ current_time.hour = parseInt(action.data["start_time.hour"].value)
+ current_time.minute = parseInt(action.data["start_time.minute"].value) || 0
+ }
_.each(action.stopPointsList, (sp) =>{
+ if(action.selectedJourneyPattern.full_schedule && action.selectedJourneyPattern.costs && action.selectedJourneyPattern.costs[prevSp.stop_area_id + "-" + sp.stop_area_id]){
+ let delta = parseInt(action.selectedJourneyPattern.costs[prevSp.stop_area_id + "-" + sp.stop_area_id].time)
+ let delta_hour = parseInt(delta/60)
+ let delta_minute = delta - 60*delta_hour
+ current_time.hour += delta_hour
+ current_time.minute += delta_minute
+ let extra_hours = parseInt(current_time.minute/60)
+ current_time.hour += extra_hours
+ current_time.minute -= extra_hours*60
+ current_time.hour = current_time.hour % 24
+ prevSp = sp
+ }
+ let offsetHours = sp.time_zone_offset / 3600
+ let offsetminutes = sp.time_zone_offset/60 - 60*offsetHours
let newVjas = {
delta: 0,
departure_time:{
- hour: '00',
- minute: '00'
+ hour: (24 + current_time.hour + offsetHours) % 24,
+ minute: current_time.minute + offsetminutes
},
arrival_time:{
- hour: '00',
- minute: '00'
+ hour: (24 + current_time.hour + offsetHours) % 24,
+ minute: current_time.minute + offsetminutes
},
stop_point_objectid: sp.object_id,
stop_area_cityname: sp.city_name,
dummy: true
}
+ if(current_time.hour + offsetHours > 24){
+ newVjas.departure_day_offset = 1
+ newVjas.arrival_day_offset = 1
+ }
+ if(current_time.hour + offsetHours < 0){
+ newVjas.departure_day_offset = -1
+ newVjas.arrival_day_offset = -1
+ }
+
_.each(action.selectedJourneyPattern.stop_areas, (jp) =>{
if (jp.stop_area_short_description.id == sp.id){
newVjas.dummy = false
return
}
})
+
+ if(newVjas.dummy){
+ newVjas.departure_time = {hour: "00", minute: "00"}
+ newVjas.arrival_time = {hour: "00", minute: "00"}
+ }
pristineVjasList.push(newVjas)
+
})
+
return {
company: action.selectedCompany,
journey_pattern: action.selectedJourneyPattern,
@@ -41,11 +80,13 @@ const vehicleJourney= (state = {}, action, keep) => {
short_id: '',
footnotes: [],
time_tables: [],
+ purchase_windows: [],
vehicle_journey_at_stops: pristineVjasList,
selected: false,
deletable: false,
transport_mode: window.transportMode ? window.transportMode : 'undefined',
- transport_submode: window.transportSubmode ? window.transportSubmode : 'undefined'
+ transport_submode: window.transportSubmode ? window.transportSubmode : 'undefined',
+ custom_fields: action.data.custom_fields
}
case 'DUPLICATE_VEHICLEJOURNEY':
case 'SHIFT_VEHICLEJOURNEY':
@@ -79,18 +120,12 @@ const vehicleJourney= (state = {}, action, keep) => {
if (action.isDeparture){
newSchedule.departure_time[action.timeUnit] = actions.pad(action.val, action.timeUnit)
if(!action.isArrivalsToggled)
- newSchedule.arrival_time[action.timeUnit] = actions.pad(action.val, action.timeUnit)
- newSchedule = actions.getDelta(newSchedule)
- if(newSchedule.delta < 0){
- return vjas
- }
+ newSchedule.arrival_time[action.timeUnit] = newSchedule.departure_time[action.timeUnit]
+ newSchedule = actions.adjustSchedule(action, newSchedule)
return _.assign({}, state.vehicle_journey_at_stops[action.subIndex], {arrival_time: newSchedule.arrival_time, departure_time: newSchedule.departure_time, delta: newSchedule.delta})
}else{
newSchedule.arrival_time[action.timeUnit] = actions.pad(action.val, action.timeUnit)
- newSchedule = actions.getDelta(newSchedule)
- if(newSchedule.delta < 0){
- return vjas
- }
+ newSchedule = actions.adjustSchedule(action, newSchedule)
return _.assign({}, state.vehicle_journey_at_stops[action.subIndex], {arrival_time: newSchedule.arrival_time, departure_time: newSchedule.departure_time, delta: newSchedule.delta})
}
}else{
@@ -131,6 +166,7 @@ export default function vehicleJourneys(state = [], action) {
company: action.selectedCompany,
published_journey_name: action.data.published_journey_name.value,
published_journey_identifier: action.data.published_journey_identifier.value,
+ custom_fields: action.data.custom_fields,
})
}else{
return vj
@@ -161,6 +197,21 @@ export default function vehicleJourneys(state = [], action) {
return vj
}
})
+ case 'EDIT_VEHICLEJOURNEYS_PURCHASE_WINDOWS':
+ let newWindows = JSON.parse(JSON.stringify(action.purchase_windows))
+ return state.map((vj,i) =>{
+ if(vj.selected){
+ let updatedVJ = _.assign({}, vj)
+ action.vehicleJourneys.map((vjm, j) =>{
+ if(vj.objectid == vjm.objectid){
+ updatedVJ.purchase_windows = newWindows
+ }
+ })
+ return updatedVJ
+ }else{
+ return vj
+ }
+ })
case 'SHIFT_VEHICLEJOURNEY':
return state.map((vj, i) => {
if (vj.selected){
@@ -222,7 +273,9 @@ export default function vehicleJourneys(state = [], action) {
return vj
}
})
+ case 'DID_VALIDATE_VEHICLE_JOURNEYS':
+ return [...action.vehicleJourneys]
default:
return state
}
-} \ No newline at end of file
+}
diff --git a/app/jobs/mailer_job.rb b/app/jobs/mailer_job.rb
index 3918745b8..eb3250a27 100644
--- a/app/jobs/mailer_job.rb
+++ b/app/jobs/mailer_job.rb
@@ -1,6 +1,9 @@
class MailerJob < ActiveJob::Base
# No need to specify queue it's already used mailers queue
+ # This job will be retried, unlike Sidekiq jobs which are configured
+ # to not retry
+
def perform klass, action, params
klass.constantize.public_send(action, *params).deliver_later
end
diff --git a/app/models/calendar.rb b/app/models/calendar.rb
index b2e73929f..84b569ab4 100644
--- a/app/models/calendar.rb
+++ b/app/models/calendar.rb
@@ -3,176 +3,115 @@ require_relative 'calendar/date_value'
require_relative 'calendar/period'
class Calendar < ActiveRecord::Base
- has_paper_trail
+ include DateSupport
+ include PeriodSupport
+ include ApplicationDaysSupport
+ include TimetableSupport
+
+ has_paper_trail class_name: 'PublicVersion'
belongs_to :organisation
- has_many :time_tables
+ belongs_to :workgroup
- validates_presence_of :name, :short_name, :organisation
+ validates_presence_of :name, :short_name, :organisation, :workgroup
validates_uniqueness_of :short_name
- after_initialize :init_dates_and_date_ranges
+ has_many :time_tables
scope :contains_date, ->(date) { where('date ? = any (dates) OR date ? <@ any (date_ranges)', date, date) }
- def init_dates_and_date_ranges
- self.dates ||= []
- self.date_ranges ||= []
- end
+ after_initialize :set_defaults
def self.ransackable_scopes(auth_object = nil)
[:contains_date]
end
- def convert_to_time_table
- Chouette::TimeTable.new.tap do |tt|
- self.dates.each do |d|
- tt.dates << Chouette::TimeTableDate.new(date: d, in_out: true)
- end
- self.periods.each do |p|
- tt.periods << Chouette::TimeTablePeriod.new(period_start: p.begin, period_end: p.end)
- end
- tt.int_day_types = 508
- end
+ def self.state_permited_attributes item
+ {name: item["comment"]}
end
-
- ### Calendar::Period
- # Required by coocon
- def build_period
- Calendar::Period.new
+ def set_defaults
+ self.excluded_dates ||= []
+ self.int_day_types ||= EVERYDAY
end
- def periods
- @periods ||= init_periods
+ def human_attribute_name(*args)
+ self.class.human_attribute_name(*args)
end
- def init_periods
- (date_ranges || [])
- .each_with_index
- .map( &Calendar::Period.method(:from_range) )
+ def shortcuts_update(date=nil)
end
- private :init_periods
-
- validate :validate_periods
- def validate_periods
- periods_are_valid = periods.all?(&:valid?)
-
- periods.each do |period|
- if period.intersect?(periods)
- period.errors.add(:base, I18n.t('calendars.errors.overlapped_periods'))
- periods_are_valid = false
+ def convert_to_time_table
+ Chouette::TimeTable.new.tap do |tt|
+ self.dates.each do |d|
+ tt.dates << Chouette::TimeTableDate.new(date: d, in_out: true)
end
- end
-
- unless periods_are_valid
- errors.add(:periods, :invalid)
+ self.periods.each do |p|
+ tt.periods << Chouette::TimeTablePeriod.new(period_start: p.begin, period_end: p.end)
+ end
+ tt.int_day_types = self.int_day_types
end
end
- def flatten_date_array attributes, key
- date_int = %w(1 2 3).map {|e| attributes["#{key}(#{e}i)"].to_i }
- Date.new(*date_int)
+ def include_in_dates?(day)
+ self.dates.include? day
end
- def periods_attributes=(attributes = {})
- @periods = []
- attributes.each do |index, period_attribute|
- # Convert date_select to date
- ['begin', 'end'].map do |attr|
- period_attribute[attr] = flatten_date_array(period_attribute, attr)
- end
- period = Calendar::Period.new(period_attribute.merge(id: index))
- @periods << period unless period.marked_for_destruction?
- end
-
- date_ranges_will_change!
+ def excluded_date?(day)
+ self.excluded_dates.include? day
end
- before_validation :fill_date_ranges
-
- def fill_date_ranges
- if @periods
- self.date_ranges = @periods.map(&:range).compact.sort_by(&:begin)
+ def update_in_out date, in_out
+ if in_out
+ self.excluded_dates.delete date
+ self.dates << date unless include_in_dates?(date)
+ else
+ self.dates.delete date
+ self.excluded_dates << date unless excluded_date?(date)
end
+ date
end
- after_save :clear_periods
-
- def clear_periods
- @periods = nil
+ def included_days
+ dates
end
- private :clear_periods
-
- ### Calendar::DateValue
-
- # Required by coocon
- def build_date_value
- Calendar::DateValue.new
+ def excluded_days
+ excluded_dates
end
- def date_values
- @date_values ||= init_date_values
+ def saved_dates
+ Hash[*self.dates.each_with_index.to_a.map(&:reverse).flatten]
end
- def init_date_values
- if dates
- dates.each_with_index.map { |d, index| Calendar::DateValue.from_date(index, d) }
- else
- []
+ def all_dates
+ (dates + excluded_dates).sort.each_with_index.map do |d, i|
+ OpenStruct.new(id: i, date: d, in_out: include_in_dates?(d))
end
end
- private :init_date_values
- validate :validate_date_values
-
- def validate_date_values
- date_values_are_valid = date_values.all?(&:valid?)
-
- date_values.each do |date_value|
- if date_values.count { |d| d.value == date_value.value } > 1
- date_value.errors.add(:base, I18n.t('activerecord.errors.models.calendar.attributes.dates.date_in_dates'))
- date_values_are_valid = false
- end
- date_ranges.each do |date_range|
- if date_range.cover? date_value.value
- date_value.errors.add(:base, I18n.t('activerecord.errors.models.calendar.attributes.dates.date_in_date_ranges'))
- date_values_are_valid = false
- end
- end
- end
-
- unless date_values_are_valid
- errors.add(:date_values, :invalid)
- end
+ def find_date_by_id id
+ self.dates[id]
end
- def date_values_attributes=(attributes = {})
- @date_values = []
- attributes.each do |index, date_value_attribute|
- date_value_attribute['value'] = flatten_date_array(date_value_attribute, 'value')
- date_value = Calendar::DateValue.new(date_value_attribute.merge(id: index))
- @date_values << date_value unless date_value.marked_for_destruction?
- end
-
- dates_will_change!
+ def destroy_date date
+ self.dates -= [date]
end
- before_validation :fill_dates
-
- def fill_dates
- if @date_values
- self.dates = @date_values.map(&:value).compact.sort
- end
+ def create_date in_out:, date:
+ update_in_out date, in_out
end
- after_save :clear_date_values
-
- def clear_date_values
- @date_values = nil
+ def find_period_by_id id
+ self.periods.find{|p| p.id == id}
end
- private :clear_date_values
+ def build_period
+ self.periods << Calendar::Period.new(id: self.periods.count + 1)
+ self.periods.last
+ end
+ def destroy_period period
+ @periods = self.periods.select{|p| p.end != period.end || p.begin != period.begin}
+ end
end
diff --git a/app/models/calendar/period.rb b/app/models/calendar/period.rb
index 1c423dfcc..8b3e4109b 100644
--- a/app/models/calendar/period.rb
+++ b/app/models/calendar/period.rb
@@ -1,5 +1,5 @@
class Calendar < ActiveRecord::Base
-
+
class Period
include ActiveAttr::Model
@@ -10,6 +10,11 @@ class Calendar < ActiveRecord::Base
validates_presence_of :begin, :end
validate :check_end_greather_than_begin
+ alias_method :period_start, :begin
+ alias_method :period_end, :end
+ alias_method :period_start=, :begin=
+ alias_method :period_end=, :end=
+
def check_end_greather_than_begin
if self.begin && self.end && self.begin >= self.end
errors.add(:base, I18n.t('calendars.errors.short_period'))
diff --git a/app/models/chouette/area_type.rb b/app/models/chouette/area_type.rb
new file mode 100644
index 000000000..e17d2ee8d
--- /dev/null
+++ b/app/models/chouette/area_type.rb
@@ -0,0 +1,55 @@
+class Chouette::AreaType
+ include Comparable
+
+ COMMERCIAL = %i(zdep zder zdlp zdlr lda gdl).freeze
+ NON_COMMERCIAL = %i(deposit border service_area relief other).freeze
+ ALL = COMMERCIAL + NON_COMMERCIAL
+
+ @@commercial = COMMERCIAL
+ @@non_commercial = NON_COMMERCIAL
+ @@all = ALL
+ mattr_accessor :all, :commercial, :non_commercial
+
+ def self.commercial=(values)
+ @@commercial = COMMERCIAL & values
+ reset_caches!
+ end
+
+ def self.non_commercial=(values)
+ @@non_commercial = NON_COMMERCIAL & values
+ reset_caches!
+ end
+
+ @@instances = {}
+ def self.find(code)
+ return unless code
+
+ code = code.to_sym
+ @@instances[code] ||= new(code) if ALL.include? code
+ end
+
+ def self.reset_caches!
+ @@all = @@commercial + @@non_commercial
+ @@instances = {}
+ @@options = {}
+ end
+
+ def self.options(kind=:all)
+ @@options ||= {}
+ @@options[kind] ||= self.send(kind).map { |c| find(c) }.map { |t| [ t.label, t.code ] }
+ end
+
+ attr_reader :code
+ def initialize(code)
+ @code = code
+ end
+
+ def <=>(other)
+ all.index(code) <=> all.index(other.code)
+ end
+
+ def label
+ I18n.translate code, scope: 'area_types.label'
+ end
+
+end
diff --git a/app/models/chouette/company.rb b/app/models/chouette/company.rb
index 12b21e347..b3d40ab96 100644
--- a/app/models/chouette/company.rb
+++ b/app/models/chouette/company.rb
@@ -3,7 +3,7 @@ module Chouette
include CompanyRestrictions
include LineReferentialSupport
include ObjectidSupport
- has_paper_trail
+ has_paper_trail class_name: 'PublicVersion'
has_many :lines
diff --git a/app/models/chouette/journey_pattern.rb b/app/models/chouette/journey_pattern.rb
index a62da6353..aa9fdb810 100644
--- a/app/models/chouette/journey_pattern.rb
+++ b/app/models/chouette/journey_pattern.rb
@@ -27,7 +27,7 @@ module Chouette
def checksum_attributes
values = self.slice(*['name', 'published_name', 'registration_number']).values
- values << self.stop_points.map(&:stop_area).map(&:user_objectid)
+ values << self.stop_points.sort_by(&:position).map(&:stop_area).map(&:user_objectid)
values.flatten
end
@@ -40,7 +40,8 @@ module Chouette
# Update attributes and stop_points associations
jp.update_attributes(state_permited_attributes(item)) unless item['new_record']
jp.state_stop_points_update(item) if !jp.errors.any? && jp.persisted?
- item['errors'] = jp.errors if jp.errors.any?
+ item['errors'] = jp.errors if jp.errors.any?
+ item['checksum'] = jp.checksum
end
if state.any? {|item| item['errors']}
@@ -57,21 +58,23 @@ module Chouette
{
name: item['name'],
published_name: item['published_name'],
- registration_number: item['registration_number']
+ registration_number: item['registration_number'],
+ costs: item['costs']
}
end
def self.state_create_instance route, item
# Flag new record, so we can unset object_id if transaction rollback
jp = route.journey_patterns.create(state_permited_attributes(item))
-
# FIXME
# DefaultAttributesSupport will trigger some weird validation on after save
# wich will call to valid?, wich will populate errors
# In this case, we mark jp to be valid if persisted? return true
jp.errors.clear if jp.persisted?
+ jp.after_commit_objectid
item['object_id'] = jp.objectid
+ item['short_id'] = jp.get_objectid.short_id
item['new_record'] = true
jp
end
@@ -145,5 +148,27 @@ module Chouette
vjas.destroy
end
end
+
+ def costs
+ read_attribute(:costs) || {}
+ end
+
+ def costs_between start, finish
+ key = "#{start.stop_area_id}-#{finish.stop_area_id}"
+ costs[key]&.symbolize_keys || {}
+ end
+
+ def full_schedule?
+ full = true
+ stop_points.order(:position).inject(nil) do |start, finish|
+ next finish unless start.present?
+ costs = costs_between(start, finish)
+ full = false unless costs.present?
+ full = false unless costs[:distance] && costs[:distance] > 0
+ full = false unless costs[:time] && costs[:time] > 0
+ finish
+ end
+ full
+ end
end
end
diff --git a/app/models/chouette/line.rb b/app/models/chouette/line.rb
index 93d4f5e8b..ba2e2755d 100644
--- a/app/models/chouette/line.rb
+++ b/app/models/chouette/line.rb
@@ -1,6 +1,6 @@
module Chouette
class Line < Chouette::ActiveRecord
- has_paper_trail
+ has_paper_trail class_name: 'PublicVersion'
include LineRestrictions
include LineReferentialSupport
include ObjectidSupport
@@ -21,6 +21,7 @@ module Chouette
has_many :journey_patterns, :through => :routes
has_many :vehicle_journeys, :through => :journey_patterns
has_many :routing_constraint_zones, through: :routes
+ has_many :time_tables, -> { distinct }, :through => :vehicle_journeys
has_and_belongs_to_many :group_of_lines, :class_name => 'Chouette::GroupOfLine', :order => 'group_of_lines.name'
@@ -79,5 +80,16 @@ module Chouette
line_referential.companies.where(id: ([company_id] + Array(secondary_company_ids)).compact)
end
+ def deactivate!
+ update_attribute :deactivated, true
+ end
+
+ def activate!
+ update_attribute :deactivated, false
+ end
+
+ def activated?
+ !deactivated
+ end
end
end
diff --git a/app/models/chouette/network.rb b/app/models/chouette/network.rb
index 9b3f2fe29..6843c69ad 100644
--- a/app/models/chouette/network.rb
+++ b/app/models/chouette/network.rb
@@ -1,6 +1,6 @@
module Chouette
class Network < Chouette::ActiveRecord
- has_paper_trail
+ has_paper_trail class_name: 'PublicVersion'
include NetworkRestrictions
include LineReferentialSupport
include ObjectidSupport
diff --git a/app/models/chouette/purchase_window.rb b/app/models/chouette/purchase_window.rb
new file mode 100644
index 000000000..334493015
--- /dev/null
+++ b/app/models/chouette/purchase_window.rb
@@ -0,0 +1,45 @@
+require 'range_ext'
+require_relative '../calendar/period'
+
+module Chouette
+ class PurchaseWindow < Chouette::TridentActiveRecord
+ # include ChecksumSupport
+ include ObjectidSupport
+ include PeriodSupport
+ include ChecksumSupport
+ extend Enumerize
+
+ enumerize :color, in: %w(#9B9B9B #FFA070 #C67300 #7F551B #41CCE3 #09B09C #3655D7 #6321A0 #E796C6 #DD2DAA)
+
+ has_paper_trail
+ belongs_to :referential
+ has_and_belongs_to_many :vehicle_journeys, :class_name => 'Chouette::VehicleJourney'
+
+ validates_presence_of :name, :referential
+
+ scope :contains_date, ->(date) { where('date ? <@ any (date_ranges)', date) }
+ scope :overlap_dates, ->(date_range) { where('daterange(?, ?) && any (date_ranges)', date_range.first, date_range.last + 1.day) }
+
+ def self.ransackable_scopes(auth_object = nil)
+ [:contains_date]
+ end
+
+ def self.colors_i18n
+ Hash[*color.values.map{|c| [I18n.t("enumerize.purchase_window.color.#{c[1..-1]}"), c]}.flatten]
+ end
+
+ def local_id
+ "IBOO-#{self.referential.id}-#{self.id}"
+ end
+
+ def checksum_attributes
+ attrs = ['name', 'color', 'referential_id']
+ ranges_attrs = date_ranges.map{|r| [r.first, r.last]}.flatten.sort
+ self.slice(*attrs).values + ranges_attrs
+ end
+
+ # def checksum_attributes
+ # end
+
+ end
+end
diff --git a/app/models/chouette/route.rb b/app/models/chouette/route.rb
index 5c0ad24a1..5cc5d8b0d 100644
--- a/app/models/chouette/route.rb
+++ b/app/models/chouette/route.rb
@@ -133,7 +133,7 @@ module Chouette
def checksum_attributes
values = self.slice(*['name', 'published_name', 'wayback']).values
values.tap do |attrs|
- attrs << self.stop_points.map{|sp| "#{sp.stop_area.user_objectid}#{sp.for_boarding}#{sp.for_alighting}" }.join
+ attrs << self.stop_points.sort_by(&:position).map{|sp| [sp.stop_area.user_objectid, sp.for_boarding, sp.for_alighting]}
attrs << self.routing_constraint_zones.map(&:checksum)
end
end
diff --git a/app/models/chouette/routing_constraint_zone.rb b/app/models/chouette/routing_constraint_zone.rb
index fcf47f154..58703598e 100644
--- a/app/models/chouette/routing_constraint_zone.rb
+++ b/app/models/chouette/routing_constraint_zone.rb
@@ -7,7 +7,7 @@ module Chouette
belongs_to :route
has_array_of :stop_points, class_name: 'Chouette::StopPoint'
- validates_presence_of :name, :stop_points, :route
+ validates_presence_of :name, :stop_points, :route_id
# 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
@@ -25,14 +25,20 @@ module Chouette
end
def checksum_attributes
- self.stop_points.map(&:stop_area).map(&:user_objectid)
+ [
+ self.stop_points.map(&:stop_area).map(&:user_objectid)
+ ]
end
def stop_points_belong_to_route
+ return unless route
+
errors.add(:stop_point_ids, I18n.t('activerecord.errors.models.routing_constraint_zone.attributes.stop_points.stop_points_not_from_route')) unless stop_points.all? { |sp| route.stop_points.include? sp }
end
def not_all_stop_points_selected
+ return unless route
+
errors.add(:stop_point_ids, I18n.t('activerecord.errors.models.routing_constraint_zone.attributes.stop_points.all_stop_points_selected')) if stop_points.length == route.stop_points.length
end
diff --git a/app/models/chouette/stop_area.rb b/app/models/chouette/stop_area.rb
index cc7170728..bb8747faa 100644
--- a/app/models/chouette/stop_area.rb
+++ b/app/models/chouette/stop_area.rb
@@ -2,14 +2,17 @@ require 'geokit'
require 'geo_ruby'
module Chouette
class StopArea < Chouette::ActiveRecord
- has_paper_trail
+ has_paper_trail class_name: 'PublicVersion'
include ProjectionFields
include StopAreaRestrictions
include StopAreaReferentialSupport
include ObjectidSupport
extend Enumerize
- enumerize :area_type, in: %i(zdep zder zdlp zdlr lda)
+ enumerize :area_type, in: Chouette::AreaType::ALL
+ enumerize :kind, in: %i(commercial non_commercial)
+
+ AVAILABLE_LOCALIZATIONS = %i(gb nl de fr it es)
with_options dependent: :destroy do |assoc|
assoc.has_many :stop_points
@@ -31,6 +34,7 @@ module Chouette
validates_format_of :registration_number, :with => %r{\A[\d\w_\-]+\Z}, :allow_blank => true
validates_presence_of :name
+ validates_presence_of :kind
validates_presence_of :latitude, :if => :longitude
validates_presence_of :longitude, :if => :latitude
validates_numericality_of :latitude, :less_than_or_equal_to => 90, :greater_than_or_equal_to => -90, :allow_nil => true
@@ -39,11 +43,36 @@ module Chouette
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
validates_format_of :url, :with => %r{\Ahttps?:\/\/([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?\Z}, :allow_nil => true, :allow_blank => true
+ validates_numericality_of :waiting_time, greater_than_or_equal_to: 0, only_integer: true, if: :waiting_time
+ validate :parent_area_type_must_be_greater
+ validate :area_type_of_right_kind
+
def self.nullable_attributes
[:registration_number, :street_name, :country_code, :fare_code,
:nearest_topic_name, :comment, :long_lat_type, :zip_code, :city_name, :url, :time_zone]
end
+ def localized_names
+ val = read_attribute(:localized_names) || {}
+ Hash[*AVAILABLE_LOCALIZATIONS.map{|k| [k, val[k.to_s]]}.flatten]
+ end
+
+ def parent_area_type_must_be_greater
+ return unless self.parent
+
+ parent_area_type = Chouette::AreaType.find(self.parent.area_type)
+ if Chouette::AreaType.find(self.area_type) >= parent_area_type
+ errors.add(:parent_id, I18n.t('stop_areas.errors.parent_area_type', area_type: parent_area_type.label))
+ end
+ end
+
+ def area_type_of_right_kind
+ return unless self.kind
+ unless Chouette::AreaType.send(self.kind).map(&:to_s).include?(self.area_type)
+ errors.add(:area_type, I18n.t('stop_areas.errors.incorrect_kind_area_type'))
+ end
+ end
+
after_update :clean_invalid_access_links
before_save :coordinates_to_lat_lng
@@ -72,6 +101,10 @@ module Chouette
end
end
+ def full_name
+ "#{name} #{zip_code} #{city_name} - #{user_objectid}"
+ end
+
def user_objectid
if objectid =~ /^.*:([0-9A-Za-z_-]+):STIF$/
$1
@@ -80,6 +113,8 @@ module Chouette
end
end
+ alias_method :local_id, :user_objectid
+
def children_in_depth
return [] if self.children.empty?
@@ -196,10 +231,12 @@ module Chouette
GeoRuby::SimpleFeatures::Envelope.from_coordinates coordinates
end
+ # DEPRECATED use StopArea#area_type
def stop_area_type
area_type ? area_type : " "
end
+ # DEPRECATED use StopArea#area_type
def stop_area_type=(stop_area_type)
self.area_type = (stop_area_type ? stop_area_type.camelcase : nil)
end
@@ -324,5 +361,41 @@ module Chouette
end
end
+ def activated?
+ deleted_at.nil?
+ end
+
+ def deactivated?
+ !activated?
+ end
+
+ def activate!
+ update_attribute :deleted_at, nil
+ end
+
+ def deactivate!
+ update_attribute :deleted_at, Time.now
+ end
+
+ def time_zone_offset
+ return 0 unless time_zone.present?
+ ActiveSupport::TimeZone[time_zone]&.utc_offset
+ end
+
+ def country_name
+ return unless country_code
+
+ country = ISO3166::Country[country_code]
+ country.translations[I18n.locale.to_s] || country.name
+ end
+
+ def time_zone_formatted_offset
+ return nil unless time_zone.present?
+ ActiveSupport::TimeZone[time_zone]&.formatted_offset
+ end
+
+ def commercial?
+ kind == "commercial"
+ end
end
end
diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb
index 74c20f061..15b22b671 100644
--- a/app/models/chouette/time_table.rb
+++ b/app/models/chouette/time_table.rb
@@ -4,11 +4,13 @@ module Chouette
include ChecksumSupport
include TimeTableRestrictions
include ObjectidSupport
+ include ApplicationDaysSupport
+ include TimetableSupport
+
# FIXME http://jira.codehaus.org/browse/JRUBY-6358
self.primary_key = "id"
acts_as_taggable
- attr_accessor :monday,:tuesday,:wednesday,:thursday,:friday,:saturday,:sunday
attr_accessor :tag_search
def self.ransackable_attributes auth_object = nil
@@ -40,11 +42,18 @@ module Chouette
def checksum_attributes
[].tap do |attrs|
attrs << self.int_day_types
- attrs << self.dates.map(&:checksum).map(&:to_s).sort
- attrs << self.periods.map(&:checksum).map(&:to_s).sort
+ dates = self.dates
+ dates += TimeTableDate.where(time_table_id: self.id)
+ attrs << dates.map(&:checksum).map(&:to_s).sort
+ periods = self.periods
+ periods += TimeTablePeriod.where(time_table_id: self.id)
+ attrs << periods.map(&:checksum).map(&:to_s).sort
end
end
+ has_checksum_children TimeTableDate
+ has_checksum_children TimeTablePeriod
+
def self.object_id_key
"Timetable"
end
@@ -81,72 +90,36 @@ module Chouette
end
end
- def state_update state
- update_attributes(self.class.state_permited_attributes(state))
- self.tag_list = state['tags'].collect{|t| t['name']}.join(', ')
- self.calendar_id = nil unless state['calendar']
-
- days = state['day_types'].split(',')
- Date::DAYNAMES.map(&:underscore).each do |name|
- prefix = human_attribute_name(name).first(2)
- send("#{name}=", days.include?(prefix))
- end
-
- saved_dates = Hash[self.dates.collect{ |d| [d.id, d.date]}]
- cmonth = Date.parse(state['current_periode_range'])
-
- state['current_month'].each do |d|
- date = Date.parse(d['date'])
- checked = d['include_date'] || d['excluded_date']
- in_out = d['include_date'] ? true : false
-
- date_id = saved_dates.key(date)
- time_table_date = self.dates.find(date_id) if date_id
+ def find_date_by_id id
+ self.dates.find id
+ end
- next if !checked && !time_table_date
- # Destroy date if no longer checked
- next if !checked && time_table_date.destroy
+ def destroy_date date
+ date.destroy
+ end
- # Create new date
- unless time_table_date
- time_table_date = self.dates.create({in_out: in_out, date: date})
- end
- # Update in_out
- if in_out != time_table_date.in_out
- time_table_date.update_attributes({in_out: in_out})
- end
+ def update_in_out date, in_out
+ if in_out != date.in_out
+ date.update_attributes({in_out: in_out})
end
-
- self.state_update_periods state['time_table_periods']
- self.save
end
- def state_update_periods state_periods
- state_periods.each do |item|
- period = self.periods.find(item['id']) if item['id']
- next if period && item['deleted'] && period.destroy
- period ||= self.periods.build
-
- period.period_start = Date.parse(item['period_start'])
- period.period_end = Date.parse(item['period_end'])
+ def find_period_by_id id
+ self.periods.find id
+ end
- if period.changed?
- period.save
- item['id'] = period.id
- end
- end
+ def build_period
+ periods.build
+ end
- state_periods.delete_if {|item| item['deleted']}
+ def destroy_period period
+ period.destroy
end
def self.state_permited_attributes item
item.slice('comment', 'color').to_hash
end
- def presenter
- @presenter ||= ::TimeTablePresenter.new( self)
- end
-
def self.start_validity_period
[Chouette::TimeTable.minimum(:start_date)].compact.min
end
@@ -167,20 +140,6 @@ module Chouette
self.save
end
- def month_inspect(date)
- (date.beginning_of_month..date.end_of_month).map do |d|
- {
- day: I18n.l(d, format: '%A'),
- date: d.to_s,
- wday: d.wday,
- wnumber: d.strftime("%W").to_s,
- mday: d.mday,
- include_date: include_in_dates?(d),
- excluded_date: excluded_date?(d)
- }
- end
- end
-
def save_shortcuts
shortcuts_update
self.update_column(:start_date, start_date)
@@ -311,102 +270,9 @@ module Chouette
bounding_max = periods_max_date if periods_max_date &&
(bounding_max.nil? || (bounding_max < periods_max_date))
end
-
[bounding_min, bounding_max].compact
end
- def display_day_types
- %w(monday tuesday wednesday thursday friday saturday sunday).select{ |d| self.send(d) }.map{ |d| self.human_attribute_name(d).first(2)}.join(', ')
- end
-
- def day_by_mask(flag)
- int_day_types & flag == flag
- end
-
- def self.day_by_mask(int_day_types,flag)
- int_day_types & flag == flag
- end
-
-
- def valid_days
- # Build an array with day of calendar week (1-7, Monday is 1).
- [].tap do |valid_days|
- valid_days << 1 if monday
- valid_days << 2 if tuesday
- valid_days << 3 if wednesday
- valid_days << 4 if thursday
- valid_days << 5 if friday
- valid_days << 6 if saturday
- valid_days << 7 if sunday
- end
- end
-
- def self.valid_days(int_day_types)
- # Build an array with day of calendar week (1-7, Monday is 1).
- [].tap do |valid_days|
- valid_days << 1 if day_by_mask(int_day_types,4)
- valid_days << 2 if day_by_mask(int_day_types,8)
- valid_days << 3 if day_by_mask(int_day_types,16)
- valid_days << 4 if day_by_mask(int_day_types,32)
- valid_days << 5 if day_by_mask(int_day_types,64)
- valid_days << 6 if day_by_mask(int_day_types,128)
- valid_days << 7 if day_by_mask(int_day_types,256)
- end
- end
-
- def monday
- day_by_mask(4)
- end
- def tuesday
- day_by_mask(8)
- end
- def wednesday
- day_by_mask(16)
- end
- def thursday
- day_by_mask(32)
- end
- def friday
- day_by_mask(64)
- end
- def saturday
- day_by_mask(128)
- end
- def sunday
- day_by_mask(256)
- end
-
- def set_day(day,flag)
- if day == '1' || day == true
- self.int_day_types |= flag
- else
- self.int_day_types &= ~flag
- end
- shortcuts_update
- end
-
- def monday=(day)
- set_day(day,4)
- end
- def tuesday=(day)
- set_day(day,8)
- end
- def wednesday=(day)
- set_day(day,16)
- end
- def thursday=(day)
- set_day(day,32)
- end
- def friday=(day)
- set_day(day,64)
- end
- def saturday=(day)
- set_day(day,128)
- end
- def sunday=(day)
- set_day(day,256)
- end
-
def effective_days_of_period(period,valid_days=self.valid_days)
days = []
period.period_start.upto(period.period_end) do |date|
@@ -453,6 +319,17 @@ module Chouette
days.sort
end
+ def create_date in_out:, date:
+ self.dates.create in_out: in_out, date: date
+ end
+
+ def saved_dates
+ Hash[self.dates.collect{ |d| [d.id, d.date]}]
+ end
+
+ def all_dates
+ dates
+ end
# produce a copy of periods without anyone overlapping or including another
def optimize_overlapping_periods
@@ -569,5 +446,56 @@ module Chouette
tt.comment = I18n.t("activerecord.copy", :name => self.comment)
tt
end
+
+ def intersect_periods!(mask_periods)
+ dates.each do |date|
+ unless mask_periods.any? { |p| p.include? date.date }
+ dates.delete date
+ end
+ end
+
+ periods.each do |period|
+ mask_periods_with_common_part = mask_periods.select { |p| p.intersect? period.range }
+
+ if mask_periods_with_common_part.empty?
+ self.periods.delete period
+ else
+ mask_periods_with_common_part.each do |mask_period|
+ intersection = (mask_period & period.range)
+ period.period_start, period.period_end = intersection.begin, intersection.end
+ end
+ end
+ end
+ end
+
+ def remove_periods!(removed_periods)
+ dates.each do |date|
+ if removed_periods.any? { |p| p.include? date.date }
+ dates.delete date
+ end
+ end
+
+ periods.each do |period|
+ modified_ranges = removed_periods.inject([period.range]) do |period_ranges, removed_period|
+ period_ranges.map { |p| p.remove removed_period }.flatten
+ end
+
+ unless modified_ranges.empty?
+ modified_ranges.each_with_index do |modified_range, index|
+ new_period = index == 0 ? period : periods.build
+
+ new_period.period_start, new_period.period_end =
+ modified_range.min, modified_range.max
+ end
+ else
+ periods.delete period
+ end
+ end
+ end
+
+ def empty?
+ dates.empty? && periods.empty?
+ end
+
end
end
diff --git a/app/models/chouette/time_table_period.rb b/app/models/chouette/time_table_period.rb
index ab3e79d7e..d9b707675 100644
--- a/app/models/chouette/time_table_period.rb
+++ b/app/models/chouette/time_table_period.rb
@@ -42,5 +42,10 @@ module Chouette
def contains?(p)
(p.period_start >= self.period_start && p.period_end <= self.period_end)
end
+
+ def range
+ period_start..period_end
+ end
+
end
-end \ No newline at end of file
+end
diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb
index 247c30668..4a6ba3f75 100644
--- a/app/models/chouette/vehicle_journey.rb
+++ b/app/models/chouette/vehicle_journey.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
module Chouette
class VehicleJourney < Chouette::TridentActiveRecord
has_paper_trail
@@ -21,8 +22,10 @@ module Chouette
belongs_to :company
belongs_to :route
belongs_to :journey_pattern
+ has_many :stop_areas, through: :journey_pattern
has_and_belongs_to_many :footnotes, :class_name => 'Chouette::Footnote'
+ has_and_belongs_to_many :purchase_windows, :class_name => 'Chouette::PurchaseWindow'
validates_presence_of :route
validates_presence_of :journey_pattern
@@ -40,6 +43,39 @@ module Chouette
before_validation :set_default_values,
:calculate_vehicle_journey_at_stop_day_offset
+ scope :with_stop_area_ids, ->(ids){
+ _ids = ids.select(&:present?).map(&:to_i)
+ if _ids.present?
+ where("array(SELECT stop_points.stop_area_id::integer FROM stop_points INNER JOIN journey_patterns_stop_points ON journey_patterns_stop_points.stop_point_id = stop_points.id WHERE journey_patterns_stop_points.journey_pattern_id = vehicle_journeys.journey_pattern_id) @> array[?]", _ids)
+ else
+ all
+ end
+ }
+
+ scope :in_purchase_window, ->(range){
+ purchase_windows = Chouette::PurchaseWindow.overlap_dates(range)
+ sql = purchase_windows.joins(:vehicle_journeys).select('vehicle_journeys.id').uniq.to_sql
+ where("id IN (#{sql})")
+ }
+
+ # We need this for the ransack object in the filters
+ ransacker :purchase_window_date_gt
+ ransacker :stop_area_ids
+
+ # returns VehicleJourneys with at least 1 day in their time_tables
+ # included in the given range
+ def self.with_matching_timetable date_range
+ out = []
+ time_tables = Chouette::TimeTable.where(id: self.joins("INNER JOIN time_tables_vehicle_journeys ON vehicle_journeys.id = time_tables_vehicle_journeys.vehicle_journey_id").pluck('time_tables_vehicle_journeys.time_table_id')).overlapping(date_range)
+ time_tables = time_tables.select do |time_table|
+ range = date_range
+ range = date_range & (time_table.start_date-1.day..time_table.end_date+1.day) || [] if time_table.start_date.present? && time_table.end_date.present?
+ range.any?{|d| time_table.include_day?(d) }
+ end
+ out += time_tables.map{|t| t.vehicle_journey_ids}.flatten
+ where(id: out)
+ end
+
# TODO: Remove this validator
# We've eliminated this validation because it prevented vehicle journeys
# from being saved with at-stops having a day offset greater than 0,
@@ -68,10 +104,14 @@ module Chouette
attrs << self.published_journey_identifier
attrs << self.try(:company).try(:get_objectid).try(:local_id)
attrs << self.footnotes.map(&:checksum).sort
- attrs << self.vehicle_journey_at_stops.map(&:checksum).sort
+ vjas = self.vehicle_journey_at_stops
+ vjas += VehicleJourneyAtStop.where(vehicle_journey_id: self.id)
+ attrs << vjas.uniq.sort_by { |s| s.stop_point&.position }.map(&:checksum).sort
end
end
+ has_checksum_children VehicleJourneyAtStop
+
def set_default_values
if number.nil?
self.number = 0
@@ -117,10 +157,14 @@ module Chouette
def update_vjas_from_state state
state.each do |vjas|
next if vjas["dummy"]
+ stop_point = Chouette::StopPoint.find_by(objectid: vjas['stop_point_objectid'])
+ stop_area = stop_point&.stop_area
+ tz = stop_area&.time_zone
+ tz = tz && ActiveSupport::TimeZone[tz]
params = {}.tap do |el|
['arrival_time', 'departure_time'].each do |field|
time = "#{vjas[field]['hour']}:#{vjas[field]['minute']}"
- el[field.to_sym] = Time.parse("2000-01-01 #{time}:00 UTC")
+ el[field.to_sym] = Time.parse("2000-01-01 #{time}:00 #{tz&.formatted_offset || "UTC"}")
end
end
stop = create_or_find_vjas_from_state(vjas)
@@ -139,7 +183,7 @@ module Chouette
end
def update_has_and_belongs_to_many_from_state item
- ['time_tables', 'footnotes'].each do |assos|
+ ['time_tables', 'footnotes', 'purchase_windows'].each do |assos|
saved = self.send(assos).map(&:id)
(saved - item[assos].map{|t| t['id']}).each do |id|
@@ -168,7 +212,8 @@ module Chouette
vj.update_attributes(state_permited_attributes(item))
vj.update_has_and_belongs_to_many_from_state(item)
- item['errors'] = vj.errors.full_messages.uniq if vj.errors.any?
+ item['errors'] = vj.errors.full_messages.uniq if vj.errors.any?
+ item['checksum'] = vj.checksum
end
# Delete ids of new object from state if we had to rollback
@@ -192,16 +237,33 @@ module Chouette
def self.state_create_instance route, item
# Flag new record, so we can unset object_id if transaction rollback
vj = route.vehicle_journeys.create(state_permited_attributes(item))
- item['objectid'] = vj.objectid
+ vj.after_commit_objectid
+ item['objectid'] = vj.objectid
+ item['short_id'] = vj.get_objectid.short_id
item['new_record'] = true
vj
end
def self.state_permited_attributes item
- attrs = item.slice('published_journey_identifier', 'published_journey_name', 'journey_pattern_id', 'company_id').to_hash
- ['company', 'journey_pattern'].map do |association|
- attrs["#{association}_id"] = item[association]['id'] if item[association]
+ attrs = item.slice(
+ 'published_journey_identifier',
+ 'published_journey_name',
+ 'journey_pattern_id',
+ 'company_id'
+ ).to_hash
+
+ if item['journey_pattern']
+ attrs['journey_pattern_id'] = item['journey_pattern']['id']
end
+
+ attrs['company_id'] = item['company'] ? item['company']['id'] : nil
+
+ attrs["custom_field_values"] = Hash[
+ *(item["custom_fields"] || {})
+ .map { |k, v| [k, v["value"]] }
+ .flatten
+ ]
+
attrs
end
@@ -240,12 +302,25 @@ module Chouette
end
end
+ def self.custom_fields
+ CustomField.where(resource_type: self.name.split("::").last)
+ end
+
+
+ def custom_fields
+ Hash[*self.class.custom_fields.map do |v|
+ [v.code, v.slice(:code, :name, :field_type, :options).update(value: custom_field_value(v.code))]
+ end.flatten]
+ end
+
+ def custom_field_value key
+ (custom_field_values || {})[key.to_s]
+ end
+
def self.matrix(vehicle_journeys)
- {}.tap do |hash|
- vehicle_journeys.map{ |vj|
- vj.vehicle_journey_at_stops.map{ |vjas |hash[ "#{vj.id}-#{vjas.stop_point_id}"] = vjas }
- }
- end
+ Hash[*VehicleJourneyAtStop.where(vehicle_journey_id: vehicle_journeys.pluck(:id)).map do |vjas|
+ [ "#{vjas.vehicle_journey_id}-#{vjas.stop_point_id}", vjas]
+ end.flatten]
end
def self.with_stops
@@ -304,5 +379,10 @@ module Chouette
')
.where('"time_tables_vehicle_journeys"."vehicle_journey_id" IS NULL')
end
+
+ def self.lines
+ lines_query = joins(:route).select("routes.line_id").to_sql
+ Chouette::Line.where("id IN (#{lines_query})")
+ end
end
end
diff --git a/app/models/chouette/vehicle_journey_at_stop.rb b/app/models/chouette/vehicle_journey_at_stop.rb
index 6f0119e74..eda711ade 100644
--- a/app/models/chouette/vehicle_journey_at_stop.rb
+++ b/app/models/chouette/vehicle_journey_at_stop.rb
@@ -75,5 +75,42 @@ module Chouette
attrs << self.arrival_day_offset.to_s
end
end
+
+ def departure
+ format_time departure_time.utc
+ end
+
+ def arrival
+ format_time arrival_time.utc
+ end
+
+ def departure_local_time
+ local_time departure_time
+ end
+
+ def arrival_local_time
+ local_time arrival_time
+ end
+
+ def departure_local
+ format_time departure_local_time
+ end
+
+ def arrival_local
+ format_time arrival_local_time
+ end
+
+ private
+ def local_time time
+ return unless time
+ return time unless stop_point&.stop_area&.time_zone.present?
+ return time unless ActiveSupport::TimeZone[stop_point.stop_area.time_zone].present?
+ time + ActiveSupport::TimeZone[stop_point.stop_area.time_zone].utc_offset
+ end
+
+ def format_time time
+ time.strftime "%H:%M" if time
+ end
+
end
-end \ No newline at end of file
+end
diff --git a/app/models/compliance_check_block.rb b/app/models/compliance_check_block.rb
index 05240b428..059547e1b 100644
--- a/app/models/compliance_check_block.rb
+++ b/app/models/compliance_check_block.rb
@@ -6,8 +6,8 @@ class ComplianceCheckBlock < ActiveRecord::Base
has_many :compliance_checks
- hstore_accessor :condition_attributes,
- transport_mode: :string,
- transport_submode: :string
+ store_accessor :condition_attributes,
+ :transport_mode,
+ :transport_submode
end
diff --git a/app/models/compliance_check_message_export.rb b/app/models/compliance_check_message_export.rb
new file mode 100644
index 000000000..04e1a9caa
--- /dev/null
+++ b/app/models/compliance_check_message_export.rb
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+require "csv"
+require "zip"
+
+class ComplianceCheckMessageExport
+ include ActiveModel::Validations
+ include ActiveModel::Conversion
+ extend ActiveModel::Naming
+
+ attr_accessor :compliance_check_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", "resource objectid", "link", "message"]
+ end
+
+ def to_csv(options = {})
+ CSV.generate(options.slice(:col_sep, :quote_char, :force_quotes)) do |csv|
+ csv << column_names
+ compliance_check_messages.each do |compliance_check_message|
+ csv << [compliance_check_message.compliance_check.criticity, *compliance_check_message.message_attributes.values_at('test_id', 'source_objectid'), options[:server_url] + compliance_check_message.message_attributes['source_object_path'], I18n.t("compliance_check_messages.#{compliance_check_message.message_key}", compliance_check_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/compliance_check_set.rb b/app/models/compliance_check_set.rb
index 020100f4a..289fc134f 100644
--- a/app/models/compliance_check_set.rb
+++ b/app/models/compliance_check_set.rb
@@ -1,6 +1,6 @@
class ComplianceCheckSet < ActiveRecord::Base
extend Enumerize
- has_paper_trail
+ has_paper_trail class_name: 'PublicVersion'
belongs_to :referential
belongs_to :compliance_control_set
@@ -19,6 +19,20 @@ class ComplianceCheckSet < ActiveRecord::Base
where('created_at BETWEEN :begin AND :end', begin: period_range.begin, end: period_range.end)
end
+ scope :blocked, -> { where('created_at < ? AND status = ?', 4.hours.ago, 'running') }
+
+ def self.finished_statuses
+ %w(successful failed warning aborted canceled)
+ end
+
+ def self.abort_old
+ where(
+ 'created_at < ? AND status NOT IN (?)',
+ 4.hours.ago,
+ finished_statuses
+ ).update_all(status: 'aborted')
+ end
+
def notify_parent
if parent
# parent.child_change
@@ -26,6 +40,14 @@ class ComplianceCheckSet < ActiveRecord::Base
end
end
+ def organisation
+ workbench.organisation
+ end
+
+ def human_attribute_name(*args)
+ self.class.human_attribute_name(*args)
+ end
+
def update_status
statuses = compliance_check_resources.map do |resource|
case resource.status
diff --git a/app/models/compliance_control.rb b/app/models/compliance_control.rb
index 65e22643d..298a63ab9 100644
--- a/app/models/compliance_control.rb
+++ b/app/models/compliance_control.rb
@@ -3,10 +3,8 @@ class ComplianceControl < ActiveRecord::Base
class << self
def criticities; %i(warning error) end
def default_code; "" end
- def prerequisite; I18n.t('compliance_controls.metas.no_prerequisite'); end
- def predicate; I18n.t("compliance_controls.#{self.name.underscore}.description") end
def dynamic_attributes
- hstore_metadata_for_control_attributes.keys
+ stored_attributes[:control_attributes] || []
end
def policy_class
@@ -39,7 +37,6 @@ class ComplianceControl < ActiveRecord::Base
belongs_to :compliance_control_block
enumerize :criticity, in: criticities, scope: true, default: :warning
- hstore_accessor :control_attributes, {}
validates :criticity, presence: true
validates :name, presence: true
@@ -66,6 +63,9 @@ def initialize(attributes = {})
self.origin_code ||= self.class.default_code
end
+def predicate; I18n.t("compliance_controls.#{self.class.name.underscore}.description") end
+def prerequisite; I18n.t('compliance_controls.metas.no_prerequisite'); end
+
end
# Ensure STI subclasses are loaded
diff --git a/app/models/compliance_control_block.rb b/app/models/compliance_control_block.rb
index e27f85ae0..d7d84fd06 100644
--- a/app/models/compliance_control_block.rb
+++ b/app/models/compliance_control_block.rb
@@ -5,9 +5,9 @@ class ComplianceControlBlock < ActiveRecord::Base
belongs_to :compliance_control_set
has_many :compliance_controls, dependent: :destroy
- hstore_accessor :condition_attributes,
- transport_mode: :string,
- transport_submode: :string
+ store_accessor :condition_attributes,
+ :transport_mode,
+ :transport_submode
validates :transport_mode, presence: true
validates :compliance_control_set, presence: true
diff --git a/app/models/compliance_control_set.rb b/app/models/compliance_control_set.rb
index 41076fefc..c0ea692f2 100644
--- a/app/models/compliance_control_set.rb
+++ b/app/models/compliance_control_set.rb
@@ -1,5 +1,5 @@
class ComplianceControlSet < ActiveRecord::Base
- has_paper_trail
+ has_paper_trail class_name: 'PublicVersion'
belongs_to :organisation
has_many :compliance_control_blocks, dependent: :destroy
has_many :compliance_controls, dependent: :destroy
diff --git a/app/models/concerns/application_days_support.rb b/app/models/concerns/application_days_support.rb
new file mode 100644
index 000000000..348436aa4
--- /dev/null
+++ b/app/models/concerns/application_days_support.rb
@@ -0,0 +1,107 @@
+module ApplicationDaysSupport
+ extend ActiveSupport::Concern
+
+ MONDAY = 4
+ TUESDAY = 8
+ WEDNESDAY = 16
+ THURSDAY = 32
+ FRIDAY = 64
+ SATURDAY = 128
+ SUNDAY = 256
+ EVERYDAY = MONDAY | TUESDAY | WEDNESDAY | THURSDAY | FRIDAY | SATURDAY | SUNDAY
+
+ def display_day_types
+ %w(monday tuesday wednesday thursday friday saturday sunday).select{ |d| self.send(d) }.map{ |d| self.human_attribute_name(d).first(2)}.join(', ')
+ end
+
+ def day_by_mask(flag)
+ int_day_types & flag == flag
+ end
+
+ def self.day_by_mask(int_day_types,flag)
+ int_day_types & flag == flag
+ end
+
+ def valid_days
+ # Build an array with day of calendar week (1-7, Monday is 1).
+ [].tap do |valid_days|
+ valid_days << 1 if monday
+ valid_days << 2 if tuesday
+ valid_days << 3 if wednesday
+ valid_days << 4 if thursday
+ valid_days << 5 if friday
+ valid_days << 6 if saturday
+ valid_days << 7 if sunday
+ end
+ end
+
+ def valid_day? wday
+ valid_days.include?(wday)
+ end
+
+ def self.valid_days(int_day_types)
+ # Build an array with day of calendar week (1-7, Monday is 1).
+ [].tap do |valid_days|
+ valid_days << 1 if day_by_mask(int_day_types,MONDAY)
+ valid_days << 2 if day_by_mask(int_day_types,TUESDAY)
+ valid_days << 3 if day_by_mask(int_day_types,WEDNESDAY)
+ valid_days << 4 if day_by_mask(int_day_types,THURSDAY)
+ valid_days << 5 if day_by_mask(int_day_types,FRIDAY)
+ valid_days << 6 if day_by_mask(int_day_types,SATURDAY)
+ valid_days << 7 if day_by_mask(int_day_types,SUNDAY)
+ end
+ end
+
+ def monday
+ day_by_mask(MONDAY)
+ end
+ def tuesday
+ day_by_mask(TUESDAY)
+ end
+ def wednesday
+ day_by_mask(WEDNESDAY)
+ end
+ def thursday
+ day_by_mask(THURSDAY)
+ end
+ def friday
+ day_by_mask(FRIDAY)
+ end
+ def saturday
+ day_by_mask(SATURDAY)
+ end
+ def sunday
+ day_by_mask(SUNDAY)
+ end
+
+ def set_day(day,flag)
+ if day == '1' || day == true
+ self.int_day_types |= flag
+ else
+ self.int_day_types &= ~flag
+ end
+ shortcuts_update
+ end
+
+ def monday=(day)
+ set_day(day,4)
+ end
+ def tuesday=(day)
+ set_day(day,8)
+ end
+ def wednesday=(day)
+ set_day(day,16)
+ end
+ def thursday=(day)
+ set_day(day,32)
+ end
+ def friday=(day)
+ set_day(day,64)
+ end
+ def saturday=(day)
+ set_day(day,128)
+ end
+ def sunday=(day)
+ set_day(day,256)
+ end
+end
diff --git a/app/models/concerns/checksum_support.rb b/app/models/concerns/checksum_support.rb
index c95e23bcf..92103798e 100644
--- a/app/models/concerns/checksum_support.rb
+++ b/app/models/concerns/checksum_support.rb
@@ -3,18 +3,50 @@ module ChecksumSupport
SEPARATOR = '|'
VALUE_FOR_NIL_ATTRIBUTE = '-'
- included do
+ included do |into|
before_save :set_current_checksum_source, :update_checksum
+ Referential.register_model_with_checksum self
+ into.extend ClassMethods
+ end
+
+ module ClassMethods
+ def has_checksum_children klass, opts={}
+ parent_class = self
+ relation = opts[:relation] || self.model_name.singular
+ klass.after_save do
+ parent = self.send(relation)
+ parent&.update_checksum_without_callbacks!
+ end
+ end
end
def checksum_attributes
self.attributes.values
end
+ def checksum_replace_nil_or_empty_values values
+ # Replace empty array by nil & nil by VALUE_FOR_NIL_ATTRIBUTE
+ values
+ .map { |x| x.present? && x || VALUE_FOR_NIL_ATTRIBUTE }
+ .map do |item|
+ item =
+ if item.kind_of?(Array)
+ checksum_replace_nil_or_empty_values(item)
+ else
+ item
+ end
+ end
+ end
+
def current_checksum_source
- source = self.checksum_attributes.map{ |x| x unless x.try(:empty?) }
- source = source.map{ |x| x || VALUE_FOR_NIL_ATTRIBUTE }
- source.map(&:to_s).join(SEPARATOR)
+ source = checksum_replace_nil_or_empty_values(self.checksum_attributes)
+ source.map{ |item|
+ if item.kind_of?(Array)
+ item.map{ |x| x.kind_of?(Array) ? "(#{x.join(',')})" : x }.join(',')
+ else
+ item
+ end
+ }.join(SEPARATOR)
end
def set_current_checksum_source
@@ -26,4 +58,20 @@ module ChecksumSupport
self.checksum = Digest::SHA256.new.hexdigest(self.checksum_source)
end
end
+
+ def update_checksum!
+ set_current_checksum_source
+ if checksum_source_changed?
+ update checksum: Digest::SHA256.new.hexdigest(checksum_source)
+ end
+ end
+
+ def update_checksum_without_callbacks!
+ set_current_checksum_source
+ _checksum = Digest::SHA256.new.hexdigest(checksum_source)
+ if _checksum != self.checksum
+ self.checksum = _checksum
+ self.class.where(id: self.id).update_all(checksum: _checksum) unless self.new_record?
+ end
+ end
end
diff --git a/app/models/concerns/date_support.rb b/app/models/concerns/date_support.rb
new file mode 100644
index 000000000..5c66cb1a9
--- /dev/null
+++ b/app/models/concerns/date_support.rb
@@ -0,0 +1,83 @@
+module DateSupport
+ extend ActiveSupport::Concern
+
+ included do
+ after_initialize :init_dates
+
+ def init_dates
+ self.dates ||= []
+ end
+
+ ### Calendar::DateValue
+ # Required by coocon
+ def build_date_value
+ Calendar::DateValue.new
+ end
+
+ def date_values
+ @date_values ||= init_date_values
+ end
+
+ def init_date_values
+ if dates
+ dates.each_with_index.map { |d, index| Calendar::DateValue.from_date(index, d) }
+ else
+ []
+ end
+ end
+ private :init_date_values
+
+ validate :validate_date_values
+
+ def validate_date_values
+ date_values_are_valid = date_values.all?(&:valid?)
+
+ date_values.each do |date_value|
+ if date_values.count { |d| d.value == date_value.value } > 1
+ date_value.errors.add(:base, I18n.t('activerecord.errors.models.calendar.attributes.dates.date_in_dates'))
+ date_values_are_valid = false
+ end
+ date_ranges.each do |date_range|
+ if date_range.cover?(date_value.value)
+ excluded_day = self.respond_to?(:valid_day?) && !self.valid_day?(date_value.value.wday)
+ unless excluded_day
+ date_value.errors.add(:base, I18n.t('activerecord.errors.models.calendar.attributes.dates.date_in_date_ranges'))
+ date_values_are_valid = false
+ end
+ end
+ end
+ end
+
+ unless date_values_are_valid
+ errors.add(:date_values, :invalid)
+ end
+ end
+
+ def date_values_attributes=(attributes = {})
+ @date_values = []
+ attributes.each do |index, date_value_attribute|
+ date_value_attribute['value'] = flatten_date_array(date_value_attribute, 'value')
+ date_value = Calendar::DateValue.new(date_value_attribute.merge(id: index))
+ @date_values << date_value unless date_value.marked_for_destruction?
+ end
+
+ dates_will_change!
+ end
+
+ before_validation :fill_dates
+
+ def fill_dates
+ if @date_values
+ self.dates = @date_values.map(&:value).compact.sort
+ end
+ end
+
+ after_save :clear_date_values
+
+ def clear_date_values
+ @date_values = nil
+ end
+
+ private :clear_date_values
+ end
+end
diff --git a/app/models/concerns/min_max_values_validation.rb b/app/models/concerns/min_max_values_validation.rb
index c177e55ca..eff779d81 100644
--- a/app/models/concerns/min_max_values_validation.rb
+++ b/app/models/concerns/min_max_values_validation.rb
@@ -2,12 +2,12 @@ module MinMaxValuesValidation
extend ActiveSupport::Concern
included do
+ validates_presence_of :minimum, :maximum
validate :min_max_values_validation
end
def min_max_values_validation
- return true unless minimum && maximum
- return true unless maximum < minimum
- errors.add(:min_max_values, I18n.t('compliance_controls.min_max_values', min: minimum, max: maximum))
+ return true if (minimum && maximum) && (minimum.to_i < maximum.to_i)
+ errors.add(:minimum, I18n.t('compliance_controls.min_max_values', min: minimum, max: maximum))
end
end
diff --git a/app/models/concerns/objectid_support.rb b/app/models/concerns/objectid_support.rb
index cec36678e..5d1f1a1c2 100644
--- a/app/models/concerns/objectid_support.rb
+++ b/app/models/concerns/objectid_support.rb
@@ -26,5 +26,10 @@ module ObjectidSupport
def objectid_class
get_objectid.try(:class)
end
+
+ def raw_objectid
+ read_attribute(:objectid)
+ end
+
end
end
diff --git a/app/models/concerns/period_support.rb b/app/models/concerns/period_support.rb
new file mode 100644
index 000000000..e17451fe4
--- /dev/null
+++ b/app/models/concerns/period_support.rb
@@ -0,0 +1,80 @@
+module PeriodSupport
+ extend ActiveSupport::Concern
+
+ included do
+ after_initialize :init_date_ranges
+
+ def init_date_ranges
+ self.date_ranges ||= []
+ end
+
+ ### Calendar::Period
+ # Required by coocon
+ def build_period
+ Calendar::Period.new
+ end
+
+ def periods
+ @periods ||= init_periods
+ end
+
+ def init_periods
+ (date_ranges || [])
+ .each_with_index
+ .map( &Calendar::Period.method(:from_range) )
+ end
+ private :init_periods
+
+ validate :validate_periods
+
+ def validate_periods
+ periods_are_valid = periods.all?(&:valid?)
+
+ periods.each do |period|
+ if period.intersect?(periods)
+ period.errors.add(:base, I18n.t('calendars.errors.overlapped_periods'))
+ periods_are_valid = false
+ end
+ end
+
+ unless periods_are_valid
+ errors.add(:periods, :invalid)
+ end
+ end
+
+ def flatten_date_array attributes, key
+ date_int = %w(1 2 3).map {|e| attributes["#{key}(#{e}i)"].to_i }
+ Date.new(*date_int)
+ end
+
+ def periods_attributes=(attributes = {})
+ @periods = []
+ attributes.each do |index, period_attribute|
+ # Convert date_select to date
+ ['begin', 'end'].map do |attr|
+ period_attribute[attr] = flatten_date_array(period_attribute, attr)
+ end
+ period = Calendar::Period.new(period_attribute.merge(id: index))
+ @periods << period unless period.marked_for_destruction?
+ end
+
+ date_ranges_will_change!
+ end
+
+ before_validation :fill_date_ranges
+
+ def fill_date_ranges
+ if @periods
+ self.date_ranges = @periods.map(&:range).compact.sort_by(&:begin)
+ end
+ end
+
+ after_save :clear_periods
+
+ def clear_periods
+ @periods = nil
+ end
+
+ private :clear_periods
+ end
+end
diff --git a/app/models/concerns/timetable_support.rb b/app/models/concerns/timetable_support.rb
new file mode 100644
index 000000000..5242abc33
--- /dev/null
+++ b/app/models/concerns/timetable_support.rb
@@ -0,0 +1,149 @@
+module TimetableSupport
+ extend ActiveSupport::Concern
+
+ def presenter
+ @presenter ||= ::TimeTablePresenter.new( self)
+ end
+
+ def periods_max_date
+ return nil if self.periods.empty?
+
+ min_start = self.periods.map(&:period_start).compact.min
+ max_end = self.periods.map(&:period_end).compact.max
+ result = nil
+
+ if max_end && min_start
+ max_end.downto( min_start) do |date|
+ if self.valid_days.include?(date.cwday) && !self.excluded_date?(date)
+ result = date
+ break
+ end
+ end
+ end
+ result
+ end
+
+ def periods_min_date
+ return nil if self.periods.empty?
+
+ min_start = self.periods.map(&:period_start).compact.min
+ max_end = self.periods.map(&:period_end).compact.max
+ result = nil
+
+ if max_end && min_start
+ min_start.upto(max_end) do |date|
+ if self.valid_days.include?(date.cwday) && !self.excluded_date?(date)
+ result = date
+ break
+ end
+ end
+ end
+ result
+ end
+
+ def bounding_dates
+ bounding_min = self.all_dates.select{|d| d.in_out}.map(&:date).compact.min
+ bounding_max = self.all_dates.select{|d| d.in_out}.map(&:date).compact.max
+
+ unless self.periods.empty?
+ bounding_min = periods_min_date if periods_min_date &&
+ (bounding_min.nil? || (periods_min_date < bounding_min))
+
+ bounding_max = periods_max_date if periods_max_date &&
+ (bounding_max.nil? || (bounding_max < periods_max_date))
+ end
+
+ [bounding_min, bounding_max].compact
+ end
+
+ def month_inspect(date)
+ (date.beginning_of_month..date.end_of_month).map do |d|
+ {
+ day: I18n.l(d, format: '%A'),
+ date: d.to_s,
+ wday: d.wday,
+ wnumber: d.strftime("%W").to_s,
+ mday: d.mday,
+ include_date: include_in_dates?(d),
+ excluded_date: excluded_date?(d)
+ }
+ end
+ end
+
+ def include_in_dates?(day)
+ self.dates.any?{ |d| d.date === day && d.in_out == true }
+ end
+
+ def excluded_date?(day)
+ self.dates.any?{ |d| d.date === day && d.in_out == false }
+ end
+
+ def include_in_overlap_dates?(day)
+ return false if self.excluded_date?(day)
+
+ self.all_dates.any?{ |d| d.date === day} \
+ && self.periods.any?{ |period| period.period_start <= day && day <= period.period_end && valid_days.include?(day.cwday) }
+ end
+
+ def include_in_periods?(day)
+ self.periods.any?{ |period| period.period_start <= day &&
+ day <= period.period_end &&
+ valid_days.include?(day.cwday) &&
+ ! excluded_date?(day) }
+ end
+
+ def state_update_periods state_periods
+ state_periods.each do |item|
+ period = self.find_period_by_id(item['id']) if item['id']
+ next if period && item['deleted'] && self.destroy_period(period)
+ period ||= self.build_period
+
+ period.period_start = Date.parse(item['period_start'])
+ period.period_end = Date.parse(item['period_end'])
+
+ period.save if period.is_a?(ActiveRecord::Base) && period.changed?
+
+ item['id'] = period.id
+ end
+
+ state_periods.delete_if {|item| item['deleted']}
+ end
+
+ def state_update state
+ update_attributes(self.class.state_permited_attributes(state))
+ self.tag_list = state['tags'].collect{|t| t['name']}.join(', ') if state['tags']
+ self.calendar_id = nil if self.respond_to?(:calendar_id) && !state['calendar']
+
+ days = state['day_types'].split(',')
+ Date::DAYNAMES.map(&:underscore).each do |name|
+ prefix = human_attribute_name(name).first(2)
+ send("#{name}=", days.include?(prefix))
+ end
+
+ cmonth = Date.parse(state['current_periode_range'])
+
+ state['current_month'].each do |d|
+ date = Date.parse(d['date'])
+ checked = d['include_date'] || d['excluded_date']
+ in_out = d['include_date'] ? true : false
+
+ date_id = saved_dates.key(date)
+ time_table_date = self.find_date_by_id(date_id) if date_id
+
+ next if !checked && !time_table_date
+ # Destroy date if no longer checked
+ next if !checked && destroy_date(time_table_date)
+
+ # Create new date
+ unless time_table_date
+ time_table_date = self.create_date in_out: in_out, date: date
+ end
+ # Update in_out
+ self.update_in_out time_table_date, in_out
+ end
+
+ self.state_update_periods state['time_table_periods']
+ self.save
+ end
+
+end
diff --git a/app/models/custom_field.rb b/app/models/custom_field.rb
new file mode 100644
index 000000000..774c8b0f6
--- /dev/null
+++ b/app/models/custom_field.rb
@@ -0,0 +1,9 @@
+class CustomField < ActiveRecord::Base
+
+ extend Enumerize
+ belongs_to :workgroup
+ enumerize :field_type, in: %i{list}
+
+ validates :name, uniqueness: {scope: [:resource_type, :workgroup_id]}
+ validates :code, uniqueness: {scope: [:resource_type, :workgroup_id], case_sensitive: false}
+end
diff --git a/app/models/generic_attribute_control/min_max.rb b/app/models/generic_attribute_control/min_max.rb
index ab6f546a7..18873b683 100644
--- a/app/models/generic_attribute_control/min_max.rb
+++ b/app/models/generic_attribute_control/min_max.rb
@@ -1,9 +1,9 @@
module GenericAttributeControl
class MinMax < ComplianceControl
- hstore_accessor :control_attributes, minimum: :integer, maximum: :integer, target: :string
+ store_accessor :control_attributes, :minimum, :maximum, :target
- validates :minimum, numericality: true, allow_nil: true
- validates :maximum, numericality: true, allow_nil: true
+ validates_numericality_of :minimum, allow_nil: true, greater_than_or_equal_to: 0
+ validates_numericality_of :maximum, allow_nil: true, greater_than_or_equal_to: 0
validates :target, presence: true
include MinMaxValuesValidation
diff --git a/app/models/generic_attribute_control/pattern.rb b/app/models/generic_attribute_control/pattern.rb
index 3a4a55d5c..7fc008e28 100644
--- a/app/models/generic_attribute_control/pattern.rb
+++ b/app/models/generic_attribute_control/pattern.rb
@@ -1,6 +1,6 @@
module GenericAttributeControl
class Pattern < ComplianceControl
- hstore_accessor :control_attributes, pattern: :string, target: :string
+ store_accessor :control_attributes, :pattern, :target
validates :target, presence: true
validates :pattern, presence: true
diff --git a/app/models/generic_attribute_control/uniqueness.rb b/app/models/generic_attribute_control/uniqueness.rb
index f707c944b..82b5c0892 100644
--- a/app/models/generic_attribute_control/uniqueness.rb
+++ b/app/models/generic_attribute_control/uniqueness.rb
@@ -1,6 +1,6 @@
module GenericAttributeControl
class Uniqueness < ComplianceControl
- hstore_accessor :control_attributes, target: :string
+ store_accessor :control_attributes, :target
validates :target, presence: true
diff --git a/app/models/import.rb b/app/models/import.rb
index 19e835986..29aadcd56 100644
--- a/app/models/import.rb
+++ b/app/models/import.rb
@@ -13,13 +13,14 @@ class Import < ActiveRecord::Base
where('started_at BETWEEN :begin AND :end', begin: period_range.begin, end: period_range.end)
end
+ scope :blocked, -> { where('created_at < ? AND status = ?', 4.hours.ago, 'running') }
+
extend Enumerize
enumerize :status, in: %w(new pending successful warning failed running aborted canceled), scope: true, default: :new
validates :name, presence: true
validates :file, presence: true
validates_presence_of :workbench, :creator
- validates_format_of :file, with: %r{\.zip\z}i, message: I18n.t('activerecord.errors.models.import.attributes.file.wrong_file_extension')
before_create :initialize_fields
@@ -43,6 +44,14 @@ class Import < ActiveRecord::Base
%w(successful failed warning aborted canceled)
end
+ def self.abort_old
+ where(
+ 'created_at < ? AND status NOT IN (?)',
+ 4.hours.ago,
+ finished_statuses
+ ).update_all(status: 'aborted')
+ end
+
def notify_parent
parent.child_change
update(notified_parent_at: DateTime.now)
diff --git a/app/models/import_message_export.rb b/app/models/import_message_export.rb
index 88d0f27e2..05f8a2cc7 100644
--- a/app/models/import_message_export.rb
+++ b/app/models/import_message_export.rb
@@ -22,14 +22,14 @@ class ImportMessageExport
end
def column_names
- ["criticity", "message key", "message"]
+ ["criticity", "message key", "message", "file name", "line", "column"]
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) ]
+ csv << [import_message.criticity, import_message.message_key, I18n.t("import_messages.#{import_message.message_key}", import_message.message_attributes.deep_symbolize_keys), *import_message.resource_attributes.values_at("filename", "line_number", "column_number") ]
end
end
end
diff --git a/app/models/line_control/route.rb b/app/models/line_control/route.rb
index b4b2bd9d8..b6c1f3630 100644
--- a/app/models/line_control/route.rb
+++ b/app/models/line_control/route.rb
@@ -3,6 +3,6 @@ module LineControl
def self.default_code; "3-Line-1" end
- def self.prerequisite; I18n.t("compliance_controls.#{self.name.underscore}.prerequisite") end
+ def prerequisite; I18n.t("compliance_controls.#{self.class.name.underscore}.prerequisite") end
end
end
diff --git a/app/models/merge.rb b/app/models/merge.rb
new file mode 100644
index 000000000..62bf581d6
--- /dev/null
+++ b/app/models/merge.rb
@@ -0,0 +1,435 @@
+class Merge < ActiveRecord::Base
+ extend Enumerize
+
+ belongs_to :workbench
+ validates :workbench, presence: true
+
+ enumerize :status, in: %w[new pending successful failed running], default: :new
+
+ has_array_of :referentials, class_name: 'Referential'
+
+ delegate :output, to: :workbench
+
+ after_commit :merge, :on => :create
+
+ def merge
+ MergeWorker.perform_async(id)
+ end
+
+ def name
+ referentials.first(3).map { |r| r.name.truncate(10) }.join(',')
+ end
+
+ def full_names
+ referentials.map(&:name).to_sentence
+ end
+
+ attr_reader :new
+
+ def merge!
+ update started_at: Time.now, status: :running
+
+ prepare_new
+
+ referentials.each do |referential|
+ merge_referential referential
+ end
+
+ save_current
+ rescue => e
+ Rails.logger.error "Merge failed: #{e} #{e.backtrace.join("\n")}"
+ update status: :failed
+ raise e if Rails.env.test?
+ ensure
+ attributes = { ended_at: Time.now }
+ attributes[:status] = :successful if status == :running
+ update attributes
+ end
+
+ def prepare_new
+ new =
+ if workbench.output.current
+ Rails.logger.debug "Clone current output"
+ Referential.new_from(workbench.output.current, fixme_functional_scope).tap do |clone|
+ clone.inline_clone = true
+ end
+ else
+ Rails.logger.debug "Create a new output"
+ # 'empty' one
+ attributes = {
+ workbench: workbench,
+ organisation: workbench.organisation, # TODO could be workbench.organisation by default
+ }
+ workbench.output.referentials.new attributes
+ end
+
+ new.referential_suite = output
+ new.workbench = workbench
+ new.organisation = workbench.organisation
+ new.slug = "output_#{workbench.id}_#{created_at.to_i}"
+ new.name = I18n.t("merges.referential_name", date: I18n.l(created_at))
+
+ unless new.valid?
+ Rails.logger.error "New referential isn't valid : #{new.errors.inspect}"
+ end
+
+ new.save!
+
+ output.update new: new
+ @new = new
+ end
+
+ def merge_referential(referential)
+ Rails.logger.debug "Merge #{referential.slug}"
+
+ metadata_merger = MetadatasMerger.new new, referential
+ metadata_merger.merge
+
+ new.metadatas.delete metadata_merger.empty_metadatas
+
+ new.save!
+
+ line_periods = LinePeriods.from_metadatas(referential.metadatas)
+
+ new.switch do
+ line_periods.each do |line_id, periods|
+ Rails.logger.debug "Clean data for #{line_id} #{periods.inspect}"
+
+ new.lines.find(line_id).time_tables.find_each do |time_table|
+ time_table.remove_periods! periods
+ unless time_table.empty?
+ time_table.save!
+ else
+ time_table.destroy
+ end
+ end
+ end
+ end
+
+ # let's merge data :)
+
+ # Routes
+
+ # Always the same pattern :
+ # - load models from original Referential
+ # - load associated datas (children, checksum for associated models)
+ # - switch to new Referential
+ # - enumerate loaded models
+ # - skip model if its checksum exists "in the same line"
+ # - prepare attributes for a fresh model
+ # - remove all primary keys
+ # - compute an ObjectId (TODO)
+ # - process children models as nested attributes
+ # - associated other models (by line/checksum)
+ # - save! and next one
+
+ referential_routes = referential.switch do
+ referential.routes.all.to_a
+ end
+
+ referential_routes_checksums = Hash[referential_routes.map { |r| [ r.id, r.checksum ] }]
+
+ referential_stop_points = referential.switch do
+ referential.stop_points.all.to_a
+ end
+
+ referential_stop_points_by_route = referential_stop_points.group_by(&:route_id)
+
+ new.switch do
+ referential_routes.each do |route|
+ existing_route = new.routes.find_by line_id: route.line_id, checksum: route.checksum
+ unless existing_route
+ objectid = Chouette::Route.where(objectid: route.objectid).exists? ? nil : route.objectid
+ attributes = route.attributes.merge(
+ id: nil,
+ objectid: objectid,
+ # line_id is the same
+ # all other primary must be changed
+ opposite_route_id: nil #FIXME
+ )
+ new_route = new.routes.build attributes
+
+ route_stop_points = referential_stop_points_by_route[route.id]
+
+ # Stop Points
+ route_stop_points.each do |stop_point|
+ objectid = Chouette::StopPoint.where(objectid: stop_point.objectid).exists? ? nil : stop_point.objectid
+ attributes = stop_point.attributes.merge(
+ id: nil,
+ route_id: nil,
+ objectid: objectid,
+ )
+
+ new_route.stop_points.build attributes
+ end
+
+ new_route.save!
+
+ if new_route.checksum != route.checksum
+ raise "Checksum has changed: #{route.inspect} #{new_route.inspect}"
+ end
+ end
+ end
+ end
+
+ # JourneyPatterns
+
+ referential_journey_patterns, referential_journey_patterns_stop_areas_objectids = referential.switch do
+ journey_patterns = referential.journey_patterns.includes(stop_points: :stop_area)
+
+ journey_patterns_stop_areas_objectids = Hash[
+ journey_patterns.map do |journey_pattern|
+ [ journey_pattern.id, journey_pattern.stop_points.map(&:stop_area).map(&:raw_objectid)]
+ end
+ ]
+
+ [journey_patterns, journey_patterns_stop_areas_objectids]
+ end
+
+ referential_journey_patterns_checksums = Hash[referential_journey_patterns.map { |j| [ j.id, j.checksum ] }]
+
+ new.switch do
+ referential_journey_patterns.each do |journey_pattern|
+ # find parent route by checksum
+ # TODO add line_id for security
+ associated_route_checksum = referential_routes_checksums[journey_pattern.route_id]
+ existing_associated_route = new.routes.find_by checksum: associated_route_checksum
+
+ existing_journey_pattern = new.journey_patterns.find_by route_id: existing_associated_route.id, checksum: journey_pattern.checksum
+
+ unless existing_journey_pattern
+ objectid = Chouette::JourneyPattern.where(objectid: journey_pattern.objectid).exists? ? nil : journey_pattern.objectid
+ attributes = journey_pattern.attributes.merge(
+ id: nil,
+ objectid: objectid,
+
+ # all other primary must be changed
+ route_id: existing_associated_route.id,
+
+ departure_stop_point_id: nil, # FIXME
+ arrival_stop_point_id: nil
+ )
+
+ stop_areas_objectids = referential_journey_patterns_stop_areas_objectids[journey_pattern.id]
+
+ stop_points = existing_associated_route.stop_points.joins(:stop_area).where("stop_areas.objectid": stop_areas_objectids).order(:position)
+ if stop_points.count != stop_areas_objectids.count
+ raise "Can't find StopPoints for #{stop_areas_objectids} : #{stop_points.inspect} #{existing_associated_route.stop_points.inspect}"
+ end
+
+ attributes.merge!(stop_points: stop_points)
+
+ new_journey_pattern = new.journey_patterns.create! attributes
+ if new_journey_pattern.checksum != journey_pattern.checksum
+ raise "Checksum has changed for #{journey_pattern.inspect}: #{journey_pattern.checksum_source} #{new_journey_pattern.checksum_source} "
+ end
+ end
+ end
+ end
+
+ # Vehicle Journeys
+
+ referential_vehicle_journeys = referential.switch do
+ referential.vehicle_journeys.includes(:vehicle_journey_at_stops).all.to_a
+ end
+
+ new.switch do
+ referential_vehicle_journeys.each do |vehicle_journey|
+ # find parent journey pattern by checksum
+ # TODO add line_id for security
+ associated_journey_pattern_checksum = referential_journey_patterns_checksums[vehicle_journey.journey_pattern_id]
+ existing_associated_journey_pattern = new.journey_patterns.find_by checksum: associated_journey_pattern_checksum
+
+ existing_vehicle_journey = new.vehicle_journeys.find_by journey_pattern_id: existing_associated_journey_pattern.id, checksum: vehicle_journey.checksum
+
+ unless existing_vehicle_journey
+ objectid = Chouette::VehicleJourney.where(objectid: vehicle_journey.objectid).exists? ? nil : vehicle_journey.objectid
+ attributes = vehicle_journey.attributes.merge(
+ id: nil,
+ objectid: objectid,
+
+ # all other primary must be changed
+ route_id: existing_associated_journey_pattern.route_id,
+ journey_pattern_id: existing_associated_journey_pattern.id,
+ )
+ new_vehicle_journey = new.vehicle_journeys.build attributes
+
+ # Create VehicleJourneyAtStops
+
+ vehicle_journey.vehicle_journey_at_stops.each_with_index do |vehicle_journey_at_stop, index|
+ at_stop_attributes = vehicle_journey_at_stop.attributes.merge(
+ id: nil,
+ stop_point_id: existing_associated_journey_pattern.stop_points[index].id
+ )
+ new_vehicle_journey.vehicle_journey_at_stops.build at_stop_attributes
+ end
+
+ new_vehicle_journey.save!
+
+ if new_vehicle_journey.checksum != vehicle_journey.checksum
+ raise "Checksum has changed: #{vehicle_journey.checksum_source} #{new_vehicle_journey.checksum_source}"
+ end
+ end
+
+ end
+ end
+
+ # Time Tables
+
+ referential_time_tables_by_id, referential_time_tables_with_lines = referential.switch do
+ time_tables_by_id = Hash[referential.time_tables.includes(:dates, :periods).all.to_a.map { |t| [t.id, t] }]
+
+ time_tables_with_associated_lines =
+ referential.time_tables.joins(vehicle_journeys: {route: :line}).pluck("lines.id", :id, "vehicle_journeys.checksum")
+
+ # Because TimeTables will be modified according metadata periods
+ # we're loading timetables per line (line is associated to a period list)
+ #
+ # line_id: [ { time_table.id, vehicle_journey.checksum } ]
+ time_tables_by_lines = time_tables_with_associated_lines.inject(Hash.new { |h,k| h[k] = [] }) do |hash, row|
+ hash[row.shift] << {id: row.first, vehicle_journey_checksum: row.second}
+ hash
+ end
+
+ [ time_tables_by_id, time_tables_by_lines ]
+ end
+
+ new.switch do
+ referential_time_tables_with_lines.each do |line_id, time_tables_properties|
+ # Because TimeTables will be modified according metadata periods
+ # we're loading timetables per line (line is associated to a period list)
+ line = workbench.line_referential.lines.find(line_id)
+
+ time_tables_properties.each do |properties|
+ time_table = referential_time_tables_by_id[properties[:id]]
+
+ # we can't test if TimeTable already exist by checksum
+ # because checksum is modified by intersect_periods!
+
+ attributes = time_table.attributes.merge(
+ id: nil,
+ comment: "Ligne #{line.name} - #{time_table.comment}",
+ calendar_id: nil
+ )
+ candidate_time_table = new.time_tables.build attributes
+
+ time_table.dates.each do |date|
+ date_attributes = date.attributes.merge(
+ id: nil,
+ time_table_id: nil
+ )
+ candidate_time_table.dates.build date_attributes
+ end
+ time_table.periods.each do |period|
+ period_attributes = period.attributes.merge(
+ id: nil,
+ time_table_id: nil
+ )
+ candidate_time_table.periods.build period_attributes
+ end
+
+ candidate_time_table.intersect_periods! line_periods.periods(line_id)
+
+ # FIXME
+ candidate_time_table.set_current_checksum_source
+ candidate_time_table.update_checksum
+
+ # after intersect_periods!, the checksum is the expected one
+ # we can search an existing TimeTable
+
+ existing_time_table = line.time_tables.find_by checksum: candidate_time_table.checksum
+
+ unless existing_time_table
+ objectid = Chouette::TimeTable.where(objectid: time_table.objectid).exists? ? nil : time_table.objectid
+ candidate_time_table.objectid = objectid
+
+ candidate_time_table.save!
+
+ # Checksum is changed by #intersect_periods
+ # if new_time_table.checksum != time_table.checksum
+ # raise "Checksum has changed: #{time_table.checksum_source} #{new_time_table.checksum_source}"
+ # end
+
+ existing_time_table = candidate_time_table
+ end
+
+ # associate VehicleJourney
+
+ associated_vehicle_journey = line.vehicle_journeys.find_by!(checksum: properties[:vehicle_journey_checksum])
+ associated_vehicle_journey.time_tables << existing_time_table
+ end
+ end
+ end
+ end
+
+ def save_current
+ output.update current: new, new: nil
+ output.current.update referential_suite: output
+
+ referentials.update_all merged_at: created_at, archived_at: created_at
+ end
+
+ def fixme_functional_scope
+ if attribute = workbench.organisation.sso_attributes.try(:[], "functional_scope")
+ JSON.parse(attribute)
+ end
+ end
+
+ def child_change
+
+ end
+
+ class MetadatasMerger
+
+ attr_reader :merge_metadatas, :referential
+ def initialize(merge_referential, referential)
+ @merge_metadatas = merge_referential.metadatas
+ @referential = referential
+ end
+
+ delegate :metadatas, to: :referential, prefix: :referential
+
+ def merge
+ referential_metadatas.each do |metadata|
+ merge_one metadata
+ end
+ end
+
+ def merged_line_metadatas(line_id)
+ merge_metadatas.select do |m|
+ m.line_ids.include? line_id
+ end
+ end
+
+ def merge_one(metadata)
+ metadata.line_ids.each do |line_id|
+ line_metadatas = merged_line_metadatas(line_id)
+
+ metadata.periodes.each do |period|
+ line_metadatas.each do |m|
+ m.periodes = m.periodes.map do |existing_period|
+ existing_period.remove period
+ end.flatten
+ end
+
+ attributes = {
+ line_ids: [line_id],
+ periodes: [period],
+ referential_source_id: referential.id,
+ created_at: metadata.created_at # TODO check required dates
+ }
+
+ # line_metadatas should not contain conflicted metadatas
+ merge_metadatas << ReferentialMetadata.new(attributes)
+ end
+ end
+ end
+
+ def empty_metadatas
+ merge_metadatas.select { |m| m.periodes.empty? }
+ end
+
+
+ end
+
+end
diff --git a/app/models/organisation.rb b/app/models/organisation.rb
index f6fba2d67..da7d1fcf3 100644
--- a/app/models/organisation.rb
+++ b/app/models/organisation.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
class Organisation < ActiveRecord::Base
include DataFormatEnumerations
@@ -18,36 +19,39 @@ class Organisation < ActiveRecord::Base
validates_presence_of :name
validates_uniqueness_of :code
- def self.portail_api_request
- conf = Rails.application.config.try(:stif_portail_api)
- raise 'Rails.application.config.stif_portail_api configuration is not defined' unless conf
+ class << self
- HTTPService.get_json_resource(
- host: conf[:url],
- path: '/api/v1/organizations',
- token: conf[:key])
- end
+ def portail_api_request
+ conf = Rails.application.config.try(:stif_portail_api)
+ raise 'Rails.application.config.stif_portail_api configuration is not defined' unless conf
+
+ HTTPService.get_json_resource(
+ host: conf[:url],
+ path: '/api/v1/organizations',
+ token: conf[:key])
+ end
- def self.sync_update code, name, scope
- org = Organisation.find_or_initialize_by(code: code)
- if scope
- org.sso_attributes ||= {}
- if org.sso_attributes['functional_scope'] != scope
- org.sso_attributes['functional_scope'] = scope
- # FIXME see #1941
- org.sso_attributes_will_change!
+ def sync_update code, name, scope
+ org = Organisation.find_or_initialize_by(code: code)
+ if scope
+ org.sso_attributes ||= {}
+ if org.sso_attributes['functional_scope'] != scope
+ org.sso_attributes['functional_scope'] = scope
+ # FIXME see #1941
+ org.sso_attributes_will_change!
+ end
end
+ org.name = name
+ org.synced_at = Time.now
+ org.save
+ org
end
- org.name = name
- org.synced_at = Time.now
- org.save
- org
- end
- def self.portail_sync
- self.portail_api_request.each do |el|
- org = self.sync_update el['code'], el['name'], el['functional_scope']
- puts "✓ Organisation #{org.name} has been updated" unless Rails.env.test?
+ def portail_sync
+ portail_api_request.each do |el|
+ org = self.sync_update el['code'], el['name'], el['functional_scope']
+ puts "✓ Organisation #{org.name} has been updated" unless Rails.env.test?
+ end
end
end
@@ -64,4 +68,16 @@ class Organisation < ActiveRecord::Base
raise ActiveRecord::RecordNotFound
end
+ def functional_scope
+ JSON.parse( (sso_attributes || {}).fetch('functional_scope', '[]') )
+ end
+
+ def lines_set
+ STIF::CodifligneLineId.lines_set_from_functional_scope( functional_scope )
+ end
+
+ def has_feature?(feature)
+ features && features.include?(feature.to_s)
+ end
+
end
diff --git a/app/models/public_version.rb b/app/models/public_version.rb
new file mode 100644
index 000000000..4dbf6ce27
--- /dev/null
+++ b/app/models/public_version.rb
@@ -0,0 +1,4 @@
+class PublicVersion < PaperTrail::Version
+ # custom behaviour, e.g:
+ self.table_name = :'public.versions'
+end
diff --git a/app/models/referential.rb b/app/models/referential.rb
index 851a33653..509e0412f 100644
--- a/app/models/referential.rb
+++ b/app/models/referential.rb
@@ -13,17 +13,17 @@ class Referential < ActiveRecord::Base
validates_uniqueness_of :slug
- 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}
- validates_format_of :lower_corner, :with => %r{\A-?[0-9]+\.?[0-9]*\,-?[0-9]+\.?[0-9]*\Z}
+ 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}
+ validates_format_of :lower_corner, with: %r{\A-?[0-9]+\.?[0-9]*\,-?[0-9]+\.?[0-9]*\Z}
validate :slug_excluded_values
attr_accessor :upper_corner
attr_accessor :lower_corner
has_one :user
- has_many :api_keys, :class_name => 'Api::V1::ApiKey', :dependent => :destroy
+ has_many :api_keys, class_name: 'Api::V1::ApiKey', dependent: :destroy
belongs_to :organisation
validates_presence_of :organisation
@@ -61,6 +61,60 @@ class Referential < ActiveRecord::Base
scope :include_metadatas_lines, ->(line_ids) { where('referential_metadata.line_ids && ARRAY[?]::bigint[]', line_ids) }
scope :order_by_validity_period, ->(dir) { joins(:metadatas).order("unnest(periodes) #{dir}") }
scope :order_by_lines, ->(dir) { joins(:metadatas).group("referentials.id").order("sum(array_length(referential_metadata.line_ids,1)) #{dir}") }
+ scope :not_in_referential_suite, -> { where referential_suite_id: nil }
+ scope :blocked, -> { where('ready = ? AND created_at < ?', false, 4.hours.ago) }
+
+ def save_with_table_lock_timeout(options = {})
+ save_without_table_lock_timeout(options)
+ rescue ActiveRecord::StatementInvalid => e
+ if e.message.include?('PG::LockNotAvailable')
+ raise TableLockTimeoutError.new(e)
+ else
+ raise
+ end
+ end
+
+ alias_method_chain :save, :table_lock_timeout
+
+ if Rails.env.development?
+ def self.force_register_models_with_checksum
+ paths = Rails.application.paths['app/models'].to_a
+ Rails.application.railties.each do |tie|
+ next unless tie.respond_to? :paths
+ paths += tie.paths['app/models'].to_a
+ end
+
+ paths.each do |path|
+ next unless File.directory?(path)
+ Dir.chdir path do
+ Dir['**/*.rb'].each do |src|
+ next if src =~ /^concerns/
+ # thanks for inconsistent naming ...
+ if src == "route_control/zdl_stop_area.rb"
+ RouteControl::ZDLStopArea
+ next
+ end
+ Rails.logger.info "Loading #{src}"
+ begin
+ src[0..-4].classify.safe_constantize
+ rescue => e
+ Rails.logger.info "Failed: #{e.message}"
+ nil
+ end
+ end
+ end
+ end
+ end
+ end
+
+ def self.register_model_with_checksum klass
+ @_models_with_checksum ||= []
+ @_models_with_checksum << klass
+ end
+
+ def self.models_with_checksum
+ @_models_with_checksum || []
+ end
def lines
if metadatas.blank?
@@ -79,7 +133,7 @@ class Referential < ActiveRecord::Base
errors.add(:slug,I18n.t("referentials.errors.public_excluded"))
end
if slug == self.class.connection_config[:username]
- errors.add(:slug,I18n.t("referentials.errors.user_excluded", :user => slug))
+ errors.add(:slug,I18n.t("referentials.errors.user_excluded", user: slug))
end
end
end
@@ -92,8 +146,12 @@ class Referential < ActiveRecord::Base
self.class.human_attribute_name(*args)
end
- def stop_areas
- Chouette::StopArea.all
+ def full_name
+ if in_referential_suite?
+ name
+ else
+ "#{self.class.model_name.human.capitalize} #{name}"
+ end
end
def access_points
@@ -128,6 +186,26 @@ class Referential < ActiveRecord::Base
Chouette::RoutingConstraintZone.all
end
+ def purchase_windows
+ Chouette::PurchaseWindow.all
+ end
+
+ def routes
+ Chouette::Route.all
+ end
+
+ def journey_patterns
+ Chouette::JourneyPattern.all
+ end
+
+ def stop_points
+ Chouette::StopPoint.all
+ end
+
+ def compliance_check_sets
+ ComplianceCheckSet.all
+ end
+
before_validation :define_default_attributes
def define_default_attributes
@@ -135,14 +213,26 @@ class Referential < ActiveRecord::Base
self.objectid_format ||= workbench.objectid_format if workbench
end
- def switch
+ def switch(&block)
raise "Referential not created" if new_record?
- Apartment::Tenant.switch!(slug)
- self
+
+ unless block_given?
+ Rails.logger.debug "Referential switch to #{slug}"
+ Apartment::Tenant.switch! slug
+ self
+ else
+ result = nil
+ Apartment::Tenant.switch slug do
+ Rails.logger.debug "Referential switch to #{slug}"
+ result = yield
+ end
+ Rails.logger.debug "Referential back"
+ result
+ end
end
def self.new_from(from, functional_scope)
- Referential.new(
+ Referential.new(
name: I18n.t("activerecord.copy", name: from.name),
slug: "#{from.slug}_clone",
prefix: from.prefix,
@@ -192,15 +282,29 @@ class Referential < ActiveRecord::Base
projection_type || ""
end
- 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_validation :assign_line_and_stop_area_referential, on: :create, if: :workbench
+ before_validation :assign_slug, on: :create
+ before_validation :assign_prefix, on: :create
+
+ # Lock the `referentials` table to prevent duplicate referentials from being
+ # created simultaneously in separate transactions. This must be the last hook
+ # to minimise the duration of the lock.
+ before_save :lock_table, on: [:create, :update]
+
before_create :create_schema
after_create :clone_schema, if: :created_from
before_destroy :destroy_schema
before_destroy :destroy_jobs
+ def referential_read_only?
+ in_referential_suite? || archived?
+ end
+
+ def in_referential_suite?
+ referential_suite_id.present?
+ end
+
def in_workbench?
workbench_id.present?
end
@@ -264,7 +368,7 @@ class Referential < ActiveRecord::Base
query = "select distinct(public.referential_metadata.referential_id) FROM public.referential_metadata, unnest(line_ids) line, LATERAL unnest(periodes) period
WHERE public.referential_metadata.referential_id
- IN (SELECT public.referentials.id FROM public.referentials WHERE referentials.workbench_id = #{workbench_id} and referentials.archived_at is null #{not_myself})
+ IN (SELECT public.referentials.id FROM public.referentials WHERE referentials.workbench_id = #{workbench_id} and referentials.archived_at is null and referentials.referential_suite_id is null #{not_myself})
AND line in (#{line_ids.join(',')}) and (#{periods_query});"
self.class.connection.select_values(query).map(&:to_i)
@@ -274,22 +378,45 @@ class Referential < ActiveRecord::Base
overlapped_referential_ids.present?
end
- validate :detect_overlapped_referentials
+ validate :detect_overlapped_referentials, unless: :in_referential_suite?
def detect_overlapped_referentials
self.class.where(id: overlapped_referential_ids).each do |referential|
+ Rails.logger.info "Referential #{referential.id} #{referential.metadatas.inspect} overlaps #{metadatas.inspect}"
errors.add :metadatas, I18n.t("referentials.errors.overlapped_referential", :referential => referential.name)
end
end
+
+ attr_accessor :inline_clone
def clone_schema
- ReferentialCloning.create(source_referential: created_from, target_referential: self)
+ cloning = ReferentialCloning.new source_referential: created_from, target_referential: self
+
+ if inline_clone
+ cloning.clone!
+ else
+ cloning.save!
+ end
end
def create_schema
unless created_from
- Apartment::Tenant.create slug
- Rails.logger.error( "Schema migrations count for Referential #{slug} " + Referential.connection.select_value("select count(*) from #{slug}.schema_migrations;").to_s )
+ report = Benchmark.measure do
+ Apartment::Tenant.create slug
+ end
+
+ check_migration_count(report)
+ end
+ end
+
+ def check_migration_count(report)
+ Rails.logger.info("Schema create benchmark: '#{slug}'\t#{report}")
+ Rails.logger.info("Schema migrations count for Referential #{slug}: #{migration_count || '-'}")
+ end
+
+ def migration_count
+ if self.class.connection.table_exists?("#{slug}.schema_migrations")
+ self.class.connection.select_value("select count(*) from #{slug}.schema_migrations;")
end
end
@@ -373,4 +500,25 @@ class Referential < ActiveRecord::Base
not metadatas_overlap?
end
+ def merged?
+ merged_at.present?
+ end
+
+ def self.not_merged
+ where merged_at: nil
+ end
+
+ def self.mergeable
+ ready.not_merged.not_in_referential_suite
+ end
+
+ private
+
+ def lock_table
+ # No explicit unlock is needed as it will be released at the end of the
+ # transaction.
+ ActiveRecord::Base.connection.execute(
+ 'LOCK public.referentials IN ACCESS EXCLUSIVE MODE'
+ )
+ end
end
diff --git a/app/models/referential_cloning.rb b/app/models/referential_cloning.rb
index 5bf283814..d4b74bd52 100644
--- a/app/models/referential_cloning.rb
+++ b/app/models/referential_cloning.rb
@@ -2,14 +2,33 @@ class ReferentialCloning < ActiveRecord::Base
include AASM
belongs_to :source_referential, class_name: 'Referential'
belongs_to :target_referential, class_name: 'Referential'
- after_commit :perform_clone, :on => :create
+ after_commit :clone, on: :create
- private
- def perform_clone
+ def clone
ReferentialCloningWorker.perform_async(id)
- # ReferentialCloningWorker.new.perform(id)
end
+ def clone_with_status!
+ run!
+ clone!
+ successful!
+ rescue Exception => e
+ Rails.logger.error "Clone failed : #{e}"
+ Rails.logger.error e.backtrace.join('\n')
+ failed!
+ end
+
+ def clone!
+ report = Benchmark.measure do
+ AF83::SchemaCloner
+ .new(source_referential.slug, target_referential.slug)
+ .clone_schema
+ end
+ target_referential.check_migration_count(report)
+ end
+
+ private
+
aasm column: :status do
state :new, :initial => true
state :pending
diff --git a/app/models/referential_suite.rb b/app/models/referential_suite.rb
index 93c2c3f36..4f825628c 100644
--- a/app/models/referential_suite.rb
+++ b/app/models/referential_suite.rb
@@ -1,7 +1,7 @@
class ReferentialSuite < ActiveRecord::Base
belongs_to :new, class_name: 'Referential'
validate def validate_consistent_new
- return true if new_id.nil?
+ return true if new_id.nil? || new.nil?
return true if new.referential_suite_id == id
errors.add(:inconsistent_new,
I18n.t('referential_suites.errors.inconsistent_new', name: new.name))
@@ -9,11 +9,11 @@ class ReferentialSuite < ActiveRecord::Base
belongs_to :current, class_name: 'Referential'
validate def validate_consistent_current
- return true if current_id.nil?
+ return true if current_id.nil? || current.nil?
return true if current.referential_suite_id == id
errors.add(:inconsistent_current,
I18n.t('referential_suites.errors.inconsistent_current', name: current.name))
end
- has_many :referentials
+ has_many :referentials, -> { order "created_at desc" }
end
diff --git a/app/models/route_control/opposite_route.rb b/app/models/route_control/opposite_route.rb
index d5616ca6f..e0e9572ce 100644
--- a/app/models/route_control/opposite_route.rb
+++ b/app/models/route_control/opposite_route.rb
@@ -4,6 +4,6 @@ module RouteControl
def self.default_code; "3-Route-2" end
- def self.prerequisite; I18n.t("compliance_controls.#{self.name.underscore}.prerequisite") end
+ def prerequisite; I18n.t("compliance_controls.#{self.class.name.underscore}.prerequisite") end
end
end
diff --git a/app/models/route_control/opposite_route_terminus.rb b/app/models/route_control/opposite_route_terminus.rb
index 24c557734..e70d2c702 100644
--- a/app/models/route_control/opposite_route_terminus.rb
+++ b/app/models/route_control/opposite_route_terminus.rb
@@ -3,6 +3,6 @@ module RouteControl
def self.default_code; "3-Route-5" end
- def self.prerequisite; I18n.t("compliance_controls.#{self.name.underscore}.prerequisite") end
+ def prerequisite; I18n.t("compliance_controls.#{self.class.name.underscore}.prerequisite") end
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 37d35209a..1342f60ed 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -36,7 +36,7 @@ class User < ActiveRecord::Base
self.name = extra[:full_name]
self.email = extra[:email]
self.organisation = Organisation.sync_update extra[:organisation_code], extra[:organisation_name], extra[:functional_scope]
- self.permissions = Stif::PermissionTranslator.translate(extra[:permissions])
+ self.permissions = Stif::PermissionTranslator.translate(extra[:permissions], self.organisation)
end
def self.portail_api_request
diff --git a/app/models/vehicle_journey_control/delta.rb b/app/models/vehicle_journey_control/delta.rb
index 1f3a4d492..737b7d78c 100644
--- a/app/models/vehicle_journey_control/delta.rb
+++ b/app/models/vehicle_journey_control/delta.rb
@@ -1,9 +1,10 @@
module VehicleJourneyControl
class Delta < ComplianceControl
- hstore_accessor :control_attributes, maximum: :integer
+ store_accessor :control_attributes, :maximum
- validates :maximum, numericality: true, allow_nil: true
+ validates_numericality_of :maximum, allow_nil: true, greater_than_or_equal_to: 0
+ validates_presence_of :maximum
def self.default_code; "3-VehicleJourney-3" end
end
diff --git a/app/models/vehicle_journey_control/speed.rb b/app/models/vehicle_journey_control/speed.rb
index be9f838e4..e5e331b50 100644
--- a/app/models/vehicle_journey_control/speed.rb
+++ b/app/models/vehicle_journey_control/speed.rb
@@ -1,9 +1,9 @@
module VehicleJourneyControl
class Speed < ComplianceControl
- hstore_accessor :control_attributes, minimum: :integer, maximum: :integer
+ store_accessor :control_attributes, :minimum, :maximum
- validates :minimum, numericality: true, allow_nil: true
- validates :maximum, numericality: true, allow_nil: true
+ validates_numericality_of :minimum, allow_nil: true, greater_than_or_equal_to: 0
+ validates_numericality_of :maximum, allow_nil: true, greater_than_or_equal_to: 0
include MinMaxValuesValidation
def self.default_code; "3-VehicleJourney-2" end
diff --git a/app/models/vehicle_journey_control/waiting_time.rb b/app/models/vehicle_journey_control/waiting_time.rb
index 68fccb5c1..89a18a5d9 100644
--- a/app/models/vehicle_journey_control/waiting_time.rb
+++ b/app/models/vehicle_journey_control/waiting_time.rb
@@ -1,8 +1,9 @@
module VehicleJourneyControl
class WaitingTime < ComplianceControl
- hstore_accessor :control_attributes, maximum: :integer
+ store_accessor :control_attributes, :maximum
- validates :maximum, numericality: true, allow_nil: true
+ validates_numericality_of :maximum, allow_nil: true, greater_than_or_equal_to: 0
+ validates_presence_of :maximum
def self.default_code; "3-VehicleJourney-1" end
end
diff --git a/app/models/workbench.rb b/app/models/workbench.rb
index e36589210..b80fa64ac 100644
--- a/app/models/workbench.rb
+++ b/app/models/workbench.rb
@@ -4,6 +4,7 @@ class Workbench < ActiveRecord::Base
belongs_to :line_referential
belongs_to :stop_area_referential
belongs_to :output, class_name: 'ReferentialSuite'
+ belongs_to :workgroup
has_many :lines, -> (workbench) { Stif::MyWorkbenchScopes.new(workbench).line_scope(self) }, through: :line_referential
has_many :networks, through: :line_referential
@@ -14,6 +15,7 @@ class Workbench < ActiveRecord::Base
has_many :workbench_imports
has_many :compliance_check_sets
has_many :compliance_control_sets
+ has_many :merges
validates :name, presence: true
validates :organisation, presence: true
@@ -29,7 +31,12 @@ class Workbench < ActiveRecord::Base
if line_ids.empty?
Referential.none
else
- Referential.joins(:metadatas).where(['referential_metadata.line_ids && ARRAY[?]::bigint[]', line_ids]).ready
+ workgroup
+ .referentials
+ .joins(:metadatas)
+ .where(['referential_metadata.line_ids && ARRAY[?]::bigint[]', line_ids])
+ .ready
+ .not_in_referential_suite
end
end
diff --git a/app/models/workgroup.rb b/app/models/workgroup.rb
new file mode 100644
index 000000000..3af20ae23
--- /dev/null
+++ b/app/models/workgroup.rb
@@ -0,0 +1,20 @@
+class Workgroup < ActiveRecord::Base
+ belongs_to :line_referential
+ belongs_to :stop_area_referential
+
+ has_many :workbenches
+ has_many :calendars
+ has_many :organisations, through: :workbenches
+ has_many :referentials, through: :workbenches
+
+ validates_uniqueness_of :name
+
+ validates_presence_of :line_referential_id
+ validates_presence_of :stop_area_referential_id
+
+ has_many :custom_fields
+
+ def custom_fields_definitions
+ Hash[*custom_fields.map{|cf| [cf.code, cf]}.flatten]
+ end
+end
diff --git a/app/policies/access_link_policy.rb b/app/policies/access_link_policy.rb
index 1f1147f60..f2ea7027f 100644
--- a/app/policies/access_link_policy.rb
+++ b/app/policies/access_link_policy.rb
@@ -6,14 +6,14 @@ class AccessLinkPolicy < ApplicationPolicy
end
def create?
- !archived? && organisation_match? && user.has_permission?('access_links.create')
+ !referential_read_only? && organisation_match? && user.has_permission?('access_links.create')
end
def update?
- !archived? && organisation_match? && user.has_permission?('access_links.update')
+ !referential_read_only? && organisation_match? && user.has_permission?('access_links.update')
end
def destroy?
- !archived? && organisation_match? && user.has_permission?('access_links.destroy')
+ !referential_read_only? && organisation_match? && user.has_permission?('access_links.destroy')
end
end
diff --git a/app/policies/access_point_policy.rb b/app/policies/access_point_policy.rb
index 41436e77c..4fa887b9e 100644
--- a/app/policies/access_point_policy.rb
+++ b/app/policies/access_point_policy.rb
@@ -6,14 +6,14 @@ class AccessPointPolicy < ApplicationPolicy
end
def create?
- !archived? && organisation_match? && user.has_permission?('access_points.create')
+ !referential_read_only? && organisation_match? && user.has_permission?('access_points.create')
end
def update?
- !archived? && organisation_match? && user.has_permission?('access_points.update')
+ !referential_read_only? && organisation_match? && user.has_permission?('access_points.update')
end
def destroy?
- !archived? && organisation_match? && user.has_permission?('access_points.destroy')
+ !referential_read_only? && organisation_match? && user.has_permission?('access_points.destroy')
end
end
diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb
index dbe4542e7..c44937c9e 100644
--- a/app/policies/application_policy.rb
+++ b/app/policies/application_policy.rb
@@ -81,6 +81,11 @@ class ApplicationPolicy
@is_archived = is_archived
end
+ def referential_read_only?
+ return @is_referential_read_only if instance_variable_defined?(:@is_referential_read_only)
+ @is_referential_read_only = is_referential_read_only
+ end
+
def organisation_match?
user.organisation_id == organisation_id
end
@@ -124,4 +129,13 @@ class ApplicationPolicy
current_referential.try(:archived_at)
end
end
+
+ def is_referential_read_only
+ !!case referential
+ when Referential
+ referential.referential_read_only?
+ else
+ current_referential.try(:referential_read_only?)
+ end
+ end
end
diff --git a/app/policies/calendar_policy.rb b/app/policies/calendar_policy.rb
index 074c41d8d..c2da8c924 100644
--- a/app/policies/calendar_policy.rb
+++ b/app/policies/calendar_policy.rb
@@ -5,18 +5,15 @@ class CalendarPolicy < ApplicationPolicy
end
end
- def create?
- !archived? && user.has_permission?('calendars.create')
- end
- def destroy?
- !archived? & organisation_match? && user.has_permission?('calendars.destroy')
- end
- def update?
- !archived? && organisation_match? && user.has_permission?('calendars.update')
+ def create?
+ user.has_permission?('calendars.create')
end
+ def destroy?; instance_permission("destroy") end
+ def update?; instance_permission("update") end
+ def share?; instance_permission("share") end
- def share?
- user.organisation.name == 'STIF' # FIXME
+ private
+ def instance_permission permission
+ organisation_match? && user.has_permission?("calendars.#{permission}")
end
-
end
diff --git a/app/policies/connection_link_policy.rb b/app/policies/connection_link_policy.rb
index 240c2a804..9bab5e4db 100644
--- a/app/policies/connection_link_policy.rb
+++ b/app/policies/connection_link_policy.rb
@@ -6,14 +6,14 @@ class ConnectionLinkPolicy < ApplicationPolicy
end
def create?
- !archived? && organisation_match? && user.has_permission?('connection_links.create')
+ !referential_read_only? && organisation_match? && user.has_permission?('connection_links.create')
end
def destroy?
- !archived? && organisation_match? && user.has_permission?('connection_links.destroy')
+ !referential_read_only? && organisation_match? && user.has_permission?('connection_links.destroy')
end
def update?
- !archived? && organisation_match? && user.has_permission?('connection_links.update')
+ !referential_read_only? && organisation_match? && user.has_permission?('connection_links.update')
end
end
diff --git a/app/policies/journey_pattern_policy.rb b/app/policies/journey_pattern_policy.rb
index 12bcced17..beb18d151 100644
--- a/app/policies/journey_pattern_policy.rb
+++ b/app/policies/journey_pattern_policy.rb
@@ -7,14 +7,14 @@ class JourneyPatternPolicy < ApplicationPolicy
end
def create?
- !archived? && organisation_match? && user.has_permission?('journey_patterns.create')
+ !referential_read_only? && organisation_match? && user.has_permission?('journey_patterns.create')
end
def destroy?
- !archived? && organisation_match? && user.has_permission?('journey_patterns.destroy')
+ !referential_read_only? && organisation_match? && user.has_permission?('journey_patterns.destroy')
end
def update?
- !archived? && organisation_match? && user.has_permission?('journey_patterns.update')
+ !referential_read_only? && organisation_match? && user.has_permission?('journey_patterns.update')
end
end
diff --git a/app/policies/line_policy.rb b/app/policies/line_policy.rb
index 67ea0b611..f7b03b0b5 100644
--- a/app/policies/line_policy.rb
+++ b/app/policies/line_policy.rb
@@ -6,7 +6,6 @@ class LinePolicy < ApplicationPolicy
end
def create?
- Rails.logger.debug "LinePolicy.create?"
user.has_permission?('lines.create')
end
@@ -14,20 +13,28 @@ class LinePolicy < ApplicationPolicy
user.has_permission?('lines.destroy')
end
+ def deactivate?
+ !record.deactivated? && user.has_permission?('lines.change_status')
+ end
+
+ def activate?
+ record.deactivated? && user.has_permission?('lines.change_status')
+ end
+
def update?
user.has_permission?('lines.update')
end
def create_footnote?
- !archived? && organisation_match? && user.has_permission?('footnotes.create')
+ !referential_read_only? && organisation_match? && user.has_permission?('footnotes.create')
end
def edit_footnote?
- !archived? && organisation_match? && user.has_permission?('footnotes.update')
+ !referential_read_only? && organisation_match? && user.has_permission?('footnotes.update')
end
def destroy_footnote?
- !archived? && organisation_match? && user.has_permission?('footnotes.destroy')
+ !referential_read_only? && organisation_match? && user.has_permission?('footnotes.destroy')
end
def update_footnote? ; edit_footnote? end
diff --git a/app/policies/line_referential_policy.rb b/app/policies/line_referential_policy.rb
new file mode 100644
index 000000000..ee742a083
--- /dev/null
+++ b/app/policies/line_referential_policy.rb
@@ -0,0 +1,14 @@
+class LineReferentialPolicy < ApplicationPolicy
+ class Scope < Scope
+ def resolve
+ scope
+ end
+ end
+
+ def synchronize?; instance_permission("synchronize") end
+
+ private
+ def instance_permission permission
+ user.has_permission?("line_referentials.#{permission}")
+ end
+end
diff --git a/app/policies/merge_policy.rb b/app/policies/merge_policy.rb
new file mode 100644
index 000000000..82eb72e08
--- /dev/null
+++ b/app/policies/merge_policy.rb
@@ -0,0 +1,15 @@
+class MergePolicy < ApplicationPolicy
+ class Scope < Scope
+ def resolve
+ scope
+ end
+ end
+
+ def create?
+ user.has_permission?('merges.create')
+ end
+
+ def update?
+ user.has_permission?('merges.update')
+ end
+end
diff --git a/app/policies/network_policy.rb b/app/policies/network_policy.rb
index 9f86451a5..9b871d2b5 100644
--- a/app/policies/network_policy.rb
+++ b/app/policies/network_policy.rb
@@ -4,4 +4,15 @@ class NetworkPolicy < ApplicationPolicy
scope
end
end
+ def create?
+ user.has_permission?('networks.create')
+ end
+
+ def destroy?
+ user.has_permission?('networks.destroy')
+ end
+
+ def update?
+ user.has_permission?('networks.update')
+ end
end
diff --git a/app/policies/purchase_window_policy.rb b/app/policies/purchase_window_policy.rb
new file mode 100644
index 000000000..eb3b04bf7
--- /dev/null
+++ b/app/policies/purchase_window_policy.rb
@@ -0,0 +1,20 @@
+class PurchaseWindowPolicy < ApplicationPolicy
+ class Scope < Scope
+ def resolve
+ scope
+ end
+ end
+
+ def create?
+ !referential_read_only? && organisation_match? && user.has_permission?('purchase_windows.create')
+ end
+
+ def update?
+ !referential_read_only? && organisation_match? && user.has_permission?('purchase_windows.update')
+ end
+
+ def destroy?
+ !referential_read_only? && organisation_match? && user.has_permission?('purchase_windows.destroy')
+ end
+
+end
diff --git a/app/policies/referential_policy.rb b/app/policies/referential_policy.rb
index 253917509..f5c2d7c08 100644
--- a/app/policies/referential_policy.rb
+++ b/app/policies/referential_policy.rb
@@ -10,27 +10,27 @@ class ReferentialPolicy < ApplicationPolicy
end
def destroy?
- !archived? && organisation_match? && user.has_permission?('referentials.destroy')
+ !referential_read_only? && organisation_match? && user.has_permission?('referentials.destroy')
end
def update?
- !archived? && organisation_match? && user.has_permission?('referentials.update')
+ !referential_read_only? && organisation_match? && user.has_permission?('referentials.update')
end
def clone?
- !archived? && create?
+ !record.in_referential_suite? && create?
end
def validate?
- !archived? && create? && organisation_match?
+ !referential_read_only? && create? && organisation_match?
end
def archive?
- record.archived_at.nil? && organisation_match? && user.has_permission?('referentials.update')
+ !referential_read_only? && record.archived_at.nil? && organisation_match? && user.has_permission?('referentials.update')
end
def unarchive?
- !record.archived_at.nil? && organisation_match? && user.has_permission?('referentials.update')
+ record.archived? && !record.merged? && organisation_match? && user.has_permission?('referentials.update')
end
def common_lines?
diff --git a/app/policies/route_policy.rb b/app/policies/route_policy.rb
index 7e9fe251a..0337a5300 100644
--- a/app/policies/route_policy.rb
+++ b/app/policies/route_policy.rb
@@ -6,15 +6,15 @@ class RoutePolicy < ApplicationPolicy
end
def create?
- !archived? && organisation_match? && user.has_permission?('routes.create')
+ !referential_read_only? && organisation_match? && user.has_permission?('routes.create')
end
def destroy?
- !archived? && organisation_match? && user.has_permission?('routes.destroy')
+ !referential_read_only? && organisation_match? && user.has_permission?('routes.destroy')
end
def update?
- !archived? && organisation_match? && user.has_permission?('routes.update')
+ !referential_read_only? && organisation_match? && user.has_permission?('routes.update')
end
def duplicate?
diff --git a/app/policies/routing_constraint_zone_policy.rb b/app/policies/routing_constraint_zone_policy.rb
index 3cfcf46ff..fd8081bef 100644
--- a/app/policies/routing_constraint_zone_policy.rb
+++ b/app/policies/routing_constraint_zone_policy.rb
@@ -6,14 +6,14 @@ class RoutingConstraintZonePolicy < ApplicationPolicy
end
def create?
- !archived? && organisation_match? && user.has_permission?('routing_constraint_zones.create')
+ !referential_read_only? && organisation_match? && user.has_permission?('routing_constraint_zones.create')
end
def destroy?
- !archived? && organisation_match? && user.has_permission?('routing_constraint_zones.destroy')
+ !referential_read_only? && organisation_match? && user.has_permission?('routing_constraint_zones.destroy')
end
def update?
- !archived? && organisation_match? && user.has_permission?('routing_constraint_zones.update')
+ !referential_read_only? && organisation_match? && user.has_permission?('routing_constraint_zones.update')
end
end
diff --git a/app/policies/stop_area_policy.rb b/app/policies/stop_area_policy.rb
index faeebbc2a..fd73b7092 100644
--- a/app/policies/stop_area_policy.rb
+++ b/app/policies/stop_area_policy.rb
@@ -1,5 +1,13 @@
class StopAreaPolicy < ApplicationPolicy
class Scope < Scope
+ def search_scope scope_name
+ scope = resolve
+ if scope_name&.to_s == "route_editor"
+ scope = scope.where("kind = ? OR area_type = ?", :non_commercial, 'zdep') unless user.organisation.has_feature?("route_stop_areas_all_types")
+ end
+ scope
+ end
+
def resolve
scope
end
@@ -16,4 +24,12 @@ class StopAreaPolicy < ApplicationPolicy
def update?
user.has_permission?('stop_areas.update')
end
+
+ def deactivate?
+ !record.deactivated? && user.has_permission?('stop_areas.change_status')
+ end
+
+ def activate?
+ record.deactivated? && user.has_permission?('stop_areas.change_status')
+ end
end
diff --git a/app/policies/stop_area_referential_policy.rb b/app/policies/stop_area_referential_policy.rb
new file mode 100644
index 000000000..e370babf8
--- /dev/null
+++ b/app/policies/stop_area_referential_policy.rb
@@ -0,0 +1,14 @@
+class StopAreaReferentialPolicy < ApplicationPolicy
+ class Scope < Scope
+ def resolve
+ scope
+ end
+ end
+
+ def synchronize?; instance_permission("synchronize") end
+
+ private
+ def instance_permission permission
+ user.has_permission?("stop_area_referentials.#{permission}")
+ end
+end
diff --git a/app/policies/time_table_combination_policy.rb b/app/policies/time_table_combination_policy.rb
index daa6808e4..bba458c18 100644
--- a/app/policies/time_table_combination_policy.rb
+++ b/app/policies/time_table_combination_policy.rb
@@ -7,6 +7,6 @@ class TimeTableCombinationPolicy < ApplicationPolicy
end
def create?
- !archived? && organisation_match? && user.has_permission?('time_tables.update')
+ !referential_read_only? && organisation_match? && user.has_permission?('time_tables.update')
end
end
diff --git a/app/policies/time_table_policy.rb b/app/policies/time_table_policy.rb
index 92d3aef3e..390c170c7 100644
--- a/app/policies/time_table_policy.rb
+++ b/app/policies/time_table_policy.rb
@@ -7,23 +7,23 @@ class TimeTablePolicy < ApplicationPolicy
end
def create?
- !archived? && organisation_match? && user.has_permission?('time_tables.create')
+ !referential_read_only? && organisation_match? && user.has_permission?('time_tables.create')
end
def destroy?
- !archived? && organisation_match? && user.has_permission?('time_tables.destroy')
+ !referential_read_only? && organisation_match? && user.has_permission?('time_tables.destroy')
end
def update?
- !archived? && organisation_match? && user.has_permission?('time_tables.update')
+ !referential_read_only? && organisation_match? && user.has_permission?('time_tables.update')
end
def actualize?
- !archived? && organisation_match? && edit?
+ !referential_read_only? && organisation_match? && edit?
end
def duplicate?
- !archived? && organisation_match? && create?
+ !referential_read_only? && organisation_match? && create?
end
def month?
diff --git a/app/policies/vehicle_journey_policy.rb b/app/policies/vehicle_journey_policy.rb
index 24040455f..adbc5fd89 100644
--- a/app/policies/vehicle_journey_policy.rb
+++ b/app/policies/vehicle_journey_policy.rb
@@ -6,14 +6,14 @@ class VehicleJourneyPolicy < ApplicationPolicy
end
def create?
- !archived? && organisation_match? && user.has_permission?('vehicle_journeys.create')
+ !referential_read_only? && organisation_match? && user.has_permission?('vehicle_journeys.create')
end
def destroy?
- !archived? && organisation_match? && user.has_permission?('vehicle_journeys.destroy')
+ !referential_read_only? && organisation_match? && user.has_permission?('vehicle_journeys.destroy')
end
def update?
- !archived? && organisation_match? && user.has_permission?('vehicle_journeys.update')
+ !referential_read_only? && organisation_match? && user.has_permission?('vehicle_journeys.update')
end
end
diff --git a/app/services/parent_import_notifier.rb b/app/services/parent_import_notifier.rb
deleted file mode 100644
index 47e6755e4..000000000
--- a/app/services/parent_import_notifier.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-class ParentImportNotifier
- def self.notify_when_finished(imports = nil)
- imports ||= imports_pending_notification
- imports.each(&:notify_parent)
- end
-
- def self.imports_pending_notification
- Import
- .where(
- notified_parent_at: nil,
- status: Import.finished_statuses
- )
- .where.not(parent: nil)
- end
-end
diff --git a/app/services/parent_notifier.rb b/app/services/parent_notifier.rb
new file mode 100644
index 000000000..653c98aff
--- /dev/null
+++ b/app/services/parent_notifier.rb
@@ -0,0 +1,19 @@
+class ParentNotifier
+ def initialize(klass)
+ @klass = klass
+ end
+
+ def notify_when_finished(collection = nil)
+ collection ||= objects_pending_notification
+ collection.each(&:notify_parent)
+ end
+
+ def objects_pending_notification
+ @klass
+ .where(
+ notified_parent_at: nil,
+ status: @klass.finished_statuses
+ )
+ .where.not(parent: nil)
+ end
+end
diff --git a/app/services/referential_overview.rb b/app/services/referential_overview.rb
new file mode 100644
index 000000000..ccfe0617a
--- /dev/null
+++ b/app/services/referential_overview.rb
@@ -0,0 +1,256 @@
+class ReferentialOverview
+ attr_reader :h
+ attr_reader :referential
+
+ PER_PAGE = 10
+
+ def initialize referential, h=nil
+ @referential = referential
+ @page = h && h.params[pagination_param_name]&.to_i || 1
+ @h = h
+ end
+
+ def lines
+ filtered_lines.includes(:company).map{|l| Line.new(l, @referential, period.first, h)}
+ end
+
+ def period
+ @period ||= @referential.metadatas_period || []
+ end
+
+ def includes_today?
+ period.include? Time.now.to_date
+ end
+
+ def weeks
+ @weeks = {}
+ period.map do |d|
+ @weeks[Week.key(d)] ||= Week.new(d, period.last, h)
+ end
+ @weeks.values
+ end
+
+ def referential_lines
+ @referential.metadatas_lines
+ end
+
+ def filtered_lines
+ search.result.page(@page).per_page(PER_PAGE)
+ end
+
+ ### Pagination
+
+ delegate :empty?, :first, :total_pages, :size, :total_entries, :offset, :length, to: :filtered_lines
+ def current_page
+ @page
+ end
+
+ ### search
+ def search
+ lines = referential_lines
+ lines = lines.search h.params[search_param_name]
+ lines
+ end
+
+ def pagination_param_name
+ "referential_#{@referential.slug}_overview"
+ end
+
+ def search_param_name
+ "q_#{pagination_param_name}"
+ end
+
+ class Line
+ attr_reader :h
+ attr_reader :referential_line
+
+ delegate :name, :number, :company, :color, :transport_mode, to: :referential_line
+
+ def initialize line, referential, start, h
+ @referential_line = line
+ @referential = referential
+ @start = start
+ @h = h
+ end
+
+ def period
+ @period ||= @referential.metadatas_period || []
+ end
+
+ def referential_periods
+ @referential_periods ||= @referential.metadatas.include_lines([@referential_line.id]).map(&:periodes).flatten.sort{|p1, p2| p1.first <=> p2.first}
+ end
+
+ def periods
+ @periods ||= begin
+ periods = referential_periods.flatten.map{|p| Period.new p, @start, h}
+ periods = fill_periods periods
+ periods = merge_periods periods
+ periods
+ end
+ end
+
+ def fill_periods periods
+ [].tap do |out|
+ previous = OpenStruct.new(end: period.first - 1.day)
+ (periods + [OpenStruct.new(start: period.last + 1.day)]).each do |p|
+ if p.start > previous.end + 1.day
+ out << Period.new((previous.end+1.day..p.start-1.day), @start, h).tap{|p| p.empty = true}
+ end
+ out << p if p.respond_to?(:end)
+ previous = p
+ end
+ end
+ end
+
+ def merge_periods periods
+ [].tap do |out|
+ current = periods.first
+ periods[1..-1].each do |p|
+ if p.start <= current.end
+ current.end = p.end
+ else
+ out << current
+ current = p
+ end
+ end
+ out << current
+ end
+ end
+
+ def width
+ period.count * Day::WIDTH
+ end
+
+ def html_style
+ {
+ width: "#{width}px"
+ }.map{|k, v| "#{k}: #{v}"}.join("; ")
+ end
+
+ def html_class
+ out = []
+ out
+ end
+
+ class Period
+ attr_accessor :empty
+ attr_accessor :h
+
+ def initialize period, start, h
+ @period = period
+ @start = start
+ @empty = false
+ @h = h
+ end
+
+ def start
+ @period.first
+ end
+
+ def end
+ @period.last
+ end
+
+ def end= val
+ @period = (start..val)
+ end
+
+ def width
+ @period.count * Day::WIDTH
+ end
+
+ def left
+ (@period.first - @start).to_i * Day::WIDTH
+ end
+
+ def html_style
+ {
+ width: "#{width}px",
+ left: "#{left}px",
+ }.map{|k, v| "#{k}: #{v}"}.join("; ")
+ end
+
+ def empty?
+ @empty
+ end
+
+ def accepted?
+ @period.count < 7
+ end
+
+ def title
+ h.l(self.start, format: :short) + " - " + h.l(self.end, format: :short)
+ end
+
+ def html_class
+ out = []
+ out << "empty" if empty?
+ out << "accepted" if accepted?
+ out
+ end
+ end
+ end
+
+ class Week
+ attr_reader :h
+ attr_reader :start_date
+ attr_reader :end_date
+
+ def initialize start_date, boundary, h
+ @start_date = start_date.to_date
+ @end_date = [start_date.end_of_week, boundary].min.to_date
+ @h = h
+ end
+
+ def self.key date
+ date.beginning_of_week.to_s
+ end
+
+ def span
+ h.l(@start_date, format: "#{@start_date.day}-#{@end_date.day} %b")
+ end
+
+ def number
+ h.l(@start_date, format: "%W")
+ end
+
+ def period
+ (@start_date..@end_date)
+ end
+
+ def days
+ period.map {|d| Day.new d, h }
+ end
+ end
+
+ class Day
+ attr_reader :h
+
+ WIDTH=50
+
+ def initialize date, h
+ @date = date
+ @h = h
+ end
+
+ def html_style
+ {width: "#{WIDTH}px"}.map{|k, v| "#{k}: #{v}"}.join("; ")
+ end
+
+ def html_class
+ out = [h.l(@date, format: "%Y-%m-%d")]
+ out << "weekend" if [0, 6].include?(@date.wday)
+ out << "today" if @date == Time.now.to_date
+ out
+ end
+
+ def short_name
+ h.l(@date, format: "%a")
+ end
+
+ def number
+ @date.day
+ end
+ end
+end
diff --git a/app/services/zip_service.rb b/app/services/zip_service.rb
index 7a4bdad1b..7166e6448 100644
--- a/app/services/zip_service.rb
+++ b/app/services/zip_service.rb
@@ -1,12 +1,16 @@
class ZipService
- class Subdir < Struct.new(:name, :stream, :spurious)
+ class Subdir < Struct.new(:name, :stream, :spurious, :foreign_lines)
+ def ok?
+ foreign_lines.empty? && spurious.empty?
+ end
end
- attr_reader :current_key, :current_output, :current_spurious, :yielder
+ attr_reader :allowed_lines, :current_key, :foreign_lines, :current_output, :current_spurious, :yielder
- def initialize data
+ def initialize data, allowed_lines
@zip_data = StringIO.new(data)
+ @allowed_lines = allowed_lines
@current_key = nil
@current_output = nil
end
@@ -35,7 +39,8 @@ class ZipService
end
def add_to_current_output entry
- return if is_spurious! entry.name
+ return if is_spurious!(entry.name) || is_foreign_line!(entry.name)
+
current_output.put_next_entry entry.name
write_to_current_output entry.get_input_stream
end
@@ -52,20 +57,22 @@ class ZipService
current_key,
# Second part of the solution, yield the closed stream
current_output.close_buffer,
- current_spurious)
+ current_spurious.to_a,
+ foreign_lines)
end
end
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)
- @current_spurious = []
+ @current_output = Zip::OutputStream.new(StringIO.new(''), true, nil)
+ @current_spurious = Set.new
+ @foreign_lines = []
end
def entry_key entry
# last dir name File.dirname.split("/").last
- entry.name.split('/', -1)[-2]
+ entry.name.split('/').first
end
def is_spurious! entry_name
@@ -75,4 +82,12 @@ class ZipService
current_spurious << segments.second
return true
end
+
+ def is_foreign_line! entry_name
+ STIF::NetexFile::Frame.get_short_id(entry_name).tap do | line_object_id |
+ return nil unless line_object_id
+ return nil if line_object_id.in? allowed_lines
+ foreign_lines << line_object_id
+ end
+ end
end
diff --git a/app/uploaders/import_uploader.rb b/app/uploaders/import_uploader.rb
index 2740393ca..60e17ca0f 100644
--- a/app/uploaders/import_uploader.rb
+++ b/app/uploaders/import_uploader.rb
@@ -36,9 +36,9 @@ class ImportUploader < CarrierWave::Uploader::Base
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
- # def extension_whitelist
- # %w(jpg jpeg gif png)
- # end
+ def extension_whitelist
+ %w(zip)
+ end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
diff --git a/app/views/api/v1/journey_patterns/show.rabl b/app/views/api/v1/journey_patterns/show.rabl
index 3ea1bb6ff..aac66b6f3 100644
--- a/app/views/api/v1/journey_patterns/show.rabl
+++ b/app/views/api/v1/journey_patterns/show.rabl
@@ -1,20 +1,30 @@
object @journey_pattern
extends "api/v1/trident_objects/show"
-[:id, :name, :published_name, :registration_number, :comment].each do |attr|
+[:id, :name, :published_name, :registration_number, :comment, :checksum].each do |attr|
attributes attr, :unless => lambda { |m| m.send( attr).nil?}
end
+node :full_schedule do |journey_pattern|
+ journey_pattern.full_schedule?
+end
+
+if has_feature? :costs_in_journey_patterns
+ attribute :costs
+end
+
node(:route_short_description) do |journey_pattern|
partial("api/v1/routes/short_description", :object => journey_pattern.route)
end
+
node(:vehicle_journey_object_ids) do |journey_pattern|
- journey_pattern.vehicle_journeys.map(&:objectid)
+ journey_pattern.vehicle_journeys.pluck(:objectid)
end unless root_object.vehicle_journeys.empty?
child :stop_points => :stop_area_short_descriptions do |stop_points|
node do |stop_point|
+ cache stop_point.stop_area_id
partial("api/v1/stop_areas/short_description", :object => stop_point.stop_area)
end
end
diff --git a/app/views/autocomplete_purchase_windows/index.rabl b/app/views/autocomplete_purchase_windows/index.rabl
new file mode 100644
index 000000000..1d0287602
--- /dev/null
+++ b/app/views/autocomplete_purchase_windows/index.rabl
@@ -0,0 +1,12 @@
+collection @purchase_windows, :object_root => false
+
+node do |window|
+ {
+ :id => window.id,
+ :name => window.name,
+ :objectid => window.objectid,
+ :color => window.color,
+ :short_id => window.get_objectid.short_id,
+ :text => "<strong><span class='fa fa-circle' style='color:" + (window.color ? window.color : '#4b4b4b') + "'></span> " + window.name + " - " + window.get_objectid.short_id + "</strong>"
+ }
+end
diff --git a/app/views/autocomplete_stop_areas/around.rabl b/app/views/autocomplete_stop_areas/around.rabl
index bc8f06054..d067dc4d0 100644
--- a/app/views/autocomplete_stop_areas/around.rabl
+++ b/app/views/autocomplete_stop_areas/around.rabl
@@ -12,7 +12,7 @@ child @stop_areas, root: :features, object_root: false do
name: s.name,
short_name: truncate(s.name, :length => 30) || "",
city_name: s.city_name,
- area_type: s.area_type,
+ area_type: Chouette::AreaType.find(s.area_type).label,
registration_number: s.registration_number,
stoparea_id: s.id,
text: "#{s.name}, #{s.zip_code} #{s.city_name}",
diff --git a/app/views/autocomplete_stop_areas/index.rabl b/app/views/autocomplete_stop_areas/index.rabl
index 5a9f76a47..c92b708f4 100644
--- a/app/views/autocomplete_stop_areas/index.rabl
+++ b/app/views/autocomplete_stop_areas/index.rabl
@@ -13,8 +13,9 @@ node do |stop_area|
:user_objectid => stop_area.user_objectid,
:longitude => stop_area.longitude,
:latitude => stop_area.latitude,
- :area_type => stop_area.area_type,
- :comment => stop_area.comment
+ :area_type => Chouette::AreaType.find(stop_area.area_type).label,
+ :comment => stop_area.comment,
+ :text => stop_area.full_name
}
end
diff --git a/app/views/calendar_mailer/created.html.slim b/app/views/calendar_mailer/created.html.slim
index 37b2a86ea..bee071150 100644
--- a/app/views/calendar_mailer/created.html.slim
+++ b/app/views/calendar_mailer/created.html.slim
@@ -1,4 +1,4 @@
-div = t('mailers.calendar_mailer.created.body', cal_name: @calendar.name, cal_index_url: calendars_url)
+div = t('mailers.calendar_mailer.created.body', cal_name: @calendar.name, cal_index_url: workgroup_calendars_url(@calendar.workgroup))
table style="border-collapse:collapse;font-family:'Open Sans', Arial, sans serif;width:550px;margin:0px auto;color:#333333;"
@@ -16,7 +16,7 @@ table style="border-collapse:collapse;font-family:'Open Sans', Arial, sans serif
= t('mailers.calendar_mailer.updated.subject')
p style="font-size:14px;margin:0px 0px 10px 0px;"
- = t('mailers.calendar_mailer.created.body', cal_name: @calendar.name, cal_index_url: calendars_url).html_safe
+ = t('mailers.calendar_mailer.created.body', cal_name: @calendar.name, cal_index_url: workgroup_calendars_url(@calendar.workgroup)).html_safe
tr
td style="text-align:center;padding:20px 0 0 0;border-top:1px solid #007fbb;"
diff --git a/app/views/calendar_mailer/updated.html.slim b/app/views/calendar_mailer/updated.html.slim
index bf128439a..0bdc2e7db 100644
--- a/app/views/calendar_mailer/updated.html.slim
+++ b/app/views/calendar_mailer/updated.html.slim
@@ -14,7 +14,7 @@ table style="border-collapse:collapse;font-family:'Open Sans', Arial, sans serif
= t('mailers.calendar_mailer.updated.subject')
p style="font-size:14px;margin:0px 0px 10px 0px;"
- = t('mailers.calendar_mailer.updated.body', cal_name: @calendar.name, cal_index_url: calendars_url).html_safe
+ = t('mailers.calendar_mailer.updated.body', cal_name: @calendar.name, cal_index_url: workgroup_calendars_url(@calendar.workgroup)).html_safe
tr
td style="text-align:center;padding:20px 0 0 0;border-top:1px solid #007fbb;"
diff --git a/app/views/calendars/_filters.html.slim b/app/views/calendars/_filters.html.slim
index b5283c1e8..8bfe1974e 100644
--- a/app/views/calendars/_filters.html.slim
+++ b/app/views/calendars/_filters.html.slim
@@ -1,22 +1,22 @@
-= search_form_for @q, url: calendars_path, builder: SimpleForm::FormBuilder, html: { method: :get, class: 'form form-filter' } do |f|
+= search_form_for @q, url: workgroup_calendars_path(@workgroup), builder: SimpleForm::FormBuilder, html: { method: :get, class: 'form form-filter' } do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :name_or_short_name_cont)
= f.search_field :name_or_short_name_cont, class: 'form-control', placeholder: 'Indiquez un nom/nom court de calendrier...'
span.input-group-btn
button.btn.btn-default#search_btn type='submit'
span.fa.fa-search
.ffg-row
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :shared_true)
= f.label Calendar.human_attribute_name(:shared), required: false, class: 'control-label'
.form-group.checkbox_list
= f.input :shared_true, as: :boolean, label: ("<span>Oui</span>").html_safe, wrapper_html: { class: 'checkbox-wrapper' }
= f.input :shared_false, as: :boolean, label: ("<span>Non</span>").html_safe, wrapper_html: { class: 'checkbox-wrapper' }
- .form-group
+ .form-group class=filter_item_class(params[:q], :contains_date)
= f.label Calendar.human_attribute_name(:date), class: 'control-label'
= f.input :contains_date, as: :date, label: false, wrapper_html: { class: 'date smart_date' }, class: 'form-control', include_blank: true
.actions
- = link_to 'Effacer', calendars_path, class: 'btn btn-link'
+ = link_to 'Effacer', workgroup_calendars_path(@workgroup), class: 'btn btn-link'
= f.submit 'Filtrer', id: 'calendar_filter_btn', class: 'btn btn-default'
diff --git a/app/views/calendars/_form.html.slim b/app/views/calendars/_form.html.slim
deleted file mode 100644
index 3c152c61d..000000000
--- a/app/views/calendars/_form.html.slim
+++ /dev/null
@@ -1,53 +0,0 @@
-= simple_form_for @calendar, html: { class: 'form-horizontal', id: 'calendar_form' }, wrapper: :horizontal_form do |f|
- .row
- .col-lg-12
- = f.input :name
- = f.input :short_name
-
- - if policy(@calendar).share?
- .form-group.has_switch
- = f.label :shared, class: 'col-sm-4 col-xs-5 control-label'
- = f.input :shared, as: :boolean, checked_value: true, unchecked_value: false, label: content_tag(:span, t("#{@calendar.shared}"), class: 'switch-label', data: {checkedValue: t('true'), uncheckedValue: t('false')}), wrapper_html: { class: 'col-sm-8 col-xs-7'}
-
- .separator
-
- .row
- .col-lg-12
- .subform
- .nested-head
- .wrapper
- div
- .form-group
- label.control-label
- = Calendar.human_attribute_name(:date)
- div
-
- = f.simple_fields_for :date_values do |date_value|
- = render 'date_value_fields', f: date_value
-
- .links.nested-linker
- = link_to_add_association t('simple_form.labels.calendar.add_a_date'), f, :date_values, class: 'btn btn-outline-primary'
-
- .separator
-
- .row
- .col-lg-12
- .subform
- .nested-head
- .wrapper
- div
- .form-group
- label.control-label
- = t('simple_form.labels.calendar.ranges.begin')
- div
- .form-group
- label.control-label
- = t('simple_form.labels.calendar.ranges.end')
- div
-
- = f.simple_fields_for :periods do |period|
- = render 'period_fields', f: period
- .links.nested-linker
- = link_to_add_association t('simple_form.labels.calendar.add_a_date_range'), f, :periods, class: 'btn btn-outline-primary'
-
- = f.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'calendar_form'
diff --git a/app/views/calendars/_form_advanced.html.slim b/app/views/calendars/_form_advanced.html.slim
new file mode 100644
index 000000000..e796e2e36
--- /dev/null
+++ b/app/views/calendars/_form_advanced.html.slim
@@ -0,0 +1,8 @@
+#periods
+
+= javascript_tag do
+ | window.actionType = "#{raw params[:action]}";
+ // | window.I18n = #{(I18n.backend.send(:translations)[I18n.locale].to_json).html_safe};
+ | window.timetablesUrl = "#{calendar_url(@calendar).html_safe}";
+
+= javascript_pack_tag 'calendars/edit.js'
diff --git a/app/views/calendars/_form_simple.html.slim b/app/views/calendars/_form_simple.html.slim
new file mode 100644
index 000000000..ba18c765b
--- /dev/null
+++ b/app/views/calendars/_form_simple.html.slim
@@ -0,0 +1,56 @@
+.row
+ .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-10.col-sm-offset-1
+ = simple_form_for [@workgroup, @calendar], html: { class: 'form-horizontal', id: 'calendar_form' }, wrapper: :horizontal_form do |f|
+ .row
+ .col-lg-12
+ = f.input :name
+ = f.input :short_name
+
+ - if policy(@calendar).share?
+ .form-group.has_switch
+ = f.label :shared, class: 'col-sm-4 col-xs-5 control-label'
+ = f.input :shared, as: :boolean, checked_value: true, unchecked_value: false, label: content_tag(:span, t("#{@calendar.shared}"), class: 'switch-label', data: {checkedValue: t('true'), uncheckedValue: t('false')}), wrapper_html: { class: 'col-sm-8 col-xs-7'}
+
+ .separator
+
+ - unless has_feature?('application_days_on_calendars')
+ .row
+ .col-lg-12
+ .subform
+ .nested-head
+ .wrapper
+ div
+ .form-group
+ label.control-label
+ = Calendar.human_attribute_name(:date)
+ div
+
+ = f.simple_fields_for :date_values do |date_value|
+ = render 'date_value_fields', f: date_value
+
+ .links.nested-linker
+ = link_to_add_association t('simple_form.labels.calendar.add_a_date'), f, :date_values, class: 'btn btn-outline-primary'
+
+ .separator
+
+ .row
+ .col-lg-12
+ .subform
+ .nested-head
+ .wrapper
+ div
+ .form-group
+ label.control-label
+ = t('simple_form.labels.calendar.ranges.begin')
+ div
+ .form-group
+ label.control-label
+ = t('simple_form.labels.calendar.ranges.end')
+ div
+
+ = f.simple_fields_for :periods do |period|
+ = render 'period_fields', f: period
+ .links.nested-linker
+ = link_to_add_association t('simple_form.labels.calendar.add_a_date_range'), f, :periods, class: 'btn btn-outline-primary'
+
+ = f.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'calendar_form'
diff --git a/app/views/calendars/edit.html.slim b/app/views/calendars/edit.html.slim
index e806fc94b..79ab1f5d0 100644
--- a/app/views/calendars/edit.html.slim
+++ b/app/views/calendars/edit.html.slim
@@ -1,7 +1,8 @@
-- breadcrumb :calendar, @calendar
+- breadcrumb :calendar, @workgroup, @calendar
- page_header_content_for @calendar
.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'
+ - if has_feature?('application_days_on_calendars')
+ = render 'form_advanced'
+ - else
+ = render 'form_simple'
diff --git a/app/views/calendars/index.html.slim b/app/views/calendars/index.html.slim
index 77478a624..0b58c0c72 100644
--- a/app/views/calendars/index.html.slim
+++ b/app/views/calendars/index.html.slim
@@ -1,7 +1,4 @@
-- breadcrumb :calendars
-- content_for :page_header_actions do
- - if policy(Calendar).create?
- = link_to(t('actions.add'), new_calendar_path, class: 'btn btn-default')
+- breadcrumb :calendars, workgroup
.page_content
.container-fluid
@@ -19,7 +16,7 @@
key: :name, \
attribute: 'name', \
link_to: lambda do |calendar| \
- calendar_path(calendar) \
+ workgroup_calendar_path(workgroup, calendar) \
end \
), \
TableBuilderHelper::Column.new( \
@@ -35,7 +32,6 @@
attribute: Proc.new { |c| t("#{c.try(:shared)}") } \
) \
],
- links: [:show, :edit],
cls: 'table has-filter'
= new_pagination @calendars, 'pull-right'
diff --git a/app/views/calendars/month.rabl b/app/views/calendars/month.rabl
new file mode 100644
index 000000000..1584db44c
--- /dev/null
+++ b/app/views/calendars/month.rabl
@@ -0,0 +1,9 @@
+object @calendar
+
+node do |tt|
+ {
+ name: I18n.l(@date, format: '%B'),
+ days: tt.month_inspect(@date),
+ day_types: %w(monday tuesday wednesday thursday friday saturday sunday).select{ |d| tt.send(d) }.map{ |d| tt.human_attribute_name(d).first(2)}.join('')
+ }
+end
diff --git a/app/views/calendars/new.html.slim b/app/views/calendars/new.html.slim
index ce8b6a036..5657a0c55 100644
--- a/app/views/calendars/new.html.slim
+++ b/app/views/calendars/new.html.slim
@@ -1,6 +1,4 @@
-- breadcrumb :calendars
+- breadcrumb :calendars, @workgroup
.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'
+ = render 'form_simple'
diff --git a/app/views/calendars/show.html.slim b/app/views/calendars/show.html.slim
index da4afa3e6..cec4f66a5 100644
--- a/app/views/calendars/show.html.slim
+++ b/app/views/calendars/show.html.slim
@@ -1,25 +1,24 @@
-- breadcrumb :calendar, @calendar
+- breadcrumb :calendar, @workgroup, @calendar
- page_header_content_for @calendar
-- content_for :page_header_content do
- .row.mb-sm
- .col-lg-12.text-right
- - @calendar.action_links.each do |link|
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
-- if policy(@calendar).edit?
- - content_for :page_header_actions do
- = link_to(t('actions.edit'), edit_calendar_path(@calendar), class: 'btn btn-default')
.page_content
.container-fluid
.row
.col-lg-6.col-md-6.col-sm-12.col-xs-12
= definition_list t('metadatas'),
- { 'Nom court' => @calendar.try(:short_name),
- Calendar.human_attribute_name(:shared) => t("#{@calendar.shared}"),
- 'Organisation' => @calendar.organisation.name,
- Calendar.human_attribute_name(:dates) => @calendar.dates.collect{|d| l(d, format: :short)}.join(', ').html_safe,
- Calendar.human_attribute_name(:date_ranges) => @calendar.periods.map{|d| t('validity_range', debut: l(d.begin, format: :short), end: l(d.end, format: :short))}.join('<br>').html_safe }
+ { 'Nom court' => resource.try(:short_name),
+ Calendar.human_attribute_name(:shared) => t("#{resource.shared}"),
+ 'Organisation' => resource.organisation.name,
+ Calendar.human_attribute_name(:dates) => resource.dates.collect{|d| l(d, format: :short)}.join(', ').html_safe,
+ Calendar.human_attribute_name(:date_ranges) => resource.periods.map{|d| t('validity_range', debut: l(d.begin, format: :short), end: l(d.end, format: :short))}.join('<br>').html_safe }
+
+ - if has_feature?('application_days_on_calendars')
+ .row
+ .col-lg-12.mb-sm
+ .pagination.pull-right
+ = @year
+ .page_links
+ = link_to '', calendar_path(@calendar, year: (@year - 1)), class: 'previous_page'
+ = link_to '', calendar_path(@calendar, year: (@year + 1)), class: 'next_page'
+
+ = render 'time_tables/show_time_table', time_table: @calendar
diff --git a/app/views/calendars/show.rabl b/app/views/calendars/show.rabl
new file mode 100644
index 000000000..295d97528
--- /dev/null
+++ b/app/views/calendars/show.rabl
@@ -0,0 +1,22 @@
+object @calendar
+
+attributes :id
+node do |tt|
+ {
+ comment: tt.name,
+ time_table_bounding: tt.presenter.time_table_bounding,
+ day_types: %w(monday tuesday wednesday thursday friday saturday sunday).select{ |d| tt.send(d) }.map{ |d| tt.human_attribute_name(d).first(2)}.join(''),
+ current_month: tt.month_inspect(Date.today),
+ periode_range: month_periode_enum(3),
+ current_periode_range: Date.today.beginning_of_month,
+ short_id: tt.object_id,
+ }
+end
+
+child(:periods, object_root: false, root: :time_table_periods) do
+ attributes :id, :period_start, :period_end
+end
+
+child(:all_dates, object_root: false, root: :time_table_dates) do
+ attributes :id, :date, :in_out
+end
diff --git a/app/views/companies/index.html.slim b/app/views/companies/index.html.slim
index 5d746642f..9f1502e54 100644
--- a/app/views/companies/index.html.slim
+++ b/app/views/companies/index.html.slim
@@ -1,7 +1,4 @@
- breadcrumb :companies, @line_referential
-- content_for :page_header_actions do
- - if policy(Chouette::Company).create?
- = link_to(t('companies.actions.new'), new_line_referential_company_path(@line_referential), class: 'btn btn-primary')
.page_content
.container-fluid
@@ -34,7 +31,6 @@
end \
) \
],
- links: [:show, :edit],
cls: 'table has-search'
= new_pagination @companies, 'pull-right'
diff --git a/app/views/companies/show.html.slim b/app/views/companies/show.html.slim
index 0d6b4aae3..ca0a410b3 100644
--- a/app/views/companies/show.html.slim
+++ b/app/views/companies/show.html.slim
@@ -1,25 +1,13 @@
- breadcrumb :company, @company
-- content_for :page_header_content do
- .row
- .col-lg-12.text-right.mb-sm
- - if policy(Chouette::Company).create?
- = link_to t('companies.actions.new'), new_line_referential_company_path(@line_referential), class: 'btn btn-primary'
- - if policy(@company).update?
- = link_to t('companies.actions.edit'), edit_line_referential_company_path(@line_referential, @company), class: 'btn btn-primary'
- - if policy(@company).destroy?
- = link_to line_referential_company_path(@line_referential, @company), method: :delete, data: {confirm: t('companies.actions.destroy_confirm')}, class: 'btn btn-primary' do
- span.fa.fa-trash
- span = t('companies.actions.destroy')
- page_header_content_for @company
-
.page_content
.container-fluid
.row
.col-lg-6.col-md-6.col-sm-12.col-xs-12
= definition_list t('metadatas'),
{ 'ID Codif' => @company.try(:get_objectid).try(:short_id),
- Chouette::Company.human_attribute_name(:phone) => @company.phone,
- Chouette::Company.human_attribute_name(:email) => @company.email,
- Chouette::Company.human_attribute_name(:url) => @company.url }
+ Chouette::Company.human_attribute_name(:phone) => resource.phone,
+ Chouette::Company.human_attribute_name(:email) => resource.email,
+ Chouette::Company.human_attribute_name(:url) => resource.url }
diff --git a/app/views/compliance_check_sets/_filters.html.slim b/app/views/compliance_check_sets/_filters.html.slim
index bf929bc08..e413a6cdd 100644
--- a/app/views/compliance_check_sets/_filters.html.slim
+++ b/app/views/compliance_check_sets/_filters.html.slim
@@ -1,23 +1,23 @@
= search_form_for @q_for_form, url: workbench_compliance_check_sets_path(@workbench), builder: SimpleForm::FormBuilder, class: 'form form-filter' do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :referential_name_cont)
= f.search_field :referential_name_cont, class: 'form-control', placeholder: t('compliance_check_sets.filters.name')
span.input-group-btn
button.btn.btn-default type='submit'
span.fa.fa-search
.ffg-row
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :parent_type_eq_any)
= f.label t('activerecord.attributes.compliance_check_set.assigned_to'), required: false, class: 'control-label'
= f.input :parent_type_eq_any, collection: ComplianceCheckSet.order('parent_type'), as: :check_boxes, label: false, label_method: lambda {|w| ("<span>#{w}</span>").html_safe}, required: false, wrapper_html: {class: 'checkbox_list'}
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :created_at)
= f.label Import.human_attribute_name(:created_at), required: false, class: 'control-label'
.filter_menu
= f.simple_fields_for :created_at do |p|
= p.input :start_date, as: :date, label: false, wrapper_html: {class: 'date smart_date filter_menu-item'}, default: @begin_range, include_blank: @begin_range ? false : true
= p.input :end_date, as: :date, label: false, wrapper_html: {class: 'date smart_date filter_menu-item'}, default: @end_range, include_blank: @end_range ? false : true
.form-group.search
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :compliance_control_set_name_cont)
= f.search_field :compliance_control_set_name_cont, class: 'form-control', placeholder: t('compliance_check_sets.filters.name_compliance_control_set')
span.input-group-btn
button.btn.btn-default type='submit'
diff --git a/app/views/compliance_check_sets/executed.html.slim b/app/views/compliance_check_sets/executed.html.slim
index da8a2a3de..b33b516b4 100644
--- a/app/views/compliance_check_sets/executed.html.slim
+++ b/app/views/compliance_check_sets/executed.html.slim
@@ -1,4 +1,4 @@
-- breadcrumb :compliance_check_set, @workbench, @compliance_check_set
+- breadcrumb :compliance_check_set_executed, @workbench, @compliance_check_set
- page_header_content_for @compliance_check_set
.page_content
diff --git a/app/views/compliance_check_sets/index.html.slim b/app/views/compliance_check_sets/index.html.slim
index f5d1bd777..31ad31e5b 100644
--- a/app/views/compliance_check_sets/index.html.slim
+++ b/app/views/compliance_check_sets/index.html.slim
@@ -12,7 +12,10 @@
[ \
TableBuilderHelper::Column.new( \
key: :ref, \
- attribute: 'compliance_check_set_id' \
+ attribute: 'id', \
+ link_to: lambda do |compliance_check_set| \
+ workbench_compliance_check_set_path(compliance_check_set.workbench_id, compliance_check_set.id) \
+ end \
), \
TableBuilderHelper::Column.new( \
key: :creation_date, \
@@ -20,9 +23,9 @@
), \
TableBuilderHelper::Column.new( \
key: :associated_object, \
- attribute: Proc.new{|n| n.referential.name}, \
+ attribute: Proc.new{|n| n.referential.present? ? n.referential.name : ''}, \
link_to: lambda do |compliance_check_set| \
- referential_path(compliance_check_set.referential_id) \
+ compliance_check_set.referential.present? ? referential_path(compliance_check_set.referential_id) : '#' \
end \
), \
TableBuilderHelper::Column.new( \
@@ -31,15 +34,15 @@
), \
TableBuilderHelper::Column.new(\
key: :compliance_control_set, \
- attribute: Proc.new{ |n| (n.compliance_control_set.name) if n.compliance_control_set} \
+ attribute: 'name', \
+ link_to: lambda do |compliance_check_set| \
+ executed_workbench_compliance_check_set_path(compliance_check_set.workbench_id, compliance_check_set.id) \
+ end \
), \
],
sortable: true,
- links: [:show],
cls: 'table has-filter has-search'
- unless @compliance_check_sets.any?
.row.mt-xs
.col-lg-12
= replacement_msg t('compliance_check_sets.search_no_results')
-
-
diff --git a/app/views/compliance_check_sets/show.html.slim b/app/views/compliance_check_sets/show.html.slim
index 5d8e3fa15..4df14ab06 100644
--- a/app/views/compliance_check_sets/show.html.slim
+++ b/app/views/compliance_check_sets/show.html.slim
@@ -1,41 +1,27 @@
- breadcrumb :compliance_check_sets, @workbench, @compliance_check_set
-/ PageHeader
-- content_for :page_header_content do
- .row
- .col-lg-12.text-right.mb-sm
- - @compliance_check_set.action_links.each do |link|
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
-
- page_header_content_for @compliance_check_set
-/ = pageheader 'jeux-de-donnees',
-/ @compliance_check_set.name,
-/ '',
-/ t('last_update', time: l(@compliance_check_set.updated_at, format: :short)) do
-
- / Below is secundary actions & optional contents (filters, ...)
- / .row
- / .col-lg-12.text-right.mb-sm
- / - @compliance_check_set.action_links.each do |link|
- / = link_to link.href,
- / method: link.method,
- / data: link.data,
- / class: 'btn btn-primary' do
- / = link.content
/ PageContent
.page_content.import_messages
.container-fluid
.row
+ .col-lg-6.col-md-6.col-sm-12.col-xs-12
+ = definition_list( t('metadatas'),
+ { I18n.t("compliance_check_sets.show.metadatas.referential") => (@compliance_check_set.referential.nil? ? '' : link_to(@compliance_check_set.referential.name, referential_path(@compliance_check_set.referential)) ),
+ I18n.t("compliance_check_sets.show.metadatas.referential_type") => 'Jeu de données',
+ I18n.t("compliance_check_sets.show.metadatas.compliance_check_set_executed") => link_to(@compliance_check_set.name, executed_workbench_compliance_check_set_path(@compliance_check_set.workbench_id, @compliance_check_set)),
+ I18n.t("compliance_check_sets.show.metadatas.compliance_control_owner") => @compliance_check_set.organisation.name,
+ I18n.t("compliance_check_sets.show.metadatas.import") => '' })
+ .row
.col-lg-12
h1
span.status_icon = compliance_check_set_status(@compliance_check_set.status)
- span = t('compliance_check_sets.show.table_state', lines_status: @compliance_check_set.lines_status , lines_in_compliance_check_set: @compliance_check_set.lines_in_compliance_check_set )
+ span = t('.table_state', lines_status: @compliance_check_set.lines_status , lines_in_compliance_check_set: @compliance_check_set.lines_in_compliance_check_set )
+ .col-lg-12
+ h2 = t('.table_title')
.col-lg-12
- = t('compliance_check_sets.show.table_explanation')
+ = t('.table_explanation')
+
.row
.col-lg-12
= table_builder_2 @compliance_check_set.compliance_check_resources,
@@ -46,13 +32,21 @@
), \
TableBuilderHelper::Column.new( \
key: :status, \
- attribute: Proc.new { |n| compliance_check_set_status(n.status) } \
+ attribute: Proc.new { |n| compliance_check_resource_status(n.status) } \
), \
TableBuilderHelper::Column.new( \
key: :metrics, \
attribute: Proc.new { |n| I18n.t('compliance_check_sets.show.metrics', n.metrics.deep_symbolize_keys) } \
+ ), \
+ 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 |compliance_check_resource| \
+ workbench_compliance_check_set_compliance_check_messages_path(@compliance_check_set.workbench, @compliance_check_set, format: 'csv', compliance_check_resource_id: compliance_check_resource.id ) \
+ end \
) \
],
sortable: false, \
links: [],
- cls: 'table'
+ cls: 'table has-search'
diff --git a/app/views/compliance_checks/_filters.html.slim b/app/views/compliance_checks/_filters.html.slim
index 0d747da27..40e45dd92 100644
--- a/app/views/compliance_checks/_filters.html.slim
+++ b/app/views/compliance_checks/_filters.html.slim
@@ -5,7 +5,7 @@
class: 'form form-filter' do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :name_cont)
= f.search_field :name_cont,
class: 'form-control',
placeholder: t('compliance_checks.filters.name')
@@ -14,7 +14,7 @@
span.fa.fa-search
.ffg-row
- .form-group.togglable#compliance_check_block-filter
+ .form-group.togglable#compliance_check_block-filter class=filter_item_class(params[:q], :compliance_check_block_id_eq_any)
= f.label t('activerecord.models.compliance_check_block.one'), required: false, class: 'control-label'
= f.input :compliance_check_block_id_eq_any,
collection: @compliance_check_set.compliance_check_blocks,
@@ -23,7 +23,7 @@
label_method: lambda {|w| ("<span>#{transport_mode_text(w)}</span>").html_safe},
required: false,
wrapper_html: {class: 'checkbox_list'}
- .form-group.togglable#subclass-filter
+ .form-group.togglable#subclass-filter class=filter_item_class(params[:q], :origin_code_cont_any)
= f.label t('compliance_checks.filters.subclass'), required: false, class: 'control-label'
= f.input :origin_code_cont_any,
collection: subclass_selection_list,
@@ -32,7 +32,7 @@
label_method: lambda {|w| ("<span>#{w.first}</span>").html_safe},
required: false,
wrapper_html: {class: 'checkbox_list'}
- .form-group.togglable#severity-filter
+ .form-group.togglable#severity-filter class=filter_item_class(params[:q], :criticity_eq_any)
= f.label t('compliance_checks.filters.criticity'), required: false, class: 'control-label'
= f.input :criticity_eq_any,
collection: ComplianceControl.criticities,
diff --git a/app/views/compliance_control_sets/_filters.html.slim b/app/views/compliance_control_sets/_filters.html.slim
index 6a5d3ac44..4348defac 100644
--- a/app/views/compliance_control_sets/_filters.html.slim
+++ b/app/views/compliance_control_sets/_filters.html.slim
@@ -1,16 +1,16 @@
= search_form_for @q_for_form, url: compliance_control_sets_path, builder: SimpleForm::FormBuilder, class: 'form form-filter' do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :name_cont)
= f.search_field :name_cont, class: 'form-control', placeholder: t('compliance_control_sets.filters.name')
span.input-group-btn
button.btn.btn-default type='submit'
span.fa.fa-search
.ffg-row
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :organisation_name_eq_any)
= f.label t('activerecord.models.organisation.one'), required: false, class: 'control-label'
= f.input :organisation_name_eq_any, collection: organisations_filters_values, as: :check_boxes, label: false, label_method: lambda {|w| ("<span>#{w.name}</span>").html_safe}, required: false, wrapper_html: {class: 'checkbox_list'}
-
- .form-group.togglable
+
+ .form-group.togglable class=filter_item_class(params[:q], :updated_at)
= f.label Import.human_attribute_name(:updated_at), required: false, class: 'control-label'
.filter_menu
= f.simple_fields_for :updated_at do |p|
@@ -19,4 +19,4 @@
.actions
= link_to t('actions.erase'), @compliance_control_set, class: 'btn btn-link'
- = f.submit t('actions.filter'), class: 'btn btn-default', id: 'compliance_control_set_filter_btn' \ No newline at end of file
+ = f.submit t('actions.filter'), class: 'btn btn-default', id: 'compliance_control_set_filter_btn'
diff --git a/app/views/compliance_control_sets/index.html.slim b/app/views/compliance_control_sets/index.html.slim
index 2a5651280..144a4e5b9 100644
--- a/app/views/compliance_control_sets/index.html.slim
+++ b/app/views/compliance_control_sets/index.html.slim
@@ -1,7 +1,4 @@
- breadcrumb :compliance_control_sets
-- content_for :page_header_actions do
- - if policy(ComplianceControlSet).create?
- = link_to(t('compliance_control_sets.actions.new'), new_compliance_control_set_path, class: 'btn btn-default')
.page_content
.container-fluid
@@ -30,7 +27,7 @@
), \
TableBuilderHelper::Column.new( \
key: :control_numbers, \
- attribute: 'control_numbers' \
+ attribute: Proc.new {|n| n.compliance_controls.count }\
), \
TableBuilderHelper::Column.new( \
key: :updated_at, \
@@ -38,7 +35,6 @@
) \
],
sortable: true,
- links: [:show],
cls: 'table has-filter has-search'
= new_pagination @compliance_control_sets, 'pull-right'
diff --git a/app/views/compliance_control_sets/show.html.slim b/app/views/compliance_control_sets/show.html.slim
index d915bbdaf..59100681d 100644
--- a/app/views/compliance_control_sets/show.html.slim
+++ b/app/views/compliance_control_sets/show.html.slim
@@ -1,17 +1,5 @@
- breadcrumb :compliance_control_set, @compliance_control_set
- page_header_content_for @compliance_control_set
-- content_for :page_header_content do
- .row.mb-sm
- .col-lg-12.text-right
- - @compliance_control_set.action_links.each do |link|
- - if link.is_a?(HTMLElement)
- = link.to_html(class: 'btn btn-primary')
- - else
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
.page_content
.container-fluid
diff --git a/app/views/compliance_controls/_filters.html.slim b/app/views/compliance_controls/_filters.html.slim
index d38da5d2d..f6b9970f2 100644
--- a/app/views/compliance_controls/_filters.html.slim
+++ b/app/views/compliance_controls/_filters.html.slim
@@ -5,7 +5,7 @@
class: 'form form-filter' do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :name_cont)
= f.search_field :name_cont,
class: 'form-control',
placeholder: t('compliance_controls.filters.name')
@@ -14,7 +14,7 @@
span.fa.fa-search
.ffg-row
- .form-group.togglable#compliance_control_block-filter
+ .form-group.togglable#compliance_control_block-filter class=filter_item_class(params[:q], :compliance_control_block_id_eq_any)
= f.label t('activerecord.models.compliance_control_block.one'), required: false, class: 'control-label'
= f.input :compliance_control_block_id_eq_any,
collection: @compliance_control_set.compliance_control_blocks,
@@ -23,7 +23,7 @@
label_method: lambda {|w| ("<span>#{transport_mode_text(w)}</span>").html_safe},
required: false,
wrapper_html: {class: 'checkbox_list'}
- .form-group.togglable#subclass-filter
+ .form-group.togglable#subclass-filter class=filter_item_class(params[:q], :origin_code_cont_any)
= f.label t('compliance_controls.filters.subclass'), required: false, class: 'control-label'
= f.input :origin_code_cont_any,
collection: subclass_selection_list,
@@ -32,7 +32,7 @@
label_method: lambda {|w| ("<span>#{w.first}</span>").html_safe},
required: false,
wrapper_html: {class: 'checkbox_list'}
- .form-group.togglable#severity-filter
+ .form-group.togglable#severity-filter class=filter_item_class(params[:q], :criticity_eq_any)
= f.label t('compliance_controls.filters.criticity'), required: false, class: 'control-label'
= f.input :criticity_eq_any,
collection: ComplianceControl.criticities,
diff --git a/app/views/compliance_controls/new.html.slim b/app/views/compliance_controls/new.html.slim
index f7f47fba3..c0abc522f 100644
--- a/app/views/compliance_controls/new.html.slim
+++ b/app/views/compliance_controls/new.html.slim
@@ -6,5 +6,5 @@
= render 'form'
= definition_list t('metadatas'),
- I18n.t('activerecord.attributes.compliance_control.predicate') => @compliance_control.class.predicate,
- I18n.t('activerecord.attributes.compliance_control.prerequisite') => @compliance_control.class.prerequisite
+ I18n.t('activerecord.attributes.compliance_control.predicate') => @compliance_control.predicate,
+ I18n.t('activerecord.attributes.compliance_control.prerequisite') => @compliance_control.prerequisite
diff --git a/app/views/compliance_controls/show.html.slim b/app/views/compliance_controls/show.html.slim
index 54b07abf1..ab25747a9 100644
--- a/app/views/compliance_controls/show.html.slim
+++ b/app/views/compliance_controls/show.html.slim
@@ -1,6 +1,4 @@
- breadcrumb :compliance_control, @compliance_control
-- content_for :page_header_actions do
- = link_to(t('actions.edit'), edit_compliance_control_set_compliance_control_path(params[:compliance_control_set_id], params[:id]), class: 'btn btn-default')
- page_header_content_for @compliance_control
@@ -15,8 +13,8 @@
ComplianceControl.human_attribute_name(:code) => @compliance_control.code,
ComplianceControl.human_attribute_name(:criticity) => @compliance_control.criticity,
ComplianceControl.human_attribute_name(:comment) => @compliance_control.comment,
- I18n.t('activerecord.attributes.compliance_control.predicate') => @compliance_control.class.predicate,
- I18n.t('activerecord.attributes.compliance_control.prerequisite') => @compliance_control.class.prerequisite,
+ I18n.t('activerecord.attributes.compliance_control.predicate') => @compliance_control.predicate,
+ I18n.t('activerecord.attributes.compliance_control.prerequisite') => @compliance_control.prerequisite,
}.merge( \
{}.tap do |hash| \
@compliance_control.class.dynamic_attributes.each do |attribute| \
diff --git a/app/views/dashboards/_dashboard.html.slim b/app/views/dashboards/_dashboard.html.slim
index f03301e23..05257a766 100644
--- a/app/views/dashboards/_dashboard.html.slim
+++ b/app/views/dashboards/_dashboard.html.slim
@@ -5,11 +5,11 @@
.panel-heading
h3.panel-title.with_actions
div
- = workbench.name
+ = link_to workbench.name, workbench_path(workbench)
span.badge.ml-xs = workbench.referentials.count if workbench.referentials.present?
div
- = link_to '', workbench_path(workbench), class: ' fa fa-chevron-right pull-right', title: t('.offers.see')
+ = link_to '', workbench_path(workbench), class: ' fa fa-chevron-right pull-right', title: t('workbenches.index.offers.see')
- if workbench.referentials.present?
.list-group
@@ -17,35 +17,38 @@
= link_to referential.name, referential_path(referential, workbench_id: referential.workbench_id, current_workbench_id: workbench.id), class: 'list-group-item'
- else
.panel-body
- em.small.text-muted = t('.offers.no_content')
+ em.small.text-muted = t('workbenches.index.offers.no_content')
.panel.panel-default
.panel-heading
h3.panel-title.with_actions
- = "Modèles de calendrier"
+ = link_to I18n.t("activerecord.models.calendar", count: @dashboard.current_organisation.calendars.size), workgroup_calendars_path(current_workgroup)
div
- = link_to '', calendars_path, class: ' fa fa-chevron-right pull-right'
+ = link_to '', workgroup_calendars_path(current_workgroup), class: ' fa fa-chevron-right pull-right'
- if @dashboard.current_organisation.calendars.present?
.list-group
- @dashboard.current_organisation.calendars.order("updated_at desc").limit(5).each do |calendar|
- = link_to calendar.name, calendar_path(calendar), class: 'list-group-item'
+ = link_to calendar.name, workgroup_calendars_path(current_workgroup, calendar), class: 'list-group-item'
- else
.panel-body
- em.small.text-muted Aucun modèle de calendrier défini
+ em.small.text-muted
+ = t('dasboard.calendars.none')
.col-lg-6.col-md-6.col-sm-6.col-xs-12
.panel.panel-default
- .panel-heading
- h3.panel-title
- = "Référentiels d'arrêts"
- .list-group
- - @dashboard.current_organisation.stop_area_referentials.each do |referential|
- = link_to referential.name, stop_area_referential_stop_areas_path(referential), class: 'list-group-item'
+ - @dashboard.current_organisation.stop_area_referentials.each do |referential|
+ .panel-heading
+ h3.panel-title
+ = referential.name
+ .list-group
+ = link_to Chouette::StopArea.model_name.human.pluralize.capitalize, stop_area_referential_stop_areas_path(referential), class: 'list-group-item'
.panel.panel-default
- .panel-heading
- h3.panel-title
- = "Référentiels de lignes"
- .list-group
- - @dashboard.current_organisation.line_referentials.all.each do |referential|
- = link_to referential.name, line_referential_lines_path(referential), class: 'list-group-item'
+ - @dashboard.current_organisation.line_referentials.all.each do |referential|
+ .panel-heading
+ h3.panel-title
+ = referential.name
+ .list-group
+ = link_to Chouette::Line.model_name.human.pluralize.capitalize, line_referential_lines_path(referential), class: 'list-group-item'
+ = link_to Chouette::Company.model_name.human.pluralize.capitalize, line_referential_companies_path(referential), class: 'list-group-item'
+ = link_to Chouette::Network.model_name.human.pluralize.capitalize, line_referential_networks_path(referential), class: 'list-group-item'
diff --git a/app/views/devise/invitations/edit.html.slim b/app/views/devise/invitations/edit.html.slim
index 6c9a6f436..7a22146c0 100644
--- a/app/views/devise/invitations/edit.html.slim
+++ b/app/views/devise/invitations/edit.html.slim
@@ -1,14 +1,19 @@
-.col-md-offset-2.col-md-8
- .panel.panel-default
- .panel-heading = t('devise.invitations.edit.header')
-
- .panel-body
- = simple_form_for resource, as: resource_name, :url => invitation_path(resource_name), :html => { :method => :put, class: "form-horizontal" } do |form|
- = form.hidden_field :invitation_token
-
- = form.input :name
- = form.input :password, as: :password
- = form.input :password_confirmation, as: :password
-
- .submit
- = form.button :submit, value: t('devise.invitations.edit.submit_button'), class: 'btn-info' \ No newline at end of file
+/ PageHeader
+
+- content_for :page_header_title, 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
+ = simple_form_for resource, as: resource_name, :url => invitation_path(resource_name), :html => { :method => :put, class: "form-horizontal", id: 'invitation_form' } do |form|
+ .row
+ .col-lg-12
+ = form.hidden_field :invitation_token
+
+ = form.input :name
+ = form.input :password, as: :password
+ = form.input :password_confirmation, as: :password
+
+ = form.button :submit, value: t('devise.invitations.edit.submit_button'), class: 'btn-info btn-default formSubmitr', form: 'invitation_form'
diff --git a/app/views/devise/mailer/invitation_instructions.fr.html.slim b/app/views/devise/mailer/invitation_instructions.fr.html.slim
index 484e0d68d..e263e188a 100644
--- a/app/views/devise/mailer/invitation_instructions.fr.html.slim
+++ b/app/views/devise/mailer/invitation_instructions.fr.html.slim
@@ -1,7 +1,7 @@
-p = t("devise.mailer.invitation_instructions.hello", email: @resource.email)
+p = t("devise.mailer.invitation_instructions.hello", email: @resource.name)
p = t("devise.mailer.invitation_instructions.someone_invited_you", url: unauthenticated_root_url)
p = link_to t("devise.mailer.invitation_instructions.accept"), accept_invitation_url(@resource, :invitation_token => @token)
-p = t("devise.mailer.invitation_instructions.ignore").html_safe \ No newline at end of file
+p = t("devise.mailer.invitation_instructions.ignore").html_safe
diff --git a/app/views/devise/passwords/edit.html.slim b/app/views/devise/passwords/edit.html.slim
index 864a44499..0d18f657c 100644
--- a/app/views/devise/passwords/edit.html.slim
+++ b/app/views/devise/passwords/edit.html.slim
@@ -1,13 +1,17 @@
-.col-md-offset-2.col-md-8
- .panel.panel-default
- .panel-heading = t('.title')
- .panel-body
- = simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put, class: "form-horizontal" }) do |f|
+/ PageHeader
- = f.input :reset_password_token, as: :hidden
- = f.input :password, as: :password
- = f.input :password_confirmation, as: :password
-
- .form-actions
- = link_to t("cancel"), unauthenticated_root_path, class: 'btn btn-default'
- = f.button :submit, :value => t("devise.passwords.edit.commit"), class: 'btn-info' \ No newline at end of file
+- content_for :page_header_title, 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
+ = simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put, class: "form-horizontal", id: 'password_form' }) do |f|
+ .row
+ .col-lg-12
+ = f.input :reset_password_token, as: :hidden
+ = f.input :password, as: :password
+ = f.input :password_confirmation, as: :password
+
+ = f.button :submit, :value => t("devise.passwords.edit.commit"), class: 'btn btn-default formSubmitr', form: 'password_form'
diff --git a/app/views/devise/passwords/new.html.slim b/app/views/devise/passwords/new.html.slim
index 8a739ecc1..303f78f0e 100644
--- a/app/views/devise/passwords/new.html.slim
+++ b/app/views/devise/passwords/new.html.slim
@@ -1,11 +1,15 @@
-.col-md-offset-2.col-md-8
- .panel.panel-default
- .panel-heading = t('.title')
-
- .panel-body
- = simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), html: {class: 'form-horizontal' } ) do |form|
- = form.input :email, :as => :email, placeholder: 'user@domain.com'
+/ PageHeader
- .form-actions
- = link_to t("cancel"), unauthenticated_root_path, class: 'btn btn-default'
- = form.button :submit, :value => t("devise.passwords.new.commit"), class: 'btn-info' \ No newline at end of file
+- content_for :page_header_title, 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
+ = simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), html: {class: 'form-horizontal', id: 'password_form' } ) do |form|
+ .row
+ .col-lg-12
+ = form.input :email, :as => :email, placeholder: 'user@domain.com'
+
+ = form.button :submit, :value => t("devise.passwords.new.commit"), class: 'btn btn-default formSubmitr', form: 'password_form'
diff --git a/app/views/devise/sessions/new.html.slim b/app/views/devise/sessions/new.html.slim
index 0ed17e24a..a812726e5 100644
--- a/app/views/devise/sessions/new.html.slim
+++ b/app/views/devise/sessions/new.html.slim
@@ -1,3 +1,5 @@
+- content_for :page_header_title, t('.title')
+
.page_content#devise
.container-fluid
#sessions_new.row
diff --git a/app/views/errors/forbidden.html.slim b/app/views/errors/forbidden.html.slim
index 23ea67eff..8c35b46a8 100644
--- a/app/views/errors/forbidden.html.slim
+++ b/app/views/errors/forbidden.html.slim
@@ -9,7 +9,7 @@
p
strong = "Désolé, la page demandée la page n'est pas accessible avec votre profil utilisateur."
- p = "Vous pouvez néanmoins continuer à utiliser l'application IBOO."
+ p = "Vous pouvez néanmoins continuer à utiliser l'application."
- else
p
diff --git a/app/views/errors/server_error.html.slim b/app/views/errors/server_error.html.slim
index 189a48760..529ad73e8 100644
--- a/app/views/errors/server_error.html.slim
+++ b/app/views/errors/server_error.html.slim
@@ -9,7 +9,7 @@
p
strong = "Désolé, une erreur est survenue."
- p = "Vous pouvez néanmoins continuer à utiliser l'application IBOO."
+ p = "Vous pouvez néanmoins continuer à utiliser l'application."
- else
p
diff --git a/app/views/import_resources/index.html.slim b/app/views/import_resources/index.html.slim
index 728d9f4a8..6b4e60026 100644
--- a/app/views/import_resources/index.html.slim
+++ b/app/views/import_resources/index.html.slim
@@ -43,9 +43,8 @@
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}")
+ = I18n.t("import_messages.#{message.message_key}")
diff --git a/app/views/imports/_filters.html.slim b/app/views/imports/_filters.html.slim
index b1f23e2c8..25c0d10d9 100644
--- a/app/views/imports/_filters.html.slim
+++ b/app/views/imports/_filters.html.slim
@@ -1,17 +1,17 @@
= search_form_for @q, url: workbench_imports_path(@workbench), html: { method: :get, class: 'form form-filter' } do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :name_or_creator_cont)
= 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
+ .form-group.togglable class=filter_item_class(params[:q], :status_eq_any)
= f.label Import.human_attribute_name(:status), required: false, class: 'control-label'
= f.input :status_eq_any, collection: %w(pending successful warning failed), as: :check_boxes, label: false, label_method: lambda{|l| ("<span>" + import_status(l) + "</span>").html_safe}, required: false, wrapper_html: { class: "checkbox_list"}
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :started_at)
= f.label Import.human_attribute_name(:started_at), required: false, class: 'control-label'
.filter_menu
= f.simple_fields_for :started_at do |p|
diff --git a/app/views/imports/_import_messages.html.slim b/app/views/imports/_import_messages.html.slim
new file mode 100644
index 000000000..af10b23e5
--- /dev/null
+++ b/app/views/imports/_import_messages.html.slim
@@ -0,0 +1,8 @@
+- if import_messages.any?
+ ul.list-unstyled.import_message-list
+ - import_messages.each do | import_message |
+ li
+ span(class="#{bootstrap_class_for_message_criticity import_message.criticity}")
+ = t( ['import_messages',
+ 'compliance_check_messages',
+ import_message.message_key].join('.'), import_message.message_attributes.symbolize_keys)
diff --git a/app/views/imports/index.html.slim b/app/views/imports/index.html.slim
index 79452bbfc..4fc077bd6 100644
--- a/app/views/imports/index.html.slim
+++ b/app/views/imports/index.html.slim
@@ -1,6 +1,4 @@
- breadcrumb :imports, @workbench
-- content_for :page_header_actions do
- = link_to(t('imports.actions.new'), new_workbench_import_path(workbench_id: @workbench), class: 'btn btn-primary')
.page_content
.container-fluid
@@ -34,7 +32,6 @@
attribute: 'creator' \
) \
],
- links: [],
cls: 'table has-search'
= new_pagination @imports, 'pull-right'
diff --git a/app/views/imports/show.html.slim b/app/views/imports/show.html.slim
index 5e22e03e0..7a9d02077 100644
--- a/app/views/imports/show.html.slim
+++ b/app/views/imports/show.html.slim
@@ -1,13 +1,4 @@
- breadcrumb :import, @workbench, @import
-- content_for :page_header_content do
- .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
- page_header_content_for @import
@@ -19,46 +10,51 @@
.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ésent(s) 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"' \
- } \
- ]
+ .error_messages
+ = render 'import_messages', import_messages: @import.messages
+
+ - if @import.children.any?
+ .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, \
+ ) \
+ ],
+ cls: 'table',
+ overhead: [ \
+ {}, \
+ { \
+ title: "#{@import.children_succeedeed} jeu de données validé sur #{@import.children.count} présent(s) 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 834501da3..8a7b0c47c 100644
--- a/app/views/journey_patterns_collections/show.html.slim
+++ b/app/views/journey_patterns_collections/show.html.slim
@@ -17,6 +17,7 @@
| window.stopPoints = #{(@stop_points_list.to_json).html_safe};
| window.journeyPatternLength = #{@journey_patterns.total_entries()};
| window.journeyPatternsPerPage = #{@ppage};
- | window.perms = #{raw @perms}
+ | window.perms = #{raw @perms};
+ | window.features = #{raw @features};
= javascript_pack_tag 'journey_patterns/index.js'
diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim
index 567e14ef0..3921c8701 100644
--- a/app/views/layouts/application.html.slim
+++ b/app/views/layouts/application.html.slim
@@ -13,6 +13,8 @@ html lang=I18n.locale
= javascript_pack_tag 'application'
= javascript_include_tag 'application'
+ = javascript_tag do
+ | I18n.locale = '#{I18n.locale}'
body
= render 'layouts/navigation/main_nav'
@@ -21,3 +23,6 @@ html lang=I18n.locale
= yield
#sidebar
= yield :sidebar
+
+ = render 'shared/development_toolbar'
+ = yield :javascript
diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb
new file mode 100644
index 000000000..977cbfe5b
--- /dev/null
+++ b/app/views/layouts/mailer.html.erb
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <style>
+ /* Email styles need to be inline */
+ body {
+ font-family: "Open Sans", sans-serif;
+ font-size: 14px;
+ line-height: 1.4;
+ color: #4b4b4b;
+ width: 800px;
+ }
+ </style>
+ </head>
+
+ <body>
+ <%= image_tag 'mail-header.png' %>
+
+ <%= yield %>
+ </body>
+</html>
diff --git a/app/views/layouts/mailer.html.slim b/app/views/layouts/mailer.html.slim
deleted file mode 100644
index 5db6917b3..000000000
--- a/app/views/layouts/mailer.html.slim
+++ /dev/null
@@ -1,7 +0,0 @@
-doctype html
-html
- head
- meta charset="utf-8"
- /!* Email styles need to be inline */
- body
- = yield
diff --git a/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim b/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim
index 3963d4cd4..1b7293d21 100644
--- a/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim
+++ b/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim
@@ -29,7 +29,7 @@
span Jeux de données
= 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
+ = link_to workgroup_calendars_path(current_workgroup), class: 'list-group-item' do
span Modèles de calendrier
= link_to workbench_compliance_check_sets_path(current_offer_workbench), class: 'list-group-item' do
span Rapport de contrôle
diff --git a/app/views/layouts/navigation/_main_nav_top.html.slim b/app/views/layouts/navigation/_main_nav_top.html.slim
index d6c849d3f..f664d5416 100644
--- a/app/views/layouts/navigation/_main_nav_top.html.slim
+++ b/app/views/layouts/navigation/_main_nav_top.html.slim
@@ -1,5 +1,5 @@
.nav-menu#menu_top
- .brandname = t('brandname')
+ .brandname = link_to t('brandname'), root_path
.menu-content
.menu-item
@@ -11,12 +11,16 @@
span.fa.fa-lg.fa-tasks
= link_to '#', class: 'menu-item', data: { panel: 'toggle', target: '#profile_panel' }, title: 'Profil' do
- span = current_user.username
+ span = current_user.name
span.fa.fa-lg.fa-user
+ - if Rails.application.config.development_toolbar
+ = link_to '#', data: { toggle: 'modal', target: '#development-toolbar' }, class: "toolbar-button menu-item" do
+ .fa.fa-cog
= link_to destroy_user_session_path, method: :delete, class: 'menu-item', title: 'Se déconnecter' do
span.fa.fa-lg.fa-sign-out
+
= render 'layouts/navigation/nav_panel_operations'
= render 'layouts/navigation/nav_panel_profile' if user_signed_in?
diff --git a/app/views/layouts/navigation/_page_header.html.slim b/app/views/layouts/navigation/_page_header.html.slim
index 90fd7d855..e407e53da 100644
--- a/app/views/layouts/navigation/_page_header.html.slim
+++ b/app/views/layouts/navigation/_page_header.html.slim
@@ -1,23 +1,36 @@
-div.page_header
- div.container-fluid
- div.row
- div.col-lg-9.col-md-8.col-sm-7.col-xs-7
+- action_links = resource.action_links(params[:action]) rescue nil
+- action_links ||= decorated_collection.action_links(params[:action]) rescue nil
+
+.page_header
+ .container-fluid
+ .row
+ .col-lg-9.col-md-8.col-sm-7.col-xs-7
- if defined?(resource_class)
- div.page-icon
+ .page-icon
span.sb class="sb-#{resource_class.model_name.name.underscore}"
- div.page-title
+ .page-title
- if content_for? :page_header_title
h1 = yield :page_header_title
- else
- if defined?(resource_class)
h1 = t("#{resource_class.model_name.name.underscore.pluralize}.#{params[:action]}.title")
- div.col-lg-3.col-md-4.col-sm-5.col-xs-5.text-right
- div.page-action
+ .col-lg-3.col-md-4.col-sm-5.col-xs-5.text-right
+ .page-action
- if content_for? :page_header_meta
= yield :page_header_meta
- if content_for? :page_header_actions
= yield :page_header_actions
+ - if action_links&.primary&.any?
+ - action_links.primary.each do |link|
+ = link.to_html do |l|
+ - l.class "btn btn-default #{l.disabled ? "disabled" : ""}"
+ - if action_links&.secondary&.any?
+ .row.mb-sm
+ .col-lg-12.text-right
+ - action_links.secondary.each do |link|
+ = link.to_html do |l|
+ - l.class "btn btn-primary #{l.disabled ? "disabled" : ""}"
- if content_for? :page_header_content
= yield :page_header_content
diff --git a/app/views/layouts/snapshots/actions_links.html.slim b/app/views/layouts/snapshots/actions_links.html.slim
new file mode 100644
index 000000000..f1fa55e87
--- /dev/null
+++ b/app/views/layouts/snapshots/actions_links.html.slim
@@ -0,0 +1,21 @@
+doctype html
+html lang=I18n.locale
+ head
+ meta charset="utf-8"
+ meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
+
+ = csrf_meta_tag
+
+ title = t('brandname')
+
+ = stylesheet_link_tag 'base'
+ = stylesheet_link_tag 'application'
+
+ = javascript_pack_tag 'application'
+ = javascript_include_tag 'application'
+
+ body
+ = render 'layouts/navigation/main_nav'
+ = render 'layouts/flash_messages', flash: flash
+ div.page_header
+ = yield
diff --git a/app/views/layouts/snapshots/default.html.slim b/app/views/layouts/snapshots/default.html.slim
new file mode 100644
index 000000000..9e4565dcb
--- /dev/null
+++ b/app/views/layouts/snapshots/default.html.slim
@@ -0,0 +1,19 @@
+doctype html
+html lang=I18n.locale
+ head
+ meta charset="utf-8"
+ meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
+
+ = csrf_meta_tag
+
+ title = t('brandname')
+
+ = stylesheet_link_tag 'base'
+ = stylesheet_link_tag 'application'
+
+ = javascript_pack_tag 'application'
+ = javascript_include_tag 'application'
+
+ body
+ = yield
+
diff --git a/app/views/line_footnotes/show.html.slim b/app/views/line_footnotes/show.html.slim
index e4f2a1d42..29e1f5708 100644
--- a/app/views/line_footnotes/show.html.slim
+++ b/app/views/line_footnotes/show.html.slim
@@ -16,7 +16,11 @@
.panel-heading = footnote.code
.panel-body
p = footnote.label
+
.panel-footer.text-right
+ div
+ p.text-muted.small = Chouette::Footnote.human_attribute_name(:checksum)
+ p.text-muted.small = footnote.checksum
p.text-muted
em.small = "Dernière mise à jour le #{l(footnote.updated_at, format: :short)}"
diff --git a/app/views/line_referentials/show.html.slim b/app/views/line_referentials/show.html.slim
index b4b32bc52..763eb076e 100644
--- a/app/views/line_referentials/show.html.slim
+++ b/app/views/line_referentials/show.html.slim
@@ -1,7 +1,8 @@
- breadcrumb :line_referential, @line_referential
- page_header_content_for @line_referential
-- content_for :page_header_actions do
- = link_to(t('actions.sync'), sync_line_referential_path(@line_referential), method: :post, class: 'btn btn-default')
+- if policy(@line_referential).synchronize?
+ - content_for :page_header_actions do
+ = link_to(t('actions.sync'), sync_line_referential_path(@line_referential), method: :post, class: 'btn btn-default')
- content_for :page_header_content do
.row.mb-md
diff --git a/app/views/lines/_filters.html.slim b/app/views/lines/_filters.html.slim
index e3674656a..67ba297cf 100644
--- a/app/views/lines/_filters.html.slim
+++ b/app/views/lines/_filters.html.slim
@@ -1,25 +1,25 @@
= search_form_for @q, url: line_referential_lines_path(@line_referential), html: {method: :get}, class: 'form form-filter' do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :name_or_number_or_objectid_cont)
= f.search_field :name_or_number_or_objectid_cont, placeholder: t('lines.index.name_or_number_or_objectid'), class: 'form-control'
span.input-group-btn
button.btn.btn-default#search-btn type='submit'
span.fa.fa-search
.ffg-row
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :network_id_eq_any)
= f.label Chouette::Line.human_attribute_name(:network_id), required: false, class: 'control-label'
= f.input :network_id_eq_any, collection: @line_referential.networks.order(name: :asc), as: :check_boxes, label: false, label_method: lambda{|l| ("<span>" + l.name + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list'}
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :company_id_eq_any)
= f.label Chouette::Line.human_attribute_name(:company_id), required: false, class: 'control-label'
= f.input :company_id_eq_any, collection: @line_referential.companies.order(name: :asc), as: :check_boxes, label: false, label_method: lambda{|l| ("<span>" + l.name + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list'}
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :transport_mode_eq_any)
= f.label Chouette::Line.human_attribute_name(:transport_mode), required: false, class: 'control-label'
= f.input :transport_mode_eq_any, collection: StifTransportModeEnumerations.sorted_transport_modes, as: :check_boxes, label: false, label_method: lambda{|l| ("<span>" + t("enumerize.transport_mode.#{l}") + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list'}
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :transport_submode_eq_any)
= f.label Chouette::Line.human_attribute_name(:transport_submode), required: false, class: 'control-label'
= f.input :transport_submode_eq_any, collection: StifTransportSubmodeEnumerations.sorted_transport_submodes, as: :check_boxes, label: false, label_method: lambda{|l| ("<span>" + t("enumerize.transport_submode.#{l}") + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list'}
diff --git a/app/views/lines/_form.html.slim b/app/views/lines/_form.html.slim
index de0308289..909d6512e 100644
--- a/app/views/lines/_form.html.slim
+++ b/app/views/lines/_form.html.slim
@@ -3,7 +3,7 @@
.col-lg-12
= f.input :name
= f.input :network_id, as: :select, :collection => @line_referential.networks, include_blank: false
- = f.input :company_id, as: :select, :collection => @line_referential.companies, include_blank: false
+ = f.input :company_id, as: :select, :collection => @line_referential.companies, include_blank: true
= f.input :secondary_company_ids, :collection => @line_referential.companies, include_blank: false, input_html: { multiple: true, 'data-select2ed': true }, label: t('activerecord.attributes.line.secondary_company')
= f.input :published_name
= f.input :registration_number
@@ -20,4 +20,3 @@
.separator
= f.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'lines_form'
-
diff --git a/app/views/lines/index.html.slim b/app/views/lines/index.html.slim
index 8b035b477..2d64e5f73 100644
--- a/app/views/lines/index.html.slim
+++ b/app/views/lines/index.html.slim
@@ -1,7 +1,4 @@
- breadcrumb :lines, @line_referential
-- content_for :page_header_actions do
- - if (policy(Chouette::Line).create? && @line_referential.organisations.include?(current_organisation))
- = link_to(t('lines.actions.new'), new_line_referential_line_path(@line_referential), class: 'btn btn-primary')
.page_content
.container-fluid
@@ -41,7 +38,7 @@
), \
TableBuilderHelper::Column.new( \
key: 'companies.name', \
- attribute: Proc.new { |n| n.try(:company).try(:name) } \
+ attribute: Proc.new { |n| n&.company&.name || "-" } \
), \
TableBuilderHelper::Column.new( \
key: :transport_mode, \
@@ -52,7 +49,6 @@
attribute: Proc.new { |n| n.transport_submode.present? ? t("enumerize.transport_submode.#{n.try(:transport_submode)}") : "-" } \
) \
],
- links: [:show],
cls: 'table has-filter has-search'
= new_pagination @lines, 'pull-right'
diff --git a/app/views/lines/show.html.slim b/app/views/lines/show.html.slim
index d62fe30d6..34b907bdd 100644
--- a/app/views/lines/show.html.slim
+++ b/app/views/lines/show.html.slim
@@ -1,14 +1,4 @@
- breadcrumb :line, @line
-- content_for :page_header_content do
- .row
- .col-lg-12.text-right.mb-sm
- - @line.action_links.each do |link|
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
-
- page_header_content_for @line
.page_content
diff --git a/app/views/merges/_form.html.slim b/app/views/merges/_form.html.slim
new file mode 100644
index 000000000..b97a4b03e
--- /dev/null
+++ b/app/views/merges/_form.html.slim
@@ -0,0 +1,12 @@
+= simple_form_for merge, as: :merge, url: workbench_merges_path(workbench), html: {class: 'form-horizontal', id: 'wb_merge_form'}, wrapper: :horizontal_form do |form|
+
+ .row
+ .col-lg-12
+ = form.input :referentials, :collection => @mergeable_referentials, include_blank: false, input_html: { multiple: true, 'data-select2ed': true }
+
+
+ .row
+ .col-lg-12
+ = form.input :creator, input_html: { disabled: true }
+
+ = form.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'wb_merge_form'
diff --git a/app/views/merges/new.html.slim b/app/views/merges/new.html.slim
new file mode 100644
index 000000000..dab4bdf4e
--- /dev/null
+++ b/app/views/merges/new.html.slim
@@ -0,0 +1,7 @@
+- breadcrumb :merges, @workbench
+
+.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', merge: @merge, workbench: @workbench
diff --git a/app/views/merges/show.html.slim b/app/views/merges/show.html.slim
new file mode 100644
index 000000000..a94552c0d
--- /dev/null
+++ b/app/views/merges/show.html.slim
@@ -0,0 +1,17 @@
+- breadcrumb :merge, @merge
+- page_header_content_for @merge
+
+.page_content
+ .container-fluid
+ .row
+ .col-lg-6.col-md-6.col-sm-12.col-xs-12
+ = definition_list t('metadatas'),
+ { @merge.class.human_attribute_name(:referentials) => @merge.referentials.map(&:name).join(', '),
+ @merge.class.human_attribute_name(:operator) => @merge.creator,
+ @merge.class.human_attribute_name(:status) => @merge.status,
+ @merge.class.human_attribute_name(:created_at) => @merge.created_at ? l(@merge.created_at) : '-',
+ @merge.class.human_attribute_name(:started_at) => @merge.started_at ? l(@merge.started_at) : '-',
+ @merge.class.human_attribute_name(:ended_at) => @merge.ended_at ? l(@merge.ended_at) : '-' }
+
+ - if resource.output.current
+ = referential_overview resource.output.current
diff --git a/app/views/networks/_form.html.slim b/app/views/networks/_form.html.slim
index 362584f97..f91a112e8 100644
--- a/app/views/networks/_form.html.slim
+++ b/app/views/networks/_form.html.slim
@@ -4,11 +4,11 @@
= f.input :name, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@line_referential)}.network.name")}
= f.input :registration_number, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@line_referential)}.network.registration_number")}
= f.input :comment
- = f.input :version_date, :label_html => { :class => 'string optional col-sm-4 col-xs-5 control-label' }, :wrapper => :multi_select_inline
- = f.input :description
- = f.input :source_name
- = f.input :source_type_name, as: :select, :collection => Chouette::Network.source_type_name.options, :include_blank => true
- = f.input :source_identifier
+ / = f.input :version_date, :label_html => { :class => 'string optional col-sm-4 col-xs-5 control-label' }, :wrapper => :multi_select_inline
+ / = f.input :description
+ / = f.input :source_name
+ / = f.input :source_type_name, as: :select, :collection => Chouette::Network.source_type_name.options, :include_blank => true
+ / = f.input :source_identifier
.separator
= f.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'network_form'
diff --git a/app/views/networks/index.html.slim b/app/views/networks/index.html.slim
index b13c73e9e..6aeb140cc 100644
--- a/app/views/networks/index.html.slim
+++ b/app/views/networks/index.html.slim
@@ -1,7 +1,4 @@
- breadcrumb :networks, @line_referential
-- content_for :page_header_actions do
- - if policy(Chouette::Network).create?
- = link_to(t('networks.actions.new'), new_line_referential_network_path(@line_referential), class: 'btn btn-primary')
.page_content
.container-fluid
diff --git a/app/views/networks/show.html.slim b/app/views/networks/show.html.slim
index f7d40a049..527fb8d5b 100644
--- a/app/views/networks/show.html.slim
+++ b/app/views/networks/show.html.slim
@@ -1,17 +1,13 @@
- breadcrumb :network, @network
- page_header_content_for @network
-- content_for :page_header_content do
- .row
- .col-lg-12.text-right.mb-sm
- - @network.action_links.each do |link|
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
+
.page_content
.container-fluid
.row
.col-lg-6.col-md-6.col-sm-12.col-xs-12
= definition_list t('metadatas'),
- { 'ID Codif' => @network.try(:get_objectid).try(:short_id) }
+ { @network.human_attribute_name(:id) => @network.get_objectid.try(:short_id), \
+ @network.human_attribute_name(:name) => @network.name, \
+ @network.human_attribute_name(:registration_number) => @network.registration_number, \
+ @network.human_attribute_name(:comment) => (@network.comment.presence || '-'), \
+ }
diff --git a/app/views/purchase_windows/_date_value_fields.html.slim b/app/views/purchase_windows/_date_value_fields.html.slim
new file mode 100644
index 000000000..7bde06a94
--- /dev/null
+++ b/app/views/purchase_windows/_date_value_fields.html.slim
@@ -0,0 +1,13 @@
+.nested-fields
+ - if f.object.errors.has_key? :base
+ .row
+ .col-lg-12
+ .alert.alert-danger
+ - f.object.errors[:base].each do |message|
+ p.small = message
+
+ .wrapper
+ div
+ = f.input :value, as: :date, label: false, wrapper_html: { class: 'date smart_date' }
+ div
+ = link_to_remove_association '', f, class: 'fa fa-trash', data: { confirm: 'Etes-vous sûr(e) ?' }, title: t('actions.delete')
diff --git a/app/views/purchase_windows/_filters.html.slim b/app/views/purchase_windows/_filters.html.slim
new file mode 100644
index 000000000..eedbf31d5
--- /dev/null
+++ b/app/views/purchase_windows/_filters.html.slim
@@ -0,0 +1,15 @@
+= search_form_for @q, url: referential_purchase_windows_path, builder: SimpleForm::FormBuilder, html: { method: :get, class: 'form form-filter' } do |f|
+ .ffg-row
+ .input-group.search_bar class=filter_item_class(params[:q], :name_cont)
+ = f.search_field :name_cont, class: 'form-control', placeholder: t('purchase_windows.index.filter_placeholder')
+ span.input-group-btn
+ button.btn.btn-default#search_btn type='submit'
+ span.fa.fa-search
+
+ .form-group class=filter_item_class(params[:q], :contains_date)
+ = f.label Chouette::PurchaseWindow.human_attribute_name(:date), class: 'control-label'
+ = f.input :contains_date, as: :date, label: false, wrapper_html: { class: 'date smart_date' }, class: 'form-control', default: @date, include_blank: @date ? false : true
+
+ .actions
+ = link_to t('actions.erase'), referential_purchase_windows_path, class: 'btn btn-link'
+ = f.submit t('actions.filter'), id: 'purchase_window_filter_btn', class: 'btn btn-default'
diff --git a/app/views/purchase_windows/_form.html.slim b/app/views/purchase_windows/_form.html.slim
new file mode 100644
index 000000000..2101ae6db
--- /dev/null
+++ b/app/views/purchase_windows/_form.html.slim
@@ -0,0 +1,29 @@
+= simple_form_for [@referential, @purchase_window], html: { class: 'form-horizontal', id: 'purchase_window_form' }, wrapper: :horizontal_form do |f|
+ .row
+ .col-lg-12
+ = f.input :name
+ = f.input :color, as: :color_select, collection: Chouette::PurchaseWindow.colors_i18n
+
+ .separator
+
+ .row
+ .col-lg-12
+ .subform
+ .nested-head
+ .wrapper
+ div
+ .form-group
+ label.control-label
+ = t('simple_form.labels.purchase_window.ranges.begin')
+ div
+ .form-group
+ label.control-label
+ = t('simple_form.labels.purchase_window.ranges.end')
+ div
+
+ = f.simple_fields_for :periods do |period|
+ = render 'period_fields', f: period
+ .links.nested-linker
+ = link_to_add_association t('simple_form.labels.purchase_window.add_a_date_range'), f, :periods, class: 'btn btn-outline-primary'
+
+ = f.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'purchase_window_form'
diff --git a/app/views/purchase_windows/_period_fields.html.slim b/app/views/purchase_windows/_period_fields.html.slim
new file mode 100644
index 000000000..95e204554
--- /dev/null
+++ b/app/views/purchase_windows/_period_fields.html.slim
@@ -0,0 +1,15 @@
+.nested-fields
+ - if f.object.errors.has_key? :base
+ .row
+ .col-lg-12
+ .alert.alert-danger
+ - f.object.errors[:base].each do |message|
+ p.small = message
+
+ .wrapper
+ div
+ = f.input :begin, as: :date, label: false, wrapper_html: { class: 'date smart_date' }
+ div
+ = f.input :end, as: :date, label: false, wrapper_html: { class: 'date smart_date' }
+ div
+ = link_to_remove_association '', f, class: 'fa fa-trash', data: { confirm: 'Etes-vous sûr(e) ?' }, title: t('actions.delete')
diff --git a/app/views/purchase_windows/edit.html.slim b/app/views/purchase_windows/edit.html.slim
new file mode 100644
index 000000000..6354db853
--- /dev/null
+++ b/app/views/purchase_windows/edit.html.slim
@@ -0,0 +1,7 @@
+- breadcrumb :purchase_window, @referential, @purchase_window
+- page_header_content_for @purchase_window
+.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'
diff --git a/app/views/purchase_windows/index.html.slim b/app/views/purchase_windows/index.html.slim
new file mode 100644
index 000000000..0dba86935
--- /dev/null
+++ b/app/views/purchase_windows/index.html.slim
@@ -0,0 +1,41 @@
+- breadcrumb :purchase_windows, @referential
+
+.page_content
+ .container-fluid
+ - if params[:q].present? or @purchase_windows.any?
+ .row
+ .col-lg-12
+ = render 'filters'
+
+ - if @purchase_windows.any?
+ .row
+ .col-lg-12
+ = table_builder_2 @purchase_windows,
+ [ \
+ TableBuilderHelper::Column.new( \
+ key: :name, \
+ attribute: 'name', \
+ link_to: lambda do |purchase_window| \
+ referential_purchase_window_path(purchase_window.referential, purchase_window) \
+ end \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :color, \
+ attribute: Proc.new { |tt| tt.color ? content_tag(:span, '', class: 'fa fa-circle', style: "color:#{tt.color}") : '-' }\
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :bounding_dates, \
+ attribute: Proc.new {|w| w.bounding_dates.nil? ? '-' : t('validity_range', debut: l(w.bounding_dates.begin, format: :short), end: l(w.bounding_dates.end, format: :short))}, \
+ sortable: false \
+ ) \
+ ],
+ cls: 'table has-filter'
+
+ = new_pagination @purchase_windows, 'pull-right'
+
+ - unless @purchase_windows.any?
+ .row.mt-xs
+ .col-lg-12
+ = replacement_msg t('purchase_windows.search_no_results')
+
+= javascript_pack_tag 'date_filters'
diff --git a/app/views/purchase_windows/new.html.slim b/app/views/purchase_windows/new.html.slim
new file mode 100644
index 000000000..402084167
--- /dev/null
+++ b/app/views/purchase_windows/new.html.slim
@@ -0,0 +1,6 @@
+- breadcrumb :purchase_windows, @referential
+.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'
diff --git a/app/views/purchase_windows/show.html.slim b/app/views/purchase_windows/show.html.slim
new file mode 100644
index 000000000..4e836f424
--- /dev/null
+++ b/app/views/purchase_windows/show.html.slim
@@ -0,0 +1,12 @@
+- breadcrumb :purchase_window, @referential, @purchase_window
+- page_header_content_for @purchase_window
+
+.page_content
+ .container-fluid
+ .row
+ .col-lg-6.col-md-6.col-sm-12.col-xs-12
+ = definition_list t('metadatas'),
+ { Chouette::PurchaseWindow.human_attribute_name(:name) => @purchase_window.try(:name),
+ 'Organisation' => @purchase_window.referential.organisation.name,
+ Chouette::PurchaseWindow.human_attribute_name(:date_ranges) => @purchase_window.periods.map{|d| t('validity_range', debut: l(d.begin, format: :short), end: l(d.end, format: :short))}.join('<br>').html_safe,
+ Chouette::PurchaseWindow.human_attribute_name(:checksum) => @purchase_window.checksum }
diff --git a/app/views/referential_companies/index.html.slim b/app/views/referential_companies/index.html.slim
index de0f7de69..3bff448c7 100644
--- a/app/views/referential_companies/index.html.slim
+++ b/app/views/referential_companies/index.html.slim
@@ -1,7 +1,4 @@
- breadcrumb :referential_companies, @referential
-- content_for :page_header_actions do
- - if policy(Chouette::Company).create?
- = link_to(t('companies.actions.new'), new_referential_company_path(@referential), class: 'btn btn-default')
.page_content
.container-fluid
@@ -46,7 +43,6 @@
attribute: 'url' \
) \
],
- links: [:show, :edit],
cls: 'table has-search'
= new_pagination @companies, 'pull-right'
diff --git a/app/views/referential_lines/_filters.html.slim b/app/views/referential_lines/_filters.html.slim
index 379d6234f..501f61c16 100644
--- a/app/views/referential_lines/_filters.html.slim
+++ b/app/views/referential_lines/_filters.html.slim
@@ -1,13 +1,13 @@
= search_form_for @q, url: referential_line_path(@referential, @line), class: 'form form-filter' do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :name_or_objectid_cont)
= f.search_field :name_or_objectid_cont, class: 'form-control', placeholder: "Indiquez un nom d'itinéraire ou un ID..."
span.input-group-btn
button.btn.btn-default#search-btn type='submit'
span.fa.fa-search
.ffg-row
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :wayback_eq_any)
= f.label Chouette::Route.human_attribute_name(:wayback), required: false, class: 'control-label'
= f.input :wayback_eq_any, class: 'form-control', collection: Chouette::Route.wayback.values, as: :check_boxes, label: false, required: false, wrapper_html: { class: 'checkbox_list'}, label_method: lambda{|l| ("<span>" + t("enumerize.route.wayback.#{l}") + "</span>").html_safe}
diff --git a/app/views/referential_lines/show.html.slim b/app/views/referential_lines/show.html.slim
index cfba8cab3..5ea0e31bb 100644
--- a/app/views/referential_lines/show.html.slim
+++ b/app/views/referential_lines/show.html.slim
@@ -1,13 +1,4 @@
- breadcrumb :referential_line, @referential, @line
-- content_for :page_header_content do
- .row
- .col-lg-12.text-right.mb-sm
- - @line.action_links.each do |link|
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
- page_header_content_for @line
.page_content
@@ -26,7 +17,8 @@
@line.human_attribute_name(:transport_submode) => (@line.transport_submode.present? ? t("enumerize.transport_submode.#{@line.transport_submode}") : '-'),
@line.human_attribute_name(:url) => (@line.url ? @line.url : '-'),
@line.human_attribute_name(:seasonal) => (@line.seasonal? ? t('true') : t('false')),}
-
+ .col-lg-6.col-md-6.col-sm-12.col-xs-12
+ #routes_map.map.mb-lg
.row
.col-lg-12
.h3 = t('lines.show.routes.title')
@@ -79,8 +71,8 @@
attribute: Proc.new{ |r| r.try(:journey_patterns).count } \
) \
],
- links: [:show, :edit],
- cls: 'table has-search'
+ cls: 'table has-search',
+ action: :index
= new_pagination @routes, 'pull-right'
@@ -88,3 +80,8 @@
.row.mt-xs
.col-lg-12
= replacement_msg t('routes.search_no_results')
+
+= javascript_tag do
+ | window.routes = "#{URI.escape(@routes.map{|r| {name: r.name, id: r.id, stops: route_json_for_edit(r, serialize: false)}}.to_json)}"
+
+= javascript_pack_tag 'referential_lines/show.js'
diff --git a/app/views/referential_networks/index.html.slim b/app/views/referential_networks/index.html.slim
index d556e7e5e..efa28dc05 100644
--- a/app/views/referential_networks/index.html.slim
+++ b/app/views/referential_networks/index.html.slim
@@ -1,7 +1,4 @@
- breadcrumb :referential_networks, @referential
-- if policy(Chouette::Network).create?
- - content_for :page_header_actions do
- = link_to(t('networks.actions.new'), new_referential_network_path(@referential), class: 'btn btn-default')
.page_content
.container-fluid
diff --git a/app/views/referential_networks/show.html.slim b/app/views/referential_networks/show.html.slim
index 7de304671..3d13d9211 100644
--- a/app/views/referential_networks/show.html.slim
+++ b/app/views/referential_networks/show.html.slim
@@ -1,14 +1,5 @@
- breadcrumb :referential_network, @referential, @network
- page_header_content_for @network
-- content_for :page_header_content do
- .row
- .col-lg-12.text-right.mb-sm
- - @network.action_links.each do |link|
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
/ PageContent
.page_content
diff --git a/app/views/referential_stop_areas/_form.html.slim b/app/views/referential_stop_areas/_form.html.slim
index 50f5d4aaf..8181ec3f3 100644
--- a/app/views/referential_stop_areas/_form.html.slim
+++ b/app/views/referential_stop_areas/_form.html.slim
@@ -7,7 +7,7 @@
= form.inputs do
= form.input :id, as: :hidden
= form.input :name, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.name")}
- = form.input :stop_area_type, as: :select, :input_html => { :disabled => !@stop_area.new_record? }, :collection => Chouette::StopArea.area_type.options, :include_blank => false }
+ = form.input :stop_area_type, as: :select, :input_html => { :disabled => !@stop_area.new_record? }, :collection => Chouette::StopArea.area_type.options, :include_blank => false
.location_info
h3 = t("stop_areas.stop_area.localisation")
diff --git a/app/views/referential_stop_areas/show.html.slim b/app/views/referential_stop_areas/show.html.slim
index 0470b4654..cb04ab7a6 100644
--- a/app/views/referential_stop_areas/show.html.slim
+++ b/app/views/referential_stop_areas/show.html.slim
@@ -1,14 +1,5 @@
- breadcrumb :referential_stop_area, @referential, @stop_area
- page_header_content_for @stop_area
-- content_for :page_header_content do
- .row
- .col-lg-12.text-right.mb-sm
- - @stop_area.action_links.each do |link|
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
.page_content
.container-fluid
diff --git a/app/views/referential_vehicle_journeys/_filters.html.slim b/app/views/referential_vehicle_journeys/_filters.html.slim
new file mode 100644
index 000000000..3104e3a71
--- /dev/null
+++ b/app/views/referential_vehicle_journeys/_filters.html.slim
@@ -0,0 +1,62 @@
+= search_form_for @q, url: referential_vehicle_journeys_path(@referential), html: {method: :get}, class: 'form form-filter' do |f|
+ .ffg-row
+ .input-group.search_bar
+ = f.search_field :published_journey_name_or_objectid_cont, placeholder: t('.published_journey_name_or_objectid'), class: 'form-control'
+ span.input-group-btn
+ button.btn.btn-default#search-btn type='submit'
+ span.fa.fa-search
+ .ffg-row
+ .form-group.per-page-select
+ = I18n.t("simple_form.per_page")
+ = %w(10 50 100).each_with_index.map{ |v, i| (params[:per_page] == v || params[:per_page].nil? && i == 0) ? "<span class='selected'>#{v}</span>" : link_to(v, referential_vehicle_journeys_path(@referential, q: params[:q], per_page: v)) }.join(' - ').html_safe
+ .form-group.togglable class=filter_item_class(params[:q], :company_id_eq_any)
+ = f.label Chouette::VehicleJourney.human_attribute_name(:company), required: false, class: 'control-label'
+ - if @all_companies.present?
+ = f.input :company_id_eq_any, collection: @all_companies.select(:id, :name).order(name: :asc), as: :check_boxes, label: false, label_method: lambda{|l| ("<span>" + l.name + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list'}
+ - else
+ = f.input :company_id_eq_any, collection: [[I18n.t('companies.search_no_results_for_filter'), nil]], as: :check_boxes, label: false, disabled: true, required: false, wrapper_html: { class: 'checkbox_list disabled'}
+
+ .form-group.togglable class=filter_item_class(params[:q], :route_line_id_eq)
+ = f.label Chouette::Line.model_name.human,
+ required: false,
+ class: 'control-label'
+ .form-inline.filter_menu
+ = f.input :route_line_id_eq,
+ as: :select,
+ include_blank: t(".all"),
+ collection: @vehicle_journeys.lines,
+ selected: params[:q] && params[:q][:route_line_id_eq],
+ input_html: { \
+ 'data-select2ed': 'true',
+ 'data-select2ed-placeholder': t('referentials.filters.line') \
+ },
+ label: false,
+ label_method: :display_name,
+ wrapper_html: { class: 'filter_menu-item select2ed' }
+
+ .form-group.togglable.name-filter class=filter_item_class(params[:q], :published_journey_name_gteq)
+ = f.label Chouette::VehicleJourney.human_attribute_name(:published_journey_name), required: false, class: 'control-label'
+ .inputs.form-inline.checkbox_list
+ = f.input :published_journey_name_gteq, label: false, wrapper_html: { class: 'w45'}
+ .form-group.w10.to= I18n.t('vehicle_journeys.form.to')
+ = f.input :published_journey_name_lteq, label: false, wrapper_html: { class: 'w45'}
+ .form-group.togglable class=filter_item_class(params[:q], :stop_area_ids)
+ = f.label Chouette::StopArea.model_name.human.pluralize, required: false, class: 'control-label'
+ = f.input :stop_area_ids, collection: @all_stop_areas.select(:id, :name).order(name: :asc), checked: params[:q] && params[:q][:stop_area_ids], as: :check_boxes, label: false, label_method: lambda{|l| ("<span>" + l.name + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list'}, multiple: true
+ .form-group.togglable class=filter_item_class(params[:q], :purchase_window)
+ = f.label Chouette::VehicleJourney.human_attribute_name(:purchase_window), class: 'control-label'
+ .filter_menu
+ = f.simple_fields_for :purchase_window do |p|
+ = p.input :start_date, as: :date, label: t('simple_form.from'), wrapper_html: { class: 'date smart_date filter_menu-item' }, default: @purchase_window_begin_range, include_blank: @purchase_window_begin_range ? false : true
+ = p.input :end_date, as: :date, label: t('simple_form.to'), wrapper_html: { class: 'date smart_date filter_menu-item' }, default: @purchase_window_end_range, include_blank: @purchase_window_end_range ? false : true
+ .form-group.togglable class=filter_item_class(params[:q], :time_table)
+ = f.label Chouette::TimeTable.model_name.human, class: 'control-label'
+ .filter_menu
+ = f.simple_fields_for :time_table do |p|
+ = p.input :start_date, as: :date, label: t('simple_form.from'), wrapper_html: { class: 'date smart_date filter_menu-item' }, default: @time_table_begin_range, include_blank: @time_table_begin_range ? false : true
+ = p.input :end_date, as: :date, label: t('simple_form.to'), wrapper_html: { class: 'date smart_date filter_menu-item' }, default: @time_table_end_range, include_blank: @time_table_end_range ? false : true
+
+
+ .actions
+ = link_to 'Effacer', referential_vehicle_journeys_path(@referential), class: 'btn btn-link'
+ = f.submit 'Filtrer', class: 'btn btn-default'
diff --git a/app/views/referential_vehicle_journeys/index.html.slim b/app/views/referential_vehicle_journeys/index.html.slim
new file mode 100644
index 000000000..69e29597c
--- /dev/null
+++ b/app/views/referential_vehicle_journeys/index.html.slim
@@ -0,0 +1,59 @@
+- breadcrumb :referential_vehicle_journeys, @referential
+- content_for :page_header_title, t('.title')
+
+.page_content
+ .container-fluid
+ - if params[:q].present? or @vehicle_journeys.present?
+ .row
+ .col-lg-12
+ = render 'filters'
+
+ - if @vehicle_journeys.present?
+ .row
+ .col-lg-12
+ .select_table
+ = table_builder_2 @vehicle_journeys,
+ [ \
+ TableBuilderHelper::Column.new( \
+ name: t('objectid'), \
+ attribute: Proc.new { |n| n.get_objectid.short_id }, \
+ sortable: false \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :published_journey_name, \
+ attribute: 'published_journey_name', \
+ link_to: lambda do |vehicle_journey| \
+ vehicle_journey.published_journey_name ? referential_line_route_vehicle_journeys_path(@referential, vehicle_journey.route.line, vehicle_journey.route) : '' \
+ end, \
+ sortable: false \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :line, \
+ attribute: Proc.new {|v| v.route.line.name}, \
+ sortable: false \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :route, \
+ attribute: Proc.new {|v| v.route.name}, \
+ sortable: false \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :departure_time, \
+ attribute: Proc.new {|v| v.vehicle_journey_at_stops.first&.departure }, \
+ sortable: false \
+ ), \
+ @filters_stop_areas&.map{|s| table_builder_column_for_stop_area(s)},
+ TableBuilderHelper::Column.new( \
+ key: :arrival_time, \
+ attribute: Proc.new {|v| v.vehicle_journey_at_stops.last&.arrival }, \
+ sortable: false \
+ ), \
+ ].flatten.compact,
+ cls: 'table has-filter has-search'
+
+ = new_pagination @vehicle_journeys, 'pull-right'
+
+ - unless @vehicle_journeys.any?
+ .row.mt-xs
+ .col-lg-12
+ = replacement_msg t('.search_no_results')
diff --git a/app/views/referentials/_filters.html.slim b/app/views/referentials/_filters.html.slim
index c5b6042f0..190e70ebe 100644
--- a/app/views/referentials/_filters.html.slim
+++ b/app/views/referentials/_filters.html.slim
@@ -1,22 +1,22 @@
= search_form_for @q, url: referential_path(@referential.id), class: 'form form-filter' do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :name_or_number_or_objectid_cont)
= f.search_field :name_or_number_or_objectid_cont, class: 'form-control', placeholder: t('.name_or_number_or_objectid')
span.input-group-btn
button.btn.btn-default type='submit'
span.fa.fa-search
.ffg-row
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :transport_mode_eq_any)
= f.label Chouette::Line.human_attribute_name(:transport_mode), required: false, class: 'control-label'
= f.input :transport_mode_eq_any, collection: @referential.lines.pluck(:transport_mode).uniq.compact, as: :check_boxes, label: false, label_method: lambda{|l| ("<span>" + t("enumerize.transport_mode.#{l}") + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }
- .form-group.togglable
- = f.label Chouette::Line.human_attribute_name(:network), required: false, class: 'control-label'
+ .form-group.togglable class=filter_item_class(params[:q], :network_id_eq_any)
+ = f.label t('activerecord.attributes.referential.networks'), required: false, class: 'control-label'
= f.input :network_id_eq_any, collection: LineReferential.first.networks.order('name').pluck(:id), as: :check_boxes, label: false, label_method: lambda{|l| ("<span>#{LineReferential.first.networks.find(l).name}</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }
- .form-group.togglable
- = f.label Chouette::Line.human_attribute_name(:company), required: false, class: 'control-label'
+ .form-group.togglable class=filter_item_class(params[:q], :company_id_eq_any)
+ = f.label t('activerecord.attributes.referential.companies'), required: false, class: 'control-label'
= f.input :company_id_eq_any, collection: LineReferential.first.companies.order('name').pluck(:id), as: :check_boxes, label: false, label_method: lambda{|l| ("<span>#{LineReferential.first.companies.find(l).name}</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }
.actions
diff --git a/app/views/referentials/_form.html.slim b/app/views/referentials/_form.html.slim
index 6f7da84c7..9927f05bd 100644
--- a/app/views/referentials/_form.html.slim
+++ b/app/views/referentials/_form.html.slim
@@ -17,7 +17,7 @@
.row
.col-lg-12
- if @referential.errors.has_key? :metadatas
- .row
+ .row.metadatas-errors
.col-lg-12
.alert.alert-danger
- @referential.errors[:metadatas].each do |msg|
@@ -51,4 +51,8 @@
.hidden = form.input :workbench_id, as: :hidden
- = form.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'referential_form'
+ = form.button :submit,
+ t('actions.submit'),
+ class: 'btn btn-default formSubmitr',
+ data: { disable_with: t('actions.processing') },
+ form: 'referential_form'
diff --git a/app/views/referentials/_overview.html.slim b/app/views/referentials/_overview.html.slim
new file mode 100644
index 000000000..143784800
--- /dev/null
+++ b/app/views/referentials/_overview.html.slim
@@ -0,0 +1,75 @@
+.referential-overview id=overview.pagination_param_name
+ .filters
+ = search_form_for overview.search, as: overview.search_param_name, url: "##{overview.pagination_param_name}", html: {method: :get}, class: 'form form-filter' do |f|
+ .ffg-row
+ .form-group.input-group.search_bar
+ = f.search_field :name_or_number_or_objectid_cont, placeholder: t('lines.index.name_or_number_or_objectid'), class: 'form-control'
+ span.input-group-btn
+ button.btn.btn-default#search-btn type='submit'
+ span.fa.fa-search
+ .form-group.togglable
+ = f.label Chouette::Line.human_attribute_name(:company_id), required: false, class: 'control-label'
+ = f.input :company_id_eq_any, collection: overview.referential_lines.map(&:company).uniq.sort_by(&:name), as: :check_boxes, label: false, label_method: lambda{|l| ("<span>" + l.name + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list'}
+
+ .form-group.togglable
+ = f.label Chouette::Line.human_attribute_name(:transport_mode), required: false, class: 'control-label'
+ = f.input :transport_mode_eq_any, collection: overview.referential_lines.map(&:transport_mode).uniq.sort, as: :check_boxes, label: false, label_method: lambda{|l| ("<span>" + t("enumerize.transport_mode.#{l}") + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list'}
+
+ .actions
+ = link_to 'Effacer', url_for() + "##{overview.pagination_param_name}", class: 'btn btn-link'
+ = f.submit 'Filtrer', class: 'btn btn-default'
+
+ .time-travel
+ .btn-group
+ = link_to I18n.t("referentials.overview.head.prev_page"), '#', class: "prev-page btn btn-default disabled"
+ = link_to I18n.t("referentials.overview.head.today"), '#', class: "today btn btn-default #{overview.includes_today? ? '' : 'disabled'}"
+ = link_to I18n.t("referentials.overview.head.next_page"), '#', class: "next-page btn btn-default"
+ .form-group
+ input.date-search type="date" min=overview.period.first max=overview.period.last
+ a.search-date href='#'
+ span.fa.fa-search
+ .overview-table
+ .left
+ .head
+ .dates= I18n.t("referentials.overview.head.dates")
+ .lines= I18n.t("referentials.overview.head.lines")
+ .lines
+ - overview.lines.each do |line|
+ .line
+ a.number style="background-color: #{line.color.present? ? "##{line.color}" : 'whitesmoke'}" title=line.name
+ = line.number
+ .company= line.company&.name
+ .mode= t("enumerize.transport_mode.#{line.transport_mode}")
+ .right
+ .inner
+ .head
+ - overview.weeks.each do |week|
+ .week
+ .week-span= week.span
+ .week-number= week.number
+ .days
+ - week.days.each do |day|
+ .day style=day.html_style class=day.html_class
+ .name= day.short_name
+ .number= day.number
+ .lines
+ - if overview.lines.any?
+ - overview.lines.each do |line|
+ .line style=line.html_style class=line.html_class
+ - line.periods.each do |period|
+ .period style=period.html_style class=period.html_class
+ .title=period.title
+ - else
+ = replacement_msg t('referential_lines.search_no_results')
+
+ = new_pagination overview, 'pull-right'
+
+- content_for :javascript do
+ = javascript_pack_tag 'referential_overview/overview.js'
+
+ javascript:
+ overview_id = "#{overview.pagination_param_name}";
+
+ coffee:
+ $ =>
+ new ReferentialOverview("##{overview_id}")
diff --git a/app/views/referentials/new.html.slim b/app/views/referentials/new.html.slim
index 2bed9f912..13d58ee71 100644
--- a/app/views/referentials/new.html.slim
+++ b/app/views/referentials/new.html.slim
@@ -1,3 +1,5 @@
+- breadcrumb :referentials
+
.page_content
.container-fluid
.row
diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim
index 9852fb0a3..289e802d7 100644
--- a/app/views/referentials/show.html.slim
+++ b/app/views/referentials/show.html.slim
@@ -1,31 +1,16 @@
- breadcrumb @referential
- page_header_content_for @referential
-- content_for :page_header_actions do
- - unless (@referential.archived? || !policy(@referential).edit?)
- = link_to(t('actions.edit'), edit_referential_path(@referential), class: 'btn btn-default')
-
-- content_for :page_header_content do
- .row.mb-sm
- .col-lg-12.text-right
- - @referential.action_links.each do |link|
- - if link.is_a?(HTMLElement)
- = link.to_html(class: 'btn btn-primary')
- - else
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
.page_content
.container-fluid
.row
.col-lg-6.col-md-6.col-sm-12.col-xs-12
- = definition_list t('metadatas'),
- { t('activerecord.attributes.referential.status') => @referential.archived? ? "<div class='td-block'><span class='fa fa-archive'></span><span>#{t('activerecord.attributes.referential.archived_at')}</span></div>".html_safe : "<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>#{t('activerecord.attributes.referential.archived_at_null')}</span></div>".html_safe,
- @referential.human_attribute_name(:validity_period) => (@referential.validity_period.present? ? t('validity_range', debut: l(@referential.try(:validity_period).try(:begin), format: :short), end: l(@referential.try(:validity_period).try(:end), format: :short)) : '-'),
- @referential.human_attribute_name(:organisation) => @referential.organisation.name,
- @referential.human_attribute_name(:published_at) => '-' }
+ - attributes = {}
+ - attributes[@referential.human_attribute_name(:status)] = @referential.referential_read_only? ? "<div class='td-block'><span class='fa fa-archive'></span><span>#{t('activerecord.attributes.referential.archived_at')}</span></div>".html_safe : "<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>#{t('activerecord.attributes.referential.archived_at_null')}</span></div>".html_safe unless @referential.in_referential_suite?
+ - attributes[@referential.human_attribute_name(:validity_period)] = (@referential.validity_period.present? ? t('validity_range', debut: l(@referential.try(:validity_period).try(:begin), format: :short), end: l(@referential.try(:validity_period).try(:end), format: :short)) : '-')
+ - attributes[@referential.human_attribute_name(:organisation)] = @referential.organisation.name
+ - attributes[@referential.human_attribute_name(:merged_at)] = @referential.merged_at ? l(@referential.merged_at, format: :short) : '-' unless @referential.in_referential_suite?
+ = definition_list t('metadatas'), attributes
- if params[:q].present? or @reflines.any?
.row
@@ -68,11 +53,11 @@
), \
TableBuilderHelper::Column.new( \
key: 'companies.name', \
- attribute: Proc.new { |n| n.try(:company).try(:name) } \
+ attribute: Proc.new { |n| n&.company&.name || "-" } \
) \
],
- links: [:show],
- cls: 'table has-filter has-search'
+ cls: 'table has-filter has-search',
+ action: :index
= new_pagination @reflines, 'pull-right'
@@ -82,6 +67,8 @@
= replacement_msg t('referential_lines.search_no_results')
+ = referential_overview resource
+
/ Modal(s)
= modalbox 'purgeModal' do
= simple_form_for [@referential, CleanUp.new] do |f|
@@ -102,5 +89,5 @@
.modal-footer
button.btn.btn-link type='button' data-dismiss='modal' #{t('cancel')}
- - unless policy(@referential).archived?
+ - unless policy(@referential).referential_read_only?
= f.button :submit, t('actions.clean_up') , class: 'btn btn-primary'
diff --git a/app/views/routes/_form.html.slim b/app/views/routes/_form.html.slim
index 29e5be3d2..81f719437 100644
--- a/app/views/routes/_form.html.slim
+++ b/app/views/routes/_form.html.slim
@@ -27,7 +27,7 @@
// Get JSON data for route stop points
= javascript_tag do
| window.itinerary_stop = "#{URI.escape(route_json_for_edit(@route))}";
- | window.I18n = #{(I18n.backend.send(:translations)[I18n.locale].to_json).html_safe};
+ // | window.I18n = #{(I18n.backend.send(:translations)[I18n.locale].to_json).html_safe};
/ StopPoints Reactux component
= javascript_pack_tag 'routes/edit.js'
diff --git a/app/views/routes/show.html.slim b/app/views/routes/show.html.slim
index 3adf3e2f6..375d7c57b 100644
--- a/app/views/routes/show.html.slim
+++ b/app/views/routes/show.html.slim
@@ -1,18 +1,5 @@
- breadcrumb :route, @referential, @route
- page_header_content_for @route
-- content_for :page_header_actions do
- - if policy(@route).edit?
- = link_to(t('actions.edit'), edit_referential_line_route_path(@referential, @line, @route), class: 'btn btn-default')
-
-- content_for :page_header_content do
- .row.mb-sm
- .col-lg-12.text-right
- - @route.action_links.each do |link|
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
.page_content
.container-fluid
@@ -22,7 +9,8 @@
{ t('objectid') => @route.get_objectid.short_id,
t('activerecord.attributes.route.published_name') => (@route.published_name ? @route.published_name : '-'),
@route.human_attribute_name(:wayback) => (@route.wayback ? @route.wayback_text : '-' ),
- @route.human_attribute_name(:opposite_route) => (@route.opposite_route ? @route.opposite_route.name : '-') }
+ @route.human_attribute_name(:opposite_route) => (@route.opposite_route ? @route.opposite_route.name : '-'),
+ @route.human_attribute_name(:checksum) => @route.checksum }
- if @route_sp.any?
.col-lg-6.col-md-6.col-sm-12.col-xs-12
@@ -40,7 +28,7 @@
), \
TableBuilderHelper::Column.new( \
key: :name, \
- attribute: Proc.new {|s| s.try(:stop_area).try(:name)}, \
+ attribute: Proc.new { |s| content_tag :span, s.stop_area&.name, class: s.stop_area&.area_type }, \
link_to: lambda do |stop_point| \
referential_stop_area_path(@referential, stop_point.stop_area) \
end \
@@ -66,9 +54,9 @@
attribute: Proc.new { |s| t("stop_points.stop_point.for_alighting.#{s.for_alighting}") } \
) \
],
- links: [:show],
sortable: false,
- cls: 'table has-stoppoints'
+ cls: 'table has-stoppoints',
+ action: :index
- else
= replacement_msg t('stop_areas.search_no_results')
diff --git a/app/views/routing_constraint_zones/_filters.html.slim b/app/views/routing_constraint_zones/_filters.html.slim
index 433dde4ab..74e299a8b 100644
--- a/app/views/routing_constraint_zones/_filters.html.slim
+++ b/app/views/routing_constraint_zones/_filters.html.slim
@@ -1,13 +1,13 @@
= search_form_for @q, url: referential_line_routing_constraint_zones_path(@referential, @line), class: 'form form-filter' do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :name_or_objectid_cont)
= f.search_field :name_or_objectid_cont, class: 'form-control', placeholder: "Indiquez un nom d'ITL ou un ID..."
span.input-group-btn
button.btn.btn-default#search-btn type='submit'
span.fa.fa-search
.ffg-row
- .form-group
+ .form-group class=filter_item_class(params[:q], :route_id_eq)
= f.label 'Itinéraire associé', required: false, class: 'control-label'
= f.input :route_id_eq, as: :select, collection: @line.routing_constraint_zones.pluck(:route_id).uniq, label: false, label_method: lambda { |r| @line.routing_constraint_zones.find_by(route_id: r).route_name }, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Indiquez un itinéraire...' }, wrapper_html: { class: 'select2ed'}
diff --git a/app/views/routing_constraint_zones/index.html.slim b/app/views/routing_constraint_zones/index.html.slim
index 7c54fca68..2f67b467e 100644
--- a/app/views/routing_constraint_zones/index.html.slim
+++ b/app/views/routing_constraint_zones/index.html.slim
@@ -1,7 +1,4 @@
- breadcrumb :routing_constraint_zones, @referential, @line
-- content_for :page_header_actions do
- - if (policy(Chouette::RoutingConstraintZone).create? && @referential.organisation == current_organisation)
- = link_to(t('actions.new'), new_referential_line_routing_constraint_zone_path(@referential, @line), class: 'btn btn-primary')
.page_content
.container-fluid
diff --git a/app/views/routing_constraint_zones/show.html.slim b/app/views/routing_constraint_zones/show.html.slim
index 6235ade68..8c8e9b17a 100644
--- a/app/views/routing_constraint_zones/show.html.slim
+++ b/app/views/routing_constraint_zones/show.html.slim
@@ -1,14 +1,5 @@
- breadcrumb :routing_constraint_zone, @referential, @line, @routing_constraint_zone
- page_header_content_for @routing_constraint_zone
-- content_for :page_header_content do
- .row
- .col-lg-12.text-right.mb-sm
- - @routing_constraint_zone.action_links.each do |link|
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
.page_content
.container-fluid
@@ -17,7 +8,8 @@
= definition_list t('metadatas'),
{ @routing_constraint_zone.human_attribute_name(:name) => @routing_constraint_zone.try(:name),
@routing_constraint_zone.human_attribute_name(:route) => link_to(@routing_constraint_zone.try(:route_name), [@referential, @line, @routing_constraint_zone.route]),
- @routing_constraint_zone.human_attribute_name(:line) => link_to(@line.name, [@referential, @line])}
+ @routing_constraint_zone.human_attribute_name(:line) => link_to(@line.name, [@referential, @line]),
+ @routing_constraint_zone.human_attribute_name(:checksum) => @routing_constraint_zone.checksum}
.row
.col-lg-12
diff --git a/app/views/shared/_development_toolbar.html.slim b/app/views/shared/_development_toolbar.html.slim
new file mode 100644
index 000000000..aafd37885
--- /dev/null
+++ b/app/views/shared/_development_toolbar.html.slim
@@ -0,0 +1,53 @@
+- if Rails.application.config.development_toolbar
+ = modalbox 'development-toolbar' do
+ = form_tag development_toolbar_update_settings_path, authenticity_token: true do
+ .modal-header
+ h3= "Toolbar"
+
+ .inner
+ .col.features
+ h4
+ = "Features"
+ .toggles
+ = link_to 'all', '#', data: {mask: 'features', val: true}
+ = link_to 'none', '#', data: {mask: 'features', val: false}
+ ul
+ - Rails.application.config.development_toolbar.available_features.sort.each do |feature|
+ li
+ = hidden_field_tag "features[#{feature}]", false, id: ""
+ = check_box_tag "features[#{feature}]", true, has_feature?(feature)
+ = label :features, feature
+ - if Rails.application.config.development_toolbar.features_doc_url
+ = link_to "#{Rails.application.config.development_toolbar.features_doc_url}##{feature}", target: :blank do
+ .fa.fa-question-circle
+ .col.permissions
+ h4
+ = "Permissions"
+ .toggles
+ = link_to 'all', '#', data: {mask: 'permissions', val: true}
+ = link_to 'none', '#', data: {mask: 'permissions', val: false}
+ - model = ""
+ - Rails.application.config.development_toolbar.available_permissions.sort.each do |permission|
+ - if permission.split('.').first != model
+ - model = permission.split('.').first
+ </ul>
+ h5
+ = model
+ .toggles
+ = link_to 'all', '#', data: {mask: "permissions[#{model}", val: true}
+ = link_to 'none', '#', data: {mask: "permissions[#{model}", val: false}
+ <ul>
+ li
+ = hidden_field_tag "permissions[#{permission}]", false, id: ""
+ = check_box_tag "permissions[#{permission}]", true, current_user.has_permission?(permission)
+ = label :permissions, permission, permission.split('.').last
+ .modal-footer
+ button.btn.btn-link type='button' data-dismiss='modal' #{t('cancel')}
+ = submit_tag t("actions.submit"), class: 'btn btn-primary'
+
+ - content_for :javascript do
+ coffee:
+ $('#development-toolbar .toggles a').click (e)->
+ $('#development-toolbar').find("[name^=\"#{e.currentTarget.dataset.mask}\"]").attr "checked", e.currentTarget.dataset.val == 'true'
+ e.preventDefault()
+ false
diff --git a/app/views/stif/dashboards/_dashboard.html.slim b/app/views/stif/dashboards/_dashboard.html.slim
index f3cd01f46..c28696a94 100644
--- a/app/views/stif/dashboards/_dashboard.html.slim
+++ b/app/views/stif/dashboards/_dashboard.html.slim
@@ -56,17 +56,16 @@
.panel.panel-default
.panel-heading
h3.panel-title.with_actions
- div
- = t('.calendars')
- span.badge.ml-xs = @dashboard.calendars.count if @dashboard.calendars.present?
+ = I18n.t("calendars.index.title")
+ span.badge.ml-xs = @dashboard.calendars.count if @dashboard.calendars.present?
div
- = link_to '', calendars_path, class: ' fa fa-chevron-right pull-right', title: t('.see')
+ = link_to '', workgroup_calendars_path(current_workgroup), class: ' fa fa-chevron-right pull-right', title: t('.see')
- if @dashboard.calendars.present?
.list-group
- @dashboard.calendars.first(5).each_with_index do |calendar, i|
- = link_to calendar.name, calendar_path(calendar), class: 'list-group-item' if i < 6
+ = link_to calendar.name, workgroup_calendar_path(current_workgroup, calendar), class: 'list-group-item' if i < 6
- else
.panel-body
diff --git a/app/views/stop_area_referentials/show.html.slim b/app/views/stop_area_referentials/show.html.slim
index d43333fd9..911006c39 100644
--- a/app/views/stop_area_referentials/show.html.slim
+++ b/app/views/stop_area_referentials/show.html.slim
@@ -1,13 +1,14 @@
- breadcrumb :stop_area_referential, @stop_area_referential
-- content_for :page_header_actions do
- = link_to(t('actions.sync'), sync_stop_area_referential_path(@stop_area_referential), method: :post, class: 'btn btn-default')
+- if policy(@stop_area_referential).synchronize?
+ - content_for :page_header_actions do
+ = link_to(t('actions.sync'), sync_stop_area_referential_path(@stop_area_referential), method: :post, class: 'btn btn-default')
- content_for :page_header_content do
.row.mb-md
.col-lg-12.text-right
= link_to stop_area_referential_stop_areas_path(@stop_area_referential), class: 'btn btn-primary' do
= Referential.human_attribute_name(:stop_areas)
- em.small = " (#{@stop_area_referential.stop_areas.size})"
+ em.small = " (#{@stop_area_referential.stop_areas.count})"
- page_header_content_for @stop_area_referential
.page_content
diff --git a/app/views/stop_areas/_filters.html.slim b/app/views/stop_areas/_filters.html.slim
index 3b99f377c..00369d3ed 100644
--- a/app/views/stop_areas/_filters.html.slim
+++ b/app/views/stop_areas/_filters.html.slim
@@ -1,18 +1,18 @@
= search_form_for @q, url: stop_area_referential_stop_areas_path(@stop_area_referential), html: {method: :get}, class: 'form form-filter' do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :name_or_objectid_cont)
= f.search_field :name_or_objectid_cont, placeholder: t('.name_or_objectid'), class: 'form-control'
span.input-group-btn
button.btn.btn-default#search-btn type='submit'
span.fa.fa-search
.ffg-row
- = f.input :zip_code_cont, placeholder: t('.zip_code'), label: Chouette::StopArea.human_attribute_name(:zip_code), required: false
- = f.input :city_name_cont, placeholder: t('.city_name'), label: Chouette::StopArea.human_attribute_name(:city_name), required: false
+ = f.input :zip_code_cont, placeholder: t('.zip_code'), label: Chouette::StopArea.human_attribute_name(:zip_code), required: false, wrapper_html: {class: filter_item_class(params[:q], :zip_code_cont)}
+ = f.input :city_name_cont, placeholder: t('.city_name'), label: Chouette::StopArea.human_attribute_name(:city_name), required: false, wrapper_html: {class: filter_item_class(params[:q], :city_name_cont)}
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :area_type_eq_any)
= f.label Chouette::StopArea.human_attribute_name(:area_type), required: false, class: 'control-label'
- = f.input :area_type_eq_any, collection: Chouette::StopArea.area_type.options.sort, as: :check_boxes, label: false, label_method: lambda{|w| ("<span>" + t("enumerize.stop_area.area_type.#{w[1]}") + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }
+ = f.input :area_type_eq_any, checked: params[:q] && params[:q][:area_type_eq_any], collection: Chouette::AreaType.options, as: :check_boxes, label: false, label_method: lambda{|w| ("<span>" + w[0] + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }
.actions
= link_to 'Effacer', @workbench, class: 'btn btn-link'
diff --git a/app/views/stop_areas/_form.html.slim b/app/views/stop_areas/_form.html.slim
index 20c7c0468..bb1fbe1e9 100644
--- a/app/views/stop_areas/_form.html.slim
+++ b/app/views/stop_areas/_form.html.slim
@@ -6,7 +6,26 @@
/= @map.to_html
= f.input :id, as: :hidden
= f.input :name, :input_html => {:title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.name")}
- = f.input :area_type, as: :select, :input_html => {:disabled => !@stop_area.new_record?}, :collection => Chouette::StopArea.area_type.options, :include_blank => false
+ - if has_feature?(:stop_area_localized_names)
+ .form-group
+ .col-sm-3.col-xs-5
+ .col-sm-9.col-xs-7
+ - f.object.localized_names.each do |k, v|
+ .col-md-6= f.input "localized_names[#{k}]", input_html: {value: v}, label: label_for_country(k)
+
+ = f.input :kind,
+ as: :radio_buttons,
+ checked: @stop_area.new_record? ? :commercial : @stop_area.kind,
+ input_html: { disabled: !@stop_area.new_record? },
+ include_blank: false,
+ item_wrapper_class: 'radio-inline',
+ wrapper: :horizontal_form,
+ disabled: !@stop_area.new_record?
+ .slave data-master="[name='stop_area[kind]']" data-value="commercial"
+ = f.input :parent_id, as: :select, :collection => [f.object.parent_id], input_html: { data: { select2_ajax: 'true', url: autocomplete_stop_area_referential_stop_areas_path(@stop_area_referential), initvalue: {id: f.object.parent_id, text: f.object.parent.try(:full_name)}}}
+ - %i(non_commercial commercial).each do |kind|
+ .slave data-master="[name='stop_area[kind]']" data-value=kind
+ = f.input :area_type, as: :select, :input_html => {id: kind, :disabled => !@stop_area.new_record?}, :collection => Chouette::AreaType.options(kind), :include_blank => false, disabled: !@stop_area.new_record?
.location_info
h3 = t("stop_areas.stop_area.localisation")
@@ -17,15 +36,18 @@
- unless @stop_area.projection.blank? or @stop_area.projection_type_label.empty?
= f.input :projection_xy, :label => t("activerecord.attributes.stop_area.projection_xy", :projection => @referential.projection_type_label), :input_html => {:title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.projection_xy")}
- = f.input :coordinates, :input_html => {:title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.coordinates")}, required: true
+ = f.input :coordinates, :input_html => {:title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.coordinates")}
= f.input :street_name
- /= f.input :country_code, required: format_restriction_for_locales(@referential) == '.hub'
= f.input :zip_code, :input_html => {:title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.zip_code")}
= f.input :city_name, required: format_restriction_for_locales(@referential) == '.hub', :input_html => {:title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.city_name")}
+ = f.input :country_code, as: :country, priority: ['FR', 'GB', 'DE', 'ES'], :include_blank => true
.stop_areas.stop_area.general_info
h3 = t("stop_areas.stop_area.general")
+ - if has_feature?(:stop_area_waiting_time)
+ = f.input :waiting_time, input_html: { min: 0 }
+
= f.input :registration_number, required: format_restriction_for_locales(@referential) == '.hub', :input_html => {:title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.registration_number")}
= f.input :fare_code
= f.input :nearest_topic_name, :input_html => {:title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.nearest_topic_name")}
@@ -43,3 +65,5 @@
.separator
= f.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'stop_area_form'
+
+= javascript_pack_tag "stop_areas/new"
diff --git a/app/views/stop_areas/autocomplete.rabl b/app/views/stop_areas/autocomplete.rabl
new file mode 100644
index 000000000..a5f0bd5ec
--- /dev/null
+++ b/app/views/stop_areas/autocomplete.rabl
@@ -0,0 +1,24 @@
+collection @stop_areas
+
+node do |stop_area|
+ {
+ :id => stop_area.id,
+ :registration_number => stop_area.registration_number || "",
+ :short_registration_number => truncate(stop_area.registration_number, :length => 10) || "",
+ :name => stop_area.name || "",
+ :short_name => truncate(stop_area.name, :length => 30) || "",
+ :zip_code => stop_area.zip_code || "",
+ :city_name => stop_area.city_name || "",
+ :short_city_name => truncate(stop_area.city_name, :length => 15) || "",
+ :user_objectid => stop_area.user_objectid,
+ :longitude => stop_area.longitude,
+ :latitude => stop_area.latitude,
+ :area_type => stop_area.area_type,
+ :comment => stop_area.comment,
+ :text => "<span class='small label label-info'>#{I18n.t("area_types.label.#{stop_area.area_type}")}</span>#{stop_area.full_name}"
+ }
+end
+
+node(:stop_area_path) { |stop_area|
+ stop_area_picture_url(stop_area) || ""
+}
diff --git a/app/views/stop_areas/index.html.slim b/app/views/stop_areas/index.html.slim
index c4d880081..71c7f995c 100644
--- a/app/views/stop_areas/index.html.slim
+++ b/app/views/stop_areas/index.html.slim
@@ -1,7 +1,4 @@
- breadcrumb :stop_areas, @stop_area_referential
-- content_for :page_header_actions do
- - if policy(Chouette::StopArea).create?
- = link_to(t('stop_areas.actions.new'), new_stop_area_referential_stop_area_path(@stop_area_referential), class: 'btn btn-primary')
.page_content
.container-fluid
@@ -24,7 +21,7 @@
key: :name, \
attribute: 'name', \
link_to: lambda do |stop_area| \
- referential_stop_area_path( \
+ stop_area_referential_stop_area_path( \
@stop_area_referential, \
stop_area \
) \
@@ -48,10 +45,9 @@
), \
TableBuilderHelper::Column.new( \
key: :area_type, \
- attribute: Proc.new { |s| (s.area_type.nil? ? '-' : t("enumerize.stop_area.area_type.#{s.try(:area_type)}")) } \
+ attribute: Proc.new { |s| Chouette::AreaType.find(s.area_type).try :label } \
), \
],
- links: [:show, :edit, :delete],
cls: 'table has-filter has-search'
= new_pagination @stop_areas, 'pull-right'
diff --git a/app/views/stop_areas/show.html.slim b/app/views/stop_areas/show.html.slim
index af673bb25..a4e14a272 100644
--- a/app/views/stop_areas/show.html.slim
+++ b/app/views/stop_areas/show.html.slim
@@ -1,26 +1,26 @@
- breadcrumb :stop_area, @stop_area_referential, @stop_area
- page_header_content_for @stop_area
-- content_for :page_header_content do
- .row
- .col-lg-12.text-right.mb-sm
- - @stop_area.action_links.each do |link|
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
/ PageContent
.page_content
.container-fluid
.row
.col-lg-6.col-md-6.col-sm-12.col-xs-12
- = definition_list t('metadatas'),
- { t('id_reflex') => @stop_area.get_objectid.short_id,
- @stop_area.human_attribute_name(:stop_area_type) => t("area_types.label.#{@stop_area.stop_area_type}"),
+ - attributes = { t('id_reflex') => @stop_area.get_objectid.short_id }
+
+ - if has_feature?(:stop_area_localized_names)
+ - @stop_area.localized_names.each do |k, v|
+ - attributes.merge!({label_for_country(k, @stop_area.human_attribute_name(:name)) => v }) if v.present?
+ - attributes.merge!({ @stop_area.human_attribute_name(:parent) => @stop_area.parent ? link_to(@stop_area.parent.name, stop_area_referential_stop_area_path(@stop_area_referential, @stop_area.parent)) : "-" }) if @stop_area.commercial?
+ - attributes.merge!({ @stop_area.human_attribute_name(:stop_area_type) => Chouette::AreaType.find(@stop_area.area_type).try(:label),
@stop_area.human_attribute_name(:registration_number) => @stop_area.registration_number,
- 'Coordonnées' => geo_data(@stop_area, @stop_area_referential),
+ })
+ - attributes.merge!(@stop_area.human_attribute_name(:waiting_time) => @stop_area.waiting_time_text) if has_feature?(:stop_area_waiting_time)
+ - attributes.merge!({ "Coordonnées" => geo_data(@stop_area, @stop_area_referential),
@stop_area.human_attribute_name(:zip_code) => @stop_area.zip_code,
@stop_area.human_attribute_name(:city_name) => @stop_area.city_name,
+ @stop_area.human_attribute_name(:country_code) => @stop_area.country_code.presence || '-',
'Etat' => (@stop_area.deleted_at ? 'Supprimé' : 'Actif'),
- @stop_area.human_attribute_name(:comment) => @stop_area.try(:comment) }
+ @stop_area.human_attribute_name(:comment) => @stop_area.try(:comment),
+ })
+ = definition_list t('metadatas'), attributes
diff --git a/app/views/stop_points/_stop_point.html.slim b/app/views/stop_points/_stop_point.html.slim
index ca86e339a..e54158cef 100644
--- a/app/views/stop_points/_stop_point.html.slim
+++ b/app/views/stop_points/_stop_point.html.slim
@@ -5,7 +5,7 @@
= link_to [@referential, stop_point.stop_area], class: "preview", title: "#{Chouette::StopArea.model_name.human.capitalize} #{stop_point.stop_area.name}" do
span.name
span.label.label-primary = stop_point.position + 1
- = image_tag "map/" + stop_point.stop_area.stop_area_type + ".png"
+ = image_tag "map/" + stop_point.stop_area.area_type + ".png"
= truncate(stop_point.stop_area.name, length: 20)
.panel-body
@@ -27,4 +27,4 @@
= t(".no_object")
- else
- stop_point.stop_area.lines.each do |line|
- span.label.label-default.line = line.number || truncate( line.name, length: 4 ) \ No newline at end of file
+ span.label.label-default.line = line.number || truncate( line.name, length: 4 )
diff --git a/app/views/time_tables/_filter.html.slim b/app/views/time_tables/_filter.html.slim
index 11e9987c4..030036a13 100644
--- a/app/views/time_tables/_filter.html.slim
+++ b/app/views/time_tables/_filter.html.slim
@@ -1,17 +1,17 @@
= search_form_for @q, url: referential_time_tables_path(@referential), html: { method: :get, class: 'form form-filter' } do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :comment_cont)
= f.text_field :comment_cont, :placeholder => "#{t('time_tables.index.comment')}", class: 'form-control'
span.input-group-btn
button.btn.btn-default type='submit'
span.fa.fa-search
.ffg-row
- .form-group
+ .form-group class=filter_item_class(params[:q], :tag_search)
= f.label Chouette::TimeTable.human_attribute_name(:tag_search), required: false, class: 'control-label'
= f.input :tag_search, as: :tags, collection: Chouette::TimeTable.tags_on(:tags).pluck(:name), label: false, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Indiquez une étiquette...' }, wrapper_html: { class: 'select2ed'}, include_blank: false, selected: params[:q] ? params[:q]['tag_search'] : nil
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :bounding_dates)
= f.label Chouette::TimeTable.human_attribute_name(:bounding_dates), required: false, class: 'control-label'
.filter_menu
= f.simple_fields_for :bounding_dates do |p|
diff --git a/app/views/time_tables/_form.html.slim b/app/views/time_tables/_form.html.slim
index d06fdf444..007044e65 100644
--- a/app/views/time_tables/_form.html.slim
+++ b/app/views/time_tables/_form.html.slim
@@ -5,7 +5,7 @@
= form.input :comment, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.time_table.comment")}
- if @time_table.new_record? && !@time_table.created_from
- = form.input :calendar_id, as: :select, input_html: { class: 'tt_target', style: "width: 100%", data: { 'select2-ajax': 'true', 'select2ed-placeholder': 'Indiquez un modèle de calendrier...', term: 'name_cont', url: autocomplete_calendars_path}}
+ = form.input :calendar_id, as: :select, input_html: { class: 'tt_target', style: "width: 100%", data: { 'select2-ajax': 'true', 'select2ed-placeholder': 'Indiquez un modèle de calendrier...', term: 'name_cont', url: autocomplete_workgroup_calendars_path(current_workgroup)}}
- if @time_table.created_from
= form.input :created_from, disabled: true, input_html: { value: @time_table.created_from.comment }
diff --git a/app/views/time_tables/_show_time_table.html.slim b/app/views/time_tables/_show_time_table.html.slim
index ebfe9d283..102dbfad7 100644
--- a/app/views/time_tables/_show_time_table.html.slim
+++ b/app/views/time_tables/_show_time_table.html.slim
@@ -2,24 +2,10 @@
- (1..12).each do |month|
.col-lg-3.col-md-4.col-sm-4.col-xs-6
= new_alt_calendar(year: @year, month: month, first_day_of_week: 1, calendar_title: "#{I18n.t("date.month_names")[month]}", show_today: false) do |d|
- / - if @time_table.excluded_date?(d)
- / - [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {class: "day excluded_date"}]
- - if @time_table.include_in_overlap_dates?(d)
- - [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {class: "day overlaped_date", title: 'Voir'}]
- - elsif @time_table.include_in_dates?(d)
- - [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {class: "day selected_date", title: 'Voir'}]
- - elsif @time_table.include_in_periods?(d)
- - [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {class: "day selected_period", title: 'Voir'}]
-
-/ .row
-/ .col-lg-12
-/ / wip
-/ - if @time_table.dates.where("in_out = true").present?
-/ h3.time_table_dates = @time_table.human_attribute_name("dates")
-/ .dates.content
-/ == render "time_tables/dates"
-/
-/ - if @time_table.dates.where("in_out = false").present?
-/ h3.time_table_dates = @time_table.human_attribute_name("excluded_dates")
-/ .excluded_dates.content
-/ == render "time_tables/excluded_dates"
+ - edit_url = [:edit, @referential, time_table].compact
+ - if time_table.include_in_overlap_dates?(d)
+ - [link_to(d.mday, edit_url), {class: "day overlaped_date", title: 'Voir'}]
+ - elsif time_table.include_in_dates?(d)
+ - [link_to(d.mday, edit_url), {class: "day selected_date", title: 'Voir'}]
+ - elsif time_table.include_in_periods?(d)
+ - [link_to(d.mday, edit_url), {class: "day selected_period", title: 'Voir'}]
diff --git a/app/views/time_tables/edit.html.slim b/app/views/time_tables/edit.html.slim
index e1c566ff4..d8cffb1b0 100644
--- a/app/views/time_tables/edit.html.slim
+++ b/app/views/time_tables/edit.html.slim
@@ -8,6 +8,6 @@
= javascript_tag do
| window.actionType = "#{raw params[:action]}";
- | window.I18n = #{(I18n.backend.send(:translations)[I18n.locale].to_json).html_safe};
+ // | window.I18n = #{(I18n.backend.send(:translations)[I18n.locale].to_json).html_safe};
= javascript_pack_tag 'time_tables/edit.js'
diff --git a/app/views/time_tables/index.html.slim b/app/views/time_tables/index.html.slim
index b684b0bcb..6913712a0 100644
--- a/app/views/time_tables/index.html.slim
+++ b/app/views/time_tables/index.html.slim
@@ -1,7 +1,4 @@
- breadcrumb :time_tables, @referential
-- content_for :page_header_actions do
- - if (policy(Chouette::TimeTable).create? && @referential.organisation == current_organisation)
- = link_to(t('actions.add'), new_referential_time_table_path(@referential), class: 'btn btn-default')
.page_content
.container-fluid
@@ -54,7 +51,6 @@
attribute: Proc.new { |tt| l(tt.updated_at, format: :short) } \
) \
],
- links: [:show, :edit],
cls: 'table has-search'
= new_pagination @time_tables, 'pull-right'
@@ -65,6 +61,6 @@
= replacement_msg t('time_tables.search_no_results')
= javascript_tag do
- | window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe};
+ // | window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe};
= javascript_pack_tag 'date_filters'
diff --git a/app/views/time_tables/show.html.slim b/app/views/time_tables/show.html.slim
index 036581268..e038b73ca 100644
--- a/app/views/time_tables/show.html.slim
+++ b/app/views/time_tables/show.html.slim
@@ -4,21 +4,6 @@
- content_for :page_header_title, t('time_tables.show.title', name: @time_table.comment), flush: true
-- content_for :page_header_actions do
- - if policy(@time_table).edit?
- = link_to(t('actions.edit'), edit_referential_time_table_path(@referential, @time_table), class: 'btn btn-default')
-
-- content_for :page_header_content do
- .row.mb-sm
- .col-lg-12.text-right
- - @time_table.action_links.each do |link|
- = link_to link.href,
- method: link.method,
- data: link.data,
- class: 'btn btn-primary' do
- = link.content
-
-
.page_content
.container-fluid
.row
@@ -28,7 +13,8 @@
'Couleur associée' => (@time_table.color.nil? ? '-' : content_tag(:span, '', class: 'fa fa-circle', style: "color:#{@time_table.try(:color)}")),
'Etiquettes' => @time_table.tag_list,
'Modèle de calendrier' => (@time_table.calendar ? link_to(@time_table.calendar.name, @time_table.calendar) : '-'),
- "Journées d'application pour les périodes ci-dessous" => %w(monday tuesday wednesday thursday friday saturday sunday).collect{ |d| content_tag(:span, t("calendars.days.#{d}"), class: "label label-default #{@time_table.send(d) ? '' : 'disabled'}") }.join.html_safe }
+ "Journées d'application pour les périodes ci-dessous" => %w(monday tuesday wednesday thursday friday saturday sunday).collect{ |d| content_tag(:span, t("calendars.days.#{d}"), class: "label label-default #{@time_table.send(d) ? '' : 'disabled'}") }.join.html_safe,
+ Chouette::TimeTable.human_attribute_name(:checksum) => @time_table.checksum}
.row
.col-lg-12.mb-sm
@@ -38,4 +24,4 @@
= link_to '', referential_time_table_path(@referential, @time_table, year: (@year - 1)), class: 'previous_page'
= link_to '', referential_time_table_path(@referential, @time_table, year: (@year + 1)), class: 'next_page'
- = render 'show_time_table'
+ = render 'show_time_table', time_table: @time_table
diff --git a/app/views/vehicle_journeys/index.html.slim b/app/views/vehicle_journeys/index.html.slim
index 52c1a9728..d53d8b50c 100644
--- a/app/views/vehicle_journeys/index.html.slim
+++ b/app/views/vehicle_journeys/index.html.slim
@@ -1,5 +1,11 @@
- breadcrumb :vehicle_journeys, @referential, @route
- content_for :page_header_title, t('vehicle_journeys.index.title', route: @route.name)
+- if @route.opposite_route.present?
+ - content_for :page_header_content do
+ .row.mb-sm
+ .col-lg-12.text-right
+ = link_to(t('routes.actions.opposite_route_timetable'), [@referential, @route.line, @route.opposite_route, :vehicle_journeys], class: 'btn btn-primary sticky-action')
+
.page_content
.container-fluid
@@ -11,7 +17,8 @@
= javascript_tag do
| window.route_id = #{params[:route_id]};
| window.stopPoints = #{(@stop_points_list.to_json).html_safe};
- | window.jpOrigin = #{(@jp_origin.to_json).html_safe};
+ | window.returnStopPoints = #{(@return_stop_points_list.to_json).html_safe};
+ | window.jpOrigin = #{(@jp_origin.present? ? @jp_origin.attributes.update({full_schedule: @jp_origin.full_schedule?}).to_json : "null").html_safe};
| window.jpOriginStopPoints = #{(@jp_origin_stop_points.to_json).html_safe};
| window.transportMode = #{(@transport_mode.to_json).html_safe};
| window.transportSubmode = #{(@transport_submode.to_json).html_safe};
@@ -19,6 +26,14 @@
| window.vehicleJourneysPerPage = #{@ppage};
| window.line_footnotes = #{raw @footnotes};
| window.perms = #{raw @perms};
- | window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe};
+ | window.features = #{raw @features};
+ | window.all_missions = #{(@all_missions.to_json).html_safe};
+ | window.custom_fields = #{(@custom_fields.to_json).html_safe};
+ // | window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe};
+
+- if has_feature?(:vehicle_journeys_return_route)
+ = javascript_tag do
+ | window.returnRouteUrl = "#{(@route.opposite_route && url_for([@referential, @route.line, @route.opposite_route, :vehicle_journeys]) || "").html_safe}";
+
= javascript_pack_tag 'vehicle_journeys/index.js'
diff --git a/app/views/vehicle_journeys/show.rabl b/app/views/vehicle_journeys/show.rabl
index 830dee8bd..546c851a4 100644
--- a/app/views/vehicle_journeys/show.rabl
+++ b/app/views/vehicle_journeys/show.rabl
@@ -1,6 +1,6 @@
object @vehicle_journey
-[:objectid, :published_journey_name, :published_journey_identifier, :company_id].each do |attr|
+[:objectid, :published_journey_name, :published_journey_identifier, :company_id, :comment, :checksum, :custom_fields].each do |attr|
attributes attr, :unless => lambda { |m| m.send( attr).nil?}
end
@@ -28,13 +28,22 @@ child(:time_tables, :object_root => false) do |time_tables|
end
end
+if has_feature? :purchase_windows
+ child(:purchase_windows, :object_root => false) do |purchase_windows|
+ attributes :id, :objectid, :name, :color
+ end
+end
+
child :footnotes, :object_root => false do |footnotes|
attributes :id, :code, :label
end
child(:vehicle_journey_at_stops_matrix, :object_root => false) do |vehicle_stops|
+ attributes :id, :connecting_service_id, :boarding_alighting_possibility
node do |vehicle_stop|
+
node(:dummy) { vehicle_stop.dummy }
+ node(:area_kind) { vehicle_stop.stop_point.stop_area.kind }
node(:stop_area_object_id) do
vehicle_stop.stop_point.stop_area.objectid
@@ -49,15 +58,11 @@ child(:vehicle_journey_at_stops_matrix, :object_root => false) do |vehicle_stops
vehicle_stop.stop_point.stop_area.city_name
end
- [:id, :connecting_service_id, :boarding_alighting_possibility].map do |att|
- node(att) { vehicle_stop.send(att) ? vehicle_stop.send(att) : nil }
- end
-
- [:arrival_time, :departure_time].map do |att|
- node(att) do |vs|
+ [:arrival, :departure].each do |att|
+ node("#{att}_time") do |vs|
{
- hour: vs.send(att).try(:strftime, '%H'),
- minute: vs.send(att).try(:strftime, '%M')
+ hour: vs.send("#{att}_local_time").try(:strftime, '%H'),
+ minute: vs.send("#{att}_local_time").try(:strftime, '%M')
}
end
end
diff --git a/app/views/workbench_outputs/show.html.slim b/app/views/workbench_outputs/show.html.slim
new file mode 100644
index 000000000..a9e106dbb
--- /dev/null
+++ b/app/views/workbench_outputs/show.html.slim
@@ -0,0 +1,40 @@
+/ PageHeader
+
+- breadcrumb :workbench_output, @workbench
+- content_for :page_header_title, t('.title')
+- content_for :page_header_content do
+ .row.mb-sm
+ .col-lg-12.text-right
+ = link_to t('.see_current_output'), referential_path(@workbench.output.current), class: 'btn btn-primary' if @workbench.output&.current
+ = link_to t('merges.actions.create'), new_workbench_merge_path(@workbench), class: 'btn btn-primary'
+
+.page_content
+ .container-fluid
+ .row
+ .col-lg-12
+ = table_builder_2 @workbench_merges,
+ [ \
+ TableBuilderHelper::Column.new( \
+ key: :status, \
+ attribute: Proc.new { |n| import_status(n.status) }, \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :name, \
+ attribute: 'full_names', \
+ link_to: lambda do |merge| \
+ workbench_merge_path merge.workbench, merge \
+ end \
+ ), \
+ TableBuilderHelper::Column.new( \
+ name: t(".table_headers.ended_at"), \
+ attribute: Proc.new { |n| l(n.ended_at, format: :long) if n.ended_at }, \
+ ), \
+ TableBuilderHelper::Column.new( \
+ key: :creator, \
+ attribute: 'creator' \
+ ) \
+ ],
+ links: [],
+ cls: 'table has-search'
+
+ = new_pagination @workbench_merges, 'pull-right'
diff --git a/app/views/workbenches/_filters.html.slim b/app/views/workbenches/_filters.html.slim
index 4d9e0066c..c9dd13d96 100644
--- a/app/views/workbenches/_filters.html.slim
+++ b/app/views/workbenches/_filters.html.slim
@@ -1,27 +1,33 @@
= search_form_for @q_for_form, url: workbench_path(@workbench.id), builder: SimpleForm::FormBuilder, class: 'form form-filter' do |f|
.ffg-row
- .input-group.search_bar
+ .input-group.search_bar class=filter_item_class(params[:q], :name_cont)
= f.search_field :name_cont, class: 'form-control', placeholder: t('referentials.filters.name')
span.input-group-btn
button.btn.btn-default type='submit'
span.fa.fa-search
.ffg-row
- .form-group
+ .form-group class=filter_item_class(params[:q], :associated_lines_id_eq)
= f.label t('activerecord.models.line.one').upcase, required: false, class: 'control-label'
= f.input :associated_lines_id_eq, as: :select, collection: @workbench.lines.includes(:company).order(:name), input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': t('referentials.filters.line') }, label: false, label_method: :display_name, wrapper_html: { class: 'select2ed'}
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :archived_at_not_null)
= f.label Referential.human_attribute_name(:status), required: false, class: 'control-label'
.form-group.checkbox_list
= f.input :archived_at_not_null, label: ("<span>#{t('activerecord.attributes.referential.archived_at')}<span class='fa fa-archive'></span></span>").html_safe, as: :boolean, wrapper_html: { class: 'checkbox-wrapper' }
= f.input :archived_at_null, label: ("<span>#{t('activerecord.attributes.referential.archived_at_null')}<span class='sb sb-lg sb-preparing'></span></span>").html_safe, as: :boolean, wrapper_html: { class: 'checkbox-wrapper' }
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :organisation_name_eq_any)
= f.label t('activerecord.models.organisation.one'), required: false, class: 'control-label'
- = f.input :organisation_name_eq_any, collection: Organisation.order('name').pluck(:name), as: :check_boxes, label: false, label_method: lambda{|w| ("<span>#{w}</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }
+ = f.input :organisation_name_eq_any,
+ collection: @workbench.workgroup.organisations.order('name').pluck(:name),
+ as: :check_boxes,
+ label: false,
+ label_method: lambda { |w| ("<span>#{w}</span>").html_safe },
+ required: false,
+ wrapper_html: { class: 'checkbox_list' }
- .form-group.togglable
+ .form-group.togglable class=filter_item_class(params[:q], :validity_period)
= f.label Referential.human_attribute_name(:validity_period), required: false, class: 'control-label'
.filter_menu
= f.simple_fields_for :validity_period do |p|
diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim
index af312fc08..aae34c51b 100644
--- a/app/views/workbenches/show.html.slim
+++ b/app/views/workbenches/show.html.slim
@@ -6,6 +6,7 @@
- if policy(Referential).create?
= link_to t('actions.import'), workbench_imports_path(@workbench), class: 'btn btn-primary'
= link_to t('actions.add'), new_referential_path(workbench_id: @workbench), class: 'btn btn-primary'
+ = link_to t('workbenches.actions.show_output'), workbench_output_path(@workbench), class: 'btn btn-primary'
.page_content
.container-fluid
@@ -29,7 +30,7 @@
), \
TableBuilderHelper::Column.new( \
key: :status, \
- attribute: Proc.new {|w| w.archived? ? ("<div class='td-block'><span class='fa fa-archive'></span><span>#{t('activerecord.attributes.referential.archived_at')}</span></div>").html_safe : ("<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>#{t('activerecord.attributes.referential.archived_at_null')}</span></div>").html_safe} \
+ attribute: Proc.new {|w| w.referential_read_only? ? ("<div class='td-block'><span class='fa fa-archive'></span><span>#{t('activerecord.attributes.referential.archived_at')}</span></div>").html_safe : ("<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>#{t('activerecord.attributes.referential.archived_at_null')}</span></div>").html_safe} \
), \
TableBuilderHelper::Column.new( \
key: :organisation, \
@@ -53,13 +54,13 @@
attribute: Proc.new {|w| l(w.updated_at, format: :short)} \
), \
TableBuilderHelper::Column.new( \
- key: :published_at, \
- attribute: '' \
+ key: :merged_at, \
+ attribute: Proc.new {|w| w.merged_at ? l(w.merged_at, format: :short) : '-'} \
) \
],
- selectable: true,
- links: [:show, :edit],
- cls: 'table has-filter has-search'
+ selectable: ->(ref){ @workbench.referentials.include?(ref) },
+ cls: 'table has-filter has-search',
+ action: :index
= multiple_selection_toolbox([:delete], collection_name: 'referentials')
@@ -71,6 +72,6 @@
= replacement_msg t('referentials.search_no_results')
= javascript_tag do
- | window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe};
+ // | window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe};
= javascript_pack_tag 'date_filters'
diff --git a/app/workers/clean_up_worker.rb b/app/workers/clean_up_worker.rb
index 2d76b3a68..9a7c3aa5a 100644
--- a/app/workers/clean_up_worker.rb
+++ b/app/workers/clean_up_worker.rb
@@ -1,6 +1,5 @@
class CleanUpWorker
include Sidekiq::Worker
- sidekiq_options :retry => false
def perform(id)
cleaner = CleanUp.find id
diff --git a/app/workers/line_referential_sync_worker.rb b/app/workers/line_referential_sync_worker.rb
index 253b8a53c..1303a63fd 100644
--- a/app/workers/line_referential_sync_worker.rb
+++ b/app/workers/line_referential_sync_worker.rb
@@ -1,6 +1,6 @@
class LineReferentialSyncWorker
include Sidekiq::Worker
- sidekiq_options :retry => false
+ sidekiq_options retry: true
def process_time
Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb
new file mode 100644
index 000000000..8a085a25a
--- /dev/null
+++ b/app/workers/merge_worker.rb
@@ -0,0 +1,7 @@
+class MergeWorker
+ include Sidekiq::Worker
+
+ def perform(id)
+ Merge.find(id).merge!
+ end
+end
diff --git a/app/workers/referential_cloning_worker.rb b/app/workers/referential_cloning_worker.rb
index 6592160ec..e24baa90c 100644
--- a/app/workers/referential_cloning_worker.rb
+++ b/app/workers/referential_cloning_worker.rb
@@ -1,32 +1,7 @@
class ReferentialCloningWorker
include Sidekiq::Worker
- # Replace default apartment created schema with clone schema from source referential
def perform(id)
- ref_cloning = ReferentialCloning.find id
-
- source_schema = ref_cloning.source_referential.slug
- target_schema = ref_cloning.target_referential.slug
-
- clone_schema ref_cloning, source_schema, target_schema
- end
-
- private
-
- def clone_schema ref_cloning, source_schema, target_schema
- ref_cloning.run!
-
- AF83::SchemaCloner
- .new(source_schema, target_schema)
- .clone_schema
-
- ref_cloning.successful!
- rescue Exception => e
- Rails.logger.error "ReferentialCloningWorker : #{e}"
- ref_cloning.failed!
- end
-
- def execute_sql sql
- ActiveRecord::Base.connection.execute sql
+ ReferentialCloning.find(id).clone_with_status!
end
end
diff --git a/app/workers/stop_area_referential_sync_worker.rb b/app/workers/stop_area_referential_sync_worker.rb
index 08bcf4f5f..3de351a91 100644
--- a/app/workers/stop_area_referential_sync_worker.rb
+++ b/app/workers/stop_area_referential_sync_worker.rb
@@ -1,6 +1,6 @@
class StopAreaReferentialSyncWorker
include Sidekiq::Worker
- sidekiq_options :retry => false
+ sidekiq_options retry: true
def process_time
Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
diff --git a/app/workers/workbench_import_worker.rb b/app/workers/workbench_import_worker.rb
index de51efded..6420be835 100644
--- a/app/workers/workbench_import_worker.rb
+++ b/app/workers/workbench_import_worker.rb
@@ -3,29 +3,25 @@ class WorkbenchImportWorker
include Rails.application.routes.url_helpers
include Configurable
+ include ObjectStateUpdater
+
+ attr_reader :entries, :workbench_import
+
# Workers
# =======
def perform(import_id)
- @workbench_import = WorkbenchImport.find(import_id)
- @response = nil
- @workbench_import.update(status: 'running', started_at: Time.now)
- downloaded = download
- zip_service = ZipService.new(downloaded)
+ @entries = 0
+ @workbench_import ||= WorkbenchImport.find(import_id)
+
+ workbench_import.update(status: 'running', started_at: Time.now)
+ zip_service = ZipService.new(downloaded, allowed_lines)
upload zip_service
- @workbench_import.update(ended_at: Time.now)
+ workbench_import.update(ended_at: Time.now)
rescue Zip::Error
handle_corrupt_zip_file
end
- def download
- logger.info "HTTP GET #{import_url}"
- HTTPService.get_resource(
- host: import_host,
- path: import_path,
- params: {token: @workbench_import.token_download}).body
- end
-
def execute_post eg_name, eg_file
logger.info "HTTP POST #{export_url} (for #{complete_entry_group_name(eg_name)})"
HTTPService.post_resource(
@@ -35,48 +31,43 @@ class WorkbenchImportWorker
end
def handle_corrupt_zip_file
- @workbench_import.messages.create(criticity: :error, message_key: 'corrupt_zip_file', message_attributes: {source_filename: @workbench_import.file.file.file})
+ workbench_import.messages.create(criticity: :error, message_key: 'corrupt_zip_file', message_attributes: {source_filename: workbench_import.file.file.file})
end
def upload zip_service
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))
+ workbench_import.update total_steps: @entries
rescue Exception => e
logger.error e.message
- @workbench_import.update( current_step: entry_group_streams.size, status: 'failed' )
+ workbench_import.update( current_step: @entries, status: 'failed' )
raise
end
- def update_object_state entry, count
- @workbench_import.update( current_step: count )
- unless entry.spurious.empty?
- @workbench_import.messages.create(
- criticity: :warning,
- message_key: 'inconsistent_zip_file',
- message_attributes: {
- 'source_filename' => @workbench_import.file.file.file,
- 'spurious_dirs' => entry.spurious.join(', ')
- })
- end
- end
def upload_entry_group entry, element_count
update_object_state entry, element_count.succ
+ return unless entry.ok?
# status = retry_service.execute(&upload_entry_group_proc(entry))
- eg_name = entry.name
- eg_stream = entry.stream
+ upload_entry_group_stream entry.name, entry.stream
+ end
+ def upload_entry_group_stream eg_name, eg_stream
FileUtils.mkdir_p(Rails.root.join('tmp', 'imports'))
- eg_file = File.new(Rails.root.join('tmp', 'imports', "WorkbenchImport_#{eg_name}_#{$$}.zip"), 'wb').tap do |file|
+ File.open(Rails.root.join('tmp', 'imports', "WorkbenchImport_#{eg_name}_#{$$}.zip"), 'wb') 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"))
+
+ upload_entry_group_tmpfile eg_name, File.new(Rails.root.join('tmp', 'imports', "WorkbenchImport_#{eg_name}_#{$$}.zip"))
+ end
+
+ def upload_entry_group_tmpfile eg_name, eg_file
result = execute_post eg_name, eg_file
if result && result.status < 400
+ @entries += 1
+ workbench_import.update( current_step: @entries )
result
else
raise StopIteration, result.body
@@ -91,7 +82,7 @@ class WorkbenchImportWorker
# =======
def complete_entry_group_name entry_group_name
- [@workbench_import.name, entry_group_name].join("--")
+ [workbench_import.name, entry_group_name].join("--")
end
# Constants
@@ -111,7 +102,7 @@ class WorkbenchImportWorker
Rails.application.config.rails_host
end
def import_path
- @__import_path__ ||= download_workbench_import_path(@workbench_import.workbench, @workbench_import)
+ @__import_path__ ||= download_workbench_import_path(workbench_import.workbench, workbench_import)
end
def import_url
@__import_url__ ||= File.join(import_host, import_path)
@@ -119,10 +110,29 @@ class WorkbenchImportWorker
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") } }
+ { 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
+
+ # Lazy Values
+ # ===========
+
+ def allowed_lines
+ @__allowed_lines__ ||= workbench_import.workbench.organisation.lines_set
end
+ def downloaded
+ @__downloaded__ ||= download_response.body
+ end
+ def download_response
+ @__download_response__ ||= HTTPService.get_resource(
+ host: import_host,
+ path: import_path,
+ params: {token: workbench_import.token_download}).tap do
+ logger.info "HTTP GET #{import_url}"
+ end
+ end
+
end
diff --git a/app/workers/workbench_import_worker/object_state_updater.rb b/app/workers/workbench_import_worker/object_state_updater.rb
new file mode 100644
index 000000000..67bdc0654
--- /dev/null
+++ b/app/workers/workbench_import_worker/object_state_updater.rb
@@ -0,0 +1,36 @@
+
+class WorkbenchImportWorker
+ module ObjectStateUpdater
+
+ def update_object_state entry, count
+ workbench_import.update( total_steps: count )
+ update_spurious entry
+ update_foreign_lines entry
+ end
+
+
+ private
+
+ def update_foreign_lines entry
+ return if entry.foreign_lines.empty?
+ workbench_import.messages.create(
+ criticity: :error,
+ message_key: 'foreign_lines_in_referential',
+ message_attributes: {
+ 'source_filename' => workbench_import.file.file.file,
+ 'foreign_lines' => entry.foreign_lines.join(', ')
+ })
+ end
+
+ def update_spurious entry
+ return if entry.spurious.empty?
+ workbench_import.messages.create(
+ criticity: :error,
+ message_key: 'inconsistent_zip_file',
+ message_attributes: {
+ 'source_filename' => workbench_import.file.file.file,
+ 'spurious_dirs' => entry.spurious.join(', ')
+ })
+ end
+ end
+end
diff --git a/config/application.rb b/config/application.rb
index 169c13e10..8da6a7428 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -35,6 +35,12 @@ module ChouetteIhm
config.active_job.queue_adapter = :sidekiq
+ config.action_dispatch.rescue_responses.merge!(
+ 'FeatureChecker::NotAuthorizedError' => :unauthorized
+ )
+
+ config.development_toolbar = false
+
unless Rails.env.production?
# Work around sprockets+teaspoon mismatch:
Rails.application.config.assets.precompile += %w(spec_helper.js)
diff --git a/config/breadcrumbs.rb b/config/breadcrumbs.rb
index eb285b731..2772895fe 100644
--- a/config/breadcrumbs.rb
+++ b/config/breadcrumbs.rb
@@ -6,11 +6,31 @@ crumb :workbench do |workbench|
link workbench.name, workbench_path(workbench)
end
+crumb :workbench_output do |workbench|
+ link I18n.t('workbench_outputs.show.title'), workbench_output_path(workbench)
+ parent :workbench, current_offer_workbench
+end
+
+crumb :merges do |workbench|
+ link I18n.t('merges.index.title'), workbench_output_path(workbench)
+ parent :workbench, workbench
+end
+
+crumb :merge do |merge|
+ link breadcrumb_name(merge), workbench_merge_path(merge.workbench, merge)
+ parent :merges, merge.workbench
+end
+
crumb :referential do |referential|
link breadcrumb_name(referential), referential_path(referential)
parent :workbench, current_offer_workbench
end
+crumb :referentials do |referential|
+ link I18n.t('referentials.index.title'), referentials_path()
+ parent :workbench, current_offer_workbench
+end
+
crumb :referential_companies do |referential|
link I18n.t('companies.index.title'), referential_companies_path(referential)
parent :referential, referential
@@ -41,6 +61,11 @@ crumb :referential_group_of_line do |referential, group_of_line|
parent :referential_group_of_lines, referential
end
+crumb :referential_vehicle_journeys do |referential|
+ link I18n.t('referential_vehicle_journeys.index.title'), referential_vehicle_journeys_path(referential)
+ parent :referential, referential
+end
+
crumb :time_tables do |referential|
link I18n.t('time_tables.index.title'), referential_time_tables_path(referential)
parent :referential, referential
@@ -71,6 +96,11 @@ crumb :compliance_check_set do |workbench, compliance_check_set|
parent :compliance_check_sets, workbench
end
+crumb :compliance_check_set_executed do |workbench, compliance_check_set|
+ link I18n.t('compliance_check_sets.executed.title', name: compliance_check_set.name), executed_workbench_compliance_check_set_path(workbench, compliance_check_set)
+ parent :compliance_check_sets, workbench
+end
+
crumb :imports do |workbench|
link I18n.t('imports.index.title'), workbench_imports_path(workbench)
parent :workbench, workbench
@@ -162,13 +192,23 @@ crumb :line do |line|
parent :lines, line.line_referential
end
-crumb :calendars do
- link I18n.t('calendars.index.title'), calendars_path
+crumb :purchase_windows do |referential|
+ link I18n.t('purchase_windows.index.title'), referential_purchase_windows_path(referential)
+ parent :referential, referential
+end
+
+crumb :purchase_window do |referential, purchase_window|
+ link breadcrumb_name(purchase_window), referential_purchase_window_path(referential, purchase_window)
+ parent :purchase_windows, referential
+end
+
+crumb :calendars do |workgroup|
+ link I18n.t('calendars.index.title'), workgroup_calendars_path(workgroup)
end
-crumb :calendar do |calendar|
- link breadcrumb_name(calendar), calendar_path(calendar)
- parent :calendars
+crumb :calendar do |workgroup, calendar|
+ link breadcrumb_name(calendar), workgroup_calendar_path(workgroup, calendar)
+ parent :calendars, workgroup
end
crumb :referential_line do |referential, line|
diff --git a/config/deploy.rb b/config/deploy.rb
index a8d44d3e5..136c60196 100644
--- a/config/deploy.rb
+++ b/config/deploy.rb
@@ -7,10 +7,14 @@ set :scm, :git
set :repository, "git@github.com:AF83/stif-boiv.git"
set :deploy_to, "/var/www/stif-boiv"
set :use_sudo, false
+set :ruby_version, "2.3.0"
default_run_options[:pty] = true
set :group_writable, true
-set :bundle_cmd, "/var/lib/gems/2.2.0/bin/bundle"
-set :rake, "#{bundle_cmd} exec /var/lib/gems/2.2.0/bin/rake"
+set :bundle_cmd, "/var/lib/gems/#{ruby_version}/bin/bundle"
+set :rake, "#{bundle_cmd} exec rake"
+set :default_environment, {
+ 'PATH' => "/var/lib/gems/#{ruby_version}/bin:$PATH"
+}
set :keep_releases, -> { fetch(:kept_releases, 5) }
after "deploy:restart", "deploy:cleanup"
@@ -29,7 +33,7 @@ require 'whenever/capistrano'
#after 'deploy:finalize_update', 'npm:install'
# Whenever
-set :whenever_variables, ->{ "'environment=#{fetch :whenever_environment}&bundle_command=bin/bundle exec&additionnal_path=/var/lib/gems/2.2.0/bin'" } # invoke bin/bundle to use 'correct' ruby environment
+set :whenever_variables, ->{ "'environment=#{fetch :whenever_environment}&bundle_command=bin/bundle exec&additionnal_path=/var/lib/gems/#{ruby_version}/bin'" } # invoke bin/bundle to use 'correct' ruby environment
set :whenever_command, "sudo /usr/local/sbin/whenever-sudo" # use sudo to change www-data crontab
set :whenever_user, "www-data" # use www-data crontab
@@ -75,6 +79,7 @@ namespace :deploy do
end
after 'deploy:update_code', 'deploy:symlink_shared'
before 'deploy:assets:precompile', 'deploy:symlink_shared'
+ after 'deploy:assets:precompile', "deploy:i18n_js_export"
desc "Make group writable all deployed files"
task :group_writable do
@@ -88,8 +93,13 @@ namespace :deploy do
end
after "deploy:restart", "deploy:sidekiq_restart"
+ desc "Run i18n:js:export"
+ task :i18n_js_export do
+ run "cd #{release_path} && RAILS_ENV=#{rails_env} #{rake} i18n:js:export"
+ end
+
desc "Run db:seed"
task :seed do
- run "cd #{current_path} && #{bundle_cmd} exec /var/lib/gems/2.2.0/bin/rake db:seed RAILS_ENV=#{rails_env}"
+ run "cd #{current_path} && RAILS_ENV=#{rails_env} #{rake} db:seed"
end
end
diff --git a/config/deploy/staging.rb b/config/deploy/staging.rb
index d0a1edc42..5307ce55a 100644
--- a/config/deploy/staging.rb
+++ b/config/deploy/staging.rb
@@ -1,2 +1,2 @@
-server "stif-boiv-staging.af83.priv", :app, :web, :db, :primary => true
+server "stif-boiv-worker-staging.af83.priv", :app, :web, :db, :primary => true, :user => 'deploy'
set :branch, 'staging'
diff --git a/config/development_toolbar.rb.tpl b/config/development_toolbar.rb.tpl
new file mode 100644
index 000000000..c278f07a7
--- /dev/null
+++ b/config/development_toolbar.rb.tpl
@@ -0,0 +1,2 @@
+toolbar.available_features = %w()
+toolbar.available_permissions = %w()
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 56773d81e..446e72190 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -36,9 +36,10 @@ Rails.application.configure do
# config.action_view.raise_on_missing_translations = true
#config.active_record.auto_explain_threshold_in_seconds = (RUBY_PLATFORM == "java" ? nil : 0.5)
- config.action_mailer.default_url_options = { :host => 'localhost:3000' }
+ config.action_mailer.default_url_options = { :host => ENV.fetch('RAILS_HOST', 'http://localhost:3000') }
config.action_mailer.default_options = { from: 'Stif BOIV <stif-boiv@af83.com>' }
config.action_mailer.delivery_method = :letter_opener
+ config.action_mailer.asset_host = ENV.fetch('RAILS_HOST', 'http://localhost:3000')
# change to true to allow email to be sent during development
config.action_mailer.perform_deliveries = true
@@ -92,4 +93,17 @@ Rails.application.configure do
config.validation_spec = "http://www.chouette.mobi/neptune-validation/v21/"
config.i18n.available_locales = [:fr, :en]
+
+ config.middleware.insert_after(ActionDispatch::Static, Rack::LiveReload) if ENV['LIVERELOAD']
+ config.middleware.use I18n::JS::Middleware
+ config.development_toolbar = false
+ if ENV['TOOLBAR'] && File.exists?("config/development_toolbar.rb")
+ config.development_toolbar = OpenStruct.new
+ config.development_toolbar.features_doc_url = nil
+ config.development_toolbar.available_features = %w()
+ config.development_toolbar.available_permissions = %w()
+ config.development_toolbar.tap do |toolbar|
+ eval File.read("config/development_toolbar.rb")
+ end
+ end
end
diff --git a/config/initializers/apartment.rb b/config/initializers/apartment.rb
index 69204a5d7..2d06fb88b 100644
--- a/config/initializers/apartment.rb
+++ b/config/initializers/apartment.rb
@@ -39,6 +39,7 @@ Apartment.configure do |config|
'Chouette::Network',
'ReferentialCloning',
'Workbench',
+ 'Workgroup',
'CleanUp',
'CleanUpResult',
'Calendar',
@@ -77,7 +78,9 @@ Apartment.configure do |config|
'ComplianceCheckSet',
'ComplianceCheckBlock',
'ComplianceCheckResource',
- 'ComplianceCheckMessage'
+ 'ComplianceCheckMessage',
+ 'Merge',
+ 'CustomField',
]
# use postgres schemas?
diff --git a/config/initializers/apartment_null_db.rb b/config/initializers/apartment_null_db.rb
new file mode 100644
index 000000000..438f1e58b
--- /dev/null
+++ b/config/initializers/apartment_null_db.rb
@@ -0,0 +1,25 @@
+if ENV['RAILS_DB_ADAPTER'] == 'nulldb'
+ require 'apartment/adapters/abstract_adapter'
+
+ module Apartment
+ module Tenant
+ def adapter
+ Thread.current[:apartment_adapter] ||= nulldb_adapter(config)
+ end
+
+ def self.nulldb_adapter(config)
+ adapter = Adapters::NulldbAdapter
+ adapter.new(config)
+ end
+ end
+
+ module Adapters
+ # Default adapter when not using Postgresql Schemas
+ class NulldbAdapter < AbstractAdapter
+ def initialize config
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/config/initializers/countries.rb b/config/initializers/countries.rb
new file mode 100644
index 000000000..7f2b5c9db
--- /dev/null
+++ b/config/initializers/countries.rb
@@ -0,0 +1,3 @@
+ISO3166.configure do |config|
+ config.locales = (I18n.available_locales + Chouette::StopArea::AVAILABLE_LOCALIZATIONS).uniq
+end
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 724aaecc5..2f65b8800 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -13,3 +13,9 @@ end
Sidekiq.configure_client do |config|
config.redis = { url: ENV.fetch('SIDEKIQ_REDIS_URL', 'redis://localhost:6379/12') }
end
+
+Sidekiq.configure_client do |config|
+ config.redis = { url: ENV.fetch('SIDEKIQ_REDIS_URL', 'redis://localhost:6379/12') }
+end
+
+Sidekiq.default_worker_options = { retry: false }
diff --git a/config/initializers/simple_form/safe_submit.rb b/config/initializers/simple_form/safe_submit.rb
new file mode 100644
index 000000000..64b9f1e6e
--- /dev/null
+++ b/config/initializers/simple_form/safe_submit.rb
@@ -0,0 +1,12 @@
+::SimpleForm::FormBuilder.class_eval do
+ def button_with_safe_submit(type, *args, &block)
+ options = args.extract_options!.dup
+ if type == :submit
+ options[:data] ||= {}
+ options[:data][:disable_with] ||= I18n.t('actions.wait_for_submission')
+ end
+ args << options
+ button_without_safe_submit type, *args, &block
+ end
+ alias_method_chain :button, :safe_submit
+end
diff --git a/config/initializers/stif.rb b/config/initializers/stif.rb
index eb918131b..a73e4931b 100644
--- a/config/initializers/stif.rb
+++ b/config/initializers/stif.rb
@@ -1,12 +1,22 @@
+# coding: utf-8
Rails.application.config.to_prepare do
Organisation.after_create do |organisation|
line_referential = LineReferential.find_by(name: "CodifLigne")
stop_area_referential = StopAreaReferential.find_by(name: "Reflex")
- organisation.workbenches.find_or_create_by(name: "Gestion de l'offre") do |workbench|
- workbench.line_referential = line_referential
- workbench.stop_area_referential = stop_area_referential
- workbench.objectid_format = Workbench.objectid_format.stif_netex
+ line_referential.organisations << organisation
+ stop_area_referential.organisations << organisation
+
+ workgroup = Workgroup.find_or_create_by(name: "Gestion de l'offre théorique IDFm") do |w|
+ w.line_referential = line_referential
+ w.stop_area_referential = stop_area_referential
+ end
+
+ workbench = organisation.workbenches.find_or_create_by(name: "Gestion de l'offre") do |w|
+ w.line_referential = line_referential
+ w.stop_area_referential = stop_area_referential
+ w.objectid_format = Workbench.objectid_format.stif_netex
+ w.workgroup = workgroup
Rails.logger.debug "Create Workbench for #{organisation.name}"
end
diff --git a/config/locales/actions.en.yml b/config/locales/actions.en.yml
index 2706ba69d..278915526 100644
--- a/config/locales/actions.en.yml
+++ b/config/locales/actions.en.yml
@@ -1,10 +1,13 @@
en:
actions:
edit: "Edit"
+ activate: 'Activate'
+ deactivate: 'Deactivate'
destroy: "Destroy"
delete: "Delete"
search: "Search"
submit: "Submit"
+ processing: "Processing…"
add: "Add new"
new: "Add new"
show: "See"
@@ -22,6 +25,7 @@ en:
erase: 'Erase'
create_api_key: "Create an API key"
select: Select
+ wait_for_submission: "Please wait..."
or: "or"
cancel: "Cancel"
back: "Go Back"
diff --git a/config/locales/actions.fr.yml b/config/locales/actions.fr.yml
index e796017c7..92e16f21e 100644
--- a/config/locales/actions.fr.yml
+++ b/config/locales/actions.fr.yml
@@ -1,10 +1,13 @@
fr:
actions:
edit: 'Editer'
+ activate: 'Activer'
+ deactivate: 'Désactiver'
destroy: 'Supprimer'
delete: 'Supprimer'
search: "Chercher"
submit: "Valider"
+ processing: "En cours…"
add: 'Créer'
new: 'Créer'
show: 'Consulter'
@@ -22,6 +25,7 @@ fr:
erase: 'Effacer'
create_api_key: "Créer une clé d'API"
select: Sélectionner
+ wait_for_submission: "Validation..."
or: "ou"
cancel: "Annuler"
back: "Retour"
diff --git a/config/locales/area_types.en.yml b/config/locales/area_types.en.yml
index 9f505c5e6..5d23a6665 100644
--- a/config/locales/area_types.en.yml
+++ b/config/locales/area_types.en.yml
@@ -6,4 +6,9 @@ en:
zdlp: ZDLp
zdlr: ZDLr
lda: LDA
-
+ gdl: GDL
+ deposit: Deposit
+ border: Border
+ service_area: Service Area
+ relief: Relief point
+ other: Other
diff --git a/config/locales/area_types.fr.yml b/config/locales/area_types.fr.yml
index fd4e1e741..bb249c235 100644
--- a/config/locales/area_types.fr.yml
+++ b/config/locales/area_types.fr.yml
@@ -6,3 +6,9 @@ fr:
zdlp: ZDLp
zdlr: ZDLr
lda: LDA
+ gdl: GDL
+ deposit: Dépôt
+ border: Frontière
+ service_area: Aire de service / Pause
+ relief: Point de releve
+ other: Autre
diff --git a/config/locales/calendars.en.yml b/config/locales/calendars.en.yml
index 0076e5207..c3df413af 100644
--- a/config/locales/calendars.en.yml
+++ b/config/locales/calendars.en.yml
@@ -41,6 +41,8 @@ en:
date: Date
new:
title: Add a new calendar
+ create:
+ title: Add a new calendar
edit:
title: Update calendar %{name}
show:
@@ -56,8 +58,9 @@ en:
end: End
activerecord:
models:
- one: calendar
- other: calendars
+ calendar:
+ one: calendar
+ other: calendars
attributes:
calendar:
name: Name
@@ -66,6 +69,13 @@ en:
dates: Dates
shared: Shared
organisation: Organisation
+ monday: "Monday"
+ tuesday: "Tuesday"
+ wednesday: "Wednesday"
+ thursday: "Thursday"
+ friday: "Friday"
+ saturday: "Saturday"
+ sunday: "Sunday"
errors:
models:
calendar:
diff --git a/config/locales/calendars.fr.yml b/config/locales/calendars.fr.yml
index fddb47d64..6fd265925 100644
--- a/config/locales/calendars.fr.yml
+++ b/config/locales/calendars.fr.yml
@@ -25,26 +25,28 @@ fr:
standard_calendars: Calendriers standards
standard_calendar: Calendrier standard
actions:
- new: Ajouter un calendrier
- edit: Editer cet calendrier
- destroy: Supprimer cet calendrier
- destroy_confirm: Etes vous sûr de supprimer cet calendrier ?
+ new: Ajouter un modèle de calendrier
+ edit: Editer ce modèle de calendrier
+ destroy: Supprimer ce modèle de calendrier
+ destroy_confirm: Etes vous sûr de supprimer ce modèle de calendrier ?
errors:
overlapped_periods: Une autre période chevauche cette période
- short_period: Une période doit être d'un duréé de deux jours minimum
+ short_period: "Une période doit être d'une durée de deux jours minimum"
index:
- title: Calendriers
+ title: Modèles de calendrier
all: Tous
shared: Partagées
not_shared: Non partagées
- search_no_results: Aucun calendrier ne correspond à votre recherche
+ search_no_results: Aucun modèle de calendrier ne correspond à votre recherche
date: Date
new:
- title: Ajouter un calendrier
+ title: Ajouter un modèle de calendrier
+ create:
+ title: Ajouter un modèle de calendrier
edit:
- title: Editer le calendrier %{name}
+ title: Editer le modèle de calendrier %{name}
show:
- title: Calendrier %{name}
+ title: Modèle de calendrier %{name}
simple_form:
labels:
calendar:
@@ -56,8 +58,9 @@ fr:
end: Fin
activerecord:
models:
- one: "calendrier"
- other: "calendriers"
+ calendar:
+ one: "modèle de calendrier"
+ other: "modèles de calendrier"
attributes:
calendar:
name: Nom
@@ -66,6 +69,13 @@ fr:
dates: Dates
shared: Partagé
organisation: Organisation
+ monday: "Lundi"
+ tuesday: "Mardi"
+ wednesday: "Mercredi"
+ thursday: "Jeudi"
+ friday: "Vendredi"
+ saturday: "Samedi"
+ sunday: "Dimanche"
errors:
models:
calendar:
diff --git a/config/locales/carrier_wave.yml b/config/locales/carrier_wave.yml
new file mode 100644
index 000000000..53dd44e86
--- /dev/null
+++ b/config/locales/carrier_wave.yml
@@ -0,0 +1,4 @@
+fr:
+ errors:
+ messages:
+ extension_whitelist_error: "Le format %{extension} n'est pas supporté, le(s) format(s) supporté(s) sont : %{allowed_types}"
diff --git a/config/locales/companies.en.yml b/config/locales/companies.en.yml
index a3cd520cb..becb087b1 100644
--- a/config/locales/companies.en.yml
+++ b/config/locales/companies.en.yml
@@ -1,6 +1,7 @@
en:
companies: &en_companies
search_no_results: "No company matching your query"
+ search_no_results_for_filter: "No company has been set for these journeys"
actions:
new: "Add a new company"
edit: "Edit this company"
diff --git a/config/locales/companies.fr.yml b/config/locales/companies.fr.yml
index 0cf729c35..3284115ab 100644
--- a/config/locales/companies.fr.yml
+++ b/config/locales/companies.fr.yml
@@ -1,6 +1,7 @@
fr:
companies: &fr_companies
search_no_results: "Aucun transporteur ne correspond à votre recherche"
+ search_no_results_for_filter: "Aucun transporteur renseigné sur ces courses"
actions:
new: "Ajouter un transporteur"
edit: "Editer ce transporteur"
diff --git a/config/locales/compliance_check_messages.en.yml b/config/locales/compliance_check_messages.en.yml
new file mode 100644
index 000000000..216a363a3
--- /dev/null
+++ b/config/locales/compliance_check_messages.en.yml
@@ -0,0 +1,31 @@
+en:
+ compliance_check_messages:
+ 3_route_1: "The route with %{source_objectid} objectid connect the stop points %{target_0_label} (%{target_0_objectid}) and %{target_1_label} (%{target_1_objectid}) which belong to the same ZDL"
+ 3_route_2: "The route with %{source_objectid} objectid references an incoherent oppposite route %{target_0_objectid}"
+ 3_route_3: "The route with %{source_objectid} objectid doesn't have any journey pattern"
+ 3_route_4: "The route with %{source_objectid} objectid is identical with another route %{target_0_objectid}"
+ 3_route_5: "The route with %{source_objectid} objectid has a first stop from the %{target_0_label} ZDL whereas its oppoite route's last stop is from the ZDL %{target_1_label}"
+ 3_route_6: "The route with %{source_objectid} objectid does not connect enough stop points (required 2 stop points)"
+ 3_route_8: "The stop point %{target_0_label} (%{target_0_objectid}) of the route %{source_objectid} is not used by any journey pattern"
+ 3_route_9: "The route with %{source_objectid} objectid does not have a journey pattern that connect all of its stop points"
+ 3_route_10: "L'itinéraire %{source_objectid} référence un arrêt (ZDEp) désactivé %{target_0_label} (%{target_0_objectid})"
+ 3_journeypattern_1: "The journey pattern with objectid %{source_objectid} is identical with another one %{target_0_objectid}"
+ 3_journeypattern_2: "The journey pattern with %{source_objectid} objectid doesn't have any vehicle journey"
+ 3_vehiclejourney_1: "On the following vehicle journey %{source_objectid}, the waiting time %{error_value} a this stop point %{target_0_label} (%{target_0_objectid}) is greater than the threshold (%{reference_value})"
+ 3_vehiclejourney_2_1: "On the following vehicle journey %{source_objectid}, the computed speed %{error_value} between the stop points %{target_0_label} (%{target_0_objectid}) and %{target_1_label} (%{target_1_objectid}) is greater than the threshold (%{reference_value})"
+ 3_vehiclejourney_2_2: "On the following vehicle journey %{source_objectid}, the computed speed %{error_value} between the stop points %{target_0_label} (%{target_0_objectid}) and %{target_1_label} (%{target_1_objectid}) is smaller than the threshold (%{reference_value})"
+ 3_vehiclejourney_3: "The travel time on the vehicle journey with %{source_objectid} objectid between the stop points %{target_0_label} (%{target_0_objectid}) and %{target_1_label} (%{target_1_objectid}) is too far off %{error_value} the average waiting on the journey pattern"
+ 3_vehiclejourney_4: "The vehicle journey with %{source_objectid} objectid does not have a timetable"
+ 3_vehiclejourney_5_1: "The vehicle journey with %{source_objectid} objectid has an arrival time %{error_value} greater than the departure time %{reference_value} at the stop point %{target_0_label} (%{target_0_objectid})"
+ 3_vehiclejourney_5_2: "The vehicle journey with %{source_objectid} objectid has an departure time %{error_value} at stop point %{target_0_label} (%{target_0_objectid}) greater than the arrival %{reference_value} at the next stop point"
+ 3_routingconstraint_1: "The Routing Constraint Zone %{source_objectid} references an unactivated stop point (ZDEp) %{target_0_label} (%{target_0_objectid})"
+ 3_routingconstraint_2: "The Routing Constraint Zone %{source_objectid} covers all the stop points of its related route : %{target_0_objectid}."
+ 3_routingconstraint_3: "The Routing Constraint Zone %{source_objectid} has less than 2 stop points"
+ 3_line_1: "On line :%{source_label} (%{source_objectid}), no route has an opposite route"
+ 3_generic_1: "%{source_objectid} : the %{source_attribute} attribute value (%{error_value}) does not respect the following pattern : %{reference_value}"
+ 3_generic_2_1: "%{source_objectid} : the %{source_attribute} attributes's value (%{error_value}) is greater than the authorized maximum value : %{reference_value}"
+ 3_generic_2_2: "%{source_objectid} : the %{source_attribute} attributes's value (%{error_value}) is smaller than the authorized minimum value %{reference_value}"
+ 3_generic_3: "%{source_objectid} : the %{source_attribute} attribute (%{error_value}) has a value shared with : %{target_0_objectid}"
+ 3_shape_1: "Tracé %{source_objectid} : le tracé passe trop loin de l'arrêt %{target_0_label} (%{target_0_objectid}) : %{error_value} > %{reference_value}"
+ 3_shape_2: "Tracé %{source_objectid} : le tracé n'est pas défini entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid})"
+ 3_shape_3: "Le tracé de l'itinéraire %{source_objectid} est en écart avec la voirie sur %{error_value} sections" \ No newline at end of file
diff --git a/config/locales/compliance_check_messages.fr.yml b/config/locales/compliance_check_messages.fr.yml
new file mode 100644
index 000000000..db127d236
--- /dev/null
+++ b/config/locales/compliance_check_messages.fr.yml
@@ -0,0 +1,31 @@
+fr:
+ compliance_check_messages:
+ 3_route_1: "L'itinéraire %{source_objectid} dessert successivement les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) de la même zone de lieu"
+ 3_route_2: "L'itinéraire %{source_objectid} référence un itinéraire retour %{target_0_objectid} incohérent"
+ 3_route_3: "L'itinéraire %{source_objectid} n'a pas de mission"
+ 3_route_4: "L'itinéraire %{source_objectid} est identique à l'itinéraire %{target_0_objectid}"
+ 3_route_5: "L'itinéraire %{source_objectid} dessert au départ un arrêt de la ZDL %{target_0_label} alors que l'itinéraire inverse dessert à l'arrivée un arrêt de la ZDL %{target_1_label}"
+ 3_route_6: "L'itinéraire %{source_objectid} ne dessert pas assez d'arrêts (minimum 2 requis)"
+ 3_route_8: "l'arrêt %{target_0_label} (%{target_0_objectid}) de l'itinéraire %{source_objectid} n'est desservi par aucune mission"
+ 3_route_9: "L'itinéraire %{source_objectid} n'a aucune mission desservant l'ensemble de ses arrêts"
+ 3_route_10: "L'itinéraire %{source_objectid} référence un arrêt (ZDEp) désactivé %{target_0_label} (%{target_0_objectid})"
+ 3_journeypattern_1: "La mission %{source_objectid} est identique à la mission %{target_0_objectid}"
+ 3_journeypattern_2: "La mission %{source_objectid} n'a pas de course"
+ 3_vehiclejourney_1: "Sur la course %{source_objectid}, le temps d'attente %{error_value} à l'arrêt %{target_0_label} (%{target_0_objectid}) est supérieur au seuil toléré (%{reference_value})"
+ 3_vehiclejourney_2_1: "Sur la course %{source_objectid}, la vitesse calculée %{error_value} entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) est supérieure au seuil toléré (%{reference_value})"
+ 3_vehiclejourney_2_2: "Sur la course %{source_objectid}, la vitesse calculée %{error_value} entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) est inférieure au seuil toléré (%{reference_value})"
+ 3_vehiclejourney_3: "Le temps de parcours sur la course %{source_objectid} entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) s'écarte de %{error_value} du temps moyen constaté sur la mission"
+ 3_vehiclejourney_4: "La course %{source_objectid} n'a pas de calendrier d'application"
+ 3_vehiclejourney_5_1: "La course %{source_objectid} a un horaire d'arrivé %{error_value} supérieur à l'horaire de départ %{reference_value} à l'arrêt %{target_0_label} (%{target_0_objectid})"
+ 3_vehiclejourney_5_2: "La course %{source_objectid} a un horaire de départ %{error_value} à l'arrêt %{target_0_label} (%{target_0_objectid}) supérieur à l'horaire d'arrivé %{reference_value} à l'arrêt suivant"
+ 3_routingconstraint_1: "L'ITL %{source_objectid} référence un arrêt (ZDEp) désactivé %{target_0_label} (%{target_0_objectid})"
+ 3_routingconstraint_2: "L'ITL %{source_objectid} couvre tous les arrêts de l'itinéraire %{target_0_objectid}."
+ 3_routingconstraint_3: "L'ITL %{source_objectid} n'a pas suffisament d'arrêts (minimum 2 arrêts requis)"
+ 3_line_1: "Sur la ligne %{source_label} (%{source_objectid}), aucun itinéraire n'a d'itinéraire inverse"
+ 3_generic_1: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} qui ne respecte pas le motif %{reference_value}"
+ 3_generic_2_1: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} supérieure à la valeur maximale autorisée %{reference_value}"
+ 3_generic_2_2: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} inférieure à la valeur minimale autorisée %{reference_value}"
+ 3_generic_3: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} partagée avec %{target_0_objectid}"
+ 3_shape_1: "Tracé %{source_objectid} : le tracé passe trop loin de l'arrêt %{target_0_label} (%{target_0_objectid}) : %{error_value} > %{reference_value}"
+ 3_shape_2: "Tracé %{source_objectid} : le tracé n'est pas défini entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid})"
+ 3_shape_3: "Le tracé de l'itinéraire %{source_objectid} est en écart avec la voirie sur %{error_value} sections" \ No newline at end of file
diff --git a/config/locales/compliance_check_results.en.yml b/config/locales/compliance_check_results.en.yml
deleted file mode 100644
index cd22aefb1..000000000
--- a/config/locales/compliance_check_results.en.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-en:
- compliance_check_messages:
diff --git a/config/locales/compliance_check_results.fr.yml b/config/locales/compliance_check_results.fr.yml
deleted file mode 100644
index d3fbf0900..000000000
--- a/config/locales/compliance_check_results.fr.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-fr:
- compliance_check_messages:
diff --git a/config/locales/compliance_check_sets.en.yml b/config/locales/compliance_check_sets.en.yml
index 1081b1d66..5e8c3b24f 100644
--- a/config/locales/compliance_check_sets.en.yml
+++ b/config/locales/compliance_check_sets.en.yml
@@ -22,7 +22,14 @@ en:
title: Compliance check set report
table_state: "%{lines_status} lines imported on %{lines_in_compliance_check_set} in the archive"
table_explanation: "These controls apply to all imported data and condition the construction of your organization's offer."
+ table_title: Analysed lines state
metrics: "%{ok_count} ok, %{error_count} errors, %{warning_count} warnings, %{uncheck_count} n/a"
+ metadatas:
+ referential: "Object analysed"
+ referential_type: "Apply to"
+ compliance_check_set_executed: "Compliance check set executed"
+ compliance_control_owner: "Compliance control owner"
+ import: "Import"
errors:
no_parent: "The compliance check set doesn't have any parent"
activerecord:
@@ -40,6 +47,14 @@ en:
metrics: Test results
download: Download
models:
+ compliance_check_set:
+ zero: "Compliance check set"
+ one: "Compliance check set"
+ other: "Compliance check sets"
+ compliance_check:
+ zero: "Compliance check"
+ one: "Compliance check"
+ other: "Compliance checks"
compliance_check_block:
one: compliance_control_set
other: compliance_control_sets
diff --git a/config/locales/compliance_check_sets.fr.yml b/config/locales/compliance_check_sets.fr.yml
index 8f1c066e7..20bf11d85 100644
--- a/config/locales/compliance_check_sets.fr.yml
+++ b/config/locales/compliance_check_sets.fr.yml
@@ -10,25 +10,32 @@ fr:
name_compliance_control_set: Indiquez le nom d'un jeu de contrôle
error_period_filter: La date de fin doit être supérieure ou égale à la date de début0
index:
- title: "Liste des jeux de contrôles"
+ title: "Liste des rapports de contrôles"
search_no_results: Aucun rapport de contrôle ne correspond à votre recherche
executed:
- title: Jeu de contrôles exécutés %{name}
+ title: Jeu de contrôles exécuté %{name}
show:
title: Rapport de contrôle
- table_state: "%{lines_status} lignes importées sur %{lines_in_compliance_check_set} présentes dans l'archive"
+ table_state: "%{lines_status} lignes valides sur %{lines_in_compliance_check_set} présentes dans l'offre de transport"
table_explanation: Ces contrôles s’appliquent pour toutes les données importées et conditionnent la construction de l’offre de votre organisation
+ table_title: État des lignes analysées
metrics: "%{ok_count} ok, %{error_count} errors, %{warning_count} warnings, %{uncheck_count} n/a"
+ metadatas:
+ referential: "Objet analysé"
+ referential_type: "Appliqué à"
+ compliance_check_set_executed: "Jeu de contrôles exécuté"
+ compliance_control_owner: "Propriétaire du jeu de contrôles"
+ import: "Rapport d'import"
errors:
no_parent: "Le jeux de contrôle n'a pas de parent"
activerecord:
attributes:
compliance_check_set:
- ref: réf
+ ref: Ref
creation_date: Date et heure de création
associated_object: Objet associé
assigned_to: Affectation
- compliance_control_set: jeu de contrôle
+ compliance_control_set: Jeu de contrôle exécuté
name: Nom
compliance_check_resource:
name: Nom de la ligne
@@ -36,6 +43,14 @@ fr:
metrics: Résultat des tests
download: Télécharger
models:
+ compliance_check_set:
+ zero: "Rapport de contrôles"
+ one: "Rapport de contrôles"
+ other: "Rapport de contrôles"
+ compliance_check:
+ zero: "Contrôle"
+ one: "Contrôle"
+ other: "Contrôles"
compliance_check_block:
zero: "Groupe de contrôle"
one: "Groupe de contrôle"
diff --git a/config/locales/compliance_controls.en.yml b/config/locales/compliance_controls.en.yml
index f9d7d23d2..ca9d83872 100644
--- a/config/locales/compliance_controls.en.yml
+++ b/config/locales/compliance_controls.en.yml
@@ -89,7 +89,7 @@ en:
vehicle_journey_control/waiting_time:
messages:
3_vehiclejourney_1: "On the following vehicle journey %{source_objectid}, the waiting time %{error_value} a this stop point %{target_0_label} (%{target_0_objectid}) is greater than the threshold (%{reference_value})"
- description: "The waiting time at a specific stop point cannot be too big"
+ description: "The waiting time, in minutes, at a specific stop point cannot be too big"
vehicle_journey_control/speed:
messages:
3_vehiclejourney_2_1: "On the following vehicle journey %{source_objectid}, the computed speed %{error_value} between the stop points %{target_0_label} (%{target_0_objectid}) and %{target_1_label} (%{target_1_objectid}) is greater than the threshold (%{reference_value})"
@@ -106,7 +106,7 @@ en:
vehicle_journey_control/vehicle_journey_at_stops:
messages:
3_vehiclejourney_5_1: "The vehicle journey with %{source_objectid} objectid has an arrival time %{error_value} greater than the departure time %{reference_value} at the stop point %{target_0_label} (%{target_0_objectid})"
- 3_vehiclejourney_5_2: "The vehicle journey with %{source_objectid} objectid has an departure time %{error_value} at stop point %{target_0_label} (%{target_0_objectid}) greater than the arrival % at the next stop point"
+ 3_vehiclejourney_5_2: "The vehicle journey with %{source_objectid} objectid has an departure time %{error_value} at stop point %{target_0_label} (%{target_0_objectid}) greater than the arrival %{reference_value} at the next stop point"
description: "The arrival time of a stop point must be smaller than the departure time of this stop point AND the departure time of the stop points must be in chronological order"
routing_constraint_zone_control/vehicle_journey_at_stops:
messages:
@@ -127,16 +127,16 @@ en:
prerequisite: Lign has multiple routes
generic_attribute_control/pattern:
messages:
- 3_generic_1: "%{source_objectid} : the %{source_label} attribute value (%{error_value}) does not respect the following pattern : %{reference_value}"
+ 3_generic_1: "%{source_objectid} : the %{source_attribute} attribute value (%{error_value}) does not respect the following pattern : %{reference_value}"
description: "The object attribute must respect a patten (regular expression)"
generic_attribute_control/min_max:
messages:
- 3_generic_2_1: "%{source_objectid} : the %{source_label} attributes's value (%{error_value}) is greater than the authorized maximum value : %{reference_value}"
- 3_generic_2_2: "%{source_objectid} : the %{source_label} attributes's value (%{error_value}) is smaller than the authorized minimum value %{reference_value}"
+ 3_generic_2_1: "%{source_objectid} : the %{source_attribute} attributes's value (%{error_value}) is greater than the authorized maximum value : %{reference_value}"
+ 3_generic_2_2: "%{source_objectid} : the %{source_attribute} attributes's value (%{error_value}) is smaller than the authorized minimum value %{reference_value}"
description: "The numeric value of an attribute must be contained between 2 values"
generic_attribute_control/uniqueness:
messages:
- 3_generic_3: "%{source_objectid} : the %{source_label} attribute's value (%{error_value}) is in conflict with : %{reference_value}"
+ 3_generic_3: "%{source_objectid} : the %{source_attribute} attribute (%{error_value}) has a value shared with : %{target_0_objectid}"
description: "The attribute's value must be unique compared to the other objects ofthe same type (related to the same line)"
shape_control:
3_shape_1: "Tracé %{source_objectid} : le tracé passe trop loin de l'arrêt %{target_0_label} (%{target_0_objectid}) : %{error_value} > %{reference_value}"
diff --git a/config/locales/compliance_controls.fr.yml b/config/locales/compliance_controls.fr.yml
index b77b4e6d4..f5f7e351f 100644
--- a/config/locales/compliance_controls.fr.yml
+++ b/config/locales/compliance_controls.fr.yml
@@ -7,14 +7,14 @@ fr:
name: "Chercher le nom ou code d'un contrôle"
subclass: Objet
subclasses:
- generic: 'Généric'
- journey_pattern: 'JourneyPattern'
+ generic: 'Générique'
+ journey_pattern: 'Mission'
line: 'Ligne'
route: 'Itinéraire'
routing_constraint_zone: 'ITL'
vehicle_journey: 'Course'
search_no_results: 'Aucun contrôle ne correspond à votre recherche'
- min_max_values: "la valeur de minimum (%{min}) ne doit pas être superieur à la valuer du maximum (%{max})"
+ min_max_values: "la valeur minimum (%{min}) ne doit pas être supérieure à la valeur maximum (%{max})"
errors:
incoherent_control_sets: "Le contrôle ne peut pas être associé à un jeu de contrôle (id: %{direct_set_name}) différent de celui de son groupe (id: %{indirect_set_name})"
mandatory_control_type: "Un type de contrôle doit être sélectionné"
@@ -88,11 +88,11 @@ fr:
vehicle_journey_control/waiting_time:
messages:
3_vehiclejourney_1: "Sur la course %{source_objectid}, le temps d'attente %{error_value} à l'arrêt %{target_0_label} (%{target_0_objectid}) est supérieur au seuil toléré (%{reference_value})"
- description: "La durée d’attente à un arrêt ne doit pas être trop grande"
+ description: "La durée d’attente, en minutes, à un arrêt ne doit pas être trop grande"
vehicle_journey_control/speed:
messages:
- 3_vehiclejourney_2_1: "Sur la course %{source_objectid}, la vitesse calculée %{error_value} entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) est supérieur au seuil toléré (%{reference_value})"
- 3_vehiclejourney_2_2: "Sur la course %{source_objectid}, la vitesse calculée %{error_value} entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) est inférieur au seuil toléré (%{reference_value})"
+ 3_vehiclejourney_2_1: "Sur la course %{source_objectid}, la vitesse calculée %{error_value} entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) est supérieure au seuil toléré (%{reference_value})"
+ 3_vehiclejourney_2_2: "Sur la course %{source_objectid}, la vitesse calculée %{error_value} entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) est inférieure au seuil toléré (%{reference_value})"
description: "La vitesse entre deux arrêts doit être dans une fourchette paramétrable"
vehicle_journey_control/delta:
messages:
@@ -105,7 +105,7 @@ fr:
vehicle_journey_control/vehicle_journey_at_stops:
messages:
3_vehiclejourney_5_1: "La course %{source_objectid} a un horaire d'arrivé %{error_value} supérieur à l'horaire de départ %{reference_value} à l'arrêt %{target_0_label} (%{target_0_objectid})"
- 3_vehiclejourney_5_2: "La course %{source_objectid} a un horaire de départ %{error_value} à l'arrêt %{target_0_label} (%{target_0_objectid}) supérieur à l'horaire d'arrivé % à l'arrêt suivant"
+ 3_vehiclejourney_5_2: "La course %{source_objectid} a un horaire de départ %{error_value} à l'arrêt %{target_0_label} (%{target_0_objectid}) supérieur à l'horaire d'arrivé %{reference_value} à l'arrêt suivant"
description: "L'horaire d'arrivée à un arrêt doit être antérieur à l'horaire de départ de cet arrêt ET les horaires de départ aux arrêts doivent être dans l'ordre chronologique croissant."
routing_constraint_zone_control/unactivated_stop_point:
messages:
@@ -126,16 +126,16 @@ fr:
prerequisite: Ligne disposant de plusieurs itinéraires
generic_attribute_control/pattern:
messages:
- 3_generic_1: "%{source_objectid} : l'attribut % à une valeur %{error_value} qui ne respecte pas le motif %{reference_value}"
+ 3_generic_1: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} qui ne respecte pas le motif %{reference_value}"
description: "l'attribut de l'objet doit respecter un motif (expression régulière)"
generic_attribute_control/min_max:
messages:
- 3_generic_2_1: "%{source_objectid} : l'attribut %{source_label} à une valeur %{error_value} supérieure à la valeur maximale autorisée %{reference_value}"
- 3_generic_2_2: "%{source_objectid} : l'attribut %{source_label} à une valeur %{error_value} inférieure à la valeur minimale autorisée %{reference_value}"
+ 3_generic_2_1: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} supérieure à la valeur maximale autorisée %{reference_value}"
+ 3_generic_2_2: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} inférieure à la valeur minimale autorisée %{reference_value}"
description: "La valeur numérique de l'attribut doit rester comprise entre 2 valeurs"
generic_attribute_control/uniqueness:
messages:
- 3_generic_3: "%{source_objectid} : l'attribut %{source_label} à une valeur %{error_value}en conflit avec %{reference_value}"
+ 3_generic_3: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} partagée avec %{target_0_objectid}"
description: "La valeur de l'attribut doit être unique au sein des objets de la ligne"
shape_control:
3_shape_1: "Tracé %{source_objectid} : le tracé passe trop loin de l'arrêt %{target_0_label} (%{target_0_objectid}) : %{error_value} > %{reference_value}"
diff --git a/config/locales/dashboard.en.yml b/config/locales/dashboard.en.yml
new file mode 100644
index 000000000..8d46ff7aa
--- /dev/null
+++ b/config/locales/dashboard.en.yml
@@ -0,0 +1,16 @@
+en:
+ dashboards:
+ show:
+ title: "Dashboard %{organisation}"
+ calendars:
+ title: Calendars
+ none: No calendar created
+ purchase_windows:
+ title: Purchase windows
+ none: No purchase window created
+ line_referentials:
+ title: Line referential
+ none: No line referential created
+ stop_area_referentials:
+ title: Stop area referential
+ none: No stop area referential created
diff --git a/config/locales/dashboard.fr.yml b/config/locales/dashboard.fr.yml
index fffb36cd1..d0aa36d61 100644
--- a/config/locales/dashboard.fr.yml
+++ b/config/locales/dashboard.fr.yml
@@ -2,3 +2,15 @@ fr:
dashboards:
show:
title: "Tableau de bord %{organisation}"
+ calendars:
+ title: Modèles de calendrier
+ none: Aucun calendrier défini
+ purchase_windows:
+ title: Calendriers commerciaux
+ none: Aucun calendrier commercial défini
+ line_referentials:
+ title: Référentiels de lignes
+ none: Aucun référentiels de lignes défini
+ stop_area_referentials:
+ title: Référentiels d'arrêts
+ none: Aucun référentiels d'arrêts défini
diff --git a/config/locales/devise.fr.yml b/config/locales/devise.fr.yml
index d3fd6d03e..42a568fec 100644
--- a/config/locales/devise.fr.yml
+++ b/config/locales/devise.fr.yml
@@ -31,7 +31,7 @@ norme Neptune (NFP 99 506)"
passwords:
new:
title: Mot de passe oublié
- commit: Envoyer les instructions pour un nouveau mot de passe
+ commit: Envoyer les instructions
edit:
title: Changer de mot de passe
new_password: Nouveau mot de passe
diff --git a/config/locales/en.yml b/config/locales/en.yml
index e59960f95..8af8067db 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -3,6 +3,7 @@ en:
"false": "No"
"unknown": "Unknown"
+
time:
formats:
hour: "%Hh%M"
@@ -61,3 +62,7 @@ en:
reflex_data: 'Reflex datas'
objectid: 'ID'
brandname: IBOO
+ error: "Error"
+ undefined: 'undefined'
+ "yes": yes
+ "no": no
diff --git a/config/locales/enumerize.en.yml b/config/locales/enumerize.en.yml
index bfd7b8c22..edc5b22e3 100644
--- a/config/locales/enumerize.en.yml
+++ b/config/locales/enumerize.en.yml
@@ -255,4 +255,15 @@ en:
travel_agency: "Travel_agency"
individual_subject_of_travel_itinerary: "Individual subject of travel itinerary"
other_information: "Other information"
-
+ purchase_window:
+ color:
+ 9B9B9B: "Grey"
+ FFA070: "Light orange"
+ C67300: "Orange"
+ 7F551B: "Dark orange"
+ 41CCE3: "Light blue"
+ 09B09C: "Green"
+ 3655D7: "Blue"
+ 6321A0: "Purple"
+ E796C6: "Light pink"
+ DD2DAA: "Pink"
diff --git a/config/locales/enumerize.fr.yml b/config/locales/enumerize.fr.yml
index b2eab665d..c4995e3c3 100644
--- a/config/locales/enumerize.fr.yml
+++ b/config/locales/enumerize.fr.yml
@@ -253,3 +253,15 @@ fr:
travel_agency: "Agence de voyage"
individual_subject_of_travel_itinerary: "Voyageur individuel"
other_information: "Autre source d'information"
+ purchase_window:
+ color:
+ 9B9B9B: "Gris"
+ FFA070: "Orange clair"
+ C67300: "Orange"
+ 7F551B: "Orange foncé"
+ 41CCE3: "Bleu clair"
+ 09B09C: "Vert"
+ 3655D7: "Bleu"
+ 6321A0: "Violet"
+ E796C6: "Rose pale"
+ DD2DAA: "Rose"
diff --git a/config/locales/footnotes.en.yml b/config/locales/footnotes.en.yml
index dba8edd0b..5b86f0806 100644
--- a/config/locales/footnotes.en.yml
+++ b/config/locales/footnotes.en.yml
@@ -16,4 +16,5 @@ en:
attributes:
footnote:
code: "number"
+ checksum: checksum
label: "line text"
diff --git a/config/locales/footnotes.fr.yml b/config/locales/footnotes.fr.yml
index f5cd71c21..692098046 100644
--- a/config/locales/footnotes.fr.yml
+++ b/config/locales/footnotes.fr.yml
@@ -16,4 +16,5 @@ fr:
attributes:
footnote:
code: "numéro"
+ checksum: Signature métier
label: "ligne de texte"
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 175b71ebc..e1f52ff55 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -61,3 +61,7 @@ fr:
reflex_data: 'Données Reflex'
objectid: 'ID'
brandname: IBOO
+ error: "Erreur"
+ undefined: 'non renseigné'
+ "yes": oui
+ "no": non
diff --git a/config/locales/import_messages.en.yml b/config/locales/import_messages.en.yml
index 42d180abd..aad4fb772 100644
--- a/config/locales/import_messages.en.yml
+++ b/config/locales/import_messages.en.yml
@@ -1,54 +1,53 @@
en:
import_messages:
- compliance_check_messages:
- corrupt_zip_file: "The zip file %{source_filename} is corrupted and cannot be read"
- inconsistent_zip_file: "The zip file %{source_filename} contains unexpected directories: %{spurious_dirs}, which are ignored"
- referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les mêmes 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 %{error_value} 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 %{error_value} 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 %{error_value} non acceptée"
- 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{error_value} obligatoire"
- 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{error_value} non acceptée"
- 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{error_value} ne respecte pas la syntaxe %{reference_value}"
- 2_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{error_value} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
- 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'"
- 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{error_value}"
- 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe : référence interne attendue"
- 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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_value} 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 %{error_value} 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_1: "%{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_3_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} a une valeur interdite %{error_value} pour l'attribut ServiceJourneyPatternType différente de 'passenger'"
- 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."
+ corrupt_zip_file: "The zip file %{source_filename} is corrupted and cannot be read"
+ inconsistent_zip_file: "The zip file %{source_filename} contains unexpected directories: %{spurious_dirs}, which are ignored"
+ referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les mêmes 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 %{error_value} 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 %{error_value} 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 %{error_value} non acceptée"
+ 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{error_value} obligatoire"
+ 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{error_value} non acceptée"
+ 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{error_value} ne respecte pas la syntaxe %{reference_value}"
+ 2_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{error_value} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
+ 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'"
+ 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{error_value}"
+ 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe : référence interne attendue"
+ 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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_value} 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 %{error_value} 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_1: "%{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_3_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} a une valeur interdite %{error_value} pour l'attribut ServiceJourneyPatternType différente de 'passenger'"
+ 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." \ No newline at end of file
diff --git a/config/locales/import_messages.fr.yml b/config/locales/import_messages.fr.yml
index e29da05f9..1e5054648 100644
--- a/config/locales/import_messages.fr.yml
+++ b/config/locales/import_messages.fr.yml
@@ -1,54 +1,53 @@
fr:
import_messages:
- compliance_check_messages:
- corrupt_zip_file: "Le fichier zip %{source_filename} est corrompu, et ne peut être lu"
- inconsistent_zip_file: "Le fichier zip %{source_filename} contient des repertoires non prévus : %{spurious_dirs} qui seront ignorés"
- referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les mêmes 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 %{error_value} 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 %{error_value} 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 %{error_value} non acceptée"
- 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{error_value} obligatoire"
- 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{error_value} non acceptée"
- 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{error_value} ne respecte pas la syntaxe %{reference_value}"
- 2_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{error_value} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
- 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'"
- 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{error_value}"
- 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe : référence interne attendue"
- 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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_value} 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 %{error_value} 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_1: "%{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_3_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} a une valeur interdite %{error_value} pour l'attribut ServiceJourneyPatternType différente de 'passenger'"
- 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."
+ corrupt_zip_file: "Le fichier zip est corrompu, et ne peut être lu"
+ inconsistent_zip_file: "Le fichier zip contient des repertoires non prévus : %{spurious_dirs} qui seront ignorés"
+ referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les mêmes 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 %{error_value} 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 %{error_value} 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 %{error_value} non acceptée"
+ 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{error_value} obligatoire"
+ 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{error_value} non acceptée"
+ 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{error_value} ne respecte pas la syntaxe %{reference_value}"
+ 2_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{error_value} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
+ 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'"
+ 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{error_value}"
+ 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe : référence interne attendue"
+ 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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_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 %{error_value} 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 %{error_value} 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_1: "%{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_3_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} a une valeur interdite %{error_value} pour l'attribut ServiceJourneyPatternType différente de 'passenger'"
+ 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/imports.en.yml b/config/locales/imports.en.yml
index 0bb54d90d..b0644acd3 100644
--- a/config/locales/imports.en.yml
+++ b/config/locales/imports.en.yml
@@ -7,6 +7,7 @@ en:
error_period_filter: "End date must be greater or equal than begin date"
actions:
new: "New import"
+ create: "New import"
show: "Import report"
download: "Download original file"
destroy: "Destroy"
@@ -15,7 +16,9 @@ en:
title: "Imports"
warning: ""
new:
- title: "Imports"
+ title: "Generate a new import"
+ create:
+ title: "Generate a new import"
show:
title: "Import %{name}"
report: "Report"
@@ -74,3 +77,7 @@ en:
max_distance_for_connection_link: "Max distance for connection link"
ignore_last_word: "ignore last word"
ignore_end_chars: "ignore last chars"
+ flash:
+ imports:
+ create:
+ notice: "The import is in progress. Please wait and refresh the page in a few moments."
diff --git a/config/locales/imports.fr.yml b/config/locales/imports.fr.yml
index 207f5cc31..2380eac45 100644
--- a/config/locales/imports.fr.yml
+++ b/config/locales/imports.fr.yml
@@ -7,6 +7,7 @@ fr:
error_period_filter: "La date de fin doit être supérieure ou égale à la date de début"
actions:
new: "Nouvel import"
+ create: "Nouvel import"
show: "Rapport d'import"
download: "Téléch. fichier source"
destroy: "Supprimer cet import"
@@ -15,7 +16,9 @@ fr:
title: "Imports"
warning: ""
new:
- title: "Imports"
+ title: "Générer un import"
+ create:
+ title: "Générer un import"
show:
title: "Import %{name}"
report: "Rapport"
@@ -74,3 +77,7 @@ fr:
max_distance_for_connection_link: "Distance max pour créer les correspondances"
ignore_last_word: "ignorer le dernier mot"
ignore_end_chars: "ignorer les n derniers caractères"
+ flash:
+ imports:
+ create:
+ notice: "L'import est en cours, veuillez patienter. Actualiser votre page si vous voulez voir l'avancement de votre traitement."
diff --git a/config/locales/journey_patterns.en.yml b/config/locales/journey_patterns.en.yml
index e5248c29c..9d9bc21e2 100644
--- a/config/locales/journey_patterns.en.yml
+++ b/config/locales/journey_patterns.en.yml
@@ -6,6 +6,7 @@ en:
vehicle_journeys_count: "Vehicle journeys: %{count}"
vehicle_journey_at_stops: "Vehicle journey at stops"
actions:
+ index: "Journey patterns"
new: "Add a new journey_pattern"
edit: "Edit this journey pattern"
destroy: "Remove this journey pattern"
diff --git a/config/locales/lines.en.yml b/config/locales/lines.en.yml
index 78d5c36be..8e0189bd8 100644
--- a/config/locales/lines.en.yml
+++ b/config/locales/lines.en.yml
@@ -6,19 +6,28 @@ en:
edit: "Edit this line"
edit_footnotes: "Edit line footnotes"
destroy: "Remove this line"
- destroy_confirm: "Are you sure you want destroy this line?"
- destroy_selection_confirm: "Are you sure you want destroy those lines?"
+ activate: "Activate this line"
+ deactivate: "Deactivate this line"
+ activate_confirm: "Are you sure you want to activate this line ?"
+ deactivate_confirm: "Are you sure you want tode activate this line ?"
+ destroy_confirm: "Are you sure you want to destroy this line ?"
+ destroy_selection_confirm: "Are you sure you want to destroy those lines ?"
import: "Import lines"
export_kml: "Export KML line"
export_kml_all: "Export KML lines"
export_hub: "Export HUB line"
export_hub_all: "Export HUB lines"
+ show: 'Show'
show_network: 'Show network'
show_company: 'Show company'
new:
title: "Add a new line"
+ create:
+ title: "Add a new line"
edit:
title: "Update line %{name}"
+ update:
+ title: "Update line %{name}"
show:
title: "Line %{name}"
routes:
@@ -66,6 +75,7 @@ en:
networks:
name: "Network"
company_id: "Company"
+ company: "Company"
secondary_company: "Secondary company"
companies:
name: "Company"
diff --git a/config/locales/lines.fr.yml b/config/locales/lines.fr.yml
index 35f8792f4..2159f06ab 100644
--- a/config/locales/lines.fr.yml
+++ b/config/locales/lines.fr.yml
@@ -6,6 +6,10 @@ fr:
edit: "Editer cette ligne"
edit_footnotes: "Editer notes en bas de page"
destroy: "Supprimer cette ligne"
+ activate: "Activer cette ligne"
+ deactivate: "Désactiver cette ligne"
+ activate_confirm: "Etes vous sûr d'activer cette ligne ?"
+ deactivate_confirm: "Etes vous sûr de désactiver cette ligne ?"
destroy_confirm: "Etes vous sûr de supprimer cette ligne ?"
destroy_selection_confirm: "Etes vous sûr de supprimer cette sélection de lignes ?"
import: "Importer des lignes"
@@ -13,12 +17,17 @@ fr:
export_kml_all: "Export KML des lignes"
export_hub: "Export HUB de la ligne"
export_hub_all: "Export HUB des lignes"
+ show: 'Consulter'
show_network: 'Voir le réseau'
show_company: 'Voir le transporteur principal'
new:
title: "Ajouter une ligne"
+ create:
+ title: "Ajouter une ligne"
edit:
title: "Editer la ligne %{name}"
+ update:
+ title: "Editer la ligne %{name}"
show:
title: "Ligne %{name}"
routes:
@@ -67,6 +76,7 @@ fr:
networks:
name: "Réseau"
company_id: "Transporteur principal"
+ company: "Transporteur principal"
secondary_company: "Transporteurs secondaires"
companies:
name: "Transporteur principal"
@@ -74,7 +84,7 @@ fr:
deactivated: "Activé"
name: "Nom de la ligne"
published_name: "Nom public"
- number: "Nom court"
+ number: "Numéro"
transport_mode: "Mode de transport"
transport_submode: "Sous mode de transport"
seasonal: "Saisonnière"
diff --git a/config/locales/merges.yml b/config/locales/merges.yml
new file mode 100644
index 000000000..d8511a7b4
--- /dev/null
+++ b/config/locales/merges.yml
@@ -0,0 +1,23 @@
+fr:
+ merges:
+ referential_name: "Offre finalisée %{date}"
+ index:
+ title: "Finalisations de l'offre"
+ new:
+ title: "Nouvelle finalisation de l'offre"
+ show:
+ title: "Finalisation de l'offre %{name}"
+ actions:
+ create: "Finaliser des Jeux de Données"
+ activerecord:
+ models:
+ merge: "Finalisation de l'offre"
+ attributes:
+ merge:
+ created_at: "Créé le"
+ started_at: Démarrage
+ name: Nom
+ ended_at: Achevé à
+ status: "Etat"
+ creator: "Demandeur"
+ referentials: "Jeux de données"
diff --git a/config/locales/purchase_windows.en.yml b/config/locales/purchase_windows.en.yml
new file mode 100644
index 000000000..9ce05a1b9
--- /dev/null
+++ b/config/locales/purchase_windows.en.yml
@@ -0,0 +1,79 @@
+en:
+ purchase_windows:
+ search_no_results: 'No purchase window matching your query'
+ days:
+ monday: M
+ tuesday: Tu
+ wednesday: W
+ thursday: Th
+ friday: F
+ saturday: Sa
+ sunday: Su
+ months:
+ 1: January
+ 2: February
+ 3: March
+ 4: April
+ 5: May
+ 6: June
+ 7: July
+ 8: August
+ 9: September
+ 10: October
+ 11: November
+ 12: December
+ actions:
+ new: Add a new purchase window
+ show: "Show"
+ edit: Edit this purchase window
+ destroy: Remove this purchase window
+ destroy_confirm: Are you sure you want destroy this purchase window?
+ errors:
+ overlapped_periods: Another period is overlapped with this period
+ short_period: A period needs to last at least two days
+ index:
+ title: purchase windows
+ all: All
+ shared: Shared
+ not_shared: Not shared
+ search_no_results: No purchase window matching your query
+ date: Date
+ filter_placeholder: Put the name of a purchase window...
+ create:
+ title: Add a new purchase window
+ new:
+ title: Add a new purchase window
+ edit:
+ title: Update purchase window %{name}
+ show:
+ title: purchase window %{name}
+ simple_form:
+ labels:
+ purchase_window:
+ date_value: Date
+ add_a_date: Add a date
+ add_a_date_range: Add a date range
+ ranges:
+ begin: Beginning
+ end: End
+ activerecord:
+ models:
+ purchase_window:
+ zero: purchase window
+ one: purchase window
+ other: purchase windows
+ attributes:
+ purchase_windows:
+ name: Name
+ date_ranges: Date ranges
+ referential: Referential
+ color: Associated Color
+ bounding_dates: Bounding Dates
+ errors:
+ models:
+ purchase_windows:
+ attributes:
+ dates:
+ date_in_date_ranges: A date can not be in Dates and in Date ranges.
+ date_in_dates: A date can appear only once in the list of dates.
+ illegal_date: The date %{date} does not exist.
diff --git a/config/locales/purchase_windows.fr.yml b/config/locales/purchase_windows.fr.yml
new file mode 100644
index 000000000..3d5582ead
--- /dev/null
+++ b/config/locales/purchase_windows.fr.yml
@@ -0,0 +1,80 @@
+fr:
+ purchase_windows:
+ search_no_results: 'Aucun calendrier commercial ne correspond à votre recherche'
+ days:
+ monday: L
+ tuesday: Ma
+ wednesday: Me
+ thursday: J
+ friday: V
+ saturday: S
+ sunday: D
+ months:
+ 1: Janvier
+ 2: Février
+ 3: Mars
+ 4: Avril
+ 5: Mai
+ 6: Juin
+ 7: Juillet
+ 8: Août
+ 9: Septembre
+ 10: Octobre
+ 11: Novembre
+ 12: Décembre
+ actions:
+ new: "Créer un calendrier commercial"
+ show: "Consulter"
+ edit: Editer
+ destroy: Supprimer
+ destroy_confirm: Etes vous sûr de supprimer cet calendrier commercial ?
+ errors:
+ overlapped_periods: Une autre période chevauche cette période
+ short_period: "Une période doit être d'une durée de deux jours minimum"
+ index:
+ title: Calendriers commerciaux
+ all: Tous
+ shared: Partagées
+ not_shared: Non partagées
+ search_no_results: Aucun calendrier commercial ne correspond à votre recherche
+ date: Date
+ filter_placeholder: Indiquez un nom de calendrier commercial...
+ new:
+ title: Ajouter un calendrier commercial
+ create:
+ title: Ajouter un calendrier commercial
+ edit:
+ title: Editer le calendrier commercial %{name}
+ show:
+ title: Calendrier commercial %{name}
+ simple_form:
+ labels:
+ purchase_window:
+ date_value: Date
+ add_a_date: Ajouter une date
+ add_a_date_range: Ajouter un intervalle de dates
+ ranges:
+ begin: Début
+ end: Fin
+ activerecord:
+ models:
+ purchase_window:
+ zero: "calendrier commercial"
+ one: "calendrier commercial"
+ other: "calendriers commerciaux"
+ attributes:
+ purchase_window:
+ name: Nom
+ short_name: Nom court
+ date_ranges: Intervalles de dates
+ referential: Jeu de données
+ color: Couleur associée
+ bounding_dates: Période englobante
+ errors:
+ models:
+ purchase_window:
+ attributes:
+ dates:
+ date_in_date_ranges: Une même date ne peut pas être incluse à la fois dans la liste et dans les intervalles de dates.
+ date_in_dates: Une même date ne peut pas être incluse plusieurs fois dans la liste.
+ illegal_date: La date %{date} n'existe pas.
diff --git a/config/locales/referentials.en.yml b/config/locales/referentials.en.yml
index 8420e9539..b7483c0aa 100644
--- a/config/locales/referentials.en.yml
+++ b/config/locales/referentials.en.yml
@@ -5,7 +5,6 @@ en:
name: 'Search by name'
line: 'Seach by associated lines'
search_no_results: 'No data space matching your query'
- operation_in_progress: The validation process is in progress
error_period_filter: "The period filter must have valid bounding dates"
index:
title: 'Data spaces'
@@ -49,6 +48,14 @@ en:
overlapped_referential: "%{referential} cover the same perimeter"
overlapped_period: "Another period is on the same period"
short_period: Min period length is two days
+ overview:
+ head:
+ dates: Dates
+ lines: Lignes
+ today: Today
+ prev_page: Prev. page
+ next_page: Next page
+
activerecord:
models:
referential:
@@ -92,7 +99,7 @@ en:
routing_constraint_zone: Routing constraint zone
validity_period: "Inclusive validity period"
updated_at: "Updated"
- published_at: "Integrated"
+ merged_at: "Finalized"
archived_at: "Archived"
archived_at_null: "Unarchived"
created_from: 'Created from'
@@ -126,6 +133,8 @@ en:
notice:
referentials:
deleted: "Datasets has been successfully destroyed"
+ duplicate: "The duplication is in progress. Please wait and refresh the page in a few moments."
+ validate: "The validation is in progress. Please wait and refresh the page in a few moments."
referential:
archived: "The data space has been successfully archived"
unarchived: "The data space has been successfully unarchived"
diff --git a/config/locales/referentials.fr.yml b/config/locales/referentials.fr.yml
index ec7ed776d..53183a4c2 100644
--- a/config/locales/referentials.fr.yml
+++ b/config/locales/referentials.fr.yml
@@ -5,22 +5,21 @@ fr:
name: 'Indiquez un nom de jeu de données...'
line: 'Indiquez une ligne...'
search_no_results: 'Aucun jeu de données ne correspond à votre recherche'
- operation_in_progress: L'opération de validation est en cours
error_period_filter: "Le filtre par période doit contenir une date de début et de fin valides"
index:
title: 'Jeux de données'
edit:
title: "Editer le jeu de données"
show:
+ title: "Jeu de données %{name}"
lines: "lignes"
networks: "réseaux"
vehicle_journeys: "courses"
time_tables: "calendriers"
- title: "Jeu de données"
clean_up: "Purge des données obsolètes"
api_keys: "Clés d'authentification pour un accès à l'API REST"
show_all_referentials: Voir tous les jeux de données
- from_this_workbench: Voir les jeux de données de cet gestion de l'offre
+ from_this_workbench: "Voir les jeux de données de cet gestion de l'offre"
counts:
objects: "Eléments"
count: "Qté"
@@ -48,7 +47,15 @@ fr:
user_excluded: "%{user} est une valeur réservée"
overlapped_referential: "%{referential} couvre le même périmètre d'offre"
overlapped_period: "Une autre période chevauche cette période"
- short_period: La durée minimum d'une période est de deux jours
+ short_period: "La durée minimum d'une période est de deux jours"
+ overview:
+ head:
+ dates: Dates
+ lines: Lignes
+ today: Aujourd'hui
+ prev_page: ←
+ next_page: →
+
activerecord:
models:
referential:
@@ -93,7 +100,7 @@ fr:
validity_period: "Période de validité englobante"
updated_at: "Edité le"
created_at: "Créé le"
- published_at: "Intégré le"
+ merged_at: "Finalisé le"
archived_at: "Conservé"
archived_at_null: "En préparation"
created_from: 'Créé à partir de'
@@ -123,7 +130,9 @@ fr:
select_lines: 'Sélection de lignes'
notice:
referentials:
- deleted: "Les jeux de données on été supprimés"
+ deleted: "Les jeux de données ont été supprimés"
+ duplicate: "La duplication est en cours, veuillez patienter. Actualiser votre page si vous voulez voir l'avancement de votre traitement."
+ validate: "La validation est en cours, veuillez patienter. Actualiser votre page si vous voulez voir l'avancement de votre traitement."
referential:
archived: "Le jeu de données a été correctement conservé"
unarchived: "Le jeu de données a été correctement déconservé"
diff --git a/config/locales/routes.en.yml b/config/locales/routes.en.yml
index d82ba98dd..bd8358bdd 100644
--- a/config/locales/routes.en.yml
+++ b/config/locales/routes.en.yml
@@ -13,6 +13,7 @@ en:
export_hub_all: "Export HUB routes"
add_stop_point: "Add stop point"
new_stop_point: "Create new stop"
+ opposite_route_timetable: "Timetable back"
new:
title: "Add a new route"
edit:
@@ -68,6 +69,7 @@ en:
other: "routes"
attributes:
route:
+ checksum: Checksum
wayback:
positive: "forward"
negative: "backward"
diff --git a/config/locales/routes.fr.yml b/config/locales/routes.fr.yml
index 457345ae8..c08e64cfd 100644
--- a/config/locales/routes.fr.yml
+++ b/config/locales/routes.fr.yml
@@ -13,6 +13,7 @@ fr:
export_hub_all: "Export HUB des itinéraires"
add_stop_point: "Ajouter un arrêt"
new_stop_point: "Créer un arrêt pour l'ajouter"
+ opposite_route_timetable: "Horaires retour"
new:
title: "Ajouter un itinéraire"
edit:
@@ -71,6 +72,7 @@ fr:
other: "itinéraires"
attributes:
route:
+ checksum: Signature métier
wayback:
positive: "Aller"
negative: "Retour"
diff --git a/config/locales/routing_constraint_zones.en.yml b/config/locales/routing_constraint_zones.en.yml
index 34a10ac67..5675fd5db 100644
--- a/config/locales/routing_constraint_zones.en.yml
+++ b/config/locales/routing_constraint_zones.en.yml
@@ -7,6 +7,7 @@ en:
other: routing constraint zones
attributes:
routing_constraint_zone:
+ checksum: Checksum
name: Name
stop_areas: Stop areas
line: Line
diff --git a/config/locales/routing_constraint_zones.fr.yml b/config/locales/routing_constraint_zones.fr.yml
index 80bbad8cf..024dd3288 100644
--- a/config/locales/routing_constraint_zones.fr.yml
+++ b/config/locales/routing_constraint_zones.fr.yml
@@ -7,6 +7,7 @@ fr:
other: zone de contraintes
attributes:
routing_constraint_zone:
+ checksum: Signature métier
name: Nom
stop_areas: Arrêts
line: Ligne associée
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index ad722312e..ed4ad2e95 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -1,5 +1,6 @@
en:
simple_form:
+ "per_page": "Per page: "
"yes": 'Yes'
"no": 'No'
from: 'From'
diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml
index cd5dd1fbe..a1868eef7 100644
--- a/config/locales/simple_form.fr.yml
+++ b/config/locales/simple_form.fr.yml
@@ -1,5 +1,6 @@
fr:
simple_form:
+ "per_page": "Afficher par: "
"yes": 'Oui'
"no": 'Non'
from: 'Du'
diff --git a/config/locales/stop_areas.en.yml b/config/locales/stop_areas.en.yml
index 324294892..c1ced1094 100644
--- a/config/locales/stop_areas.en.yml
+++ b/config/locales/stop_areas.en.yml
@@ -1,8 +1,10 @@
en:
stop_areas: &en_stop_areas
+ waiting_time_format: "%{value} minutes"
search_no_results: "No stop area matching your query"
errors:
empty: Aucun stop_area_id
+ parent_area_type: can not be of type %{area_type}
default_geometry_success: "%{count} modified stop areas"
stop_area:
no_position: "No Position"
@@ -14,8 +16,14 @@ en:
accessibility: "Accessibility"
actions:
new: "Add a new stop"
+ create: "Add a new stop"
edit: "Edit this stop"
- destroy: "Remove this stop"
+ update: "Edit this stop"
+ destroy: "Remove"
+ activate: "Activate this stop"
+ deactivate: "Deactivate this stop"
+ activate_confirm: "Are you sure you want to activate this stop ?"
+ deactivate_confirm: "Are you sure you want tode activate this stop ?"
deleted_at: "Activated"
destroy_confirm: "Are you sure you want destroy this stop and all of his children ?"
select_parent: "Create or modify the relation child -> parent"
@@ -40,11 +48,15 @@ en:
area_type: Type an area type...
new:
title: "Add a new stop"
+ update:
+ title: "Add a new stop"
form:
address: "246 Boulevard Saint-Germain, 75007 Paris"
geolocalize: "Pinpoint "
edit:
title: "Update stop %{stop_area}"
+ update:
+ title: "Update stop %{stop_area}"
show:
title: "Stop %{stop_area}"
geographic_data: "Geographic data"
@@ -98,7 +110,7 @@ en:
area_type: "Area type"
nearest_topic_name: "Nearest point of interest"
street_name: "Street name"
- country_code: "INSEE code"
+ country_code: "Country"
fare_code: "Fare code"
mobility_restricted_suitability: "Mobility reduced passenger suitable"
stairs_availability: "Escalator"
@@ -126,6 +138,7 @@ en:
city_name: "City"
created_at: Created at
updated_at: Updated at
+ waiting_time: Waiting time (minutes)
formtastic:
titles:
stop_area:
diff --git a/config/locales/stop_areas.fr.yml b/config/locales/stop_areas.fr.yml
index bf4dd832f..ede1aada6 100644
--- a/config/locales/stop_areas.fr.yml
+++ b/config/locales/stop_areas.fr.yml
@@ -1,8 +1,11 @@
fr:
stop_areas: &fr_stop_areas
+ waiting_time_format: "%{value} minutes"
search_no_results: "Aucun arrêt ne correspond à votre recherche"
errors:
empty: Aucun stop_area_id
+ parent_area_type: ne peut être de type %{area_type}
+ incorrect_kind_area_type: Ce type d'arrêt est invalide pour cette catégorie
default_geometry_success: "%{count} arrêts édités"
stop_area:
no_position: "Pas de position"
@@ -14,8 +17,14 @@ fr:
accessibility: "Accessibilité"
actions:
new: "Ajouter un arrêt"
+ create: "Ajouter un arrêt"
edit: "Editer cet arrêt"
- destroy: "Supprimer cet arrêt"
+ update: "Editer cet arrêt"
+ destroy: "Supprimer"
+ activate: "Activer cet arrêt"
+ deactivate: "Désactiver cet arrêt"
+ activate_confirm: "Etes vous sûr d'activer cet arrêt ?"
+ deactivate_confirm: "Etes vous sûr de désactiver cet arrêt ?"
deleted_at: "Activé"
destroy_confirm: "Etes vous sûr de supprimer cet arrêt ainsi que tous ses fils?"
select_parent: "Créer ou éditer la relation enfant -> parent"
@@ -37,14 +46,18 @@ fr:
name_or_objectid: "Recherche par nom ou par objectid..."
zip_code: Indiquez un code postal...
city_name: Indiquez un nom de commune...
- area_type: Indiquez un type d'arrêt...
+ area_type: "Indiquez un type d'arrêt..."
new:
title: "Ajouter un arrêt"
+ create:
+ title: "Ajouter un arrêt"
form:
address: "246 Boulevard Saint-Germain, 75007 Paris"
geolocalize: "Géolocalisez "
edit:
title: "Editer l'arrêt %{name}"
+ update:
+ title: "Editer l'arrêt %{name}"
show:
title: "Arrêt %{name}"
geographic_data: "Données géographiques"
@@ -89,6 +102,7 @@ fr:
attributes:
stop_area:
name: "Nom"
+ kind: "Catégorie"
registration_number: "Numéro d'enregistrement"
published_name: "Nom public"
deleted: "Supprimé"
@@ -98,7 +112,7 @@ fr:
area_type: "Type d'arrêt"
nearest_topic_name: "Point d'intérêt le plus proche"
street_name: "Nom de la rue"
- country_code: "Code INSEE"
+ country_code: "Pays"
fare_code: "Zone tarifaire"
mobility_restricted_suitability: "Accès pour voyageur à mobilité réduite"
stairs_availability: "Escalator"
@@ -126,6 +140,7 @@ fr:
city_name: "Commune"
created_at: "Créé le"
updated_at: "Edité le"
+ waiting_time: Temps de desserte (minutes)
formtastic:
titles:
stop_area:
diff --git a/config/locales/stop_points.en.yml b/config/locales/stop_points.en.yml
index d22d85731..72e138270 100644
--- a/config/locales/stop_points.en.yml
+++ b/config/locales/stop_points.en.yml
@@ -55,3 +55,4 @@ en:
name: Stop Point
for_boarding: "Pickup"
for_alighting: "Drop off"
+ reflex_id: ID
diff --git a/config/locales/stop_points.fr.yml b/config/locales/stop_points.fr.yml
index d3c873442..71be684f6 100644
--- a/config/locales/stop_points.fr.yml
+++ b/config/locales/stop_points.fr.yml
@@ -52,6 +52,7 @@ fr:
simple_form:
labels:
stop_point:
- name: Arrêt
+ name: Arrêt
for_boarding: "Montée"
for_alighting: "Descente"
+ reflex_id: ID
diff --git a/config/locales/time_tables.en.yml b/config/locales/time_tables.en.yml
index ff36a6d7d..ce890942d 100644
--- a/config/locales/time_tables.en.yml
+++ b/config/locales/time_tables.en.yml
@@ -102,6 +102,7 @@ en:
other: "timetables"
attributes:
time_table:
+ checksum: Checksum
comment: "Name"
color: "Associated color"
bounding_dates: 'Global validity period'
diff --git a/config/locales/time_tables.fr.yml b/config/locales/time_tables.fr.yml
index 631ecca95..8abc0e0af 100644
--- a/config/locales/time_tables.fr.yml
+++ b/config/locales/time_tables.fr.yml
@@ -102,6 +102,7 @@ fr:
other: "calendriers"
attributes:
time_table:
+ checksum: Signature métier
comment: "Nom du calendrier"
color: "Couleur associée"
bounding_dates: 'Période contenue dans le calendrier'
diff --git a/config/locales/vehicle_journeys.en.yml b/config/locales/vehicle_journeys.en.yml
index 7f3871fbf..0c8a75b0c 100644
--- a/config/locales/vehicle_journeys.en.yml
+++ b/config/locales/vehicle_journeys.en.yml
@@ -1,7 +1,14 @@
en:
vehicle_journeys:
vehicle_journeys_matrix:
+ cancel_selection: "Cancel Selection"
+ fetching_error: "There has been a problem fetching the data. Please reload the page to try again."
line_routes: "Line's routes"
+ modal_confirm: 'Do you want to save mofications before moving on to the next page ?'
+ pagination: "Schedules %{minVJ} to %{maxVJ} over %{total}"
+ selected_journeys: "%{count} selected journeys"
+ show_purchase_window: 'Show the purchase window'
+ show_timetable: 'Show calendar'
vehicle_journey:
title_stopless: "Vehicle journey %{name}"
title: "Vehicle journey leaving from %{stop} at %{time}"
@@ -25,48 +32,61 @@ en:
title_stopless: "Update vehicle journey %{name}"
title: "Update vehicle journey %{name} leaving from %{stop} at %{time}"
form:
- stop_title: "Stop"
- departure: "Departure"
+ arrival_at: "Arrival at"
arrival: "Arrival"
- to_arrivals: "Copy departures to arrivals"
- to_departures: "Copy arrivals to departures"
- time_tables: "Associated calendars to vehicle journey"
- slide: "Shift"
- slide_title: "Shift all vehicle passing times"
+ departure_at: "Departure at"
+ departure: "Departure"
+ departure_range:
+ label: Journey departure range
+ start: Start
+ end: End
+ infos: Informations
set: "Set"
- to: "at"
- slide_departure: "departure time at first stop"
+ show_arrival_time: "Show and edit arrival times"
+ show_journeys_with_calendar: "Show journeys with calendar"
+ show_journeys_without_schedule: "Show journeys without schedule"
slide_arrival: "arrival time at first stop"
- submit_timed: "Create vehicle journey"
+ slide_departure: "departure time at first stop"
+ slide_title: "Shift all vehicle passing times"
+ slide: "Shift"
+ stop_title: "Stop"
+ submit_frequency_edit: "Edit frequency vehicle journey"
submit_frequency: "Create frequency vehicle journey"
submit_timed_edit: "Edit vehicle journey"
- submit_frequency_edit: "Edit frequency vehicle journey"
+ submit_timed: "Create vehicle journey"
+ time_tables: "Associated calendars to vehicle journey"
+ to_arrivals: "Copy departures to arrivals"
+ to_departures: "Copy arrivals to departures"
+ to: "at"
timeless:
title: "Timeless vehicle journeys"
vehicle_journeys: "Vehicle journeys with times at stop"
vehicles_list: "Vehicle journeys list"
show:
- title: "Vehicle Journey %{vehicle journey}"
- stop_title: "Stop"
- departure: "Departure"
arrival: "Arrival"
- time_tables: "Calendars list"
bounding: "From %{start} to %{end}"
- translation_form: "Vehicle journey translations"
+ departure: "Departure"
journey_frequencies: "Timeband"
+ stop_title: "Stop"
+ time_tables: "Calendars list"
+ title: "Vehicle Journey %{vehicle journey}"
+ translation_form: "Vehicle journey translations"
index:
- title: "Vehicle journeys on route %{route}"
- vehicle_journeys: "Departure's times"
- selection: "Filter on"
- selection_all: "All"
+ advanced_search: "Advanced Search"
select_journey_patterns: "Select journey pattern"
select_time_tables: "Enter a timetable"
+ selection_all: "All"
+ selection: "Filter on"
time_range: "Departure time threshold"
- advanced_search: "Advanced Search"
+ title: "Vehicle journeys on route %{route}"
+ vehicle_journeys: "Departure's times"
time_filter:
time_range_filter: "Filter"
sidebar:
timeless: "Timeless vehicle journeys"
+ errors:
+ purchase_window: Invalid purchase window
+ time_table: Invalid dates
activerecord:
models:
vehicle_journey:
@@ -75,37 +95,47 @@ en:
other: "vehicle journeys"
attributes:
vehicle_journey:
- line: "Line"
- route: "Route"
- journey_pattern: "Journey Pattern"
- time_tables: "Calendars"
- time_slot: "Time Slot"
- company: "Company"
- number: "Number"
+ accessible: "Accessible"
+ arrival_time: "Arrival"
+ checksum: "Checksum"
comment: "Comments"
- status_value: "Status Value"
- transport_mode: "Transport Mode"
- mobility_restricted_suitability: "PRM accessibility"
+ company: "Company"
+ created_at: Created at
+ creator_id: "Created by"
+ departure_time: "Departure"
+ facility: "Facility"
flexible_service: "On demond transportation"
- unspecified_mrs: "Not specified"
- accessible: "Accessible"
+ footnote_ids: "Footnotes"
+ id: "Journey ID"
+ journey_frequency_ids: "Timeband"
+ journey_name: "Name of the journey"
+ journey_pattern_id: "Pattern ID"
+ journey_pattern: "Journey Pattern"
+ line: "Line"
+ mobility_restricted_suitability: "PRM accessibility"
+ name: "Journey Name"
not_accessible: "Not accessible"
- unspecified_fs: "Not specified"
+ number: "Number"
+ object_version: "Version"
+ objectid: "Neptune identifier"
on_demand_fs: "On demand service"
- regular_fs: "Regular service"
- published_journey_name: "Published Name"
published_journey_identifier: "Published Identifier"
- facility: "Facility"
- vehicle_type_identifier: "Vehicle Type Identifier"
+ published_journey_name: "Published Name"
+ purchase_window: "Purchase availability"
+ regular_fs: "Regular service"
+ route: "Route"
+ status_value: "Status Value"
+ time_slot: "Time Slot"
time_table_ids: "Calendar list"
- vehicle_journey_at_stop_ids: "Time list"
- journey_frequency_ids: "Timeband"
- objectid: "Neptune identifier"
- object_version: "Version"
- created_at: Created at
+ time_tables: "Calendars"
+ train_number: "Train number"
+ transport_mode: "Transport Mode"
+ transport_submode: "Transport Submode"
+ unspecified_fs: "Not specified"
+ unspecified_mrs: "Not specified"
updated_at: Updated at
- creator_id: "Created by"
- footnote_ids: "Footnotes"
+ vehicle_journey_at_stop_ids: "Time list"
+ vehicle_type_identifier: "Vehicle Type Identifier"
errors:
models:
vehicle_journey:
@@ -126,3 +156,9 @@ en:
hub:
vehicle_journey:
objectid: "[prefix]:VehicleJourney:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character. Maximum length of the unique key = 8."
+ referential_vehicle_journeys:
+ index:
+ title: "Vehicle Journeys"
+ search_no_results: "No vehicle journey match your search"
+ filters:
+ published_journey_name_or_objectid: "Search by name or by ID..."
diff --git a/config/locales/vehicle_journeys.fr.yml b/config/locales/vehicle_journeys.fr.yml
index ed4b1c30a..1034a3fba 100644
--- a/config/locales/vehicle_journeys.fr.yml
+++ b/config/locales/vehicle_journeys.fr.yml
@@ -1,7 +1,14 @@
fr:
vehicle_journeys:
vehicle_journeys_matrix:
+ cancel_selection: "Annuler la sélection"
+ fetching_error: "La récupération des missions a rencontré un problème. Rechargez la page pour tenter de corriger le problème."
line_routes: "Séquences d'arrêts de la ligne"
+ modal_confirm: 'Voulez-vous valider vos modifications avant de changer de page?'
+ pagination: "Liste des horaires %{minVJ} à %{maxVJ} sur %{total}"
+ selected_journeys: "%{count} course(s) sélectionnée(s)"
+ show_purchase_window: 'Voir le calendrier commercial'
+ show_timetable: 'Voir le calendrier'
vehicle_journey:
title_stopless: "Course %{name}"
title: "Course partant de %{stop} à %{time}"
@@ -25,48 +32,62 @@ fr:
title_stopless: "Editer la course %{name}"
title: "Editer la course partant de %{stop} à %{time}"
form:
- stop_title: "Arrêt"
- departure: "Départ"
+ arrival_at: "Arrivée à"
arrival: "Arrivée"
- to_arrivals: "Copie départs vers arrivées"
- to_departures: "Copie arrivées vers départs"
- time_tables: "Calendriers associés à la course"
- slide: "Décaler"
- slide_title: "Décaler l'ensemble des horaires de course"
+ departure_at: "Départ à"
+ departure: "Départ"
+ departure_range:
+ label: Plage horaire au départ de la course
+ start: Début
+ end: Fin
+ infos: Informations
set: "Fixer"
- to: "à"
- slide_departure: "horaire de départ au 1° arrêt à"
+ show_arrival_time: "Afficher et éditer les horaires d'arrivée"
+ show_journeys_with_calendar: "Afficher les courses avec calendrier"
+ show_journeys_without_schedule: "Afficher les courses sans horaires"
slide_arrival: "horaire d'arrivée au 1° arrêt à"
- submit_timed: "Créer course"
+ slide_departure: "horaire de départ au 1° arrêt à"
+ slide_title: "Décaler l'ensemble des horaires de course"
+ slide: "Décaler"
+ stop_title: "Arrêt"
+ submit_frequency_edit: "Editer course en fréquence"
submit_frequency: "Créer course en fréquence"
submit_timed_edit: "Editer course"
- submit_frequency_edit: "Editer course en fréquence"
+ submit_timed: "Créer course"
+ time_tables: "Calendriers associés à la course"
+ to_arrivals: "Copie départs vers arrivées"
+ to_arrivals: "Copie départs vers arrivées"
+ to_departures: "Copie arrivées vers départs"
+ to: "à"
timeless:
title: "Courses sans horaire"
vehicle_journeys: "Courses ayant des horaires"
vehicles_list: "Liste des courses"
show:
- title: "Course au départ de %{stop} à %{time} sur la séquence %{route}"
- stop_title: "Arrêt"
- departure: "Départ"
arrival: "Arrivée"
- time_tables: "Liste des calendriers"
bounding: "De %{start} à %{end}"
- translation_form: "Cloner la course"
+ departure: "Départ"
journey_frequencies: "Créneau horaire"
+ stop_title: "Arrêt"
+ time_tables: "Liste des calendriers"
+ title: "Course au départ de %{stop} à %{time} sur la séquence %{route}"
+ translation_form: "Cloner la course"
index:
- title: "Horaires de '%{route}'"
- vehicle_journeys: "Horaires de départ aux arrêts"
- selection: "Filtrer sur"
- selection_all: "Tous"
+ advanced_search: "Recherche avancée"
select_journey_patterns: "Sélectionner une mission"
select_time_tables: "Saisir un calendrier"
+ selection_all: "Tous"
+ selection: "Filtrer sur"
time_range: "Seuil horaire au départ"
- advanced_search: "Recherche avancée"
+ title: "Horaires de '%{route}'"
+ vehicle_journeys: "Horaires de départ aux arrêts"
time_filter:
time_range_filter: "Filtrer"
sidebar:
timeless: "Courses sans horaire"
+ errors:
+ purchase_window: Calendrier commercial invalide
+ time_table: Dates d'application invalides
activerecord:
models:
vehicle_journey:
@@ -75,37 +96,47 @@ fr:
other: "courses"
attributes:
vehicle_journey:
- line: "Ligne"
- route: "Séquence d'arrêt"
- journey_pattern: "Mission"
- time_tables: "Calendriers"
- time_slot: "Fréquence"
- company: "Transporteur"
- number: "Numéro"
+ accessible: "Accessible"
+ arrival_time: "Arrivée"
+ checksum: "Signature métier"
comment: "Commentaires"
- status_value: "Etat de trafic"
- transport_mode: "Mode de transport"
- mobility_restricted_suitability: "Accessibilité PMR"
+ company: "Transporteur"
+ created_at: "Créé le"
+ creator_id: "Créé par"
+ departure_time: "Départ"
+ facility: "Equipement"
flexible_service: "Transport à la demande"
- unspecified_mrs: "Non spécifié"
- accessible: "Accessible"
+ footnote_ids: "Notes de bas de page"
+ id: "ID Course"
+ journey_frequency_ids: "Créneau horaire"
+ journey_name: "Nom de la course"
+ journey_pattern_id: "ID Mission"
+ journey_pattern: "Mission"
+ line: "Ligne"
+ mobility_restricted_suitability: "Accessibilité PMR"
+ name: "Nom Course"
not_accessible: "Non accessible"
- unspecified_fs: "Non spécifié"
+ number: "Numéro"
+ object_version: "Version"
+ objectid: "Identifiant Neptune"
on_demand_fs: "Service à la demande"
- regular_fs: "Service régulier"
- published_journey_name: "Nom public"
published_journey_identifier: "Identifiant public"
- facility: "Equipement"
- vehicle_type_identifier: "Type d'identifiant du véhicule"
+ published_journey_name: "Nom public"
+ purchase_window: "Disponibilité commerciale"
+ regular_fs: "Service régulier"
+ route: "Itinéraire"
+ status_value: "Etat de trafic"
+ time_slot: "Fréquence"
time_table_ids: "Liste des calendriers"
- vehicle_journey_at_stop_ids: "Liste des horaires"
- journey_frequency_ids: "Créneau horaire"
- objectid: "Identifiant Neptune"
- object_version: "Version"
- created_at: "Créé le"
+ time_tables: "Calendriers"
+ train_number: "Numéro de train"
+ transport_mode: "Mode de transport"
+ transport_submode: "Sous-mode de transport"
+ unspecified_fs: "Non spécifié"
+ unspecified_mrs: "Non spécifié"
updated_at: "Edité le"
- creator_id: "Créé par"
- footnote_ids: "Notes de bas de page"
+ vehicle_journey_at_stop_ids: "Liste des horaires"
+ vehicle_type_identifier: "Type d'identifiant du véhicule"
errors:
models:
vehicle_journey:
@@ -126,3 +157,9 @@ fr:
hub:
vehicle_journey:
objectid: "[prefixe]:VehicleJourney:[clé_unique] caractères autorisés : alphanumériques et 'souligné' pour le préfixe, la clé unique accepte en plus le 'moins'. Longueur maximale de la clé unique = 8."
+ referential_vehicle_journeys:
+ index:
+ title: "Courses"
+ search_no_results: "Aucune course ne correspond à votre recherche"
+ filters:
+ published_journey_name_or_objectid: "Indiquez le nom ou l'ID..."
diff --git a/config/locales/workbench_outputs.en.yml b/config/locales/workbench_outputs.en.yml
new file mode 100644
index 000000000..05cf52d0e
--- /dev/null
+++ b/config/locales/workbench_outputs.en.yml
@@ -0,0 +1,7 @@
+en:
+ workbench_outputs:
+ show:
+ title: "Finalisations de l'offre"
+ see_current_output: "Voir l'Offre actuelle"
+ table_headers:
+ ended_at: "Offer created date"
diff --git a/config/locales/workbench_outputs.fr.yml b/config/locales/workbench_outputs.fr.yml
new file mode 100644
index 000000000..560888c54
--- /dev/null
+++ b/config/locales/workbench_outputs.fr.yml
@@ -0,0 +1,7 @@
+fr:
+ workbench_outputs:
+ show:
+ title: "Finalisations de l'offre"
+ see_current_output: "Voir l'Offre actuelle"
+ table_headers:
+ ended_at: "Date et heure de création de l'offre"
diff --git a/config/locales/workbenches.fr.yml b/config/locales/workbenches.fr.yml
index d76255e86..e7a392e66 100644
--- a/config/locales/workbenches.fr.yml
+++ b/config/locales/workbenches.fr.yml
@@ -6,6 +6,8 @@ fr:
zero: "Aucun jeu de données dans cet espace de travail"
one: "1 jeu de données dans cet espace de travail"
other: "#{count} jeux de données dans cet espace de travail"
+ actions:
+ show_output: "Finaliser l'Offre"
activerecord:
models:
workbench:
diff --git a/config/routes.rb b/config/routes.rb
index 65fa62557..0b657b028 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -14,7 +14,11 @@ ChouetteIhm::Application.routes.draw do
resources :compliance_check_sets, only: [:index, :show] do
get :executed, on: :member
resources :compliance_checks, only: [:show]
+ resources :compliance_check_messages, only: [:index]
end
+
+ resource :output, controller: :workbench_outputs
+ resources :merges
end
devise_for :users, :controllers => {
@@ -86,27 +90,42 @@ ChouetteIhm::Application.routes.draw do
resources :compliance_control_blocks, :except => [:show, :index]
end
+ deactivable = Proc.new do
+ put :deactivate, on: :member
+ put :activate, on: :member
+ end
+
resources :stop_area_referentials, :only => [:show] do
post :sync, on: :member
- resources :stop_areas
+ resources :stop_areas do
+ put :deactivate, on: :member
+ put :activate, on: :member
+ get :autocomplete, on: :collection
+ end
end
resources :line_referentials, :only => [:show, :edit, :update] do
post :sync, on: :member
- resources :lines
+ resources :lines, &deactivable
resources :group_of_lines
resources :companies
resources :networks
end
-
- resources :calendars do
- get :autocomplete, on: :collection, controller: 'autocomplete_calendars'
+
+ resources :workgroups do
+ resources :calendars do
+ get :autocomplete, on: :collection, controller: 'autocomplete_calendars'
+ member do
+ get 'month', defaults: { format: :json }
+ end
+ end
end
resources :referentials, except: :index do
resources :autocomplete_stop_areas, only: [:show, :index] do
get 'around', on: :member
end
+ resources :autocomplete_purchase_windows, only: [:index]
get :select_compliance_control_set
post :validate, on: :member
resources :autocomplete_time_tables, only: [:index]
@@ -156,6 +175,8 @@ ChouetteIhm::Application.routes.draw do
resources :routing_constraint_zones
end
+ resources :vehicle_journeys, controller: 'referential_vehicle_journeys', only: [:index]
+
resources :import_tasks, :only => [:new, :create]
resources :export_tasks, :only => [:new, :create] do
collection do
@@ -171,6 +192,8 @@ ChouetteIhm::Application.routes.draw do
resources :companies, controller: "referential_companies"
+ resources :purchase_windows
+
resources :time_tables do
collection do
get :tags
@@ -218,11 +241,21 @@ ChouetteIhm::Application.routes.draw do
root :to => "dashboards#show"
+ if Rails.env.development? || Rails.env.test?
+ get "/snap" => "snapshots#show"
+ end
+
get '/help/(*slug)' => 'help#show'
+ if Rails.application.config.development_toolbar
+ post "/development_toolbar" => "development_toolbar#update_settings", as: :development_toolbar_update_settings
+ end
+
match '/404', to: 'errors#not_found', via: :all, as: 'not_found'
match '/403', to: 'errors#forbidden', via: :all, as: 'forbidden'
match '/422', to: 'errors#server_error', via: :all, as: 'unprocessable_entity'
match '/500', to: 'errors#server_error', via: :all, as: 'server_error'
+ match '/status', to: 'statuses#index', via: :get
+
end
diff --git a/config/schedule.rb b/config/schedule.rb
index 08488c255..0d2a24f31 100644
--- a/config/schedule.rb
+++ b/config/schedule.rb
@@ -40,9 +40,15 @@ every :day, :at => '4:00 am' do
end
every 5.minutes do
+ rake "import:netex_abort_old"
rake "import:notify_parent"
end
+every 5.minutes do
+ rake "compliance_check_sets:abort_old"
+ rake "compliance_check_sets:notify_parent"
+end
+
every 1.minute do
command "/bin/echo HeartBeat"
end
diff --git a/config/webpack/environment.js b/config/webpack/environment.js
index e7c879fb9..743cf66a8 100644
--- a/config/webpack/environment.js
+++ b/config/webpack/environment.js
@@ -1,4 +1,5 @@
const { environment } = require('@rails/webpacker')
+const coffee = require('./loaders/coffee')
const CleanWebpackPlugin = require('clean-webpack-plugin')
let pathsToClean = [
@@ -13,7 +14,7 @@ let cleanOptions = {
};
-environment.plugins.set(
+environment.plugins.append(
'CleanWebpack',
new CleanWebpackPlugin(pathsToClean, cleanOptions)
)
@@ -24,4 +25,5 @@ environment.plugins.set(
// jquery: "jquery/src/jquery",
// }
+environment.loaders.append('coffee', coffee)
module.exports = environment
diff --git a/config/webpack/loaders/coffee.js b/config/webpack/loaders/coffee.js
new file mode 100644
index 000000000..4666716dc
--- /dev/null
+++ b/config/webpack/loaders/coffee.js
@@ -0,0 +1,6 @@
+module.exports = {
+ test: /\.coffee(\.erb)?$/,
+ use: [{
+ loader: 'coffee-loader'
+ }]
+}
diff --git a/config/webpack/production.js b/config/webpack/production.js
index 7703f8452..82478b156 100644
--- a/config/webpack/production.js
+++ b/config/webpack/production.js
@@ -2,7 +2,7 @@ const environment = require('./environment')
const webpack = require('webpack')
const UglifyJsPlugin = require('uglify-js')
-environment.plugins.set(
+environment.plugins.append(
'UglifyJs',
new webpack.optimize.UglifyJsPlugin({
compress: {
diff --git a/config/webpack/staging.js b/config/webpack/staging.js
index 7703f8452..82478b156 100644
--- a/config/webpack/staging.js
+++ b/config/webpack/staging.js
@@ -2,7 +2,7 @@ const environment = require('./environment')
const webpack = require('webpack')
const UglifyJsPlugin = require('uglify-js')
-environment.plugins.set(
+environment.plugins.append(
'UglifyJs',
new webpack.optimize.UglifyJsPlugin({
compress: {
diff --git a/db/migrate/20171212152452_create_merges.rb b/db/migrate/20171212152452_create_merges.rb
new file mode 100644
index 000000000..7915bd91b
--- /dev/null
+++ b/db/migrate/20171212152452_create_merges.rb
@@ -0,0 +1,16 @@
+class CreateMerges < ActiveRecord::Migration
+ def change
+ create_table :merges do |t|
+ t.bigint :workbench_id, index: true, foreign_key: true
+ t.bigint :referential_ids, array: true
+
+ t.string :creator
+ t.string :status
+
+ t.datetime :started_at
+ t.datetime :ended_at
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/migrate/20171214130636_enable_unaccent_extension.rb b/db/migrate/20171214130636_enable_unaccent_extension.rb
new file mode 100644
index 000000000..f7411b1f4
--- /dev/null
+++ b/db/migrate/20171214130636_enable_unaccent_extension.rb
@@ -0,0 +1,9 @@
+class EnableUnaccentExtension < ActiveRecord::Migration
+ def up
+ execute 'CREATE EXTENSION IF NOT EXISTS unaccent SCHEMA shared_extensions;'
+ end
+
+ def down
+ execute 'DROP EXTENSION IF EXISTS unaccent SCHEMA shared_extensions;'
+ end
+end
diff --git a/db/migrate/20171214131755_create_business_calendars.rb b/db/migrate/20171214131755_create_business_calendars.rb
new file mode 100644
index 000000000..aa7c1ab12
--- /dev/null
+++ b/db/migrate/20171214131755_create_business_calendars.rb
@@ -0,0 +1,14 @@
+class CreateBusinessCalendars < ActiveRecord::Migration
+ def change
+ create_table :business_calendars do |t|
+ t.string :name
+ t.string :short_name
+ t.string :color
+ t.daterange :date_ranges, array: true
+ t.date :dates, array: true
+ t.belongs_to :organisation, index: true
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/migrate/20171215144543_rename_business_calendars_to_purchase_windows.rb b/db/migrate/20171215144543_rename_business_calendars_to_purchase_windows.rb
new file mode 100644
index 000000000..d4467d6a7
--- /dev/null
+++ b/db/migrate/20171215144543_rename_business_calendars_to_purchase_windows.rb
@@ -0,0 +1,5 @@
+class RenameBusinessCalendarsToPurchaseWindows < ActiveRecord::Migration
+ def change
+ rename_table :business_calendars, :purchase_windows
+ end
+end
diff --git a/db/migrate/20171215145023_update_purchase_windows_attributes.rb b/db/migrate/20171215145023_update_purchase_windows_attributes.rb
new file mode 100644
index 000000000..48dfb15bc
--- /dev/null
+++ b/db/migrate/20171215145023_update_purchase_windows_attributes.rb
@@ -0,0 +1,13 @@
+class UpdatePurchaseWindowsAttributes < ActiveRecord::Migration
+ def change
+ add_column :purchase_windows, :objectid, :string
+ add_column :purchase_windows, :checksum, :string
+ add_column :purchase_windows, :checksum_source, :text
+
+ remove_column :purchase_windows, :short_name, :string
+ remove_column :purchase_windows, :dates, :date
+ remove_column :purchase_windows, :organisation_id, :integer
+
+ add_reference :purchase_windows, :referential, type: :bigint, index: true
+ end
+end
diff --git a/db/migrate/20171218174509_change_compliance_control_compliance_check_control_attributes_format_from_hstore_to_json.rb b/db/migrate/20171218174509_change_compliance_control_compliance_check_control_attributes_format_from_hstore_to_json.rb
new file mode 100644
index 000000000..0576dddf2
--- /dev/null
+++ b/db/migrate/20171218174509_change_compliance_control_compliance_check_control_attributes_format_from_hstore_to_json.rb
@@ -0,0 +1,33 @@
+class ChangeComplianceControlComplianceCheckControlAttributesFormatFromHstoreToJson < ActiveRecord::Migration
+ def up
+ change_column :compliance_controls,
+ :control_attributes,
+ 'json USING hstore_to_json(control_attributes)'
+ change_column :compliance_checks,
+ :control_attributes,
+ 'json USING hstore_to_json(control_attributes)'
+ end
+
+ def down
+ execute <<-SQL
+ CREATE OR REPLACE FUNCTION my_json_to_hstore(json)
+ RETURNS hstore
+ IMMUTABLE
+ STRICT
+ LANGUAGE sql
+ AS $func$
+ SELECT hstore(array_agg(key), array_agg(value))
+ FROM json_each_text($1)
+ $func$;
+ SQL
+
+ change_column :compliance_controls,
+ :control_attributes,
+ 'hstore USING my_json_to_hstore(control_attributes)'
+ change_column :compliance_checks,
+ :control_attributes,
+ 'hstore USING my_json_to_hstore(control_attributes)'
+
+ execute "DROP FUNCTION my_json_to_hstore(json)"
+ end
+end
diff --git a/db/migrate/20171219170128_add_features_to_organisations.rb b/db/migrate/20171219170128_add_features_to_organisations.rb
new file mode 100644
index 000000000..bbec3297b
--- /dev/null
+++ b/db/migrate/20171219170128_add_features_to_organisations.rb
@@ -0,0 +1,5 @@
+class AddFeaturesToOrganisations < ActiveRecord::Migration
+ def change
+ add_column :organisations, :features, :string, array: true, default: []
+ end
+end
diff --git a/db/migrate/20171220164059_add_waiting_time_to_stop_areas.rb b/db/migrate/20171220164059_add_waiting_time_to_stop_areas.rb
new file mode 100644
index 000000000..369fed3ab
--- /dev/null
+++ b/db/migrate/20171220164059_add_waiting_time_to_stop_areas.rb
@@ -0,0 +1,5 @@
+class AddWaitingTimeToStopAreas < ActiveRecord::Migration
+ def change
+ add_column :stop_areas, :waiting_time, :integer
+ end
+end
diff --git a/db/migrate/20171227113809_create_join_table_purchase_windows_vehicle_journeys.rb b/db/migrate/20171227113809_create_join_table_purchase_windows_vehicle_journeys.rb
new file mode 100644
index 000000000..5460878aa
--- /dev/null
+++ b/db/migrate/20171227113809_create_join_table_purchase_windows_vehicle_journeys.rb
@@ -0,0 +1,8 @@
+class CreateJoinTablePurchaseWindowsVehicleJourneys < ActiveRecord::Migration
+ def change
+ create_join_table :purchase_windows, :vehicle_journeys do |t|
+ t.integer :purchase_window_id, limit: 8
+ t.integer :vehicle_journey_id, limit: 8
+ end
+ end
+end
diff --git a/db/migrate/20180103084612_add_costs_to_journey_patterns.rb b/db/migrate/20180103084612_add_costs_to_journey_patterns.rb
new file mode 100644
index 000000000..6795e3671
--- /dev/null
+++ b/db/migrate/20180103084612_add_costs_to_journey_patterns.rb
@@ -0,0 +1,5 @@
+class AddCostsToJourneyPatterns < ActiveRecord::Migration
+ def change
+ add_column :journey_patterns, :costs, :json
+ end
+end
diff --git a/db/migrate/20180108132310_create_workgroups.rb b/db/migrate/20180108132310_create_workgroups.rb
new file mode 100644
index 000000000..717f05856
--- /dev/null
+++ b/db/migrate/20180108132310_create_workgroups.rb
@@ -0,0 +1,11 @@
+class CreateWorkgroups < ActiveRecord::Migration
+ def change
+ create_table :workgroups do |t|
+ t.string :name
+ t.integer :line_referential_id, limit: 8
+ t.integer :stop_area_referential_id, limit: 8
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/migrate/20180109133022_add_workgroup_id_to_workbenches.rb b/db/migrate/20180109133022_add_workgroup_id_to_workbenches.rb
new file mode 100644
index 000000000..8736f7fbb
--- /dev/null
+++ b/db/migrate/20180109133022_add_workgroup_id_to_workbenches.rb
@@ -0,0 +1,6 @@
+class AddWorkgroupIdToWorkbenches < ActiveRecord::Migration
+ def change
+ add_column :workbenches, :workgroup_id, :integer, limit: 8
+ add_index :workbenches, :workgroup_id
+ end
+end
diff --git a/db/migrate/20180109144120_create_custom_fields.rb b/db/migrate/20180109144120_create_custom_fields.rb
new file mode 100644
index 000000000..49df645c5
--- /dev/null
+++ b/db/migrate/20180109144120_create_custom_fields.rb
@@ -0,0 +1,14 @@
+class CreateCustomFields < ActiveRecord::Migration
+ def change
+ create_table :custom_fields do |t|
+ t.string :code
+ t.string :resource_type
+ t.string :name
+ t.string :field_type
+ t.json :options
+ t.bigint :workgroup_id
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/migrate/20180109173815_add_index_resource_type_on_custom_fields.rb b/db/migrate/20180109173815_add_index_resource_type_on_custom_fields.rb
new file mode 100644
index 000000000..326e85806
--- /dev/null
+++ b/db/migrate/20180109173815_add_index_resource_type_on_custom_fields.rb
@@ -0,0 +1,5 @@
+class AddIndexResourceTypeOnCustomFields < ActiveRecord::Migration
+ def change
+ add_index :custom_fields, :resource_type
+ end
+end
diff --git a/db/migrate/20180109180350_add_custom_field_values_to_vehicle_journeys.rb b/db/migrate/20180109180350_add_custom_field_values_to_vehicle_journeys.rb
new file mode 100644
index 000000000..873dc97d4
--- /dev/null
+++ b/db/migrate/20180109180350_add_custom_field_values_to_vehicle_journeys.rb
@@ -0,0 +1,5 @@
+class AddCustomFieldValuesToVehicleJourneys < ActiveRecord::Migration
+ def change
+ add_column :vehicle_journeys, :custom_field_values, :jsonb, default: {}
+ end
+end
diff --git a/db/migrate/20180111200406_add_merged_at_to_referentials.rb b/db/migrate/20180111200406_add_merged_at_to_referentials.rb
new file mode 100644
index 000000000..27b11fa29
--- /dev/null
+++ b/db/migrate/20180111200406_add_merged_at_to_referentials.rb
@@ -0,0 +1,5 @@
+class AddMergedAtToReferentials < ActiveRecord::Migration
+ def change
+ add_column :referentials, :merged_at, :datetime
+ end
+end
diff --git a/db/migrate/20180123174450_add_workgroup_id_to_calendars.rb b/db/migrate/20180123174450_add_workgroup_id_to_calendars.rb
new file mode 100644
index 000000000..64ad1a752
--- /dev/null
+++ b/db/migrate/20180123174450_add_workgroup_id_to_calendars.rb
@@ -0,0 +1,6 @@
+class AddWorkgroupIdToCalendars < ActiveRecord::Migration
+ def change
+ add_column :calendars, :workgroup_id, :integer, limit: 8
+ add_index :calendars, :workgroup_id
+ end
+end
diff --git a/db/migrate/20180124061955_add_int_day_types_to_calendars.rb b/db/migrate/20180124061955_add_int_day_types_to_calendars.rb
new file mode 100644
index 000000000..5b1ff6fc1
--- /dev/null
+++ b/db/migrate/20180124061955_add_int_day_types_to_calendars.rb
@@ -0,0 +1,5 @@
+class AddIntDayTypesToCalendars < ActiveRecord::Migration
+ def change
+ add_column :calendars, :int_day_types, :integer
+ end
+end
diff --git a/db/migrate/20180124124215_add_excluded_dates_to_calendars.rb b/db/migrate/20180124124215_add_excluded_dates_to_calendars.rb
new file mode 100644
index 000000000..b98b50717
--- /dev/null
+++ b/db/migrate/20180124124215_add_excluded_dates_to_calendars.rb
@@ -0,0 +1,5 @@
+class AddExcludedDatesToCalendars < ActiveRecord::Migration
+ def change
+ add_column :calendars, :excluded_dates, :date, array: true
+ end
+end
diff --git a/db/migrate/20180126134944_add_kind_to_stop_areas.rb b/db/migrate/20180126134944_add_kind_to_stop_areas.rb
new file mode 100644
index 000000000..08f54a6c5
--- /dev/null
+++ b/db/migrate/20180126134944_add_kind_to_stop_areas.rb
@@ -0,0 +1,6 @@
+class AddKindToStopAreas < ActiveRecord::Migration
+ def change
+ add_column :stop_areas, :kind, :string
+ Chouette::StopArea.where.not(kind: :non_commercial).update_all kind: :commercial
+ end
+end
diff --git a/db/migrate/20180129141656_add_localized_names_to_stop_areas.rb b/db/migrate/20180129141656_add_localized_names_to_stop_areas.rb
new file mode 100644
index 000000000..320ce739a
--- /dev/null
+++ b/db/migrate/20180129141656_add_localized_names_to_stop_areas.rb
@@ -0,0 +1,5 @@
+class AddLocalizedNamesToStopAreas < ActiveRecord::Migration
+ def change
+ add_column :stop_areas, :localized_names, :jsonb
+ end
+end
diff --git a/db/migrate/20180202170009_set_stop_areas_kind_to_commercial_on_existing_records.rb b/db/migrate/20180202170009_set_stop_areas_kind_to_commercial_on_existing_records.rb
new file mode 100644
index 000000000..6c6f6370e
--- /dev/null
+++ b/db/migrate/20180202170009_set_stop_areas_kind_to_commercial_on_existing_records.rb
@@ -0,0 +1,11 @@
+class SetStopAreasKindToCommercialOnExistingRecords < ActiveRecord::Migration
+ def up
+ Chouette::StopArea
+ .where('kind != ? or kind is null', :non_commercial)
+ .update_all(kind: :commercial)
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 4a04dac26..596682ce8 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,12 +11,13 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20171130180144) do
+ActiveRecord::Schema.define(version: 20180202170009) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
enable_extension "postgis"
enable_extension "hstore"
+ enable_extension "unaccent"
create_table "access_links", id: :bigserial, force: :cascade do |t|
t.integer "access_point_id", limit: 8
@@ -89,10 +90,14 @@ ActiveRecord::Schema.define(version: 20171130180144) do
t.integer "organisation_id", limit: 8
t.datetime "created_at"
t.datetime "updated_at"
+ t.integer "workgroup_id", limit: 8
+ t.integer "int_day_types"
+ t.date "excluded_dates", array: true
end
add_index "calendars", ["organisation_id"], name: "index_calendars_on_organisation_id", using: :btree
add_index "calendars", ["short_name"], name: "index_calendars_on_short_name", unique: true, using: :btree
+ add_index "calendars", ["workgroup_id"], name: "index_calendars_on_workgroup_id", using: :btree
create_table "clean_up_results", id: :bigserial, force: :cascade do |t|
t.string "message_key"
@@ -207,7 +212,7 @@ ActiveRecord::Schema.define(version: 20171130180144) do
t.integer "compliance_check_set_id", limit: 8
t.integer "compliance_check_block_id", limit: 8
t.string "type"
- t.hstore "control_attributes"
+ t.json "control_attributes"
t.string "name"
t.string "code"
t.string "criticity"
@@ -242,7 +247,7 @@ ActiveRecord::Schema.define(version: 20171130180144) do
create_table "compliance_controls", id: :bigserial, force: :cascade do |t|
t.integer "compliance_control_set_id", limit: 8
t.string "type"
- t.hstore "control_attributes"
+ t.json "control_attributes"
t.string "name"
t.string "code"
t.string "criticity"
@@ -280,6 +285,19 @@ ActiveRecord::Schema.define(version: 20171130180144) do
add_index "connection_links", ["objectid"], name: "connection_links_objectid_key", unique: true, using: :btree
+ create_table "custom_fields", id: :bigserial, force: :cascade do |t|
+ t.string "code"
+ t.string "resource_type"
+ t.string "name"
+ t.string "field_type"
+ t.json "options"
+ t.integer "workgroup_id", limit: 8
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ add_index "custom_fields", ["resource_type"], name: "index_custom_fields_on_resource_type", using: :btree
+
create_table "exports", id: :bigserial, force: :cascade do |t|
t.integer "referential_id", limit: 8
t.string "status"
@@ -402,9 +420,9 @@ ActiveRecord::Schema.define(version: 20171130180144) do
t.string "type"
t.integer "parent_id", limit: 8
t.string "parent_type"
- t.datetime "notified_parent_at"
t.integer "current_step", default: 0
t.integer "total_steps", default: 0
+ t.datetime "notified_parent_at"
t.string "creator"
end
@@ -441,6 +459,7 @@ ActiveRecord::Schema.define(version: 20171130180144) do
t.string "checksum"
t.text "checksum_source"
t.string "data_source_ref"
+ t.json "costs"
end
add_index "journey_patterns", ["objectid"], name: "journey_patterns_objectid_key", unique: true, using: :btree
@@ -521,6 +540,19 @@ ActiveRecord::Schema.define(version: 20171130180144) do
add_index "lines", ["registration_number"], name: "lines_registration_number_key", using: :btree
add_index "lines", ["secondary_company_ids"], name: "index_lines_on_secondary_company_ids", using: :gin
+ create_table "merges", id: :bigserial, force: :cascade do |t|
+ t.integer "workbench_id", limit: 8
+ t.integer "referential_ids", limit: 8, array: true
+ t.string "creator"
+ t.string "status"
+ t.datetime "started_at"
+ t.datetime "ended_at"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ add_index "merges", ["workbench_id"], name: "index_merges_on_workbench_id", using: :btree
+
create_table "networks", id: :bigserial, force: :cascade do |t|
t.string "objectid", null: false
t.integer "object_version", limit: 8
@@ -551,6 +583,7 @@ ActiveRecord::Schema.define(version: 20171130180144) do
t.datetime "synced_at"
t.hstore "sso_attributes"
t.string "custom_view"
+ t.string "features", default: [], array: true
end
add_index "organisations", ["code"], name: "index_organisations_on_code", unique: true, using: :btree
@@ -570,6 +603,25 @@ ActiveRecord::Schema.define(version: 20171130180144) do
add_index "pt_links", ["objectid"], name: "pt_links_objectid_key", unique: true, using: :btree
+ create_table "purchase_windows", id: :bigserial, force: :cascade do |t|
+ t.string "name"
+ t.string "color"
+ t.daterange "date_ranges", array: true
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.string "objectid"
+ t.string "checksum"
+ t.text "checksum_source"
+ t.integer "referential_id", limit: 8
+ end
+
+ add_index "purchase_windows", ["referential_id"], name: "index_purchase_windows_on_referential_id", using: :btree
+
+ create_table "purchase_windows_vehicle_journeys", id: false, force: :cascade do |t|
+ t.integer "purchase_window_id", limit: 8
+ t.integer "vehicle_journey_id", limit: 8
+ end
+
create_table "referential_clonings", id: :bigserial, force: :cascade do |t|
t.string "status"
t.datetime "started_at"
@@ -628,6 +680,7 @@ ActiveRecord::Schema.define(version: 20171130180144) do
t.boolean "ready", default: false
t.integer "referential_suite_id", limit: 8
t.string "objectid_format"
+ t.datetime "merged_at"
end
add_index "referentials", ["created_from_id"], name: "index_referentials_on_created_from_id", using: :btree
@@ -736,6 +789,9 @@ ActiveRecord::Schema.define(version: 20171130180144) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "stif_type"
+ t.integer "waiting_time"
+ t.string "kind"
+ t.jsonb "localized_names"
end
add_index "stop_areas", ["name"], name: "index_stop_areas_on_name", using: :btree
@@ -906,7 +962,7 @@ ActiveRecord::Schema.define(version: 20171130180144) do
t.integer "route_id", limit: 8
t.integer "journey_pattern_id", limit: 8
t.integer "company_id", limit: 8
- t.string "objectid", null: false
+ t.string "objectid", null: false
t.integer "object_version", limit: 8
t.string "comment"
t.string "status_value"
@@ -918,12 +974,13 @@ ActiveRecord::Schema.define(version: 20171130180144) do
t.integer "number", limit: 8
t.boolean "mobility_restricted_suitability"
t.boolean "flexible_service"
- t.integer "journey_category", default: 0, null: false
+ t.integer "journey_category", default: 0, null: false
t.datetime "created_at"
t.datetime "updated_at"
t.string "checksum"
t.text "checksum_source"
t.string "data_source_ref"
+ t.jsonb "custom_field_values", default: {}
end
add_index "vehicle_journeys", ["objectid"], name: "vehicle_journeys_objectid_key", unique: true, using: :btree
@@ -949,11 +1006,21 @@ ActiveRecord::Schema.define(version: 20171130180144) do
t.integer "stop_area_referential_id", limit: 8
t.integer "output_id", limit: 8
t.string "objectid_format"
+ t.integer "workgroup_id", limit: 8
end
add_index "workbenches", ["line_referential_id"], name: "index_workbenches_on_line_referential_id", using: :btree
add_index "workbenches", ["organisation_id"], name: "index_workbenches_on_organisation_id", using: :btree
add_index "workbenches", ["stop_area_referential_id"], name: "index_workbenches_on_stop_area_referential_id", using: :btree
+ add_index "workbenches", ["workgroup_id"], name: "index_workbenches_on_workgroup_id", using: :btree
+
+ create_table "workgroups", id: :bigserial, force: :cascade do |t|
+ t.string "name"
+ t.integer "line_referential_id", limit: 8
+ t.integer "stop_area_referential_id", limit: 8
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
add_foreign_key "access_links", "access_points", name: "aclk_acpt_fkey"
add_foreign_key "api_keys", "organisations"
diff --git a/db/seeds/stif.seeds.rb b/db/seeds/stif.seeds.rb
index 464601557..f898021ce 100644
--- a/db/seeds/stif.seeds.rb
+++ b/db/seeds/stif.seeds.rb
@@ -5,34 +5,41 @@
stop_area_referential = StopAreaReferential.find_or_create_by!(name: "Reflex", objectid_format: "stif_netex")
line_referential = LineReferential.find_or_create_by!(name: "CodifLigne", objectid_format: "stif_netex")
+workgroup = Workgroup.find_or_create_by!(name: "Gestion de l'offre théorique IDFm") do |w|
+ w.line_referential = line_referential
+ w.stop_area_referential = stop_area_referential
+end
+
+Workbench.update_all workgroup_id: workgroup
+
# Organisations
stif = Organisation.find_or_create_by!(code: "STIF") do |org|
org.name = 'STIF'
end
-operator = Organisation.find_or_create_by!(code: 'transporteur-a') do |organisation|
- organisation.name = "Transporteur A"
-end
+# operator = Organisation.find_or_create_by!(code: 'transporteur-a') do |organisation|
+# organisation.name = "Transporteur A"
+# end
# Member
line_referential.add_member stif, owner: true
-line_referential.add_member operator
+# line_referential.add_member operator
stop_area_referential.add_member stif, owner: true
-stop_area_referential.add_member operator
+# stop_area_referential.add_member operator
# Users
-stif.users.find_or_create_by!(username: "admin") do |user|
- user.email = 'stif-boiv@af83.com'
- user.password = "secret"
- user.name = "STIF Administrateur"
-end
-
-operator.users.find_or_create_by!(username: "transporteur") do |user|
- user.email = 'stif-boiv+transporteur@af83.com'
- user.password = "secret"
- user.name = "Martin Lejeune"
-end
+# stif.users.find_or_create_by!(username: "admin") do |user|
+# user.email = 'stif-boiv@af83.com'
+# user.password = "secret"
+# user.name = "STIF Administrateur"
+# end
+#
+# operator.users.find_or_create_by!(username: "transporteur") do |user|
+# user.email = 'stif-boiv+transporteur@af83.com'
+# user.password = "secret"
+# user.name = "Martin Lejeune"
+# end
# Include all Lines in organisation functional_scope
stif.update sso_attributes: { functional_scope: line_referential.lines.pluck(:objectid) }
-operator.update sso_attributes: { functional_scope: line_referential.lines.limit(3).pluck(:objectid) }
+#operator.update sso_attributes: { functional_scope: line_referential.lines.limit(3).pluck(:objectid) }
diff --git a/lib/af83/decorator.rb b/lib/af83/decorator.rb
new file mode 100644
index 000000000..71cf1170d
--- /dev/null
+++ b/lib/af83/decorator.rb
@@ -0,0 +1,131 @@
+class AF83::Decorator < ModelDecorator
+ include AF83::Decorator::EnhancedDecorator
+ extend AF83::Decorator::EnhancedDecorator::ClassMethods
+
+ class << self
+ def decorates klass
+ instance_decorator.decorates klass
+ end
+
+ def instance_decorator
+ @instance_decorator ||= begin
+ klass = Class.new(AF83::Decorator::InstanceDecorator)
+ klass.delegate_all
+ klass
+ end
+ end
+
+ def with_instance_decorator
+ @_with_instance_decorator = true
+ yield instance_decorator
+ @_with_instance_decorator = false
+ end
+
+ def decorate object, options = {}
+ if object.is_a?(ActiveRecord::Base)
+ return instance_decorator.decorate object, options
+ else
+ self.new object, options.update(with: instance_decorator)
+ end
+ end
+
+ def define_instance_method method_name, &block
+ instance_decorator.send(:define_method, method_name, &block)
+ end
+
+ # Defines a class method on the decorated object's class. These
+ # can be called like `object.class.my_method`.
+ def define_instance_class_method method_name, &block
+ instance_decorator.send(:define_singleton_method, method_name, &block)
+ end
+
+ def set_scope_with_instance_decorator value=nil, &block
+ set_scope_without_instance_decorator value, &block
+ instance_decorator.set_scope value, &block
+ end
+
+ alias_method_chain :set_scope, :instance_decorator
+ end
+
+ class ActionLinks
+ attr_reader :options
+
+ delegate :each, :map, :size, :first, :last, :any?, :select, to: :resolve
+
+ def initialize opts
+ @options = opts.deep_dup
+ end
+
+ def for_group group
+ returning_a_copy do
+ @options[:groups] = [group] if group.present?
+ end
+ end
+
+ def for_groups groups
+ returning_a_copy do
+ @options[:groups] = groups if groups.present?
+ end
+ end
+
+ def primary
+ for_group :primary
+ end
+
+ def secondary
+ for_group :secondary
+ end
+
+ def resolve
+ out = @options[:links].map{|l| l.bind_to_context(@options[:context], @options[:action])}.select{|l| l.enabled?}
+ if @options[:groups].present?
+ out = out.select do |l|
+ @options[:groups].any? do |g|
+ l.in_group_for_action?(g)
+ end
+ end
+ end
+ out
+ end
+ alias_method :to_ary, :resolve
+
+ def grouped_by *groups
+ add_footer = groups.include?(:footer)
+ groups -= [:footer]
+ out = HashWithIndifferentAccess[*groups.map{|g| [g, []]}.flatten(1)]
+ out[:other] = []
+ if add_footer
+ out[:footer] = []
+ groups << :footer
+ end
+
+ each do |l|
+ found = false
+ groups.each do |g|
+ if l.in_group_for_action?(g)
+ out[g] << l
+ found = true
+ next
+ end
+ end
+ out[:other] << l unless found
+ end
+ out
+ end
+
+ private
+ def returning_a_copy &block
+ out = ActionLinks.new options
+ out.instance_eval &block
+ out
+ end
+ end
+
+ class IncompleteLinkDefinition < RuntimeError
+ end
+
+ class InstanceDecorator < Draper::Decorator
+ include AF83::Decorator::EnhancedDecorator
+ extend AF83::Decorator::EnhancedDecorator::ClassMethods
+ end
+end
diff --git a/lib/af83/decorator/enhanced_decorator.rb b/lib/af83/decorator/enhanced_decorator.rb
new file mode 100644
index 000000000..fff8bb8b3
--- /dev/null
+++ b/lib/af83/decorator/enhanced_decorator.rb
@@ -0,0 +1,159 @@
+module AF83::Decorator::EnhancedDecorator
+ module ClassMethods
+ def action_link args={}
+ raise "You are using `action_link` inside a with_instance_decorator block, but not on the instance decorator itself.\n Use `instance_decorator.action_link` or move outside of the block, as this may lead to an unforeseen behaviour." if @_with_instance_decorator
+ args[:if] = @_condition if args[:if].nil?
+
+ options, link_options = parse_options args
+
+ link = AF83::Decorator::Link.new(link_options)
+ instance_exec(link, &options[:before_block]) if options[:before_block]
+ yield link if block_given?
+ raise AF83::Decorator::IncompleteLinkDefinition.new(link.errors) unless link.complete?
+
+ weight = options[:weight] || 1
+ @_action_links ||= []
+ @_action_links[weight] ||= []
+ @_action_links[weight] << link
+ end
+
+ ### Here we define some shortcuts that match dthe default behaviours
+ def create_action_link args={}, &block
+ opts = {
+ on: :index,
+ primary: :index,
+ policy: :create,
+ before_block: -> (l){
+ l.content { h.t('actions.add') }
+ l.href { [:new, scope, object.klass.model_name.singular] }
+ }
+ }
+ action_link opts.update(args), &block
+ end
+
+ def show_action_link args={}, &block
+ opts = {
+ on: :index,
+ primary: :index,
+ before_block: -> (l){
+ l.content { h.t('actions.show') }
+ l.href { [scope, object] }
+ }
+ }
+ action_link opts.update(args), &block
+ end
+
+ def edit_action_link args={}, &block
+ opts = {
+ primary: %i(show index),
+ policy: :edit,
+ before_block: -> (l){
+ l.content { h.t('actions.edit') }
+ l.href { [:edit, scope, object] }
+ }
+ }
+ action_link opts.update(args), &block
+ end
+
+ def destroy_action_link args={}, &block
+ opts = {
+ policy: :destroy,
+ footer: true,
+ secondary: :show,
+ before_block: -> (l){
+ l.content { h.destroy_link_content }
+ l.href { [scope, object] }
+ l.method :delete
+ l.data {{ confirm: h.t('actions.destroy_confirm') }}
+ }
+ }
+ action_link opts.update(args), &block
+ end
+
+ def set_scope value=nil, &block
+ @scope = value || block
+ end
+
+ def scope
+ @scope
+ end
+
+ def t key
+ eval "-> (l){ h.t('#{key}') }"
+ end
+
+ def with_condition condition, &block
+ @_condition = condition
+ instance_eval &block
+ @_condition = nil
+ end
+
+ def action_links action
+ (@_action_links || []).flatten.compact.select{|l| l.for_action?(action)}
+ end
+
+ def parse_options args
+ options = {}
+ %i(weight primary secondary footer on action actions policy feature if groups group before_block).each do |k|
+ options[k] = args.delete(k) if args.has_key?(k)
+ end
+ link_options = args.dup
+
+ actions = options.delete :actions
+ actions ||= options.delete :on
+ actions ||= [options.delete(:action)]
+ actions = [actions] unless actions.is_a?(Array)
+ link_options[:_actions] = actions.compact
+
+ link_options[:_groups] = options.delete(:groups)
+ link_options[:_groups] ||= {}
+ if single_group = options.delete(:group)
+ if(single_group.is_a?(Symbol) || single_group.is_a?(String))
+ link_options[:_groups][single_group] = true
+ else
+ link_options[:_groups].update single_group
+ end
+ end
+ link_options[:_groups][:primary] ||= options.delete :primary
+ link_options[:_groups][:secondary] ||= options.delete :secondary
+ link_options[:_groups][:footer] ||= options.delete :footer
+
+ link_options[:_if] = options.delete(:if)
+ link_options[:_policy] = options.delete(:policy)
+ link_options[:_feature] = options.delete(:feature)
+ [options, link_options]
+ end
+ end
+
+ def action_links action=:index, opts={}
+ @action = action&.to_sym
+ links = AF83::Decorator::ActionLinks.new links: self.class.action_links(action), context: self, action: action
+ group = opts[:group]
+ links = links.for_group opts[:group]
+ links
+ end
+
+ def primary_links action=:index
+ action_links(action, group: :primary)
+ end
+
+ def secondary_links action=:index
+ action_links(action, group: :secondary)
+ end
+
+ def check_policy policy
+ _object = policy.to_s == "create" ? object.klass : object
+ method = "#{policy}?"
+ h.policy(_object).send(method)
+ end
+
+ def check_feature feature
+ h.has_feature? feature
+ end
+
+ def scope
+ scope = self.class.scope
+ scope = instance_exec &scope if scope.is_a? Proc
+ scope
+ end
+end
diff --git a/lib/af83/decorator/link.rb b/lib/af83/decorator/link.rb
new file mode 100644
index 000000000..ee09f80dc
--- /dev/null
+++ b/lib/af83/decorator/link.rb
@@ -0,0 +1,156 @@
+class AF83::Decorator::Link
+ REQUIRED_ATTRIBUTES = %i(href content)
+
+ attr_reader :context
+ attr_reader :action
+
+ def initialize options={}
+ @options = {}
+ options.each do |k, v|
+ send "#{k}", v
+ end
+ end
+
+ def bind_to_context context, action
+ @context = context
+ @action = action
+ self
+ end
+
+ def method *args
+ link_method *args
+ end
+
+ def class *args
+ link_class args
+ end
+
+ def method_missing name, *args, &block
+ if block_given?
+ @options[name] = block
+ elsif args.size == 0
+ out = @options[name]
+ out = context.instance_exec(self, &out) if out.is_a?(Proc)
+ out = out.flatten.compact if name.to_s == "href" && out.is_a?(Array)
+ out
+ else
+ # we can use l.foo("bar") or l.foo = "bar"
+ if name.to_s =~ /\=$/
+ _name = name.to_s.gsub(/=$/, '')
+ return send(_name, *args, &block)
+ end
+ @options[name] = args.first
+ end
+ end
+
+ def options
+ @options.symbolize_keys
+ end
+
+ def complete?
+ @missing_attributes = REQUIRED_ATTRIBUTES.select{|a| !@options[a].present?}
+ @missing_attributes.empty?
+ end
+
+ def enabled_actions
+ @options[:_actions].map(&:to_s) || []
+ end
+
+ def for_action? action=nil
+ action ||= @action
+ enabled_actions.empty? || enabled_actions.include?(action.to_s)
+ end
+
+ def actions_for_group group
+ val = @options[:_groups][group]
+ val.is_a?(Array) ? val.map(&:to_s) : val
+ end
+
+ def in_group_for_action? group
+ vals = actions_for_group(group)
+ if vals.is_a?(Array)
+ return vals.include?(@action.to_s)
+ elsif vals.is_a?(String) || vals.is_a?(Symbol)
+ vals.to_s == @action.to_s
+ else
+ !!vals
+ end
+ end
+
+ def primary?
+ in_group_for_action? :primary
+ end
+
+ def secondary?
+ in_group_for_action? :secondary
+ end
+
+ def enabled?
+ enabled = false
+ if @options[:_if].nil?
+ enabled = true
+ elsif @options[:_if].is_a?(Proc)
+ enabled = context.instance_exec(&@options[:_if])
+ else
+ enabled = !!@options[:_if]
+ end
+
+ enabled = enabled && check_policy(@options[:_policy]) if @options[:_policy].present?
+ enabled = enabled && check_feature(@options[:_feature]) if @options[:_feature].present?
+ enabled
+ end
+
+ def check_policy(policy)
+ @context.check_policy policy
+ end
+
+ def check_feature(feature)
+ @context.check_feature feature
+ end
+
+ def errors
+ "Missing attributes: #{@missing_attributes.to_sentence}"
+ end
+
+ def add_class val
+ @options[:link_class] ||= []
+ @options[:link_class] << val
+ @options[:link_class].flatten!
+ end
+
+ def extra_class
+ (options[:link_class] || []).join(' ')
+ end
+
+ def html_options
+ out = {}
+ options.each do |k, v|
+ out[k] = self.send(k) unless k == :content || k == :href || k.to_s =~ /^_/
+ end
+ out[:method] = link_method
+ out[:class] = extra_class
+ out.delete(:link_class)
+ out.delete(:link_method)
+ out[:class] += " disabled" if disabled
+ out[:class].strip!
+ out[:disabled] = !!disabled
+ out
+ end
+
+ def to_html
+ if block_given?
+ link = AF83::Decorator::Link.new(@options).bind_to_context(context, @action)
+ yield link
+ return link.to_html
+ end
+ if type&.to_sym == :button
+ HTMLElement.new(
+ :button,
+ content,
+ html_options
+ ).to_html
+ else
+ context.h.link_to content, href, html_options
+ end
+ end
+end
diff --git a/lib/line_periods.rb b/lib/line_periods.rb
new file mode 100644
index 000000000..c176a7a08
--- /dev/null
+++ b/lib/line_periods.rb
@@ -0,0 +1,35 @@
+class LinePeriods
+
+ def initialize
+ @periods_by_line = Hash.new { |h,k| h[k] = [] }
+ end
+
+ def add(line_id, period)
+ @periods_by_line[line_id] << period
+ end
+
+ def each(&block)
+ @periods_by_line.each do |line_id, periods|
+ yield line_id, periods
+ end
+ end
+
+ def periods(line_id)
+ @periods_by_line[line_id]
+ end
+
+ def self.from_metadatas(metadatas)
+ line_periods = new
+
+ metadatas.each do |metadata|
+ metadata.line_ids.each do |line_id|
+ metadata.periodes.each do |period|
+ line_periods.add(line_id, period)
+ end
+ end
+ end
+
+ line_periods
+ end
+
+end
diff --git a/lib/link.rb b/lib/link.rb
index 7683a808f..33995c2f7 100644
--- a/lib/link.rb
+++ b/lib/link.rb
@@ -1,10 +1,12 @@
class Link
- attr_reader :content, :href, :method, :data
+ attr_reader :content, :href, :method, :data, :extra_class, :disabled
- def initialize(content: nil, href:, method: nil, data: nil)
+ def initialize(content: nil, href:, method: nil, data: nil, extra_class: nil, disabled: false)
@content = content
@href = href
@method = method
@data = data
+ @extra_class = extra_class
+ @disabled = disabled
end
end
diff --git a/lib/range_ext.rb b/lib/range_ext.rb
index f1df5e70d..e7e0e903f 100644
--- a/lib/range_ext.rb
+++ b/lib/range_ext.rb
@@ -1,8 +1,24 @@
class Range
def intersection(other)
- return nil if (self.max < other.min or other.max < self.min)
+ return nil unless intersect?(other)
[self.min, other.min].max..[self.max, other.max].min
end
alias_method :&, :intersection
+
+ def intersect?(other)
+ self.max > other.min and other.max > self.min
+ end
+
+ def remove(other)
+ return self if (self.max < other.min or other.max < self.min)
+
+ [].tap do |remaining|
+ remaining << (self.min..other.min-1) if self.min < other.min
+ remaining << (other.max+1..self.max) if other.max < self.max
+ remaining.compact!
+ end
+ end
+ alias_method :-, :remove
+
end
diff --git a/lib/stif/codifligne_line_id.rb b/lib/stif/codifligne_line_id.rb
new file mode 100644
index 000000000..8c1bcc54b
--- /dev/null
+++ b/lib/stif/codifligne_line_id.rb
@@ -0,0 +1,19 @@
+module STIF
+ module CodifligneLineId extend self
+
+ LINE_OBJECT_ID_SEPERATOR = ':'
+
+ def lines_set_from_functional_scope(functional_scope)
+ Set.new(
+ functional_scope
+ .map{ |line| extract_codif_line_id line })
+ end
+
+
+ private
+
+ def extract_codif_line_id line_name
+ line_name.split(LINE_OBJECT_ID_SEPERATOR).last
+ end
+ end
+end
diff --git a/lib/stif/dashboard.rb b/lib/stif/dashboard.rb
index b6b6b8284..46c635091 100644
--- a/lib/stif/dashboard.rb
+++ b/lib/stif/dashboard.rb
@@ -4,12 +4,16 @@ module Stif
@workbench ||= current_organisation.workbenches.find_by(name: "Gestion de l'offre")
end
+ def workgroup
+ workbench.workgroup
+ end
+
def referentials
@referentials ||= self.workbench.all_referentials
end
def calendars
- @calendars ||= Calendar.where('organisation_id = ? OR shared = ?', current_organisation.id, true)
+ @calendars ||= Calendar.where('(organisation_id = ? OR shared = ?) AND workgroup_id = ?', current_organisation.id, true, workgroup.id)
end
end
end
diff --git a/lib/stif/my_workbench_scopes.rb b/lib/stif/my_workbench_scopes.rb
index 89c4e659c..04bc93089 100644
--- a/lib/stif/my_workbench_scopes.rb
+++ b/lib/stif/my_workbench_scopes.rb
@@ -2,12 +2,13 @@ module Stif
class MyWorkbenchScopes
attr_accessor :workbench
+
def initialize(workbench)
@workbench = workbench
end
def line_scope(initial_scope)
- ids = self.parse_functional_scope
+ ids = parse_functional_scope
ids ? initial_scope.where(objectid: ids) : initial_scope
end
diff --git a/lib/stif/netex_file.rb b/lib/stif/netex_file.rb
index a977c1ad3..db0801bbe 100644
--- a/lib/stif/netex_file.rb
+++ b/lib/stif/netex_file.rb
@@ -2,8 +2,9 @@ module STIF
class NetexFile
CALENDAR_FILE_NAME = 'calendriers.xml'
- LINE_FILE_FORMAT = /^offre_.*\.xml$/
- XML_NAME_SPACE = "http://www.netex.org.uk/netex"
+ LINE_FILE_FORMAT = %r{\A offre_ (?<line_object_id> .*?) _ .* \. xml \z}x
+ XML_NAME_SPACE = "http://www.netex.org.uk/netex"
+
def initialize(file_name)
@file_name = file_name
@@ -13,58 +14,72 @@ module STIF
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
+ add_frame(to_frames: frames, from_entry: entry) if entry.ftype == :file
end
end
frames.values
end
- end
- class NetexFile::Frame
+ private
- attr_accessor :name
+ def add_frame(to_frames:, from_entry:)
+ entry_dir_name, entry_file_name = File.split(from_entry.name)
- def initialize(name)
- @name = name
- end
+ if CALENDAR_FILE_NAME === entry_file_name
+ from_entry.get_input_stream do |stream|
+ to_frames[entry_dir_name].parse_calendars(stream.read)
+ end
+ return
+ 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))
+ line_file_match = LINE_FILE_FORMAT.match( entry_file_name )
+ if line_file_match
+ to_frames[entry_dir_name].add_offer_file( line_file_match['line_object_id'])
end
end
- def add_offer_file(file_name)
- if file_name =~ /^offre_([^_]*)_/
- line_refs << $1
+
+ class Frame
+
+ class << self
+ def get_short_id file_name
+ base_name = File.basename(file_name)
+ STIF::NetexFile::LINE_FILE_FORMAT.match(base_name).try(:[], 'line_object_id')
+ end
end
- end
- def periods
- @periods ||= []
- end
+ attr_accessor :name
- def line_refs
- @line_refs ||= []
- end
+ 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
+
+ def add_offer_file(line_object_id)
+ line_refs << line_object_id
+ end
+ def periods
+ @periods ||= []
+ end
+
+ def line_refs
+ @line_refs ||= []
+ end
+
+ end
end
end
diff --git a/lib/stif/permission_translator.rb b/lib/stif/permission_translator.rb
index 2d267bc7b..9e0feb9b8 100644
--- a/lib/stif/permission_translator.rb
+++ b/lib/stif/permission_translator.rb
@@ -1,11 +1,11 @@
module Stif
module PermissionTranslator extend self
- def translate(sso_extra_permissions)
- sso_extra_permissions
- .sort
+ def translate(sso_extra_permissions, organisation=nil)
+ permissions = sso_extra_permissions.sort
.flat_map(&method(:extra_permission_translation))
- .uniq
+ permissions += extra_organisation_permissions(organisation)
+ permissions.uniq
end
private
@@ -21,6 +21,7 @@ module Stif
calendars
footnotes
imports
+ merges
journey_patterns
referentials
routes
@@ -49,5 +50,12 @@ module Stif
"boiv:edit-offer" => all_destructive_permissions + %w{sessions.create},
}
end
+
+ def extra_organisation_permissions organisation
+ if organisation&.name&.downcase == "stif"
+ return %w{calendars.share stop_area_referentials.synchronize line_referentials.synchronize}
+ end
+ []
+ end
end
end
diff --git a/lib/stif/reflex_synchronization.rb b/lib/stif/reflex_synchronization.rb
index 39a92bd1f..7570e4c49 100644
--- a/lib/stif/reflex_synchronization.rb
+++ b/lib/stif/reflex_synchronization.rb
@@ -151,6 +151,7 @@ module Stif
def create_or_update_stop_area entry
stop = Chouette::StopArea.find_or_create_by(objectid: entry['id'], stop_area_referential: self.defaut_referential )
+ stop.kind = :commercial
stop.deleted_at = nil
{
:comment => 'Description',
diff --git a/lib/tasks/ci.rake b/lib/tasks/ci.rake
index 3e73b7a3b..89f9aa9c8 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:drop db:create db:migrate"
- sh "yarn --production --no-progress install"
+ sh "yarn --no-progress install"
end
def git_branch
@@ -31,18 +31,22 @@ namespace :ci do
sh "bundle exec bundle-audit check --update"
end
- task :spec => ["ci:assets","spec"]
-
task :assets do
sh "RAILS_ENV=test bundle exec rake assets:precompile"
end
- task :jest => "ci:assets" do
- sh "node_modules/.bin/jest"
+ task :i18n_js_export do
+ sh "RAILS_ENV=test bundle exec rake i18n:js:export"
+ end
+
+ task :jest do
+ sh "node_modules/.bin/jest" unless ENV["CHOUETTE_JEST_DISABLED"]
end
desc "Deploy after CI"
task :deploy do
+ return if ENV["CHOUETTE_DEPLOY_DISABLED"]
+
if deploy_env
sh "cap #{deploy_env} deploy:migrations"
else
@@ -58,4 +62,4 @@ namespace :ci do
end
desc "Run continuous integration tasks (spec, ...)"
-task :ci => ["ci:setup", "ci:spec", "ci:jest", "cucumber", "ci:check_security", "ci:deploy", "ci:clean"]
+task :ci => ["ci:setup", "ci:assets", "ci:i18n_js_export", "spec", "ci:jest", "cucumber", "ci:check_security", "ci:deploy", "ci:clean"]
diff --git a/lib/tasks/compliance_check_sets.rb b/lib/tasks/compliance_check_sets.rb
new file mode 100644
index 000000000..c53c7f9ed
--- /dev/null
+++ b/lib/tasks/compliance_check_sets.rb
@@ -0,0 +1,11 @@
+namespace :compliance_check_sets do
+ desc "Notify parent check sets when children finish"
+ task notify_parent: :environment do
+ ParentNotifier.new(ComplianceCheckSet).notify_when_finished
+ end
+
+ desc "Mark old unfinished check sets as 'aborted'"
+ task abort_old: :environment do
+ ComplianceCheckSet.abort_old
+ end
+end
diff --git a/lib/tasks/erd.rake b/lib/tasks/erd.rake
index e2665374e..96bb7fe37 100644
--- a/lib/tasks/erd.rake
+++ b/lib/tasks/erd.rake
@@ -2,12 +2,12 @@ namespace :generate do
desc "Create model diagrams for Chouette"
task :model_diagram => :environment do
- sh "bundle exec rake erd only='Organisation,Referential,User,Workbench' filename='organisation' title='Organisation'"
+ sh "bundle exec rake erd only='Organisation,Referential,User,Workbench,Workgroup' filename='organisation' title='Organisation'"
sh "bundle exec rake erd only='Calendar,Referential,ReferentialMetadata,Chouette::Line,Chouette::Route,Chouette::JourneyPattern,Chouette::VehicleJourney,Chouette::VehicleJourneyAtStop,Chouette::TimeTable,Chouette::TimeTableDate,Chouette::TimeTablePeriod,Chouette::Footnote,Chouette::Network,Chouette::Company,Chouette::StopPoint,Chouette::StopArea' filename='offer_datas' title='Offer Datas'"
sh "bundle exec rake erd only='Organisation,StopAreaReferential,StopAreaReferentialSync,StopAreaReferentialSyncMessage,StopAreaReferentialMembership,LineReferential,LineReferentialSync,LineReferentialSyncMessage,LineReferentialMembership' filename='referentiels_externes' title='Référentiels externes'"
sh "bundle exec rake erd only='NetexImport,Import,WorkbenchImport,ImportResource,ImportMessage' filename='import' title='Import'"
sh "bundle exec rake erd only='ComplianceControlSet,ComplianceControlBlock,ComplianceControl,ComplianceCheckSet,ComplianceCheckBlock,ComplianceCheck,ComplianceCheckResource,ComplianceCheckMessage' filename='validation' title='Validation'"
- sh "bundle exec rake erd only='Organisation,Workbench,ReferentialSuite,Referential' filename='merge' title='Merge'"
+ sh "bundle exec rake erd only='Organisation,Workgroup,Workbench,ReferentialSuite,Referential' filename='merge' title='Merge'"
#sh "bundle exec rake erd only='VehicleJourney,VehicleJourneyExport' filename='export' title='Export'"
#sh "bundle exec rake erd only='' filename='integration' title='Integration'"
#sh "bundle exec rake erd only='' filename='publication' title='Publication'"
diff --git a/lib/tasks/imports.rake b/lib/tasks/imports.rake
index 6bc84acc8..02e32fd3d 100644
--- a/lib/tasks/imports.rake
+++ b/lib/tasks/imports.rake
@@ -1,6 +1,11 @@
namespace :import do
desc "Notify parent imports when children finish"
task notify_parent: :environment do
- ParentImportNotifier.notify_when_finished
+ ParentNotifier.new(Import).notify_when_finished
+ end
+
+ desc "Mark old unfinished Netex imports as 'aborted'"
+ task netex_abort_old: :environment do
+ NetexImport.abort_old
end
end
diff --git a/lib/tasks/referential.rake b/lib/tasks/referential.rake
index 7bab6e040..d53157312 100644
--- a/lib/tasks/referential.rake
+++ b/lib/tasks/referential.rake
@@ -67,4 +67,47 @@ namespace :referential do
referential.update(ready: true)
end
end
+
+ def update_checksums_for_referential referential
+ thing = %w(\\ | / —)
+ Referential.force_register_models_with_checksum if Rails.env.development? && Referential.models_with_checksum.empty?
+ puts "\n \e[33m***\e[0m Referential #{referential.name}"
+ referential.switch do
+ Referential.models_with_checksum.each do |klass|
+ i = 0
+ j = 0
+ prev_size = 1
+ head = "Updating checksums for #{klass.name}: "
+ print head
+ print "⎯"*(80-head.size)
+ print " "
+ count = klass.count
+ klass.find_each do |o|
+ o.update_checksum!
+ if j%10 == 0
+ out = "#{"\b"*prev_size}\e[33m#{thing[i]}\e[0m (#{j}/#{count})"
+ prev_size = out.size - prev_size - 9
+ print out
+ i = (i+1) % thing.size
+ end
+ j += 1
+ end
+ print "#{"\b"*prev_size}\e[32m✓\e[0m (#{count}/#{count})\n"
+ end
+ end
+ end
+
+ desc 'Update all the checksums in the given referential'
+ task :update_checksums_in_referential, [:slug] => :environment do |t, args|
+ referential = Referential.find_by_slug(args[:slug])
+ update_checksums_for_referential referential
+ end
+
+ desc 'Update all the checksums in the given organisation'
+ task :update_checksums_in_organisation, [:organisation_id] => :environment do |t, args|
+ thing = %w(\\ | / —)
+ Organisation.find(args[:organisation_id]).referentials.find_each do |referential|
+ update_checksums_for_referential referential
+ end
+ end
end
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 000000000..35d2de450
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,12274 @@
+{
+ "name": "stif-boiv",
+ "requires": true,
+ "lockfileVersion": 1,
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.0.0-beta.36",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.36.tgz",
+ "integrity": "sha512-sW77BFwJ48YvQp3Gzz5xtAUiXuYOL2aMJKDwiaY3OcvdqBFurtYfOpSa4QrNyDxmOGRFSYzUpabU2m9QrlWE7w==",
+ "dev": true,
+ "requires": {
+ "chalk": "2.3.0",
+ "esutils": "2.0.2",
+ "js-tokens": "3.0.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "@rails/webpacker": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@rails/webpacker/-/webpacker-3.2.0.tgz",
+ "integrity": "sha512-SeeKl54LQs1YjwUlHr3I/Nz9OEludpVWe/dBXo1qJpFGs+99KsRE8flDlQ+B/YLJaF7n9W22PGRnbLS4TGsMiw==",
+ "requires": {
+ "babel-core": "6.26.0",
+ "babel-loader": "7.1.2",
+ "babel-plugin-syntax-dynamic-import": "6.18.0",
+ "babel-plugin-transform-class-properties": "6.24.1",
+ "babel-plugin-transform-object-rest-spread": "6.26.0",
+ "babel-polyfill": "6.26.0",
+ "babel-preset-env": "1.6.1",
+ "case-sensitive-paths-webpack-plugin": "2.1.1",
+ "compression-webpack-plugin": "1.1.3",
+ "css-loader": "0.28.7",
+ "extract-text-webpack-plugin": "3.0.2",
+ "file-loader": "1.1.6",
+ "glob": "7.1.2",
+ "js-yaml": "3.10.0",
+ "node-sass": "4.7.2",
+ "path-complete-extname": "0.1.0",
+ "postcss-cssnext": "3.0.2",
+ "postcss-import": "11.0.0",
+ "postcss-loader": "2.0.9",
+ "sass-loader": "6.0.6",
+ "style-loader": "0.19.1",
+ "webpack": "3.10.0",
+ "webpack-manifest-plugin": "1.3.2"
+ }
+ },
+ "@std/esm": {
+ "version": "0.16.0",
+ "resolved": "https://registry.npmjs.org/@std/esm/-/esm-0.16.0.tgz",
+ "integrity": "sha512-JokzOdnTmxUWJ81VWp0OuSR+VZGuvM9lmnefiPoeTwrOH/wworkRvwkXMpSuso0zYQ0LcbGUKLEdkoKwkYyohg=="
+ },
+ "@types/node": {
+ "version": "8.5.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.2.tgz",
+ "integrity": "sha512-KA4GKOpgXnrqEH2eCVhiv2CsxgXGQJgV1X0vsGlh+WCnxbeAE1GT44ZsTU1IN5dEeV/gDupKa7gWo08V5IxWVQ==",
+ "dev": true
+ },
+ "abab": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz",
+ "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=",
+ "dev": true
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "accepts": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz",
+ "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=",
+ "dev": true,
+ "requires": {
+ "mime-types": "2.1.17",
+ "negotiator": "0.6.1"
+ }
+ },
+ "acorn": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz",
+ "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug=="
+ },
+ "acorn-dynamic-import": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz",
+ "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=",
+ "requires": {
+ "acorn": "4.0.13"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
+ "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
+ }
+ }
+ },
+ "acorn-globals": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.1.0.tgz",
+ "integrity": "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==",
+ "dev": true,
+ "requires": {
+ "acorn": "5.3.0"
+ }
+ },
+ "ajv": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+ "requires": {
+ "co": "4.6.0",
+ "fast-deep-equal": "1.0.0",
+ "fast-json-stable-stringify": "2.0.0",
+ "json-schema-traverse": "0.3.1"
+ }
+ },
+ "ajv-keywords": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
+ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I="
+ },
+ "align-text": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
+ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+ "requires": {
+ "kind-of": "3.2.2",
+ "longest": "1.0.1",
+ "repeat-string": "1.6.1"
+ }
+ },
+ "almond": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/almond/-/almond-0.3.3.tgz",
+ "integrity": "sha1-oOfJWsdiTWQXtElLHmi/9pMWiiA="
+ },
+ "alphanum-sort": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
+ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM="
+ },
+ "amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
+ },
+ "ansi-escapes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz",
+ "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==",
+ "dev": true
+ },
+ "ansi-html": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
+ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ },
+ "anymatch": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
+ "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
+ "requires": {
+ "micromatch": "2.3.11",
+ "normalize-path": "2.1.1"
+ }
+ },
+ "append-transform": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz",
+ "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=",
+ "dev": true,
+ "requires": {
+ "default-require-extensions": "1.0.0"
+ }
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
+ "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
+ "requires": {
+ "delegates": "1.0.0",
+ "readable-stream": "2.3.3"
+ }
+ },
+ "argparse": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
+ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
+ "requires": {
+ "sprintf-js": "1.0.3"
+ }
+ },
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "requires": {
+ "arr-flatten": "1.1.0"
+ }
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="
+ },
+ "array-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
+ "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=",
+ "dev": true
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
+ },
+ "array-flatten": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz",
+ "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=",
+ "dev": true
+ },
+ "array-includes": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
+ "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
+ "dev": true,
+ "requires": {
+ "define-properties": "1.1.2",
+ "es-abstract": "1.10.0"
+ }
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "dev": true,
+ "requires": {
+ "array-uniq": "1.0.3"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM="
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
+ },
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
+ "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
+ },
+ "asn1.js": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz",
+ "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==",
+ "requires": {
+ "bn.js": "4.11.8",
+ "inherits": "2.0.3",
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "assert": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
+ "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+ "requires": {
+ "util": "0.10.3"
+ }
+ },
+ "assert-plus": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
+ "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ="
+ },
+ "astral-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+ "dev": true
+ },
+ "async": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
+ "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==",
+ "requires": {
+ "lodash": "4.17.4"
+ }
+ },
+ "async-each": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0="
+ },
+ "async-foreach": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
+ "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI="
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "autoprefixer": {
+ "version": "6.7.7",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz",
+ "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=",
+ "requires": {
+ "browserslist": "1.7.7",
+ "caniuse-db": "1.0.30000784",
+ "normalize-range": "0.1.2",
+ "num2fraction": "1.2.2",
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0"
+ },
+ "dependencies": {
+ "browserslist": {
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
+ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
+ "requires": {
+ "caniuse-db": "1.0.30000784",
+ "electron-to-chromium": "1.3.30"
+ }
+ }
+ }
+ },
+ "aws-sign2": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
+ "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8="
+ },
+ "aws4": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
+ "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "requires": {
+ "chalk": "1.1.3",
+ "esutils": "2.0.2",
+ "js-tokens": "3.0.2"
+ }
+ },
+ "babel-core": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz",
+ "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=",
+ "requires": {
+ "babel-code-frame": "6.26.0",
+ "babel-generator": "6.26.0",
+ "babel-helpers": "6.24.1",
+ "babel-messages": "6.23.0",
+ "babel-register": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0",
+ "babylon": "6.18.0",
+ "convert-source-map": "1.5.1",
+ "debug": "2.6.9",
+ "json5": "0.5.1",
+ "lodash": "4.17.4",
+ "minimatch": "3.0.4",
+ "path-is-absolute": "1.0.1",
+ "private": "0.1.8",
+ "slash": "1.0.0",
+ "source-map": "0.5.7"
+ }
+ },
+ "babel-generator": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz",
+ "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=",
+ "requires": {
+ "babel-messages": "6.23.0",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "detect-indent": "4.0.0",
+ "jsesc": "1.3.0",
+ "lodash": "4.17.4",
+ "source-map": "0.5.7",
+ "trim-right": "1.0.1"
+ }
+ },
+ "babel-helper-builder-binary-assignment-operator-visitor": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
+ "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
+ "requires": {
+ "babel-helper-explode-assignable-expression": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-builder-react-jsx": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz",
+ "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "esutils": "2.0.2"
+ }
+ },
+ "babel-helper-call-delegate": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
+ "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
+ "requires": {
+ "babel-helper-hoist-variables": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-define-map": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
+ "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=",
+ "requires": {
+ "babel-helper-function-name": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "lodash": "4.17.4"
+ }
+ },
+ "babel-helper-explode-assignable-expression": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
+ "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
+ "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
+ "requires": {
+ "babel-helper-get-function-arity": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-get-function-arity": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
+ "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-hoist-variables": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
+ "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-optimise-call-expression": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
+ "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-regex": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz",
+ "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "lodash": "4.17.4"
+ }
+ },
+ "babel-helper-remap-async-to-generator": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
+ "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=",
+ "requires": {
+ "babel-helper-function-name": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-replace-supers": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
+ "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
+ "requires": {
+ "babel-helper-optimise-call-expression": "6.24.1",
+ "babel-messages": "6.23.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helpers": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
+ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-jest": {
+ "version": "22.0.4",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-22.0.4.tgz",
+ "integrity": "sha512-/Yt61fUpdFjetYlnpj280BPKEsPnK4mqzxDdo8DybPvrPNrLurbAF/WBjn2nnoi1Hc2Ippsf12/aOp8ys/Vl1A==",
+ "requires": {
+ "babel-plugin-istanbul": "4.1.5",
+ "babel-preset-jest": "22.0.3"
+ }
+ },
+ "babel-loader": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.2.tgz",
+ "integrity": "sha512-jRwlFbINAeyDStqK6Dd5YuY0k5YuzQUvlz2ZamuXrXmxav3pNqe9vfJ402+2G+OmlJSXxCOpB6Uz0INM7RQe2A==",
+ "requires": {
+ "find-cache-dir": "1.0.0",
+ "loader-utils": "1.1.0",
+ "mkdirp": "0.5.1"
+ }
+ },
+ "babel-messages": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-check-es2015-constants": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
+ "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-istanbul": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.5.tgz",
+ "integrity": "sha1-Z2DN2Xf0EdPhdbsGTyvDJ9mbK24=",
+ "requires": {
+ "find-up": "2.1.0",
+ "istanbul-lib-instrument": "1.9.1",
+ "test-exclude": "4.1.1"
+ }
+ },
+ "babel-plugin-jest-hoist": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.0.3.tgz",
+ "integrity": "sha512-Z0pOZFs0xDctwF0bPEKrnAzvbbgDi2vDFbQ0EdofnLI2bOa3P1H66gNLb2vMJJaa00VDjfiGhIocsHvBkqtyEQ=="
+ },
+ "babel-plugin-syntax-async-functions": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
+ "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU="
+ },
+ "babel-plugin-syntax-class-properties": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
+ "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94="
+ },
+ "babel-plugin-syntax-dynamic-import": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
+ "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo="
+ },
+ "babel-plugin-syntax-exponentiation-operator": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
+ "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4="
+ },
+ "babel-plugin-syntax-flow": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz",
+ "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0="
+ },
+ "babel-plugin-syntax-jsx": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
+ "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
+ },
+ "babel-plugin-syntax-object-rest-spread": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
+ "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U="
+ },
+ "babel-plugin-syntax-trailing-function-commas": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
+ "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM="
+ },
+ "babel-plugin-transform-async-to-generator": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
+ "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=",
+ "requires": {
+ "babel-helper-remap-async-to-generator": "6.24.1",
+ "babel-plugin-syntax-async-functions": "6.13.0",
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-class-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz",
+ "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=",
+ "requires": {
+ "babel-helper-function-name": "6.24.1",
+ "babel-plugin-syntax-class-properties": "6.13.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-arrow-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
+ "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-block-scoped-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
+ "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-block-scoping": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
+ "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0",
+ "lodash": "4.17.4"
+ }
+ },
+ "babel-plugin-transform-es2015-classes": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
+ "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
+ "requires": {
+ "babel-helper-define-map": "6.26.0",
+ "babel-helper-function-name": "6.24.1",
+ "babel-helper-optimise-call-expression": "6.24.1",
+ "babel-helper-replace-supers": "6.24.1",
+ "babel-messages": "6.23.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-computed-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
+ "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-destructuring": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
+ "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-duplicate-keys": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
+ "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-for-of": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
+ "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
+ "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
+ "requires": {
+ "babel-helper-function-name": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
+ "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-amd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
+ "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
+ "requires": {
+ "babel-plugin-transform-es2015-modules-commonjs": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-commonjs": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz",
+ "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=",
+ "requires": {
+ "babel-plugin-transform-strict-mode": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-systemjs": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
+ "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
+ "requires": {
+ "babel-helper-hoist-variables": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-umd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
+ "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
+ "requires": {
+ "babel-plugin-transform-es2015-modules-amd": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-object-super": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
+ "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
+ "requires": {
+ "babel-helper-replace-supers": "6.24.1",
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-parameters": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
+ "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
+ "requires": {
+ "babel-helper-call-delegate": "6.24.1",
+ "babel-helper-get-function-arity": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-shorthand-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
+ "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-spread": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
+ "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-sticky-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
+ "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
+ "requires": {
+ "babel-helper-regex": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-template-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
+ "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-typeof-symbol": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
+ "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-unicode-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
+ "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
+ "requires": {
+ "babel-helper-regex": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "regexpu-core": "2.0.0"
+ }
+ },
+ "babel-plugin-transform-exponentiation-operator": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
+ "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
+ "requires": {
+ "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1",
+ "babel-plugin-syntax-exponentiation-operator": "6.13.0",
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-flow-strip-types": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz",
+ "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=",
+ "requires": {
+ "babel-plugin-syntax-flow": "6.18.0",
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-object-rest-spread": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz",
+ "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=",
+ "requires": {
+ "babel-plugin-syntax-object-rest-spread": "6.13.0",
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-react-display-name": {
+ "version": "6.25.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz",
+ "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=",
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-react-jsx": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz",
+ "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=",
+ "requires": {
+ "babel-helper-builder-react-jsx": "6.26.0",
+ "babel-plugin-syntax-jsx": "6.18.0",
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-react-jsx-self": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz",
+ "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=",
+ "requires": {
+ "babel-plugin-syntax-jsx": "6.18.0",
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-react-jsx-source": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz",
+ "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=",
+ "requires": {
+ "babel-plugin-syntax-jsx": "6.18.0",
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-regenerator": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
+ "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
+ "requires": {
+ "regenerator-transform": "0.10.1"
+ }
+ },
+ "babel-plugin-transform-strict-mode": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
+ "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-polyfill": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
+ "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "core-js": "2.5.2",
+ "regenerator-runtime": "0.10.5"
+ },
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
+ "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
+ }
+ }
+ },
+ "babel-preset-env": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz",
+ "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==",
+ "requires": {
+ "babel-plugin-check-es2015-constants": "6.22.0",
+ "babel-plugin-syntax-trailing-function-commas": "6.22.0",
+ "babel-plugin-transform-async-to-generator": "6.24.1",
+ "babel-plugin-transform-es2015-arrow-functions": "6.22.0",
+ "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0",
+ "babel-plugin-transform-es2015-block-scoping": "6.26.0",
+ "babel-plugin-transform-es2015-classes": "6.24.1",
+ "babel-plugin-transform-es2015-computed-properties": "6.24.1",
+ "babel-plugin-transform-es2015-destructuring": "6.23.0",
+ "babel-plugin-transform-es2015-duplicate-keys": "6.24.1",
+ "babel-plugin-transform-es2015-for-of": "6.23.0",
+ "babel-plugin-transform-es2015-function-name": "6.24.1",
+ "babel-plugin-transform-es2015-literals": "6.22.0",
+ "babel-plugin-transform-es2015-modules-amd": "6.24.1",
+ "babel-plugin-transform-es2015-modules-commonjs": "6.26.0",
+ "babel-plugin-transform-es2015-modules-systemjs": "6.24.1",
+ "babel-plugin-transform-es2015-modules-umd": "6.24.1",
+ "babel-plugin-transform-es2015-object-super": "6.24.1",
+ "babel-plugin-transform-es2015-parameters": "6.24.1",
+ "babel-plugin-transform-es2015-shorthand-properties": "6.24.1",
+ "babel-plugin-transform-es2015-spread": "6.22.0",
+ "babel-plugin-transform-es2015-sticky-regex": "6.24.1",
+ "babel-plugin-transform-es2015-template-literals": "6.22.0",
+ "babel-plugin-transform-es2015-typeof-symbol": "6.23.0",
+ "babel-plugin-transform-es2015-unicode-regex": "6.24.1",
+ "babel-plugin-transform-exponentiation-operator": "6.24.1",
+ "babel-plugin-transform-regenerator": "6.26.0",
+ "browserslist": "2.10.0",
+ "invariant": "2.2.2",
+ "semver": "5.4.1"
+ }
+ },
+ "babel-preset-es2015": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz",
+ "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=",
+ "requires": {
+ "babel-plugin-check-es2015-constants": "6.22.0",
+ "babel-plugin-transform-es2015-arrow-functions": "6.22.0",
+ "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0",
+ "babel-plugin-transform-es2015-block-scoping": "6.26.0",
+ "babel-plugin-transform-es2015-classes": "6.24.1",
+ "babel-plugin-transform-es2015-computed-properties": "6.24.1",
+ "babel-plugin-transform-es2015-destructuring": "6.23.0",
+ "babel-plugin-transform-es2015-duplicate-keys": "6.24.1",
+ "babel-plugin-transform-es2015-for-of": "6.23.0",
+ "babel-plugin-transform-es2015-function-name": "6.24.1",
+ "babel-plugin-transform-es2015-literals": "6.22.0",
+ "babel-plugin-transform-es2015-modules-amd": "6.24.1",
+ "babel-plugin-transform-es2015-modules-commonjs": "6.26.0",
+ "babel-plugin-transform-es2015-modules-systemjs": "6.24.1",
+ "babel-plugin-transform-es2015-modules-umd": "6.24.1",
+ "babel-plugin-transform-es2015-object-super": "6.24.1",
+ "babel-plugin-transform-es2015-parameters": "6.24.1",
+ "babel-plugin-transform-es2015-shorthand-properties": "6.24.1",
+ "babel-plugin-transform-es2015-spread": "6.22.0",
+ "babel-plugin-transform-es2015-sticky-regex": "6.24.1",
+ "babel-plugin-transform-es2015-template-literals": "6.22.0",
+ "babel-plugin-transform-es2015-typeof-symbol": "6.23.0",
+ "babel-plugin-transform-es2015-unicode-regex": "6.24.1",
+ "babel-plugin-transform-regenerator": "6.26.0"
+ }
+ },
+ "babel-preset-flow": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz",
+ "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=",
+ "requires": {
+ "babel-plugin-transform-flow-strip-types": "6.22.0"
+ }
+ },
+ "babel-preset-jest": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-22.0.3.tgz",
+ "integrity": "sha512-FbMMniSMXFvkKldCf+e4Tuol/v3XMaIpIp8xiT1WFlEW3ZapTKDW9YgVt3hqcpZXsIGFf6eUF3Owxom7yFlI8w==",
+ "requires": {
+ "babel-plugin-jest-hoist": "22.0.3",
+ "babel-plugin-syntax-object-rest-spread": "6.13.0"
+ }
+ },
+ "babel-preset-react": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz",
+ "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=",
+ "requires": {
+ "babel-plugin-syntax-jsx": "6.18.0",
+ "babel-plugin-transform-react-display-name": "6.25.0",
+ "babel-plugin-transform-react-jsx": "6.24.1",
+ "babel-plugin-transform-react-jsx-self": "6.22.0",
+ "babel-plugin-transform-react-jsx-source": "6.22.0",
+ "babel-preset-flow": "6.23.0"
+ }
+ },
+ "babel-register": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
+ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=",
+ "requires": {
+ "babel-core": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "core-js": "2.5.2",
+ "home-or-tmp": "2.0.0",
+ "lodash": "4.17.4",
+ "mkdirp": "0.5.1",
+ "source-map-support": "0.4.18"
+ }
+ },
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "requires": {
+ "core-js": "2.5.2",
+ "regenerator-runtime": "0.11.1"
+ }
+ },
+ "babel-template": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
+ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0",
+ "babylon": "6.18.0",
+ "lodash": "4.17.4"
+ }
+ },
+ "babel-traverse": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+ "requires": {
+ "babel-code-frame": "6.26.0",
+ "babel-messages": "6.23.0",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "babylon": "6.18.0",
+ "debug": "2.6.9",
+ "globals": "9.18.0",
+ "invariant": "2.2.2",
+ "lodash": "4.17.4"
+ }
+ },
+ "babel-types": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "esutils": "2.0.2",
+ "lodash": "4.17.4",
+ "to-fast-properties": "1.0.3"
+ }
+ },
+ "babelify": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/babelify/-/babelify-8.0.0.tgz",
+ "integrity": "sha512-xVr63fKEvMWUrrIbqlHYsMcc5Zdw4FSVesAHgkgajyCE1W8gbm9rbMakqavhxKvikGYMhEcqxTwB/gQmQ6lBtw=="
+ },
+ "babylon": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base64-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
+ "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw=="
+ },
+ "batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
+ "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
+ "optional": true,
+ "requires": {
+ "tweetnacl": "0.14.5"
+ }
+ },
+ "big.js": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
+ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="
+ },
+ "binary-extensions": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
+ "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU="
+ },
+ "bindings": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz",
+ "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==",
+ "dev": true,
+ "optional": true
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+ "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "bluebird": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
+ "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
+ },
+ "bn.js": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="
+ },
+ "body-parser": {
+ "version": "1.18.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
+ "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
+ "dev": true,
+ "requires": {
+ "bytes": "3.0.0",
+ "content-type": "1.0.4",
+ "debug": "2.6.9",
+ "depd": "1.1.1",
+ "http-errors": "1.6.2",
+ "iconv-lite": "0.4.19",
+ "on-finished": "2.3.0",
+ "qs": "6.5.1",
+ "raw-body": "2.3.2",
+ "type-is": "1.6.15"
+ },
+ "dependencies": {
+ "qs": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
+ "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
+ "dev": true
+ }
+ }
+ },
+ "bonjour": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
+ "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+ "dev": true,
+ "requires": {
+ "array-flatten": "2.1.1",
+ "deep-equal": "1.0.1",
+ "dns-equal": "1.0.0",
+ "dns-txt": "2.0.2",
+ "multicast-dns": "6.2.1",
+ "multicast-dns-service-types": "1.1.0"
+ }
+ },
+ "boom": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
+ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "bootstrap": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.3.7.tgz",
+ "integrity": "sha1-WjiTlFSfIzMIdaOxUGVldPip63E="
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "requires": {
+ "expand-range": "1.8.2",
+ "preserve": "0.2.0",
+ "repeat-element": "1.1.2"
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
+ },
+ "browser-process-hrtime": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz",
+ "integrity": "sha1-Ql1opY00R/AqBKqJQYf86K+Le44=",
+ "dev": true
+ },
+ "browser-resolve": {
+ "version": "1.11.2",
+ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz",
+ "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=",
+ "dev": true,
+ "requires": {
+ "resolve": "1.1.7"
+ },
+ "dependencies": {
+ "resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+ "dev": true
+ }
+ }
+ },
+ "browserify-aes": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz",
+ "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==",
+ "requires": {
+ "buffer-xor": "1.0.3",
+ "cipher-base": "1.0.4",
+ "create-hash": "1.1.3",
+ "evp_bytestokey": "1.0.3",
+ "inherits": "2.0.3",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz",
+ "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=",
+ "requires": {
+ "browserify-aes": "1.1.1",
+ "browserify-des": "1.0.0",
+ "evp_bytestokey": "1.0.3"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz",
+ "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=",
+ "requires": {
+ "cipher-base": "1.0.4",
+ "des.js": "1.0.0",
+ "inherits": "2.0.3"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "randombytes": "2.0.5"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "browserify-rsa": "4.0.1",
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "elliptic": "6.4.0",
+ "inherits": "2.0.3",
+ "parse-asn1": "5.1.0"
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "requires": {
+ "pako": "1.0.6"
+ }
+ },
+ "browserslist": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.10.0.tgz",
+ "integrity": "sha512-WyvzSLsuAVPOjbljXnyeWl14Ae+ukAT8MUuagKVzIDvwBxl4UAwD1xqtyQs2eWYPGUKMeC3Ol62goqYuKqTTcw==",
+ "requires": {
+ "caniuse-lite": "1.0.30000784",
+ "electron-to-chromium": "1.3.30"
+ }
+ },
+ "bser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz",
+ "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=",
+ "dev": true,
+ "requires": {
+ "node-int64": "0.4.0"
+ }
+ },
+ "buffer": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+ "requires": {
+ "base64-js": "1.2.1",
+ "ieee754": "1.1.8",
+ "isarray": "1.0.0"
+ }
+ },
+ "buffer-indexof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
+ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
+ "dev": true
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8="
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+ "dev": true
+ },
+ "cacache": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.1.tgz",
+ "integrity": "sha512-dRHYcs9LvG9cHgdPzjiI+/eS7e1xRhULrcyOx04RZQsszNJXU2SL9CyG60yLnge282Qq5nwTv+ieK2fH+WPZmA==",
+ "requires": {
+ "bluebird": "3.5.1",
+ "chownr": "1.0.1",
+ "glob": "7.1.2",
+ "graceful-fs": "4.1.11",
+ "lru-cache": "4.1.1",
+ "mississippi": "1.3.0",
+ "mkdirp": "0.5.1",
+ "move-concurrently": "1.0.1",
+ "promise-inflight": "1.0.1",
+ "rimraf": "2.6.2",
+ "ssri": "5.0.0",
+ "unique-filename": "1.1.0",
+ "y18n": "3.2.1"
+ }
+ },
+ "callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
+ },
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "requires": {
+ "camelcase": "2.1.1",
+ "map-obj": "1.0.1"
+ }
+ },
+ "caniuse-api": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz",
+ "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=",
+ "requires": {
+ "browserslist": "1.7.7",
+ "caniuse-db": "1.0.30000784",
+ "lodash.memoize": "4.1.2",
+ "lodash.uniq": "4.5.0"
+ },
+ "dependencies": {
+ "browserslist": {
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
+ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
+ "requires": {
+ "caniuse-db": "1.0.30000784",
+ "electron-to-chromium": "1.3.30"
+ }
+ }
+ }
+ },
+ "caniuse-db": {
+ "version": "1.0.30000784",
+ "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000784.tgz",
+ "integrity": "sha1-G+lQEtlInHcZB0+BruV9vf/mNhs="
+ },
+ "caniuse-lite": {
+ "version": "1.0.30000784",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000784.tgz",
+ "integrity": "sha1-EpztdOmhKApEGIC2zSvOMO9Z5sA="
+ },
+ "case-sensitive-paths-webpack-plugin": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.1.1.tgz",
+ "integrity": "sha1-PSnO2MHxJL9vU4Rvs/WJRzH9yQk="
+ },
+ "caseless": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
+ "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c="
+ },
+ "center-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
+ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+ "requires": {
+ "align-text": "0.1.4",
+ "lazy-cache": "1.0.4"
+ },
+ "dependencies": {
+ "lazy-cache": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
+ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
+ }
+ }
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ }
+ },
+ "chokidar": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
+ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
+ "requires": {
+ "anymatch": "1.3.2",
+ "async-each": "1.0.1",
+ "fsevents": "1.1.3",
+ "glob-parent": "2.0.0",
+ "inherits": "2.0.3",
+ "is-binary-path": "1.0.1",
+ "is-glob": "2.0.1",
+ "path-is-absolute": "1.0.1",
+ "readdirp": "2.1.0"
+ }
+ },
+ "chownr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz",
+ "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE="
+ },
+ "ci-info": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.2.tgz",
+ "integrity": "sha512-uTGIPNx/nSpBdsF6xnseRXLLtfr9VLqkz8ZqHXr3Y7b6SftyRxBGjwMtJj1OhNbmlc1wZzLNAlAcvyIiE8a6ZA==",
+ "dev": true
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "requires": {
+ "inherits": "2.0.3",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "clap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz",
+ "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==",
+ "requires": {
+ "chalk": "1.1.3"
+ }
+ },
+ "clean-webpack-plugin": {
+ "version": "0.1.17",
+ "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-0.1.17.tgz",
+ "integrity": "sha512-Bts/V725v8Ijosp4K1cqppQXgXcrohxoMsg0CV2xL4y/vua1G5pAfHEW/eJIiKF+GNNG72mdjbipxMRFEms7yg==",
+ "dev": true,
+ "requires": {
+ "rimraf": "2.6.2"
+ }
+ },
+ "cliui": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+ "requires": {
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wrap-ansi": "2.1.0"
+ }
+ },
+ "clone": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz",
+ "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8="
+ },
+ "clone-deep": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.3.0.tgz",
+ "integrity": "sha1-NIxhrpzb4O3+BT2R/0zFIdeQ7eg=",
+ "requires": {
+ "for-own": "1.0.0",
+ "is-plain-object": "2.0.4",
+ "kind-of": "3.2.2",
+ "shallow-clone": "0.1.2"
+ }
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
+ },
+ "coa": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz",
+ "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=",
+ "requires": {
+ "q": "1.5.1"
+ }
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+ },
+ "coffeescript": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.1.0.tgz",
+ "integrity": "sha512-RuEF4gFUV9QSFPREl8gx6w0vS6Ncnr0Nd71lOmxSHfKQFQI66meE54Y636TACbe55j2Lwi6R1O8lOa0dD550GA=="
+ },
+ "color": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz",
+ "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=",
+ "requires": {
+ "clone": "1.0.3",
+ "color-convert": "1.9.1",
+ "color-string": "0.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
+ "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+ },
+ "color-string": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz",
+ "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "colormin": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz",
+ "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=",
+ "requires": {
+ "color": "0.11.4",
+ "css-color-names": "0.0.4",
+ "has": "1.0.1"
+ }
+ },
+ "colors": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM="
+ },
+ "combined-stream": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
+ "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
+ "requires": {
+ "delayed-stream": "1.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.12.2",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz",
+ "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA=="
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
+ },
+ "compressible": {
+ "version": "2.0.12",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz",
+ "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.30.0"
+ }
+ },
+ "compression": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.1.tgz",
+ "integrity": "sha1-7/JgPvwuIs+G810uuTWJ+YdTc9s=",
+ "dev": true,
+ "requires": {
+ "accepts": "1.3.4",
+ "bytes": "3.0.0",
+ "compressible": "2.0.12",
+ "debug": "2.6.9",
+ "on-headers": "1.0.1",
+ "safe-buffer": "5.1.1",
+ "vary": "1.1.2"
+ }
+ },
+ "compression-webpack-plugin": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-1.1.3.tgz",
+ "integrity": "sha512-DIvTIkihu1tyoPdoan5Lh9GVvXgcNMDEgXSfyjlAriW3UaILoPhUFHFTU7Zsui+rPEexmFNlTyiLe0TCkQFJGg==",
+ "requires": {
+ "async": "2.6.0",
+ "cacache": "10.0.1",
+ "find-cache-dir": "1.0.0",
+ "serialize-javascript": "1.4.0",
+ "webpack-sources": "1.1.0"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "concat-stream": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
+ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=",
+ "requires": {
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3",
+ "typedarray": "0.0.6"
+ }
+ },
+ "connect-history-api-fallback": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz",
+ "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=",
+ "dev": true
+ },
+ "console-browserify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+ "requires": {
+ "date-now": "0.1.4"
+ }
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
+ },
+ "content-disposition": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+ "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
+ "dev": true
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "dev": true
+ },
+ "content-type-parser": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.2.tgz",
+ "integrity": "sha512-lM4l4CnMEwOLHAHr/P6MEZwZFPJFtAAKgL6pogbXmVZggIqXhdB6RbBtPOTsw2FcXwYhehRGERJmRrjOiIB8pQ==",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz",
+ "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU="
+ },
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+ "dev": true
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
+ "dev": true
+ },
+ "copy-concurrently": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+ "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+ "requires": {
+ "aproba": "1.2.0",
+ "fs-write-stream-atomic": "1.0.10",
+ "iferr": "0.1.5",
+ "mkdirp": "0.5.1",
+ "rimraf": "2.6.2",
+ "run-queue": "1.0.3"
+ }
+ },
+ "core-js": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.2.tgz",
+ "integrity": "sha1-vEZIZW59ydyA19PHu8Fy2W50TmM="
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "cosmiconfig": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz",
+ "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==",
+ "requires": {
+ "is-directory": "0.3.1",
+ "js-yaml": "3.10.0",
+ "minimist": "1.2.0",
+ "object-assign": "4.1.1",
+ "os-homedir": "1.0.2",
+ "parse-json": "2.2.0",
+ "require-from-string": "1.2.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+ }
+ }
+ },
+ "create-ecdh": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz",
+ "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "elliptic": "6.4.0"
+ }
+ },
+ "create-hash": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
+ "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=",
+ "requires": {
+ "cipher-base": "1.0.4",
+ "inherits": "2.0.3",
+ "ripemd160": "2.0.1",
+ "sha.js": "2.4.9"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz",
+ "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=",
+ "requires": {
+ "cipher-base": "1.0.4",
+ "create-hash": "1.1.3",
+ "inherits": "2.0.3",
+ "ripemd160": "2.0.1",
+ "safe-buffer": "5.1.1",
+ "sha.js": "2.4.9"
+ }
+ },
+ "cross-spawn": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
+ "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
+ "requires": {
+ "lru-cache": "4.1.1",
+ "which": "1.3.0"
+ }
+ },
+ "cryptiles": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
+ "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
+ "requires": {
+ "boom": "2.10.1"
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "requires": {
+ "browserify-cipher": "1.0.0",
+ "browserify-sign": "4.0.4",
+ "create-ecdh": "4.0.0",
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "diffie-hellman": "5.0.2",
+ "inherits": "2.0.3",
+ "pbkdf2": "3.0.14",
+ "public-encrypt": "4.0.0",
+ "randombytes": "2.0.5",
+ "randomfill": "1.0.3"
+ }
+ },
+ "css-color-function": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/css-color-function/-/css-color-function-1.3.3.tgz",
+ "integrity": "sha1-jtJMLAIFBzM5+voAS8jBQfzLKC4=",
+ "requires": {
+ "balanced-match": "0.1.0",
+ "color": "0.11.4",
+ "debug": "3.1.0",
+ "rgb": "0.1.0"
+ },
+ "dependencies": {
+ "balanced-match": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.1.0.tgz",
+ "integrity": "sha1-tQS9BYabOSWd0MXvw12EMXbczEo="
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "css-color-names": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
+ "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA="
+ },
+ "css-loader": {
+ "version": "0.28.7",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.7.tgz",
+ "integrity": "sha512-GxMpax8a/VgcfRrVy0gXD6yLd5ePYbXX/5zGgTVYp4wXtJklS8Z2VaUArJgc//f6/Dzil7BaJObdSv8eKKCPgg==",
+ "requires": {
+ "babel-code-frame": "6.26.0",
+ "css-selector-tokenizer": "0.7.0",
+ "cssnano": "3.10.0",
+ "icss-utils": "2.1.0",
+ "loader-utils": "1.1.0",
+ "lodash.camelcase": "4.3.0",
+ "object-assign": "4.1.1",
+ "postcss": "5.2.18",
+ "postcss-modules-extract-imports": "1.1.0",
+ "postcss-modules-local-by-default": "1.2.0",
+ "postcss-modules-scope": "1.1.0",
+ "postcss-modules-values": "1.3.0",
+ "postcss-value-parser": "3.3.0",
+ "source-list-map": "2.0.0"
+ }
+ },
+ "css-selector-tokenizer": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz",
+ "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=",
+ "requires": {
+ "cssesc": "0.1.0",
+ "fastparse": "1.1.1",
+ "regexpu-core": "1.0.0"
+ },
+ "dependencies": {
+ "regexpu-core": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
+ "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
+ "requires": {
+ "regenerate": "1.3.3",
+ "regjsgen": "0.2.0",
+ "regjsparser": "0.1.5"
+ }
+ }
+ }
+ },
+ "css-unit-converter": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz",
+ "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY="
+ },
+ "cssesc": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
+ "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q="
+ },
+ "cssnano": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz",
+ "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=",
+ "requires": {
+ "autoprefixer": "6.7.7",
+ "decamelize": "1.2.0",
+ "defined": "1.0.0",
+ "has": "1.0.1",
+ "object-assign": "4.1.1",
+ "postcss": "5.2.18",
+ "postcss-calc": "5.3.1",
+ "postcss-colormin": "2.2.2",
+ "postcss-convert-values": "2.6.1",
+ "postcss-discard-comments": "2.0.4",
+ "postcss-discard-duplicates": "2.1.0",
+ "postcss-discard-empty": "2.1.0",
+ "postcss-discard-overridden": "0.1.1",
+ "postcss-discard-unused": "2.2.3",
+ "postcss-filter-plugins": "2.0.2",
+ "postcss-merge-idents": "2.1.7",
+ "postcss-merge-longhand": "2.0.2",
+ "postcss-merge-rules": "2.1.2",
+ "postcss-minify-font-values": "1.0.5",
+ "postcss-minify-gradients": "1.0.5",
+ "postcss-minify-params": "1.2.2",
+ "postcss-minify-selectors": "2.1.1",
+ "postcss-normalize-charset": "1.1.1",
+ "postcss-normalize-url": "3.0.8",
+ "postcss-ordered-values": "2.2.3",
+ "postcss-reduce-idents": "2.4.0",
+ "postcss-reduce-initial": "1.0.1",
+ "postcss-reduce-transforms": "1.0.4",
+ "postcss-svgo": "2.1.6",
+ "postcss-unique-selectors": "2.0.2",
+ "postcss-value-parser": "3.3.0",
+ "postcss-zindex": "2.2.0"
+ }
+ },
+ "csso": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz",
+ "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=",
+ "requires": {
+ "clap": "1.2.3",
+ "source-map": "0.5.7"
+ }
+ },
+ "cssom": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz",
+ "integrity": "sha1-uANhcMefB6kP8vFuIihAJ6JDhIs=",
+ "dev": true
+ },
+ "cssstyle": {
+ "version": "0.2.37",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz",
+ "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=",
+ "dev": true,
+ "requires": {
+ "cssom": "0.3.2"
+ }
+ },
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "requires": {
+ "array-find-index": "1.0.2"
+ }
+ },
+ "cyclist": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
+ "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA="
+ },
+ "d": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
+ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
+ "requires": {
+ "es5-ext": "0.10.37"
+ }
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "date-now": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs="
+ },
+ "dateformat": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "4.0.1",
+ "meow": "3.7.0"
+ }
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "deep-diff": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz",
+ "integrity": "sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ="
+ },
+ "deep-equal": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
+ "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
+ "dev": true
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "default-require-extensions": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz",
+ "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=",
+ "dev": true,
+ "requires": {
+ "strip-bom": "2.0.0"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
+ "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
+ "dev": true,
+ "requires": {
+ "foreach": "2.0.5",
+ "object-keys": "1.0.11"
+ }
+ },
+ "defined": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
+ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM="
+ },
+ "del": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
+ "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=",
+ "dev": true,
+ "requires": {
+ "globby": "6.1.0",
+ "is-path-cwd": "1.0.0",
+ "is-path-in-cwd": "1.0.0",
+ "p-map": "1.2.0",
+ "pify": "3.0.0",
+ "rimraf": "2.6.2"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+ },
+ "depd": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
+ "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=",
+ "dev": true
+ },
+ "des.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+ "requires": {
+ "inherits": "2.0.3",
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
+ "dev": true
+ },
+ "detect-indent": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
+ "requires": {
+ "repeating": "2.0.1"
+ }
+ },
+ "detect-newline": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz",
+ "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=",
+ "dev": true
+ },
+ "detect-node": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz",
+ "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=",
+ "dev": true
+ },
+ "diff": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz",
+ "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz",
+ "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "miller-rabin": "4.0.1",
+ "randombytes": "2.0.5"
+ }
+ },
+ "dns-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+ "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
+ "dev": true
+ },
+ "dns-packet": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.2.2.tgz",
+ "integrity": "sha512-kN+DjfGF7dJGUL7nWRktL9Z18t1rWP3aQlyZdY8XlpvU3Nc6GeFTQApftcjtWKxAZfiggZSGrCEoszNgvnpwDg==",
+ "dev": true,
+ "requires": {
+ "ip": "1.1.5",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "dns-txt": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
+ "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+ "dev": true,
+ "requires": {
+ "buffer-indexof": "1.1.1"
+ }
+ },
+ "domain-browser": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz",
+ "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw="
+ },
+ "domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.0.tgz",
+ "integrity": "sha512-WpwuBlZ2lQRFa4H/4w49deb9rJLot9KmqrKKjMc9qBl7CID+DdC2swoa34ccRl+anL2B6bLp6TjFdIdnzekMBQ==",
+ "dev": true
+ },
+ "duplexify": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz",
+ "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==",
+ "requires": {
+ "end-of-stream": "1.4.0",
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3",
+ "stream-shift": "1.0.0"
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+ "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.1"
+ }
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+ "dev": true
+ },
+ "electron-releases": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/electron-releases/-/electron-releases-2.1.0.tgz",
+ "integrity": "sha512-cyKFD1bTE/UgULXfaueIN1k5EPFzs+FRc/rvCY5tIynefAPqopQEgjr0EzY+U3Dqrk/G4m9tXSPuZ77v6dL/Rw=="
+ },
+ "electron-to-chromium": {
+ "version": "1.3.30",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.30.tgz",
+ "integrity": "sha512-zx1Prv7kYLfc4OA60FhxGbSo4qrEjgSzpo1/37i7l9ltXPYOoQBtjQxY9KmsgfHnBxHlBGXwLlsbt/gub1w5lw==",
+ "requires": {
+ "electron-releases": "2.1.0"
+ }
+ },
+ "elliptic": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
+ "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "brorand": "1.1.0",
+ "hash.js": "1.1.3",
+ "hmac-drbg": "1.0.1",
+ "inherits": "2.0.3",
+ "minimalistic-assert": "1.0.0",
+ "minimalistic-crypto-utils": "1.0.1"
+ }
+ },
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
+ },
+ "encodeurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz",
+ "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=",
+ "dev": true
+ },
+ "encoding": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+ "requires": {
+ "iconv-lite": "0.4.19"
+ }
+ },
+ "end-of-stream": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz",
+ "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=",
+ "requires": {
+ "once": "1.4.0"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz",
+ "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "memory-fs": "0.4.1",
+ "object-assign": "4.1.1",
+ "tapable": "0.2.8"
+ }
+ },
+ "errno": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz",
+ "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==",
+ "requires": {
+ "prr": "1.0.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
+ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
+ "requires": {
+ "is-arrayish": "0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz",
+ "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "1.1.1",
+ "function-bind": "1.1.1",
+ "has": "1.0.1",
+ "is-callable": "1.1.3",
+ "is-regex": "1.0.4"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
+ "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
+ "dev": true,
+ "requires": {
+ "is-callable": "1.1.3",
+ "is-date-object": "1.0.1",
+ "is-symbol": "1.0.1"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.37",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz",
+ "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=",
+ "requires": {
+ "es6-iterator": "2.0.3",
+ "es6-symbol": "3.1.1"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.37",
+ "es6-symbol": "3.1.1"
+ }
+ },
+ "es6-map": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
+ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.37",
+ "es6-iterator": "2.0.3",
+ "es6-set": "0.1.5",
+ "es6-symbol": "3.1.1",
+ "event-emitter": "0.3.5"
+ }
+ },
+ "es6-object-assign": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
+ "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=",
+ "dev": true
+ },
+ "es6-set": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
+ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.37",
+ "es6-iterator": "2.0.3",
+ "es6-symbol": "3.1.1",
+ "event-emitter": "0.3.5"
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
+ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.37"
+ }
+ },
+ "es6-weak-map": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz",
+ "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=",
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.37",
+ "es6-iterator": "2.0.3",
+ "es6-symbol": "3.1.1"
+ }
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ },
+ "escodegen": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz",
+ "integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==",
+ "dev": true,
+ "requires": {
+ "esprima": "3.1.3",
+ "estraverse": "4.2.0",
+ "esutils": "2.0.2",
+ "optionator": "0.8.2",
+ "source-map": "0.5.7"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
+ "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
+ "dev": true
+ }
+ }
+ },
+ "escope": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
+ "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=",
+ "requires": {
+ "es6-map": "0.1.5",
+ "es6-weak-map": "2.0.2",
+ "esrecurse": "4.2.0",
+ "estraverse": "4.2.0"
+ }
+ },
+ "esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE="
+ },
+ "esrecurse": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz",
+ "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=",
+ "requires": {
+ "estraverse": "4.2.0",
+ "object-assign": "4.1.1"
+ }
+ },
+ "estraverse": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+ "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+ "dev": true
+ },
+ "event-emitter": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
+ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.37"
+ }
+ },
+ "eventemitter2": {
+ "version": "0.4.14",
+ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
+ "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=",
+ "dev": true
+ },
+ "eventemitter3": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz",
+ "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=",
+ "dev": true
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
+ },
+ "eventsource": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz",
+ "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=",
+ "dev": true,
+ "requires": {
+ "original": "1.0.0"
+ }
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "requires": {
+ "md5.js": "1.3.4",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "exec-sh": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.1.tgz",
+ "integrity": "sha512-aLt95pexaugVtQerpmE51+4QfWrNc304uez7jvj6fWnN8GeEHpttB8F36n8N7uVhUMbH/1enbxQ9HImZ4w/9qg==",
+ "dev": true,
+ "requires": {
+ "merge": "1.2.0"
+ }
+ },
+ "execa": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "requires": {
+ "cross-spawn": "5.1.0",
+ "get-stream": "3.0.0",
+ "is-stream": "1.1.0",
+ "npm-run-path": "2.0.2",
+ "p-finally": "1.0.0",
+ "signal-exit": "3.0.2",
+ "strip-eof": "1.0.0"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "requires": {
+ "lru-cache": "4.1.1",
+ "shebang-command": "1.2.0",
+ "which": "1.3.0"
+ }
+ }
+ }
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "dev": true
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "requires": {
+ "is-posix-bracket": "0.1.1"
+ }
+ },
+ "expand-range": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+ "requires": {
+ "fill-range": "2.2.3"
+ }
+ },
+ "expect": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-22.0.3.tgz",
+ "integrity": "sha512-QapzeQkcA3jCx4pDnD07I4SPPxScKbey8TD/WwrnzmpHmL5q0dUtXfUt5OIFOjVBCg+C4zn4Y1zK9Rb9SIDL1g==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "jest-diff": "22.0.3",
+ "jest-get-type": "22.0.3",
+ "jest-matcher-utils": "22.0.3",
+ "jest-message-util": "22.0.3",
+ "jest-regex-util": "22.0.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ }
+ }
+ },
+ "express": {
+ "version": "4.16.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz",
+ "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=",
+ "dev": true,
+ "requires": {
+ "accepts": "1.3.4",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.18.2",
+ "content-disposition": "0.5.2",
+ "content-type": "1.0.4",
+ "cookie": "0.3.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "1.1.1",
+ "encodeurl": "1.0.1",
+ "escape-html": "1.0.3",
+ "etag": "1.8.1",
+ "finalhandler": "1.1.0",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "1.1.2",
+ "on-finished": "2.3.0",
+ "parseurl": "1.3.2",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "2.0.2",
+ "qs": "6.5.1",
+ "range-parser": "1.2.0",
+ "safe-buffer": "5.1.1",
+ "send": "0.16.1",
+ "serve-static": "1.13.1",
+ "setprototypeof": "1.1.0",
+ "statuses": "1.3.1",
+ "type-is": "1.6.15",
+ "utils-merge": "1.0.1",
+ "vary": "1.1.2"
+ },
+ "dependencies": {
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
+ "dev": true
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
+ "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
+ "dev": true
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
+ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "extract-text-webpack-plugin": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz",
+ "integrity": "sha512-bt/LZ4m5Rqt/Crl2HiKuAl/oqg0psx1tsTLkvWbJen1CtD+fftkZhMaQ9HOtY2gWsl2Wq+sABmMVi9z3DhKWQQ==",
+ "requires": {
+ "async": "2.6.0",
+ "loader-utils": "1.1.0",
+ "schema-utils": "0.3.0",
+ "webpack-sources": "1.1.0"
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+ },
+ "fast-deep-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
+ "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8="
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "fastparse": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz",
+ "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg="
+ },
+ "faye-websocket": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": "0.7.0"
+ }
+ },
+ "fb-watchman": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz",
+ "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=",
+ "dev": true,
+ "requires": {
+ "bser": "2.0.0"
+ }
+ },
+ "fbjs": {
+ "version": "0.8.16",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz",
+ "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=",
+ "requires": {
+ "core-js": "1.2.7",
+ "isomorphic-fetch": "2.2.1",
+ "loose-envify": "1.3.1",
+ "object-assign": "4.1.1",
+ "promise": "7.3.1",
+ "setimmediate": "1.0.5",
+ "ua-parser-js": "0.7.17"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+ "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
+ }
+ }
+ },
+ "file-loader": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.6.tgz",
+ "integrity": "sha512-873ztuL+/hfvXbLDJ262PGO6XjERnybJu2gW1/5j8HUfxSiFJI9Hj/DhZ50ZGRUxBvuNiazb/cM2rh9pqrxP6Q==",
+ "requires": {
+ "loader-utils": "1.1.0",
+ "schema-utils": "0.3.0"
+ }
+ },
+ "filename-regex": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
+ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY="
+ },
+ "fileset": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
+ "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=",
+ "dev": true,
+ "requires": {
+ "glob": "7.1.2",
+ "minimatch": "3.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
+ "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
+ "requires": {
+ "is-number": "2.1.0",
+ "isobject": "2.1.0",
+ "randomatic": "1.1.7",
+ "repeat-element": "1.1.2",
+ "repeat-string": "1.6.1"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
+ "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "1.0.1",
+ "escape-html": "1.0.3",
+ "on-finished": "2.3.0",
+ "parseurl": "1.3.2",
+ "statuses": "1.3.1",
+ "unpipe": "1.0.0"
+ }
+ },
+ "find-cache-dir": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
+ "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+ "requires": {
+ "commondir": "1.0.1",
+ "make-dir": "1.1.0",
+ "pkg-dir": "2.0.0"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "requires": {
+ "locate-path": "2.0.0"
+ }
+ },
+ "findup-sync": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz",
+ "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=",
+ "dev": true,
+ "requires": {
+ "glob": "5.0.15"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+ "dev": true,
+ "requires": {
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ }
+ }
+ },
+ "flatten": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
+ "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I="
+ },
+ "flush-write-stream": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz",
+ "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=",
+ "requires": {
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3"
+ }
+ },
+ "flux-standard-action": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/flux-standard-action/-/flux-standard-action-0.6.1.tgz",
+ "integrity": "sha1-bzQhG5SDTqHDzDD056+tPQ+/caI=",
+ "requires": {
+ "lodash.isplainobject": "3.2.0"
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
+ },
+ "for-own": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
+ "requires": {
+ "for-in": "1.0.2"
+ }
+ },
+ "foreach": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
+ "dev": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+ },
+ "form-data": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
+ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
+ "requires": {
+ "asynckit": "0.4.0",
+ "combined-stream": "1.0.5",
+ "mime-types": "2.1.17"
+ }
+ },
+ "formatio": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz",
+ "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=",
+ "dev": true,
+ "requires": {
+ "samsam": "1.3.0"
+ }
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
+ "dev": true
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
+ "dev": true
+ },
+ "from2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+ "requires": {
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3"
+ }
+ },
+ "fs-extra": {
+ "version": "0.30.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
+ "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "jsonfile": "2.4.0",
+ "klaw": "1.3.1",
+ "path-is-absolute": "1.0.1",
+ "rimraf": "2.6.2"
+ }
+ },
+ "fs-write-stream-atomic": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+ "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "iferr": "0.1.5",
+ "imurmurhash": "0.1.4",
+ "readable-stream": "2.3.3"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "fsevents": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz",
+ "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==",
+ "optional": true,
+ "requires": {
+ "nan": "2.8.0",
+ "node-pre-gyp": "0.6.39"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.0",
+ "bundled": true,
+ "optional": true
+ },
+ "ajv": {
+ "version": "4.11.8",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "co": "4.6.0",
+ "json-stable-stringify": "1.0.1"
+ }
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true
+ },
+ "aproba": {
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "delegates": "1.0.0",
+ "readable-stream": "2.2.9"
+ }
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "bundled": true,
+ "optional": true
+ },
+ "assert-plus": {
+ "version": "0.2.0",
+ "bundled": true,
+ "optional": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "bundled": true,
+ "optional": true
+ },
+ "aws-sign2": {
+ "version": "0.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "aws4": {
+ "version": "1.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "balanced-match": {
+ "version": "0.4.2",
+ "bundled": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "tweetnacl": "0.14.5"
+ }
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "bundled": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "boom": {
+ "version": "2.10.1",
+ "bundled": true,
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.7",
+ "bundled": true,
+ "requires": {
+ "balanced-match": "0.4.2",
+ "concat-map": "0.0.1"
+ }
+ },
+ "buffer-shims": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "bundled": true,
+ "optional": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "combined-stream": {
+ "version": "1.0.5",
+ "bundled": true,
+ "requires": {
+ "delayed-stream": "1.0.0"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "cryptiles": {
+ "version": "2.0.5",
+ "bundled": true,
+ "requires": {
+ "boom": "2.10.1"
+ }
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "debug": {
+ "version": "2.6.8",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.4.2",
+ "bundled": true,
+ "optional": true
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.1"
+ }
+ },
+ "extend": {
+ "version": "3.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "extsprintf": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "bundled": true,
+ "optional": true
+ },
+ "form-data": {
+ "version": "2.1.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "asynckit": "0.4.0",
+ "combined-stream": "1.0.5",
+ "mime-types": "2.1.15"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "bundled": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "inherits": "2.0.3",
+ "mkdirp": "0.5.1",
+ "rimraf": "2.6.1"
+ }
+ },
+ "fstream-ignore": {
+ "version": "1.0.5",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "fstream": "1.0.11",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4"
+ }
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "aproba": "1.1.1",
+ "console-control-strings": "1.1.0",
+ "has-unicode": "2.0.1",
+ "object-assign": "4.1.1",
+ "signal-exit": "3.0.2",
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wide-align": "1.1.2"
+ }
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "bundled": true,
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "bundled": true
+ },
+ "har-schema": {
+ "version": "1.0.5",
+ "bundled": true,
+ "optional": true
+ },
+ "har-validator": {
+ "version": "4.2.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "ajv": "4.11.8",
+ "har-schema": "1.0.5"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "hawk": {
+ "version": "3.1.3",
+ "bundled": true,
+ "requires": {
+ "boom": "2.10.1",
+ "cryptiles": "2.0.5",
+ "hoek": "2.16.3",
+ "sntp": "1.0.9"
+ }
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "bundled": true
+ },
+ "http-signature": {
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "0.2.0",
+ "jsprim": "1.4.0",
+ "sshpk": "1.13.0"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true
+ },
+ "ini": {
+ "version": "1.3.4",
+ "bundled": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "requires": {
+ "number-is-nan": "1.0.1"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "bundled": true,
+ "optional": true
+ },
+ "jodid25519": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.1"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "bundled": true,
+ "optional": true
+ },
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "jsonify": "0.0.0"
+ }
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "jsprim": {
+ "version": "1.4.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.0.2",
+ "json-schema": "0.2.3",
+ "verror": "1.3.6"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "mime-db": {
+ "version": "1.27.0",
+ "bundled": true
+ },
+ "mime-types": {
+ "version": "2.1.15",
+ "bundled": true,
+ "requires": {
+ "mime-db": "1.27.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "requires": {
+ "brace-expansion": "1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "node-pre-gyp": {
+ "version": "0.6.39",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "1.0.2",
+ "hawk": "3.1.3",
+ "mkdirp": "0.5.1",
+ "nopt": "4.0.1",
+ "npmlog": "4.1.0",
+ "rc": "1.2.1",
+ "request": "2.81.0",
+ "rimraf": "2.6.1",
+ "semver": "5.3.0",
+ "tar": "2.2.1",
+ "tar-pack": "3.4.0"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1.1.0",
+ "osenv": "0.1.4"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "1.1.4",
+ "console-control-strings": "1.1.0",
+ "gauge": "2.7.4",
+ "set-blocking": "2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "oauth-sign": {
+ "version": "0.8.2",
+ "bundled": true,
+ "optional": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "1.0.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "performance-now": {
+ "version": "0.2.0",
+ "bundled": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "bundled": true
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "bundled": true,
+ "optional": true
+ },
+ "qs": {
+ "version": "6.4.0",
+ "bundled": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "0.4.2",
+ "ini": "1.3.4",
+ "minimist": "1.2.0",
+ "strip-json-comments": "2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.2.9",
+ "bundled": true,
+ "requires": {
+ "buffer-shims": "1.0.0",
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "string_decoder": "1.0.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "request": {
+ "version": "2.81.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "aws-sign2": "0.6.0",
+ "aws4": "1.6.0",
+ "caseless": "0.12.0",
+ "combined-stream": "1.0.5",
+ "extend": "3.0.1",
+ "forever-agent": "0.6.1",
+ "form-data": "2.1.4",
+ "har-validator": "4.2.1",
+ "hawk": "3.1.3",
+ "http-signature": "1.1.1",
+ "is-typedarray": "1.0.0",
+ "isstream": "0.1.2",
+ "json-stringify-safe": "5.0.1",
+ "mime-types": "2.1.15",
+ "oauth-sign": "0.8.2",
+ "performance-now": "0.2.0",
+ "qs": "6.4.0",
+ "safe-buffer": "5.0.1",
+ "stringstream": "0.0.5",
+ "tough-cookie": "2.3.2",
+ "tunnel-agent": "0.6.0",
+ "uuid": "3.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.1",
+ "bundled": true,
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.0.1",
+ "bundled": true
+ },
+ "semver": {
+ "version": "5.3.0",
+ "bundled": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "sntp": {
+ "version": "1.0.9",
+ "bundled": true,
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "sshpk": {
+ "version": "1.13.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "asn1": "0.2.3",
+ "assert-plus": "1.0.0",
+ "bcrypt-pbkdf": "1.0.1",
+ "dashdash": "1.14.1",
+ "ecc-jsbn": "0.1.1",
+ "getpass": "0.1.7",
+ "jodid25519": "1.0.2",
+ "jsbn": "0.1.1",
+ "tweetnacl": "0.14.5"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "requires": {
+ "code-point-at": "1.1.0",
+ "is-fullwidth-code-point": "1.0.0",
+ "strip-ansi": "3.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "5.0.1"
+ }
+ },
+ "stringstream": {
+ "version": "0.0.5",
+ "bundled": true,
+ "optional": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "2.2.1",
+ "bundled": true,
+ "requires": {
+ "block-stream": "0.0.9",
+ "fstream": "1.0.11",
+ "inherits": "2.0.3"
+ }
+ },
+ "tar-pack": {
+ "version": "3.4.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "debug": "2.6.8",
+ "fstream": "1.0.11",
+ "fstream-ignore": "1.0.5",
+ "once": "1.4.0",
+ "readable-stream": "2.2.9",
+ "rimraf": "2.6.1",
+ "tar": "2.2.1",
+ "uid-number": "0.0.6"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.3.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "punycode": "1.4.1"
+ }
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "bundled": true,
+ "optional": true
+ },
+ "uid-number": {
+ "version": "0.0.6",
+ "bundled": true,
+ "optional": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "uuid": {
+ "version": "3.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "verror": {
+ "version": "1.3.6",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "extsprintf": "1.0.2"
+ }
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "string-width": "1.0.2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true
+ }
+ }
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
+ "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "inherits": "2.0.3",
+ "mkdirp": "0.5.1",
+ "rimraf": "2.6.2"
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "requires": {
+ "aproba": "1.2.0",
+ "console-control-strings": "1.1.0",
+ "has-unicode": "2.0.1",
+ "object-assign": "4.1.1",
+ "signal-exit": "3.0.2",
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wide-align": "1.1.2"
+ }
+ },
+ "gaze": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz",
+ "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=",
+ "requires": {
+ "globule": "1.2.0"
+ }
+ },
+ "generate-function": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
+ "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ="
+ },
+ "generate-object-property": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
+ "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
+ "requires": {
+ "is-property": "1.0.2"
+ }
+ },
+ "get-caller-file": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
+ "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U="
+ },
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
+ },
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
+ },
+ "getobject": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz",
+ "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=",
+ "dev": true
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "glob-base": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+ "requires": {
+ "glob-parent": "2.0.0",
+ "is-glob": "2.0.1"
+ }
+ },
+ "glob-parent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+ "requires": {
+ "is-glob": "2.0.1"
+ }
+ },
+ "globals": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ=="
+ },
+ "globby": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+ "dev": true,
+ "requires": {
+ "array-union": "1.0.2",
+ "glob": "7.1.2",
+ "object-assign": "4.1.1",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "globule": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz",
+ "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=",
+ "requires": {
+ "glob": "7.1.2",
+ "lodash": "4.17.4",
+ "minimatch": "3.0.4"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
+ },
+ "growly": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
+ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
+ "dev": true
+ },
+ "grunt": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.1.tgz",
+ "integrity": "sha1-6HeHZOlEsY8yuw8QuQeEdcnftWs=",
+ "dev": true,
+ "requires": {
+ "coffee-script": "1.10.0",
+ "dateformat": "1.0.12",
+ "eventemitter2": "0.4.14",
+ "exit": "0.1.2",
+ "findup-sync": "0.3.0",
+ "glob": "7.0.6",
+ "grunt-cli": "1.2.0",
+ "grunt-known-options": "1.1.0",
+ "grunt-legacy-log": "1.0.0",
+ "grunt-legacy-util": "1.0.0",
+ "iconv-lite": "0.4.19",
+ "js-yaml": "3.5.5",
+ "minimatch": "3.0.4",
+ "nopt": "3.0.6",
+ "path-is-absolute": "1.0.1",
+ "rimraf": "2.2.8"
+ },
+ "dependencies": {
+ "coffee-script": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz",
+ "integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA=",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+ "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "grunt-cli": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz",
+ "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=",
+ "dev": true,
+ "requires": {
+ "findup-sync": "0.3.0",
+ "grunt-known-options": "1.1.0",
+ "nopt": "3.0.6",
+ "resolve": "1.1.7"
+ }
+ },
+ "js-yaml": {
+ "version": "3.5.5",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz",
+ "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=",
+ "dev": true,
+ "requires": {
+ "argparse": "1.0.9",
+ "esprima": "2.7.3"
+ }
+ },
+ "resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.2.8",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
+ "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-contrib-watch": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz",
+ "integrity": "sha1-hKGnodar0m7VaEE0lscxM+mQAY8=",
+ "dev": true,
+ "requires": {
+ "async": "1.5.2",
+ "gaze": "1.1.2",
+ "lodash": "3.10.1",
+ "tiny-lr": "0.2.1"
+ },
+ "dependencies": {
+ "async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-known-options": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz",
+ "integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk=",
+ "dev": true
+ },
+ "grunt-legacy-log": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-1.0.0.tgz",
+ "integrity": "sha1-+4bxgJhHvAfcR4Q/ns1srLYt8tU=",
+ "dev": true,
+ "requires": {
+ "colors": "1.1.2",
+ "grunt-legacy-log-utils": "1.0.0",
+ "hooker": "0.2.3",
+ "lodash": "3.10.1",
+ "underscore.string": "3.2.3"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-legacy-log-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz",
+ "integrity": "sha1-p7ji0Ps1taUPSvmG/BEnSevJbz0=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "lodash": "4.3.0"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
+ "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-legacy-util": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz",
+ "integrity": "sha1-OGqnjcbtUJhsKxiVcmWxtIq7m4Y=",
+ "dev": true,
+ "requires": {
+ "async": "1.5.2",
+ "exit": "0.1.2",
+ "getobject": "0.1.0",
+ "hooker": "0.2.3",
+ "lodash": "4.3.0",
+ "underscore.string": "3.2.3",
+ "which": "1.2.14"
+ },
+ "dependencies": {
+ "async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz",
+ "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=",
+ "dev": true
+ },
+ "which": {
+ "version": "1.2.14",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
+ "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=",
+ "dev": true,
+ "requires": {
+ "isexe": "2.0.0"
+ }
+ }
+ }
+ },
+ "grunt-watch-change": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/grunt-watch-change/-/grunt-watch-change-0.1.1.tgz",
+ "integrity": "sha1-+rEoHrZvRK7wKn8vEzWUTGwF7Ag=",
+ "dev": true
+ },
+ "handle-thing": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
+ "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=",
+ "dev": true
+ },
+ "handlebars": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz",
+ "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=",
+ "dev": true,
+ "requires": {
+ "async": "1.5.2",
+ "optimist": "0.6.1",
+ "source-map": "0.4.4",
+ "uglify-js": "2.8.29"
+ },
+ "dependencies": {
+ "async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+ "dev": true,
+ "optional": true
+ },
+ "cliui": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "center-align": "0.1.3",
+ "right-align": "0.1.3",
+ "wordwrap": "0.0.2"
+ }
+ },
+ "source-map": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+ "dev": true,
+ "requires": {
+ "amdefine": "1.0.1"
+ }
+ },
+ "uglify-js": {
+ "version": "2.8.29",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
+ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "source-map": "0.5.7",
+ "uglify-to-browserify": "1.0.2",
+ "yargs": "3.10.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "yargs": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "camelcase": "1.2.1",
+ "cliui": "2.1.0",
+ "decamelize": "1.2.0",
+ "window-size": "0.1.0"
+ }
+ }
+ }
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "dev": true
+ },
+ "har-validator": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
+ "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
+ "requires": {
+ "chalk": "1.1.3",
+ "commander": "2.12.2",
+ "is-my-json-valid": "2.17.1",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "has": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
+ "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
+ "requires": {
+ "function-bind": "1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo="
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
+ },
+ "hash-base": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
+ "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=",
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "hash.js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
+ "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
+ "requires": {
+ "inherits": "2.0.3",
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "hawk": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
+ "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
+ "requires": {
+ "boom": "2.10.1",
+ "cryptiles": "2.0.5",
+ "hoek": "2.16.3",
+ "sntp": "1.0.9"
+ }
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "requires": {
+ "hash.js": "1.1.3",
+ "minimalistic-assert": "1.0.0",
+ "minimalistic-crypto-utils": "1.0.1"
+ }
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+ "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
+ },
+ "hoist-non-react-statics": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz",
+ "integrity": "sha1-ND24TGAYxlB3iJgkATWhQg7iLOA="
+ },
+ "home-or-tmp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
+ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=",
+ "requires": {
+ "os-homedir": "1.0.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "hooker": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz",
+ "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz",
+ "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg=="
+ },
+ "hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "obuf": "1.1.1",
+ "readable-stream": "2.3.3",
+ "wbuf": "1.7.2"
+ }
+ },
+ "html-comment-regex": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz",
+ "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4="
+ },
+ "html-encoding-sniffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz",
+ "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==",
+ "dev": true,
+ "requires": {
+ "whatwg-encoding": "1.0.3"
+ }
+ },
+ "html-entities": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
+ "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
+ "dev": true
+ },
+ "http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
+ "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
+ "dev": true,
+ "requires": {
+ "depd": "1.1.1",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.0.3",
+ "statuses": "1.3.1"
+ },
+ "dependencies": {
+ "setprototypeof": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
+ "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=",
+ "dev": true
+ }
+ }
+ },
+ "http-parser-js": {
+ "version": "0.4.9",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz",
+ "integrity": "sha1-6hoE+2St/wJC6ZdPKX3Uw8rSceE=",
+ "dev": true
+ },
+ "http-proxy": {
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz",
+ "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=",
+ "dev": true,
+ "requires": {
+ "eventemitter3": "1.2.0",
+ "requires-port": "1.0.0"
+ }
+ },
+ "http-proxy-middleware": {
+ "version": "0.17.4",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz",
+ "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=",
+ "dev": true,
+ "requires": {
+ "http-proxy": "1.16.2",
+ "is-glob": "3.1.0",
+ "lodash": "4.17.4",
+ "micromatch": "2.3.11"
+ },
+ "dependencies": {
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "2.1.1"
+ }
+ }
+ }
+ },
+ "http-signature": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
+ "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
+ "requires": {
+ "assert-plus": "0.2.0",
+ "jsprim": "1.4.1",
+ "sshpk": "1.13.1"
+ }
+ },
+ "https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
+ },
+ "iconv-lite": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
+ "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
+ },
+ "icss-replace-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
+ "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0="
+ },
+ "icss-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz",
+ "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=",
+ "requires": {
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "ieee754": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
+ "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q="
+ },
+ "iferr": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
+ },
+ "import-local": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-0.1.1.tgz",
+ "integrity": "sha1-sReVcqrNwRxqkQCftDDbyrX2aKg=",
+ "dev": true,
+ "requires": {
+ "pkg-dir": "2.0.0",
+ "resolve-cwd": "2.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+ },
+ "in-publish": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
+ "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E="
+ },
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "requires": {
+ "repeating": "2.0.1"
+ }
+ },
+ "indexes-of": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
+ "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc="
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "internal-ip": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz",
+ "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=",
+ "dev": true,
+ "requires": {
+ "meow": "3.7.0"
+ }
+ },
+ "interpret": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz",
+ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ="
+ },
+ "invariant": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz",
+ "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=",
+ "requires": {
+ "loose-envify": "1.3.1"
+ }
+ },
+ "invert-kv": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
+ },
+ "ip": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
+ "dev": true
+ },
+ "ipaddr.js": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz",
+ "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=",
+ "dev": true
+ },
+ "is-absolute-url": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz",
+ "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY="
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "requires": {
+ "binary-extensions": "1.11.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
+ "is-builtin-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+ "requires": {
+ "builtin-modules": "1.1.1"
+ }
+ },
+ "is-callable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
+ "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
+ "dev": true
+ },
+ "is-ci": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz",
+ "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=",
+ "dev": true,
+ "requires": {
+ "ci-info": "1.1.2"
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+ "dev": true
+ },
+ "is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
+ },
+ "is-dotfile": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+ "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE="
+ },
+ "is-equal-shallow": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+ "requires": {
+ "is-primitive": "2.0.0"
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
+ },
+ "is-finite": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+ "requires": {
+ "number-is-nan": "1.0.1"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "requires": {
+ "number-is-nan": "1.0.1"
+ }
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "is-my-json-valid": {
+ "version": "2.17.1",
+ "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz",
+ "integrity": "sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ==",
+ "requires": {
+ "generate-function": "2.0.0",
+ "generate-object-property": "1.2.0",
+ "jsonpointer": "4.0.1",
+ "xtend": "4.0.1"
+ }
+ },
+ "is-number": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+ "requires": {
+ "kind-of": "3.2.2"
+ }
+ },
+ "is-path-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+ "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+ "dev": true
+ },
+ "is-path-in-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz",
+ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=",
+ "dev": true,
+ "requires": {
+ "is-path-inside": "1.0.1"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "1.0.2"
+ }
+ },
+ "is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "requires": {
+ "isobject": "3.0.1"
+ }
+ },
+ "is-posix-bracket": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+ "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q="
+ },
+ "is-primitive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU="
+ },
+ "is-property": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
+ "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
+ },
+ "is-regex": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "dev": true,
+ "requires": {
+ "has": "1.0.1"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+ },
+ "is-svg": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz",
+ "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=",
+ "requires": {
+ "html-comment-regex": "1.1.1"
+ }
+ },
+ "is-symbol": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
+ "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
+ "dev": true
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
+ },
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+ },
+ "isnumeric": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/isnumeric/-/isnumeric-0.2.0.tgz",
+ "integrity": "sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ="
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+ },
+ "isomorphic-fetch": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+ "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
+ "requires": {
+ "node-fetch": "1.7.3",
+ "whatwg-fetch": "2.0.3"
+ }
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+ },
+ "istanbul-api": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.2.1.tgz",
+ "integrity": "sha512-oFCwXvd65amgaPCzqrR+a2XjanS1MvpXN6l/MlMUTv6uiA1NOgGX+I0uyq8Lg3GDxsxPsaP1049krz3hIJ5+KA==",
+ "dev": true,
+ "requires": {
+ "async": "2.6.0",
+ "fileset": "2.0.3",
+ "istanbul-lib-coverage": "1.1.1",
+ "istanbul-lib-hook": "1.1.0",
+ "istanbul-lib-instrument": "1.9.1",
+ "istanbul-lib-report": "1.1.2",
+ "istanbul-lib-source-maps": "1.2.2",
+ "istanbul-reports": "1.1.3",
+ "js-yaml": "3.10.0",
+ "mkdirp": "0.5.1",
+ "once": "1.4.0"
+ }
+ },
+ "istanbul-lib-coverage": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz",
+ "integrity": "sha512-0+1vDkmzxqJIn5rcoEqapSB4DmPxE31EtI2dF2aCkV5esN9EWHxZ0dwgDClivMXJqE7zaYQxq30hj5L0nlTN5Q=="
+ },
+ "istanbul-lib-hook": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz",
+ "integrity": "sha512-U3qEgwVDUerZ0bt8cfl3dSP3S6opBoOtk3ROO5f2EfBr/SRiD9FQqzwaZBqFORu8W7O0EXpai+k7kxHK13beRg==",
+ "dev": true,
+ "requires": {
+ "append-transform": "0.4.0"
+ }
+ },
+ "istanbul-lib-instrument": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz",
+ "integrity": "sha512-RQmXeQ7sphar7k7O1wTNzVczF9igKpaeGQAG9qR2L+BS4DCJNTI9nytRmIVYevwO0bbq+2CXvJmYDuz0gMrywA==",
+ "requires": {
+ "babel-generator": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0",
+ "babylon": "6.18.0",
+ "istanbul-lib-coverage": "1.1.1",
+ "semver": "5.4.1"
+ }
+ },
+ "istanbul-lib-report": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.2.tgz",
+ "integrity": "sha512-UTv4VGx+HZivJQwAo1wnRwe1KTvFpfi/NYwN7DcsrdzMXwpRT/Yb6r4SBPoHWj4VuQPakR32g4PUUeyKkdDkBA==",
+ "dev": true,
+ "requires": {
+ "istanbul-lib-coverage": "1.1.1",
+ "mkdirp": "0.5.1",
+ "path-parse": "1.0.5",
+ "supports-color": "3.2.3"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "dev": true,
+ "requires": {
+ "has-flag": "1.0.0"
+ }
+ }
+ }
+ },
+ "istanbul-lib-source-maps": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.2.tgz",
+ "integrity": "sha512-8BfdqSfEdtip7/wo1RnrvLpHVEd8zMZEDmOFEnpC6dg0vXflHt9nvoAyQUzig2uMSXfF2OBEYBV3CVjIL9JvaQ==",
+ "dev": true,
+ "requires": {
+ "debug": "3.1.0",
+ "istanbul-lib-coverage": "1.1.1",
+ "mkdirp": "0.5.1",
+ "rimraf": "2.6.2",
+ "source-map": "0.5.7"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "istanbul-reports": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.3.tgz",
+ "integrity": "sha512-ZEelkHh8hrZNI5xDaKwPMFwDsUf5wIEI2bXAFGp1e6deR2mnEKBPhLJEgr4ZBt8Gi6Mj38E/C8kcy9XLggVO2Q==",
+ "dev": true,
+ "requires": {
+ "handlebars": "4.0.11"
+ }
+ },
+ "jest": {
+ "version": "22.0.4",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-22.0.4.tgz",
+ "integrity": "sha512-S0tmgK5psULvt/11QzgAZWGpY5y5TkMRzd3T21Q13JzTx37Vx6F0Nw022c9Kc/IbEy+AHkKkGFVO5QafE8MrDg==",
+ "dev": true,
+ "requires": {
+ "jest-cli": "22.0.4"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "jest-cli": {
+ "version": "22.0.4",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-22.0.4.tgz",
+ "integrity": "sha512-f1lZRM13IwIINzjE3RebXQKtQLiKncpSrbJZ/aTZJXmzEWGdgSayW4ESyhU+xK3uGiJEUSzbHjwPY6nGJ8VbUA==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "3.0.0",
+ "chalk": "2.3.0",
+ "glob": "7.1.2",
+ "graceful-fs": "4.1.11",
+ "is-ci": "1.0.10",
+ "istanbul-api": "1.2.1",
+ "istanbul-lib-coverage": "1.1.1",
+ "istanbul-lib-instrument": "1.9.1",
+ "istanbul-lib-source-maps": "1.2.2",
+ "jest-changed-files": "22.0.3",
+ "jest-config": "22.0.4",
+ "jest-environment-jsdom": "22.0.4",
+ "jest-get-type": "22.0.3",
+ "jest-haste-map": "22.0.3",
+ "jest-message-util": "22.0.3",
+ "jest-regex-util": "22.0.3",
+ "jest-resolve-dependencies": "22.0.3",
+ "jest-runner": "22.0.4",
+ "jest-runtime": "22.0.4",
+ "jest-snapshot": "22.0.3",
+ "jest-util": "22.0.4",
+ "jest-worker": "22.0.3",
+ "micromatch": "2.3.11",
+ "node-notifier": "5.1.2",
+ "realpath-native": "1.0.0",
+ "rimraf": "2.6.2",
+ "slash": "1.0.0",
+ "string-length": "2.0.0",
+ "strip-ansi": "4.0.0",
+ "which": "1.3.0",
+ "yargs": "10.0.3"
+ }
+ },
+ "os-locale": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
+ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+ "dev": true,
+ "requires": {
+ "execa": "0.7.0",
+ "lcid": "1.0.0",
+ "mem": "1.1.0"
+ }
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0",
+ "strip-ansi": "4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "3.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "10.0.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.0.3.tgz",
+ "integrity": "sha512-DqBpQ8NAUX4GyPP/ijDGHsJya4tYqLQrjPr95HNsr1YwL3+daCfvBwg7+gIC6IdJhR2kATh3hb61vjzMWEtjdw==",
+ "dev": true,
+ "requires": {
+ "cliui": "3.2.0",
+ "decamelize": "1.2.0",
+ "find-up": "2.1.0",
+ "get-caller-file": "1.0.2",
+ "os-locale": "2.1.0",
+ "require-directory": "2.1.1",
+ "require-main-filename": "1.0.1",
+ "set-blocking": "2.0.0",
+ "string-width": "2.1.1",
+ "which-module": "2.0.0",
+ "y18n": "3.2.1",
+ "yargs-parser": "8.1.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz",
+ "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "4.1.0"
+ }
+ }
+ }
+ },
+ "jest-changed-files": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-22.0.3.tgz",
+ "integrity": "sha512-CG7eNJNO9x1O/3J4Uhe2QXra1MnC9+KS1f2NeOg+7iQ+8dDCgxCtpusmKfu44TnEyKwkIDhDr6htPfPaI+Fwbw==",
+ "dev": true,
+ "requires": {
+ "throat": "4.1.0"
+ }
+ },
+ "jest-config": {
+ "version": "22.0.4",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-22.0.4.tgz",
+ "integrity": "sha512-NcBeixqHjHDZO9+pUj+365LQV2s65d2f0/IrwlUyv0xaJovRNc6eDvoJ/r2UUlHnqjP3Go+R0ECUsXPXjk4SHw==",
+ "dev": true,
+ "requires": {
+ "chalk": "2.3.0",
+ "glob": "7.1.2",
+ "jest-environment-jsdom": "22.0.4",
+ "jest-environment-node": "22.0.4",
+ "jest-get-type": "22.0.3",
+ "jest-jasmine2": "22.0.4",
+ "jest-regex-util": "22.0.3",
+ "jest-resolve": "22.0.4",
+ "jest-util": "22.0.4",
+ "jest-validate": "22.0.3",
+ "pretty-format": "22.0.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "jest-context": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/jest-context/-/jest-context-2.1.0.tgz",
+ "integrity": "sha512-86TlB/2xgZFAHtHCLUloGWqraFx9IZtBbRR0A2382LDEZBppQZSAc+20AQCXop9OF0fUta1Lyr/b+yOIyDsI0Q==",
+ "dev": true
+ },
+ "jest-diff": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-22.0.3.tgz",
+ "integrity": "sha512-Y7xN9Lc/NgFvR14lvjrJXB6x2x1LLe5NnMyzLvilBSSOyjy9uAVnR2Bt1YgzdfRrfaxsx7xFUVcqXLUnPkrJcA==",
+ "dev": true,
+ "requires": {
+ "chalk": "2.3.0",
+ "diff": "3.4.0",
+ "jest-get-type": "22.0.3",
+ "pretty-format": "22.0.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "jest-docblock": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-22.0.3.tgz",
+ "integrity": "sha512-LhviP2rqIg2IzS6m97W7T032oMrT699Tr6Njjhhl4FCLj+75BUy9CsSmGgfoVEql1uc+myBkssvcbn7T9xDR+A==",
+ "dev": true,
+ "requires": {
+ "detect-newline": "2.1.0"
+ }
+ },
+ "jest-environment-jsdom": {
+ "version": "22.0.4",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-22.0.4.tgz",
+ "integrity": "sha512-vnjefLZlsNsmnjKcaXkx2IxTBNG40vfRVOdMfcfkPkq85JxFB7wzNtjLx+RIfiNpIZd04C1PXbF0aJIenY85Ng==",
+ "dev": true,
+ "requires": {
+ "jest-mock": "22.0.3",
+ "jest-util": "22.0.4",
+ "jsdom": "11.5.1"
+ }
+ },
+ "jest-environment-node": {
+ "version": "22.0.4",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-22.0.4.tgz",
+ "integrity": "sha512-9vjNKb86UivvKCZCudMNixQgdMnOG7ql6iVYnaiK0CmvZ0WQD+mlM10NvgiWpRv4HstcnRL1pY/GSIHXAD6qXw==",
+ "dev": true,
+ "requires": {
+ "jest-mock": "22.0.3",
+ "jest-util": "22.0.4"
+ }
+ },
+ "jest-get-type": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.0.3.tgz",
+ "integrity": "sha512-TaJnc/lnJQ3jwry+NUWkqaJmKrM/Ut3XdK89HfiqdI3DMRLd6Zb4wyKjwuNP37MEQqlNg0YWH4sbBR8D4exjCA==",
+ "dev": true
+ },
+ "jest-haste-map": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-22.0.3.tgz",
+ "integrity": "sha512-VosIMOFQFu1rTF+MvOWVuv2KVmZ9eTkRgfwW2yUAs6/AhwmIfXRl/tih+fIOYcHzU4Auu1G8Fvl2kkF5g0k6/A==",
+ "dev": true,
+ "requires": {
+ "fb-watchman": "2.0.0",
+ "graceful-fs": "4.1.11",
+ "jest-docblock": "22.0.3",
+ "jest-worker": "22.0.3",
+ "micromatch": "2.3.11",
+ "sane": "2.2.0"
+ }
+ },
+ "jest-jasmine2": {
+ "version": "22.0.4",
+ "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-22.0.4.tgz",
+ "integrity": "sha512-pn1XPHUkffHK6oNY1Dfl/+Rg0UuTdlg3aGDnjyK6dZzGEBeiH1uKuSgZEjy3Lj461l3atpzsQyw7ilXPyjFnUw==",
+ "dev": true,
+ "requires": {
+ "callsites": "2.0.0",
+ "chalk": "2.3.0",
+ "expect": "22.0.3",
+ "graceful-fs": "4.1.11",
+ "jest-diff": "22.0.3",
+ "jest-matcher-utils": "22.0.3",
+ "jest-message-util": "22.0.3",
+ "jest-snapshot": "22.0.3",
+ "source-map-support": "0.5.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz",
+ "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==",
+ "dev": true,
+ "requires": {
+ "source-map": "0.6.1"
+ }
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "jest-leak-detector": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-22.0.3.tgz",
+ "integrity": "sha512-xyVdAmcG8M3jWtVeadDUU6MAHLBrjkP4clz2UtTZ1gpe5bRLk27VjQOpzTwK20MkV/6iZQhSuRVuzHS5kD0HpA==",
+ "dev": true,
+ "requires": {
+ "pretty-format": "22.0.3",
+ "weak": "1.0.1"
+ }
+ },
+ "jest-matcher-utils": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-22.0.3.tgz",
+ "integrity": "sha512-FJbKpCR3K7YYE/Pnvy5OrLFgPEswpYWIfVtdwT2NC6pBARbYGX39KF3bTxS9yg2mv0YL2zHe3UbwzFsi9nFpVA==",
+ "dev": true,
+ "requires": {
+ "chalk": "2.3.0",
+ "jest-get-type": "22.0.3",
+ "pretty-format": "22.0.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "jest-message-util": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-22.0.3.tgz",
+ "integrity": "sha512-AVBdCx7Oj5wBpMOH089lx7Zgwpdz9HbReA82HuVAlIT4kEQRvCy6Sl9yVWDGJwHTgB/OYQGkgmbv/P/K8TkWNw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "7.0.0-beta.36",
+ "chalk": "2.3.0",
+ "micromatch": "2.3.11",
+ "slash": "1.0.0",
+ "stack-utils": "1.0.1"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "jest-mock": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-22.0.3.tgz",
+ "integrity": "sha512-donODXcDG03EAEavc9xfJ7fBF/LNVjoZYkmj9DLrQ1B9YcT6wh8Xx7IYg25b8V/8F/eXPMAE0KK5q6Fqe6yAeg==",
+ "dev": true
+ },
+ "jest-regex-util": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-22.0.3.tgz",
+ "integrity": "sha512-mplC9chiAotES3ClzNhy0SJcfHB2DivooKJZW+2hDdvP8LLB+OUI+D6bJd7sncbKUsyFcmblEvpm/zz/hef7HA==",
+ "dev": true
+ },
+ "jest-resolve": {
+ "version": "22.0.4",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-22.0.4.tgz",
+ "integrity": "sha512-yoxHsX4MTT2Ra/dFia9VCunzsA/4jMBENMmLjREIUkCIP1edk/PZUOGVVf680Gw04CtmT5stETylcbmbL7hJBw==",
+ "dev": true,
+ "requires": {
+ "browser-resolve": "1.11.2",
+ "chalk": "2.3.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "jest-resolve-dependencies": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-22.0.3.tgz",
+ "integrity": "sha512-u9MUNJIa9GJ0YFhvM0+Scr4tyX84nC42d3w18Cly1doY7pTT+9momm+TncpuDlFyB2aNmS8SfdEbiLr1e6tBwg==",
+ "dev": true,
+ "requires": {
+ "jest-regex-util": "22.0.3"
+ }
+ },
+ "jest-runner": {
+ "version": "22.0.4",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-22.0.4.tgz",
+ "integrity": "sha512-srBkbqmiSB+jzSaG652fmi3kS6rV6wS/4fOG8dxxBg3dCqNQcM2/L3TI3ZK0SwIAcdGJh5Gybs8aDboT8K9Cdw==",
+ "dev": true,
+ "requires": {
+ "jest-config": "22.0.4",
+ "jest-docblock": "22.0.3",
+ "jest-haste-map": "22.0.3",
+ "jest-jasmine2": "22.0.4",
+ "jest-leak-detector": "22.0.3",
+ "jest-message-util": "22.0.3",
+ "jest-runtime": "22.0.4",
+ "jest-util": "22.0.4",
+ "jest-worker": "22.0.3",
+ "throat": "4.1.0"
+ }
+ },
+ "jest-runtime": {
+ "version": "22.0.4",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-22.0.4.tgz",
+ "integrity": "sha512-+7uEwf/4f8k1E/eViyGK6/M5yA4O3f6TdWViuqF9MV7vXwG2OVJu8YEZa5239nEnHJiwinXp4eZXX+HB4pQRPg==",
+ "dev": true,
+ "requires": {
+ "babel-core": "6.26.0",
+ "babel-jest": "22.0.4",
+ "babel-plugin-istanbul": "4.1.5",
+ "chalk": "2.3.0",
+ "convert-source-map": "1.5.1",
+ "graceful-fs": "4.1.11",
+ "jest-config": "22.0.4",
+ "jest-haste-map": "22.0.3",
+ "jest-regex-util": "22.0.3",
+ "jest-resolve": "22.0.4",
+ "jest-util": "22.0.4",
+ "json-stable-stringify": "1.0.1",
+ "micromatch": "2.3.11",
+ "realpath-native": "1.0.0",
+ "slash": "1.0.0",
+ "strip-bom": "3.0.0",
+ "write-file-atomic": "2.3.0",
+ "yargs": "10.0.3"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "os-locale": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
+ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+ "dev": true,
+ "requires": {
+ "execa": "0.7.0",
+ "lcid": "1.0.0",
+ "mem": "1.1.0"
+ }
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0",
+ "strip-ansi": "4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "3.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "10.0.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.0.3.tgz",
+ "integrity": "sha512-DqBpQ8NAUX4GyPP/ijDGHsJya4tYqLQrjPr95HNsr1YwL3+daCfvBwg7+gIC6IdJhR2kATh3hb61vjzMWEtjdw==",
+ "dev": true,
+ "requires": {
+ "cliui": "3.2.0",
+ "decamelize": "1.2.0",
+ "find-up": "2.1.0",
+ "get-caller-file": "1.0.2",
+ "os-locale": "2.1.0",
+ "require-directory": "2.1.1",
+ "require-main-filename": "1.0.1",
+ "set-blocking": "2.0.0",
+ "string-width": "2.1.1",
+ "which-module": "2.0.0",
+ "y18n": "3.2.1",
+ "yargs-parser": "8.1.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz",
+ "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "4.1.0"
+ }
+ }
+ }
+ },
+ "jest-set": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/jest-set/-/jest-set-2.0.0.tgz",
+ "integrity": "sha512-xbkgBhzLueM0y5loQa9swFA3Gg6DxyHa9qxyNNE7E7ICLeFbI4vl3ykoZuN4HCY5w6c4LA+wzmNCLf9N+yH2Sg==",
+ "dev": true
+ },
+ "jest-snapshot": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-22.0.3.tgz",
+ "integrity": "sha512-e/a/EvMsY5XROWy4QWX6PvYziuJ8ttD6+QcnbogODWtx2LGhvVQOb7pmqGTo0tL/p0vzFetZA9GlZSh/EfMepg==",
+ "dev": true,
+ "requires": {
+ "chalk": "2.3.0",
+ "jest-diff": "22.0.3",
+ "jest-matcher-utils": "22.0.3",
+ "mkdirp": "0.5.1",
+ "natural-compare": "1.4.0",
+ "pretty-format": "22.0.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "jest-util": {
+ "version": "22.0.4",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-22.0.4.tgz",
+ "integrity": "sha512-gNNPtcCFkVh7daKIl3/06eoQ90QXGXCyDOfyZ3IEyTWmHBdX3GvklcOtyGcdOvrYEubaZTfMcMKmEeo/6sRTog==",
+ "dev": true,
+ "requires": {
+ "callsites": "2.0.0",
+ "chalk": "2.3.0",
+ "graceful-fs": "4.1.11",
+ "is-ci": "1.0.10",
+ "jest-message-util": "22.0.3",
+ "jest-validate": "22.0.3",
+ "mkdirp": "0.5.1"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "jest-validate": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-22.0.3.tgz",
+ "integrity": "sha512-GmlLmPCtrSQ3iB4A1uxcfjawaaQnwESCDcUg5tMxJKeBbmPdcWPAb6EWzvANxULPUV7hfPKLwg4xIPpi7cx1/g==",
+ "dev": true,
+ "requires": {
+ "chalk": "2.3.0",
+ "jest-get-type": "22.0.3",
+ "leven": "2.1.0",
+ "pretty-format": "22.0.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "jest-worker": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-22.0.3.tgz",
+ "integrity": "sha512-fPdCTnogFQiR0CP6whEsIly2RfcHxvalqyLjhui6qa1SnOmHiX7L8k4Umo8CBIp5ndWY0+ej1o7OTE5MlzPabg==",
+ "dev": true,
+ "requires": {
+ "merge-stream": "1.0.1"
+ }
+ },
+ "jquery": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz",
+ "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c="
+ },
+ "jquery-mousewheel": {
+ "version": "3.1.13",
+ "resolved": "https://registry.npmjs.org/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz",
+ "integrity": "sha1-BvAzXxbjU6aV5yBr9QUDy1I6buU="
+ },
+ "js-base64": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.0.tgz",
+ "integrity": "sha512-Wehd+7Pf9tFvGb+ydPm9TjYjV8X1YHOVyG8QyELZxEMqOhemVwGRmoG8iQ/soqI3n8v4xn59zaLxiCJiaaRzKA=="
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
+ },
+ "js-yaml": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
+ "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
+ "requires": {
+ "argparse": "1.0.9",
+ "esprima": "4.0.0"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw=="
+ }
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "optional": true
+ },
+ "jsdom": {
+ "version": "11.5.1",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.5.1.tgz",
+ "integrity": "sha512-89ztIZ03aYK9f1uUrLXLsZndRge/JnZjzjpaN+lrse3coqz+8PR/dX4WLHpbF5fIKTXhDjFODOJw2328lPJ90g==",
+ "dev": true,
+ "requires": {
+ "abab": "1.0.4",
+ "acorn": "5.3.0",
+ "acorn-globals": "4.1.0",
+ "array-equal": "1.0.0",
+ "browser-process-hrtime": "0.1.2",
+ "content-type-parser": "1.0.2",
+ "cssom": "0.3.2",
+ "cssstyle": "0.2.37",
+ "domexception": "1.0.0",
+ "escodegen": "1.9.0",
+ "html-encoding-sniffer": "1.0.2",
+ "left-pad": "1.2.0",
+ "nwmatcher": "1.4.3",
+ "parse5": "3.0.3",
+ "pn": "1.0.0",
+ "request": "2.83.0",
+ "request-promise-native": "1.0.5",
+ "sax": "1.2.4",
+ "symbol-tree": "3.2.2",
+ "tough-cookie": "2.3.3",
+ "webidl-conversions": "4.0.2",
+ "whatwg-encoding": "1.0.3",
+ "whatwg-url": "6.4.0",
+ "xml-name-validator": "2.0.1"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "dev": true
+ },
+ "boom": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
+ "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
+ "dev": true,
+ "requires": {
+ "hoek": "4.2.0"
+ }
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
+ "cryptiles": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
+ "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
+ "dev": true,
+ "requires": {
+ "boom": "5.2.0"
+ },
+ "dependencies": {
+ "boom": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
+ "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
+ "dev": true,
+ "requires": {
+ "hoek": "4.2.0"
+ }
+ }
+ }
+ },
+ "form-data": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz",
+ "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=",
+ "dev": true,
+ "requires": {
+ "asynckit": "0.4.0",
+ "combined-stream": "1.0.5",
+ "mime-types": "2.1.17"
+ }
+ },
+ "har-validator": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
+ "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
+ "dev": true,
+ "requires": {
+ "ajv": "5.5.2",
+ "har-schema": "2.0.0"
+ }
+ },
+ "hawk": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
+ "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==",
+ "dev": true,
+ "requires": {
+ "boom": "4.3.1",
+ "cryptiles": "3.1.2",
+ "hoek": "4.2.0",
+ "sntp": "2.1.0"
+ }
+ },
+ "hoek": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz",
+ "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==",
+ "dev": true
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "jsprim": "1.4.1",
+ "sshpk": "1.13.1"
+ }
+ },
+ "qs": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
+ "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
+ "dev": true
+ },
+ "request": {
+ "version": "2.83.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz",
+ "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "0.7.0",
+ "aws4": "1.6.0",
+ "caseless": "0.12.0",
+ "combined-stream": "1.0.5",
+ "extend": "3.0.1",
+ "forever-agent": "0.6.1",
+ "form-data": "2.3.1",
+ "har-validator": "5.0.3",
+ "hawk": "6.0.2",
+ "http-signature": "1.2.0",
+ "is-typedarray": "1.0.0",
+ "isstream": "0.1.2",
+ "json-stringify-safe": "5.0.1",
+ "mime-types": "2.1.17",
+ "oauth-sign": "0.8.2",
+ "performance-now": "2.1.0",
+ "qs": "6.5.1",
+ "safe-buffer": "5.1.1",
+ "stringstream": "0.0.5",
+ "tough-cookie": "2.3.3",
+ "tunnel-agent": "0.6.0",
+ "uuid": "3.1.0"
+ }
+ },
+ "sntp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz",
+ "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==",
+ "dev": true,
+ "requires": {
+ "hoek": "4.2.0"
+ }
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "jsesc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+ "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s="
+ },
+ "json-loader": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
+ "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w=="
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
+ },
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
+ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
+ "dev": true,
+ "requires": {
+ "jsonify": "0.0.0"
+ }
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+ },
+ "json3": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
+ "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
+ "dev": true
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
+ },
+ "jsonfile": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+ "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
+ "requires": {
+ "graceful-fs": "4.1.11"
+ }
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+ "dev": true
+ },
+ "jsonpointer": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
+ "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk="
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "just-extend": {
+ "version": "1.1.27",
+ "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz",
+ "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==",
+ "dev": true
+ },
+ "killable": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz",
+ "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ },
+ "klaw": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
+ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
+ "requires": {
+ "graceful-fs": "4.1.11"
+ }
+ },
+ "lazy-cache": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz",
+ "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U="
+ },
+ "lcid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+ "requires": {
+ "invert-kv": "1.0.0"
+ }
+ },
+ "left-pad": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.2.0.tgz",
+ "integrity": "sha1-0wpzxrggHY99jnlWupYWCHpo4O4=",
+ "dev": true
+ },
+ "leven": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
+ "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=",
+ "dev": true
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2"
+ }
+ },
+ "livereload-js": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz",
+ "integrity": "sha1-bIclfmSKtHW8JOoldFftzB+NC8I=",
+ "dev": true
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "parse-json": "2.2.0",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "strip-bom": "2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ }
+ }
+ },
+ "loader-runner": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz",
+ "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI="
+ },
+ "loader-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+ "requires": {
+ "big.js": "3.2.0",
+ "emojis-list": "2.1.0",
+ "json5": "0.5.1"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "requires": {
+ "p-locate": "2.0.0",
+ "path-exists": "3.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.4",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
+ },
+ "lodash-es": {
+ "version": "4.17.4",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz",
+ "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc="
+ },
+ "lodash._basefor": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz",
+ "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI="
+ },
+ "lodash._reinterpolate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
+ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
+ },
+ "lodash.assign": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
+ "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc="
+ },
+ "lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
+ },
+ "lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
+ },
+ "lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
+ "dev": true
+ },
+ "lodash.isarguments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo="
+ },
+ "lodash.isarray": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U="
+ },
+ "lodash.isplainobject": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-3.2.0.tgz",
+ "integrity": "sha1-moI4rhayAEMpYM1zRlEtASP79MU=",
+ "requires": {
+ "lodash._basefor": "3.0.3",
+ "lodash.isarguments": "3.1.0",
+ "lodash.keysin": "3.0.8"
+ }
+ },
+ "lodash.keysin": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-3.0.8.tgz",
+ "integrity": "sha1-IsRJPrvtsUJ5YqVLRFssinZ/tH8=",
+ "requires": {
+ "lodash.isarguments": "3.1.0",
+ "lodash.isarray": "3.0.4"
+ }
+ },
+ "lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
+ },
+ "lodash.mergewith": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz",
+ "integrity": "sha1-FQzwoWeR9ZA7iJHqsVRgknS96lU="
+ },
+ "lodash.sortby": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
+ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
+ "dev": true
+ },
+ "lodash.tail": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz",
+ "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ="
+ },
+ "lodash.template": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz",
+ "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=",
+ "requires": {
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.templatesettings": "4.1.0"
+ }
+ },
+ "lodash.templatesettings": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz",
+ "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=",
+ "requires": {
+ "lodash._reinterpolate": "3.0.0"
+ }
+ },
+ "lodash.uniq": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M="
+ },
+ "loglevel": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.0.tgz",
+ "integrity": "sha1-rgyqVhERSYxboTcj1vtjHSQAOTQ=",
+ "dev": true
+ },
+ "lolex": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.1.tgz",
+ "integrity": "sha512-mQuW55GhduF3ppo+ZRUTz1PRjEh1hS5BbqU7d8D0ez2OKxHDod7StPPeAVKisZR5aLkHZjdGWSL42LSONUJsZw==",
+ "dev": true
+ },
+ "longest": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
+ "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
+ },
+ "loose-envify": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
+ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
+ "requires": {
+ "js-tokens": "3.0.2"
+ }
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "requires": {
+ "currently-unhandled": "0.4.1",
+ "signal-exit": "3.0.2"
+ }
+ },
+ "lru-cache": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
+ "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
+ "requires": {
+ "pseudomap": "1.0.2",
+ "yallist": "2.1.2"
+ }
+ },
+ "macaddress": {
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz",
+ "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI="
+ },
+ "make-dir": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz",
+ "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==",
+ "requires": {
+ "pify": "3.0.0"
+ }
+ },
+ "makeerror": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz",
+ "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=",
+ "dev": true,
+ "requires": {
+ "tmpl": "1.0.4"
+ }
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0="
+ },
+ "math-expression-evaluator": {
+ "version": "1.2.17",
+ "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz",
+ "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw="
+ },
+ "md5.js": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
+ "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
+ "requires": {
+ "hash-base": "3.0.4",
+ "inherits": "2.0.3"
+ },
+ "dependencies": {
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "requires": {
+ "inherits": "2.0.3",
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+ "dev": true
+ },
+ "mem": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
+ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+ "requires": {
+ "mimic-fn": "1.1.0"
+ }
+ },
+ "memory-fs": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+ "requires": {
+ "errno": "0.1.6",
+ "readable-stream": "2.3.3"
+ }
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "requires": {
+ "camelcase-keys": "2.1.0",
+ "decamelize": "1.2.0",
+ "loud-rejection": "1.6.0",
+ "map-obj": "1.0.1",
+ "minimist": "1.2.0",
+ "normalize-package-data": "2.4.0",
+ "object-assign": "4.1.1",
+ "read-pkg-up": "1.0.1",
+ "redent": "1.0.0",
+ "trim-newlines": "1.0.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+ }
+ }
+ },
+ "merge": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz",
+ "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=",
+ "dev": true
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
+ "dev": true
+ },
+ "merge-stream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz",
+ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.3.3"
+ }
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "requires": {
+ "arr-diff": "2.0.0",
+ "array-unique": "0.2.1",
+ "braces": "1.8.5",
+ "expand-brackets": "0.1.5",
+ "extglob": "0.3.2",
+ "filename-regex": "2.0.1",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1",
+ "kind-of": "3.2.2",
+ "normalize-path": "2.1.1",
+ "object.omit": "2.0.1",
+ "parse-glob": "3.0.4",
+ "regex-cache": "0.4.4"
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "requires": {
+ "bn.js": "4.11.8",
+ "brorand": "1.1.0"
+ }
+ },
+ "mime": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
+ "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
+ "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE="
+ },
+ "mime-types": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
+ "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
+ "requires": {
+ "mime-db": "1.30.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz",
+ "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg="
+ },
+ "minimalistic-assert": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
+ "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M="
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "1.1.8"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+ },
+ "mississippi": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-1.3.0.tgz",
+ "integrity": "sha1-0gFYPrEjJ+PFwWQqQEqcrPlONPU=",
+ "requires": {
+ "concat-stream": "1.6.0",
+ "duplexify": "3.5.1",
+ "end-of-stream": "1.4.0",
+ "flush-write-stream": "1.0.2",
+ "from2": "2.3.0",
+ "parallel-transform": "1.1.0",
+ "pump": "1.0.3",
+ "pumpify": "1.3.5",
+ "stream-each": "1.2.2",
+ "through2": "2.0.3"
+ }
+ },
+ "mixin-object": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz",
+ "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=",
+ "requires": {
+ "for-in": "0.1.8",
+ "is-extendable": "0.1.1"
+ },
+ "dependencies": {
+ "for-in": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz",
+ "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE="
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "move-concurrently": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+ "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+ "requires": {
+ "aproba": "1.2.0",
+ "copy-concurrently": "1.0.5",
+ "fs-write-stream-atomic": "1.0.10",
+ "mkdirp": "0.5.1",
+ "rimraf": "2.6.2",
+ "run-queue": "1.0.3"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "multicast-dns": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.1.tgz",
+ "integrity": "sha512-uV3/ckdsffHx9IrGQrx613mturMdMqQ06WTq+C09NsStJ9iNG6RcUWgPKs1Rfjy+idZT6tfQoXEusGNnEZhT3w==",
+ "dev": true,
+ "requires": {
+ "dns-packet": "1.2.2",
+ "thunky": "0.1.0"
+ }
+ },
+ "multicast-dns-service-types": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
+ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz",
+ "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo="
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "negotiator": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
+ "dev": true
+ },
+ "nise": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/nise/-/nise-1.2.0.tgz",
+ "integrity": "sha512-q9jXh3UNsMV28KeqI43ILz5+c3l+RiNW8mhurEwCKckuHQbL+hTJIKKTiUlCPKlgQ/OukFvSnKB/Jk3+sFbkGA==",
+ "dev": true,
+ "requires": {
+ "formatio": "1.2.0",
+ "just-extend": "1.1.27",
+ "lolex": "1.6.0",
+ "path-to-regexp": "1.7.0",
+ "text-encoding": "0.6.4"
+ },
+ "dependencies": {
+ "lolex": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz",
+ "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=",
+ "dev": true
+ }
+ }
+ },
+ "node-fetch": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
+ "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+ "requires": {
+ "encoding": "0.1.12",
+ "is-stream": "1.1.0"
+ }
+ },
+ "node-forge": {
+ "version": "0.6.33",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.6.33.tgz",
+ "integrity": "sha1-RjgRh59XPUUVWtap9D3ClujoXrw=",
+ "dev": true
+ },
+ "node-gyp": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz",
+ "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=",
+ "requires": {
+ "fstream": "1.0.11",
+ "glob": "7.1.2",
+ "graceful-fs": "4.1.11",
+ "minimatch": "3.0.4",
+ "mkdirp": "0.5.1",
+ "nopt": "3.0.6",
+ "npmlog": "4.1.2",
+ "osenv": "0.1.4",
+ "request": "2.79.0",
+ "rimraf": "2.6.2",
+ "semver": "5.3.0",
+ "tar": "2.2.1",
+ "which": "1.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+ "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
+ }
+ }
+ },
+ "node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
+ "dev": true
+ },
+ "node-libs-browser": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz",
+ "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==",
+ "requires": {
+ "assert": "1.4.1",
+ "browserify-zlib": "0.2.0",
+ "buffer": "4.9.1",
+ "console-browserify": "1.1.0",
+ "constants-browserify": "1.0.0",
+ "crypto-browserify": "3.12.0",
+ "domain-browser": "1.1.7",
+ "events": "1.1.1",
+ "https-browserify": "1.0.0",
+ "os-browserify": "0.3.0",
+ "path-browserify": "0.0.0",
+ "process": "0.11.10",
+ "punycode": "1.4.1",
+ "querystring-es3": "0.2.1",
+ "readable-stream": "2.3.3",
+ "stream-browserify": "2.0.1",
+ "stream-http": "2.7.2",
+ "string_decoder": "1.0.3",
+ "timers-browserify": "2.0.4",
+ "tty-browserify": "0.0.0",
+ "url": "0.11.0",
+ "util": "0.10.3",
+ "vm-browserify": "0.0.4"
+ }
+ },
+ "node-notifier": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.1.2.tgz",
+ "integrity": "sha1-L6nhJgX6EACdRFSdb82KY93g5P8=",
+ "dev": true,
+ "requires": {
+ "growly": "1.3.0",
+ "semver": "5.4.1",
+ "shellwords": "0.1.1",
+ "which": "1.3.0"
+ }
+ },
+ "node-sass": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.7.2.tgz",
+ "integrity": "sha512-CaV+wLqZ7//Jdom5aUFCpGNoECd7BbNhjuwdsX/LkXBrHl8eb1Wjw4HvWqcFvhr5KuNgAk8i/myf/MQ1YYeroA==",
+ "requires": {
+ "async-foreach": "0.1.3",
+ "chalk": "1.1.3",
+ "cross-spawn": "3.0.1",
+ "gaze": "1.1.2",
+ "get-stdin": "4.0.1",
+ "glob": "7.1.2",
+ "in-publish": "2.0.0",
+ "lodash.assign": "4.2.0",
+ "lodash.clonedeep": "4.5.0",
+ "lodash.mergewith": "4.6.0",
+ "meow": "3.7.0",
+ "mkdirp": "0.5.1",
+ "nan": "2.8.0",
+ "node-gyp": "3.6.2",
+ "npmlog": "4.1.2",
+ "request": "2.79.0",
+ "sass-graph": "2.2.4",
+ "stdout-stream": "1.4.0",
+ "true-case-path": "1.0.2"
+ }
+ },
+ "nopt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+ "requires": {
+ "abbrev": "1.1.1"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
+ "requires": {
+ "hosted-git-info": "2.5.0",
+ "is-builtin-module": "1.0.0",
+ "semver": "5.4.1",
+ "validate-npm-package-license": "3.0.1"
+ }
+ },
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "requires": {
+ "remove-trailing-separator": "1.1.0"
+ }
+ },
+ "normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI="
+ },
+ "normalize-url": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz",
+ "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=",
+ "requires": {
+ "object-assign": "4.1.1",
+ "prepend-http": "1.0.4",
+ "query-string": "4.3.4",
+ "sort-keys": "1.1.2"
+ }
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "requires": {
+ "path-key": "2.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "requires": {
+ "are-we-there-yet": "1.1.4",
+ "console-control-strings": "1.1.0",
+ "gauge": "2.7.4",
+ "set-blocking": "2.0.0"
+ }
+ },
+ "num2fraction": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
+ "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4="
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+ },
+ "nwmatcher": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.3.tgz",
+ "integrity": "sha512-IKdSTiDWCarf2JTS5e9e2+5tPZGdkRJ79XjYV0pzK8Q9BpsFyBq1RGKxzs7Q8UBushGw7m6TzVKz6fcY99iSWw==",
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+ "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "object-keys": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
+ "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=",
+ "dev": true
+ },
+ "object.getownpropertydescriptors": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
+ "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
+ "dev": true,
+ "requires": {
+ "define-properties": "1.1.2",
+ "es-abstract": "1.10.0"
+ }
+ },
+ "object.omit": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
+ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+ "requires": {
+ "for-own": "0.1.5",
+ "is-extendable": "0.1.1"
+ },
+ "dependencies": {
+ "for-own": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+ "requires": {
+ "for-in": "1.0.2"
+ }
+ }
+ }
+ },
+ "obuf": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz",
+ "integrity": "sha1-EEEktsYCxnlogaBCVB0220OlJk4=",
+ "dev": true
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "dev": true,
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "on-headers": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
+ "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "onecolor": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/onecolor/-/onecolor-3.0.5.tgz",
+ "integrity": "sha1-Nu/zIgE3nv3xGA+0ReUajiQl+fY="
+ },
+ "opn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz",
+ "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==",
+ "dev": true,
+ "requires": {
+ "is-wsl": "1.1.0"
+ }
+ },
+ "optimist": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8",
+ "wordwrap": "0.0.2"
+ }
+ },
+ "optionator": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "dev": true,
+ "requires": {
+ "deep-is": "0.1.3",
+ "fast-levenshtein": "2.0.6",
+ "levn": "0.3.0",
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2",
+ "wordwrap": "1.0.0"
+ },
+ "dependencies": {
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+ "dev": true
+ }
+ }
+ },
+ "original": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz",
+ "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=",
+ "dev": true,
+ "requires": {
+ "url-parse": "1.0.5"
+ },
+ "dependencies": {
+ "url-parse": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz",
+ "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=",
+ "dev": true,
+ "requires": {
+ "querystringify": "0.0.4",
+ "requires-port": "1.0.0"
+ }
+ }
+ }
+ },
+ "os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc="
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
+ },
+ "os-locale": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+ "requires": {
+ "lcid": "1.0.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+ },
+ "osenv": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
+ "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=",
+ "requires": {
+ "os-homedir": "1.0.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
+ },
+ "p-limit": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz",
+ "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw="
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "requires": {
+ "p-limit": "1.1.0"
+ }
+ },
+ "p-map": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
+ "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
+ "dev": true
+ },
+ "pako": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
+ "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg=="
+ },
+ "parallel-transform": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
+ "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
+ "requires": {
+ "cyclist": "0.2.2",
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3"
+ }
+ },
+ "parse-asn1": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz",
+ "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=",
+ "requires": {
+ "asn1.js": "4.9.2",
+ "browserify-aes": "1.1.1",
+ "create-hash": "1.1.3",
+ "evp_bytestokey": "1.0.3",
+ "pbkdf2": "3.0.14"
+ }
+ },
+ "parse-glob": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+ "requires": {
+ "glob-base": "0.3.0",
+ "is-dotfile": "1.0.3",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1"
+ }
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "requires": {
+ "error-ex": "1.3.1"
+ }
+ },
+ "parse5": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+ "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+ "dev": true,
+ "requires": {
+ "@types/node": "8.5.2"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
+ "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
+ "dev": true
+ },
+ "path-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
+ "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo="
+ },
+ "path-complete-extname": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/path-complete-extname/-/path-complete-extname-0.1.0.tgz",
+ "integrity": "sha1-xFRwJmnzFFL4GTqmFokV+jFpL0o="
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+ },
+ "path-parse": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
+ "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME="
+ },
+ "path-to-regexp": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
+ "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
+ "dev": true,
+ "requires": {
+ "isarray": "0.0.1"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ }
+ }
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ }
+ }
+ },
+ "pbkdf2": {
+ "version": "3.0.14",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz",
+ "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==",
+ "requires": {
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "ripemd160": "2.0.1",
+ "safe-buffer": "5.1.1",
+ "sha.js": "2.4.9"
+ }
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "requires": {
+ "pinkie": "2.0.4"
+ }
+ },
+ "pixrem": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pixrem/-/pixrem-4.0.1.tgz",
+ "integrity": "sha1-LaSh3m7EQjxfw3lOkwuB1EkOxoY=",
+ "requires": {
+ "browserslist": "2.10.0",
+ "postcss": "6.0.14",
+ "reduce-css-calc": "1.3.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+ "requires": {
+ "find-up": "2.1.0"
+ }
+ },
+ "pleeease-filters": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/pleeease-filters/-/pleeease-filters-4.0.0.tgz",
+ "integrity": "sha1-ZjKy+wVkjSdY2GU4T7zteeHMrsc=",
+ "requires": {
+ "onecolor": "3.0.5",
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "pn": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/pn/-/pn-1.0.0.tgz",
+ "integrity": "sha1-HPWjCw2AbNGPiPxBprXUrWFbO6k=",
+ "dev": true
+ },
+ "portfinder": {
+ "version": "1.0.13",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz",
+ "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=",
+ "dev": true,
+ "requires": {
+ "async": "1.5.2",
+ "debug": "2.6.9",
+ "mkdirp": "0.5.1"
+ },
+ "dependencies": {
+ "async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ }
+ }
+ },
+ "postcss": {
+ "version": "5.2.18",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
+ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "requires": {
+ "chalk": "1.1.3",
+ "js-base64": "2.4.0",
+ "source-map": "0.5.7",
+ "supports-color": "3.2.3"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "requires": {
+ "has-flag": "1.0.0"
+ }
+ }
+ }
+ },
+ "postcss-apply": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/postcss-apply/-/postcss-apply-0.8.0.tgz",
+ "integrity": "sha1-FOVEu7XLbxweBIhXll15rgZrE0M=",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "balanced-match": "0.4.2",
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "balanced-match": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+ "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-attribute-case-insensitive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-2.0.0.tgz",
+ "integrity": "sha1-lNxCLI+QmX8WvTOjZUu77AhJY7Q=",
+ "requires": {
+ "postcss": "6.0.14",
+ "postcss-selector-parser": "2.2.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-calc": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz",
+ "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=",
+ "requires": {
+ "postcss": "5.2.18",
+ "postcss-message-helpers": "2.0.0",
+ "reduce-css-calc": "1.3.0"
+ }
+ },
+ "postcss-color-function": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-color-function/-/postcss-color-function-4.0.1.tgz",
+ "integrity": "sha1-QCs/LOvD9pR+YY+2vjZU++zvZEQ=",
+ "requires": {
+ "css-color-function": "1.3.3",
+ "postcss": "6.0.14",
+ "postcss-message-helpers": "2.0.0",
+ "postcss-value-parser": "3.3.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-color-gray": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-4.1.0.tgz",
+ "integrity": "sha512-L4iLKQLdqChz6ZOgGb6dRxkBNw78JFYcJmBz1orHpZoeLtuhDDGegRtX9gSyfoCIM7rWZ3VNOyiqqvk83BEN+w==",
+ "requires": {
+ "color": "2.0.1",
+ "postcss": "6.0.14",
+ "postcss-message-helpers": "2.0.0",
+ "reduce-function-call": "1.0.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "color": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color/-/color-2.0.1.tgz",
+ "integrity": "sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw==",
+ "requires": {
+ "color-convert": "1.9.1",
+ "color-string": "1.5.2"
+ }
+ },
+ "color-string": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz",
+ "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=",
+ "requires": {
+ "color-name": "1.1.3",
+ "simple-swizzle": "0.2.2"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-color-hex-alpha": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-3.0.0.tgz",
+ "integrity": "sha1-HlPmyKyyN5Vej9CLfs2xuLgwn5U=",
+ "requires": {
+ "color": "1.0.3",
+ "postcss": "6.0.14",
+ "postcss-message-helpers": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "color": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz",
+ "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=",
+ "requires": {
+ "color-convert": "1.9.1",
+ "color-string": "1.5.2"
+ }
+ },
+ "color-string": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz",
+ "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=",
+ "requires": {
+ "color-name": "1.1.3",
+ "simple-swizzle": "0.2.2"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-color-hsl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-color-hsl/-/postcss-color-hsl-2.0.0.tgz",
+ "integrity": "sha1-EnA2ZvoxBDDj8wpFTawThjF9WEQ=",
+ "requires": {
+ "postcss": "6.0.14",
+ "postcss-value-parser": "3.3.0",
+ "units-css": "0.4.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-color-hwb": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-color-hwb/-/postcss-color-hwb-3.0.0.tgz",
+ "integrity": "sha1-NAKxnvTYSXVAwftQcr6YY8qVVx4=",
+ "requires": {
+ "color": "1.0.3",
+ "postcss": "6.0.14",
+ "postcss-message-helpers": "2.0.0",
+ "reduce-function-call": "1.0.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "color": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz",
+ "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=",
+ "requires": {
+ "color-convert": "1.9.1",
+ "color-string": "1.5.2"
+ }
+ },
+ "color-string": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz",
+ "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=",
+ "requires": {
+ "color-name": "1.1.3",
+ "simple-swizzle": "0.2.2"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-color-rebeccapurple": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-3.0.0.tgz",
+ "integrity": "sha1-7rrwPTY7QwC5Z5K9MIHBntZlE9M=",
+ "requires": {
+ "postcss": "6.0.14",
+ "postcss-value-parser": "3.3.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-color-rgb": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-color-rgb/-/postcss-color-rgb-2.0.0.tgz",
+ "integrity": "sha1-FFOcinExSUtILg3RzCZf9lFLUmM=",
+ "requires": {
+ "postcss": "6.0.14",
+ "postcss-value-parser": "3.3.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-color-rgba-fallback": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-color-rgba-fallback/-/postcss-color-rgba-fallback-3.0.0.tgz",
+ "integrity": "sha1-N9XJNToHoJJwkSqCYGu0Kg1wLAQ=",
+ "requires": {
+ "postcss": "6.0.14",
+ "postcss-value-parser": "3.3.0",
+ "rgb-hex": "2.1.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-colormin": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz",
+ "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=",
+ "requires": {
+ "colormin": "1.1.2",
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-convert-values": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz",
+ "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=",
+ "requires": {
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-cssnext": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-cssnext/-/postcss-cssnext-3.0.2.tgz",
+ "integrity": "sha512-jA6kGdcUMZqLUgw6MdpyNWGFhk0LIITVhC/jTnLRZLoXSTR88qT2cFOn3LbY06udt1PVdTCHDG3plBjxVKf8BQ==",
+ "requires": {
+ "autoprefixer": "7.2.3",
+ "caniuse-api": "2.0.0",
+ "chalk": "2.3.0",
+ "pixrem": "4.0.1",
+ "pleeease-filters": "4.0.0",
+ "postcss": "6.0.14",
+ "postcss-apply": "0.8.0",
+ "postcss-attribute-case-insensitive": "2.0.0",
+ "postcss-calc": "6.0.1",
+ "postcss-color-function": "4.0.1",
+ "postcss-color-gray": "4.1.0",
+ "postcss-color-hex-alpha": "3.0.0",
+ "postcss-color-hsl": "2.0.0",
+ "postcss-color-hwb": "3.0.0",
+ "postcss-color-rebeccapurple": "3.0.0",
+ "postcss-color-rgb": "2.0.0",
+ "postcss-color-rgba-fallback": "3.0.0",
+ "postcss-custom-media": "6.0.0",
+ "postcss-custom-properties": "6.2.0",
+ "postcss-custom-selectors": "4.0.1",
+ "postcss-font-family-system-ui": "2.1.1",
+ "postcss-font-variant": "3.0.0",
+ "postcss-image-set-polyfill": "0.3.5",
+ "postcss-initial": "2.0.0",
+ "postcss-media-minmax": "3.0.0",
+ "postcss-nesting": "4.2.1",
+ "postcss-pseudo-class-any-link": "4.0.0",
+ "postcss-pseudoelements": "5.0.0",
+ "postcss-replace-overflow-wrap": "2.0.0",
+ "postcss-selector-matches": "3.0.1",
+ "postcss-selector-not": "3.0.1"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "autoprefixer": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.3.tgz",
+ "integrity": "sha512-dqzVGiz3v934+s3YZA6nk7tAs9xuTz5wMJbX1M+L4cY/MTNkOUqP61c1GWkEVlUL/PEy1pKRSCFuoRZrXYx9qA==",
+ "requires": {
+ "browserslist": "2.10.0",
+ "caniuse-lite": "1.0.30000784",
+ "normalize-range": "0.1.2",
+ "num2fraction": "1.2.2",
+ "postcss": "6.0.14",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "caniuse-api": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-2.0.0.tgz",
+ "integrity": "sha1-sd21pZZrFvSNxJmERNS7xsfZ2DQ=",
+ "requires": {
+ "browserslist": "2.10.0",
+ "caniuse-lite": "1.0.30000784",
+ "lodash.memoize": "4.1.2",
+ "lodash.uniq": "4.5.0"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "postcss-calc": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-6.0.1.tgz",
+ "integrity": "sha1-PSQXG79udinUIqQ26/5t2VEfQzA=",
+ "requires": {
+ "css-unit-converter": "1.1.1",
+ "postcss": "6.0.14",
+ "postcss-selector-parser": "2.2.3",
+ "reduce-css-calc": "2.1.3"
+ }
+ },
+ "reduce-css-calc": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.3.tgz",
+ "integrity": "sha1-Y8TGMl/7v06mwj8dTetHw5U/O4E=",
+ "requires": {
+ "css-unit-converter": "1.1.1",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-custom-media": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-6.0.0.tgz",
+ "integrity": "sha1-vlMnhBEOyylQRPtTlaGABushpzc=",
+ "requires": {
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-custom-properties": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-6.2.0.tgz",
+ "integrity": "sha512-eNR2h9T9ciKMoQEORrPjH33XeN/nuvVuxArOKmHtsFbGbNss631tgTrKou3/pmjAZbA4QQkhLIkPQkIk3WW+8w==",
+ "requires": {
+ "balanced-match": "1.0.0",
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-custom-selectors": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-4.0.1.tgz",
+ "integrity": "sha1-eBOC+UxS5yfvXKR3bqKt9JphE4I=",
+ "requires": {
+ "postcss": "6.0.14",
+ "postcss-selector-matches": "3.0.1"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-discard-comments": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz",
+ "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=",
+ "requires": {
+ "postcss": "5.2.18"
+ }
+ },
+ "postcss-discard-duplicates": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz",
+ "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=",
+ "requires": {
+ "postcss": "5.2.18"
+ }
+ },
+ "postcss-discard-empty": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz",
+ "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=",
+ "requires": {
+ "postcss": "5.2.18"
+ }
+ },
+ "postcss-discard-overridden": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz",
+ "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=",
+ "requires": {
+ "postcss": "5.2.18"
+ }
+ },
+ "postcss-discard-unused": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz",
+ "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=",
+ "requires": {
+ "postcss": "5.2.18",
+ "uniqs": "2.0.0"
+ }
+ },
+ "postcss-filter-plugins": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz",
+ "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=",
+ "requires": {
+ "postcss": "5.2.18",
+ "uniqid": "4.1.1"
+ }
+ },
+ "postcss-font-family-system-ui": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-font-family-system-ui/-/postcss-font-family-system-ui-2.1.1.tgz",
+ "integrity": "sha512-AOAn553wVmMDx2nph0axVDXJwhsd9x4MjKHRH9SOXL4YdiqsYFxyTVTWnlka9iNB70Pb3Idxmj79bIXxq38b/w==",
+ "requires": {
+ "@std/esm": "0.16.0",
+ "lodash": "4.17.4",
+ "postcss": "6.0.14",
+ "postcss-value-parser": "3.3.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-font-variant": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-3.0.0.tgz",
+ "integrity": "sha1-CMzIj2BQuoLtjvLMdsDGprQfGD4=",
+ "requires": {
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-image-set-polyfill": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/postcss-image-set-polyfill/-/postcss-image-set-polyfill-0.3.5.tgz",
+ "integrity": "sha1-Dxk0E3AM8fgr05Bm7wFtZaShgYE=",
+ "requires": {
+ "postcss": "6.0.14",
+ "postcss-media-query-parser": "0.2.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-import": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.0.0.tgz",
+ "integrity": "sha1-qWLi34LTvFptpqOGhBdHIE9B71s=",
+ "requires": {
+ "postcss": "6.0.14",
+ "postcss-value-parser": "3.3.0",
+ "read-cache": "1.0.0",
+ "resolve": "1.5.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-initial": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-2.0.0.tgz",
+ "integrity": "sha1-cnFfczbgu3k1HZnuZcSiU6hEG6Q=",
+ "requires": {
+ "lodash.template": "4.4.0",
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-load-config": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz",
+ "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=",
+ "requires": {
+ "cosmiconfig": "2.2.2",
+ "object-assign": "4.1.1",
+ "postcss-load-options": "1.2.0",
+ "postcss-load-plugins": "2.3.0"
+ }
+ },
+ "postcss-load-options": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz",
+ "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=",
+ "requires": {
+ "cosmiconfig": "2.2.2",
+ "object-assign": "4.1.1"
+ }
+ },
+ "postcss-load-plugins": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz",
+ "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=",
+ "requires": {
+ "cosmiconfig": "2.2.2",
+ "object-assign": "4.1.1"
+ }
+ },
+ "postcss-loader": {
+ "version": "2.0.9",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.0.9.tgz",
+ "integrity": "sha512-sgoXPtmgVT3aBAhU47Kig8oPF+mbXl8Unjvtz1Qj1q2D2EvSVJW2mKJNzxv5y/LvA9xWwuvdysvhc7Zn80UWWw==",
+ "requires": {
+ "loader-utils": "1.1.0",
+ "postcss": "6.0.14",
+ "postcss-load-config": "1.2.0",
+ "schema-utils": "0.3.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-media-minmax": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-3.0.0.tgz",
+ "integrity": "sha1-Z1JWA3pD70C8Twdgv9BtTcadSNI=",
+ "requires": {
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-media-query-parser": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
+ "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ="
+ },
+ "postcss-merge-idents": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz",
+ "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=",
+ "requires": {
+ "has": "1.0.1",
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-merge-longhand": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz",
+ "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=",
+ "requires": {
+ "postcss": "5.2.18"
+ }
+ },
+ "postcss-merge-rules": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz",
+ "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=",
+ "requires": {
+ "browserslist": "1.7.7",
+ "caniuse-api": "1.6.1",
+ "postcss": "5.2.18",
+ "postcss-selector-parser": "2.2.3",
+ "vendors": "1.0.1"
+ },
+ "dependencies": {
+ "browserslist": {
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz",
+ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=",
+ "requires": {
+ "caniuse-db": "1.0.30000784",
+ "electron-to-chromium": "1.3.30"
+ }
+ }
+ }
+ },
+ "postcss-message-helpers": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz",
+ "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4="
+ },
+ "postcss-minify-font-values": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz",
+ "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=",
+ "requires": {
+ "object-assign": "4.1.1",
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-minify-gradients": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz",
+ "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=",
+ "requires": {
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-minify-params": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz",
+ "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=",
+ "requires": {
+ "alphanum-sort": "1.0.2",
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0",
+ "uniqs": "2.0.0"
+ }
+ },
+ "postcss-minify-selectors": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz",
+ "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=",
+ "requires": {
+ "alphanum-sort": "1.0.2",
+ "has": "1.0.1",
+ "postcss": "5.2.18",
+ "postcss-selector-parser": "2.2.3"
+ }
+ },
+ "postcss-modules-extract-imports": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz",
+ "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=",
+ "requires": {
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-modules-local-by-default": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz",
+ "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=",
+ "requires": {
+ "css-selector-tokenizer": "0.7.0",
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-modules-scope": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz",
+ "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=",
+ "requires": {
+ "css-selector-tokenizer": "0.7.0",
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-modules-values": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz",
+ "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=",
+ "requires": {
+ "icss-replace-symbols": "1.1.0",
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-nesting": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-4.2.1.tgz",
+ "integrity": "sha512-IkyWXICwagCnlaviRexi7qOdwPw3+xVVjgFfGsxmztvRVaNxAlrypOIKqDE5mxY+BVxnId1rnUKBRQoNE2VDaA==",
+ "requires": {
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-normalize-charset": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz",
+ "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=",
+ "requires": {
+ "postcss": "5.2.18"
+ }
+ },
+ "postcss-normalize-url": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz",
+ "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=",
+ "requires": {
+ "is-absolute-url": "2.1.0",
+ "normalize-url": "1.9.1",
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-ordered-values": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz",
+ "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=",
+ "requires": {
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-pseudo-class-any-link": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-4.0.0.tgz",
+ "integrity": "sha1-kVKgYT00UHIFE+iJKFS65C0O5o4=",
+ "requires": {
+ "postcss": "6.0.14",
+ "postcss-selector-parser": "2.2.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-pseudoelements": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-pseudoelements/-/postcss-pseudoelements-5.0.0.tgz",
+ "integrity": "sha1-7vGU6NUkZFylIKlJ6V5RjoEkAss=",
+ "requires": {
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-reduce-idents": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz",
+ "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=",
+ "requires": {
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-reduce-initial": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz",
+ "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=",
+ "requires": {
+ "postcss": "5.2.18"
+ }
+ },
+ "postcss-reduce-transforms": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz",
+ "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=",
+ "requires": {
+ "has": "1.0.1",
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-replace-overflow-wrap": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-2.0.0.tgz",
+ "integrity": "sha1-eU22+qVPjbEAhUOSqTr0V2i04ls=",
+ "requires": {
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-selector-matches": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-3.0.1.tgz",
+ "integrity": "sha1-5WNAEeE5UIgYYbvdWMLQER/8lqs=",
+ "requires": {
+ "balanced-match": "0.4.2",
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "balanced-match": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+ "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-selector-not": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-3.0.1.tgz",
+ "integrity": "sha1-Lk2y8JZTNsAefOx9tsYN/3ZzNdk=",
+ "requires": {
+ "balanced-match": "0.4.2",
+ "postcss": "6.0.14"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "balanced-match": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+ "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "postcss": {
+ "version": "6.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz",
+ "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==",
+ "requires": {
+ "chalk": "2.3.0",
+ "source-map": "0.6.1",
+ "supports-color": "4.5.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz",
+ "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=",
+ "requires": {
+ "flatten": "1.0.2",
+ "indexes-of": "1.0.1",
+ "uniq": "1.0.1"
+ }
+ },
+ "postcss-svgo": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz",
+ "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=",
+ "requires": {
+ "is-svg": "2.1.0",
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0",
+ "svgo": "0.7.2"
+ }
+ },
+ "postcss-unique-selectors": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz",
+ "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=",
+ "requires": {
+ "alphanum-sort": "1.0.2",
+ "postcss": "5.2.18",
+ "uniqs": "2.0.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz",
+ "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU="
+ },
+ "postcss-zindex": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz",
+ "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=",
+ "requires": {
+ "has": "1.0.1",
+ "postcss": "5.2.18",
+ "uniqs": "2.0.0"
+ }
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true
+ },
+ "prepend-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
+ },
+ "preserve": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks="
+ },
+ "pretty-format": {
+ "version": "22.0.3",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.0.3.tgz",
+ "integrity": "sha512-qXbDFJ2/Kk3HFIaLdOblbsCKQ09kZu4MKbXB+m/EaqD7PZ/wXe2XcRREmQleMh4wmerxlma6eJTh3nxCXYUmmA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "3.0.0",
+ "ansi-styles": "3.2.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ }
+ }
+ },
+ "private": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
+ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+ },
+ "promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "requires": {
+ "asap": "2.0.6"
+ }
+ },
+ "promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
+ },
+ "promise-polyfill": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-7.0.0.tgz",
+ "integrity": "sha1-xmW22h+X4hw/L3qgVDyQIJEnyxU="
+ },
+ "prop-types": {
+ "version": "15.6.0",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz",
+ "integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=",
+ "requires": {
+ "fbjs": "0.8.16",
+ "loose-envify": "1.3.1",
+ "object-assign": "4.1.1"
+ }
+ },
+ "proxy-addr": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz",
+ "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=",
+ "dev": true,
+ "requires": {
+ "forwarded": "0.1.2",
+ "ipaddr.js": "1.5.2"
+ }
+ },
+ "prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+ },
+ "public-encrypt": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz",
+ "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "browserify-rsa": "4.0.1",
+ "create-hash": "1.1.3",
+ "parse-asn1": "5.1.0",
+ "randombytes": "2.0.5"
+ }
+ },
+ "pump": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz",
+ "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==",
+ "requires": {
+ "end-of-stream": "1.4.0",
+ "once": "1.4.0"
+ }
+ },
+ "pumpify": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.3.5.tgz",
+ "integrity": "sha1-G2ccYZlAq8rqwK0OOjwWS+dgmTs=",
+ "requires": {
+ "duplexify": "3.5.1",
+ "inherits": "2.0.3",
+ "pump": "1.0.3"
+ }
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ },
+ "q": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
+ },
+ "qs": {
+ "version": "6.3.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz",
+ "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw="
+ },
+ "query-string": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
+ "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
+ "requires": {
+ "object-assign": "4.1.1",
+ "strict-uri-encode": "1.1.0"
+ }
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
+ },
+ "querystringify": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz",
+ "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=",
+ "dev": true
+ },
+ "randomatic": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
+ "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
+ "requires": {
+ "is-number": "3.0.0",
+ "kind-of": "4.0.0"
+ },
+ "dependencies": {
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "requires": {
+ "kind-of": "3.2.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "randombytes": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz",
+ "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz",
+ "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==",
+ "requires": {
+ "randombytes": "2.0.5",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "range-parser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
+ "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
+ "dev": true,
+ "requires": {
+ "bytes": "3.0.0",
+ "http-errors": "1.6.2",
+ "iconv-lite": "0.4.19",
+ "unpipe": "1.0.0"
+ }
+ },
+ "react": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-16.2.0.tgz",
+ "integrity": "sha512-ZmIomM7EE1DvPEnSFAHZn9Vs9zJl5A9H7el0EGTE6ZbW9FKe/14IYAlPbC8iH25YarEQxZL+E8VW7Mi7kfQrDQ==",
+ "requires": {
+ "fbjs": "0.8.16",
+ "loose-envify": "1.3.1",
+ "object-assign": "4.1.1",
+ "prop-types": "15.6.0"
+ }
+ },
+ "react-addons-test-utils": {
+ "version": "15.6.2",
+ "resolved": "https://registry.npmjs.org/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz",
+ "integrity": "sha1-wStu/cIkfBDae4dw0YUICnsEcVY=",
+ "dev": true
+ },
+ "react-dom": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.2.0.tgz",
+ "integrity": "sha512-zpGAdwHVn9K0091d+hr+R0qrjoJ84cIBFL2uU60KvWBPfZ7LPSrfqviTxGHWN0sjPZb2hxWzMexwrvJdKePvjg==",
+ "requires": {
+ "fbjs": "0.8.16",
+ "loose-envify": "1.3.1",
+ "object-assign": "4.1.1",
+ "prop-types": "15.6.0"
+ }
+ },
+ "react-redux": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.6.tgz",
+ "integrity": "sha512-8taaaGu+J7PMJQDJrk/xiWEYQmdo3mkXw6wPr3K3LxvXis3Fymiq7c13S+Tpls/AyNUAsoONkU81AP0RA6y6Vw==",
+ "requires": {
+ "hoist-non-react-statics": "2.3.1",
+ "invariant": "2.2.2",
+ "lodash": "4.17.4",
+ "lodash-es": "4.17.4",
+ "loose-envify": "1.3.1",
+ "prop-types": "15.6.0"
+ }
+ },
+ "react-select2-wrapper": {
+ "version": "1.0.4-beta5",
+ "resolved": "https://registry.npmjs.org/react-select2-wrapper/-/react-select2-wrapper-1.0.4-beta5.tgz",
+ "integrity": "sha1-UHFPYYqc7zecVPbt34vYLUu6Tao=",
+ "requires": {
+ "prop-types": "15.6.0",
+ "select2": "4.0.5",
+ "shallow-equal-fuzzy": "0.0.2"
+ }
+ },
+ "react-test-renderer": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.2.0.tgz",
+ "integrity": "sha512-Kd4gJFtpNziR9ElOE/C23LeflKLZPRpNQYWP3nQBY43SJ5a+xyEGSeMrm2zxNKXcnCbBS/q1UpD9gqd5Dv+rew==",
+ "dev": true,
+ "requires": {
+ "fbjs": "0.8.16",
+ "object-assign": "4.1.1",
+ "prop-types": "15.6.0"
+ }
+ },
+ "read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=",
+ "requires": {
+ "pify": "2.3.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ }
+ }
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "requires": {
+ "load-json-file": "1.1.0",
+ "normalize-package-data": "2.4.0",
+ "path-type": "1.1.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "requires": {
+ "find-up": "1.1.2",
+ "read-pkg": "1.1.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "requires": {
+ "path-exists": "2.1.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "requires": {
+ "pinkie-promise": "2.0.1"
+ }
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "readdirp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
+ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "minimatch": "3.0.4",
+ "readable-stream": "2.3.3",
+ "set-immediate-shim": "1.0.1"
+ }
+ },
+ "realpath-native": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.0.tgz",
+ "integrity": "sha512-XJtlRJ9jf0E1H1SLeJyQ9PGzQD7S65h1pRXEcAeK48doKOnKxcgPeNohJvD5u/2sI9J1oke6E8bZHS/fmW1UiQ==",
+ "dev": true,
+ "requires": {
+ "util.promisify": "1.0.0"
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "requires": {
+ "indent-string": "2.1.0",
+ "strip-indent": "1.0.1"
+ }
+ },
+ "reduce-css-calc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz",
+ "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=",
+ "requires": {
+ "balanced-match": "0.4.2",
+ "math-expression-evaluator": "1.2.17",
+ "reduce-function-call": "1.0.2"
+ },
+ "dependencies": {
+ "balanced-match": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+ "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
+ }
+ }
+ },
+ "reduce-function-call": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz",
+ "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=",
+ "requires": {
+ "balanced-match": "0.4.2"
+ },
+ "dependencies": {
+ "balanced-match": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+ "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
+ }
+ }
+ },
+ "redux": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz",
+ "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==",
+ "requires": {
+ "lodash": "4.17.4",
+ "lodash-es": "4.17.4",
+ "loose-envify": "1.3.1",
+ "symbol-observable": "1.1.0"
+ }
+ },
+ "redux-logger": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz",
+ "integrity": "sha1-91VZZvMJjzyIYExEnPC69XeCdL8=",
+ "requires": {
+ "deep-diff": "0.3.8"
+ }
+ },
+ "redux-promise": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/redux-promise/-/redux-promise-0.5.3.tgz",
+ "integrity": "sha1-6X5snTvzdurLebq+bZBtogES1tg=",
+ "requires": {
+ "flux-standard-action": "0.6.1"
+ }
+ },
+ "redux-thunk": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.2.0.tgz",
+ "integrity": "sha1-5hWhbha0ehmlFXZhM9Hj6Zt4UuU="
+ },
+ "regenerate": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz",
+ "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg=="
+ },
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+ },
+ "regenerator-transform": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
+ "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "private": "0.1.8"
+ }
+ },
+ "regex-cache": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
+ "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+ "requires": {
+ "is-equal-shallow": "0.1.3"
+ }
+ },
+ "regexpu-core": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
+ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
+ "requires": {
+ "regenerate": "1.3.3",
+ "regjsgen": "0.2.0",
+ "regjsparser": "0.1.5"
+ }
+ },
+ "regjsgen": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+ "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc="
+ },
+ "regjsparser": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+ "requires": {
+ "jsesc": "0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
+ }
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
+ },
+ "repeat-element": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
+ "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo="
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "requires": {
+ "is-finite": "1.0.2"
+ }
+ },
+ "request": {
+ "version": "2.79.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz",
+ "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=",
+ "requires": {
+ "aws-sign2": "0.6.0",
+ "aws4": "1.6.0",
+ "caseless": "0.11.0",
+ "combined-stream": "1.0.5",
+ "extend": "3.0.1",
+ "forever-agent": "0.6.1",
+ "form-data": "2.1.4",
+ "har-validator": "2.0.6",
+ "hawk": "3.1.3",
+ "http-signature": "1.1.1",
+ "is-typedarray": "1.0.0",
+ "isstream": "0.1.2",
+ "json-stringify-safe": "5.0.1",
+ "mime-types": "2.1.17",
+ "oauth-sign": "0.8.2",
+ "qs": "6.3.2",
+ "stringstream": "0.0.5",
+ "tough-cookie": "2.3.3",
+ "tunnel-agent": "0.4.3",
+ "uuid": "3.1.0"
+ }
+ },
+ "request-promise-core": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz",
+ "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=",
+ "dev": true,
+ "requires": {
+ "lodash": "4.17.4"
+ }
+ },
+ "request-promise-native": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz",
+ "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=",
+ "dev": true,
+ "requires": {
+ "request-promise-core": "1.1.1",
+ "stealthy-require": "1.1.1",
+ "tough-cookie": "2.3.3"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+ },
+ "require-from-string": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz",
+ "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg="
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",
+ "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
+ "requires": {
+ "path-parse": "1.0.5"
+ }
+ },
+ "resolve-cwd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+ "dev": true,
+ "requires": {
+ "resolve-from": "3.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+ "dev": true
+ },
+ "rgb": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/rgb/-/rgb-0.1.0.tgz",
+ "integrity": "sha1-vieykej+/+rBvZlylyG/pA/AN7U="
+ },
+ "rgb-hex": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-2.1.0.tgz",
+ "integrity": "sha1-x3PF/iJoolV42SU5qCp6XOU77aY="
+ },
+ "right-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
+ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+ "requires": {
+ "align-text": "0.1.4"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
+ "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=",
+ "requires": {
+ "hash-base": "2.0.2",
+ "inherits": "2.0.3"
+ }
+ },
+ "run-queue": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+ "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+ "requires": {
+ "aproba": "1.2.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
+ },
+ "samsam": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz",
+ "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==",
+ "dev": true
+ },
+ "sane": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/sane/-/sane-2.2.0.tgz",
+ "integrity": "sha512-OSJxhHO0CgPUw3lUm3GhfREAfza45smvEI9ozuFrxKG10GHVo0ryW9FK5VYlLvxj0SV7HVKHW0voYJIRu27GWg==",
+ "dev": true,
+ "requires": {
+ "anymatch": "1.3.2",
+ "exec-sh": "0.2.1",
+ "fb-watchman": "2.0.0",
+ "fsevents": "1.1.3",
+ "minimatch": "3.0.4",
+ "minimist": "1.2.0",
+ "walker": "1.0.7",
+ "watch": "0.18.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "sass-graph": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
+ "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
+ "requires": {
+ "glob": "7.1.2",
+ "lodash": "4.17.4",
+ "scss-tokenizer": "0.2.3",
+ "yargs": "7.1.0"
+ }
+ },
+ "sass-loader": {
+ "version": "6.0.6",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-6.0.6.tgz",
+ "integrity": "sha512-c3/Zc+iW+qqDip6kXPYLEgsAu2lf4xz0EZDplB7EmSUMda12U1sGJPetH55B/j9eu0bTtKzKlNPWWyYC7wFNyQ==",
+ "requires": {
+ "async": "2.6.0",
+ "clone-deep": "0.3.0",
+ "loader-utils": "1.1.0",
+ "lodash.tail": "4.1.1",
+ "pify": "3.0.0"
+ }
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
+ "schema-utils": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
+ "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=",
+ "requires": {
+ "ajv": "5.5.2"
+ }
+ },
+ "scss-tokenizer": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
+ "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
+ "requires": {
+ "js-base64": "2.4.0",
+ "source-map": "0.4.4"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+ "requires": {
+ "amdefine": "1.0.1"
+ }
+ }
+ }
+ },
+ "select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+ "dev": true
+ },
+ "select2": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/select2/-/select2-4.0.5.tgz",
+ "integrity": "sha1-eqxQaSVhmFs007guxV4ib4lg1Ao=",
+ "requires": {
+ "almond": "0.3.3",
+ "jquery-mousewheel": "3.1.13"
+ }
+ },
+ "selfsigned": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.1.tgz",
+ "integrity": "sha1-v4y3uDJWxFUeMTR8YxF3jbme7FI=",
+ "dev": true,
+ "requires": {
+ "node-forge": "0.6.33"
+ }
+ },
+ "semver": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
+ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg=="
+ },
+ "send": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz",
+ "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "1.1.1",
+ "destroy": "1.0.4",
+ "encodeurl": "1.0.1",
+ "escape-html": "1.0.3",
+ "etag": "1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "1.6.2",
+ "mime": "1.4.1",
+ "ms": "2.0.0",
+ "on-finished": "2.3.0",
+ "range-parser": "1.2.0",
+ "statuses": "1.3.1"
+ }
+ },
+ "serialize-javascript": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.4.0.tgz",
+ "integrity": "sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU="
+ },
+ "serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+ "dev": true,
+ "requires": {
+ "accepts": "1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "1.0.3",
+ "http-errors": "1.6.2",
+ "mime-types": "2.1.17",
+ "parseurl": "1.3.2"
+ }
+ },
+ "serve-static": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz",
+ "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==",
+ "dev": true,
+ "requires": {
+ "encodeurl": "1.0.1",
+ "escape-html": "1.0.3",
+ "parseurl": "1.3.2",
+ "send": "0.16.1"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+ },
+ "set-immediate-shim": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
+ },
+ "setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "dev": true
+ },
+ "sha.js": {
+ "version": "2.4.9",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz",
+ "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==",
+ "requires": {
+ "inherits": "2.0.3",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "shallow-clone": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz",
+ "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=",
+ "requires": {
+ "is-extendable": "0.1.1",
+ "kind-of": "2.0.1",
+ "lazy-cache": "0.2.7",
+ "mixin-object": "2.0.1"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz",
+ "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=",
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "shallow-equal-fuzzy": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/shallow-equal-fuzzy/-/shallow-equal-fuzzy-0.0.2.tgz",
+ "integrity": "sha1-mZcXyWjTYiOxvX6pVAW2l7Gf1Vw="
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "requires": {
+ "shebang-regex": "1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+ },
+ "shellwords": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
+ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+ },
+ "simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
+ "requires": {
+ "is-arrayish": "0.3.1"
+ },
+ "dependencies": {
+ "is-arrayish": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.1.tgz",
+ "integrity": "sha1-wt/DhquqDD4zxI2z/ocFnmkGXv0="
+ }
+ }
+ },
+ "sinon": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.1.3.tgz",
+ "integrity": "sha512-c7u0ZuvBRX1eXuB4jN3BRCAOGiUTlM8SE3TxbJHrNiHUKL7wonujMOB6Fi1gQc00U91IscFORQHDga/eccqpbw==",
+ "dev": true,
+ "requires": {
+ "diff": "3.4.0",
+ "formatio": "1.2.0",
+ "lodash.get": "4.4.2",
+ "lolex": "2.3.1",
+ "nise": "1.2.0",
+ "supports-color": "4.5.0",
+ "type-detect": "4.0.5"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU="
+ },
+ "sntp": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
+ "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "sockjs": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.18.tgz",
+ "integrity": "sha1-2bKJMWyn33dZXvKZ4HXw+TfrQgc=",
+ "dev": true,
+ "requires": {
+ "faye-websocket": "0.10.0",
+ "uuid": "2.0.3"
+ },
+ "dependencies": {
+ "uuid": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
+ "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=",
+ "dev": true
+ }
+ }
+ },
+ "sockjs-client": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz",
+ "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "eventsource": "0.1.6",
+ "faye-websocket": "0.11.1",
+ "inherits": "2.0.3",
+ "json3": "3.3.2",
+ "url-parse": "1.2.0"
+ },
+ "dependencies": {
+ "faye-websocket": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz",
+ "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": "0.7.0"
+ }
+ }
+ }
+ },
+ "sort-keys": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
+ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
+ "requires": {
+ "is-plain-obj": "1.1.0"
+ }
+ },
+ "source-list-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz",
+ "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A=="
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ },
+ "source-map-support": {
+ "version": "0.4.18",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
+ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
+ "requires": {
+ "source-map": "0.5.7"
+ }
+ },
+ "spdx-correct": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
+ "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=",
+ "requires": {
+ "spdx-license-ids": "1.2.2"
+ }
+ },
+ "spdx-expression-parse": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz",
+ "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw="
+ },
+ "spdx-license-ids": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
+ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc="
+ },
+ "spdy": {
+ "version": "3.4.7",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz",
+ "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "handle-thing": "1.2.5",
+ "http-deceiver": "1.2.7",
+ "safe-buffer": "5.1.1",
+ "select-hose": "2.0.0",
+ "spdy-transport": "2.0.20"
+ }
+ },
+ "spdy-transport": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.20.tgz",
+ "integrity": "sha1-c15yBUxIayNU/onnAiVgBKOazk0=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "detect-node": "2.0.3",
+ "hpack.js": "2.1.6",
+ "obuf": "1.1.1",
+ "readable-stream": "2.3.3",
+ "safe-buffer": "5.1.1",
+ "wbuf": "1.7.2"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+ },
+ "sshpk": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
+ "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
+ "requires": {
+ "asn1": "0.2.3",
+ "assert-plus": "1.0.0",
+ "bcrypt-pbkdf": "1.0.1",
+ "dashdash": "1.14.1",
+ "ecc-jsbn": "0.1.1",
+ "getpass": "0.1.7",
+ "jsbn": "0.1.1",
+ "tweetnacl": "0.14.5"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "ssri": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.0.0.tgz",
+ "integrity": "sha512-728D4yoQcQm1ooZvSbywLkV1RjfITZXh0oWrhM/lnsx3nAHx7LsRGJWB/YyvoceAYRq98xqbstiN4JBv1/wNHg==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "stack-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.1.tgz",
+ "integrity": "sha1-1PM6tU6OOHeLDKXP07OvsS22hiA=",
+ "dev": true
+ },
+ "statuses": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=",
+ "dev": true
+ },
+ "stdout-stream": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz",
+ "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=",
+ "requires": {
+ "readable-stream": "2.3.3"
+ }
+ },
+ "stealthy-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
+ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
+ "dev": true
+ },
+ "stream-browserify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
+ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
+ "requires": {
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3"
+ }
+ },
+ "stream-each": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz",
+ "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==",
+ "requires": {
+ "end-of-stream": "1.4.0",
+ "stream-shift": "1.0.0"
+ }
+ },
+ "stream-http": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz",
+ "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==",
+ "requires": {
+ "builtin-status-codes": "3.0.0",
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3",
+ "to-arraybuffer": "1.0.1",
+ "xtend": "4.0.1"
+ }
+ },
+ "stream-shift": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
+ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI="
+ },
+ "strict-uri-encode": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
+ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
+ },
+ "string-length": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz",
+ "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=",
+ "dev": true,
+ "requires": {
+ "astral-regex": "1.0.0",
+ "strip-ansi": "4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "3.0.0"
+ }
+ }
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "1.1.0",
+ "is-fullwidth-code-point": "1.0.0",
+ "strip-ansi": "3.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "stringstream": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
+ "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "requires": {
+ "is-utf8": "0.2.1"
+ }
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
+ },
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "requires": {
+ "get-stdin": "4.0.1"
+ }
+ },
+ "style-loader": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.19.1.tgz",
+ "integrity": "sha512-IRE+ijgojrygQi3rsqT0U4dd+UcPCqcVvauZpCnQrGAlEe+FUIyrK93bUDScamesjP08JlQNsFJU+KmPedP5Og==",
+ "requires": {
+ "loader-utils": "1.1.0",
+ "schema-utils": "0.3.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+ },
+ "svgo": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz",
+ "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=",
+ "requires": {
+ "coa": "1.0.4",
+ "colors": "1.1.2",
+ "csso": "2.3.2",
+ "js-yaml": "3.7.0",
+ "mkdirp": "0.5.1",
+ "sax": "1.2.4",
+ "whet.extend": "0.9.9"
+ },
+ "dependencies": {
+ "js-yaml": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz",
+ "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=",
+ "requires": {
+ "argparse": "1.0.9",
+ "esprima": "2.7.3"
+ }
+ }
+ }
+ },
+ "symbol-observable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.1.0.tgz",
+ "integrity": "sha512-dQoid9tqQ+uotGhuTKEY11X4xhyYePVnqGSoSm3OGKh2E8LZ6RPULp1uXTctk33IeERlrRJYoVSBglsL05F5Uw=="
+ },
+ "symbol-tree": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
+ "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=",
+ "dev": true
+ },
+ "tapable": {
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz",
+ "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI="
+ },
+ "tar": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
+ "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
+ "requires": {
+ "block-stream": "0.0.9",
+ "fstream": "1.0.11",
+ "inherits": "2.0.3"
+ }
+ },
+ "test-exclude": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.1.1.tgz",
+ "integrity": "sha512-35+Asrsk3XHJDBgf/VRFexPgh3UyETv8IAn/LRTiZjVy6rjPVqdEk8dJcJYBzl1w0XCJM48lvTy8SfEsCWS4nA==",
+ "requires": {
+ "arrify": "1.0.1",
+ "micromatch": "2.3.11",
+ "object-assign": "4.1.1",
+ "read-pkg-up": "1.0.1",
+ "require-main-filename": "1.0.1"
+ }
+ },
+ "text-encoding": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz",
+ "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=",
+ "dev": true
+ },
+ "throat": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz",
+ "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+ "requires": {
+ "readable-stream": "2.3.3",
+ "xtend": "4.0.1"
+ }
+ },
+ "thunky": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz",
+ "integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=",
+ "dev": true
+ },
+ "time-stamp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz",
+ "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=",
+ "dev": true
+ },
+ "timers-browserify": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz",
+ "integrity": "sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==",
+ "requires": {
+ "setimmediate": "1.0.5"
+ }
+ },
+ "tiny-lr": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz",
+ "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=",
+ "dev": true,
+ "requires": {
+ "body-parser": "1.14.2",
+ "debug": "2.2.0",
+ "faye-websocket": "0.10.0",
+ "livereload-js": "2.2.2",
+ "parseurl": "1.3.2",
+ "qs": "5.1.0"
+ },
+ "dependencies": {
+ "body-parser": {
+ "version": "1.14.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz",
+ "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=",
+ "dev": true,
+ "requires": {
+ "bytes": "2.2.0",
+ "content-type": "1.0.4",
+ "debug": "2.2.0",
+ "depd": "1.1.1",
+ "http-errors": "1.3.1",
+ "iconv-lite": "0.4.13",
+ "on-finished": "2.3.0",
+ "qs": "5.2.0",
+ "raw-body": "2.1.7",
+ "type-is": "1.6.15"
+ },
+ "dependencies": {
+ "qs": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz",
+ "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=",
+ "dev": true
+ }
+ }
+ },
+ "bytes": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz",
+ "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+ "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
+ "dev": true,
+ "requires": {
+ "ms": "0.7.1"
+ }
+ },
+ "http-errors": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz",
+ "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "statuses": "1.3.1"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.13",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz",
+ "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=",
+ "dev": true
+ },
+ "ms": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+ "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
+ "dev": true
+ },
+ "qs": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz",
+ "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz",
+ "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=",
+ "dev": true,
+ "requires": {
+ "bytes": "2.4.0",
+ "iconv-lite": "0.4.13",
+ "unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
+ "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "tmpl": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
+ "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
+ "dev": true
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M="
+ },
+ "to-fast-properties": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
+ },
+ "tough-cookie": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz",
+ "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=",
+ "requires": {
+ "punycode": "1.4.1"
+ }
+ },
+ "tr46": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
+ "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
+ "dev": true,
+ "requires": {
+ "punycode": "2.1.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz",
+ "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=",
+ "dev": true
+ }
+ }
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM="
+ },
+ "trim-right": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
+ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM="
+ },
+ "true-case-path": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz",
+ "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=",
+ "requires": {
+ "glob": "6.0.4"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
+ "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
+ "requires": {
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ }
+ }
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="
+ },
+ "tunnel-agent": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
+ "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us="
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "optional": true
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "1.1.2"
+ }
+ },
+ "type-detect": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz",
+ "integrity": "sha512-N9IvkQslUGYGC24RkJk1ba99foK6TkwC2FHAEBlQFBP0RxQZS8ZpJuAZcwiY/w9ZJHFQb1aOXBI60OdxhTrwEQ==",
+ "dev": true
+ },
+ "type-is": {
+ "version": "1.6.15",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
+ "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=",
+ "dev": true,
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "2.1.17"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
+ },
+ "ua-parser-js": {
+ "version": "0.7.17",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz",
+ "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g=="
+ },
+ "uglify-js": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.2.tgz",
+ "integrity": "sha512-uZp2gduFfZDDfx0iIAmfKgRTANCooWcFjnFmJ2n8x/+RpBNk97lac1HU5wvZxWZCBbwHmTFDpWAsEhKnQpsM2A==",
+ "dev": true,
+ "requires": {
+ "commander": "2.12.2",
+ "source-map": "0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "uglify-to-browserify": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
+ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
+ "optional": true
+ },
+ "uglifyjs-webpack-plugin": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz",
+ "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=",
+ "requires": {
+ "source-map": "0.5.7",
+ "uglify-js": "2.8.29",
+ "webpack-sources": "1.1.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
+ },
+ "cliui": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+ "requires": {
+ "center-align": "0.1.3",
+ "right-align": "0.1.3",
+ "wordwrap": "0.0.2"
+ }
+ },
+ "uglify-js": {
+ "version": "2.8.29",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
+ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
+ "requires": {
+ "source-map": "0.5.7",
+ "uglify-to-browserify": "1.0.2",
+ "yargs": "3.10.0"
+ }
+ },
+ "yargs": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+ "requires": {
+ "camelcase": "1.2.1",
+ "cliui": "2.1.0",
+ "decamelize": "1.2.0",
+ "window-size": "0.1.0"
+ }
+ }
+ }
+ },
+ "underscore.string": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz",
+ "integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to=",
+ "dev": true
+ },
+ "uniq": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
+ "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8="
+ },
+ "uniqid": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz",
+ "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=",
+ "requires": {
+ "macaddress": "0.2.8"
+ }
+ },
+ "uniqs": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz",
+ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI="
+ },
+ "unique-filename": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz",
+ "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=",
+ "requires": {
+ "unique-slug": "2.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz",
+ "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=",
+ "requires": {
+ "imurmurhash": "0.1.4"
+ }
+ },
+ "units-css": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/units-css/-/units-css-0.4.0.tgz",
+ "integrity": "sha1-1iKGU6UZg9fBb/KPi53Dsf/tOgc=",
+ "requires": {
+ "isnumeric": "0.2.0",
+ "viewport-dimensions": "0.2.0"
+ }
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+ "dev": true
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ }
+ }
+ },
+ "url-parse": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz",
+ "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==",
+ "dev": true,
+ "requires": {
+ "querystringify": "1.0.0",
+ "requires-port": "1.0.0"
+ },
+ "dependencies": {
+ "querystringify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz",
+ "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=",
+ "dev": true
+ }
+ }
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "requires": {
+ "inherits": "2.0.1"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
+ }
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "util.promisify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
+ "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "1.1.2",
+ "object.getownpropertydescriptors": "2.0.3"
+ }
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
+ "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
+ "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
+ "requires": {
+ "spdx-correct": "1.0.2",
+ "spdx-expression-parse": "1.0.4"
+ }
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+ "dev": true
+ },
+ "vendors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz",
+ "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI="
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "1.3.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ }
+ }
+ },
+ "viewport-dimensions": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz",
+ "integrity": "sha1-3nQHR9tTh/0XJfUXXpG6x2r982w="
+ },
+ "vm-browserify": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
+ "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
+ "requires": {
+ "indexof": "0.0.1"
+ }
+ },
+ "walker": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",
+ "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=",
+ "dev": true,
+ "requires": {
+ "makeerror": "1.0.11"
+ }
+ },
+ "watch": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz",
+ "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=",
+ "dev": true,
+ "requires": {
+ "exec-sh": "0.2.1",
+ "minimist": "1.2.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "watchpack": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz",
+ "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=",
+ "requires": {
+ "async": "2.6.0",
+ "chokidar": "1.7.0",
+ "graceful-fs": "4.1.11"
+ }
+ },
+ "wbuf": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz",
+ "integrity": "sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=",
+ "dev": true,
+ "requires": {
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "weak": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/weak/-/weak-1.0.1.tgz",
+ "integrity": "sha1-q5mqswcGlZqgIAy4z1RbucszuZ4=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "bindings": "1.3.0",
+ "nan": "2.8.0"
+ }
+ },
+ "webidl-conversions": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+ "dev": true
+ },
+ "webpack": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz",
+ "integrity": "sha512-fxxKXoicjdXNUMY7LIdY89tkJJJ0m1Oo8PQutZ5rLgWbV5QVKI15Cn7+/IHnRTd3vfKfiwBx6SBqlorAuNA8LA==",
+ "requires": {
+ "acorn": "5.3.0",
+ "acorn-dynamic-import": "2.0.2",
+ "ajv": "5.5.2",
+ "ajv-keywords": "2.1.1",
+ "async": "2.6.0",
+ "enhanced-resolve": "3.4.1",
+ "escope": "3.6.0",
+ "interpret": "1.1.0",
+ "json-loader": "0.5.7",
+ "json5": "0.5.1",
+ "loader-runner": "2.3.0",
+ "loader-utils": "1.1.0",
+ "memory-fs": "0.4.1",
+ "mkdirp": "0.5.1",
+ "node-libs-browser": "2.1.0",
+ "source-map": "0.5.7",
+ "supports-color": "4.5.0",
+ "tapable": "0.2.8",
+ "uglifyjs-webpack-plugin": "0.4.6",
+ "watchpack": "1.4.0",
+ "webpack-sources": "1.1.0",
+ "yargs": "8.0.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+ },
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+ },
+ "load-json-file": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "parse-json": "2.2.0",
+ "pify": "2.3.0",
+ "strip-bom": "3.0.0"
+ }
+ },
+ "os-locale": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
+ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+ "requires": {
+ "execa": "0.7.0",
+ "lcid": "1.0.0",
+ "mem": "1.1.0"
+ }
+ },
+ "path-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+ "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+ "requires": {
+ "pify": "2.3.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ },
+ "read-pkg": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
+ "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+ "requires": {
+ "load-json-file": "2.0.0",
+ "normalize-package-data": "2.4.0",
+ "path-type": "2.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
+ "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+ "requires": {
+ "find-up": "2.1.0",
+ "read-pkg": "2.0.0"
+ }
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0",
+ "strip-ansi": "4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "requires": {
+ "ansi-regex": "3.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
+ },
+ "yargs": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz",
+ "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=",
+ "requires": {
+ "camelcase": "4.1.0",
+ "cliui": "3.2.0",
+ "decamelize": "1.2.0",
+ "get-caller-file": "1.0.2",
+ "os-locale": "2.1.0",
+ "read-pkg-up": "2.0.0",
+ "require-directory": "2.1.1",
+ "require-main-filename": "1.0.1",
+ "set-blocking": "2.0.0",
+ "string-width": "2.1.1",
+ "which-module": "2.0.0",
+ "y18n": "3.2.1",
+ "yargs-parser": "7.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz",
+ "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=",
+ "requires": {
+ "camelcase": "4.1.0"
+ }
+ }
+ }
+ },
+ "webpack-dev-middleware": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz",
+ "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==",
+ "dev": true,
+ "requires": {
+ "memory-fs": "0.4.1",
+ "mime": "1.6.0",
+ "path-is-absolute": "1.0.1",
+ "range-parser": "1.2.0",
+ "time-stamp": "2.0.0"
+ },
+ "dependencies": {
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true
+ }
+ }
+ },
+ "webpack-dev-server": {
+ "version": "2.9.7",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.9.7.tgz",
+ "integrity": "sha512-Pu7uoQFgQj5RE5wmlfkpYSzihMKxulwEuO2xCsaMnAnyRSApwoVi3B8WCm9XbigyWTHaIMzYGkB90Vr6leAeTQ==",
+ "dev": true,
+ "requires": {
+ "ansi-html": "0.0.7",
+ "array-includes": "3.0.3",
+ "bonjour": "3.5.0",
+ "chokidar": "1.7.0",
+ "compression": "1.7.1",
+ "connect-history-api-fallback": "1.5.0",
+ "debug": "3.1.0",
+ "del": "3.0.0",
+ "express": "4.16.2",
+ "html-entities": "1.2.1",
+ "http-proxy-middleware": "0.17.4",
+ "import-local": "0.1.1",
+ "internal-ip": "1.2.0",
+ "ip": "1.1.5",
+ "killable": "1.0.0",
+ "loglevel": "1.6.0",
+ "opn": "5.1.0",
+ "portfinder": "1.0.13",
+ "selfsigned": "1.10.1",
+ "serve-index": "1.9.1",
+ "sockjs": "0.3.18",
+ "sockjs-client": "1.1.4",
+ "spdy": "3.4.7",
+ "strip-ansi": "3.0.1",
+ "supports-color": "4.5.0",
+ "webpack-dev-middleware": "1.12.2",
+ "yargs": "6.6.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ },
+ "yargs": {
+ "version": "6.6.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz",
+ "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=",
+ "dev": true,
+ "requires": {
+ "camelcase": "3.0.0",
+ "cliui": "3.2.0",
+ "decamelize": "1.2.0",
+ "get-caller-file": "1.0.2",
+ "os-locale": "1.4.0",
+ "read-pkg-up": "1.0.1",
+ "require-directory": "2.1.1",
+ "require-main-filename": "1.0.1",
+ "set-blocking": "2.0.0",
+ "string-width": "1.0.2",
+ "which-module": "1.0.0",
+ "y18n": "3.2.1",
+ "yargs-parser": "4.2.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
+ "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
+ "dev": true,
+ "requires": {
+ "camelcase": "3.0.0"
+ }
+ }
+ }
+ },
+ "webpack-manifest-plugin": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-1.3.2.tgz",
+ "integrity": "sha512-MX60Bv2G83Zks9pi3oLOmRgnPAnwrlMn+lftMrWBm199VQjk46/xgzBi9lPfpZldw2+EI2S+OevuLIaDuxCWRw==",
+ "requires": {
+ "fs-extra": "0.30.0",
+ "lodash": "4.17.4"
+ }
+ },
+ "webpack-sources": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz",
+ "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==",
+ "requires": {
+ "source-list-map": "2.0.0",
+ "source-map": "0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "websocket-driver": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz",
+ "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=",
+ "dev": true,
+ "requires": {
+ "http-parser-js": "0.4.9",
+ "websocket-extensions": "0.1.3"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
+ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
+ "dev": true
+ },
+ "whatwg-encoding": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz",
+ "integrity": "sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw==",
+ "dev": true,
+ "requires": {
+ "iconv-lite": "0.4.19"
+ }
+ },
+ "whatwg-fetch": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz",
+ "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ="
+ },
+ "whatwg-url": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.4.0.tgz",
+ "integrity": "sha512-Z0CVh/YE217Foyb488eo+iBv+r7eAQ0wSTyApi9n06jhcA3z6Nidg/EGvl0UFkg7kMdKxfBzzr+o9JF+cevgMg==",
+ "dev": true,
+ "requires": {
+ "lodash.sortby": "4.7.0",
+ "tr46": "1.0.1",
+ "webidl-conversions": "4.0.2"
+ }
+ },
+ "whet.extend": {
+ "version": "0.9.9",
+ "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz",
+ "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE="
+ },
+ "which": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
+ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
+ "requires": {
+ "isexe": "2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
+ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8="
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
+ "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
+ "requires": {
+ "string-width": "1.0.2"
+ }
+ },
+ "window-size": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
+ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
+ },
+ "wordwrap": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+ "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "requires": {
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "write-file-atomic": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz",
+ "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "imurmurhash": "0.1.4",
+ "signal-exit": "3.0.2"
+ }
+ },
+ "xml-name-validator": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz",
+ "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=",
+ "dev": true
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
+ },
+ "y18n": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ },
+ "yargs": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
+ "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
+ "requires": {
+ "camelcase": "3.0.0",
+ "cliui": "3.2.0",
+ "decamelize": "1.2.0",
+ "get-caller-file": "1.0.2",
+ "os-locale": "1.4.0",
+ "read-pkg-up": "1.0.1",
+ "require-directory": "2.1.1",
+ "require-main-filename": "1.0.1",
+ "set-blocking": "2.0.0",
+ "string-width": "1.0.2",
+ "which-module": "1.0.0",
+ "y18n": "3.2.1",
+ "yargs-parser": "5.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz",
+ "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
+ "requires": {
+ "camelcase": "3.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
+ }
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
index a4791a452..262d80b97 100644
--- a/package.json
+++ b/package.json
@@ -1,47 +1,63 @@
{
"name": "stif-boiv",
"dependencies": {
- "@rails/webpacker": "3.0.2",
- "babel-jest": "21.2.0",
- "babel-polyfill": "6.16.0",
- "babel-preset-es2015": "6.18.0",
+ "@rails/webpacker": "3.2.0",
+ "babel-jest": "22.0.4",
+ "babel-polyfill": "6.26.0",
+ "babel-preset-es2015": "6.24.1",
"babel-preset-react": "6.24.1",
- "babelify": "7.3.0",
+ "babelify": "8.0.0",
"bootstrap": "3",
+ "clean-webpack-plugin": "^0.1.18",
+ "coffee-loader": "^0.9.0",
"coffeescript": "1.12.7",
"jquery": "3.2.1",
"lodash": "4.17.4",
- "promise-polyfill": "6.0.2",
- "react": "15.3.2",
- "react-dom": "15.3.2",
- "react-redux": "4.4.5",
- "react-select2": "4.0.3",
- "redux": "3.6.0",
- "redux-logger": "2.7.4",
+ "promise-polyfill": "7.0.0",
+ "prop-types": "^15.6.0",
+ "react": "16.2.0",
+ "react-dom": "16.2.0",
+ "react-redux": "5.0.6",
+ "react-select2-wrapper": "^1.0.4-beta5",
+ "redux": "3.7.2",
+ "redux-logger": "3.0.6",
"redux-promise": "0.5.3",
- "redux-thunk": "2.1.0",
+ "redux-thunk": "2.2.0",
+ "uglify-js": "3.3.2",
"whatwg-fetch": "2.0.3"
},
"license": "MIT",
"engines": {
- "node": "~6.12.0"
+ "node": "^6.12.3"
},
"devDependencies": {
- "clean-webpack-plugin": "0.1.17",
- "es6-object-assign": "1.0.3",
- "jest": "21.2.1",
- "react-addons-test-utils": "15.3.2",
- "sinon": "1.17.7",
- "uglify-js": "3.1.3",
- "webpack-dev-server": "2.9.1"
+ "es6-object-assign": "1.1.0",
+ "grunt": "^1.0.1",
+ "grunt-contrib-watch": "^1.0.0",
+ "grunt-watch-change": "^0.1.1",
+ "jest": "22.0.4",
+ "jest-context": "^2.1.0",
+ "jest-environment-jsdom-global": "^1.0.2",
+ "jest-set": "^2.0.0",
+ "react-addons-test-utils": "15.6.2",
+ "react-test-renderer": "^16.2.0",
+ "sinon": "4.1.3",
+ "webpack-dev-server": "2.9.7"
},
"jest": {
"testRegex": "(/test/.*|(\\_|/)spec)\\.js$",
"roots": [
"<rootDir>/spec/javascript"
],
+ "transform": {
+ "^.+\\.coffee$": "<rootDir>/spec/javascript/preprocessor.js",
+ "^.+\\.jsx?$": "babel-jest"
+ },
+ "testEnvironment": "jest-environment-jsdom-global",
"setupFiles": [
- "<rootDir>/spec/javascript/spec_helper.js"
+ "<rootDir>/spec/javascript/spec_helper.js",
+ "jest-context/setup",
+ "jest-set/setup"
]
}
}
diff --git a/spec/controllers/api/v1/stop_area_controller_spec.rb b/spec/controllers/api/v1/stop_area_controller_spec.rb
index eb0c87661..1ad71a95a 100644
--- a/spec/controllers/api/v1/stop_area_controller_spec.rb
+++ b/spec/controllers/api/v1/stop_area_controller_spec.rb
@@ -18,16 +18,15 @@ describe Api::V1::StopAreasController, :type => :controller do
end
end
describe "GET #index, :q => { :name_cont => 'aa'}" do
- let!(:sa1) { create(:stop_area, :name => "aaa") }
- let!(:sa2) { create(:stop_area, :name => "aab") }
- let!(:sa3) { create(:stop_area, :name => "abb") }
+ let!(:sa1) { create(:stop_area, :name => "aaa", stop_area_referential: referential.stop_area_referential) }
+ let!(:sa2) { create(:stop_area, :name => "aab", stop_area_referential: referential.stop_area_referential) }
+ let!(:sa3) { create(:stop_area, :name => "abb", stop_area_referential: referential.stop_area_referential) }
before :each do
config_formatted_request_with_authorization( "application/json")
- get :index, :q => { :name_cont => "aa"}
+ get :index, :q => { :name_cont => "aa"}
end
it "should assign expected stop_areas" do
expect(assigns[:stop_areas].map(&:name).sort).to eq([ sa1.name, sa2.name])
end
end
end
-
diff --git a/spec/controllers/autocomplete_purchase_windows_controller_spec.rb b/spec/controllers/autocomplete_purchase_windows_controller_spec.rb
new file mode 100644
index 000000000..cea600ea8
--- /dev/null
+++ b/spec/controllers/autocomplete_purchase_windows_controller_spec.rb
@@ -0,0 +1,33 @@
+require 'rails_helper'
+
+RSpec.describe AutocompletePurchaseWindowsController, type: :controller do
+ login_user
+
+ let(:referential) { Referential.first }
+ let!(:window) { create :purchase_window, referential: referential, name: 'écolà militaire' }
+
+ describe 'GET #index' do
+ it 'should be unauthorized' do
+ expect { get(:index, referential_id: referential.id) }.to raise_error(FeatureChecker::NotAuthorizedError)
+ end
+
+ with_feature "purchase_windows" do
+ let(:request){ get(:index, referential_id: referential.id) }
+ before do
+ request
+ end
+
+ it 'should be successful' do
+ expect(response).to be_success
+ end
+
+ context 'search by name' do
+ let(:request){ get :index, referential_id: referential.id, q: {name_or_objectid_cont_any: 'écolà'}, :format => :json }
+ it 'should be successful' do
+ expect(response).to be_success
+ expect(assigns(:purchase_windows)).to eq([window])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/autocomplete_stop_areas_controller_spec.rb b/spec/controllers/autocomplete_stop_areas_controller_spec.rb
new file mode 100644
index 000000000..e0d1cd714
--- /dev/null
+++ b/spec/controllers/autocomplete_stop_areas_controller_spec.rb
@@ -0,0 +1,61 @@
+require 'rails_helper'
+
+RSpec.describe AutocompleteStopAreasController, type: :controller do
+ login_user
+
+ let(:referential) { Referential.first }
+ let(:other_referential) { create :referential }
+ let!(:stop_area) { create :stop_area, name: 'écolà militaire', referential: referential }
+ let!(:other_referential_stop_area) { create :stop_area, name: 'écolà militaire', referential: other_referential }
+ let!(:zdep_stop_area) { create :stop_area, area_type: "zdep", referential: referential }
+ let!(:not_zdep_stop_area) { create :stop_area, area_type: "lda", referential: referential }
+
+ describe 'GET #index' do
+ it 'should be successful' do
+ get :index, referential_id: referential.id
+ expect(response).to be_success
+ end
+
+ it "should filter stop areas based on referential" do
+ get :index, referential_id: referential.id
+ expect(assigns(:stop_areas)).to include(stop_area)
+ expect(assigns(:stop_areas)).to_not include(other_referential_stop_area)
+ end
+
+ context 'search by name' do
+ it 'should be successful' do
+ get :index, referential_id: referential.id, q: 'écolà', :format => :json
+ expect(response).to be_success
+ expect(assigns(:stop_areas)).to eq([stop_area])
+ end
+
+ it 'should be accent insensitive' do
+ get :index, referential_id: referential.id, q: 'ecola', :format => :json
+ expect(response).to be_success
+ expect(assigns(:stop_areas)).to eq([stop_area])
+ end
+ end
+ end
+
+ context "when searching from the route editor" do
+ let(:scope) { :route_editor }
+ let(:request){
+ get :index, referential_id: referential.id, scope: scope
+ }
+ it "should filter stop areas based on type" do
+ request
+ expect(assigns(:stop_areas)).to include(zdep_stop_area)
+ expect(assigns(:stop_areas)).to_not include(not_zdep_stop_area)
+ end
+
+ with_feature :route_stop_areas_all_types do
+ it "should not filter stop areas based on type" do
+ request
+ expect(assigns(:stop_areas)).to include(zdep_stop_area)
+ expect(assigns(:stop_areas)).to include(not_zdep_stop_area)
+ end
+ end
+ end
+
+
+end
diff --git a/spec/controllers/concerns/feature_checker_spec.rb b/spec/controllers/concerns/feature_checker_spec.rb
new file mode 100644
index 000000000..1d289bb15
--- /dev/null
+++ b/spec/controllers/concerns/feature_checker_spec.rb
@@ -0,0 +1,37 @@
+require "rails_helper"
+
+RSpec.describe "FeatureChecker", type: :controller do
+ login_user
+
+ controller do
+ include FeatureChecker
+ requires_feature :test, only: :protected
+
+ def protected; render text: "protected"; end
+ def not_protected; render text: "not protected"; end
+
+ def current_organisation
+ @organisation ||= Organisation.new
+ end
+ end
+
+ before do
+ routes.draw do
+ get "protected" => "anonymous#protected"
+ get "not_protected" => "anonymous#not_protected"
+ end
+ end
+
+ it "refuse access when organisation does not have the feature" do
+ expect{ get(:protected) }.to raise_error(FeatureChecker::NotAuthorizedError)
+ end
+
+ it "accept access on unprotected action" do
+ get :not_protected
+ end
+
+ it 'accept access when organisation has feature' do
+ controller.current_organisation.features << "test"
+ get :protected
+ end
+end
diff --git a/spec/controllers/imports_controller_spec.rb b/spec/controllers/imports_controller_spec.rb
index 22be9f6ed..08495ff47 100644
--- a/spec/controllers/imports_controller_spec.rb
+++ b/spec/controllers/imports_controller_spec.rb
@@ -17,6 +17,20 @@ RSpec.describe ImportsController, :type => :controller do
end
end
+ describe "POST #create" do
+ it "displays a flash message" do
+ post :create, workbench_id: workbench.id,
+ import: {
+ name: 'Offre',
+ file: fixture_file_upload('nozip.zip')
+ }
+
+ expect(controller).to set_flash[:notice].to(
+ I18n.t('flash.imports.create.notice')
+ )
+ end
+ end
+
describe 'GET #download' do
it 'should be successful' do
get :download, workbench_id: workbench.id, id: import.id, token: import.token_download
diff --git a/spec/controllers/journey_patterns_collections_controller_spec.rb b/spec/controllers/journey_patterns_collections_controller_spec.rb
index 7015bfe98..e2adc59f4 100644
--- a/spec/controllers/journey_patterns_collections_controller_spec.rb
+++ b/spec/controllers/journey_patterns_collections_controller_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe JourneyPatternsCollectionsController, :type => :controller do
before do
allow(controller).to receive(:pundit_user).and_return(user_context)
+ allow(controller).to receive(:current_organisation).and_return(@user.organisation)
end
it 'computes them correctly if not authorized' do
@@ -24,4 +25,20 @@ RSpec.describe JourneyPatternsCollectionsController, :type => :controller do
'journey_patterns.update' => true }.to_json)
end
end
+
+ context "get show" do
+ login_user
+
+ let( :referential ){ Referential.first }
+ let( :line ){ create(:line) }
+ let( :route ){ create(:route, line: line) }
+
+ let(:request){
+ get :show, referential_id: referential.id, line_id: line.id, route_id: route.id, format: :json
+ }
+ it 'should be successful' do
+ request
+ expect(response).to be_success
+ end
+ end
end
diff --git a/spec/controllers/line_referentials_controller_spec.rb b/spec/controllers/line_referentials_controller_spec.rb
index aee24b0fa..17ffb670d 100644
--- a/spec/controllers/line_referentials_controller_spec.rb
+++ b/spec/controllers/line_referentials_controller_spec.rb
@@ -1,3 +1,19 @@
RSpec.describe LineReferentialsController, :type => :controller do
+ login_user
+ let(:line_referential) { create :line_referential }
+
+ describe 'PUT sync' do
+ let(:request){ put :sync, id: line_referential.id }
+
+ it 'should redirect to 403' do
+ expect(request).to redirect_to "/403"
+ end
+
+ with_permission "line_referentials.synchronize" do
+ it 'returns HTTP success' do
+ expect(request).to redirect_to [line_referential]
+ end
+ end
+ end
end
diff --git a/spec/controllers/lines_controller_spec.rb b/spec/controllers/lines_controller_spec.rb
new file mode 100644
index 000000000..65fe88b96
--- /dev/null
+++ b/spec/controllers/lines_controller_spec.rb
@@ -0,0 +1,38 @@
+RSpec.describe LinesController, :type => :controller do
+ login_user
+
+ let(:line_referential) { create :line_referential, member: @user.organisation }
+ let(:line) { create :line, line_referential: line_referential }
+
+ describe 'PUT deactivate' do
+ let(:request){ put :deactivate, id: line.id, line_referential_id: line_referential.id }
+
+ it 'should redirect to 403' do
+ expect(request).to redirect_to "/403"
+ end
+
+ with_permission "lines.change_status" do
+ it 'returns HTTP success' do
+ expect(request).to redirect_to [line_referential, line]
+ expect(line.reload).to be_deactivated
+ end
+ end
+ end
+
+ describe 'PUT activate' do
+ let(:request){ put :activate, id: line.id, line_referential_id: line_referential.id }
+ before(:each){
+ line.deactivate!
+ }
+ it 'should redirect to 403' do
+ expect(request).to redirect_to "/403"
+ end
+
+ with_permission "lines.change_status" do
+ it 'returns HTTP success' do
+ expect(request).to redirect_to [line_referential, line]
+ expect(line.reload).to be_activated
+ end
+ end
+ end
+end
diff --git a/spec/controllers/referential_vehicle_journeys_controller_spec.rb b/spec/controllers/referential_vehicle_journeys_controller_spec.rb
new file mode 100644
index 000000000..cc6b44b9d
--- /dev/null
+++ b/spec/controllers/referential_vehicle_journeys_controller_spec.rb
@@ -0,0 +1,98 @@
+require "rails_helper"
+
+RSpec.describe ReferentialVehicleJourneysController, type: :controller do
+ login_user
+
+ before do
+ @user.organisation.update features: %w{referential_vehicle_journeys}
+ end
+
+ describe 'GET #index' do
+ it 'should be successful' do
+ get :index, referential_id: referential
+ expect(response).to be_success
+ end
+
+ it "refuse access when organisation does not have the feature 'referential_vehicle_journeys'" do
+ @user.organisation.update features: []
+
+ expect do
+ get :index, referential_id: referential
+ end.to raise_error(FeatureChecker::NotAuthorizedError)
+ end
+
+ it 'define Ransack search (alias @q)' do
+ get :index, referential_id: referential
+ expect(assigns[:q]).to be_an_instance_of(Ransack::Search)
+ end
+
+ it 'define @vehicle_journeys collection' do
+ vehicle_journey = FactoryGirl.create :vehicle_journey
+ get :index, referential_id: referential
+ expect(assigns[:vehicle_journeys]).to include(vehicle_journey)
+ end
+
+ it 'paginage @vehicle_journeys collection' do
+ FactoryGirl.create :vehicle_journey
+
+ get :index, referential_id: referential
+ expect(assigns[:vehicle_journeys].total_entries).to be(1)
+ end
+
+ context "when filtered on stop areas" do
+ let!(:request){
+ get :index, referential_id: referential, q: q
+ }
+
+ let(:stop_area_ids){ [] }
+
+ def create_journey_pattern_with_stop_areas(*stop_areas)
+ j = create(:journey_pattern)
+ stop_areas.each do |area|
+ sp = create(:stop_point, stop_area: area)
+ j.stop_points << sp
+ end
+ j.save
+ j
+ end
+
+ let(:q){ {stop_area_ids: stop_area_ids}}
+ let(:stop_area_1){ create :stop_area }
+ let(:stop_area_2){ create :stop_area }
+ let!(:journey_1){ create_journey_pattern_with_stop_areas(stop_area_1)}
+ let!(:journey_2){ create_journey_pattern_with_stop_areas(stop_area_2)}
+ let!(:journey_1_and_2){ create_journey_pattern_with_stop_areas(stop_area_1, stop_area_2)}
+ let!(:vehicle_journey_1){ create(:vehicle_journey, journey_pattern: journey_1)}
+ let!(:vehicle_journey_2){ create(:vehicle_journey, journey_pattern: journey_2)}
+ let!(:vehicle_journey_1_and_2){ create(:vehicle_journey, journey_pattern: journey_1_and_2)}
+
+ context "with one stop" do
+ let(:stop_area_ids){[stop_area_1.id]}
+ it "should apply filters" do
+ expect(vehicle_journey_1.stop_areas).to include stop_area_1
+ expect(vehicle_journey_2.stop_areas).to_not include stop_area_1
+ expect(vehicle_journey_1_and_2.stop_areas).to include stop_area_1
+ expect(assigns[:vehicle_journeys]).to include(vehicle_journey_1)
+ expect(assigns[:vehicle_journeys]).to_not include(vehicle_journey_2)
+ expect(assigns[:vehicle_journeys]).to include(vehicle_journey_1_and_2)
+ end
+ end
+
+ context "with 2 stops" do
+ let(:stop_area_ids){[stop_area_1.id, stop_area_2.id]}
+ it "should apply filters" do
+ expect(vehicle_journey_1.stop_areas).to include stop_area_1
+ expect(vehicle_journey_1.stop_areas).to_not include stop_area_2
+ expect(vehicle_journey_2.stop_areas).to include stop_area_2
+ expect(vehicle_journey_2.stop_areas).to_not include stop_area_1
+ expect(vehicle_journey_1_and_2.stop_areas).to include stop_area_1
+ expect(vehicle_journey_1_and_2.stop_areas).to include stop_area_2
+ expect(assigns[:vehicle_journeys]).to_not include(vehicle_journey_1)
+ expect(assigns[:vehicle_journeys]).to_not include(vehicle_journey_2)
+ expect(assigns[:vehicle_journeys]).to include(vehicle_journey_1_and_2)
+ end
+ end
+ end
+ end
+
+end
diff --git a/spec/controllers/referentials_controller_spec.rb b/spec/controllers/referentials_controller_spec.rb
index fba063085..f97480600 100644
--- a/spec/controllers/referentials_controller_spec.rb
+++ b/spec/controllers/referentials_controller_spec.rb
@@ -30,4 +30,33 @@ describe ReferentialsController, :type => :controller do
expect(assigns[:compliance_control_sets]).to eq([compliance_control_set])
end
end
+
+ describe "POST #validate" do
+ it "displays a flash message" do
+ post :validate, id: referential.id, params: {
+ compliance_control_set: create(:compliance_control_set).id
+ }
+
+ expect(controller).to set_flash[:notice].to(
+ I18n.t('notice.referentials.validate')
+ )
+ end
+ end
+
+ describe "POST #create" do
+ context "when duplicating" do
+ it "displays a flash message", pending: 'requires more params to create a valid Referential' do
+ post :create,
+ from: referential.id,
+ current_workbench_id: referential.workbench_id,
+ referential: {
+ name: 'Duplicated'
+ }
+
+ expect(controller).to set_flash[:notice].to(
+ I18n.t('notice.referentials.duplicate')
+ )
+ end
+ end
+ end
end
diff --git a/spec/controllers/statuses_controller_spec.rb b/spec/controllers/statuses_controller_spec.rb
new file mode 100644
index 000000000..8a6db8e28
--- /dev/null
+++ b/spec/controllers/statuses_controller_spec.rb
@@ -0,0 +1,50 @@
+RSpec.describe StatusesController, :type => :controller do
+
+ describe "GET index" do
+ login_user
+ render_views
+
+
+ let(:request){ get :index}
+ let(:parsed_response){ JSON.parse response.body }
+ it "should be ok" do
+ request
+ expect(response).to have_http_status 200
+ expect(parsed_response["status"]).to eq "ok"
+ end
+ context "without blocked object" do
+ before do
+ create :referential
+ create :import
+ create :compliance_check_set
+ request
+ end
+
+ it "should be ok" do
+ expect(response).to have_http_status 200
+ expect(parsed_response["status"]).to eq "ok"
+ expect(parsed_response["referentials_blocked"]).to eq 0
+ expect(parsed_response["imports_blocked"]).to eq 0
+ expect(parsed_response["imports_blocked"]).to eq 0
+ end
+ end
+
+ context "with a blocked object" do
+ before do
+ create :referential, created_at: 5.hours.ago, ready: false
+ create :import
+ create :compliance_check_set
+ request
+ end
+
+ it "should be ko" do
+ expect(Referential.blocked.count).to eq 1
+ expect(response).to have_http_status 200
+ expect(parsed_response["status"]).to eq "ko"
+ expect(parsed_response["referentials_blocked"]).to eq 1
+ expect(parsed_response["imports_blocked"]).to eq 0
+ expect(parsed_response["imports_blocked"]).to eq 0
+ end
+ end
+ end
+end
diff --git a/spec/controllers/stop_area_referentials_controller_spec.rb b/spec/controllers/stop_area_referentials_controller_spec.rb
new file mode 100644
index 000000000..384323334
--- /dev/null
+++ b/spec/controllers/stop_area_referentials_controller_spec.rb
@@ -0,0 +1,17 @@
+RSpec.describe StopAreaReferentialsController, :type => :controller do
+ login_user
+
+ let(:stop_area_referential) { create :stop_area_referential }
+
+ describe 'PUT sync' do
+ let(:request){ put :sync, id: stop_area_referential.id }
+
+ it { expect(request).to redirect_to "/403" }
+
+ with_permission "stop_area_referentials.synchronize" do
+ it 'returns HTTP success' do
+ expect(request).to redirect_to [stop_area_referential]
+ end
+ end
+ end
+end
diff --git a/spec/controllers/stop_areas_controller_spec.rb b/spec/controllers/stop_areas_controller_spec.rb
new file mode 100644
index 000000000..23bca3c36
--- /dev/null
+++ b/spec/controllers/stop_areas_controller_spec.rb
@@ -0,0 +1,38 @@
+RSpec.describe StopAreasController, :type => :controller do
+ login_user
+
+ let(:stop_area_referential) { create :stop_area_referential, member: @user.organisation }
+ let(:stop_area) { create :stop_area, stop_area_referential: stop_area_referential }
+
+ describe 'PUT deactivate' do
+ let(:request){ put :deactivate, id: stop_area.id, stop_area_referential_id: stop_area_referential.id }
+
+ it 'should redirect to 403' do
+ expect(request).to redirect_to "/403"
+ end
+
+ with_permission "stop_areas.change_status" do
+ it 'returns HTTP success' do
+ expect(request).to redirect_to [stop_area_referential, stop_area]
+ expect(stop_area.reload).to be_deactivated
+ end
+ end
+ end
+
+ describe 'PUT activate' do
+ let(:request){ put :activate, id: stop_area.id, stop_area_referential_id: stop_area_referential.id }
+ before(:each){
+ stop_area.deactivate!
+ }
+ it 'should redirect to 403' do
+ expect(request).to redirect_to "/403"
+ end
+
+ with_permission "stop_areas.change_status" do
+ it 'returns HTTP success' do
+ expect(request).to redirect_to [stop_area_referential, stop_area]
+ expect(stop_area.reload).to be_activated
+ end
+ end
+ end
+end
diff --git a/spec/controllers/time_tables_controller_spec.rb b/spec/controllers/time_tables_controller_spec.rb
new file mode 100644
index 000000000..85f2c10e4
--- /dev/null
+++ b/spec/controllers/time_tables_controller_spec.rb
@@ -0,0 +1,29 @@
+RSpec.describe TimeTablesController, :type => :controller do
+ login_user
+
+ describe 'POST create' do
+ let(:request){ post :create, referential_id: referential.id, time_table: time_table_params }
+ let(:time_table_params){{comment: "test"}}
+
+ it "should create a timetable" do
+ expect{request}.to change{ Chouette::TimeTable.count }.by 1
+ expect(Chouette::TimeTable.last.comment).to eq "test"
+ %i(monday tuesday wednesday thursday friday saturday sunday).each do |d|
+ expect(Chouette::TimeTable.last.send(d)).to be_falsy
+ end
+ end
+
+ context "when given a calendar" do
+ let(:calendar){ create :calendar, int_day_types: Calendar::MONDAY | Calendar::SUNDAY }
+ let(:time_table_params){{comment: "test", calendar_id: calendar.id}}
+ it "should create a timetable" do
+ expect{request}.to change{ Chouette::TimeTable.count }.by 1
+ expect(Chouette::TimeTable.last.comment).to eq "test"
+ expect(Chouette::TimeTable.last.calendar).to eq calendar
+ %i(monday tuesday wednesday thursday friday saturday sunday).each do |d|
+ expect(Chouette::TimeTable.last.send(d)).to eq calendar.send(d)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/vehicle_journeys_controller_spec.rb b/spec/controllers/vehicle_journeys_controller_spec.rb
index c9356fffa..300684532 100644
--- a/spec/controllers/vehicle_journeys_controller_spec.rb
+++ b/spec/controllers/vehicle_journeys_controller_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe VehicleJourneysController, :type => :controller do
before do
allow(controller).to receive(:pundit_user).and_return(user_context)
+ allow(controller).to receive(:current_organisation).and_return(@user.organisation)
end
it 'computes them correctly if not authorized' do
@@ -25,4 +26,28 @@ RSpec.describe VehicleJourneysController, :type => :controller do
end
end
+ describe "GET index" do
+ login_user
+ render_views
+
+ context "in JSON" do
+ let(:vehicle_journey){ create :vehicle_journey }
+ let(:route){ vehicle_journey.route }
+ let(:line){ route.line }
+ let!(:request){ get :index, referential_id: referential.id, line_id: line.id, route_id: route.id, format: :json}
+ let(:parsed_response){ JSON.parse response.body }
+ it "should have all the attributes" do
+ expect(response).to have_http_status 200
+ vehicle_journey = parsed_response["vehicle_journeys"].first
+ vehicle_journey_at_stops_matrix = vehicle_journey["vehicle_journey_at_stops"]
+ vehicle_journey_at_stops_matrix.each do |received_vjas|
+ expect(received_vjas).to have_key("id")
+ vjas = Chouette::VehicleJourneyAtStop.find received_vjas["id"]
+ [:connecting_service_id, :boarding_alighting_possibility].each do |att|
+ expect(received_vjas[att]).to eq vjas.send(att)
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 585636124..a7fe0a162 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -44,6 +44,6 @@ Diff: #{diff}
def diff
RSpec::Support::Differ.new(
color: RSpec::Matchers.configuration.color?
- ).diff_as_string(@expected, @original)
+ ).diff_as_string(@original, @expected)
end
end
diff --git a/spec/decorators/api_key_decorator_spec.rb b/spec/decorators/api_key_decorator_spec.rb
deleted file mode 100644
index 9451a3974..000000000
--- a/spec/decorators/api_key_decorator_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'spec_helper'
-
-describe ApiKeyDecorator do
-end
diff --git a/spec/decorators/referential_decorator_spec.rb b/spec/decorators/referential_decorator_spec.rb
index cbeaf2407..efc438132 100644
--- a/spec/decorators/referential_decorator_spec.rb
+++ b/spec/decorators/referential_decorator_spec.rb
@@ -1,4 +1,5 @@
RSpec.describe ReferentialDecorator, type: [:helper, :decorator] do
+ include Support::DecoratorHelpers
let( :object ){ build_stubbed :referential }
let( :referential ){ object }
@@ -20,8 +21,8 @@ RSpec.describe ReferentialDecorator, type: [:helper, :decorator] do
context 'unarchived referential' do
context 'no rights' do
- it 'has only a Calendar action' do
- expect_action_link_hrefs.to eq([referential_time_tables_path(object)])
+ it 'has only show and Calendar actions' do
+ expect_action_link_hrefs.to eq([[object], referential_time_tables_path(object)])
end
end
@@ -30,8 +31,9 @@ RSpec.describe ReferentialDecorator, type: [:helper, :decorator] do
let( :user ){ build_stubbed :allmighty_user }
it 'has only default actions' do
- expect_action_link_elements.to be_empty
+ expect_action_link_elements.to eq ["Consulter", "Calendriers", "Dupliquer"]
expect_action_link_hrefs.to eq([
+ [object],
referential_time_tables_path(object),
new_referential_path(from: object)
])
@@ -40,16 +42,36 @@ RSpec.describe ReferentialDecorator, type: [:helper, :decorator] do
context 'all rights and same organisation' do
let( :user ){ build_stubbed :allmighty_user, organisation: referential.organisation }
+ let( :action){ :index }
+ context "on index" do
+ it 'has corresponding actions' do
+ expect_action_link_elements(action).to eq ["Consulter", "Editer", "Calendriers", "Dupliquer", "Valider", "Conserver","<span class=\"fa fa-trash mr-xs\"></span>Supprimer"]
+ expect_action_link_hrefs(action).to eq([
+ [object],
+ [:edit, object],
+ referential_time_tables_path(object),
+ new_referential_path(from: object),
+ referential_select_compliance_control_set_path(object),
+ archive_referential_path(object),
+ referential_path(object)
+ ])
+ end
+ end
- it 'has all actions' do
- expect_action_link_elements.to eq(%w{Purger})
- expect_action_link_hrefs.to eq([
- referential_time_tables_path(object),
- new_referential_path(from: object),
- referential_select_compliance_control_set_path(object),
- archive_referential_path(object),
- referential_path(object)
- ])
+ context "on show" do
+ let( :action){ :show }
+ it 'has corresponding actions' do
+ expect_action_link_elements(action).to eq ["Editer", "Calendriers", "Dupliquer", "Valider", "Conserver", "Purger", "<span class=\"fa fa-trash mr-xs\"></span>Supprimer"]
+ expect_action_link_hrefs(action).to eq([
+ [:edit, object],
+ referential_time_tables_path(object),
+ new_referential_path(from: object),
+ referential_select_compliance_control_set_path(object),
+ archive_referential_path(object),
+ "#",
+ referential_path(object)
+ ])
+ end
end
end
end
@@ -57,17 +79,19 @@ RSpec.describe ReferentialDecorator, type: [:helper, :decorator] do
context 'archived referential' do
before { referential.archived_at = 42.seconds.ago }
context 'no rights' do
- it 'has only a Calendar action' do
- expect_action_link_hrefs.to eq([referential_time_tables_path(object)])
+ it 'has only ahow and calendar actions' do
+ expect_action_link_hrefs.to eq([[object], referential_time_tables_path(object)])
end
end
context 'all rights and different organisation' do
let( :user ){ build_stubbed :allmighty_user }
it 'has only default actions' do
- expect_action_link_elements.to be_empty
+ expect_action_link_elements.to eq ["Consulter", "Calendriers", "Dupliquer"]
expect_action_link_hrefs.to eq([
+ [object],
referential_time_tables_path(object),
+ new_referential_path(from: object)
])
end
end
diff --git a/spec/decorators/stop_area_decorator_spec.rb b/spec/decorators/stop_area_decorator_spec.rb
new file mode 100644
index 000000000..fd6aa207a
--- /dev/null
+++ b/spec/decorators/stop_area_decorator_spec.rb
@@ -0,0 +1,25 @@
+require "rails_helper"
+
+RSpec.describe StopAreaDecorator do
+
+ let(:stop_area) { Chouette::StopArea.new }
+ let(:decorator) { stop_area.decorate }
+
+ describe '#waiting_time_text' do
+ it "returns '-' when waiting_time is nil" do
+ stop_area.waiting_time = nil
+ expect(decorator.waiting_time_text).to eq('-')
+ end
+
+ it "returns '-' when waiting_time is zero" do
+ stop_area.waiting_time = 0
+ expect(decorator.waiting_time_text).to eq('-')
+ end
+
+ it "returns '120 minutes' when waiting_time is 120" do
+ stop_area.waiting_time = 120
+ expect(decorator.waiting_time_text).to eq('120 minutes')
+ end
+ end
+
+end
diff --git a/spec/factories/calendars.rb b/spec/factories/calendars.rb
index 5f3188bee..d9fd242d1 100644
--- a/spec/factories/calendars.rb
+++ b/spec/factories/calendars.rb
@@ -6,6 +6,7 @@ FactoryGirl.define do
sequence(:dates) { |n| [ Date.yesterday - n, Date.yesterday - 2*n ] }
shared false
organisation
+ workgroup
end
sequence :date_range do |n|
diff --git a/spec/factories/chouette_journey_pattern.rb b/spec/factories/chouette_journey_pattern.rb
index 05d8d536a..d96302e7f 100644
--- a/spec/factories/chouette_journey_pattern.rb
+++ b/spec/factories/chouette_journey_pattern.rb
@@ -13,6 +13,12 @@ FactoryGirl.define do
j.stop_point_ids = j.route.stop_points.map(&:id)
j.departure_stop_point_id = j.route.stop_points.first.id
j.arrival_stop_point_id = j.route.stop_points.last.id
+ j.costs = {
+ "1-2": {
+ distance: 10,
+ time: 10
+ }
+ }
end
end
@@ -35,5 +41,3 @@ FactoryGirl.define do
end
end
-
-
diff --git a/spec/factories/chouette_lines.rb b/spec/factories/chouette_lines.rb
index 95f760174..c013b9d2b 100644
--- a/spec/factories/chouette_lines.rb
+++ b/spec/factories/chouette_lines.rb
@@ -8,7 +8,7 @@ FactoryGirl.define do
association :network, :factory => :network
association :company, :factory => :company
-
+
before(:create) do |line|
line.line_referential ||= LineReferential.find_by! name: "first"
end
@@ -35,7 +35,7 @@ FactoryGirl.define do
after(:create) do |line|
line.routes.each do |route|
route.stop_points.each do |stop_point|
- comm = create(:stop_area, :area_type => "lda")
+ comm = create(:stop_area, :area_type => "gdl")
stop_point.stop_area.update_attributes(:parent_id => comm.id)
end
end
diff --git a/spec/factories/chouette_purchase_windows.rb b/spec/factories/chouette_purchase_windows.rb
new file mode 100644
index 000000000..2e2faf4d8
--- /dev/null
+++ b/spec/factories/chouette_purchase_windows.rb
@@ -0,0 +1,12 @@
+FactoryGirl.define do
+ factory :purchase_window, class: Chouette::PurchaseWindow do
+ sequence(:name) { |n| "Purchase Window #{n}" }
+ sequence(:objectid) { |n| "organisation:PurchaseWindow:#{n}:LOC" }
+ date_ranges { [generate(:periods)] }
+ end
+
+ sequence :periods do |n|
+ date = Date.today + 2*n
+ date..(date+1)
+ end
+end
diff --git a/spec/factories/chouette_routes.rb b/spec/factories/chouette_routes.rb
index 4e20059fe..92a50b924 100644
--- a/spec/factories/chouette_routes.rb
+++ b/spec/factories/chouette_routes.rb
@@ -19,6 +19,7 @@ FactoryGirl.define do
after(:create) do |route, evaluator|
create_list(:stop_point, evaluator.stop_points_count, route: route)
route.reload
+ route.update_checksum!
end
factory :route_with_journey_patterns do
@@ -31,6 +32,13 @@ FactoryGirl.define do
end
end
+
+ trait :with_opposite do
+ after(:create) do |route|
+ opposite = create :route
+ route.opposite_route = opposite
+ end
+ end
end
factory :route_with_after_commit do
diff --git a/spec/factories/chouette_stop_areas.rb b/spec/factories/chouette_stop_areas.rb
index 8b64c227b..dab135ca6 100644
--- a/spec/factories/chouette_stop_areas.rb
+++ b/spec/factories/chouette_stop_areas.rb
@@ -3,10 +3,23 @@ FactoryGirl.define do
sequence(:objectid) { |n| "FR:#{n}:ZDE:#{n}:STIF" }
sequence(:name) { |n| "stop_area_#{n}" }
sequence(:registration_number) { |n| "test-#{n}" }
- area_type { Chouette::StopArea.area_type.values.sample }
+ area_type { Chouette::AreaType.commercial.sample }
latitude {10.0 * rand}
longitude {10.0 * rand}
+ kind "commercial"
association :stop_area_referential
+
+ transient do
+ referential nil
+ end
+
+ before(:create) do |stop_area, evaluator|
+ stop_area.stop_area_referential = evaluator.referential.stop_area_referential if evaluator.referential
+ end
+
+ trait :deactivated do
+ deleted_at { 1.hour.ago }
+ end
end
end
diff --git a/spec/factories/chouette_stop_points.rb b/spec/factories/chouette_stop_points.rb
index 14e08b1ac..97baae2fd 100644
--- a/spec/factories/chouette_stop_points.rb
+++ b/spec/factories/chouette_stop_points.rb
@@ -2,7 +2,7 @@ FactoryGirl.define do
factory :stop_point, :class => Chouette::StopPoint do
sequence(:objectid) { |n| "test:StopPoint:#{n}:loc" }
- association :stop_area, :factory => :stop_area
+ association :stop_area, :factory => :stop_area, area_type: "zdep"
end
end
diff --git a/spec/factories/chouette_time_table.rb b/spec/factories/chouette_time_table.rb
index a3ff63b2f..af48e1b42 100644
--- a/spec/factories/chouette_time_table.rb
+++ b/spec/factories/chouette_time_table.rb
@@ -11,20 +11,24 @@ FactoryGirl.define do
end
after(:create) do |time_table, evaluator|
-
- 0.upto(4) do |i|
- time_table.dates << create(:time_table_date, :time_table => time_table, :date => i.days.since.to_date, :in_out => true)
+ unless time_table.dates.any?
+ evaluator.dates_count.times do |i|
+ time_table.dates << create(:time_table_date, :time_table => time_table, :date => i.days.since.to_date, :in_out => true)
+ end
end
start_date = Date.today
end_date = start_date + 10
- 0.upto(4) do |i|
- time_table.periods << create(:time_table_period, :time_table => time_table, :period_start => start_date, :period_end => end_date)
- start_date = start_date + 20
- end_date = start_date + 10
+ unless time_table.periods.any?
+ evaluator.periods_count.times do |i|
+ time_table.periods << create(:time_table_period, :time_table => time_table, :period_start => start_date, :period_end => end_date)
+ start_date = start_date + 20
+ end_date = start_date + 10
+ end
end
time_table.save_shortcuts
+ time_table.update_checksum!
end
end
diff --git a/spec/factories/chouette_vehicle_journey.rb b/spec/factories/chouette_vehicle_journey.rb
index 5f64bd502..7d63a2e58 100644
--- a/spec/factories/chouette_vehicle_journey.rb
+++ b/spec/factories/chouette_vehicle_journey.rb
@@ -30,6 +30,7 @@ FactoryGirl.define do
:arrival_time => "2000-01-01 #{arrival_time} UTC",
:departure_time => "2000-01-01 #{departure_time} UTC")
end
+ vehicle_journey.update_checksum!
end
factory :vehicle_journey_odd do
diff --git a/spec/factories/chouette_vehicle_journey_at_stop.rb b/spec/factories/chouette_vehicle_journey_at_stop.rb
index 831e347d4..07a4ec557 100644
--- a/spec/factories/chouette_vehicle_journey_at_stop.rb
+++ b/spec/factories/chouette_vehicle_journey_at_stop.rb
@@ -1,9 +1,9 @@
FactoryGirl.define do
factory :vehicle_journey_at_stop, :class => Chouette::VehicleJourneyAtStop do
association :vehicle_journey, :factory => :vehicle_journey
+ association :stop_point, :factory => :stop_point
departure_day_offset { 0 }
departure_time { Time.now }
arrival_time { Time.now - 1.hour }
end
end
-
diff --git a/spec/factories/compliance_controls/generic_factories.rb b/spec/factories/compliance_controls/generic_factories.rb
index ddcf6c116..fd22b4c94 100644
--- a/spec/factories/compliance_controls/generic_factories.rb
+++ b/spec/factories/compliance_controls/generic_factories.rb
@@ -2,6 +2,8 @@ FactoryGirl.define do
factory :generic_attribute_control_min_max, class: 'GenericAttributeControl::MinMax' do
sequence(:name) { |n| "MinMax control #{n}" }
association :compliance_control_set
+ minimum 90
+ maximum 120
target "route#name"
end
diff --git a/spec/factories/compliance_controls/vehicle_journey_control_factories.rb b/spec/factories/compliance_controls/vehicle_journey_control_factories.rb
index b9da530fb..86a335aba 100644
--- a/spec/factories/compliance_controls/vehicle_journey_control_factories.rb
+++ b/spec/factories/compliance_controls/vehicle_journey_control_factories.rb
@@ -1,15 +1,19 @@
FactoryGirl.define do
factory :vehicle_journey_control_wating_time, class: 'VehicleJourneyControl::WaitingTime' do
+ maximum 10
association :compliance_control_set
end
factory :vehicle_journey_control_delta, class: 'VehicleJourneyControl::Delta' do
+ maximum 10
association :compliance_control_set
end
factory :vehicle_journey_control_speed, class: 'VehicleJourneyControl::Speed' do
association :compliance_control_set
+ minimum 200
+ maximum 300
end
factory :vehicle_journey_control_time_table, class: 'VehicleJourneyControl::TimeTable' do
diff --git a/spec/factories/custom_fields.rb b/spec/factories/custom_fields.rb
new file mode 100644
index 000000000..2f5fae555
--- /dev/null
+++ b/spec/factories/custom_fields.rb
@@ -0,0 +1,9 @@
+FactoryGirl.define do
+ factory :custom_field do
+ code "code"
+ resource_type "VehicleJourney"
+ sequence(:name){|n| "custom field ##{n}"}
+ field_type "list"
+ options( { "capacity" => "0" } )
+ end
+end
diff --git a/spec/factories/import_messages.rb b/spec/factories/import_messages.rb
index 75f80566c..5d936679a 100644
--- a/spec/factories/import_messages.rb
+++ b/spec/factories/import_messages.rb
@@ -3,5 +3,17 @@ FactoryGirl.define do
association :import
association :resource, factory: :import_resource
criticity :info
+
+ factory :corrupt_zip_file do
+ message_key 'corrupt_zip_file'
+ message_attributes({ source_filename: 'political file' })
+ criticity :error
+ end
+
+ factory :inconsistent_zip_file do
+ message_key 'inconsistent_zip_file'
+ message_attributes({ source_filename: 'robert talking', spurious_dirs: %w{dogs and cats}.join })
+ criticity :warning
+ end
end
end
diff --git a/spec/factories/line_referentials.rb b/spec/factories/line_referentials.rb
index e9e6dce5a..8c2aad646 100644
--- a/spec/factories/line_referentials.rb
+++ b/spec/factories/line_referentials.rb
@@ -2,5 +2,14 @@ FactoryGirl.define do
factory :line_referential do
sequence(:name) { |n| "Line Referential #{n}" }
objectid_format 'stif_codifligne'
+
+ transient do
+ member nil
+ end
+
+ after(:create) do |line_referential, evaluator|
+ line_referential.add_member evaluator.member if evaluator.member
+ line_referential.save
+ end
end
end
diff --git a/spec/factories/organisations.rb b/spec/factories/organisations.rb
index 239557a0e..2914c30cb 100644
--- a/spec/factories/organisations.rb
+++ b/spec/factories/organisations.rb
@@ -2,5 +2,8 @@ FactoryGirl.define do
factory :organisation do
sequence(:name) { |n| "Organisation #{n}" }
sequence(:code) { |n| "000#{n}" }
+ factory :org_with_lines do
+ sso_attributes { { 'functional_scope' => %w{STIF:CODIFLIGNE:Line:C00108 STIF:CODIFLIGNE:Line:C00109}.to_json } }
+ end
end
end
diff --git a/spec/factories/stop_area_referentials.rb b/spec/factories/stop_area_referentials.rb
index fcba996e4..bdac050b1 100644
--- a/spec/factories/stop_area_referentials.rb
+++ b/spec/factories/stop_area_referentials.rb
@@ -2,5 +2,14 @@ FactoryGirl.define do
factory :stop_area_referential, :class => StopAreaReferential do
sequence(:name) { |n| "StopArea Referential #{n}" }
objectid_format 'stif_reflex'
+
+ transient do
+ member nil
+ end
+
+ after(:create) do |stop_area_referential, evaluator|
+ stop_area_referential.add_member evaluator.member if evaluator.member
+ stop_area_referential.save
+ end
end
end
diff --git a/spec/factories/workbenches.rb b/spec/factories/workbenches.rb
index 0f26559d8..98fdd6ad9 100644
--- a/spec/factories/workbenches.rb
+++ b/spec/factories/workbenches.rb
@@ -7,5 +7,6 @@ FactoryGirl.define do
association :line_referential
association :stop_area_referential
association :output, factory: :referential_suite
+ association :workgroup
end
end
diff --git a/spec/factories/workgroups.rb b/spec/factories/workgroups.rb
new file mode 100644
index 000000000..792deddf8
--- /dev/null
+++ b/spec/factories/workgroups.rb
@@ -0,0 +1,7 @@
+FactoryGirl.define do
+ factory :workgroup do
+ sequence(:name) { |n| "Workgroup ##{n}" }
+ association :line_referential
+ association :stop_area_referential
+ end
+end
diff --git a/spec/features/access_points_spec.rb b/spec/features/access_points_spec.rb
index c16039d67..890906de7 100644
--- a/spec/features/access_points_spec.rb
+++ b/spec/features/access_points_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
describe "Access points", :type => :feature do
login_user
- let!(:stop_area) { create(:stop_area) }
+ let!(:stop_area) { create(:stop_area, stop_area_referential: referential.stop_area_referential) }
let!(:access_points) { Array.new(2) { create(:access_point, :stop_area => stop_area) } }
subject { access_points.first }
diff --git a/spec/features/calendars_permissions_spec.rb b/spec/features/calendars_permissions_spec.rb
index 9b47ab2bb..4857592d5 100644
--- a/spec/features/calendars_permissions_spec.rb
+++ b/spec/features/calendars_permissions_spec.rb
@@ -2,6 +2,7 @@ RSpec.describe 'Calendars', type: :feature do
login_user
let(:calendar) { create :calendar, organisation_id: 1 }
+ let(:workgroup) { calendar.workgroup }
describe 'permissions' do
before do
@@ -13,7 +14,7 @@ RSpec.describe 'Calendars', type: :feature do
end
context 'on show view' do
- let( :path ){ calendar_path(calendar) }
+ let( :path ){ workgroup_calendar_path(workgroup, calendar) }
context 'if present → ' do
let( :permission ){ true }
@@ -33,7 +34,7 @@ RSpec.describe 'Calendars', type: :feature do
end
context 'on edit view' do
- let( :path ){ edit_calendar_path(calendar) }
+ let( :path ){ edit_workgroup_calendar_path(workgroup, calendar) }
context 'if present → ' do
let( :permission ){ true }
@@ -51,7 +52,7 @@ RSpec.describe 'Calendars', type: :feature do
end
context 'on index view' do
- let( :path ){ calendars_path }
+ let( :path ){ workgroup_calendars_path(workgroup) }
context 'if present → ' do
let( :permission ){ true }
diff --git a/spec/features/companies_spec.rb b/spec/features/companies_spec.rb
index 1b9dae56f..4e778b3a0 100644
--- a/spec/features/companies_spec.rb
+++ b/spec/features/companies_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
describe "Companies", :type => :feature do
login_user
- let(:line_referential) { create :line_referential }
+ let(:line_referential) { create :line_referential, member: @user.organisation }
let!(:companies) { Array.new(2) { create :company, line_referential: line_referential } }
subject { companies.first }
diff --git a/spec/features/compliance_check_sets_spec.rb b/spec/features/compliance_check_sets_spec.rb
index 7ba64b6b8..5cace04d4 100644
--- a/spec/features/compliance_check_sets_spec.rb
+++ b/spec/features/compliance_check_sets_spec.rb
@@ -29,10 +29,10 @@ RSpec.describe "ComplianceCheckSets", type: :feature do
it 'we can see the expected content' do
# Breadcrumbs
- expect_breadcrumb_links "Accueil", "Gestion de l'offre", "Liste des jeux de contrôles"
+ expect_breadcrumb_links "Accueil", "Gestion de l'offre", "Liste des rapports de contrôles"
# Headline
- expect( page ).to have_content("Jeu de contrôles exécutés #{compliance_check_set.name}")
+ expect( page ).to have_content(I18n.t("compliance_check_sets.executed.title", name: compliance_check_set.name))
# Information Definition List
expect( page.first('.dl-term') ).to have_content("Nom")
@@ -49,10 +49,10 @@ RSpec.describe "ComplianceCheckSets", type: :feature do
# Direct Children
within(:xpath, xpath_for_div_of_block) do
direct_checks.each do | direct_check |
- expect( page ).to have_content( direct_check.code )
- expect( page ).to have_content( direct_check.name )
- expect( page ).to have_content( direct_check.criticity )
- expect( page ).to have_content( direct_check.comment )
+ expect( page ).to have_content( direct_check.code )
+ expect( page ).to have_content( direct_check.name )
+ expect( page ).to have_content( direct_check.criticity )
+ expect( page ).to have_content( direct_check.comment )
end
end
@@ -60,10 +60,10 @@ RSpec.describe "ComplianceCheckSets", type: :feature do
compliance_check_set.compliance_check_blocks.each do | block |
within(:xpath, xpath_for_div_of_block(block)) do
block.compliance_checks.each do | check |
- expect( page ).to have_content( check.code )
- expect( page ).to have_content( check.name )
- expect( page ).to have_content( check.criticity )
- expect( page ).to have_content( check.comment )
+ expect( page ).to have_content( check.code )
+ expect( page ).to have_content( check.name )
+ expect( page ).to have_content( check.criticity )
+ expect( page ).to have_content( check.comment )
end
end
end
@@ -86,7 +86,7 @@ RSpec.describe "ComplianceCheckSets", type: :feature do
all_checks.each do | check |
expect( page ).to have_content(check.code)
end
-
+
end
end
diff --git a/spec/features/group_of_lines_permissions_spec.rb b/spec/features/group_of_lines_permissions_spec.rb
index 5c03481ec..33d78c0dd 100644
--- a/spec/features/group_of_lines_permissions_spec.rb
+++ b/spec/features/group_of_lines_permissions_spec.rb
@@ -22,7 +22,7 @@ describe "Group of lines", :type => :feature do
context 'on show view' do
let( :path ){ line_referential_group_of_line_path(line_referential, group_of_line, delete: true) }
- context 'if permissions present → ' do
+ context 'if permissions present → ' do
let( :permission ){ true }
it 'shows the appropriate buttons' do
@@ -30,7 +30,7 @@ describe "Group of lines", :type => :feature do
expect( page ).to have_link('Supprimer', href: expected_url)
end
end
- context 'if permissions absent → ' do
+ context 'if permissions absent → ' do
let( :permission ){ false }
it 'shows the appropriate buttons' do
diff --git a/spec/features/group_of_lines_spec.rb b/spec/features/group_of_lines_spec.rb
index 59101ccd5..8b88e6e9e 100644
--- a/spec/features/group_of_lines_spec.rb
+++ b/spec/features/group_of_lines_spec.rb
@@ -10,7 +10,7 @@ describe "Group of lines", :type => :feature do
let!(:group_of_lines) { Array.new(2) { create(:group_of_line, line_referential: line_referential) } }
subject { group_of_lines.first }
- let(:line_referential) { create :line_referential }
+ let(:line_referential) { create :line_referential, member: @user.organisation }
before :each do
subject.lines << line
diff --git a/spec/features/lines_spec.rb b/spec/features/lines_spec.rb
index 2a442bd2f..f176e34fe 100644
--- a/spec/features/lines_spec.rb
+++ b/spec/features/lines_spec.rb
@@ -1,7 +1,8 @@
+# coding: utf-8
describe "Lines", type: :feature do
login_user
- let(:line_referential) { create :line_referential }
+ let(:line_referential) { create :line_referential, member: @user.organisation }
let!(:network) { create(:network) }
let!(:company) { create(:company) }
let!(:lines) { Array.new(2) { create :line_with_stop_areas, network: network, company: company, line_referential: line_referential } }
@@ -60,22 +61,22 @@ describe "Lines", type: :feature do
# it "creates line and return to show" do
# visit line_referential_lines_path(line_referential)
# click_link "Ajouter une ligne"
- # fill_in "line_name", :with => "Line 1"
- # fill_in "Numéro d'enregistrement", :with => "1"
- # fill_in "Identifiant Neptune", :with => "chouette:test:Line:999"
+ # fill_in "line_name", with: "Line 1"
+ # fill_in "Numéro d'enregistrement", with: "1"
+ # fill_in "Identifiant Neptune", with: "chouette:test:Line:999"
# click_button("Créer ligne")
# expect(page).to have_content("Line 1")
# end
# end
# Fixme #1780
- # describe "new with group of line", :js => true do
+ # describe "new with group of line", truncation: true do
# it "creates line and return to show" do
# visit new_line_referential_line_path(line_referential)
- # fill_in "line_name", :with => "Line 1"
- # fill_in "Numéro d'enregistrement", :with => "1"
- # fill_in "Identifiant Neptune", :with => "test:Line:999"
- # fill_in_token_input('line_group_of_line_tokens', :with => "#{group_of_line.name}")
+ # fill_in "line_name", with: "Line 1"
+ # fill_in "Numéro d'enregistrement", with: "1"
+ # fill_in "Identifiant Neptune", with: "test:Line:999"
+ # fill_in_token_input('line_group_of_line_tokens', with: "#{group_of_line.name}")
# find_button("Créer ligne").trigger("click")
# expect(page).to have_text("Line 1")
# expect(page).to have_text("#{group_of_line.name}")
@@ -87,8 +88,8 @@ describe "Lines", type: :feature do
# it "edit line" do
# visit line_referential_line_path(line_referential, subject)
# click_link "Editer cette ligne"
- # fill_in "line_name", :with => "Line Modified"
- # fill_in "Numéro d'enregistrement", :with => "test-1"
+ # fill_in "line_name", with: "Line Modified"
+ # fill_in "Numéro d'enregistrement", with: "test-1"
# click_button("Editer ligne")
# expect(page).to have_content("Line Modified")
# end
diff --git a/spec/features/networks_spec.rb b/spec/features/networks_spec.rb
index 75070e7fa..8586b2a16 100644
--- a/spec/features/networks_spec.rb
+++ b/spec/features/networks_spec.rb
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
require 'spec_helper'
-describe "Networks", :type => :feature do
+describe "Networks", type: :feature do
login_user
- let(:line_referential) { create :line_referential }
+ let(:line_referential) { create :line_referential, member: @user.organisation }
let!(:networks) { Array.new(2) { create(:network, line_referential: line_referential) } }
subject { networks.first }
@@ -54,9 +54,9 @@ describe "Networks", :type => :feature do
# # allow(subject).to receive(:stop_areas).and_return(Array.new(2) { create(:stop_area) })
# visit line_referential_networks_path(line_referential)
# click_link "Ajouter un réseau"
- # fill_in "network_name", :with => "Network 1"
- # fill_in "Numéro d'enregistrement", :with => "test-1"
- # fill_in "Identifiant Neptune", :with => "chouette:test:GroupOfLine:1"
+ # fill_in "network_name", with: "Network 1"
+ # fill_in "Numéro d'enregistrement", with: "test-1"
+ # fill_in "Identifiant Neptune", with: "chouette:test:GroupOfLine:1"
# click_button("Créer réseau")
# expect(page).to have_content("Network 1")
# end
@@ -67,14 +67,14 @@ describe "Networks", :type => :feature do
# # allow(subject).to receive(:stop_areas).and_return(Array.new(2) { create(:stop_area) })
# visit line_referential_network_path(line_referential, subject)
# click_link "Editer ce réseau"
- # fill_in "network_name", :with => "Network Modified"
- # fill_in "Numéro d'enregistrement", :with => "test-1"
+ # fill_in "network_name", with: "Network Modified"
+ # fill_in "Numéro d'enregistrement", with: "test-1"
# click_button("Editer réseau")
# expect(page).to have_content("Network Modified")
# end
# end
- # describe "delete", :js => true do
+ # describe "delete", truncation: true do
# it "delete network and return to the list" do
# subject.stub(:stop_areas).and_return(Array.new(2) { create(:stop_area) })
# visit line_referential_network_path(line_referential, subject)
diff --git a/spec/features/purchase_windows_permission_spec.rb b/spec/features/purchase_windows_permission_spec.rb
new file mode 100644
index 000000000..9f155a1e8
--- /dev/null
+++ b/spec/features/purchase_windows_permission_spec.rb
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+require 'spec_helper'
+
+describe "PurchaseWindows", :type => :feature do
+ login_user
+
+ before do
+ @user.organisation.update features: %w{purchase_windows}
+ end
+
+ let(:purchase_window) { create :purchase_window, referential: first_referential}
+
+ describe 'permissions' do
+ before do
+ allow_any_instance_of(PurchaseWindowPolicy).to receive(:create?).and_return permission
+ allow_any_instance_of(PurchaseWindowPolicy).to receive(:destroy?).and_return permission
+ allow_any_instance_of(PurchaseWindowPolicy).to receive(:update?).and_return permission
+ visit path
+ end
+
+ context 'on show view' do
+ let( :path ){ referential_purchase_window_path(first_referential, purchase_window) }
+
+ context 'if present → ' do
+ let( :permission ){ true }
+ it 'view shows the corresponding buttons' do
+ expect(page).to have_content(I18n.t('purchase_windows.actions.edit'))
+ expect(page).to have_content(I18n.t('purchase_windows.actions.destroy'))
+ end
+ end
+
+ context 'if absent → ' do
+ let( :permission ){ false }
+ it 'view does not show the corresponding buttons' do
+ expect(page).not_to have_content(I18n.t('purchase_windows.actions.edit'))
+ expect(page).not_to have_content(I18n.t('purchase_windows.actions.destroy'))
+ end
+ end
+ end
+
+ context 'on index view' do
+ let( :path ){ referential_purchase_windows_path(first_referential) }
+
+ context 'if present → ' do
+ let( :permission ){ true }
+ it 'index shows an edit button' do
+ expect(page).to have_content(I18n.t('purchase_windows.actions.new'))
+ end
+ end
+
+ context 'if absent → ' do
+ let( :permission ){ false }
+ it 'index does not show any edit button' do
+ expect(page).not_to have_content(I18n.t('purchase_windows.actions.new'))
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/purchase_windows_spec.rb b/spec/features/purchase_windows_spec.rb
new file mode 100644
index 000000000..f797594b7
--- /dev/null
+++ b/spec/features/purchase_windows_spec.rb
@@ -0,0 +1,69 @@
+describe "PurchaseWindows", type: :feature do
+ login_user
+
+ before do
+ @user.organisation.update features: %w{purchase_windows}
+ end
+
+ describe "#index" do
+ with_permissions('purchase_windows.create') do
+ it "allows users to create new purchase windows" do
+ name = 'Test purchase window create'
+
+ visit(referential_purchase_windows_path(first_referential.id))
+
+ click_link(I18n.t('purchase_windows.actions.new'))
+
+ fill_in('purchase_window[name]', with: name)
+ # select('#DD2DAA', from: 'purchase_window[color]')
+
+ click_link(I18n.t('simple_form.labels.purchase_window.add_a_date_range'))
+ click_button(I18n.t('actions.submit'))
+
+ expect(page).to have_content(name)
+ end
+ end
+
+ with_permissions('purchase_windows.update') do
+ it "allows users to update purchase windows" do
+ actual_name = 'Existing purchase window'
+ expected_name = 'Updated purchase window'
+ create(
+ :purchase_window,
+ referential: first_referential,
+ name: actual_name
+ )
+
+ visit(referential_purchase_windows_path(first_referential.id))
+
+ click_link(actual_name)
+
+ click_link(I18n.t('purchase_windows.actions.edit'))
+ fill_in('purchase_window[name]', with: expected_name)
+
+ click_button(I18n.t('actions.submit'))
+
+ expect(page).to have_content(expected_name)
+ end
+ end
+
+ with_permissions('purchase_windows.destroy') do
+ it "allows users to destroy purchase windows" do
+ name = 'Existing purchase window'
+ create(
+ :purchase_window,
+ referential: first_referential,
+ name: name
+ )
+
+ visit(referential_purchase_windows_path(first_referential.id))
+
+ click_link(name)
+
+ click_link(I18n.t('purchase_windows.actions.destroy'))
+
+ expect(page).to_not have_content(name)
+ end
+ end
+ end
+end
diff --git a/spec/features/referential_stop_areas_spec.rb b/spec/features/referential_stop_areas_spec.rb
index 0dc7951a7..5e70857e7 100644
--- a/spec/features/referential_stop_areas_spec.rb
+++ b/spec/features/referential_stop_areas_spec.rb
@@ -5,7 +5,7 @@ describe 'ReferentialStopAreas', type: :feature do
login_user
let(:referential) { Referential.first }
- let(:stop_area_referential) { create :stop_area_referential }
+ let(:stop_area_referential) { referential.stop_area_referential }
let!(:stop_areas) { Array.new(2) { create :stop_area, stop_area_referential: stop_area_referential } }
describe 'index' do
diff --git a/spec/features/safe_submit_spec.rb b/spec/features/safe_submit_spec.rb
new file mode 100644
index 000000000..9968d4310
--- /dev/null
+++ b/spec/features/safe_submit_spec.rb
@@ -0,0 +1,9 @@
+RSpec.describe 'SafeSubmit', type: :feature do
+ login_user
+
+ let( :path ){ new_api_key_path() }
+ it 'view shows the corresponding buttons' do
+ visit path
+ expect(page).to have_css('input[type=submit][data-disable-with]')
+ end
+end
diff --git a/spec/features/stop_areas_spec.rb b/spec/features/stop_areas_spec.rb
index 6afb22bc6..668eb2fa3 100644
--- a/spec/features/stop_areas_spec.rb
+++ b/spec/features/stop_areas_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
describe "StopAreas", :type => :feature do
login_user
- let(:stop_area_referential) { create :stop_area_referential }
+ let(:stop_area_referential) { create :stop_area_referential, member: @user.organisation }
let!(:stop_areas) { Array.new(2) { create :stop_area, stop_area_referential: stop_area_referential } }
subject { stop_areas.first }
diff --git a/spec/features/users/user_delete_spec.rb b/spec/features/users/user_delete_spec.rb
index 48f4e35d1..8b2ffcbe5 100644
--- a/spec/features/users/user_delete_spec.rb
+++ b/spec/features/users/user_delete_spec.rb
@@ -7,7 +7,7 @@ Warden.test_mode!
# As a user
# I want to delete my user profile
# So I can close my account
-feature 'User delete', :devise, :js do
+feature 'User delete', :devise, :truncation do
after(:each) do
Warden.test_reset!
diff --git a/spec/features/workbenches/workbenches_show_spec.rb b/spec/features/workbenches/workbenches_show_spec.rb
index f1151a67b..7be813b94 100644
--- a/spec/features/workbenches/workbenches_show_spec.rb
+++ b/spec/features/workbenches/workbenches_show_spec.rb
@@ -22,11 +22,69 @@ RSpec.describe 'Workbenches', type: :feature do
end
end
+ it 'lists referentials in the current workgroup' do
+ other_workbench = create(
+ :workbench,
+ line_referential: line_ref,
+ workgroup: workbench.workgroup
+ )
+ other_referential = create(
+ :workbench_referential,
+ workbench: other_workbench,
+ organisation: other_workbench.organisation,
+ metadatas: [
+ create(
+ :referential_metadata,
+ lines: [create(:line, line_referential: line_ref)]
+ )
+ ]
+ )
+
+ hidden_referential = create(
+ :workbench_referential,
+ workbench: create(
+ :workbench,
+ line_referential: line_ref
+ ),
+ metadatas: [
+ create(
+ :referential_metadata,
+ lines: [create(:line, line_referential: line_ref)]
+ )
+ ]
+ )
+
+ visit workbench_path(workbench)
+
+ expect(page).to have_content(referential.name),
+ "Couldn't find `referential`: `#{referential.inspect}`"
+ expect(page).to have_content(other_referential.name),
+ "Couldn't find `other_referential`: `#{other_referential.inspect}`"
+ expect(page).to_not have_content(hidden_referential.name),
+ "Couldn't find `hidden_referential`: `#{hidden_referential.inspect}`"
+ end
+
context 'filtering' do
let!(:another_organisation) { create :organisation }
let(:another_line) { create :line, line_referential: line_ref }
let(:another_ref_metadata) { create(:referential_metadata, lines: [another_line]) }
- let!(:other_referential) { create :workbench_referential, workbench: workbench, metadatas: [another_ref_metadata] }
+ let(:other_workbench) do
+ create(
+ :workbench,
+ line_referential: line_ref,
+ organisation: another_organisation,
+ workgroup: workbench.workgroup
+ )
+ end
+ let!(:other_referential) do
+ create(
+ :workbench_referential,
+ workbench: other_workbench,
+ metadatas: [another_ref_metadata],
+ organisation: other_workbench.organisation
+ )
+ end
+
before(:each) do
visit workbench_path(workbench)
@@ -64,6 +122,18 @@ RSpec.describe 'Workbenches', type: :feature do
click_button I18n.t('actions.filter')
expect(find(box)).to be_checked
end
+
+ it 'only lists organisations in the current workgroup' do
+ unaffiliated_workbench = workbench.dup
+ unaffiliated_workbench.update(organisation: create(:organisation))
+
+ expect(page).to have_selector(
+ "#q_organisation_name_eq_any_#{@user.organisation.name.parameterize.underscore}"
+ )
+ expect(page).to_not have_selector(
+ "#q_organisation_name_eq_any_#{unaffiliated_workbench.name.parameterize.underscore}"
+ )
+ end
end
context 'filter by status' do
diff --git a/spec/fixtures/OFFRE_WITH_EXTRA.zip b/spec/fixtures/OFFRE_WITH_EXTRA.zip
deleted file mode 100644
index 97ea3f513..000000000
--- a/spec/fixtures/OFFRE_WITH_EXTRA.zip
+++ /dev/null
Binary files differ
diff --git a/spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/SPURIOUS/spurious.xml b/spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/SPURIOUS/spurious.xml
new file mode 100644
index 000000000..a6204cd5c
--- /dev/null
+++ b/spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/SPURIOUS/spurious.xml
@@ -0,0 +1 @@
+spurious
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/calendriers.xml b/spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/calendriers.xml
index bfbd0aea1..bfbd0aea1 100644
--- a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/calendriers.xml
+++ b/spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/calendriers.xml
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/commun.xml b/spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/commun.xml
index 266c8a598..266c8a598 100644
--- a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/commun.xml
+++ b/spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/commun.xml
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml b/spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/offre_C00108_9.xml
index 832793036..832793036 100644
--- a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml
+++ b/spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/offre_C00108_9.xml
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml b/spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/offre_C00109_10.xml
index 9dff0d850..9dff0d850 100644
--- a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml
+++ b/spec/fixtures/extra_file_nok/OFFRE_WITH_EXTRA/offre_C00109_10.xml
diff --git a/spec/fixtures/foreign_and_spurious/FOREIGN_LINE/calendriers.xml b/spec/fixtures/foreign_and_spurious/FOREIGN_LINE/calendriers.xml
new file mode 100644
index 000000000..bfbd0aea1
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/FOREIGN_LINE/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/foreign_and_spurious/FOREIGN_LINE/commun.xml b/spec/fixtures/foreign_and_spurious/FOREIGN_LINE/commun.xml
new file mode 100644
index 000000000..266c8a598
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/FOREIGN_LINE/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/foreign_and_spurious/FOREIGN_LINE/offre_C00107_10.xml b/spec/fixtures/foreign_and_spurious/FOREIGN_LINE/offre_C00107_10.xml
new file mode 100644
index 000000000..9dff0d850
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/FOREIGN_LINE/offre_C00107_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/foreign_and_spurious/FOREIGN_LINE/offre_C00108_9.xml b/spec/fixtures/foreign_and_spurious/FOREIGN_LINE/offre_C00108_9.xml
new file mode 100644
index 000000000..832793036
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/FOREIGN_LINE/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/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/calendriers.xml b/spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/calendriers.xml
new file mode 100644
index 000000000..bfbd0aea1
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/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/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/commun.xml b/spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/commun.xml
new file mode 100644
index 000000000..266c8a598
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/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/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml b/spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml
new file mode 100644
index 000000000..832793036
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/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/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml b/spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml
new file mode 100644
index 000000000..9dff0d850
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/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/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/calendriers.xml
index 1043e0cde..1043e0cde 100644
--- a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/calendriers.xml
+++ b/spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/calendriers.xml
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/commun.xml b/spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/commun.xml
index f59f8ac2d..f59f8ac2d 100644
--- a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/commun.xml
+++ b/spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/commun.xml
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml b/spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml
index 9eefeeb43..9eefeeb43 100644
--- a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml
+++ b/spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml
diff --git a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml b/spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml
index d260ef17e..d260ef17e 100644
--- a/spec/fixtures/source_OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml
+++ b/spec/fixtures/foreign_and_spurious/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml
diff --git a/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/SPURIOUS/spurious.xml b/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/SPURIOUS/spurious.xml
new file mode 100644
index 000000000..a6204cd5c
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/SPURIOUS/spurious.xml
@@ -0,0 +1 @@
+spurious
diff --git a/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/calendriers.xml b/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/calendriers.xml
new file mode 100644
index 000000000..bfbd0aea1
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/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/foreign_and_spurious/OFFRE_WITH_EXTRA/commun.xml b/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/commun.xml
new file mode 100644
index 000000000..266c8a598
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/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/foreign_and_spurious/OFFRE_WITH_EXTRA/offre_C00108_9.xml b/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/offre_C00108_9.xml
new file mode 100644
index 000000000..832793036
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/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/foreign_and_spurious/OFFRE_WITH_EXTRA/offre_C00109_10.xml b/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/offre_C00109_10.xml
new file mode 100644
index 000000000..9dff0d850
--- /dev/null
+++ b/spec/fixtures/foreign_and_spurious/OFFRE_WITH_EXTRA/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/meta_zip/one/alpha b/spec/fixtures/meta_zip/one/alpha
new file mode 100644
index 000000000..4a5800705
--- /dev/null
+++ b/spec/fixtures/meta_zip/one/alpha
@@ -0,0 +1 @@
+alpha
diff --git a/spec/fixtures/meta_zip/two/beta b/spec/fixtures/meta_zip/two/beta
new file mode 100644
index 000000000..65b2df87f
--- /dev/null
+++ b/spec/fixtures/meta_zip/two/beta
@@ -0,0 +1 @@
+beta
diff --git a/spec/fixtures/meta_zip/two/subdir/gamma b/spec/fixtures/meta_zip/two/subdir/gamma
new file mode 100644
index 000000000..af17f6cc8
--- /dev/null
+++ b/spec/fixtures/meta_zip/two/subdir/gamma
@@ -0,0 +1 @@
+gamma
diff --git a/spec/fixtures/nozip.zip b/spec/fixtures/nozip.zip
index 505bd213a..e69de29bb 100644
--- a/spec/fixtures/nozip.zip
+++ b/spec/fixtures/nozip.zip
@@ -1 +0,0 @@
-no zip file
diff --git a/spec/fixtures/regression-5281.zip b/spec/fixtures/regression-5281.zip
new file mode 100644
index 000000000..2ff4ec66d
--- /dev/null
+++ b/spec/fixtures/regression-5281.zip
Binary files differ
diff --git a/spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/calendriers.xml b/spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/calendriers.xml
new file mode 100644
index 000000000..bc2b63527
--- /dev/null
+++ b/spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/calendriers.xml
@@ -0,0 +1,145 @@
+<?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:core="http://www.govtalk.gov.uk/core" xmlns:gml="http://www.opengis.net/gml/3.2" 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-06-25T00: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>Semaine vacances</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:4:LOC" version="any" >
+ <netex:Name>WE vacances</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:5:LOC" version="any" >
+ <netex:Name>Service spécial</netex:Name>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:6:LOC" version="any" >
+ <netex:Name>Restriction</netex:Name>
+ </netex:DayType>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:1:LOC" 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="CITYWAY:DayTypeAssignment:2:LOC" 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="CITYWAY:DayTypeAssignment:3:LOC" version="any" order="0" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:3:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:4:LOC" version="any" order="0" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:3:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:2:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:5:LOC" version="any" order="0" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:2:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:3:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:6:LOC" version="any" order="0" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:2:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:4:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:7:LOC" version="any" order="0" >
+ <netex:Date>2017-07-05</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:5:LOC" version="any"/>
+ <netex:isAvailable>true</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:8:LOC" version="any" order="0" >
+ <netex:Date>2017-08-14</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:6:LOC" version="any"/>
+ <netex:isAvailable>false</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:9:LOC" version="any" order="0" >
+ <netex:Date>2017-08-15</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:6:LOC" version="any"/>
+ <netex:isAvailable>false</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:10:LOC" version="any" order="0" >
+ <netex:Date>2017-08-16</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:6:LOC" version="any"/>
+ <netex:isAvailable>false</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:OperatingPeriod id="CITYWAY:OperatingPeriod:1:LOC" version="any" >
+ <netex:FromDate>2017-06-25T00:00:00</netex:FromDate>
+ <netex:ToDate>2017-07-01T00:00:00</netex:ToDate>
+ </netex:OperatingPeriod>
+ <netex:OperatingPeriod id="CITYWAY:OperatingPeriod:2:LOC" version="any" >
+ <netex:FromDate>2017-07-10T00:00:00</netex:FromDate>
+ <netex:ToDate>2017-08-31T00:00:00</netex:ToDate>
+ </netex:OperatingPeriod>
+ <netex:OperatingPeriod id="CITYWAY:OperatingPeriod:3:LOC" version="any" >
+ <netex:FromDate>2017-09-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/regression-5281/OFFRE_SNTYO_1_20170820120001/commun.xml b/spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/commun.xml
new file mode 100644
index 000000000..b6337b65f
--- /dev/null
+++ b/spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/commun.xml
@@ -0,0 +1,30 @@
+<?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>note numéro 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>note numéro 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>note numéro 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/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00166_05.xml b/spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00166_05.xml
new file mode 100644
index 000000000..fac9a3187
--- /dev/null
+++ b/spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00166_05.xml
@@ -0,0 +1,459 @@
+<?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 5</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>de rambouillet vers orphin</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00166">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>de Orphin vers rambouillet</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00166">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>vers orphin</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>vers rambouillet</netex:Name>
+ </netex:Direction>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC" version="any">
+ <netex:Name>vers orphin</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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-4:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-5:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5: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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-4:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-5:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5: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>05011</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC" version="any">
+ <netex:FrontText>Mission 2</netex:FrontText>
+ <netex:PublicCode>05021</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:1-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-5: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:78517:ZDE:50111663: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:78464:ZDE:50016099:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78464:ZDE:50016096:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78470:ZDE:50016107:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78470:ZDE:50016111: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:78470:ZDE:50016114: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:78470:ZDE:50016108:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78464:ZDE:50016097:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78464:ZDE:50016100:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78517:ZDE:50111663: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:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:2:LOC" version="any">
+ <netex:Name>ITL 2</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5: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 s note 1 </netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:1:LOC" 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:013">
+ 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>08:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:02:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:10:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:11:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:15:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:16:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:19:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:22:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-2:LOC" version="any">
+ <netex:Name>Course 1 we not 2 </netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:2:LOC" 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:2:LOC"> version="any"</netex:DayTypeRef>
+ </netex:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>09:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:02:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>09:10:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:11:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>09:15:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:16:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>09:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:19:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>09:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:22:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-3:LOC" version="any">
+ <netex:Name>Course 1 exceptionnel note 1 et 2 </netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:3:LOC" version="any" order="0">
+ <netex:NoticeRef ref="CITYWAY:Notice:1:LOC">
+ version="any"</netex:NoticeRef>
+ </netex:NoticeAssignment>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:4:LOC" 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:3:LOC"> version="any"</netex:DayTypeRef>
+ <netex:DayTypeRef ref="CITYWAY:DayType:5:LOC"> version="any"</netex:DayTypeRef>
+ </netex:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>10:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:02:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>10:10:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:11:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>10:15:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:16:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>10:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:19:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>10:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:22:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-4:LOC" version="any">
+ <netex:Name>Course 1 semaine en vacances et exclusions note 3 </netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:5:LOC" version="any" order="0">
+ <netex:NoticeRef ref="CITYWAY:Notice:1:LOC">
+ version="any"</netex:NoticeRef>
+ </netex:NoticeAssignment>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:6:LOC" version="any" order="0">
+ <netex:NoticeRef ref="CITYWAY:Notice:3:LOC">
+ version="any"</netex:NoticeRef>
+ </netex:NoticeAssignment>
+ </netex:noticeAssignments>
+ <netex:dayTypes>
+ <netex:DayTypeRef ref="CITYWAY:DayType:3:LOC"> version="any"</netex:DayTypeRef>
+ <netex:DayTypeRef ref="CITYWAY:DayType:6:LOC"> version="any"</netex:DayTypeRef>
+ </netex:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>11:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>11:02:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>11:10:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>11:11:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>11:15:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>11:16:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>11:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>11:19:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>11:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>11:22:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-1:LOC" version="any">
+ <netex:Name>Course 1 semaine note 3 </netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:7:LOC" version="any" order="0">
+ <netex:NoticeRef ref="CITYWAY:Notice:3: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:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>13:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>13:02:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>13:10:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>13:11:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>13:15:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>13:16:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>13:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>13:19:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>13:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>13:22: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/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00168_08.xml b/spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00168_08.xml
new file mode 100644
index 000000000..77116b8b4
--- /dev/null
+++ b/spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00168_08.xml
@@ -0,0 +1,667 @@
+<?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 8</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:C00168">version="any"</netex:LineRef>
+ <netex:DirectionType>outbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:1:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:3: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:C00168">version="any"</netex:LineRef>
+ <netex:DirectionType>outbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:2:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:4:LOC" version="any"/>
+ </netex:Route>
+ <netex:Route id="CITYWAY:Route:3:LOC" version="any">
+ <netex:Name>route 3</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00168">version="any"</netex:LineRef>
+ <netex:DirectionType>inbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:3:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ </netex:Route>
+ <netex:Route id="CITYWAY:Route:4:LOC" version="any">
+ <netex:Name>route 4</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00168">version="any"</netex:LineRef>
+ <netex:DirectionType>inbound</netex:DirectionType>
+ <netex:DirectionRef ref="CITYWAY:Direction:4:LOC" version="any"/>
+ <netex:InverseRouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ </netex:Route>
+ <netex:Direction id="CITYWAY:Direction:1:LOC" version="any">
+ <netex:Name>rambouillet vers auffargis</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>rambouillet vers les essarts</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:3:LOC" version="any">
+ <netex:Name>auffargis vers rambouillet</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:4:LOC" version="any">
+ <netex:Name>les essarts vers rambouillet</netex:Name>
+ </netex:Direction>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC" version="any">
+ <netex:Name>de rambouillet vers auffargis </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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-4:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-5:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-6:LOC" order="6"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-7:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-7: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>de rambouillet aux essarts via le perray</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-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:2-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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-1-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-1-4:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-1-5:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-1-6:LOC" order="6"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-8:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-1-7:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-9:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-1-8:LOC" order="8"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-10: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:3:LOC" version="any">
+ <netex:Name>auffargis SNCF rambouillet sncf</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:3:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:3:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:3-2-1:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:3-2-2:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:3-2-3:LOC" order="6"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:3-2-4:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:3-2-5:LOC" order="8"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-8:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:3-2-6:LOC" order="9"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-9:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:3-2-7:LOC" order="10"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-10: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:4:LOC" version="any">
+ <netex:Name>les essarts SNCF rambouillet sncf</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:4:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:3:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:4-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:4-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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:4-2-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:4-2-4:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:4-2-5:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:4-2-6:LOC" order="6"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-8:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:4-2-7:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-9:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:4-2-8:LOC" order="8"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-10: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>Auffargis route du perray</netex:FrontText>
+ <netex:PublicCode>1234</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC" version="any">
+ <netex:FrontText>les essarts sncf</netex:FrontText>
+ <netex:PublicCode>2345</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:3:LOC" version="any">
+ <netex:FrontText>rambouillet</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:1-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-7:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-8:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-9:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-10:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-7:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-8:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-9:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-10: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:78269:ZDE:50111665: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:78517:ZDE:50076501:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78517:ZDE:50111663:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78517:ZDE:50016341:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78486:ZDE:50015940:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-6:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78030:ZDE:50015569:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-7:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-7:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78030:ZDE:50015577:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-8:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-8:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78486:ZDE:50015930:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-9:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-9:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78486:ZDE:50015937:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-10:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-10:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78220:ZDE:50076444: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:78220:ZDE:50076444: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:78486:ZDE:50015936:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78486:ZDE:50015931:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78030:ZDE:50015576:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78030:ZDE:50015568:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-6:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78486:ZDE:50015940:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-7:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78517:ZDE:50016340:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-8:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-8:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78517:ZDE:50111663:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-9:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-9:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78517:ZDE:50016206:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-10:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-10:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78269:ZDE:50111664: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-3:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:2:LOC" version="any">
+ <netex:Name>ITL 2</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-8: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 direction auffargis</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:1:LOC" 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:013">
+ 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>06:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:04:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:06:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:06:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:08:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:08:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:18:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:24:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:24:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-1:LOC" version="any">
+ <netex:Name>Course 1 directionles essarts</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:2:LOC" 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:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>07:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:04:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:07:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:07:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:08:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:08:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:18:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:23:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:23:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:29:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:3-1:LOC" version="any">
+ <netex:Name>Course 1 direction rambouillet</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:3:LOC" 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:3:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>09:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>09:04:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>09:06:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:06:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>09:16:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:16:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>09:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:18:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>09:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>09:24:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>09:24:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:4-1:LOC" version="any">
+ <netex:Name>Course 1 les essarts rambouillet</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:4:LOC" 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:4:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>10:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>10:04:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>10:07:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:07:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>10:08:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:08:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>10:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:18:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>10:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>10:23:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:23:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>10:29:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:29: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/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00171_11.xml b/spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00171_11.xml
new file mode 100644
index 000000000..9d5309d60
--- /dev/null
+++ b/spec/fixtures/regression-5281/OFFRE_SNTYO_1_20170820120001/offre_C00171_11.xml
@@ -0,0 +1,473 @@
+<?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 11</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:C00171">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:C00171">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>Rambouillet Auneau </netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>Auneau Rambouillet</netex:Name>
+ </netex:Direction>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC" version="any">
+ <netex:Name>orsonville eglise </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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-4:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5: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>auneau SNCF </netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:2:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-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:2-1-2:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-1-3:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-1-4:LOC" order="6"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-1-5:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-7: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:3:LOC" version="any">
+ <netex:Name>orsonville rambouillet</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:3:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:3-2-1:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:3-2-2:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:3-2-3:LOC" order="6"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:3-2-4:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7: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:4:LOC" version="any">
+ <netex:Name>auneau SNCF rambouillet</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:3:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:4-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:4-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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:4-2-3:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:4-2-4:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:4-2-5:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7: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>Vers orsonville</netex:FrontText>
+ <netex:PublicCode>11011</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC" version="any">
+ <netex:FrontText>vers auneau</netex:FrontText>
+ <netex:PublicCode>11021</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:3:LOC" version="any">
+ <netex:FrontText>vers rambouillet</netex:FrontText>
+ <netex:PublicCode>11031</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:1-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-7:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-7: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:78517:ZDE:50016296: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:78003:ZDE:50015543:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78003:ZDE:50015539:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78003:ZDE:50015524:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78472:ZDE:50016121:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-6:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:QuayRef ref="FR:28015:ZDE:50015578:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-7:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-7:LOC" version="any"/>
+ <netex:QuayRef ref="FR:28015:ZDE:50015586: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:28015:ZDE:50015587: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:28015:ZDE:50015581:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78472:ZDE:50016122:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78003:ZDE:50015523:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78003:ZDE:50015538:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-6:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78003:ZDE:50015542:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-7:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78517:ZDE:50016296: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:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:2:LOC" version="any">
+ <netex:Name>ITL 2</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7: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 direction orsonville</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:1:LOC" 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:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>10:58:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>10:59:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>11:03:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>11:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>11:10:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>11:11:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>11:17:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>11:18:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-1:LOC" version="any">
+ <netex:Name>Course 1 direction Auneau sncf</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:2:LOC" 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:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>14:58:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>14:59:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>15:03:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>15:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>15:10:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>15:11:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>15:17:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>15:18:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>15:22:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>15:23:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:3-1:LOC" version="any">
+ <netex:Name>direction rambouillet retour</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:3:LOC" 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:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:3:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>20:58:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>20:59:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>21:03:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>21:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>21:10:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>21:11:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>21:17:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>21:18:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:4-1:LOC" version="any">
+ <netex:Name>de auneau sncf à rambouillet </netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:4:LOC" 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:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:4:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>00:10:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>1</netex:ArrivalDayOffset>
+ <netex:DepartureTime>00:11:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>1</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>00:13:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>1</netex:ArrivalDayOffset>
+ <netex:DepartureTime>00:14:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>1</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>00:17:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>1</netex:ArrivalDayOffset>
+ <netex:DepartureTime>00:18: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/regression-5281/OFFRE_SNTYO_2_20170820120001/calendriers.xml b/spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/calendriers.xml
new file mode 100644
index 000000000..bc2b63527
--- /dev/null
+++ b/spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/calendriers.xml
@@ -0,0 +1,145 @@
+<?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:core="http://www.govtalk.gov.uk/core" xmlns:gml="http://www.opengis.net/gml/3.2" 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-06-25T00: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>Semaine vacances</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:4:LOC" version="any" >
+ <netex:Name>WE vacances</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:5:LOC" version="any" >
+ <netex:Name>Service spécial</netex:Name>
+ </netex:DayType>
+ <netex:DayType id="CITYWAY:DayType:6:LOC" version="any" >
+ <netex:Name>Restriction</netex:Name>
+ </netex:DayType>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:1:LOC" 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="CITYWAY:DayTypeAssignment:2:LOC" 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="CITYWAY:DayTypeAssignment:3:LOC" version="any" order="0" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:3:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:1:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:4:LOC" version="any" order="0" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:3:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:2:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:5:LOC" version="any" order="0" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:2:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:3:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:6:LOC" version="any" order="0" >
+ <netex:OperatingPeriodRef ref="CITYWAY:OperatingPeriod:2:LOC" version="any"/>
+ <netex:DayTypeRef ref="CITYWAY:DayType:4:LOC" version="any"/>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:7:LOC" version="any" order="0" >
+ <netex:Date>2017-07-05</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:5:LOC" version="any"/>
+ <netex:isAvailable>true</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:8:LOC" version="any" order="0" >
+ <netex:Date>2017-08-14</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:6:LOC" version="any"/>
+ <netex:isAvailable>false</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:9:LOC" version="any" order="0" >
+ <netex:Date>2017-08-15</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:6:LOC" version="any"/>
+ <netex:isAvailable>false</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:DayTypeAssignment id="CITYWAY:DayTypeAssignment:10:LOC" version="any" order="0" >
+ <netex:Date>2017-08-16</netex:Date>
+ <netex:DayTypeRef ref="CITYWAY:DayType:6:LOC" version="any"/>
+ <netex:isAvailable>false</netex:isAvailable>
+ </netex:DayTypeAssignment>
+ <netex:OperatingPeriod id="CITYWAY:OperatingPeriod:1:LOC" version="any" >
+ <netex:FromDate>2017-06-25T00:00:00</netex:FromDate>
+ <netex:ToDate>2017-07-01T00:00:00</netex:ToDate>
+ </netex:OperatingPeriod>
+ <netex:OperatingPeriod id="CITYWAY:OperatingPeriod:2:LOC" version="any" >
+ <netex:FromDate>2017-07-10T00:00:00</netex:FromDate>
+ <netex:ToDate>2017-08-31T00:00:00</netex:ToDate>
+ </netex:OperatingPeriod>
+ <netex:OperatingPeriod id="CITYWAY:OperatingPeriod:3:LOC" version="any" >
+ <netex:FromDate>2017-09-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/regression-5281/OFFRE_SNTYO_2_20170820120001/commun.xml b/spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/commun.xml
new file mode 100644
index 000000000..b6337b65f
--- /dev/null
+++ b/spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/commun.xml
@@ -0,0 +1,30 @@
+<?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>note numéro 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>note numéro 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>note numéro 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/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00163_01.xml b/spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00163_01.xml
new file mode 100644
index 000000000..b3bccc74f
--- /dev/null
+++ b/spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00163_01.xml
@@ -0,0 +1,497 @@
+<?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 01</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> itinéraire rambouillet vers poigny</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00163">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> itinéraire poigny vers rambouillet</netex:Name>
+ <netex:LineRef ref="STIF:CODIFLIGNE:Line:C00163">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>poigny feuillettes</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>rambouillet SNCF</netex:Name>
+ </netex:Direction>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC" version="any">
+ <netex:Name>rambouillet vers poigny</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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-4:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-5:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5: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>poigny vers rambouillet</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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-4:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-5:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5: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>01101</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC" version="any">
+ <netex:FrontText>Mission 2</netex:FrontText>
+ <netex:PublicCode>01201</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:1-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-5: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:78517:ZDE:50111663: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:78497:ZDE:50016141: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:78497:ZDE:50016136: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:78497:ZDE:50016139:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78497:ZDE:50016142:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78497:ZDE:50016143:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78497:ZDE:50016138:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78497:ZDE:50016137:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78497:ZDE:50016140:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78517:ZDE:50111663: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-2:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:2:LOC" version="any">
+ <netex:Name>ITL 2</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4: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-01:LOC" version="any">
+ <netex:Name>Course 01 rambouillet vers poigny</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:1:LOC" 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:013">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:01101:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:09:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:09:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:11:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:11:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:13:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:13:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:15:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:15:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-02:LOC" version="any">
+ <netex:Name>Course 02 rambouillet vers poigny</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:2:LOC" 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:013">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:01101:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:09:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:09:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:11:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:11:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:13:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:13:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:15:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:15:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-03:LOC" version="any">
+ <netex:Name>Course 03 rambouillet vers poigny</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:3:LOC" 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:013">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:01101:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:31:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:31:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:39:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:39:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:41:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:41:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:43:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:43:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:45:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:45:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-01:LOC" version="any">
+ <netex:Name>Course 01 poigny vers rambouillet</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:4:LOC" 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:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:01101:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:29:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:31:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:31:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:33:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:33:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:35:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:35:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-02:LOC" version="any">
+ <netex:Name>Course 02 poigny vers rambouillet</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:5:LOC" 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:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:01101:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:29:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:31:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:31:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:33:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:33:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:35:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:35:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-03:LOC" version="any">
+ <netex:Name>Course 03 poigny vers rambouillet</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:6:LOC" 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:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ version="any"</netex:OperatorRef>
+ <netex:trainNumbers>
+ <netex:TrainNumberRef ref="CITYWAY:TrainNumber:01101:LOC">version="any"</netex:TrainNumberRef>
+ </netex:trainNumbers>
+ <netex:passingTimes>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:51:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:51:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:59:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:59:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:03:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:03:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:05:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08: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/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00164_03.xml b/spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00164_03.xml
new file mode 100644
index 000000000..56d6ce805
--- /dev/null
+++ b/spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00164_03.xml
@@ -0,0 +1,951 @@
+<?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 03</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:C00164">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:C00164">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>rambouillet vers pontevrard</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name> pontevrard vers rambouillet</netex:Name>
+ </netex:Direction>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC" version="any">
+ <netex:Name>omnibus pontevrard</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>false</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:ForAlighting>false</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-4:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-5:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-6:LOC" order="6"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-7:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-7: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> omnibus rambouillet</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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-4:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-5:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-6:LOC" order="6"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-7:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7: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:3:LOC" version="any">
+ <netex:Name>semi direct pontevrard</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:1:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:3:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-3-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-3-2:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-3-3:LOC" order="6"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-3-4:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-7: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:4:LOC" version="any">
+ <netex:Name> semi direct rambouillet</netex:Name>
+ <netex:RouteRef ref="CITYWAY:Route:2:LOC" version="any"/>
+ <netex:DestinationDisplayRef ref="CITYWAY:DestinationDisplay:4:LOC" version="any"/>
+ <netex:pointsInSequence>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-4-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-4-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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-4-3:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-4-4:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7: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>pontevrard omni</netex:FrontText>
+ <netex:PublicCode>03011</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC" version="any">
+ <netex:FrontText>dourdan omni</netex:FrontText>
+ <netex:PublicCode>03021</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:3:LOC" version="any">
+ <netex:FrontText>pontevrard sd</netex:FrontText>
+ <netex:PublicCode>03012</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:4:LOC" version="any">
+ <netex:FrontText>dourdan sd</netex:FrontText>
+ <netex:PublicCode>03022</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:1-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-7:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-7: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:91200:ZDE:50097554: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:91200:ZDE:50097522:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78569:ZDE:50016385:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78569:ZDE:50016381:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78569:ZDE:50016379:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-6:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78499:ZDE:50016153:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-7:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-7:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78499:ZDE:50016155: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:78499:ZDE:50016154: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:78499:ZDE:50016152:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78569:ZDE:50016378:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78569:ZDE:50016380:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78569:ZDE:50016384:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-6:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:QuayRef ref="FR:91200:ZDE:50097522:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-7:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7:LOC" version="any"/>
+ <netex:QuayRef ref="FR:91200:ZDE:50097554: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-2:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:2:LOC" version="any">
+ <netex:Name>ITL 2</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-6: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 omni vers pontevrard</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:1:LOC" 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:013">
+ 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>05:00:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:04:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:08:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:09:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:13:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:13:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:18:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:22:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:25:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:26:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-2:LOC" version="any">
+ <netex:Name>Course 2 omni vers pontevrard</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:2:LOC" 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:013">
+ 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>06:00:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:04:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:08:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:09:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:13:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:13:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:18:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:22:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:25:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:26:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-3:LOC" version="any">
+ <netex:Name>Course 3 omni vers pontevrard</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:3:LOC" 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:013">
+ 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>07:00:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:04:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:04:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:08:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:09:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:13:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:13:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:18:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:18:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:22:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:25:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:26:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-4:LOC" version="any">
+ <netex:Name>Course 4 sd vers pontevrard</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:4:LOC" 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:3:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>05:30:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:31:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:37:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:37:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:40:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:41:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:44:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:45:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-5:LOC" version="any">
+ <netex:Name>Course 5 sd vers pontevrard</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:5:LOC" 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:3:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>06:30:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:31:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:37:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:37:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:40:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:41:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:44:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:45:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-6:LOC" version="any">
+
+
+ <netex:Name>Course 6 sd vers pontevrard</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:6:LOC" 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:3:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>07:30:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:31:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:37:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:37:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:40:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:41:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:44:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:45:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-1:LOC" version="any">
+ <netex:Name>Course 1 omni vers rambouillet</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:7:LOC" 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:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>05:20:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:24:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:24:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:28:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:33:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:33:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:38:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:38:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:41:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:42:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:45:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:46:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-2:LOC" version="any">
+ <netex:Name>Course 2 omni vers rambouillet</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:8:LOC" 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:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>06:20:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:24:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:24:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:28:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:33:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:33:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:38:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:38:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:41:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:42:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:45:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:46:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-3:LOC" version="any">
+ <netex:Name>Course 3 omni vers rambouillet</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:9:LOC" 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:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>07:20:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:24:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:24:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:28:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:33:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:33:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:38:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:38:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:41:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:42:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:45:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:46:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-4:LOC" version="any">
+ <netex:Name>Course 4 sd vers rambouillet</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:10:LOC" 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:4:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>05:40:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:41:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:47:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:47:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:50:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:51:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:54:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:55:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-5:LOC" version="any">
+ <netex:Name>Course 5 sd vers rambouillet</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:11:LOC" 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:4:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>06:40:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:41:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:47:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:47:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:50:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:51:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:54:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:55:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-6:LOC" version="any">
+ <netex:Name>Course 6 sd vers rambouillet</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:12:LOC" 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:4:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>07:40:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:41:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:47:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:47:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:50:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:51:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:54:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:55: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/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00165_04.xml b/spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00165_04.xml
new file mode 100644
index 000000000..714e9565f
--- /dev/null
+++ b/spec/fixtures/regression-5281/OFFRE_SNTYO_2_20170820120001/offre_C00165_04.xml
@@ -0,0 +1,803 @@
+<?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 4</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:C00165">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:C00165">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>rambouillet vers bullion</netex:Name>
+ </netex:Direction>
+ <netex:Direction id="CITYWAY:Direction:2:LOC" version="any">
+ <netex:Name>bullon vers rambouillet</netex:Name>
+ </netex:Direction>
+ <netex:ServiceJourneyPattern id="CITYWAY:ServiceJourneyPattern:1:LOC" version="any">
+ <netex:Name>rambouillet vers bullion</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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-4:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-5:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-6:LOC" order="6"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-7:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-7:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-8:LOC" order="8"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-8:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-9:LOC" order="9"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-9:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:1-1-10:LOC" order="10"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-10: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>bullion vers rambouillet</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:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-3:LOC" order="3"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-4:LOC" order="4"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-5:LOC" order="5"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-6:LOC" order="6"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-7:LOC" order="7"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-8:LOC" order="8"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-8:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-9:LOC" order="9"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-9:LOC" version="any"/>
+ <netex:ForAlighting>true</netex:ForAlighting>
+ <netex:ForBoarding>true</netex:ForBoarding>
+ </netex:StopPointInJourneyPattern>
+ <netex:StopPointInJourneyPattern id="CITYWAY:StopPointInJourneyPattern:2-2-10:LOC" order="10"
+ version="any">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-10: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>05010</netex:PublicCode>
+ </netex:DestinationDisplay>
+ <netex:DestinationDisplay id="CITYWAY:DestinationDisplay:2:LOC" version="any">
+ <netex:FrontText>Mission 2</netex:FrontText>
+ <netex:PublicCode>05021</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:1-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-7:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-8:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-9:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:1-10:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-2:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-7:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-8:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-9:LOC" version="any"/>
+ <netex:ScheduledStopPoint id="CITYWAY:ScheduledStopPoint:2-10: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:78517:ZDE:50111663: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:78517:ZDE:50076506:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78164:ZDE:50015685:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78164:ZDE:50015683:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78164:ZDE:50015687:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-6:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-6:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78125:ZDE:50015678:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-7:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-7:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78125:ZDE:50015676:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-8:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-8:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78125:ZDE:50015672:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-9:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-9:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78120:ZDE:50015671:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:1-10:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-10:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78120:ZDE:50015667: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:78120:ZDE:50015666: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:78120:ZDE:50015670:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-3:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-3:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78125:ZDE:50015673:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-4:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-4:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78125:ZDE:50015677:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-5:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-5:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78125:ZDE:50015679:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-6:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-6:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78164:ZDE:50015686:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-7:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78164:ZDE:50015682:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-8:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-8:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78164:ZDE:50015684:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-9:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-9:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78517:ZDE:50076505:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:PassengerStopAssignment id="CITYWAY:PassengerStopAssignment:2-10:LOC" version="any" order="0">
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-10:LOC" version="any"/>
+ <netex:QuayRef ref="FR:78517:ZDE:50111663:STIF">version="any"</netex:QuayRef>
+ </netex:PassengerStopAssignment>
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:1:LOC" version="any">
+ <netex:Name>ITL RBT clairefontaine </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:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-3:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-4:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:2:LOC" version="any">
+ <netex:Name>ITL clairefontaine RBT</netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-7:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-8:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-9:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-10:LOC" version="any"/>
+ </netex:members>
+ <netex:ZoneUse>cannotBoardAndAlightInSameZone</netex:ZoneUse>
+ </netex:RoutingConstraintZone>
+ <netex:RoutingConstraintZone id="CITYWAY:RoutingConstraintZone:3:LOC" version="any">
+ <netex:Name>ITL bullion </netex:Name>
+ <netex:members>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-9:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:1-10:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-1:LOC" version="any"/>
+ <netex:ScheduledStopPointRef ref="CITYWAY:ScheduledStopPoint:2-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>C1 bullion semaine</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:1:LOC" 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:013">
+ 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>06:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:05:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:05:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:09:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:09:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:12:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:12:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:15:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:15:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:22:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:25:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:25:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:29:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:31:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:32:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:34:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:35:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-2:LOC" version="any">
+ <netex:Name>C bullion WE</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:2:LOC" 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:2:LOC"> version="any"</netex:DayTypeRef>
+ </netex:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>07:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:05:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:05:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:09:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:09:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:12:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:12:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:15:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:15:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:22:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:25:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:25:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:29:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:31:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:32:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:34:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:35:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:1-3:LOC" version="any">
+ <netex:Name>C bullion WE</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:3:LOC" 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:DayTypeRef ref="CITYWAY:DayType:2:LOC"> version="any"</netex:DayTypeRef>
+ </netex:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:1:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>08:01:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:01:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:05:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:05:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:09:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:09:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:12:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:12:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:15:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:15:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:22:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:25:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:25:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:29:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:31:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:32:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>08:34:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>08:35:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-1:LOC" version="any">
+ <netex:Name>C rbt semaine</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:4:LOC" 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:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>05:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:25:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:25:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:29:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:32:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:32:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:35:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:35:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:41:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:42:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:45:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:45:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:49:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:49:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:51:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:52:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>05:54:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>05:55:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-2:LOC" version="any">
+ <netex:Name>C rbt we</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:5:LOC" 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:2:LOC"> version="any"</netex:DayTypeRef>
+ </netex:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>06:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:25:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:25:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:29:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:32:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:32:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:35:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:35:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:41:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:42:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:45:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:45:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:49:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:49:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:51:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:52:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>06:54:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>06:55:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ </netex:passingTimes>
+ </netex:ServiceJourney>
+ <netex:ServiceJourney id="CITYWAY:ServiceJourney:2-3:LOC" version="any">
+ <netex:Name>C rbt semaine et we</netex:Name>
+ <netex:noticeAssignments>
+ <netex:NoticeAssignment id="CITYWAY:NoticeAssignment:6:LOC" 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:DayTypeRef ref="CITYWAY:DayType:2:LOC"> version="any"</netex:DayTypeRef>
+ </netex:dayTypes>
+ <netex:JourneyPatternRef ref="CITYWAY:ServiceJourneyPattern:2:LOC" version="any"/>
+ <netex:OperatorRef ref="STIF:CODIFLIGNE:Operator:013">
+ 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>07:21:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:21:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:25:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:25:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:29:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:29:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:32:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:32:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:35:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:35:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:41:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:42:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:45:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:45:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:49:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:49:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:51:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:52:00.000</netex:DepartureTime>
+ <netex:DepartureDayOffset>0</netex:DepartureDayOffset>
+ </netex:TimetabledPassingTime>
+ <netex:TimetabledPassingTime version="any">
+ <netex:ArrivalTime>07:54:00.000</netex:ArrivalTime>
+ <netex:ArrivalDayOffset>0</netex:ArrivalDayOffset>
+ <netex:DepartureTime>07:55: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/some_foreign_mixed/FOREIGN_LINE/calendriers.xml b/spec/fixtures/some_foreign_mixed/FOREIGN_LINE/calendriers.xml
new file mode 100644
index 000000000..bfbd0aea1
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/FOREIGN_LINE/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/some_foreign_mixed/FOREIGN_LINE/commun.xml b/spec/fixtures/some_foreign_mixed/FOREIGN_LINE/commun.xml
new file mode 100644
index 000000000..266c8a598
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/FOREIGN_LINE/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/some_foreign_mixed/FOREIGN_LINE/offre_C00107_10.xml b/spec/fixtures/some_foreign_mixed/FOREIGN_LINE/offre_C00107_10.xml
new file mode 100644
index 000000000..9dff0d850
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/FOREIGN_LINE/offre_C00107_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/some_foreign_mixed/FOREIGN_LINE/offre_C00108_9.xml b/spec/fixtures/some_foreign_mixed/FOREIGN_LINE/offre_C00108_9.xml
new file mode 100644
index 000000000..832793036
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/FOREIGN_LINE/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/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/calendriers.xml b/spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/calendriers.xml
new file mode 100644
index 000000000..bfbd0aea1
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/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/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/commun.xml b/spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/commun.xml
new file mode 100644
index 000000000..266c8a598
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/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/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml b/spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml
new file mode 100644
index 000000000..832793036
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/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/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml b/spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml
new file mode 100644
index 000000000..9dff0d850
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/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/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/calendriers.xml b/spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/calendriers.xml
new file mode 100644
index 000000000..1043e0cde
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/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/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/commun.xml b/spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/commun.xml
new file mode 100644
index 000000000..f59f8ac2d
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/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/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml b/spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml
new file mode 100644
index 000000000..9eefeeb43
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/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/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml b/spec/fixtures/some_foreign_mixed/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml
new file mode 100644
index 000000000..d260ef17e
--- /dev/null
+++ b/spec/fixtures/some_foreign_mixed/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/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/calendriers.xml b/spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/calendriers.xml
new file mode 100644
index 000000000..bfbd0aea1
--- /dev/null
+++ b/spec/fixtures/two_referentials_ok/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/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/commun.xml b/spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/commun.xml
new file mode 100644
index 000000000..266c8a598
--- /dev/null
+++ b/spec/fixtures/two_referentials_ok/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/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml b/spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/offre_C00108_9.xml
new file mode 100644
index 000000000..832793036
--- /dev/null
+++ b/spec/fixtures/two_referentials_ok/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/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml b/spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122517/offre_C00109_10.xml
new file mode 100644
index 000000000..9dff0d850
--- /dev/null
+++ b/spec/fixtures/two_referentials_ok/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/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/calendriers.xml b/spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/calendriers.xml
new file mode 100644
index 000000000..1043e0cde
--- /dev/null
+++ b/spec/fixtures/two_referentials_ok/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/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/commun.xml b/spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/commun.xml
new file mode 100644
index 000000000..f59f8ac2d
--- /dev/null
+++ b/spec/fixtures/two_referentials_ok/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/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml b/spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/offre_C00108_9.xml
new file mode 100644
index 000000000..9eefeeb43
--- /dev/null
+++ b/spec/fixtures/two_referentials_ok/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/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml b/spec/fixtures/two_referentials_ok/OFFRE_TRANSDEV_20170301122519/offre_C00109_10.xml
new file mode 100644
index 000000000..d260ef17e
--- /dev/null
+++ b/spec/fixtures/two_referentials_ok/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_spec.rb b/spec/helpers/table_builder_helper_spec.rb
index 3b0a18379..5bddbb16f 100644
--- a/spec/helpers/table_builder_helper_spec.rb
+++ b/spec/helpers/table_builder_helper_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
require 'htmlbeautifier'
module TableBuilderHelper
@@ -5,6 +6,13 @@ module TableBuilderHelper
end
describe TableBuilderHelper, type: :helper do
+ let(:features){ [] }
+ before do
+ allow_any_instance_of(AF83::Decorator::Link).to receive(:check_feature){|f|
+ features.include?(f)
+ }
+ end
+
describe "#table_builder_2" do
it "builds a table" do
referential = build_stubbed(:workbench_referential)
@@ -35,9 +43,8 @@ describe TableBuilderHelper, type: :helper do
id: referentials[0].workbench.id
})
- referentials = ModelDecorator.decorate(
- referentials,
- with: ReferentialDecorator
+ referentials = ReferentialDecorator.decorate(
+ referentials
)
expected = <<-HTML
@@ -54,12 +61,12 @@ describe TableBuilderHelper, type: :helper do
<th><a href="/workbenches/#{workbench.id}?direction=desc&amp;sort=lines">Lignes<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th>
<th><a href="/workbenches/#{workbench.id}?direction=desc&amp;sort=created_at">Créé le<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th>
<th><a href="/workbenches/#{workbench.id}?direction=desc&amp;sort=updated_at">Edité le<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th>
- <th><a href="/workbenches/#{workbench.id}?direction=desc&amp;sort=published_at">Intégré le<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th>
+ <th><a href="/workbenches/#{workbench.id}?direction=desc&amp;sort=merged_at">Finalisé le<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th>
<th></th>
</tr>
</thead>
<tbody>
- <tr>
+ <tr class="referential-#{referential.id}">
<td>
<div class="checkbox"><input type="checkbox" name="#{referential.id}" id="#{referential.id}" value="#{referential.id}" /><label for="#{referential.id}"></label></div>
</td>
@@ -76,15 +83,21 @@ describe TableBuilderHelper, type: :helper do
<td class="actions">
<div class="btn-group">
<div class="btn dropdown-toggle" data-toggle="dropdown"><span class="fa fa-cog"></span></div>
- <ul class="dropdown-menu">
- <li><a href="/referentials/#{referential.id}">Consulter</a></li>
- <li><a href="/referentials/#{referential.id}/edit">Editer</a></li>
- <li><a href="/referentials/#{referential.id}/time_tables">Calendriers</a></li>
- <li><a href="/referentials/new?from=#{referential.id}">Dupliquer</a></li>
- <li><a href="/referentials/#{referential.id}/select_compliance_control_set">Valider</a></li>
- <li><a rel="nofollow" data-method="put" href="/referentials/#{referential.id}/archive">Conserver</a></li>
- <li class="delete-action"><a data-confirm="Etes vous sûr de vouloir supprimer ce jeu de données ?" rel="nofollow" data-method="delete" href="/referentials/#{referential.id}"><span class="fa fa-trash mr-xs"></span>Supprimer</a></li>
- </ul>
+ <div class="dropdown-menu">
+ <ul class="primary">
+ <li class=""><a href="/referentials/#{referential.id}">Consulter</a></li>
+ <li class=""><a href="/referentials/#{referential.id}/edit">Editer</a></li>
+ </ul>
+ <ul class="other">
+ <li class=""><a href="/referentials/#{referential.id}/time_tables">Calendriers</a></li>
+ <li class=""><a href="/referentials/new?from=#{referential.id}">Dupliquer</a></li>
+ <li class=""><a href="/referentials/#{referential.id}/select_compliance_control_set">Valider</a></li>
+ <li class=""><a rel="nofollow" data-method="put" href="/referentials/#{referential.id}/archive">Conserver</a></li>
+ </ul>
+ <ul class="footer">
+ <li class=" delete-action"><a data-confirm="Etes vous sûr de vouloir supprimer ce jeu de données ?" rel="nofollow" data-method="delete" href="/referentials/#{referential.id}"><span class="fa fa-trash mr-xs"></span>Supprimer</a></li>
+ </ul>
+ </div>
</div>
</td>
</tr>
@@ -105,7 +118,7 @@ describe TableBuilderHelper, type: :helper do
TableBuilderHelper::Column.new(
key: :status,
attribute: Proc.new do |w|
- if w.archived?
+ if w.referential_read_only?
("<div class='td-block'><span class='fa fa-archive'></span><span>Conservé</span></div>").html_safe
else
("<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>En préparation</span></div>").html_safe
@@ -143,12 +156,12 @@ describe TableBuilderHelper, type: :helper do
attribute: Proc.new {|w| l(w.updated_at, format: :short)}
),
TableBuilderHelper::Column.new(
- key: :published_at,
+ key: :merged_at,
attribute: ''
)
],
selectable: true,
- links: [:show, :edit],
+ action: :index,
cls: 'table has-filter has-search'
)
@@ -194,9 +207,9 @@ describe TableBuilderHelper, type: :helper do
referential_id: referential.id
})
- companies = ModelDecorator.decorate(
+ companies = CompanyDecorator.decorate(
companies,
- with: CompanyDecorator
+ context: { referential: referential }
)
stub_policy_scope(company)
@@ -213,7 +226,7 @@ describe TableBuilderHelper, type: :helper do
</tr>
</thead>
<tbody>
- <tr>
+ <tr class="company-#{company.id}">
<td>#{company.get_objectid.local_id}</td>
<td title="Voir"><a href="/referentials/#{referential.id}/companies/#{company.id}">#{company.name}</a></td>
<td></td>
@@ -222,9 +235,11 @@ describe TableBuilderHelper, type: :helper do
<td class="actions">
<div class="btn-group">
<div class="btn dropdown-toggle" data-toggle="dropdown"><span class="fa fa-cog"></span></div>
- <ul class="dropdown-menu">
- <li><a href="/referentials/#{referential.id}/companies/#{company.id}">Consulter</a></li>
- </ul>
+ <div class="dropdown-menu">
+ <ul class="primary">
+ <li class=""><a href="/referentials/#{referential.id}/companies/#{company.id}">Consulter</a></li>
+ </ul>
+ </div>
</div>
</td>
</tr>
@@ -306,9 +321,8 @@ describe TableBuilderHelper, type: :helper do
referential_id: referential.id
})
- companies = ModelDecorator.decorate(
+ companies = CompanyDecorator.decorate(
companies,
- with: CompanyDecorator,
context: { referential: line_referential }
)
stub_policy_scope(company)
@@ -326,7 +340,7 @@ describe TableBuilderHelper, type: :helper do
</tr>
</thead>
<tbody>
- <tr>
+ <tr class="company-#{company.id}">
<td>#{company.get_objectid.local_id}</td>
<td title="Voir"><a href="/referentials/#{referential.id}/companies/#{company.id}">#{company.name}</a></td>
<td></td>
@@ -335,9 +349,11 @@ describe TableBuilderHelper, type: :helper do
<td class="actions">
<div class="btn-group">
<div class="btn dropdown-toggle" data-toggle="dropdown"><span class="fa fa-cog"></span></div>
- <ul class="dropdown-menu">
- <li><a href="/referentials/#{referential.id}/companies/#{company.id}">Consulter</a></li>
- </ul>
+ <div class="dropdown-menu">
+ <ul class="primary">
+ <li class=""><a href="/line_referentials/#{line_referential.id}/companies/#{company.id}">Consulter</a></li>
+ </ul>
+ </div>
</div>
</td>
</tr>
@@ -373,7 +389,6 @@ describe TableBuilderHelper, type: :helper do
),
],
sortable: false,
- links: [:show, :edit, :delete],
cls: 'table has-search'
)
@@ -381,5 +396,86 @@ describe TableBuilderHelper, type: :helper do
expect(beautified_html).to eq(expected.chomp)
end
+
+ context "on a single row" do
+ let(:referential){ build_stubbed :referential }
+ let(:other_referential){ build_stubbed :referential }
+ let(:user_context){
+ UserContext.new(
+ build_stubbed(
+ :user,
+ organisation: referential.organisation,
+ permissions: [
+ 'referentials.create',
+ 'referentials.update',
+ 'referentials.destroy',
+ ]
+ ),
+ referential: referential
+ )
+ }
+ let(:columns){
+ [
+ TableBuilderHelper::Column.new(
+ key: :name,
+ attribute: 'name'
+ ),
+ ]
+ }
+ let(:item){ referential.decorate }
+ let(:other_item){ other_referential.decorate }
+ let(:selectable){ false }
+ let(:links){ [:show] }
+ let(:overhead){ [] }
+ let(:model_name){ "referential" }
+ let(:other_tr){ helper.send(:tr, other_item, columns, selectable, links, overhead, model_name) }
+ let(:items){ [item, other_item] }
+
+ before(:each){
+ allow(helper).to receive(:current_user).and_return(user_context)
+ }
+
+ context "with all rows non-selectable" do
+ let(:selectable){ false }
+ it "sets all rows as non selectable" do
+ items.each do |i|
+ tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name, :index)
+ klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}"
+ selector = "tr.#{klass} [type=checkbox]"
+ expect(tr).to_not have_selector selector
+ end
+ end
+ end
+
+ context "with all rows selectable" do
+ let(:selectable){ true }
+ it "adds a checkbox in all rows" do
+ items.each do |i|
+ tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name, :index)
+ klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}"
+ selector = "tr.#{klass} [type=checkbox]"
+ expect(tr).to have_selector selector
+ end
+ end
+ end
+
+ context "with THIS row non selectable" do
+ let(:selectable){ ->(i){ i.id != item.id } }
+ it "adds a checkbox in all rows" do
+ items.each do |i|
+ tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name, :index)
+ klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}"
+ selector = "tr.#{klass} [type=checkbox]"
+ expect(tr).to have_selector selector
+ end
+ end
+ it "disables this rows checkbox" do
+ tr = helper.send(:tr, item, columns, selectable, links, overhead, model_name, :index)
+ klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{item.id}"
+ selector = "tr.#{klass} [type=checkbox][disabled]"
+ expect(tr).to have_selector selector
+ end
+ end
+ end
end
end
diff --git a/spec/javascript/journey_patterns/actions_spec.js b/spec/javascript/journey_patterns/actions_spec.js
index 2542fa2f4..60d6d88bb 100644
--- a/spec/javascript/journey_patterns/actions_spec.js
+++ b/spec/javascript/journey_patterns/actions_spec.js
@@ -112,6 +112,22 @@ describe('when clicking on a journey pattern delete button', () => {
expect(actions.deleteJourneyPattern(index)).toEqual(expectedAction)
})
})
+describe('when changing on a journey pattern costs', () => {
+ it('should create an action to update journey pattern', () => {
+ const index = 1
+ const costs = {
+ "1-2": {
+ distance: 1
+ }
+ }
+ const expectedAction = {
+ type: 'UPDATE_JOURNEYPATTERN_COSTS',
+ index,
+ costs
+ }
+ expect(actions.updateJourneyPatternCosts(index, costs)).toEqual(expectedAction)
+ })
+})
describe('when clicking on validate button inside edit modal', () => {
it('should create an action to save journey pattern modifications', () => {
const index = 1
diff --git a/spec/javascript/journey_patterns/components/JourneyPattern_spec.js b/spec/javascript/journey_patterns/components/JourneyPattern_spec.js
new file mode 100644
index 000000000..0da75ad47
--- /dev/null
+++ b/spec/javascript/journey_patterns/components/JourneyPattern_spec.js
@@ -0,0 +1,63 @@
+import React, { Component } from 'react'
+import JourneyPattern from '../../../../app/javascript/journey_patterns/components/JourneyPattern'
+import renderer from 'react-test-renderer'
+
+describe('the edit button', () => {
+ set('policy', () => {
+ return {}
+ })
+ set('features', () => {
+ return []
+ })
+ set('editMode', () => {
+ return false
+ })
+ set('component', () => {
+ let props = {
+ status: {
+ policy: policy,
+ features: features
+ },
+ onCheckboxChange: ()=>{},
+ onDeleteJourneyPattern: ()=>{},
+ onOpenEditModal: ()=>{},
+ journeyPatterns: {},
+ value: {
+ stop_points: []
+ },
+ index: 0,
+ editMode: editMode
+ }
+ let list = renderer.create(
+ <JourneyPattern
+ status={props.status}
+ journeyPatterns={props.journeyPatterns}
+ value={props.value}
+ index={props.index}
+ onCheckboxChange={props.onCheckboxChange}
+ onDeleteJourneyPattern={props.onDeleteJourneyPattern}
+ onOpenEditModal={props.onOpenEditModal}
+ editMode={props.editMode}
+ />
+ )
+
+ return list
+ })
+
+
+ it('should display the show link', () => {
+ expect(component.toJSON()).toMatchSnapshot()
+ expect(component.root.findByProps({"data-target": "#JourneyPatternModal"})._fiber.stateNode.children[0].text).toEqual("Consulter")
+ })
+
+ context('in edit mode', () => {
+ set('editMode', () => {
+ return true
+ })
+
+ it('should display the edit link', () => {
+ expect(component.toJSON()).toMatchSnapshot()
+ expect(component.root.findByProps({"data-target": "#JourneyPatternModal"})._fiber.stateNode.children[0].text).toEqual("Editer")
+ })
+ })
+})
diff --git a/spec/javascript/journey_patterns/components/JourneyPatterns_spec.js b/spec/javascript/journey_patterns/components/JourneyPatterns_spec.js
new file mode 100644
index 000000000..0c852deff
--- /dev/null
+++ b/spec/javascript/journey_patterns/components/JourneyPatterns_spec.js
@@ -0,0 +1,77 @@
+import React, { Component } from 'react'
+import JourneyPatterns from '../../../../app/javascript/journey_patterns/components/JourneyPatterns'
+import renderer from 'react-test-renderer'
+
+describe('stopPointHeader', () => {
+ set('features', () => {
+ return {}
+ })
+ set('component', () => {
+ let props = {
+ status: {
+ features: features
+ },
+ onCheckboxChange: ()=>{},
+ onLoadFirstPage: ()=>{},
+ onOpenEditModal: ()=>{},
+ stopPointsList: [stop_point, same_city_stop_point, other_country_stop_point],
+ journeyPatterns: []
+ }
+ let list = renderer.create(
+ <JourneyPatterns
+ status={props.status}
+ journeyPatterns={props.journeyPatterns}
+ stopPointsList={props.stopPointsList}
+ onCheckboxChange={props.onCheckboxChange}
+ onLoadFirstPage={props.onLoadFirstPage}
+ onOpenEditModal={props.onOpenEditModal}
+ />
+ ).toJSON()
+
+ return list
+ })
+
+ set('stop_point', () => {
+ return {
+ name: "Stop point",
+ city_name: "City Name",
+ zip_code: "12345",
+ country_code: "FR",
+ country_name: "france",
+ object_id: "sp-FR"
+ }
+ })
+
+ set('same_city_stop_point', () => {
+ return {
+ name: "Antother stop point",
+ city_name: stop_point.city_name,
+ zip_code: stop_point.zip_code,
+ country_code: stop_point.country_code,
+ country_name: stop_point.country_name,
+ object_id: stop_point.object_id + "-2"
+ }
+ })
+
+ set('other_country_stop_point', () => {
+ return {
+ name: "Antother stop point",
+ city_name: "New York",
+ zip_code: "232323",
+ country_code: "US",
+ country_name: "USA",
+ object_id: "sp-USA"
+ }
+ })
+ it('should display the city name', () => {
+ expect(component).toMatchSnapshot()
+ })
+ context('with the "long_distance_routes" feature', () => {
+ set('features', () => {
+ return { long_distance_routes: true }
+ })
+ it('should display the country name', () => {
+ expect(component).toMatchSnapshot()
+ })
+ })
+})
diff --git a/spec/javascript/journey_patterns/components/__snapshots__/JourneyPattern_spec.js.snap b/spec/javascript/journey_patterns/components/__snapshots__/JourneyPattern_spec.js.snap
new file mode 100644
index 000000000..0bedd8d69
--- /dev/null
+++ b/spec/javascript/journey_patterns/components/__snapshots__/JourneyPattern_spec.js.snap
@@ -0,0 +1,143 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`the edit button in edit mode should display the edit link 1`] = `
+<div
+ className="t2e-item to_record"
+>
+ <div
+ className="th"
+ >
+ <div
+ className="strong mb-xs"
+ >
+ -
+ </div>
+ <div />
+ <div>
+ 0
+ arrêt(s)
+ </div>
+ <div
+ className="btn-group"
+ >
+ <div
+ className="btn dropdown-toggle"
+ data-toggle="dropdown"
+ >
+ <span
+ className="fa fa-cog"
+ />
+ </div>
+ <ul
+ className="dropdown-menu"
+ >
+ <li>
+ <button
+ data-target="#JourneyPatternModal"
+ data-toggle="modal"
+ onClick={[Function]}
+ type="button"
+ >
+ Editer
+ </button>
+ </li>
+ <li
+ className="disabled"
+ >
+ <a
+ href="blank/vehicle_journeys?jp=undefined"
+ >
+ Horaires des courses
+ </a>
+ </li>
+ <li
+ className="delete-action disabled"
+ >
+ <button
+ className="disabled"
+ disabled={true}
+ onClick={[Function]}
+ type="button"
+ >
+ <span
+ className="fa fa-trash"
+ />
+ Supprimer
+ </button>
+ </li>
+ </ul>
+ </div>
+ </div>
+</div>
+`;
+
+exports[`the edit button should display the show link 1`] = `
+<div
+ className="t2e-item to_record"
+>
+ <div
+ className="th"
+ >
+ <div
+ className="strong mb-xs"
+ >
+ -
+ </div>
+ <div />
+ <div>
+ 0
+ arrêt(s)
+ </div>
+ <div
+ className="btn-group"
+ >
+ <div
+ className="btn dropdown-toggle"
+ data-toggle="dropdown"
+ >
+ <span
+ className="fa fa-cog"
+ />
+ </div>
+ <ul
+ className="dropdown-menu"
+ >
+ <li>
+ <button
+ data-target="#JourneyPatternModal"
+ data-toggle="modal"
+ onClick={[Function]}
+ type="button"
+ >
+ Consulter
+ </button>
+ </li>
+ <li
+ className="disabled"
+ >
+ <a
+ href="blank/vehicle_journeys?jp=undefined"
+ >
+ Horaires des courses
+ </a>
+ </li>
+ <li
+ className="delete-action disabled"
+ >
+ <button
+ className="disabled"
+ disabled={true}
+ onClick={[Function]}
+ type="button"
+ >
+ <span
+ className="fa fa-trash"
+ />
+ Supprimer
+ </button>
+ </li>
+ </ul>
+ </div>
+ </div>
+</div>
+`;
diff --git a/spec/javascript/journey_patterns/components/__snapshots__/JourneyPatterns_spec.js.snap b/spec/javascript/journey_patterns/components/__snapshots__/JourneyPatterns_spec.js.snap
new file mode 100644
index 000000000..a332e7d80
--- /dev/null
+++ b/spec/javascript/journey_patterns/components/__snapshots__/JourneyPatterns_spec.js.snap
@@ -0,0 +1,169 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`stopPointHeader should display the city name 1`] = `
+<div
+ className="row"
+>
+ <div
+ className="col-lg-12"
+ >
+ <div
+ className="table table-2entries mt-sm mb-sm no_result"
+ >
+ <div
+ className="t2e-head w20"
+ >
+ <div
+ className="th"
+ >
+ <div
+ className="strong mb-xs"
+ >
+ ID Mission
+ </div>
+ <div>
+ Code mission
+ </div>
+ <div>
+ Nb arrêts
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className="headlined"
+ data-headline="City Name"
+ title="City Name (12345)"
+ >
+ <span>
+ <span>
+ Stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className=""
+ data-headline=""
+ title="City Name (12345)"
+ >
+ <span>
+ <span>
+ Antother stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className="headlined"
+ data-headline="New York"
+ title="New York (232323)"
+ >
+ <span>
+ <span>
+ Antother stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ className="t2e-item-list w80"
+ >
+ <div />
+ </div>
+ </div>
+ </div>
+</div>
+`;
+
+exports[`stopPointHeader with the "long_distance_routes" feature should display the country name 1`] = `
+<div
+ className="row"
+>
+ <div
+ className="col-lg-12"
+ >
+ <div
+ className="table table-2entries mt-sm mb-sm no_result"
+ >
+ <div
+ className="t2e-head w20"
+ >
+ <div
+ className="th"
+ >
+ <div
+ className="strong mb-xs"
+ >
+ ID Mission
+ </div>
+ <div>
+ Code mission
+ </div>
+ <div>
+ Nb arrêts
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className="headlined"
+ data-headline="france"
+ title="City Name (12345)"
+ >
+ <span>
+ <span>
+ Stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className=""
+ data-headline=""
+ title="City Name (12345)"
+ >
+ <span>
+ <span>
+ Antother stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className="headlined"
+ data-headline="USA"
+ title="New York (232323)"
+ >
+ <span>
+ <span>
+ Antother stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ className="t2e-item-list w80"
+ >
+ <div />
+ </div>
+ </div>
+ </div>
+</div>
+`;
diff --git a/spec/javascript/journey_patterns/reducers/journey_patterns_spec.js b/spec/javascript/journey_patterns/reducers/journey_patterns_spec.js
index 24780ab5a..bfa87d24a 100644
--- a/spec/javascript/journey_patterns/reducers/journey_patterns_spec.js
+++ b/spec/javascript/journey_patterns/reducers/journey_patterns_spec.js
@@ -47,7 +47,10 @@ describe('journeyPatterns reducer', () => {
object_id : 'o1',
published_name: 'M1',
registration_number: '',
- stop_points: fakeStopPoints
+ stop_points: fakeStopPoints,
+ costs: {
+
+ }
},
{
deletable: false,
@@ -55,7 +58,13 @@ describe('journeyPatterns reducer', () => {
object_id : 'o2',
published_name: 'M2',
registration_number: '',
- stop_points: fakeStopPoints
+ stop_points: fakeStopPoints,
+ costs: {
+ "1-2": {
+ distance: 0,
+ time: 10,
+ }
+ }
}
]
})
@@ -83,7 +92,8 @@ describe('journeyPatterns reducer', () => {
published_name: 'M3',
registration_number: '',
deletable: false,
- stop_points: stopPoints
+ stop_points: stopPoints,
+ costs: {}
}, ...state])
})
@@ -100,6 +110,28 @@ describe('journeyPatterns reducer', () => {
).toEqual([newState, state[1]])
})
+ it('should handle UPDATE_JOURNEYPATTERN_COSTS', () => {
+ const costs = {
+ "1-2": {
+ distance: 1
+ }
+ }
+ const new_costs = {
+ "1-2": {
+ distance: 1,
+ time: 10,
+ }
+ }
+ const new_state = Object.assign({}, state[1], {costs: new_costs})
+ expect(
+ jpReducer(state, {
+ type: 'UPDATE_JOURNEYPATTERN_COSTS',
+ index: 1,
+ costs
+ })
+ ).toEqual([state[0], new_state])
+ })
+
it('should handle DELETE_JOURNEYPATTERN', () => {
expect(
jpReducer(state, {
diff --git a/spec/javascript/preprocessor.js b/spec/javascript/preprocessor.js
new file mode 100644
index 000000000..a2de8e4be
--- /dev/null
+++ b/spec/javascript/preprocessor.js
@@ -0,0 +1,15 @@
+'use strict';
+
+var coffee = require('coffeescript');
+
+module.exports = {
+ process: function(src, filename) {
+ if (coffee.helpers.isCoffee(filename)) {
+ return coffee.compile(src, {
+ 'bare': false,
+ 'inlineMap': true
+ })
+ }
+ return src;
+ }
+};
diff --git a/spec/javascript/routes/reducers/stop_points_spec.js b/spec/javascript/routes/reducers/stop_points_spec.js
index b375cdc2c..124618f9d 100644
--- a/spec/javascript/routes/reducers/stop_points_spec.js
+++ b/spec/javascript/routes/reducers/stop_points_spec.js
@@ -1,7 +1,17 @@
import stopPointsReducer from '../../../../app/javascript/routes/reducers/stopPoints'
+import formHelper from '../../../../app/javascript/routes/form_helper'
+import _ from 'lodash'
+
+ // _ _ ___ _ ___ ___ ___ ___
+ // | || | __| | | _ \ __| _ \/ __|
+ // | __ | _|| |__| _/ _|| /\__ \
+ // |_||_|___|____|_| |___|_|_\|___/
+ //
let state = []
+formHelper.addInput = (...args)=>{}
+
let fakeData = {
geometry: undefined,
registration_number: 'rn_test',
@@ -10,34 +20,47 @@ let fakeData = {
user_objectid: 'uoid_test'
}
+let update_stop_point = (stop_point, opts) => {
+ return _.assign({}, stop_point, opts)
+}
+
+let stop_point = (opts) => {
+ return _.assign({},
+ {
+ text: "",
+ index: 0,
+ edit: false,
+ for_boarding: 'normal',
+ for_alighting: 'normal',
+ olMap: { isOpened: false, json: {} }
+ },
+ opts
+ )
+}
+
+let stop_point_1 = stop_point({text: 'first', index: 0, stoppoint_id: 72 })
+let stop_point_2 = stop_point({text: 'second', index: 1, stoppoint_id: 73 })
+let stop_point_3 = stop_point({text: 'third', index: 2, stoppoint_id: 74 })
+
+let it_should_handle = (action, final_state, custom_state=null) => {
+ it("should handle "+ action.type, () => {
+ expect(
+ stopPointsReducer(custom_state || state, action)
+ ).toEqual( final_state )
+ })
+}
+
+
+ // ___ ___ ___ ___ ___
+ // / __| _ \ __/ __/ __|
+ // \__ \ _/ _| (__\__ \
+ // |___/_| |___\___|___/
+ //
+
+
describe('stops reducer', () => {
beforeEach(()=>{
- state = [
- {
- text: 'first',
- index: 0,
- stoppoint_id: 72,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- },
- {
- text: 'second',
- index: 1,
- stoppoint_id: 73,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- }
- ]
+ state = [ stop_point_1, stop_point_2, stop_point_3 ]
})
it('should return the initial state', () => {
@@ -46,441 +69,124 @@ describe('stops reducer', () => {
).toEqual([])
})
- it('should handle ADD_STOP', () => {
- expect(
- stopPointsReducer(state, {
- type: 'ADD_STOP'
- })
- ).toEqual(
- [
- {
- text: 'first',
- index: 0,
- stoppoint_id: 72,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- },
- {
- text: 'second',
- index: 1,
- stoppoint_id: 73,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- },
- {
- text: '',
- index: 2,
- edit: true,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- }
- ]
- )
- })
+ it_should_handle(
+ {type: "ADD_STOP"},
+ [stop_point_1, stop_point_2, stop_point_3, stop_point({index: 3, edit: true})]
+ )
- it('should handle MOVE_UP_STOP', () => {
- expect(
- stopPointsReducer(state, {
- type: 'MOVE_STOP_UP',
- index: 1
- })
- ).toEqual(
- [
- {
- text: 'second',
- index: 1,
- stoppoint_id: 72,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- },
- {
- text: 'first',
- index: 0,
- stoppoint_id: 73,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- }
- ]
- )
- })
+ it_should_handle(
+ {type: 'MOVE_STOP_UP', index: 1},
+ [ update_stop_point(stop_point_2, {index: 0}), update_stop_point(stop_point_1, {index: 1}), stop_point_3 ]
+ )
- it('should handle MOVE_DOWN_STOP', () => {
- expect(
- stopPointsReducer(state, {
- type: 'MOVE_STOP_DOWN',
- index: 0
- })
- ).toEqual(
- [
- {
- text: 'second',
- index: 1,
- stoppoint_id: 72,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- },
- {
- text: 'first',
- index: 0,
- stoppoint_id: 73,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- }
- ]
- )
- })
+ it_should_handle(
+ {type: 'MOVE_STOP_DOWN', index: 0},
+ [ update_stop_point(stop_point_2, {index: 0}), update_stop_point(stop_point_1, {index: 1}), stop_point_3 ]
+ )
- // it('should handle DELETE_STOP', () => {
- // expect(
- // stopPointsReducer(state, {
- // type: 'DELETE_STOP',
- // index: 1
- // })
- // ).toEqual(
- // [
- // {
- // text: 'first',
- // index: 0,
- // stoppoint_id: 72,
- // edit: false,
- // for_boarding: 'normal',
- // for_alighting: 'normal',
- // olMap: {
- // isOpened: false,
- // json: {}
- // }
- // }
- // ]
- // )
- // })
+ it_should_handle(
+ {type: 'DELETE_STOP', index: 1},
+ [stop_point_1, stop_point_3]
+ )
- it('should handle UPDATE_INPUT_VALUE', () => {
- expect(
- stopPointsReducer(state, {
- type: 'UPDATE_INPUT_VALUE',
- index: 0,
- edit: false,
- text: {
- text: "new value",
- name: 'new',
- stoparea_id: 1,
- user_objectid: "1234",
- longitude: 123,
- latitude: 123,
- registration_number: '0',
- city_name: 'city',
- area_type: 'area',
- short_name: 'new',
- comment: 'newcomment'
- }
- })
- ).toEqual(
- [
- {
- text: 'new value',
- name: 'new',
- index: 0,
- stoppoint_id: 72,
- edit: false,
- stoparea_id: 1,
- for_boarding: 'normal',
- for_alighting: 'normal',
- user_objectid: "1234",
- longitude: 123,
- latitude: 123,
- registration_number: '0',
- city_name: 'city',
- area_type: 'area',
- short_name: 'new',
- comment: 'newcomment',
- olMap: {
- isOpened: false,
- json: {}
- }
- },
- {
- text: 'second',
- index: 1,
- stoppoint_id: 73,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- }
- ]
- )
- })
+ let text = {
+ text: "new value",
+ name: 'new',
+ stoparea_id: 1,
+ user_objectid: "1234",
+ longitude: 123,
+ latitude: 123,
+ registration_number: '0',
+ city_name: 'city',
+ area_type: 'area',
+ short_name: 'new',
+ comment: 'newcomment'
+ }
+ it_should_handle(
+ {type: 'UPDATE_INPUT_VALUE', index: 0, text: text},
+ [
+ update_stop_point(stop_point_1, text),
+ stop_point_2,
+ stop_point_3
+ ]
+ )
- it('should handle UPDATE_SELECT_VALUE', () => {
- expect(
- stopPointsReducer(state, {
- type :'UPDATE_SELECT_VALUE',
- select_id: 'for_boarding',
- select_value: 'prohibited',
- index: 0
- })
- ).toEqual(
- [
- {
- text: 'first',
- index: 0,
- stoppoint_id: 72,
- edit: false,
- for_boarding: 'prohibited',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- },
- {
- text: 'second',
- index: 1,
- stoppoint_id: 73,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- }
- ]
- )
- })
+ it_should_handle(
+ {type: 'UPDATE_SELECT_VALUE', index: 0, select_id: 'for_boarding', select_value: 'prohibited'},
+ [
+ update_stop_point(stop_point_1, {for_boarding: 'prohibited'}),
+ stop_point_2,
+ stop_point_3
+ ]
+ )
- it('should handle TOGGLE_MAP', () => {
- expect(
- stopPointsReducer(state, {
- type: 'TOGGLE_MAP',
- index: 0
- })
- ).toEqual(
- [
- {
+ it_should_handle(
+ {type: 'TOGGLE_MAP', index: 0},
+ [
+ update_stop_point(stop_point_1, {olMap: {
+ isOpened: true,
+ json: {
text: 'first',
index: 0,
stoppoint_id: 72,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
- olMap: {
- isOpened: true,
- json: {
- text: 'first',
- index: 0,
- stoppoint_id: 72,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: undefined
- }
- }
- },
- {
- text: 'second',
- index: 1,
- stoppoint_id: 73,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
+ olMap: undefined
}
- ]
- )
- })
+ }}),
+ stop_point_2,
+ stop_point_3
+ ]
+ )
- it('should handle TOGGLE_EDIT', () => {
- expect(
- stopPointsReducer(state, {
- type: 'TOGGLE_EDIT',
- index: 0
- })
- ).toEqual(
- [
- {
- text: 'first',
- index: 0,
- stoppoint_id: 72,
- edit: true,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- },
- {
- text: 'second',
- index: 1,
- stoppoint_id: 73,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- }
- ]
- )
- })
+ it_should_handle(
+ {type: 'TOGGLE_EDIT', index: 0},
+ [
+ update_stop_point(stop_point_1, {edit: true}),
+ stop_point_2,
+ stop_point_3
+ ]
+ )
- it('should handle SELECT_MARKER', () => {
- let openedMapState = [
- {
- text: 'first',
- index: 0,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: true,
- json: {}
- }
- },
- {
- text: 'second',
- index: 1,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
+ let openedMapState = [
+ update_stop_point(stop_point_1, {
+ olMap: {
+ isOpened: true,
+ json: {}
}
- ]
- expect(
- stopPointsReducer(openedMapState, {
- type: 'SELECT_MARKER',
- index: 0,
- data: fakeData
- })
- ).toEqual(
- [
- {
- text: 'first',
- index: 0,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: true,
- json: fakeData
- }
- },
- {
- text: 'second',
- index: 1,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- }
- ]
- )
- })
+ }),
+ stop_point_2,
+ stop_point_3
+ ]
- it('should handle UNSELECT_MARKER', () => {
- let openedMapState = [
- {
- text: 'first',
- index: 0,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
+ it_should_handle(
+ {type: 'SELECT_MARKER', index: 0, data: fakeData},
+ [
+ update_stop_point(stop_point_1, {
olMap: {
isOpened: true,
- json: {}
- }
- },
- {
- text: 'second',
- index: 1,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
+ json: fakeData
+ }
+ }),
+ stop_point_2,
+ stop_point_3
+ ],
+ openedMapState
+ )
+
+ it_should_handle(
+ {type: 'UNSELECT_MARKER', index: 0},
+ [
+ update_stop_point(stop_point_1, {
olMap: {
- isOpened: false,
+ isOpened: true,
json: {}
}
- }
- ]
-
- expect(
- stopPointsReducer(openedMapState, {
- type: 'UNSELECT_MARKER',
- index: 0
- })
- ).toEqual(
- [
- {
- text: 'first',
- index: 0,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: true,
- json: {}
- }
- },
- {
- text: 'second',
- index: 1,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- }
- ]
- )
- })
+ }),
+ stop_point_2,
+ stop_point_3
+ ],
+ openedMapState
+ )
})
diff --git a/spec/javascript/time_table/reducers/timetable_spec.js b/spec/javascript/time_table/reducers/timetable_spec.js
index f0f9eaa8c..926fb2687 100644
--- a/spec/javascript/time_table/reducers/timetable_spec.js
+++ b/spec/javascript/time_table/reducers/timetable_spec.js
@@ -22,8 +22,6 @@ let json = {
time_table_dates: time_table_dates
}
-
-
describe('timetable reducer with empty state', () => {
beforeEach(() => {
state = {
@@ -87,6 +85,7 @@ describe('timetable reducer with filled state', () => {
periode_range: periode_range,
currentPage: current_periode_range
}
+ jsdom.reconfigure({url: "http://example.com/foo/bar"})
expect(
timetableReducer(state, {
type: 'GO_TO_PREVIOUS_PAGE',
diff --git a/spec/javascript/vehicle_journeys/actions_spec.js b/spec/javascript/vehicle_journeys/actions_spec.js
index 74765a7ef..9710d833c 100644
--- a/spec/javascript/vehicle_journeys/actions_spec.js
+++ b/spec/javascript/vehicle_journeys/actions_spec.js
@@ -1,6 +1,7 @@
import actions from '../../../app/javascript/vehicle_journeys/actions/index'
const dispatch = function(){}
+window.fetch = function(){return Promise.resolve()}
const currentPage = 1
describe('when cannot fetch api', () => {
@@ -37,11 +38,53 @@ describe('when clicking on add button', () => {
expect(actions.openCreateModal()).toEqual(expectedAction)
})
})
+describe('when validating the form', () => {
+ it('should check that non-commercial stops have passing time', () => {
+ let state = [{
+ vehicle_journey_at_stops: [{
+ area_kind: "non_commercial",
+ departure_time: {
+ hour: "00",
+ minute: "00"
+ }
+ }]
+ }]
+
+ expect(actions.validate(dispatch, state)).toEqual(true)
+
+ state = [{
+ vehicle_journey_at_stops: [{
+ area_kind: "non_commercial",
+ departure_time: {
+ hour: "00",
+ minute: "01"
+ }
+ }]
+ }]
+
+ expect(actions.validate(dispatch, state)).toEqual(true)
+ })
+
+ it('should not check that commercial stops', () => {
+ let state = [{
+ vehicle_journey_at_stops: [{
+ area_kind: "commercial",
+ departure_time: {
+ hour: "00",
+ minute: "00"
+ }
+ }]
+ }]
+
+ expect(actions.validate(dispatch, state)).toEqual(true)
+ })
+})
describe('when using select2 to pick a journey pattern', () => {
it('should create an action to select a journey pattern inside modal', () => {
let selectedJP = {
id: 1,
object_id: 2,
+ short_id: 2,
name: 'test',
published_name: 'test',
stop_area_short_descriptions: ['test']
@@ -51,6 +94,7 @@ describe('when using select2 to pick a journey pattern', () => {
selectedItem:{
id: selectedJP.id,
objectid: selectedJP.object_id,
+ short_id: selectedJP.object_id,
name: selectedJP.name,
published_name: selectedJP.published_name,
stop_areas: selectedJP.stop_area_short_descriptions
@@ -174,15 +218,55 @@ describe('when clicking on validate button inside shifting modal', () => {
})
})
describe('when clicking on validate button inside editing modal', () => {
- it('should create an action to update a vehiclejourney', () => {
- const data = {}
- const selectedCompany = {}
- const expectedAction = {
- type: 'EDIT_VEHICLEJOURNEY',
- data,
- selectedCompany
- }
- expect(actions.editVehicleJourney(data, selectedCompany)).toEqual(expectedAction)
+ context("with invalid data", () => {
+ it('should not validate the data', () => {
+ const data = {
+ foo: {
+ validity: { valid: false }
+ },
+ bar: {
+ validity: { valid: true }
+ }
+ }
+
+ expect(actions.validateFields(data)).toBeFalsy
+ })
+ })
+
+ context("with data not needing validation", () => {
+ it('should validate the data', () => {
+ const data = {
+ foo: {}
+ }
+
+ expect(actions.validateFields(data)).toBeTruthy
+ })
+ })
+ context("with valid data", () => {
+ it('should validate the data', () => {
+ const data = {
+ foo: {
+ validity: { valid: true }
+ },
+ bar: {
+ validity: { valid: true }
+ }
+ }
+
+ expect(actions.validateFields(data)).toBeTruthy
+ })
+ })
+ context("once the data has been validated", () => {
+ it('should create an action to update a vehiclejourney', () => {
+ const data = {}
+ const selectedCompany = {}
+ const expectedAction = {
+ type: 'EDIT_VEHICLEJOURNEY',
+ data,
+ selectedCompany
+ }
+ expect(actions.editVehicleJourney(data, selectedCompany)).toEqual(expectedAction)
+ })
})
})
describe('when clicking on validate button inside duplicating modal', () => {
@@ -209,6 +293,13 @@ describe('when clicking on edit notes modal', () => {
expect(actions.openNotesEditModal(vehicleJourney)).toEqual(expectedAction)
})
})
+
+ // ___ ___ ___ _____ _ _ ___ _____ ___ ___
+ // | __/ _ \ / _ \_ _| \| |/ _ \_ _| __/ __|
+ // | _| (_) | (_) || | | .` | (_) || | | _|\__ \
+ // |_| \___/ \___/ |_| |_|\_|\___/ |_| |___|___/
+ //
+
describe('when clicking on a footnote button inside footnote modal', () => {
it('should create an action to toggle this footnote', () => {
const footnote = {}, isShown = true
@@ -230,6 +321,13 @@ describe('when clicking on validate button inside footnote modal', () => {
expect(actions.editVehicleJourneyNotes(footnotes)).toEqual(expectedAction)
})
})
+
+ // _____ ___ __ __ ___ _____ _ ___ _ ___ ___
+ // |_ _|_ _| \/ | __|_ _/_\ | _ ) | | __/ __|
+ // | | | || |\/| | _| | |/ _ \| _ \ |__| _|\__ \
+ // |_| |___|_| |_|___| |_/_/ \_\___/____|___|___/
+ //
+
describe('when clicking on calendar button in toolbox', () => {
it('should create an action to open calendar modal', () => {
const vehicleJourneys = []
@@ -288,6 +386,83 @@ describe('when using select2 to pick a timetable', () => {
expect(actions.selectTTCalendarsModal(selectedTT)).toEqual(expectedAction)
})
})
+
+ // ___ _ _ ___ ___ _ _ _ ___ ___
+ // | _ \ | | | _ \/ __| || | /_\ / __| __|
+ // | _/ |_| | / (__| __ |/ _ \\__ \ _|
+ // |_| \___/|_|_\\___|_||_/_/_\_\___/___|__
+ // \ \ / /_ _| \| | \ / _ \ \ / / __|
+ // \ \/\/ / | || .` | |) | (_) \ \/\/ /\__ \
+ // \_/\_/ |___|_|\_|___/ \___/ \_/\_/ |___/
+ //
+
+describe('when clicking on purchase window button in toolbox', () => {
+ it('should create an action to open purchase window modal', () => {
+ const vehicleJourneys = []
+ const expectedAction = {
+ type: 'EDIT_PURCHASE_WINDOWS_VEHICLEJOURNEY_MODAL',
+ vehicleJourneys
+ }
+ expect(actions.openPurchaseWindowsEditModal(vehicleJourneys)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on delete button next to a purchase window inside modal', () => {
+ it('should create an action to delete purchase window from selected vehicle journeys', () => {
+ const purchaseWindow = {}
+ const expectedAction = {
+ type: 'DELETE_PURCHASE_WINDOW_MODAL',
+ purchaseWindow
+ }
+ expect(actions.deletePurchaseWindowsModal(purchaseWindow)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on validate button inside purchase windows modal', () => {
+ it('should create an action to update vj purchase windows', () => {
+ const vehicleJourneys = []
+ const purchase_windows = []
+ const expectedAction = {
+ type: 'EDIT_VEHICLEJOURNEYS_PURCHASE_WINDOWS',
+ vehicleJourneys,
+ purchase_windows
+ }
+ expect(actions.editVehicleJourneyPurchaseWindows(vehicleJourneys, purchase_windows)).toEqual(expectedAction)
+ })
+})
+describe('when clicking on add button inside purchase windows modal', () => {
+ it('should create an action to add the selected purchase window to preselected vjs', () => {
+ const expectedAction = {
+ type: 'ADD_SELECTED_PURCHASE_WINDOW',
+ }
+ expect(actions.addSelectedPurchaseWindow()).toEqual(expectedAction)
+ })
+})
+describe('when using select2 to pick a purchase window', () => {
+ it('should create an action to select a purchase window inside modal', () => {
+ let selectedTT = {
+ id: 1,
+ objectid: 2,
+ name: 'test',
+ color: 'color',
+ }
+ const expectedAction = {
+ type: 'SELECT_PURCHASE_WINDOW_MODAL',
+ selectedItem:{
+ id: selectedTT.id,
+ objectid: selectedTT.objectid,
+ name: selectedTT.name,
+ color: "color"
+ }
+ }
+ expect(actions.selectPurchaseWindowsModal(selectedTT)).toEqual(expectedAction)
+ })
+})
+
+ // ___ ___ _ _____ ___ ___ ___
+ // | __|_ _| ||_ _| __| _ \/ __|
+ // | _| | || |__| | | _|| /\__ \
+ // |_| |___|____|_| |___|_|_\|___/
+ //
+
describe('when clicking on reset button inside query filters', () => {
it('should create an action to reset the query filters', () => {
const expectedAction = {
@@ -447,3 +622,84 @@ describe('when using select2 to unselect a company', () => {
expect(actions.unselect2Company()).toEqual(expectedAction)
})
})
+
+describe('actions.adjustSchedule', () => {
+ set('time', () => {
+ return {
+ hour: 9,
+ minute: 30
+ }
+ })
+ context('when editing the departure time', () => {
+ set('action', () => { return { isDeparture: true } })
+ context('with a positive delta', () => {
+ set('schedule', () => {
+ return {
+ departure_time: time,
+ arrival_time: time
+ }
+ })
+ it('should do nothing', () => {
+ expect(actions.adjustSchedule(action, schedule)).toEqual(schedule)
+ })
+ }),
+ context('with a delta < 0', () => {
+ set('departure_time', () => {
+ return {
+ hour: time.hour,
+ minute: time.minute - 1
+ }
+ })
+ set('schedule', () => {
+ return {
+ departure_time: departure_time,
+ arrival_time: time
+ }
+ })
+ it('should adjust arrival time', () => {
+ let expected = {
+ departure_time: departure_time,
+ arrival_time: departure_time,
+ delta: 0
+ }
+ expect(actions.adjustSchedule(action, schedule)).toEqual(expected)
+ })
+ })
+ }),
+ context('when editing the arrival time', () => {
+ set('action', () => { return { isDeparture: false } })
+ context('with a positive delta', () => {
+ set('schedule', () => {
+ return {
+ departure_time: time,
+ arrival_time: time
+ }
+ })
+ it('should do nothing', () => {
+ expect(actions.adjustSchedule(action, schedule)).toEqual(schedule)
+ })
+ }),
+ context('with a delta < 0', () => {
+ set('arrival_time', () => {
+ return {
+ hour: time.hour,
+ minute: time.minute + 1
+ }
+ })
+ set('schedule', () => {
+ return {
+ departure_time: time,
+ arrival_time: arrival_time
+ }
+ })
+ it('should adjust departure time', () => {
+ let expected = {
+ departure_time: arrival_time,
+ arrival_time: arrival_time,
+ delta: 0
+ }
+ expect(actions.adjustSchedule(action, schedule)).toEqual(expected)
+ })
+ })
+ })
+})
diff --git a/spec/javascript/vehicle_journeys/components/CustomFieldsInputs_spec.js b/spec/javascript/vehicle_journeys/components/CustomFieldsInputs_spec.js
new file mode 100644
index 000000000..4f8d42d2d
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/components/CustomFieldsInputs_spec.js
@@ -0,0 +1,41 @@
+import React, { Component } from 'react'
+import CustomFieldsInputs from '../../../../app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs'
+import renderer from 'react-test-renderer'
+require('select2')
+
+describe('CustomFieldsInputs', () => {
+ set('values', () => {
+ return {}
+ })
+
+ set('component', () => {
+ let inputs = renderer.create(
+ <CustomFieldsInputs
+ values={values}
+ disabled={false}
+ onUpdate={()=>{}}
+ />
+ ).toJSON()
+
+ return inputs
+ })
+
+ it('should match the snapshot', () => {
+ expect(component).toMatchSnapshot()
+ })
+
+ // context('with fields', () => {
+ // set('values', () => {
+ // return {
+ // foo: {
+ // options: { list_values: ["", "1", "2"] },
+ // field_type: "list",
+ // name: "test"
+ // }
+ // }
+ // })
+ // it('should match the snapshot', () => {
+ // expect(component).toMatchSnapshot()
+ // })
+ // })
+})
diff --git a/spec/javascript/vehicle_journeys/components/VehicleJourneys_spec.js b/spec/javascript/vehicle_journeys/components/VehicleJourneys_spec.js
new file mode 100644
index 000000000..2a84cb9ca
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/components/VehicleJourneys_spec.js
@@ -0,0 +1,87 @@
+import React, { Component } from 'react'
+import VehicleJourneys from '../../../../app/javascript/vehicle_journeys/components/VehicleJourneys'
+import renderer from 'react-test-renderer'
+import fs from 'fs'
+
+import I18n from '../../../../public/javascripts/i18n'
+import decorateI18n from '../../../../app/assets/javascripts/i18n/extended.coffee'
+window.I18n = decorateI18n(I18n)
+I18n.locale = "fr"
+eval(fs.readFileSync('./public/javascripts/translations.js')+'')
+
+describe('stopPointHeader', () => {
+ set('features', () => {
+ return {}
+ })
+ set('component', () => {
+ let props = {
+ status: {},
+ filters: {
+ permissions: {},
+ features: features
+ },
+ onLoadFirstPage: ()=>{},
+ onUpdateTime: ()=>{},
+ onSelectVehicleJourney: ()=>{},
+ stopPointsList: [stop_point, same_city_stop_point, other_country_stop_point],
+ vehicleJourneys: []
+ }
+ let list = renderer.create(
+ <VehicleJourneys
+ status={props.status}
+ filters={props.filters}
+ onLoadFirstPage={props.onLoadFirstPage}
+ onUpdateTime={props.onUpdateTime}
+ onSelectVehicleJourney={props.onSelectVehicleJourney}
+ stopPointsList={props.stopPointsList}
+ vehicleJourneys={props.vehicleJourneys}
+ />
+ ).toJSON()
+
+ return list
+ })
+
+ set('stop_point', () => {
+ return {
+ name: "Stop point",
+ city_name: "City Name",
+ zip_code: "12345",
+ country_code: "FR",
+ country_name: "france",
+ object_id: "sp-FR"
+ }
+ })
+
+ set('same_city_stop_point', () => {
+ return {
+ name: "Antother stop point",
+ city_name: stop_point.city_name,
+ zip_code: stop_point.zip_code,
+ country_code: stop_point.country_code,
+ country_name: stop_point.country_name,
+ object_id: stop_point.object_id + "-2"
+ }
+ })
+
+ set('other_country_stop_point', () => {
+ return {
+ name: "Antother stop point",
+ city_name: "New York",
+ zip_code: "232323",
+ country_code: "US",
+ country_name: "USA",
+ object_id: "sp-USA"
+ }
+ })
+ it('should display the city name', () => {
+ expect(component).toMatchSnapshot()
+ })
+ context('with the "long_distance_routes" feature', () => {
+ set('features', () => {
+ return { long_distance_routes: true }
+ })
+ it('should display the country name', () => {
+ expect(component).toMatchSnapshot()
+ })
+ })
+})
diff --git a/spec/javascript/vehicle_journeys/components/__snapshots__/CustomFieldsInputs_spec.js.snap b/spec/javascript/vehicle_journeys/components/__snapshots__/CustomFieldsInputs_spec.js.snap
new file mode 100644
index 000000000..c93ec0097
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/components/__snapshots__/CustomFieldsInputs_spec.js.snap
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`CustomFieldsInputs should match the snapshot 1`] = `<div />`;
diff --git a/spec/javascript/vehicle_journeys/components/__snapshots__/VehicleJourneys_spec.js.snap b/spec/javascript/vehicle_journeys/components/__snapshots__/VehicleJourneys_spec.js.snap
new file mode 100644
index 000000000..cdd34cbbd
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/components/__snapshots__/VehicleJourneys_spec.js.snap
@@ -0,0 +1,181 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`stopPointHeader should display the city name 1`] = `
+<div
+ className="row"
+>
+ <div
+ className="col-lg-12"
+ >
+ <div
+ className="table table-2entries mt-sm mb-sm no_result"
+ >
+ <div
+ className="t2e-head w20"
+ >
+ <div
+ className="th"
+ >
+ <div
+ className="strong mb-xs"
+ >
+ ID Course
+ </div>
+ <div>
+ Nom Course
+ </div>
+ <div>
+ ID Mission
+ </div>
+ <div>
+ transporteur
+ </div>
+ <div>
+ calendrier
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className="headlined"
+ data-headline="City Name"
+ title="City Name (12345)"
+ >
+ <span>
+ <span>
+ Stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className=""
+ data-headline=""
+ title="City Name (12345)"
+ >
+ <span>
+ <span>
+ Antother stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className="headlined"
+ data-headline="New York"
+ title="New York (232323)"
+ >
+ <span>
+ <span>
+ Antother stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ className="t2e-item-list w80"
+ >
+ <div />
+ </div>
+ </div>
+ </div>
+</div>
+`;
+
+exports[`stopPointHeader with the "long_distance_routes" feature should display the country name 1`] = `
+<div
+ className="row"
+>
+ <div
+ className="col-lg-12"
+ >
+ <div
+ className="table table-2entries mt-sm mb-sm no_result"
+ >
+ <div
+ className="t2e-head w20"
+ >
+ <div
+ className="th"
+ >
+ <div
+ className="strong mb-xs"
+ >
+ ID Course
+ </div>
+ <div>
+ Nom Course
+ </div>
+ <div>
+ ID Mission
+ </div>
+ <div>
+ transporteur
+ </div>
+ <div>
+ calendrier
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className="headlined"
+ data-headline="france"
+ title="City Name (12345)"
+ >
+ <span>
+ <span>
+ Stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className=""
+ data-headline=""
+ title="City Name (12345)"
+ >
+ <span>
+ <span>
+ Antother stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ <div
+ className="td"
+ >
+ <div
+ className="headlined"
+ data-headline="USA"
+ title="New York (232323)"
+ >
+ <span>
+ <span>
+ Antother stop point
+ </span>
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ className="t2e-item-list w80"
+ >
+ <div />
+ </div>
+ </div>
+ </div>
+</div>
+`;
diff --git a/spec/javascript/vehicle_journeys/reducers/modal_spec.js b/spec/javascript/vehicle_journeys/reducers/modal_spec.js
index 69de9168b..ee50f091b 100644
--- a/spec/javascript/vehicle_journeys/reducers/modal_spec.js
+++ b/spec/javascript/vehicle_journeys/reducers/modal_spec.js
@@ -91,6 +91,12 @@ describe('modal reducer', () => {
).toEqual(newState)
})
+ // _____ ___ __ __ ___ _____ _ ___ _ ___ ___
+ // |_ _|_ _| \/ | __|_ _/_\ | _ ) | | __/ __|
+ // | | | || |\/| | _| | |/ _ \| _ \ |__| _|\__ \
+ // |_| |___|_| |_|___| |_/_/ \_\___/____|___|___/
+ //
+
it('should handle EDIT_CALENDARS_VEHICLEJOURNEY_MODAL', () => {
let vehicleJourneys = []
let modalPropsResult = {
@@ -158,14 +164,89 @@ describe('modal reducer', () => {
).toEqual(newState)
})
+ // ___ _ _ ___ ___ _ _ _ ___ ___
+ // | _ \ | | | _ \/ __| || | /_\ / __| __|
+ // | _/ |_| | / (__| __ |/ _ \\__ \ _|
+ // |_| \___/|_|_\\___|_||_/_/_\_\___/___|__
+ // \ \ / /_ _| \| | \ / _ \ \ / / __|
+ // \ \/\/ / | || .` | |) | (_) \ \/\/ /\__ \
+ // \_/\_/ |___|_|\_|___/ \___/ \_/\_/ |___/
+ //
+
+ it('should handle EDIT_PURCHASE_WINDOWS_VEHICLEJOURNEY_MODAL', () => {
+ let vehicleJourneys = []
+ let modalPropsResult = {
+ vehicleJourneys: [],
+ purchase_windows: []
+ }
+ expect(
+ modalReducer(state, {
+ type: 'EDIT_PURCHASE_WINDOWS_VEHICLEJOURNEY_MODAL',
+ vehicleJourneys
+ })
+ ).toEqual(Object.assign({}, state, {type: 'purchase_windows_edit', modalProps: modalPropsResult}))
+ })
+
+ it('should handle SELECT_PURCHASE_WINDOW_MODAL', () => {
+ let newModalProps = {selectedPurchaseWindow : {id: 1}}
+ expect(
+ modalReducer(state, {
+ type: 'SELECT_PURCHASE_WINDOW_MODAL',
+ selectedItem: {id: 1}
+ })
+ ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ })
+
+ it('should handle ADD_SELECTED_PURCHASE_WINDOW', () => {
+ let fakeWindows = [{'test': 'test'}, {'test 2': 'test 2'}]
+ let newWindows = [{'test': 'test'}, {'test 2': 'test 2'}, {'add': 'add'}]
+ let fakeVehicleJourneys= [{purchase_windows: fakeWindows}, {purchase_windows: newWindows}]
+ state.modalProps.vehicleJourneys = fakeVehicleJourneys
+ state.modalProps.purchase_windows = fakeWindows
+ state.modalProps.selectedPurchaseWindow = {'add': 'add'}
+ let newState = {
+ type: '',
+ modalProps:{
+ vehicleJourneys: fakeVehicleJourneys,
+ purchase_windows: [{'test': 'test'},{'test 2': 'test 2'},{'add': 'add'}],
+ selectedPurchaseWindow: {'add': 'add'}
+ },
+ confirmModal: {}
+ }
+ expect(
+ modalReducer(state, {
+ type: 'ADD_SELECTED_PURCHASE_WINDOW',
+ })
+ ).toEqual(newState)
+ })
+
+ it('should handle DELETE_PURCHASE_WINDOW_MODAL', () => {
+ let deletableWindow = {'delete': 'delete'}
+ let fakeWindows = [{'test': 'test'}, {'test 2': 'test 2'}, deletableWindow]
+ let newWindows = [{'test': 'test'}, {'test 2': 'test 2'}]
+ let fakeVehicleJourneys= [{purchase_windows: fakeWindows}, {purchase_windows: newWindows}]
+ state.modalProps = Object.assign({}, state.modalProps,{vehicleJourneys : fakeVehicleJourneys, purchase_windows: fakeWindows })
+ let newState = {
+ // for the sake of the test, no need to specify the type
+ type: '',
+ modalProps:{vehicleJourneys: [{purchase_windows: newWindows},{purchase_windows: newWindows}], purchase_windows: newWindows},
+ confirmModal: {}
+ }
+ expect(
+ modalReducer(state, {
+ type: 'DELETE_PURCHASE_WINDOW_MODAL',
+ purchaseWindow: deletableWindow
+ })
+ ).toEqual(newState)
+ })
+
it('should handle SELECT_CP_EDIT_MODAL', () => {
- let newModalProps = {selectedCompany : {name: 'ALBATRANS'}}
expect(
modalReducer(state, {
type: 'SELECT_CP_EDIT_MODAL',
selectedItem: {name: 'ALBATRANS'}
- })
- ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ }).modalProps.vehicleJourney.company
+ ).toEqual({name: 'ALBATRANS'})
})
it('should handle UNSELECT_CP_EDIT_MODAL', () => {
@@ -173,7 +254,7 @@ describe('modal reducer', () => {
expect(
modalReducer(state, {
type: 'UNSELECT_CP_EDIT_MODAL'
- })
- ).toEqual(Object.assign({}, state, {modalProps: newModalProps}))
+ }).modalProps.vehicleJourney.company
+ ).toBe(undefined)
})
})
diff --git a/spec/javascript/vehicle_journeys/reducers/vehicle_journeys_spec.js b/spec/javascript/vehicle_journeys/reducers/vehicleJourneys_spec.js
index 1c2cc1577..0d7612a80 100644
--- a/spec/javascript/vehicle_journeys/reducers/vehicle_journeys_spec.js
+++ b/spec/javascript/vehicle_journeys/reducers/vehicleJourneys_spec.js
@@ -76,12 +76,12 @@ describe('vehicleJourneys reducer', () => {
let pristineVjasList = [{
delta : 0,
arrival_time : {
- hour: '00',
- minute: '00'
+ hour: "00",
+ minute: "00"
},
departure_time : {
- hour: '00',
- minute: '00'
+ hour: "00",
+ minute: "00"
},
stop_point_objectid: 'test',
stop_area_cityname: 'city',
@@ -89,7 +89,12 @@ describe('vehicleJourneys reducer', () => {
}]
let fakeData = {
published_journey_name: {value: 'test'},
- published_journey_identifier: {value : ''}
+ published_journey_identifier: {value : ''},
+ custom_fields: {
+ foo: {
+ value: 12
+ }
+ }
}
let fakeSelectedJourneyPattern = {id: "1"}
let fakeSelectedCompany = {name: "ALBATRANS"}
@@ -110,10 +115,205 @@ describe('vehicleJourneys reducer', () => {
objectid: '',
footnotes: [],
time_tables: [],
+ purchase_windows: [],
vehicle_journey_at_stops: pristineVjasList,
selected: false,
deletable: false,
transport_mode: 'undefined',
+ transport_submode: 'undefined',
+ custom_fields: {
+ foo: {
+ value: 12
+ }
+ }
+ }, ...state])
+ })
+
+ it('should handle ADD_VEHICLEJOURNEY with a start time and a fully timed JP', () => {
+ let pristineVjasList = [{
+ delta : 0,
+ arrival_time : {
+ hour: 22,
+ minute: 59
+ },
+ departure_time : {
+ hour: 22,
+ minute: 59
+ },
+ stop_point_objectid: 'test-1',
+ stop_area_cityname: 'city',
+ dummy: false
+ },
+ {
+ delta : 0,
+ arrival_time : {
+ hour: 23,
+ minute: 2
+ },
+ departure_time : {
+ hour: 23,
+ minute: 2
+ },
+ departure_day_offset: -1,
+ arrival_day_offset: -1,
+ stop_point_objectid: 'test-2',
+ stop_area_cityname: 'city',
+ dummy: false
+ },
+ {
+ delta : 0,
+ arrival_time : {
+ hour: "00",
+ minute: "00"
+ },
+ departure_time : {
+ hour: "00",
+ minute: "00"
+ },
+ stop_point_objectid: 'test-3',
+ stop_area_cityname: 'city',
+ dummy: true
+ },
+ {
+ delta : 0,
+ arrival_time : {
+ hour: 0,
+ minute: 32
+ },
+ departure_time : {
+ hour: 0,
+ minute: 32
+ },
+ stop_point_objectid: 'test-4',
+ stop_area_cityname: 'city',
+ dummy: false
+ }]
+ let fakeData = {
+ published_journey_name: {value: 'test'},
+ published_journey_identifier: {value : ''},
+ "start_time.hour": {value : '22'},
+ "start_time.minute": {value : '59'}
+ }
+ let fakeSelectedJourneyPattern = {
+ id: "1",
+ full_schedule: true,
+ stop_areas: [
+ {stop_area_short_description: {id: 1}},
+ {stop_area_short_description: {id: 2}},
+ {stop_area_short_description: {id: 4}},
+ ],
+ costs: {
+ "1-2": {
+ distance: 10,
+ time: 63
+ },
+ "2-4": {
+ distance: 10,
+ time: 30
+ }
+ }
+ }
+ let fakeSelectedCompany = {name: "ALBATRANS"}
+ expect(
+ vjReducer(state, {
+ type: 'ADD_VEHICLEJOURNEY',
+ data: fakeData,
+ selectedJourneyPattern: fakeSelectedJourneyPattern,
+ stopPointsList: [{object_id: 'test-1', city_name: 'city', stop_area_id: 1, id: 1, time_zone_offset: 0}, {object_id: 'test-2', city_name: 'city', stop_area_id: 2, id: 2, time_zone_offset: -3600}, {object_id: 'test-3', city_name: 'city', stop_area_id: 3, id: 3, time_zone_offset: 0}, {object_id: 'test-4', city_name: 'city', stop_area_id: 4, id: 4, time_zone_offset: 0}],
+ selectedCompany: fakeSelectedCompany
+ })
+ ).toEqual([{
+ journey_pattern: fakeSelectedJourneyPattern,
+ company: fakeSelectedCompany,
+ published_journey_name: 'test',
+ published_journey_identifier: '',
+ short_id: '',
+ objectid: '',
+ footnotes: [],
+ time_tables: [],
+ purchase_windows: [],
+ vehicle_journey_at_stops: pristineVjasList,
+ selected: false,
+ custom_fields: undefined,
+ deletable: false,
+ transport_mode: 'undefined',
+ transport_submode: 'undefined'
+ }, ...state])
+ })
+
+ it('should handle ADD_VEHICLEJOURNEY with a start time and a fully timed JP but the minutes are not set', () => {
+ let pristineVjasList = [{
+ delta : 0,
+ arrival_time : {
+ hour: 22,
+ minute: 0
+ },
+ departure_time : {
+ hour: 22,
+ minute: 0
+ },
+ stop_point_objectid: 'test-1',
+ stop_area_cityname: 'city',
+ dummy: false
+ },
+ {
+ delta : 0,
+ arrival_time : {
+ hour: 22,
+ minute: 3
+ },
+ departure_time : {
+ hour: 22,
+ minute: 3
+ },
+ stop_point_objectid: 'test-2',
+ stop_area_cityname: 'city',
+ dummy: false
+ }]
+ let fakeData = {
+ published_journey_name: {value: 'test'},
+ published_journey_identifier: {value : ''},
+ "start_time.hour": {value : '22'},
+ "start_time.minute": {value : ''}
+ }
+ let fakeSelectedJourneyPattern = {
+ id: "1",
+ full_schedule: true,
+ stop_areas: [
+ {stop_area_short_description: {id: 1}},
+ {stop_area_short_description: {id: 2}},
+ ],
+ costs: {
+ "1-2": {
+ distance: 10,
+ time: 63
+ },
+ }
+ }
+ let fakeSelectedCompany = {name: "ALBATRANS"}
+ expect(
+ vjReducer(state, {
+ type: 'ADD_VEHICLEJOURNEY',
+ data: fakeData,
+ selectedJourneyPattern: fakeSelectedJourneyPattern,
+ stopPointsList: [{object_id: 'test-1', city_name: 'city', stop_area_id: 1, id: 1, time_zone_offset: 0}, {object_id: 'test-2', city_name: 'city', stop_area_id: 2, id: 2, time_zone_offset: -3600}],
+ selectedCompany: fakeSelectedCompany
+ })
+ ).toEqual([{
+ journey_pattern: fakeSelectedJourneyPattern,
+ company: fakeSelectedCompany,
+ published_journey_name: 'test',
+ published_journey_identifier: '',
+ short_id: '',
+ objectid: '',
+ footnotes: [],
+ time_tables: [],
+ purchase_windows: [],
+ vehicle_journey_at_stops: pristineVjasList,
+ selected: false,
+ custom_fields: undefined,
+ deletable: false,
+ transport_mode: 'undefined',
transport_submode: 'undefined'
}, ...state])
})
@@ -240,12 +440,18 @@ describe('vehicleJourneys reducer', () => {
})
it('should handle EDIT_VEHICLEJOURNEY', () => {
+ let custom_fields = {
+ foo: {
+ value: 12
+ }
+ }
let fakeData = {
published_journey_name: {value : 'test'},
- published_journey_identifier: {value: 'test'}
+ published_journey_identifier: {value: 'test'},
+ custom_fields: {foo: {value: 12}}
}
let fakeSelectedCompany : {name : 'ALBATRANS'}
- let newVJ = Object.assign({}, state[0], {company: fakeSelectedCompany, published_journey_name: fakeData.published_journey_name.value, published_journey_identifier: fakeData.published_journey_identifier.value})
+ let newVJ = Object.assign({}, state[0], {company: fakeSelectedCompany, published_journey_name: fakeData.published_journey_name.value, published_journey_identifier: fakeData.published_journey_identifier.value, custom_fields})
expect(
vjReducer(state, {
type: 'EDIT_VEHICLEJOURNEY',
@@ -254,7 +460,6 @@ describe('vehicleJourneys reducer', () => {
).toEqual([newVJ, state[1]])
})
-
it('should handle EDIT_VEHICLEJOURNEYS_TIMETABLES', () => {
let newState = JSON.parse(JSON.stringify(state))
newState[0].time_tables = [fakeTimeTables[0]]
@@ -266,4 +471,16 @@ describe('vehicleJourneys reducer', () => {
})
).toEqual(newState)
})
+
+ it('should handle EDIT_VEHICLEJOURNEYS_PURCHASE_WINDOWS', () => {
+ let newState = JSON.parse(JSON.stringify(state))
+ newState[0].purchase_windows = [fakeTimeTables[0]]
+ expect(
+ vjReducer(state, {
+ type: 'EDIT_VEHICLEJOURNEYS_PURCHASE_WINDOWS',
+ vehicleJourneys: state,
+ purchase_windows: [fakeTimeTables[0]]
+ })
+ ).toEqual(newState)
+ })
})
diff --git a/spec/lib/af83/decorator/decorator_link_spec.rb b/spec/lib/af83/decorator/decorator_link_spec.rb
new file mode 100644
index 000000000..0b2939421
--- /dev/null
+++ b/spec/lib/af83/decorator/decorator_link_spec.rb
@@ -0,0 +1,79 @@
+RSpec.describe AF83::Decorator::Link, type: :decorator do
+ describe "#complete?" do
+ context "on a imcomplete link" do
+ it "should be false" do
+ expect(AF83::Decorator::Link.new.complete?).to be_falsy
+ expect(AF83::Decorator::Link.new(content: "foo").complete?).to be_falsy
+ expect(AF83::Decorator::Link.new(href: "foo").complete?).to be_falsy
+ end
+ end
+
+ context "on a complete link" do
+ it "should be true" do
+ expect(AF83::Decorator::Link.new(href: "foo", content: "foo").complete?).to be_truthy
+ end
+ end
+ end
+
+ describe "#class" do
+ let(:link){
+ AF83::Decorator::Link.new(href: "foo", content: "foo", class: "initial_class")
+ }
+
+ it "should override exisiting class" do
+ expect(link.html_options[:class]).to eq "initial_class"
+ link.class "new_class"
+ expect(link.html_options[:class]).to eq "new_class"
+ link.class = "another_class"
+ expect(link.html_options[:class]).to eq "another_class"
+ link.class = %w(foo bar)
+ expect(link.html_options[:class]).to eq "foo bar"
+ end
+ end
+
+ describe "#add_class" do
+ let(:link){
+ AF83::Decorator::Link.new(href: "foo", content: "foo", class: "initial_class")
+ }
+
+ it "should add to exisiting class" do
+ expect(link.html_options[:class]).to eq "initial_class"
+ link.add_class "new_class"
+ expect(link.html_options[:class]).to eq "initial_class new_class"
+ link.add_class "another_class"
+ expect(link.html_options[:class]).to eq "initial_class new_class another_class"
+ link.add_class %w(foo bar)
+ expect(link.html_options[:class]).to eq "initial_class new_class another_class foo bar"
+ end
+ end
+
+ describe "#type" do
+
+ let(:link){
+ AF83::Decorator::Link.new(href: "foo", content: "foo")
+ }
+
+ let(:context){
+ Class.new do
+ def h
+ Class.new do
+ def link_to *args
+ HTMLElement.new(:a, 'foo', {}).to_html
+ end
+ end.new
+ end
+ end.new
+ }
+
+ it "should allow for buttons" do
+ link.type = :button
+ expect(link.to_html).to match /\<button.*\<\/button\>/
+ end
+
+ it "should fallback to <a>" do
+ link.type = :spaghetti
+ link.bind_to_context context, :show
+ expect(link.to_html).to match /\<a.*\<\/a\>/
+ end
+ end
+end
diff --git a/spec/lib/af83/decorator/decorator_spec.rb b/spec/lib/af83/decorator/decorator_spec.rb
new file mode 100644
index 000000000..61a849b9d
--- /dev/null
+++ b/spec/lib/af83/decorator/decorator_spec.rb
@@ -0,0 +1,824 @@
+RSpec.describe AF83::Decorator, type: :decorator do
+ describe(:parse_options) do
+ let(:options){
+ {primary: true, secondary: %i(index show), policy: :blublu, weight: 12}
+ }
+ let(:link_options){
+ {foo: :foo, bar: :bar}
+ }
+ let(:args){ options.dup.update(link_options.dup) }
+ it "should separate options from link_options" do
+ _options, _link_options = AF83::Decorator.instance_decorator.send :parse_options, args
+ expect(_options).to eq({weight: 12})
+ link_options.each do |k, v|
+ expect(_link_options[k]).to eq v
+ end
+ expect(_link_options[:_groups][:primary]).to eq true
+ expect(_link_options[:_groups][:secondary]).to eq %i(index show)
+ expect(_link_options[:_policy]).to eq :blublu
+ end
+ end
+
+ link_should_match_options = ->(link, options){
+ options.each do |k, v|
+ expect(link.send(k)).to eq v
+ end
+ }
+
+ context "as an collection decorator" do
+ let(:link_options) do
+ {
+ href: "/foo/bar",
+ content: "Blublu"
+ }
+ end
+
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.action_link link_options
+ klass
+ end
+
+ let(:decorated) do
+ 3.times { create :line }
+ decorator.decorate(Chouette::Line.all)
+ end
+
+ it "should return the links" do
+ links = decorated.action_links
+ instance_exec links.first, link_options, &link_should_match_options
+ end
+ end
+
+ context "as an instance decorator" do
+ describe("with the actual decorator") do
+ before(:each) do
+ Draper::HelperProxy.any_instance.stub(:policy){
+ klass = Class.new do
+ def method_missing *args
+ true
+ end
+ end.new
+ }
+ end
+
+ let(:decorated) do
+ line = create :line
+ line.decorate(context: {line_referential: line.line_referential})
+ end
+
+ it "should return the links" do
+ expect{ decorated.action_links }.to_not raise_error
+ end
+ end
+
+ describe(:action_links) do
+ let(:decorated) do
+ obj = create :line
+ decorator.decorate(obj)
+ end
+
+ context "without links" do
+ let(:decorator) do
+ Class.new(AF83::Decorator)
+ end
+
+ it "should return no link" do
+ links = decorated.action_links
+ expect(links.size).to eq 0
+ end
+ end
+
+ context "with a single link" do
+ let(:link_options) do
+ {
+ href: "/foo/bar",
+ content: "Blublu"
+ }
+ end
+
+ context "incompletetly defined" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link href: "bar"
+ end
+ klass
+ end
+
+ it "should raise an error" do
+ expect{decorator}.to raise_error(AF83::Decorator::IncompleteLinkDefinition)
+ end
+ end
+
+ context "defined inline" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options
+ end
+ klass
+ end
+
+ it "should return the defined link" do
+ links = decorated.action_links
+ expect(links.size).to eq 1
+ instance_exec links.first, link_options, &link_should_match_options
+ end
+ end
+
+ context "defined in a block" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link do |l|
+ l.href link_options[:href]
+ l.content link_options[:content]
+ end
+ end
+ klass
+ end
+
+ it "should return the defined link" do
+ links = decorated.action_links
+ expect(links.size).to eq 1
+ instance_exec links.first, link_options, &link_should_match_options
+ end
+ end
+
+ context "with proc attributes" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link do |l|
+ l.href { context[:href] }
+ l.content "Blublu"
+ end
+ end
+ klass
+ end
+
+ let(:decorated) do
+ obj = create :line
+ decorator.decorate(obj, context: {href: link_options[:href]})
+ end
+
+ it "should return the defined link" do
+ links = decorated.action_links
+ expect(links.size).to eq 1
+ expect(links.first.href).to eq link_options[:href]
+ end
+ end
+
+ context "with a method attributes" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link do |l|
+ l.href "/foo/bar"
+ l.content "Blublu"
+ l.method :put
+ end
+ end
+ klass
+ end
+
+ let(:decorated) do
+ obj = create :line
+ decorator.decorate(obj, context: {href: link_options[:href]})
+ end
+
+ it "should return the defined method" do
+ links = decorated.action_links
+ expect(links.size).to eq 1
+ expect(links.first.method).to eq :put
+ end
+ end
+ end
+
+ context "with 2 links" do
+ let(:link_options_1) do
+ {
+ href: "/foo/bar",
+ content: "Blublu"
+ }
+ end
+
+ let(:link_options_2) do
+ {
+ href: "/foo/bar/baz",
+ content: "Foo"
+ }
+ end
+
+ context "without weight" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options_1
+ instance_decorator.action_link link_options_2
+ end
+ klass
+ end
+
+ it "should return links in the sequence they were defined" do
+ links = decorated.action_links
+ expect(links.size).to eq 2
+ instance_exec links.first, link_options_1, &link_should_match_options
+ instance_exec links.last, link_options_2, &link_should_match_options
+ end
+ end
+
+ context "with weight" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options_1.update(weight: 10)
+ instance_decorator.action_link link_options_2
+ end
+ klass
+ end
+
+ it "should return links in the correct sequence" do
+ links = decorated.action_links
+ expect(links.size).to eq 2
+ instance_exec links.first, link_options_2, &link_should_match_options
+ instance_exec links.last, link_options_1, &link_should_match_options
+ end
+ end
+
+ context "scoped by action" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options_1.update(action: :index)
+ instance_decorator.action_link link_options_2
+ end
+ klass
+ end
+
+ it "should only return links defined for the given action" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 1
+ instance_exec links.first, link_options_2, &link_should_match_options
+ end
+ end
+
+ context "with a policy" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link href: "foo", content: "foo", policy: :edit
+ end
+ klass
+ end
+
+ context "when the policy is not met" do
+ before(:each) do
+ Draper::HelperProxy.any_instance.stub(:policy){
+ klass = Class.new do
+ def edit?
+ false
+ end
+ end.new
+ }
+ end
+
+ it "should not return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 0
+ end
+ end
+
+ context "when the policy is met" do
+ before(:each) do
+ Draper::HelperProxy.any_instance.stub(:policy){
+ klass = Class.new do
+ def edit?
+ true
+ end
+ end.new
+ }
+ end
+
+ it "should not return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 1
+ end
+ end
+ end
+
+ context "with a feature" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link href: "foo", content: "foo", feature: :foo
+ end
+ klass
+ end
+
+ context "when the feature is not present" do
+ before(:each) do
+ Draper::HelperProxy.any_instance.stub(:has_feature?){false}
+ end
+
+ it "should not return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 0
+ end
+ end
+
+ context "when the feature is present" do
+ before(:each) do
+ Draper::HelperProxy.any_instance.stub(:has_feature?){true}
+ end
+
+ it "should not return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 1
+ end
+ end
+ end
+
+ context "with a condition" do
+ context "set with 'with_condition'" do
+ context "as a value" do
+ context "when the condition is true" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.with_condition true do
+ action_link href: "foo", content: "foo"
+ end
+ end
+ klass
+ end
+
+ it "should return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 1
+ end
+ end
+
+ context "when the condition is false" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.with_condition false do
+ action_link href: "foo", content: "foo"
+ end
+ end
+ klass
+ end
+
+ it "should not return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 0
+ end
+ end
+ end
+
+ context "as a Proc" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.with_condition ->{context[:show_link]} do
+ action_link href: "foo", content: "foo"
+ end
+ end
+ klass
+ end
+
+ context "when the condition is true" do
+ let(:decorated) do
+ obj = create :line
+ decorator.decorate(obj, context: {show_link: true})
+ end
+
+ it "should return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 1
+ end
+ end
+
+ context "when the condition is false" do
+ let(:decorated) do
+ obj = create :line
+ decorator.decorate(obj, context: {show_link: false})
+ end
+
+ it "should not return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 0
+ end
+ end
+ end
+ end
+
+ context "set inline" do
+ context "as a value" do
+ context "when the condition is true" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options_1.update(if: true)
+ end
+ klass
+ end
+
+ it "should return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 1
+ end
+ end
+
+ context "when the condition is false" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options_1.update(if: false)
+ end
+ klass
+ end
+
+ it "should not return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 0
+ end
+ end
+ end
+
+ context "as a Proc" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options_1.update(if: ->{context[:show_link]})
+ end
+ klass
+ end
+
+ context "when the condition is true" do
+ let(:decorated) do
+ obj = create :line
+ decorator.decorate(obj, context: {show_link: true})
+ end
+
+ it "should return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 1
+ end
+ end
+
+ context "when the condition is false" do
+ let(:decorated) do
+ obj = create :line
+ decorator.decorate(obj, context: {show_link: false})
+ end
+
+ it "should not return the link" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 0
+ end
+ end
+ end
+ end
+ end
+
+ context "scoped by action" do
+ context "with a single action" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options_1.update(action: :index)
+ instance_decorator.action_link link_options_2
+ end
+ klass
+ end
+
+ it "should only return links defined for the given action" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 1
+ instance_exec links.first, link_options_2, &link_should_match_options
+ end
+ end
+
+ context "with several actions" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options_1.update(actions: %i(index edit))
+ instance_decorator.action_link link_options_2.update(actions: %i(show edit))
+ end
+ klass
+ end
+
+ it "should only return links defined for the given action" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 1
+ instance_exec links.first, link_options_2, &link_should_match_options
+ end
+ end
+
+ context "with the keyword 'on'" do
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options_1.update(on: %i(index edit))
+ instance_decorator.action_link link_options_2.update(on: :show)
+ end
+ klass
+ end
+
+ it "should only return links defined for the given action" do
+ links = decorated.action_links(:show)
+ expect(links.size).to eq 1
+ instance_exec links.first, link_options_2, &link_should_match_options
+ end
+ end
+ end
+ end
+ end
+
+ describe '#primary' do
+ let(:decorator) do
+ Class.new(AF83::Decorator)
+ end
+
+ let(:decorated) do
+ obj = create :line
+ decorator.decorate(obj)
+ end
+
+ it "should return a new object everytime" do
+ actions = decorated.action_links
+ primary = actions.primary
+ expect(actions.options[:groups]).to be_nil
+ expect(primary.options[:groups]).to_not be_nil
+ end
+ end
+
+ describe(:primary_links) do
+ let(:decorated) do
+ obj = create :line
+ decorator.decorate(obj)
+ end
+
+ context "without links" do
+ let(:decorator) do
+ Class.new(AF83::Decorator)
+ end
+
+ it "should return no link" do
+ links = decorated.action_links
+ expect(links.size).to eq 0
+ end
+ end
+
+ context "with a single link" do
+ let(:link_options) do
+ {
+ href: "/foo/bar/baz",
+ content: "Blublu",
+ primary: primary
+ }
+ end
+
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options
+ end
+ klass
+ end
+
+ context "always primary" do
+ let(:primary){ true }
+
+ it "should return the link" do
+ links = decorated.primary_links(:show)
+ expect(links.size).to eq 1
+ end
+ end
+
+ context "primary on this action" do
+ let(:primary){ :show }
+
+ it "should return the link" do
+ links = decorated.primary_links(:show)
+ expect(links.size).to eq 1
+ end
+ end
+
+ context "primary on this action among others" do
+ let(:primary){ %i(show edit) }
+
+ it "should return the link" do
+ links = decorated.action_links(:show, group: :primary)
+ expect(links.size).to eq 1
+ end
+ end
+
+ context "primary on other actions" do
+ let(:primary){ %i(index edit) }
+
+ it "should not return the link" do
+ links = decorated.action_links(:show, group: :primary)
+ expect(links.size).to eq 0
+ end
+ end
+
+ context "primary on another action" do
+ let(:primary){ :index }
+
+ it "should not return the link" do
+ links = decorated.primary_links(:show)
+ expect(links.size).to eq 0
+ end
+ end
+
+ context "never primary" do
+ let(:primary){ nil }
+
+ it "should not return the link" do
+ links = decorated.primary_links(:show)
+ expect(links.size).to eq 0
+ end
+ end
+ end
+ end
+
+ describe("in a group") do
+ let(:decorated) do
+ obj = create :line
+ decorator.decorate(obj)
+ end
+
+ context "without links" do
+ let(:decorator) do
+ Class.new(AF83::Decorator)
+ end
+
+ it "should return no link" do
+ links = decorated.action_links
+ expect(links.size).to eq 0
+ end
+ end
+
+
+ context "with a single link" do
+ let(:link_options) do
+ {
+ href: "/foo/bar/baz",
+ content: "Blublu",
+ groups: {foo: group}
+ }
+ end
+
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options
+ end
+ klass
+ end
+
+ context "always in" do
+ let(:group){ true }
+
+ it "should return the link" do
+ links = decorated.action_links(:show, group: :foo)
+ expect(links.size).to eq 1
+ end
+
+ context "define with group" do
+ let(:link_options) do
+ {
+ href: "/foo/bar/baz",
+ content: "Blublu",
+ group: :foo
+ }
+ end
+
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options
+ end
+ klass
+ end
+
+ it "should return the link" do
+ links = decorated.action_links(:show, group: :foo)
+ expect(links.size).to eq 1
+ end
+
+ it "should not return the link" do
+ links = decorated.action_links(:show, group: :bar)
+ expect(links.size).to eq 0
+ end
+ end
+ end
+
+ context "primary on this action" do
+ let(:group){ :show }
+
+ it "should return the link" do
+ links = decorated.action_links(:show, group: :foo)
+ expect(links.size).to eq 1
+ end
+ end
+
+ context "in this action among others" do
+ let(:group){ %i(show edit) }
+
+ it "should return the link" do
+ links = decorated.action_links(:show, group: :foo)
+ expect(links.size).to eq 1
+ end
+ end
+
+ context "in other actions" do
+ let(:group){ %i(index edit) }
+
+ it "should not return the link" do
+ links = decorated.action_links(:show, group: :foo)
+ expect(links.size).to eq 0
+ end
+ end
+
+ context "in another action" do
+ let(:group){ :index }
+
+ it "should not return the link" do
+ links = decorated.action_links(:show, group: :foo)
+ expect(links.size).to eq 0
+ end
+ end
+
+ context "never" do
+ let(:group){ nil }
+
+ it "should not return the link" do
+ links = decorated.action_links(:show, group: :foo)
+ expect(links.size).to eq 0
+ end
+ end
+ end
+
+ describe(:grouped_by) do
+ let(:link_options_1) do
+ {
+ href: "/foo/bar",
+ content: "Blublu",
+ primary: true
+ }
+ end
+
+ let(:link_options_2) do
+ {
+ href: "/foo/bar/baz",
+ content: "Foo",
+ groups: {secondary: :show}
+ }
+ end
+
+ let(:link_options_3) do
+ {
+ href: "/foo/bar/baz/bat",
+ content: "Foo",
+ groups: {foo: :show}
+ }
+ end
+
+ let(:link_options_4) do
+ {
+ href: "/footer",
+ content: "Foo",
+ footer: true
+ }
+ end
+
+ let(:decorator) do
+ klass = Class.new(AF83::Decorator)
+ klass.with_instance_decorator do |instance_decorator|
+ instance_decorator.action_link link_options_1
+ instance_decorator.action_link link_options_2
+ instance_decorator.action_link link_options_3
+ instance_decorator.action_link link_options_4
+ end
+ klass
+ end
+
+ it "should return links in their groups" do
+ links = decorated.action_links(:show).grouped_by(:primary, :secondary, :blu, :footer)
+ expect(links.size).to eq 5
+ instance_exec links[:primary].first, link_options_1, &link_should_match_options
+ instance_exec links[:secondary].first, link_options_2, &link_should_match_options
+ expect(links[:blu].size).to eq 0
+ instance_exec links[:other].first, link_options_3, &link_should_match_options
+ instance_exec links[:footer].first, link_options_4, &link_should_match_options
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/range_ext_spec.rb b/spec/lib/range_ext_spec.rb
index 9c44608b9..eee488c91 100644
--- a/spec/lib/range_ext_spec.rb
+++ b/spec/lib/range_ext_spec.rb
@@ -1,6 +1,6 @@
require 'range_ext'
RSpec.describe Range do
- context "intersection" do
+ describe "#intersection" do
it "is nil (sic) for two distinct ranges" do
expect( (1..2).intersection(3..4) ).to be_nil
end
@@ -15,4 +15,53 @@ RSpec.describe Range do
expect( (2..4) & (1..3) ).to eq 2..3
end
end
+
+ describe "intersect?" do
+ it 'is true when the given range includes begin' do
+ expect( (2..4).intersect? (1..3) ).to be_truthy
+ end
+
+ it 'is true when the given range includes end' do
+ expect( (2..4).intersect? (3..5) ).to be_truthy
+ end
+
+ it 'is true when the given range includes both begin and end' do
+ expect( (2..4).intersect? (1..5) ).to be_truthy
+ end
+
+ it 'is true when the given range is the same' do
+ expect( (2..4).intersect? (2..4) ).to be_truthy
+ end
+
+ it 'is false when the given range is after' do
+ expect( (2..4).intersect? (5..7) ).to be_falsey
+ end
+
+ it 'is false when the given range is before' do
+ expect( (2..4).intersect? (0..2) ).to be_falsey
+ end
+ end
+
+ context "remove" do
+ it "is unchanged when the given range has no intersection" do
+ expect( (1..2).remove(3..4) ).to eq 1..2
+ expect( (3..4).remove(1..2) ).to eq 3..4
+ end
+
+ it "is nil for two equal ranges" do
+ expect( (1..2).remove(1..2) ).to be_empty
+ end
+
+ it "is the begin of the range when given range intersect the end" do
+ expect( (5..10).remove(8..15) ).to eq [5..7]
+ end
+
+ it "is the end of the range when given range intersect the begin" do
+ expect( (5..10).remove(1..6) ).to eq [7..10]
+ end
+
+ it "is the two remaing ranges when given range is the middle" do
+ expect( (1..10).remove(4..6) ).to eq [1..3, 7..10]
+ end
+ end
end
diff --git a/spec/lib/stif/netex_file/frame_spec.rb b/spec/lib/stif/netex_file/frame_spec.rb
new file mode 100644
index 000000000..506da2148
--- /dev/null
+++ b/spec/lib/stif/netex_file/frame_spec.rb
@@ -0,0 +1,13 @@
+require 'stif/netex_file'
+RSpec.describe STIF::NetexFile::Frame do
+
+ context "line object id extraction" do
+ it "gets the line object id if frame describes a line" do
+ expect( described_class.get_short_id('offre_C00109_10.xml') ).to eq('C00109')
+ end
+
+ it "gets nil if the frame does not describe a line" do
+ expect( described_class.get_short_id('commun.xml') ).to be_nil
+ end
+ end
+end
diff --git a/spec/lib/stif/netex_file_spec.rb b/spec/lib/stif/netex_file_spec.rb
index ef69b994c..850d0d3de 100644
--- a/spec/lib/stif/netex_file_spec.rb
+++ b/spec/lib/stif/netex_file_spec.rb
@@ -1,8 +1,9 @@
+require 'stif/netex_file'
RSpec.describe STIF::NetexFile do
let( :zip_file ){ fixtures_path 'OFFRE_TRANSDEV_2017030112251.zip' }
- let(:frames) { STIF::NetexFile.new(zip_file).frames }
+ let(:frames) { described_class.new(zip_file).frames }
it "should return a frame for each sub directory" do
expect(frames.size).to eq(2)
@@ -22,4 +23,5 @@ RSpec.describe STIF::NetexFile do
end
end
+
end
diff --git a/spec/lib/stif/permission_translator_spec.rb b/spec/lib/stif/permission_translator_spec.rb
index ae1a2d1d5..9771af187 100644
--- a/spec/lib/stif/permission_translator_spec.rb
+++ b/spec/lib/stif/permission_translator_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
RSpec.describe Stif::PermissionTranslator do
context "No SSO Permissions" do
@@ -42,4 +43,19 @@ RSpec.describe Stif::PermissionTranslator do
).to match_array(Support::Permissions.all_permissions)
end
end
+
+ context "For the STIF organisation" do
+ let(:organisation){ build_stubbed :organisation, name: "STIF" }
+ let(:permissions){ %w{calendars.share stop_area_referentials.synchronize line_referentials.synchronize}.sort }
+ it "adds the STIF permission" do
+ expect(described_class.translate([], organisation).sort).to eq permissions
+ end
+
+ context "with the case changed" do
+ let(:organisation){ build_stubbed :organisation, name: "StiF" }
+ it "adds the STIF permission" do
+ expect(described_class.translate([], organisation).sort).to eq permissions
+ end
+ end
+ end
end
diff --git a/spec/mailers/calendar_mailer_spec.rb b/spec/mailers/calendar_mailer_spec.rb
index 9a2076f64..00d73a58b 100644
--- a/spec/mailers/calendar_mailer_spec.rb
+++ b/spec/mailers/calendar_mailer_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe CalendarMailer, type: :mailer do
end
it 'should have correct body' do
- key = I18n.t("mailers.calendar_mailer.#{type}.body", cal_name: calendar.name, cal_index_url: calendars_url)
+ key = I18n.t("mailers.calendar_mailer.#{type}.body", cal_name: calendar.name, cal_index_url: workgroup_calendars_url(calendar.workgroup))
expect(email).to have_body_text /#{key}/
end
end
diff --git a/spec/models/calendar_spec.rb b/spec/models/calendar_spec.rb
index e71c2b081..a5c0a7471 100644
--- a/spec/models/calendar_spec.rb
+++ b/spec/models/calendar_spec.rb
@@ -9,20 +9,34 @@ RSpec.describe Calendar, :type => :model do
it { is_expected.to be_versioned }
describe '#to_time_table' do
- let(:calendar) { create(:calendar, date_ranges: [Date.today...(Date.today + 1.month)]) }
+ let(:calendar) { create(:calendar, int_day_types: Calendar::MONDAY | Calendar::SUNDAY, date_ranges: [Date.today...(Date.today + 1.month)]) }
it 'should convert calendar to an instance of Chouette::TimeTable' do
time_table = calendar.convert_to_time_table
expect(time_table).to be_an_instance_of(Chouette::TimeTable)
+ expect(time_table.int_day_types).to eq calendar.int_day_types
expect(time_table.periods[0].period_start).to eq(calendar.periods[0].begin)
expect(time_table.periods[0].period_end).to eq(calendar.periods[0].end)
expect(time_table.dates.map(&:date)).to match_array(calendar.dates)
end
end
+ describe 'application days' do
+ let(:calendar) { create(:calendar) }
+ it "should default to all days" do
+ %w(monday tuesday wednesday thursday friday saturday sunday).each do |day|
+ expect(calendar.send(day)).to be_truthy
+ end
+ end
+ end
+
describe 'validations' do
it 'validates that dates and date_ranges do not overlap' do
- expect(build(:calendar, dates: [Date.today], date_ranges: [Date.today..Date.tomorrow])).to_not be_valid
+ expect(build(:calendar, dates: [Date.today.beginning_of_week], date_ranges: [Date.today.beginning_of_week..Date.today])).to_not be_valid
+ end
+
+ it 'validates that dates and date_ranges do not overlap but allow for days not in the list' do
+ expect(build(:calendar, dates: [Date.today.beginning_of_week - 1.week], date_ranges: [(Date.today.beginning_of_week - 1.week)..Date.today], int_day_types: Calendar::THURSDAY)).to be_valid
end
it 'validates that there are no duplicates in dates' do
@@ -42,4 +56,108 @@ RSpec.describe Calendar, :type => :model do
end
end
+ describe "Update state" do
+ def calendar_to_state calendar
+ calendar.slice('id').tap do |item|
+ item['comment'] = calendar.name
+ item['day_types'] = "Di,Lu,Ma,Me,Je,Ve,Sa"
+ item['current_month'] = calendar.month_inspect(Date.today.beginning_of_month)
+ item['current_periode_range'] = Date.today.beginning_of_month.to_s
+ item['time_table_periods'] = calendar.periods.map{|p| {'id': p.id, 'period_start': p.period_start.to_s, 'period_end': p.period_end.to_s}}
+ end
+ end
+
+ subject(:calendar){ create :calendar }
+ let(:state) { calendar_to_state subject }
+
+ it 'should update time table periods association' do
+ period = state['time_table_periods'].first
+ period['period_start'] = (Date.today - 1.month).to_s
+ period['period_end'] = (Date.today + 1.month).to_s
+
+ subject.state_update_periods state['time_table_periods']
+ ['period_end', 'period_start'].each do |prop|
+ expect(subject.reload.periods.first.send(prop).to_s).to eq(period[prop])
+ end
+ end
+
+ it 'should create time table periods association' do
+ state['time_table_periods'] << {
+ 'id' => false,
+ 'period_start' => (Date.today + 1.year).to_s,
+ 'period_end' => (Date.today + 2.year).to_s
+ }
+
+ expect {
+ subject.state_update_periods state['time_table_periods']
+ }.to change {subject.periods.count}.by(1)
+ expect(state['time_table_periods'].last['id']).to eq subject.reload.periods.last.id
+ end
+
+ it 'should delete time table periods association' do
+ state['time_table_periods'].first['deleted'] = true
+ expect {
+ subject.state_update_periods state['time_table_periods']
+ }.to change {subject.periods.count}.by(-1)
+ end
+
+ it 'should update name' do
+ state['comment'] = "Edited timetable name"
+ subject.state_update state
+ expect(subject.reload.name).to eq state['comment']
+ end
+
+ it 'should update day_types' do
+ state['day_types'] = "Di,Lu,Je,Ma"
+ subject.state_update state
+ expect(subject.reload.valid_days).to include(7, 1, 4, 2)
+ expect(subject.reload.valid_days).not_to include(3, 5, 6)
+ end
+
+ it 'should delete date if date is set to neither include or excluded date' do
+ updated = state['current_month'].map do |day|
+ day['include_date'] = false if day['include_date']
+ end
+
+ expect {
+ subject.state_update state
+ }.to change {subject.dates.count}.by(-updated.compact.count)
+ end
+
+ it 'should update date if date is set to excluded date' do
+ updated = state['current_month'].map do |day|
+ next unless day['include_date']
+ day['include_date'] = false
+ day['excluded_date'] = true
+ end
+
+ subject.state_update state
+ expect(subject.reload.excluded_days.count).to eq (updated.compact.count)
+ end
+
+ it 'should create new include date' do
+ day = state['current_month'].find{|d| !d['excluded_date'] && !d['include_date'] }
+ date = Date.parse(day['date'])
+ day['include_date'] = true
+ expect(subject.included_days).not_to include(date)
+
+ expect {
+ subject.state_update state
+ }.to change {subject.dates.count}.by(1)
+ expect(subject.reload.included_days).to include(date)
+ end
+
+ it 'should create new exclude date' do
+ day = state['current_month'].find{|d| !d['excluded_date'] && !d['include_date']}
+ date = Date.parse(day['date'])
+ day['excluded_date'] = true
+ expect(subject.excluded_days).not_to include(date)
+
+ expect {
+ subject.state_update state
+ }.to change {subject.all_dates.count}.by(1)
+ expect(subject.reload.excluded_days).to include(date)
+ end
+ end
+
end
diff --git a/spec/models/chouette/access_point_spec.rb b/spec/models/chouette/access_point_spec.rb
index c734ecedf..2184c6ec2 100644
--- a/spec/models/chouette/access_point_spec.rb
+++ b/spec/models/chouette/access_point_spec.rb
@@ -136,7 +136,7 @@ describe Chouette::AccessPoint, :type => :model do
describe "#generic_access_link_matrix" do
it "should have 2 generic_access_links in matrix" do
- stop_place = create :stop_area, :area_type => "zdlp"
+ stop_place = create :stop_area, :area_type => "gdl"
commercial_stop_point = create :stop_area, :area_type => "lda" ,:parent => stop_place
subject = create :access_point, :stop_area => stop_place
expect(subject.generic_access_link_matrix.size).to eq(2)
diff --git a/spec/models/chouette/area_type_spec.rb b/spec/models/chouette/area_type_spec.rb
new file mode 100644
index 000000000..28325dd0a
--- /dev/null
+++ b/spec/models/chouette/area_type_spec.rb
@@ -0,0 +1,43 @@
+require "rails_helper"
+
+RSpec.describe Chouette::AreaType do
+
+ describe "::ALL" do
+ it "includes all supported types" do
+ expect(Chouette::AreaType::ALL).to match_array( %i(zdep zder zdlp zdlr lda gdl deposit border service_area relief other) )
+ expect(Chouette::AreaType::COMMERCIAL).to match_array( %i(zdep zder zdlp zdlr lda gdl) )
+ expect(Chouette::AreaType::NON_COMMERCIAL).to match_array( %i( deposit border service_area relief other) )
+ end
+ end
+
+ describe ".find" do
+ it "returns nil if the given code is nil" do
+ expect(Chouette::AreaType.find(nil)).to be_nil
+ end
+
+ it "returns nil if the given code is unknown" do
+ expect(Chouette::AreaType.find('dummy')).to be_nil
+ end
+
+ it "returns an AreaType associated to the code" do
+ expect(Chouette::AreaType.find('zdep').code).to eq :zdep
+ end
+ end
+
+ describe ".options" do
+ before do
+ Chouette::AreaType.reset_caches!
+ end
+
+ it "returns an array with label and code for each type" do
+ allow(Chouette::AreaType).to receive(:all).and_return(%i{zdep lda})
+
+ expected_options = [
+ [Chouette::AreaType.find('zdep').label, :zdep],
+ [Chouette::AreaType.find('lda').label, :lda]
+ ]
+ expect(Chouette::AreaType.options).to eq(expected_options)
+ end
+ end
+
+end
diff --git a/spec/models/chouette/footnote_spec.rb b/spec/models/chouette/footnote_spec.rb
index fc5e5f306..05f55c2f0 100644
--- a/spec/models/chouette/footnote_spec.rb
+++ b/spec/models/chouette/footnote_spec.rb
@@ -1,12 +1,12 @@
require 'spec_helper'
describe Chouette::Footnote, type: :model do
- let(:footnote) { create(:footnote) }
+ subject { 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"
+ expect(subject.data_source_ref).to eq "DATASOURCEREF_EDITION_BOIV"
end
it 'should not set default if not omitted' do
@@ -18,16 +18,16 @@ describe Chouette::Footnote, type: :model do
end
describe 'checksum' do
- it_behaves_like 'checksum support', :footnote
+ it_behaves_like 'checksum support'
context '#checksum_attributes' do
it 'should return code and label' do
- expected = [footnote.code, footnote.label]
- expect(footnote.checksum_attributes).to include(*expected)
+ expected = [subject.code, subject.label]
+ expect(subject.checksum_attributes).to include(*expected)
end
it 'should not return other atrributes' do
- expect(footnote.checksum_attributes).to_not include(footnote.updated_at)
+ expect(subject.checksum_attributes).to_not include(subject.updated_at)
end
end
end
diff --git a/spec/models/chouette/journey_pattern_spec.rb b/spec/models/chouette/journey_pattern_spec.rb
index ea7c2a2e9..19a74a0e7 100644
--- a/spec/models/chouette/journey_pattern_spec.rb
+++ b/spec/models/chouette/journey_pattern_spec.rb
@@ -2,9 +2,10 @@ require 'spec_helper'
describe Chouette::JourneyPattern, :type => :model do
it { is_expected.to be_versioned }
+ subject { create(:journey_pattern) }
describe 'checksum' do
- it_behaves_like 'checksum support', :journey_pattern
+ it_behaves_like 'checksum support'
end
# context 'validate minimum stop_points size' do
@@ -32,6 +33,44 @@ describe Chouette::JourneyPattern, :type => :model do
# end
# end
+ describe "full_schedule?" do
+ let(:journey_pattern) { create :journey_pattern }
+ subject{ journey_pattern.full_schedule? }
+ context "when no time is set" do
+ it { should be_falsy }
+ end
+
+ context "when the costs are incomplete" do
+ context "with a missing distance" do
+ before(:each){
+ journey_pattern.costs = generate_journey_pattern_costs(->(i){i == 1 ? nil : 10}, 10)
+ }
+ it { should be_falsy }
+ end
+
+ context "with a missing time" do
+ before(:each){
+ journey_pattern.costs = generate_journey_pattern_costs(10, ->(i){i == 1 ? nil : 10})
+ }
+ it { should be_falsy }
+ end
+ end
+
+ context "with a zeroed cost" do
+ before(:each){
+ journey_pattern.costs = generate_journey_pattern_costs(->(i){i == 1 ? 0 : 10}, 10)
+ }
+ it { should be_falsy }
+ end
+
+ context "when all the times are set" do
+ before(:each){
+ journey_pattern.costs = generate_journey_pattern_costs(10, 10)
+ }
+ it { should be_truthy }
+ end
+ end
+
describe "state_update" do
def journey_pattern_to_state jp
jp.attributes.slice('name', 'published_name', 'registration_number').tap do |item|
@@ -39,6 +78,7 @@ describe Chouette::JourneyPattern, :type => :model do
item['stop_points'] = jp.stop_points.map do |sp|
{ 'id' => sp.stop_area_id }
end
+ item['costs'] = jp.costs
end
end
@@ -72,6 +112,14 @@ describe Chouette::JourneyPattern, :type => :model do
expect(new_state['new_record']).to be_truthy
end
+ it 'should create journey_pattern with state_update' do
+ new_state = journey_pattern_to_state(build(:journey_pattern, objectid: nil, route: route))
+ collection = [new_state]
+ expect {
+ Chouette::JourneyPattern.state_update route, collection
+ }.to change{Chouette::JourneyPattern.count}.by(1)
+ end
+
it 'should delete journey_pattern' do
state['deletable'] = true
collection = [state]
diff --git a/spec/models/chouette/purchase_window_spec.rb b/spec/models/chouette/purchase_window_spec.rb
new file mode 100644
index 000000000..702a44eeb
--- /dev/null
+++ b/spec/models/chouette/purchase_window_spec.rb
@@ -0,0 +1,27 @@
+RSpec.describe Chouette::PurchaseWindow, :type => :model do
+ let(:referential) {create(:referential)}
+ subject { create(:purchase_window, referential: referential) }
+
+ it { should belong_to(:referential) }
+ it { is_expected.to validate_presence_of(:name) }
+
+ describe 'validations' do
+ it 'validates and date_ranges do not overlap' do
+ expect(build(:purchase_window, referential: referential,date_ranges: [Date.today..Date.today + 10.day, Date.yesterday..Date.tomorrow])).to_not be_valid
+ # expect(build(periods: [Date.today..Date.today + 10.day, Date.yesterday..Date.tomorrow ])).to_not be_valid
+ end
+ end
+
+ describe 'before_validation' do
+ let(:purchase_window) { build(:purchase_window, referential: referential, date_ranges: []) }
+
+ it 'shoud fill date_ranges with date ranges' do
+ expected_range = Date.today..Date.tomorrow
+ purchase_window.date_ranges << expected_range
+ purchase_window.valid?
+
+ expect(purchase_window.date_ranges.map { |period| period.begin..period.end }).to eq([expected_range])
+ end
+ end
+
+end
diff --git a/spec/models/chouette/route/route_base_spec.rb b/spec/models/chouette/route/route_base_spec.rb
index 26f57eae5..98cb3e358 100644
--- a/spec/models/chouette/route/route_base_spec.rb
+++ b/spec/models/chouette/route/route_base_spec.rb
@@ -1,8 +1,8 @@
RSpec.describe Chouette::Route, :type => :model do
-
subject { create(:route) }
+
describe 'checksum' do
- it_behaves_like 'checksum support', :route
+ it_behaves_like 'checksum support'
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/route/route_duplication_spec.rb b/spec/models/chouette/route/route_duplication_spec.rb
index ee45b5005..8b3a948a2 100644
--- a/spec/models/chouette/route/route_duplication_spec.rb
+++ b/spec/models/chouette/route/route_duplication_spec.rb
@@ -2,7 +2,7 @@ RSpec.describe Chouette::Route do
let!( :route ){ create :route }
- context '#duplicate' do
+ context '#duplicate' do
describe 'properties' do
it 'same attribute values' do
route.duplicate
@@ -23,7 +23,12 @@ RSpec.describe Chouette::Route do
it 'duplicates its stop points' do
expect{ route.duplicate }.to change{Chouette::StopPoint.count}.by(route.stop_points.count)
end
- it 'does bot duplicate the stop areas' do
+
+ it 'duplicates its stop points in the same order' do
+ expect(route.duplicate.stop_points.order(:position).map(&:stop_area_id)).to eq route.stop_points.order(:position).map(&:stop_area_id)
+ end
+
+ it 'does not duplicate the stop areas' do
expect{ route.duplicate }.not_to change{Chouette::StopArea.count}
end
end
@@ -34,7 +39,7 @@ RSpec.describe Chouette::Route do
it 'the required attributes' do
expect( values_for_create(first_duplicate, except: %w{objectid name checksum checksum_source}) ).to eq( values_for_create( second_duplicate, except: %w{objectid name checksum checksum_source} ) )
- end
+ end
it 'the stop areas' do
expect( first_duplicate.stop_areas.pluck(:id) ).to eq( route.stop_areas.pluck(:id) )
diff --git a/spec/models/chouette/routing_constraint_zone_spec.rb b/spec/models/chouette/routing_constraint_zone_spec.rb
index 8ebd8695c..bda6bb04a 100644
--- a/spec/models/chouette/routing_constraint_zone_spec.rb
+++ b/spec/models/chouette/routing_constraint_zone_spec.rb
@@ -5,21 +5,16 @@ describe Chouette::RoutingConstraintZone, type: :model do
subject { create(:routing_constraint_zone) }
it { is_expected.to validate_presence_of :name }
+ it { is_expected.to validate_presence_of :route_id }
# shoulda matcher to validate length of array ?
xit { is_expected.to validate_length_of(:stop_point_ids).is_at_least(2) }
it { is_expected.to be_versioned }
describe 'checksum' do
- it_behaves_like 'checksum support', :routing_constraint_zone
+ it_behaves_like 'checksum support'
end
describe 'validations' do
- it 'validates the presence of route_id' do
- expect {
- subject.update!(route_id: nil)
- }.to raise_error(NoMethodError)
- end
-
it 'validates the presence of stop_point_ids' do
expect {
subject.update!(stop_point_ids: [])
diff --git a/spec/models/chouette/stop_area_spec.rb b/spec/models/chouette/stop_area_spec.rb
index c6aeafaf8..32ee5a3a6 100644
--- a/spec/models/chouette/stop_area_spec.rb
+++ b/spec/models/chouette/stop_area_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
require 'spec_helper'
describe Chouette::StopArea, :type => :model do
@@ -9,10 +10,20 @@ describe Chouette::StopArea, :type => :model do
it { should belong_to(:stop_area_referential) }
it { should validate_presence_of :name }
+ it { should validate_presence_of :kind }
it { should validate_numericality_of :latitude }
it { should validate_numericality_of :longitude }
it { is_expected.to be_versioned }
+ describe "#area_type" do
+ it "should validate the value is correct regarding to the kind" do
+ expect(build(:stop_area, kind: :commercial, area_type: :gdl)).to be_valid
+ expect(build(:stop_area, kind: :non_commercial, area_type: :relief)).to be_valid
+ expect(build(:stop_area, kind: :commercial, area_type: :relief)).to_not be_valid
+ expect(build(:stop_area, kind: :non_commercial, area_type: :gdl)).to_not be_valid
+ end
+ end
+
# describe ".latitude" do
# it "should accept -90 value" do
# subject = create :stop_area, :area_type => "BoardingPosition"
@@ -426,5 +437,74 @@ describe Chouette::StopArea, :type => :model do
# end
# end
+ describe "#parent" do
+
+ let(:stop_area) { FactoryGirl.build :stop_area, parent: FactoryGirl.build(:stop_area) }
+
+ it "is valid when parent has an 'higher' type" do
+ stop_area.area_type = 'zdep'
+ stop_area.parent.area_type = 'zdlp'
+
+ stop_area.valid?
+ expect(stop_area.errors).to_not have_key(:parent_id)
+ end
+
+ it "is valid when parent is undefined" do
+ stop_area.parent = nil
+
+ stop_area.valid?
+ expect(stop_area.errors).to_not have_key(:parent_id)
+ end
+
+ it "isn't valid when parent has the same type" do
+ stop_area.parent.area_type = stop_area.area_type = 'zdep'
+
+ stop_area.valid?
+ expect(stop_area.errors).to have_key(:parent_id)
+ end
+
+ it "isn't valid when parent has a lower type" do
+ stop_area.area_type = 'lda'
+ stop_area.parent.area_type = 'zdep'
+
+ stop_area.valid?
+ expect(stop_area.errors).to have_key(:parent_id)
+ end
+
+ it "use parent area type label in validation error message" do
+ stop_area.area_type = 'zdep'
+ stop_area.parent.area_type = 'zdep'
+
+ stop_area.valid?
+ expect(stop_area.errors[:parent_id].first).to include(Chouette::AreaType.find(stop_area.parent.area_type).label)
+ end
+
+ end
+
+ describe '#waiting_time' do
+
+ let(:stop_area) { FactoryGirl.build :stop_area }
+
+ it 'can be nil' do
+ stop_area.waiting_time = nil
+ expect(stop_area).to be_valid
+ end
+
+ it 'can be zero' do
+ stop_area.waiting_time = 0
+ expect(stop_area).to be_valid
+ end
+
+ it 'can be positive' do
+ stop_area.waiting_time = 120
+ expect(stop_area).to be_valid
+ end
+
+ it "can't be negative" do
+ stop_area.waiting_time = -1
+ expect(stop_area).to_not be_valid
+ end
+
+ end
end
diff --git a/spec/models/chouette/time_table_period_spec.rb b/spec/models/chouette/time_table_period_spec.rb
index cc1a3ae09..e14d38ade 100644
--- a/spec/models/chouette/time_table_period_spec.rb
+++ b/spec/models/chouette/time_table_period_spec.rb
@@ -10,7 +10,7 @@ describe Chouette::TimeTablePeriod, :type => :model do
it { is_expected.to validate_presence_of :period_end }
describe 'checksum' do
- it_behaves_like 'checksum support', :time_table_period
+ it_behaves_like 'checksum support'
end
describe "#overlap" do
diff --git a/spec/models/chouette/time_table_spec.rb b/spec/models/chouette/time_table_spec.rb
index 677308fc8..bb88877b9 100644
--- a/spec/models/chouette/time_table_spec.rb
+++ b/spec/models/chouette/time_table_spec.rb
@@ -926,6 +926,7 @@ end
end
end
end
+
describe "#validity_out_between?" do
let(:empty_tm) {build(:time_table)}
it "should be false if empty calendar" do
@@ -1048,7 +1049,39 @@ end
# it { is_expected.to validate_uniqueness_of :objectid }
describe 'checksum' do
- it_behaves_like 'checksum support', :time_table
+ it_behaves_like 'checksum support'
+
+ it "handles newly built dates and periods" do
+ time_table = build(:time_table)
+ time_table.periods.build period_start: Time.now, period_end: 1.month.from_now
+ time_table.dates.build date: Time.now
+ time_table.save!
+ expect{time_table.update_checksum!}.to_not change{time_table.checksum}
+ expect(time_table.dates.count).to eq 1
+ expect(time_table.periods.count).to eq 1
+ end
+
+ it "changes when a date is updated" do
+ time_table = create(:time_table)
+ expect{time_table.dates.last.update_attribute(:date, Time.now)}.to change{time_table.reload.checksum}
+ end
+
+ it "changes when a date is added" do
+ time_table = create(:time_table)
+ expect(time_table).to receive(:update_checksum_without_callbacks!).at_least(:once).and_call_original
+ expect{create(:time_table_date, time_table: time_table, date: 1.year.ago)}.to change{time_table.checksum}
+ end
+
+ it "changes when a period is updated" do
+ time_table = create(:time_table)
+ expect{time_table.periods.last.update_attribute(:period_start, Time.now)}.to change{time_table.reload.checksum}
+ end
+
+ it "changes when a period is added" do
+ time_table = create(:time_table)
+ expect(time_table).to receive(:update_checksum_without_callbacks!).at_least(:once).and_call_original
+ expect{create(:time_table_period, time_table: time_table)}.to change{time_table.checksum}
+ end
end
describe "#excluded_days" do
@@ -1068,8 +1101,6 @@ end
end
end
-
-
describe "#effective_days" do
before do
subject.periods.clear
@@ -1094,8 +1125,6 @@ end
end
end
-
-
describe "#optimize_overlapping_periods" do
before do
subject.periods.clear
@@ -1187,4 +1216,99 @@ end
expect(subject.tag_list.size).to eq(2)
end
end
+
+ describe "#intersect_periods!" do
+ let(:time_table) { Chouette::TimeTable.new }
+ let(:periods) do
+ [
+ Date.new(2018, 1, 1)..Date.new(2018, 2, 1),
+ ]
+ end
+
+ it "remove a date not included in given periods" do
+ time_table.dates.build date: Date.new(2017,12,31)
+ time_table.intersect_periods! periods
+ expect(time_table.dates).to be_empty
+ end
+
+ it "keep a date included in given periods" do
+ time_table.dates.build date: Date.new(2018,1,15)
+ expect{time_table.intersect_periods! periods}.to_not change(time_table, :dates)
+ end
+
+ it "remove a period not included in given periods" do
+ time_table.periods.build period_start: Date.new(2017,12,1), period_end: Date.new(2017,12,31)
+ time_table.intersect_periods! periods
+ expect(time_table.periods).to be_empty
+ end
+
+ it "modify a start period if not included in given periods" do
+ period = time_table.periods.build period_start: Date.new(2017,12,1), period_end: Date.new(2018,1,15)
+ time_table.intersect_periods! periods
+ expect(period.period_start).to eq(Date.new(2018, 1, 1))
+ end
+
+ it "modify a end period if not included in given periods" do
+ period = time_table.periods.build period_start: Date.new(2018,1,15), period_end: Date.new(2018,3,1)
+ time_table.intersect_periods! periods
+ expect(period.period_end).to eq(Date.new(2018, 2, 1))
+ end
+
+ it "keep a period included in given periods" do
+ time_table.periods.build period_start: Date.new(2018,1,10), period_end: Date.new(2018,1,20)
+ expect{time_table.intersect_periods! periods}.to_not change(time_table, :periods)
+ end
+
+ end
+
+ describe "#remove_periods!" do
+ let(:time_table) { Chouette::TimeTable.new }
+ let(:periods) do
+ [
+ Date.new(2018, 1, 1)..Date.new(2018, 2, 1),
+ ]
+ end
+
+ it "remove a date included in given periods" do
+ time_table.dates.build date: Date.new(2018,1,15)
+ time_table.remove_periods! periods
+ expect(time_table.dates).to be_empty
+ end
+
+ it "keep a date not included in given periods" do
+ time_table.dates.build date: Date.new(2017,12,31)
+ expect{time_table.remove_periods! periods}.to_not change(time_table, :dates)
+ end
+
+ it "modify a end period if included in given periods" do
+ period = time_table.periods.build period_start: Date.new(2017,12,1), period_end: Date.new(2018,1,15)
+ time_table.remove_periods! periods
+ expect(period.period_end).to eq(Date.new(2017, 12, 31))
+ end
+
+ it "modify a start period if included in given periods" do
+ period = time_table.periods.build period_start: Date.new(2018,1,15), period_end: Date.new(2018,3,1)
+ time_table.remove_periods! periods
+ expect(period.period_start).to eq(Date.new(2018, 2, 2))
+ end
+
+ it "remove a period included in given periods" do
+ time_table.periods.build period_start: Date.new(2018,1,10), period_end: Date.new(2018,1,20)
+ time_table.remove_periods! periods
+ expect(time_table.periods).to be_empty
+ end
+
+ it "split a period including a given period" do
+ time_table.periods.build period_start: Date.new(2017,12,1), period_end: Date.new(2018,3,1)
+ time_table.remove_periods! periods
+
+ expected_ranges = [
+ Date.new(2017,12,1)..Date.new(2017,12,31),
+ Date.new(2018,2,2)..Date.new(2018,3,1)
+ ]
+ expect(time_table.periods.map(&:range)).to eq(expected_ranges)
+ end
+
+ end
+
end
diff --git a/spec/models/chouette/vehicle_journey_at_stop_spec.rb b/spec/models/chouette/vehicle_journey_at_stop_spec.rb
index df8a630fe..a97559a0c 100644
--- a/spec/models/chouette/vehicle_journey_at_stop_spec.rb
+++ b/spec/models/chouette/vehicle_journey_at_stop_spec.rb
@@ -1,10 +1,12 @@
require 'spec_helper'
RSpec.describe Chouette::VehicleJourneyAtStop, type: :model do
+ subject { create(:vehicle_journey_at_stop) }
+
describe 'checksum' do
let(:at_stop) { build_stubbed(:vehicle_journey_at_stop) }
- it_behaves_like 'checksum support', :vehicle_journey_at_stop
+ it_behaves_like 'checksum support'
context '#checksum_attributes' do
it 'should return attributes' do
@@ -40,6 +42,41 @@ RSpec.describe Chouette::VehicleJourneyAtStop, type: :model do
end
end
+ context "the different times" do
+ let (:at_stop) { build_stubbed(:vehicle_journey_at_stop) }
+
+ describe "without a TimeZone" do
+ it "should not offset times" do
+ expect(at_stop.departure).to eq at_stop.departure_local
+ expect(at_stop.arrival).to eq at_stop.arrival_local
+ end
+ end
+
+
+ describe "with a TimeZone" do
+ before(:each) do
+ stop = at_stop.stop_point.stop_area
+ stop.time_zone = "Mexico City"
+ end
+
+ it "should offset times" do
+ expect(at_stop.departure_local).to eq at_stop.send(:format_time, at_stop.departure_time - 6.hours)
+ expect(at_stop.arrival_local).to eq at_stop.send(:format_time, at_stop.arrival_time - 6.hours)
+ end
+
+ context "with a wrong Timezone" do
+ before do
+ at_stop.stop_point.stop_area.time_zone = "Gotham City"
+ end
+
+ it "should not offset times" do
+ expect(at_stop.departure_local).to eq at_stop.send(:format_time, at_stop.departure_time)
+ expect(at_stop.arrival_local).to eq at_stop.send(:format_time, at_stop.arrival_time)
+ end
+ end
+ end
+ end
+
describe "#validate" do
it "displays the proper error message when day offset exceeds the max" do
bad_offset = Chouette::VehicleJourneyAtStop::DAY_OFFSET_MAX + 1
diff --git a/spec/models/chouette/vehicle_journey_spec.rb b/spec/models/chouette/vehicle_journey_spec.rb
index ac9b21ceb..76e73d9cf 100644
--- a/spec/models/chouette/vehicle_journey_spec.rb
+++ b/spec/models/chouette/vehicle_journey_spec.rb
@@ -1,7 +1,10 @@
require 'spec_helper'
describe Chouette::VehicleJourney, :type => :model do
+ subject { create(:vehicle_journey) }
+
it { is_expected.to be_versioned }
+ it { should have_and_belong_to_many(:purchase_windows) }
it "must be valid with an at-stop day offset of 1" do
vehicle_journey = create(
@@ -20,7 +23,183 @@ describe Chouette::VehicleJourney, :type => :model do
end
describe 'checksum' do
- it_behaves_like 'checksum support', :vehicle_journey
+ it_behaves_like 'checksum support'
+ it "changes when a vjas is updated" do
+ vehicle_journey = create(:vehicle_journey)
+ expect{vehicle_journey.vehicle_journey_at_stops.last.update_attribute(:departure_time, Time.now)}.to change{vehicle_journey.reload.checksum}
+ end
+
+ it "changes when a vjas is added" do
+ vehicle_journey = create(:vehicle_journey)
+ expect(vehicle_journey).to receive(:update_checksum_without_callbacks!).at_least(:once).and_call_original
+ expect{create(:vehicle_journey_at_stop, vehicle_journey: vehicle_journey)}.to change{vehicle_journey.checksum}
+ end
+ end
+
+ describe "#with_stop_area_ids" do
+ subject(:result){Chouette::VehicleJourney.with_stop_area_ids(ids)}
+ let(:ids){[]}
+ let(:common_stop_area){ create :stop_area}
+ let!(:journey_1){ create :vehicle_journey }
+ let!(:journey_2){ create :vehicle_journey }
+
+ before(:each) do
+ journey_1.journey_pattern.stop_points.last.update_attribute :stop_area_id, common_stop_area.id
+ journey_2.journey_pattern.stop_points.last.update_attribute :stop_area_id, common_stop_area.id
+ expect(journey_1.stop_areas).to include(common_stop_area)
+ expect(journey_2.stop_areas).to include(common_stop_area)
+ end
+ context "with no value" do
+ it "should return all journeys" do
+ expect(result).to eq Chouette::VehicleJourney.all
+ end
+ end
+
+ context "with a single value" do
+ let(:ids){[journey_1.stop_areas.first.id]}
+ it "should return all journeys" do
+ expect(result).to eq [journey_1]
+ end
+
+ context "with a common area" do
+ let(:ids){[common_stop_area.id]}
+ it "should return all journeys" do
+ expect(result.to_a.sort).to eq [journey_1, journey_2].sort
+ end
+ end
+ end
+
+ context "with a couple of values" do
+ let(:ids){[journey_1.stop_areas.first.id, common_stop_area.id]}
+ it "should return only the matching journeys" do
+ expect(result).to eq [journey_1]
+ end
+ end
+
+ end
+
+ describe '#in_purchase_window' do
+ let(:start_date){2.month.ago.to_date}
+ let(:end_date){1.month.ago.to_date}
+
+ subject{Chouette::VehicleJourney.in_purchase_window start_date..end_date}
+
+ let!(:without_purchase_window){ create :vehicle_journey }
+ let!(:without_matching_purchase_window){
+ pw = create :purchase_window, referential: Referential.first, date_ranges: [(end_date+1.day..end_date+2.days)]
+ pw2 = create :purchase_window, referential: Referential.first, date_ranges: [(end_date+10.day..end_date+20.days)]
+ create :vehicle_journey, purchase_windows: [pw, pw2]
+ }
+ let!(:included_purchase_window){
+ pw = create :purchase_window, referential: Referential.first, date_ranges: [(start_date..end_date)]
+ pw2 = create :purchase_window, referential: Referential.first
+ create :vehicle_journey, purchase_windows: [pw, pw2]
+ }
+ let!(:overlapping_purchase_window){
+ pw = create :purchase_window, referential: Referential.first, date_ranges: [(end_date..end_date+1.day)]
+ pw2 = create :purchase_window, referential: Referential.first
+ create :vehicle_journey, purchase_windows: [pw, pw2]
+ }
+
+
+ it "should not include VJ with no purchase window" do
+ expect(subject).to_not include without_purchase_window
+ end
+
+ it "should not include VJ with no matching purchase window" do
+ expect(subject).to_not include without_matching_purchase_window
+ end
+
+ it "should include VJ with included purchase window" do
+ expect(subject).to include included_purchase_window
+ end
+
+ it "should include VJ with overlapping purchase_window purchase window" do
+ expect(subject).to include overlapping_purchase_window
+ end
+ end
+
+ describe '#in_time_table' do
+ let(:start_date){2.month.ago.to_date}
+ let(:end_date){1.month.ago.to_date}
+
+ subject{Chouette::VehicleJourney.with_matching_timetable start_date..end_date}
+
+ context "without time table" do
+ let!(:vehicle_journey){ create :vehicle_journey }
+ it "should not include VJ " do
+ expect(subject).to_not include vehicle_journey
+ end
+ end
+
+ context "without a time table matching on a regular day" do
+ let(:timetable){
+ period = create :time_table_period, period_start: start_date-2.day, period_end: start_date
+ create :time_table, periods: [period], dates_count: 0
+ }
+ let!(:vehicle_journey){ create :vehicle_journey, time_tables: [timetable] }
+ it "should include VJ " do
+ expect(subject).to include vehicle_journey
+ end
+ end
+
+ context "without a time table matching on a regular day" do
+ let(:timetable){
+ period = create :time_table_period, period_start: end_date, period_end: end_date+1.day
+ create :time_table, periods: [period], dates_count: 0
+ }
+ let!(:vehicle_journey){ create :vehicle_journey, time_tables: [timetable] }
+ it "should include VJ " do
+ expect(subject).to include vehicle_journey
+ end
+ end
+
+ context "with a time table with a matching period but not the right day" do
+ let(:start_date){end_date - 1.day}
+ let(:end_date){Time.now.end_of_week.to_date}
+
+ let(:timetable){
+ period = create :time_table_period, period_start: start_date-1.month, period_end: end_date+1.month
+ create :time_table, periods: [period], int_day_types: 4 + 8, dates_count: 0
+ }
+ let!(:vehicle_journey){ create :vehicle_journey, time_tables: [timetable] }
+ it "should not include VJ " do
+ expect(subject).to_not include vehicle_journey
+ end
+ end
+
+ context "with a time table with a matching period but day opted-out" do
+ let(:start_date){end_date - 1.day}
+ let(:end_date){Time.now.end_of_week.to_date}
+
+ let(:timetable){
+ tt = create :time_table, dates_count: 0, periods_count: 0
+ create :time_table_period, period_start: start_date-1.month, period_end: start_date-1.day, time_table: tt
+ create(:time_table_date, :date => start_date, in_out: false, time_table: tt)
+ tt
+ }
+ let!(:vehicle_journey){ create :vehicle_journey, time_tables: [timetable] }
+ it "should not include VJ " do
+ expect(subject).to_not include vehicle_journey
+ end
+ end
+
+ context "with a time table with no matching period but not the right extra day" do
+ let(:start_date){end_date - 1.day}
+ let(:end_date){Time.now.end_of_week.to_date}
+
+ let(:timetable){
+ tt = create :time_table, dates_count: 0, periods_count: 0
+ create :time_table_period, period_start: start_date-1.month, period_end: start_date-1.day, time_table: tt
+ create(:time_table_date, :date => start_date, in_out: true, time_table: tt)
+ tt
+ }
+ let!(:vehicle_journey){ create :vehicle_journey, time_tables: [timetable] }
+ it "should include VJ " do
+ expect(subject).to include vehicle_journey
+ end
+ end
+
end
describe "vjas_departure_time_must_be_before_next_stop_arrival_time",
@@ -63,10 +242,12 @@ describe Chouette::VehicleJourney, :type => :model do
at_stop[att.to_s] = vjas.send(att) unless vjas.send(att).nil?
end
- [:arrival_time, :departure_time].map do |att|
- at_stop[att.to_s] = {
- 'hour' => vjas.send(att).strftime('%H'),
- 'minute' => vjas.send(att).strftime('%M'),
+ at_stop["stop_point_objectid"] = vjas&.stop_point&.objectid
+
+ [:arrival, :departure].map do |att|
+ at_stop["#{att}_time"] = {
+ 'hour' => vjas.send("#{att}_local_time").strftime('%H'),
+ 'minute' => vjas.send("#{att}_local_time").strftime('%M'),
}
end
at_stop
@@ -76,7 +257,10 @@ describe Chouette::VehicleJourney, :type => :model do
vj.slice('objectid', 'published_journey_name', 'journey_pattern_id', 'company_id').tap do |item|
item['vehicle_journey_at_stops'] = []
item['time_tables'] = []
+ item['purchase_windows'] = []
item['footnotes'] = []
+ item['purchase_windows'] = []
+ item['custom_fields'] = vj.custom_fields
vj.vehicle_journey_at_stops.each do |vjas|
item['vehicle_journey_at_stops'] << vehicle_journey_at_stop_to_state(vjas)
@@ -91,18 +275,44 @@ describe Chouette::VehicleJourney, :type => :model do
let(:collection) { [state] }
it 'should create new vj from state' do
- new_vj = build(:vehicle_journey, objectid: nil, published_journey_name: 'dummy', route: route, journey_pattern: journey_pattern)
+ create(:custom_field, code: :energy)
+ new_vj = build(:vehicle_journey, objectid: nil, published_journey_name: 'dummy', route: route, journey_pattern: journey_pattern, custom_field_values: {energy: 99})
collection << vehicle_journey_to_state(new_vj)
expect {
Chouette::VehicleJourney.state_update(route, collection)
}.to change {Chouette::VehicleJourney.count}.by(1)
- expect(collection.last['objectid']).not_to be_nil
obj = Chouette::VehicleJourney.last
+ expect(obj).to receive(:after_commit_objectid).and_call_original
+
+ # For some reason we have to force it
+ obj.after_commit_objectid
obj.run_callbacks(:commit)
+ expect(collection.last['objectid']).to eq obj.objectid
expect(obj.published_journey_name).to eq 'dummy'
+ expect(obj.custom_fields["energy"]["value"]).to eq 99
+ end
+
+ it 'should expect local times' do
+ new_vj = build(:vehicle_journey, objectid: nil, published_journey_name: 'dummy', route: route, journey_pattern: journey_pattern)
+ stop_area = create(:stop_area, time_zone: "Mexico City")
+ stop_point = create(:stop_point, stop_area: stop_area)
+ new_vj.vehicle_journey_at_stops << build(:vehicle_journey_at_stop, vehicle_journey: vehicle_journey, stop_point: stop_point)
+ data = vehicle_journey_to_state(new_vj)
+ data['vehicle_journey_at_stops'][0]["departure_time"]["hour"] = "15"
+ data['vehicle_journey_at_stops'][0]["arrival_time"]["hour"] = "12"
+ collection << data
+ expect {
+ Chouette::VehicleJourney.state_update(route, collection)
+ }.to change {Chouette::VehicleJourney.count}.by(1)
+ created = Chouette::VehicleJourney.last.vehicle_journey_at_stops.last
+ expect(created.stop_point).to eq stop_point
+ expect(created.departure_local_time.hour).to_not eq created.departure_time.hour
+ expect(created.arrival_local_time.hour).to_not eq created.arrival_time.hour
+ expect(created.departure_local_time.hour).to eq 15
+ expect(created.arrival_local_time.hour).to eq 12
end
it 'should save vehicle_journey_at_stops of newly created vj' do
@@ -159,6 +369,23 @@ describe Chouette::VehicleJourney, :type => :model do
expect(vehicle_journey.reload.time_tables).to be_empty
end
+ it 'should update vj purchase_windows association from state' do
+ 2.times{state['purchase_windows'] << create(:purchase_window, referential: referential).slice('id', 'name', 'objectid', 'color')}
+ vehicle_journey.update_has_and_belongs_to_many_from_state(state)
+
+ expected = state['purchase_windows'].map{|tt| tt['id']}
+ actual = vehicle_journey.reload.purchase_windows.map(&:id)
+ expect(actual).to match_array(expected)
+ end
+
+ it 'should clear vj purchase_windows association when remove from state' do
+ vehicle_journey.purchase_windows << create(:purchase_window, referential: referential)
+ state['purchase_windows'] = []
+ vehicle_journey.update_has_and_belongs_to_many_from_state(state)
+
+ expect(vehicle_journey.reload.purchase_windows).to be_empty
+ end
+
it 'should update vj footnote association from state' do
2.times{state['footnotes'] << create(:footnote, line: route.line).slice('id', 'code', 'label', 'line_id')}
vehicle_journey.update_has_and_belongs_to_many_from_state(state)
@@ -182,14 +409,24 @@ describe Chouette::VehicleJourney, :type => :model do
expect(vehicle_journey.reload.company_id).to eq state['company']['id']
end
+ it "handles vehicle journey company deletion" do
+ vehicle_journey.update(company: create(:company))
+ state.delete('company')
+ Chouette::VehicleJourney.state_update(route, collection)
+
+ expect(vehicle_journey.reload.company_id).to be_nil
+ end
+
it 'should update vj attributes from state' do
state['published_journey_name'] = 'edited_name'
state['published_journey_identifier'] = 'edited_identifier'
+ state['custom_fields'] = {energy: {value: 99}}
Chouette::VehicleJourney.state_update(route, collection)
expect(state['errors']).to be_nil
expect(vehicle_journey.reload.published_journey_name).to eq state['published_journey_name']
expect(vehicle_journey.reload.published_journey_identifier).to eq state['published_journey_identifier']
+ expect(vehicle_journey.reload.custom_field_value("energy")).to eq 99
end
it 'should return errors when validation failed' do
@@ -379,8 +616,7 @@ describe Chouette::VehicleJourney, :type => :model do
end
describe ".where_departure_time_between" do
- it "selects vehicle journeys whose departure times are between the
- specified range" do
+ it "selects vehicle journeys whose departure times are between the specified range" do
journey_early = create(
:vehicle_journey,
stop_departure_time: '02:00:00'
@@ -395,7 +631,7 @@ describe Chouette::VehicleJourney, :type => :model do
journey_pattern: journey_pattern,
stop_departure_time: '03:00:00'
)
- journey_late = create(
+ create(
:vehicle_journey,
route: route,
journey_pattern: journey_pattern,
diff --git a/spec/models/compliance_check_spec.rb b/spec/models/compliance_check_spec.rb
index f83d78c29..ffa59245c 100644
--- a/spec/models/compliance_check_spec.rb
+++ b/spec/models/compliance_check_spec.rb
@@ -15,4 +15,36 @@ RSpec.describe ComplianceCheck, type: :model do
it { should validate_presence_of :name }
it { should validate_presence_of :code }
it { should validate_presence_of :origin_code }
+
+ describe ".abort_old" do
+ it "changes check sets older than 4 hours to aborted" do
+ Timecop.freeze(Time.now) do
+ old_check_set = create(
+ :compliance_check_set,
+ status: 'pending',
+ created_at: 4.hours.ago - 1.minute
+ )
+ current_check_set = create(:compliance_check_set, status: 'pending')
+
+ ComplianceCheckSet.abort_old
+
+ expect(current_check_set.reload.status).to eq('pending')
+ expect(old_check_set.reload.status).to eq('aborted')
+ end
+ end
+
+ it "doesn't work on check sets with a `finished_status`" do
+ Timecop.freeze(Time.now) do
+ check_set = create(
+ :compliance_check_set,
+ status: 'successful',
+ created_at: 4.hours.ago - 1.minute
+ )
+
+ ComplianceCheckSet.abort_old
+
+ expect(check_set.reload.status).to eq('successful')
+ end
+ end
+ end
end
diff --git a/spec/models/compliance_control_class_level_defaults/generic_attribute_control/pattern_cccld_spec.rb b/spec/models/compliance_control_class_level_defaults/generic_attribute_control/pattern_cccld_spec.rb
index 9610cc796..90bb660ee 100644
--- a/spec/models/compliance_control_class_level_defaults/generic_attribute_control/pattern_cccld_spec.rb
+++ b/spec/models/compliance_control_class_level_defaults/generic_attribute_control/pattern_cccld_spec.rb
@@ -4,4 +4,7 @@ RSpec.describe GenericAttributeControl::Pattern, type: :model do
let( :factory ){ :generic_attribute_control_pattern }
it_behaves_like 'ComplianceControl Class Level Defaults'
+ it_behaves_like 'has target attribute'
+
+ it { should validate_presence_of(:pattern) }
end
diff --git a/spec/models/compliance_control_class_level_defaults/generic_attribute_control/uniqueness_cccld_spec.rb b/spec/models/compliance_control_class_level_defaults/generic_attribute_control/uniqueness_cccld_spec.rb
index e4ab8d2cd..c4874b5a2 100644
--- a/spec/models/compliance_control_class_level_defaults/generic_attribute_control/uniqueness_cccld_spec.rb
+++ b/spec/models/compliance_control_class_level_defaults/generic_attribute_control/uniqueness_cccld_spec.rb
@@ -4,4 +4,5 @@ RSpec.describe GenericAttributeControl::Uniqueness, type: :model do
let( :factory ){ :generic_attribute_control_uniqueness }
it_behaves_like 'ComplianceControl Class Level Defaults'
+ it_behaves_like 'has target attribute'
end
diff --git a/spec/models/compliance_control_spec.rb b/spec/models/compliance_control_spec.rb
index 4267459ea..5cffba58d 100644
--- a/spec/models/compliance_control_spec.rb
+++ b/spec/models/compliance_control_spec.rb
@@ -1,5 +1,15 @@
RSpec.describe ComplianceControl, type: :model do
+ context 'dynamic attributes' do
+ let(:compliance_control1) { build_stubbed :compliance_control }
+ let(:compliance_control2) { build_stubbed :compliance_control, type: 'VehicleJouneyControl::TimeTable' }
+
+ it 'should always return a array' do
+ expect(compliance_control1.class.dynamic_attributes).to be_kind_of Array
+ expect(compliance_control2.class.dynamic_attributes).to be_kind_of Array
+ end
+ end
+
context 'standard validation' do
let(:compliance_control) { build_stubbed :compliance_control }
diff --git a/spec/models/compliance_control_validations/genric_attribute_validation/min_max_validation_spec.rb b/spec/models/compliance_control_validations/genric_attribute_validation/min_max_validation_spec.rb
index 4d30d61e3..138f7aae1 100644
--- a/spec/models/compliance_control_validations/genric_attribute_validation/min_max_validation_spec.rb
+++ b/spec/models/compliance_control_validations/genric_attribute_validation/min_max_validation_spec.rb
@@ -4,5 +4,6 @@ RSpec.describe GenericAttributeControl::MinMax do
subject{ build factory }
it_behaves_like 'has min_max_values'
+ it_behaves_like 'has target attribute'
end
diff --git a/spec/models/custom_field_spec.rb b/spec/models/custom_field_spec.rb
new file mode 100644
index 000000000..51128b0a2
--- /dev/null
+++ b/spec/models/custom_field_spec.rb
@@ -0,0 +1,35 @@
+require 'rails_helper'
+
+RSpec.describe CustomField, type: :model do
+ let( :vj ){ create :vehicle_journey, custom_field_values: {energy: 99} }
+
+ context "validates" do
+ it { should validate_uniqueness_of(:name).scoped_to(:resource_type, :workgroup_id) }
+ it { should validate_uniqueness_of(:code).scoped_to(:resource_type, :workgroup_id).case_insensitive }
+ end
+
+ context "field access" do
+ let( :custom_field ){ build_stubbed :custom_field }
+
+ it "option's values can be accessed by a key" do
+ expect( custom_field.options['capacity'] ).to eq("0")
+ end
+ end
+
+
+ context "custom fields for a resource" do
+ let!( :fields ){ [create(:custom_field), create(:custom_field, code: :energy)] }
+ let!( :instance_fields ){
+ {
+ fields[0].code => fields[0].slice(:code, :name, :field_type, :options).update(value: nil),
+ "energy" => fields[1].slice(:code, :name, :field_type, :options).update(value: 99)
+ }
+ }
+ it { expect(Chouette::VehicleJourney.custom_fields).to eq(fields) }
+ it { expect(vj.custom_fields).to eq(instance_fields) }
+ end
+
+ context "custom field_values for a resource" do
+ it { expect(vj.custom_field_value("energy")).to eq(99) }
+ end
+end
diff --git a/spec/models/import_spec.rb b/spec/models/import_spec.rb
index 3e4128865..8b85f151b 100644
--- a/spec/models/import_spec.rb
+++ b/spec/models/import_spec.rb
@@ -10,8 +10,9 @@ RSpec.describe Import, type: :model do
it { should validate_presence_of(:workbench) }
it { should validate_presence_of(:creator) }
- it { should allow_value('file.zip').for(:file).with_message(I18n.t('activerecord.errors.models.import.attributes.file.wrong_file_extension')) }
- it { should_not allow_values('file.json', 'file.png', 'file.pdf').for(:file) }
+ include ActionDispatch::TestProcess
+ it { should allow_value(fixture_file_upload('OFFRE_TRANSDEV_2017030112251.zip')).for(:file) }
+ it { should_not allow_value(fixture_file_upload('users.json')).for(:file).with_message(I18n.t('errors.messages.extension_whitelist_error', extension: '"json"', allowed_types: "zip")) }
let(:workbench_import) {netex_import.parent}
let(:workbench_import_with_completed_steps) do
@@ -28,6 +29,58 @@ RSpec.describe Import, type: :model do
)
end
+ describe ".abort_old" do
+ it "changes imports older than 4 hours to aborted" do
+ Timecop.freeze(Time.now) do
+ old_import = create(
+ :workbench_import,
+ status: 'pending',
+ created_at: 4.hours.ago - 1.minute
+ )
+ current_import = create(:workbench_import, status: 'pending')
+
+ Import.abort_old
+
+ expect(current_import.reload.status).to eq('pending')
+ expect(old_import.reload.status).to eq('aborted')
+ end
+ end
+
+ it "doesn't work on imports with a `finished_status`" do
+ Timecop.freeze(Time.now) do
+ import = create(
+ :workbench_import,
+ status: 'successful',
+ created_at: 4.hours.ago - 1.minute
+ )
+
+ Import.abort_old
+
+ expect(import.reload.status).to eq('successful')
+ end
+ end
+
+ it "only works on the caller type" do
+ Timecop.freeze(Time.now) do
+ workbench_import = create(
+ :workbench_import,
+ status: 'pending',
+ created_at: 4.hours.ago - 1.minute
+ )
+ netex_import = create(
+ :netex_import,
+ status: 'pending',
+ created_at: 4.hours.ago - 1.minute
+ )
+
+ NetexImport.abort_old
+
+ expect(workbench_import.reload.status).to eq('pending')
+ expect(netex_import.reload.status).to eq('aborted')
+ end
+ end
+ end
+
describe "#destroy" do
it "must destroy all child imports" do
netex_import = create(:netex_import)
diff --git a/spec/models/merge_spec.rb b/spec/models/merge_spec.rb
new file mode 100644
index 000000000..92f8f74b1
--- /dev/null
+++ b/spec/models/merge_spec.rb
@@ -0,0 +1,58 @@
+require "rails_helper"
+
+RSpec.describe Merge do
+
+ it "should work" do
+ stop_area_referential = FactoryGirl.create :stop_area_referential
+ 10.times { FactoryGirl.create :stop_area, stop_area_referential: stop_area_referential }
+
+ line_referential = FactoryGirl.create :line_referential
+ company = FactoryGirl.create :company, line_referential: line_referential
+ 10.times { FactoryGirl.create :line, line_referential: line_referential, company: company, network: nil }
+
+ workbench = FactoryGirl.create :workbench, line_referential: line_referential, stop_area_referential: stop_area_referential
+
+ referential_metadata = FactoryGirl.create(:referential_metadata, lines: line_referential.lines.limit(3))
+
+ referential = FactoryGirl.create :referential,
+ workbench: workbench,
+ organisation: workbench.organisation,
+ metadatas: [referential_metadata]
+
+ factor = 1
+
+ referential.switch do
+ line_referential.lines.each do |line|
+ factor.times do
+ stop_areas = stop_area_referential.stop_areas.order("random()").limit(5)
+ FactoryGirl.create :route, line: line, stop_areas: stop_areas, stop_points_count: 0
+ end
+ end
+
+ referential.routes.each do |route|
+ factor.times do
+ FactoryGirl.create :journey_pattern, route: route, stop_points: route.stop_points.sample(3)
+ end
+ end
+
+ referential.journey_patterns.each do |journey_pattern|
+ factor.times do
+ FactoryGirl.create :vehicle_journey, journey_pattern: journey_pattern, company: company
+ end
+ end
+
+ shared_time_table = FactoryGirl.create :time_table
+
+ referential.vehicle_journeys.each do |vehicle_journey|
+ vehicle_journey.time_tables << shared_time_table
+
+ specific_time_table = FactoryGirl.create :time_table
+ vehicle_journey.time_tables << specific_time_table
+ end
+ end
+
+ merge = Merge.create!(workbench: referential.workbench, referentials: [referential, referential])
+ merge.merge!
+ end
+
+end
diff --git a/spec/models/organisation_spec.rb b/spec/models/organisation_spec.rb
index 1217666f7..595b08058 100644
--- a/spec/models/organisation_spec.rb
+++ b/spec/models/organisation_spec.rb
@@ -2,8 +2,19 @@ describe Organisation, :type => :model do
it { should validate_presence_of(:name) }
it { should validate_uniqueness_of(:code) }
- it 'should have a valid factory' do
- expect(FactoryGirl.build(:organisation)).to be_valid
+ subject { build_stubbed :organisation }
+
+ it 'has a valid factory' do
+ expect_it.to be_valid
+ end
+
+ context 'lines_set' do
+ it 'has no lines' do
+ expect( subject.lines_set ).to eq(Set.new())
+ end
+ it 'has two lines' do
+ expect( build_stubbed(:org_with_lines).lines_set ).to eq(Set.new(%w{C00109 C00108}))
+ end
end
# it "create a rule_parameter_set" do
@@ -51,4 +62,26 @@ describe Organisation, :type => :model do
expect{Organisation.portail_sync}.to change{ Organisation.count }.by(4)
end
end
+
+ describe "#has_feature?" do
+
+ let(:organisation) { Organisation.new }
+
+ it 'return false if Organisation features is nil' do
+ organisation.features = nil
+ expect(organisation.has_feature?(:dummy)).to be_falsy
+ end
+
+ it 'return true if Organisation features contains given feature' do
+ organisation.features = %w{present}
+ expect(organisation.has_feature?(:present)).to be_truthy
+ end
+
+ it "return false if Organisation features doesn't contains given feature" do
+ organisation.features = %w{other}
+ expect(organisation.has_feature?(:absent)).to be_falsy
+ end
+
+ end
+
end
diff --git a/spec/models/referential/referential_lock_during_creation_spec.rb b/spec/models/referential/referential_lock_during_creation_spec.rb
new file mode 100644
index 000000000..717a96136
--- /dev/null
+++ b/spec/models/referential/referential_lock_during_creation_spec.rb
@@ -0,0 +1,198 @@
+RSpec.describe Referential, type: :model do
+ let (:workbench) { create(:workbench) }
+
+ def with_a_mutual_lock timeout: false
+ @with_a_mutual_lock = true
+ yield
+ thread_1 = Thread.new do
+ ActiveRecord::Base.transaction do
+ # seize LOCK
+ @locking_thread_content.try :call
+ sleep 10
+ # release LOCK
+ end
+ end
+
+ thread_2 = Thread.new do
+ sleep 5
+ ActiveRecord::Base.transaction do
+ if timeout
+ ActiveRecord::Base.connection.execute "SET lock_timeout = '1s'"
+ end
+ # waits for LOCK, (because of sleep 5)
+ @waiting_thread_content.try :call
+ # when lock was eventually obtained validation failed
+ end
+ end
+
+ thread_1.join
+ if timeout
+ expect do
+ thread_2.join
+ end.to raise_error(TableLockTimeoutError)
+ else
+ thread_2.join
+ end
+ @locking_thread_content = nil
+ @waiting_thread_content = nil
+ @with_a_mutual_lock = false
+ end
+
+ def locking_thread
+ raise "this method is intended to be called inside a `with_a_mutual_lock`" unless @with_a_mutual_lock
+ @locking_thread_content = yield
+ end
+
+ def waiting_thread
+ @waiting_thread_content = yield
+ end
+
+ context "when two identical Referentials are created, only one is saved" do
+ it "works synchronously" do
+ referential_1 = build(
+ :referential,
+ workbench: workbench,
+ organisation: workbench.organisation
+ )
+ referential_2 = referential_1.dup
+ referential_2.slug = "#{referential_1.slug}_different"
+
+ metadata_1 = build(:referential_metadata, referential: nil)
+ metadata_2 = metadata_1.dup
+
+ referential_1.metadatas << metadata_1
+ referential_2.metadatas << metadata_2
+
+ referential_1.save
+ referential_2.save
+
+ expect(referential_1).to be_persisted
+ expect(referential_2).not_to be_persisted
+ end
+
+ context truncation: true do
+ it "works asynchronously" do
+ skip('The truncation strategy breaks all subsequent tests (See #5295)')
+
+ begin
+ referential_1 = build(
+ :referential,
+ workbench: workbench,
+ organisation: workbench.organisation
+ )
+ referential_2 = referential_1.dup
+ referential_2.slug = "#{referential_1.slug}_different"
+ referential_3 = nil
+
+ metadata_1 = build(:referential_metadata, referential: nil)
+ metadata_2 = metadata_1.dup
+
+ referential_1.metadatas << metadata_1
+ referential_2.metadatas << metadata_2
+
+ with_a_mutual_lock do
+ locking_thread do
+ referential_1.save
+ end
+ waiting_thread do
+ referential_2.save
+ referential_3 = create(:referential)
+ end
+ end
+
+ expect(referential_1).to be_persisted
+ expect(referential_2).not_to be_persisted
+ expect(referential_3).to be_persisted
+ ensure
+ Apartment::Tenant.drop(referential_1.slug) if referential_1.persisted?
+ Apartment::Tenant.drop(referential_2.slug) if referential_2.persisted?
+
+ if referential_3.try(:persisted?)
+ Apartment::Tenant.drop(referential_3.slug)
+ end
+ end
+ end
+
+ it "works asynchronously when one is updated" do
+ skip('The truncation strategy breaks all subsequent tests (See #5295)')
+
+ begin
+ referential_1 = nil
+ referential_2 = nil
+
+ ActiveRecord::Base.transaction do
+ referential_1 = create(
+ :referential,
+ workbench: workbench,
+ organisation: workbench.organisation
+ )
+ referential_2 = referential_1.dup
+ referential_2.name = 'Another'
+ referential_2.slug = "#{referential_1.slug}_different"
+ referential_2.save!
+ end
+
+ metadata_2 = build(:referential_metadata, referential: nil)
+ metadata_1 = metadata_2.dup
+ with_a_mutual_lock do
+ locking_thread do
+ referential_1.metadatas_attributes = [metadata_1.attributes]
+ referential_1.save
+ end
+ waiting_thread do
+ referential_2.metadatas_attributes = [metadata_2.attributes]
+ referential_2.save
+ end
+ end
+
+ expect(referential_1).to be_valid
+ expect(referential_2).not_to be_valid
+ ensure
+ Apartment::Tenant.drop(referential_1.slug) if referential_1.persisted?
+ Apartment::Tenant.drop(referential_2.slug) if referential_2.persisted?
+ end
+ end
+ end
+ end
+
+ context "when two Referentials are created at the same time", truncation: true do
+ it "raises an error when the DB lock timeout is reached" do
+ skip('The truncation strategy breaks all subsequent tests (See #5295)')
+
+ begin
+ referential_1 = build(
+ :referential,
+ workbench: workbench,
+ organisation: workbench.organisation
+ )
+ referential_2 = referential_1.dup
+ referential_2.slug = "#{referential_1.slug}_different"
+ referential_3 = nil
+
+ metadata_1 = build(:referential_metadata, referential: nil)
+ metadata_2 = metadata_1.dup
+
+ referential_1.metadatas << metadata_1
+ referential_2.metadatas << metadata_2
+ with_a_mutual_lock timeout: true do
+ locking_thread do
+ referential_1.save
+ end
+ waiting_thread do
+ referential_2.save
+ referential_3 = create(:referential)
+ end
+ end
+
+ expect(referential_1).to be_persisted
+ ensure
+ Apartment::Tenant.drop(referential_1.slug) if referential_1.persisted?
+ Apartment::Tenant.drop(referential_2.slug) if referential_2.persisted?
+
+ if referential_3.try(:persisted?)
+ Apartment::Tenant.drop(referential_3.slug)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/referential_cloning_spec.rb b/spec/models/referential_cloning_spec.rb
index 5acd433ec..815e05a67 100644
--- a/spec/models/referential_cloning_spec.rb
+++ b/spec/models/referential_cloning_spec.rb
@@ -1,6 +1,7 @@
require 'spec_helper'
RSpec.describe ReferentialCloning, :type => :model do
+
it 'should have a valid factory' do
expect(FactoryGirl.build(:referential_cloning)).to be_valid
end
@@ -8,11 +9,79 @@ RSpec.describe ReferentialCloning, :type => :model do
it { should belong_to :source_referential }
it { should belong_to :target_referential }
- describe "ReferentialCloningWorker" do
+ describe 'after commit' do
+ let(:referential_cloning) { FactoryGirl.create(:referential_cloning) }
+
+ it 'invoke clone method' do
+ expect(referential_cloning).to receive(:clone)
+ referential_cloning.run_callbacks(:commit)
+ end
+ end
+
+ describe '#clone' do
let(:referential_cloning) { FactoryGirl.create(:referential_cloning) }
it "should schedule a job in worker" do
- expect{referential_cloning.run_callbacks(:commit)}.to change {ReferentialCloningWorker.jobs.count}.by(1)
+ expect{referential_cloning.clone}.to change {ReferentialCloningWorker.jobs.count}.by(1)
end
end
+
+ describe '#clone!' do
+ let(:source_referential) { Referential.new slug: "source"}
+ let(:target_referential) { Referential.new slug: "target"}
+ let(:referential_cloning) do
+ ReferentialCloning.new source_referential: source_referential,
+ target_referential: target_referential
+ end
+
+ let(:cloner) { double }
+
+ it 'creates a schema cloner with source and target schemas and clone schema' do
+ expect(AF83::SchemaCloner).to receive(:new).with(source_referential.slug, target_referential.slug).and_return(cloner)
+ expect(cloner).to receive(:clone_schema)
+
+ referential_cloning.clone!
+ end
+ end
+
+ describe '#clone_with_status!' do
+ let(:referential_cloning) do
+ ReferentialCloning.new(target_referential: Referential.new(slug: "target"))
+ end
+
+ before do
+ allow(referential_cloning).to receive(:clone!)
+ end
+
+ it 'invokes clone! method' do
+ expect(referential_cloning).to receive(:clone!)
+ referential_cloning.clone_with_status!
+ end
+
+ context 'when clone_schema is performed without error' do
+ it "should have successful status" do
+ referential_cloning.clone_with_status!
+ expect(referential_cloning.status).to eq("successful")
+ end
+ end
+
+ context 'when clone_schema raises an error' do
+ it "should have failed status" do
+ expect(referential_cloning).to receive(:clone!).and_raise("#fail")
+ referential_cloning.clone_with_status!
+ expect(referential_cloning.status).to eq("failed")
+ end
+ end
+
+ it "defines started_at" do
+ referential_cloning.clone_with_status!
+ expect(referential_cloning.started_at).not_to be_nil
+ end
+
+ it "defines ended_at" do
+ referential_cloning.clone_with_status!
+ expect(referential_cloning.ended_at).not_to be_nil
+ end
+
+ end
end
diff --git a/spec/models/referential_spec.rb b/spec/models/referential_spec.rb
index d0b1d6447..6d699f759 100644
--- a/spec/models/referential_spec.rb
+++ b/spec/models/referential_spec.rb
@@ -1,13 +1,6 @@
-require 'spec_helper'
-
describe Referential, :type => :model do
let(:ref) { create :workbench_referential, metadatas: [create(:referential_metadata)] }
- # it "create a rule_parameter_set" do
- # referential = create(:referential)
- # expect(referential.rule_parameter_sets.size).to eq(1)
- # end
-
it { should have_many(:metadatas) }
it { should belong_to(:workbench) }
it { should belong_to(:referential_suite) }
@@ -131,4 +124,40 @@ describe Referential, :type => :model do
end
end
end
+
+ context "to be referential_read_only or not to be referential_read_only" do
+ let( :referential ){ build_stubbed( :referential ) }
+
+ context "in the beginning" do
+ it{ expect( referential ).not_to be_referential_read_only }
+ end
+
+ context "after archivation" do
+ before{ referential.archived_at = 1.day.ago }
+ it{ expect( referential ).to be_referential_read_only }
+ end
+
+ context "used in a ReferentialSuite" do
+ before { referential.referential_suite_id = 42 }
+
+ it{ expect( referential ).to be_referential_read_only }
+
+ it "return true to in_referential_suite?" do
+ expect(referential).to be_in_referential_suite
+ end
+
+ it "don't use detect_overlapped_referentials in validation" do
+ expect(referential).to_not receive(:detect_overlapped_referentials)
+ expect(referential).to be_valid
+ end
+ end
+
+ context "archived and finalised" do
+ before do
+ referential.archived_at = 1.month.ago
+ referential.referential_suite_id = 53
+ end
+ it{ expect( referential ).to be_referential_read_only }
+ end
+ end
end
diff --git a/spec/models/workbench_spec.rb b/spec/models/workbench_spec.rb
index 3b9ed6b07..2f1fe39da 100644
--- a/spec/models/workbench_spec.rb
+++ b/spec/models/workbench_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe Workbench, :type => :model do
it { should belong_to(:organisation) }
it { should belong_to(:line_referential) }
it { should belong_to(:stop_area_referential) }
+ it { should belong_to(:workgroup) }
it { should belong_to(:output).class_name('ReferentialSuite') }
it { should have_many(:lines).through(:line_referential) }
@@ -36,7 +37,7 @@ RSpec.describe Workbench, :type => :model do
let(:workbench) { create :workbench, organisation: organisation }
it 'should filter lines based on my organisation functional_scope' do
- ids.insert('STIF:CODIFLIGNE:Line:0000').each do |id|
+ (ids + ['STIF:CODIFLIGNE:Line:0000']).each do |id|
create :line, objectid: id, line_referential: workbench.line_referential
end
lines = workbench.lines
diff --git a/spec/models/workgroup_spec.rb b/spec/models/workgroup_spec.rb
new file mode 100644
index 000000000..ac8d3fc98
--- /dev/null
+++ b/spec/models/workgroup_spec.rb
@@ -0,0 +1,30 @@
+require 'rails_helper'
+
+RSpec.describe Workgroup, type: :model do
+ context "associations" do
+ let( :workgroup ){ build_stubbed :workgroup, line_referential_id: 53, stop_area_referential_id: 42 }
+
+ it{ should have_many(:workbenches) }
+ it{ should validate_uniqueness_of(:name) }
+
+ it 'is not valid without a stop_area_referential' do
+ workgroup.stop_area_referential_id = nil
+ expect( workgroup ).not_to be_valid
+ end
+ it 'is not valid without a line_referential' do
+ workgroup.line_referential_id = nil
+ expect( workgroup ).not_to be_valid
+ end
+ it 'is valid with both assoications' do
+ expect( workgroup ).to be_valid
+ end
+ end
+
+ context "find organisations" do
+ let( :workgroup ){ create :workgroup }
+ let!( :workbench1 ){ create :workbench, workgroup: workgroup }
+ let!( :workbench2 ){ create :workbench, workgroup: workgroup }
+
+ it{ expect( Set.new(workgroup.organisations) ).to eq(Set.new([ workbench1.organisation, workbench2.organisation ])) }
+ end
+end
diff --git a/spec/policies/access_link_policy_spec.rb b/spec/policies/access_link_policy_spec.rb
index 6194ae55c..9ba3ffa45 100644
--- a/spec/policies/access_link_policy_spec.rb
+++ b/spec/policies/access_link_policy_spec.rb
@@ -3,18 +3,18 @@ RSpec.describe AccessLinkPolicy, type: :policy do
let( :record ){ build_stubbed :access_link }
permissions :create? do
- it_behaves_like 'permitted policy and same organisation', "access_links.create", archived: true
+ it_behaves_like 'permitted policy and same organisation', "access_links.create", archived_and_finalised: true
end
permissions :destroy? do
- it_behaves_like 'permitted policy and same organisation', "access_links.destroy", archived: true
+ it_behaves_like 'permitted policy and same organisation', "access_links.destroy", archived_and_finalised: true
end
permissions :edit? do
- it_behaves_like 'permitted policy and same organisation', "access_links.update", archived: true
+ it_behaves_like 'permitted policy and same organisation', "access_links.update", archived_and_finalised: true
end
permissions :new? do
- it_behaves_like 'permitted policy and same organisation', "access_links.create", archived: true
+ it_behaves_like 'permitted policy and same organisation', "access_links.create", archived_and_finalised: true
end
permissions :update? do
- it_behaves_like 'permitted policy and same organisation', "access_links.update", archived: true
+ it_behaves_like 'permitted policy and same organisation', "access_links.update", archived_and_finalised: true
end
end
diff --git a/spec/policies/access_point_policy_spec.rb b/spec/policies/access_point_policy_spec.rb
index b6bc46eb4..ec7bf1486 100644
--- a/spec/policies/access_point_policy_spec.rb
+++ b/spec/policies/access_point_policy_spec.rb
@@ -3,18 +3,18 @@ RSpec.describe AccessPointPolicy, type: :policy do
let( :record ){ build_stubbed :access_point }
permissions :create? do
- it_behaves_like 'permitted policy and same organisation', "access_points.create", archived: true
+ it_behaves_like 'permitted policy and same organisation', "access_points.create", archived_and_finalised: true
end
permissions :destroy? do
- it_behaves_like 'permitted policy and same organisation', "access_points.destroy", archived: true
+ it_behaves_like 'permitted policy and same organisation', "access_points.destroy", archived_and_finalised: true
end
permissions :edit? do
- it_behaves_like 'permitted policy and same organisation', "access_points.update", archived: true
+ it_behaves_like 'permitted policy and same organisation', "access_points.update", archived_and_finalised: true
end
permissions :new? do
- it_behaves_like 'permitted policy and same organisation', "access_points.create", archived: true
+ it_behaves_like 'permitted policy and same organisation', "access_points.create", archived_and_finalised: true
end
permissions :update? do
- it_behaves_like 'permitted policy and same organisation', "access_points.update", archived: true
+ it_behaves_like 'permitted policy and same organisation', "access_points.update", archived_and_finalised: true
end
end
diff --git a/spec/policies/calendar_policy_spec.rb b/spec/policies/calendar_policy_spec.rb
index 294be8198..144a1c6bb 100644
--- a/spec/policies/calendar_policy_spec.rb
+++ b/spec/policies/calendar_policy_spec.rb
@@ -5,18 +5,24 @@ RSpec.describe CalendarPolicy, type: :policy do
permissions :create? do
- it_behaves_like 'permitted policy', 'calendars.create', archived: true
+ it_behaves_like 'permitted policy', 'calendars.create'
+ end
+ permissions :share? do
+ it_behaves_like 'permitted policy and same organisation', 'calendars.share'
+ end
+ permissions :share? do
+ it_behaves_like 'permitted policy and same organisation', 'calendars.share'
end
permissions :destroy? do
- it_behaves_like 'permitted policy and same organisation', 'calendars.destroy', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'calendars.destroy'
end
permissions :edit? do
- it_behaves_like 'permitted policy and same organisation', 'calendars.update', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'calendars.update'
end
permissions :new? do
- it_behaves_like 'permitted policy', 'calendars.create', archived: true
+ it_behaves_like 'permitted policy', 'calendars.create'
end
permissions :update? do
- it_behaves_like 'permitted policy and same organisation', 'calendars.update', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'calendars.update'
end
end
diff --git a/spec/policies/company_policy_spec.rb b/spec/policies/company_policy_spec.rb
index e018902ca..16225c441 100644
--- a/spec/policies/company_policy_spec.rb
+++ b/spec/policies/company_policy_spec.rb
@@ -1,4 +1,3 @@
-# coding: utf-8
RSpec.describe CompanyPolicy, type: :policy do
let( :record ){ build_stubbed :company }
@@ -11,10 +10,10 @@ RSpec.describe CompanyPolicy, type: :policy do
context 'Non Destructive actions →' do
permissions :index? do
- it_behaves_like 'always allowed', 'anything', archived: true
+ it_behaves_like 'always allowed', 'anything', archived_and_finalised: true
end
permissions :show? do
- it_behaves_like 'always allowed', 'anything', archived: true
+ it_behaves_like 'always allowed', 'anything', archived_and_finalised: true
end
end
diff --git a/spec/policies/connection_link_policy_spec.rb b/spec/policies/connection_link_policy_spec.rb
index 23e40abe3..6fc9f95df 100644
--- a/spec/policies/connection_link_policy_spec.rb
+++ b/spec/policies/connection_link_policy_spec.rb
@@ -3,18 +3,18 @@ RSpec.describe ConnectionLinkPolicy, type: :policy do
let( :record ){ build_stubbed :connection_link }
permissions :create? do
- it_behaves_like 'permitted policy and same organisation', "connection_links.create", archived: true
+ it_behaves_like 'permitted policy and same organisation', "connection_links.create", archived_and_finalised: true
end
permissions :destroy? do
- it_behaves_like 'permitted policy and same organisation', "connection_links.destroy", archived: true
+ it_behaves_like 'permitted policy and same organisation', "connection_links.destroy", archived_and_finalised: true
end
permissions :edit? do
- it_behaves_like 'permitted policy and same organisation', "connection_links.update", archived: true
+ it_behaves_like 'permitted policy and same organisation', "connection_links.update", archived_and_finalised: true
end
permissions :new? do
- it_behaves_like 'permitted policy and same organisation', "connection_links.create", archived: true
+ it_behaves_like 'permitted policy and same organisation', "connection_links.create", archived_and_finalised: true
end
permissions :update? do
- it_behaves_like 'permitted policy and same organisation', "connection_links.update", archived: true
+ it_behaves_like 'permitted policy and same organisation', "connection_links.update", archived_and_finalised: true
end
end
diff --git a/spec/policies/group_of_line_policy_spec.rb b/spec/policies/group_of_line_policy_spec.rb
index 29fbb1bfb..0aeab97bd 100644
--- a/spec/policies/group_of_line_policy_spec.rb
+++ b/spec/policies/group_of_line_policy_spec.rb
@@ -10,10 +10,10 @@ RSpec.describe GroupOfLinePolicy, type: :policy do
context 'Non Destructive actions →' do
permissions :index? do
- it_behaves_like 'always allowed', 'anything', archived: true
+ it_behaves_like 'always allowed', 'anything', archived_and_finalised: true
end
permissions :show? do
- it_behaves_like 'always allowed', 'anything', archived: true
+ it_behaves_like 'always allowed', 'anything', archived_and_finalised: true
end
end
@@ -24,19 +24,19 @@ RSpec.describe GroupOfLinePolicy, type: :policy do
context 'Destructive actions →' do
permissions :create? do
- it_behaves_like 'always forbidden', 'group_of_lines.create', archived: true
+ it_behaves_like 'always forbidden', 'group_of_lines.create', archived_and_finalised: true
end
permissions :destroy? do
- it_behaves_like 'always forbidden', 'group_of_lines.destroy', archived: true
+ it_behaves_like 'always forbidden', 'group_of_lines.destroy', archived_and_finalised: true
end
permissions :edit? do
- it_behaves_like 'always forbidden', 'group_of_lines.update', archived: true
+ it_behaves_like 'always forbidden', 'group_of_lines.update', archived_and_finalised: true
end
permissions :new? do
- it_behaves_like 'always forbidden', 'group_of_lines.create', archived: true
+ it_behaves_like 'always forbidden', 'group_of_lines.create', archived_and_finalised: true
end
permissions :update? do
- it_behaves_like 'always forbidden', 'group_of_lines.update', archived: true
+ it_behaves_like 'always forbidden', 'group_of_lines.update', archived_and_finalised: true
end
end
end
diff --git a/spec/policies/journey_pattern_policy_spec.rb b/spec/policies/journey_pattern_policy_spec.rb
index 39f849277..b5e72d813 100644
--- a/spec/policies/journey_pattern_policy_spec.rb
+++ b/spec/policies/journey_pattern_policy_spec.rb
@@ -3,18 +3,18 @@ RSpec.describe JourneyPatternPolicy, type: :policy do
let( :record ){ build_stubbed :journey_pattern }
permissions :create? do
- it_behaves_like 'permitted policy and same organisation', "journey_patterns.create", archived: true
+ it_behaves_like 'permitted policy and same organisation', "journey_patterns.create", archived_and_finalised: true
end
permissions :destroy? do
- it_behaves_like 'permitted policy and same organisation', "journey_patterns.destroy", archived: true
+ it_behaves_like 'permitted policy and same organisation', "journey_patterns.destroy", archived_and_finalised: true
end
permissions :edit? do
- it_behaves_like 'permitted policy and same organisation', "journey_patterns.update", archived: true
+ it_behaves_like 'permitted policy and same organisation', "journey_patterns.update", archived_and_finalised: true
end
permissions :new? do
- it_behaves_like 'permitted policy and same organisation', "journey_patterns.create", archived: true
+ it_behaves_like 'permitted policy and same organisation', "journey_patterns.create", archived_and_finalised: true
end
permissions :update? do
- it_behaves_like 'permitted policy and same organisation', "journey_patterns.update", archived: true
+ it_behaves_like 'permitted policy and same organisation', "journey_patterns.update", archived_and_finalised: true
end
end
diff --git a/spec/policies/line_policy_spec.rb b/spec/policies/line_policy_spec.rb
index 452606bcf..555008abf 100644
--- a/spec/policies/line_policy_spec.rb
+++ b/spec/policies/line_policy_spec.rb
@@ -1,4 +1,3 @@
-# coding: utf-8
RSpec.describe LinePolicy, type: :policy do
let( :record ){ build_stubbed :line }
@@ -11,10 +10,10 @@ RSpec.describe LinePolicy, type: :policy do
context 'Non Destructive actions →' do
permissions :index? do
- it_behaves_like 'always allowed', 'anything', archived: true
+ it_behaves_like 'always allowed', 'anything', archived_and_finalised: true
end
permissions :show? do
- it_behaves_like 'always allowed', 'anything', archived: true
+ it_behaves_like 'always allowed', 'anything', archived_and_finalised: true
end
end
@@ -47,14 +46,14 @@ RSpec.describe LinePolicy, type: :policy do
# ---------------------------
permissions :create_footnote? do
- it_behaves_like 'permitted policy and same organisation', 'footnotes.create', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'footnotes.create', archived_and_finalised: true
end
permissions :destroy_footnote? do
- it_behaves_like 'permitted policy and same organisation', 'footnotes.destroy', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'footnotes.destroy', archived_and_finalised: true
end
permissions :update_footnote? do
- it_behaves_like 'permitted policy and same organisation', 'footnotes.update', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'footnotes.update', archived_and_finalised: true
end
end
diff --git a/spec/policies/line_referential_policy_spec.rb b/spec/policies/line_referential_policy_spec.rb
new file mode 100644
index 000000000..7e0a9da8e
--- /dev/null
+++ b/spec/policies/line_referential_policy_spec.rb
@@ -0,0 +1,9 @@
+RSpec.describe LineReferentialPolicy, type: :policy do
+
+ let( :record ){ build_stubbed :line_referential }
+ before { stub_policy_scope(record) }
+
+ permissions :synchronize? do
+ it_behaves_like 'permitted policy', 'line_referentials.synchronize'
+ end
+end
diff --git a/spec/policies/network_policy_spec.rb b/spec/policies/network_policy_spec.rb
index c09546c22..2b7bbcdca 100644
--- a/spec/policies/network_policy_spec.rb
+++ b/spec/policies/network_policy_spec.rb
@@ -10,10 +10,10 @@ RSpec.describe Chouette::NetworkPolicy, type: :policy do
context 'Non Destructive actions →' do
permissions :index? do
- it_behaves_like 'always allowed', 'anything', archived: true
+ it_behaves_like 'always allowed', 'anything', archived_and_finalised: true
end
permissions :show? do
- it_behaves_like 'always allowed', 'anything', archived: true
+ it_behaves_like 'always allowed', 'anything', archived_and_finalised: true
end
end
@@ -24,19 +24,19 @@ RSpec.describe Chouette::NetworkPolicy, type: :policy do
context 'Destructive actions →' do
permissions :create? do
- it_behaves_like 'always forbidden', 'networks.create', archived: true
+ it_behaves_like 'permitted policy', 'networks.create'
end
permissions :destroy? do
- it_behaves_like 'always forbidden', 'networks.destroy', archived: true
+ it_behaves_like 'permitted policy', 'networks.destroy'
end
permissions :edit? do
- it_behaves_like 'always forbidden', 'networks.update', archived: true
+ it_behaves_like 'permitted policy', 'networks.update'
end
permissions :new? do
- it_behaves_like 'always forbidden', 'networks.create', archived: true
+ it_behaves_like 'permitted policy', 'networks.create'
end
permissions :update? do
- it_behaves_like 'always forbidden', 'networks.update', archived: true
+ it_behaves_like 'permitted policy', 'networks.update'
end
end
end
diff --git a/spec/policies/purchase_window_policy_spec.rb b/spec/policies/purchase_window_policy_spec.rb
new file mode 100644
index 000000000..184152cec
--- /dev/null
+++ b/spec/policies/purchase_window_policy_spec.rb
@@ -0,0 +1,15 @@
+RSpec.describe PurchaseWindowPolicy, type: :policy do
+
+ let( :record ){ build_stubbed :purchase_window }
+ before { stub_policy_scope(record) }
+
+ permissions :create? do
+ it_behaves_like 'permitted policy and same organisation', "purchase_windows.create", archived_and_finalised: true
+ end
+ permissions :destroy? do
+ it_behaves_like 'permitted policy and same organisation', "purchase_windows.destroy", archived_and_finalised: true
+ end
+ permissions :update? do
+ it_behaves_like 'permitted policy and same organisation', "purchase_windows.update", archived_and_finalised: true
+ end
+end
diff --git a/spec/policies/referential_policy_spec.rb b/spec/policies/referential_policy_spec.rb
index d00415fc6..778e14901 100644
--- a/spec/policies/referential_policy_spec.rb
+++ b/spec/policies/referential_policy_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
RSpec.describe ReferentialPolicy, type: :policy do
let( :record ){ build_stubbed :referential }
@@ -32,22 +33,22 @@ RSpec.describe ReferentialPolicy, type: :policy do
# ---------------------------------------
permissions :destroy? do
- it_behaves_like 'permitted policy and same organisation', 'referentials.destroy', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'referentials.destroy', archived_and_finalised: true
end
permissions :edit? do
- it_behaves_like 'permitted policy and same organisation', 'referentials.update', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'referentials.update', archived_and_finalised: true
end
permissions :update? do
- it_behaves_like 'permitted policy and same organisation', 'referentials.update', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'referentials.update', archived_and_finalised: true
end
#
# Custom Permissions
# ------------------
- permissions :clone? do
- it_behaves_like 'permitted policy', 'referentials.create', archived: true
- end
+ # permissions :clone? do
+ # it_behaves_like 'permitted policy', 'referentials.create', archived_and_finalised: true
+ # end
permissions :archive? do
diff --git a/spec/policies/route_policy_spec.rb b/spec/policies/route_policy_spec.rb
index df2e41a89..5dc8be76f 100644
--- a/spec/policies/route_policy_spec.rb
+++ b/spec/policies/route_policy_spec.rb
@@ -3,26 +3,26 @@ RSpec.describe Chouette::RoutePolicy, type: :policy do
let( :record ){ build_stubbed :route }
permissions :create? do
- it_behaves_like 'permitted policy and same organisation', 'routes.create', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'routes.create', archived_and_finalised: true
end
permissions :duplicate? do
- it_behaves_like 'permitted policy and same organisation', 'routes.create', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'routes.create', archived_and_finalised: true
end
permissions :destroy? do
- it_behaves_like 'permitted policy and same organisation', 'routes.destroy', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'routes.destroy', archived_and_finalised: true
end
permissions :edit? do
- it_behaves_like 'permitted policy and same organisation', 'routes.update', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'routes.update', archived_and_finalised: true
end
permissions :new? do
- it_behaves_like 'permitted policy and same organisation', 'routes.create', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'routes.create', archived_and_finalised: true
end
permissions :update? do
- it_behaves_like 'permitted policy and same organisation', 'routes.update', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'routes.update', archived_and_finalised: true
end
end
diff --git a/spec/policies/routing_constraint_zone_policy_spec.rb b/spec/policies/routing_constraint_zone_policy_spec.rb
index 2ef15fa95..d619649d3 100644
--- a/spec/policies/routing_constraint_zone_policy_spec.rb
+++ b/spec/policies/routing_constraint_zone_policy_spec.rb
@@ -4,22 +4,22 @@ RSpec.describe RoutingConstraintZonePolicy, type: :policy do
permissions :create? do
- it_behaves_like 'permitted policy and same organisation', 'routing_constraint_zones.create', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'routing_constraint_zones.create', archived_and_finalised: true
end
permissions :destroy? do
- it_behaves_like 'permitted policy and same organisation', 'routing_constraint_zones.destroy', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'routing_constraint_zones.destroy', archived_and_finalised: true
end
permissions :edit? do
- it_behaves_like 'permitted policy and same organisation', 'routing_constraint_zones.update', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'routing_constraint_zones.update', archived_and_finalised: true
end
permissions :new? do
- it_behaves_like 'permitted policy and same organisation', 'routing_constraint_zones.create', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'routing_constraint_zones.create', archived_and_finalised: true
end
permissions :update? do
- it_behaves_like 'permitted policy and same organisation', 'routing_constraint_zones.update', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'routing_constraint_zones.update', archived_and_finalised: true
end
end
diff --git a/spec/policies/sto_area_referential_policy_spec.rb b/spec/policies/sto_area_referential_policy_spec.rb
new file mode 100644
index 000000000..5bd6da427
--- /dev/null
+++ b/spec/policies/sto_area_referential_policy_spec.rb
@@ -0,0 +1,9 @@
+RSpec.describe StopAreaReferentialPolicy, type: :policy do
+
+ let( :record ){ build_stubbed :stop_area_referential }
+ before { stub_policy_scope(record) }
+
+ permissions :synchronize? do
+ it_behaves_like 'permitted policy', 'stop_area_referentials.synchronize'
+ end
+end
diff --git a/spec/policies/stop_area_policy_spec.rb b/spec/policies/stop_area_policy_spec.rb
index 90835d1d8..8144c16e2 100644
--- a/spec/policies/stop_area_policy_spec.rb
+++ b/spec/policies/stop_area_policy_spec.rb
@@ -11,10 +11,10 @@ RSpec.describe StopAreaPolicy, type: :policy do
context 'Non Destructive actions →' do
permissions :index? do
- it_behaves_like 'always allowed', 'anything', archived: true
+ it_behaves_like 'always allowed', 'anything', archived_and_finalised: true
end
permissions :show? do
- it_behaves_like 'always allowed', 'anything', archived: true
+ it_behaves_like 'always allowed', 'anything', archived_and_finalised: true
end
end
diff --git a/spec/policies/time_table_policy_spec.rb b/spec/policies/time_table_policy_spec.rb
index dad3c13bc..5a2abc61d 100644
--- a/spec/policies/time_table_policy_spec.rb
+++ b/spec/policies/time_table_policy_spec.rb
@@ -3,22 +3,22 @@ RSpec.describe TimeTablePolicy, type: :policy do
let( :record ){ build_stubbed :time_table }
permissions :create? do
- it_behaves_like 'permitted policy and same organisation', 'time_tables.create', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'time_tables.create', archived_and_finalised: true
end
permissions :destroy? do
- it_behaves_like 'permitted policy and same organisation', 'time_tables.destroy', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'time_tables.destroy', archived_and_finalised: true
end
permissions :edit? do
- it_behaves_like 'permitted policy and same organisation', 'time_tables.update', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'time_tables.update', archived_and_finalised: true
end
permissions :new? do
- it_behaves_like 'permitted policy and same organisation', 'time_tables.create', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'time_tables.create', archived_and_finalised: true
end
permissions :update? do
- it_behaves_like 'permitted policy and same organisation', 'time_tables.update', archived: true
+ it_behaves_like 'permitted policy and same organisation', 'time_tables.update', archived_and_finalised: true
end
end
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
index 47578405e..9eb628d95 100644
--- a/spec/rails_helper.rb
+++ b/spec/rails_helper.rb
@@ -32,11 +32,6 @@ RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
- # If you're not using ActiveRecord, or you'd prefer not to run each of your
- # examples within a transaction, remove the following line or assign false
- # instead of true.
- config.use_transactional_fixtures = true
-
# RSpec Rails can automatically mix in different behaviours to your tests
# based on their file location, for example enabling you to call `get` and
# `post` in specs under `spec/controllers`.
diff --git a/spec/requests/api/v1/netex_import_spec.rb b/spec/requests/api/v1/netex_import_spec.rb
index a90e51e5b..8597c1d32 100644
--- a/spec/requests/api/v1/netex_import_spec.rb
+++ b/spec/requests/api/v1/netex_import_spec.rb
@@ -32,18 +32,18 @@ RSpec.describe "NetexImport", type: :request do
let( :authorization ){ authorization_token_header( get_api_key.token ) }
#TODO Check why referential_id is nil
it 'succeeds' do
- 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
+ # 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
@@ -54,24 +54,21 @@ RSpec.describe "NetexImport", type: :request do
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
- 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
+ it 'creates a correct Referential', pending: 'see #5073' 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
- context 'with incorrect credentials and correct request', pending: "see #4311" do
+ context 'with incorrect credentials and correct request', pending: "see #4311 & #5072" do
let( :authorization ){ authorization_token_header( "#{referential.id}-incorrect_token") }
it 'does not create any DB object and does not succeed' do
diff --git a/spec/services/meta_zip_data_spec.rb b/spec/services/meta_zip_data_spec.rb
new file mode 100644
index 000000000..1cbfee008
--- /dev/null
+++ b/spec/services/meta_zip_data_spec.rb
@@ -0,0 +1,55 @@
+# Convenience meta spec to debug potential bugs in zip support helpers
+# uncomment run and check files in `zip_fixtures_path`
+#
+# It also describes what the two helpers do and therefore facilitates the usage of
+#
+# * `make_zip` and
+# * `make_zip_from_tree
+#
+RSpec.describe 'ZipData', type: [:zip, :meta] do
+
+ # let( :zip_file ){ zip_fixtures_path('xxx.zip') }
+ # let( :tmp_output ){ zip_fixtures_path('tmp') }
+
+ # before do
+ # clear_all_zip_fixtures!
+ # Dir.mkdir(tmp_output)
+ # end
+
+ # context 'a simple archive' do
+ # let( :zip_data ){ make_zip "xxx.zip", archive_content }
+ # let( :archive_content ){ {
+ # 'hello.txt' => 'hello',
+ # 'subdir/too.txt' => 'in a subdir'
+ # } }
+
+ # it 'handmade: plausibility and manual check' do
+ # zip_data.write_to(zip_file)
+ # %x{unzip -oqq #{zip_file} -d #{tmp_output}}
+ # archive_content.each do | rel_path, content |
+ # expect(File.read(File.join(tmp_output, rel_path))).to eq(content)
+ # end
+ # end
+ # end
+
+ # context 'archive from dir tree' do
+ # let( :dir ){ fixtures_path 'meta_zip' }
+ # let( :zip_data ){ make_zip_from_tree dir }
+
+ # let( :archive_content ){ {
+ # 'one/alpha' => "alpha\n",
+ # 'two/beta' => "beta\n",
+ # 'two/subdir/gamma' => "gamma\n"
+ # } }
+
+ # it 'directory: plausibility and manual check' do
+ # zip_data.write_to(zip_file)
+ # %x{unzip -oqq #{zip_file} -d #{tmp_output}}
+ # archive_content.each do | rel_path, content |
+ # expect(File.read(File.join(tmp_output, rel_path))).to eq(content)
+ # end
+ # end
+
+ # end
+
+end
diff --git a/spec/services/parent_import_notifier_spec.rb b/spec/services/parent_notifier_spec.rb
index 3ab505f88..ecf508fcd 100644
--- a/spec/services/parent_import_notifier_spec.rb
+++ b/spec/services/parent_notifier_spec.rb
@@ -1,4 +1,4 @@
-RSpec.describe ParentImportNotifier do
+RSpec.describe ParentNotifier do
let(:workbench_import) { create(:workbench_import) }
describe ".notify_when_finished" do
@@ -20,7 +20,7 @@ RSpec.describe ParentImportNotifier do
expect(netex_import).to receive(:notify_parent)
end
- ParentImportNotifier.notify_when_finished(netex_imports)
+ ParentNotifier.new(Import).notify_when_finished(netex_imports)
end
it "doesn't call #notify_parent if its `notified_parent_at` is set" do
@@ -33,11 +33,11 @@ RSpec.describe ParentImportNotifier do
expect(netex_import).not_to receive(:notify_parent)
- ParentImportNotifier.notify_when_finished
+ ParentNotifier.new(Import).notify_when_finished
end
end
- describe ".imports_pending_notification" do
+ describe ".objects_pending_notification" do
it "includes imports with a parent and `notified_parent_at` unset" do
netex_import = create(
:netex_import,
@@ -47,7 +47,7 @@ RSpec.describe ParentImportNotifier do
)
expect(
- ParentImportNotifier.imports_pending_notification
+ ParentNotifier.new(Import).objects_pending_notification
).to eq([netex_import])
end
@@ -55,7 +55,7 @@ RSpec.describe ParentImportNotifier do
create(:import, parent: nil)
expect(
- ParentImportNotifier.imports_pending_notification
+ ParentNotifier.new(Import).objects_pending_notification
).to be_empty
end
@@ -70,7 +70,7 @@ RSpec.describe ParentImportNotifier do
end
expect(
- ParentImportNotifier.imports_pending_notification
+ ParentNotifier.new(Import).objects_pending_notification
).to be_empty
end
@@ -83,7 +83,7 @@ RSpec.describe ParentImportNotifier do
)
expect(
- ParentImportNotifier.imports_pending_notification
+ ParentNotifier.new(Import).objects_pending_notification
).to be_empty
end
end
diff --git a/spec/services/referential_overview_spec.rb b/spec/services/referential_overview_spec.rb
new file mode 100644
index 000000000..0ce29643c
--- /dev/null
+++ b/spec/services/referential_overview_spec.rb
@@ -0,0 +1,154 @@
+RSpec.describe ReferentialOverview do
+
+ subject{ described_class }
+
+end
+
+RSpec.describe ReferentialOverview::Week do
+
+ describe "#initialize" do
+ it "should respect the boundary" do
+ week = ReferentialOverview::Week.new(Time.now.beginning_of_week, 1.week.from_now, {})
+ expect(week.start_date).to eq Time.now.beginning_of_week.to_date
+ expect(week.end_date).to eq Time.now.end_of_week.to_date
+
+ week = ReferentialOverview::Week.new(Time.now.beginning_of_week, Time.now, {})
+ expect(week.start_date).to eq Time.now.beginning_of_week.to_date
+ expect(week.end_date).to eq Time.now.to_date
+ end
+ end
+end
+
+RSpec.describe ReferentialOverview::Line do
+
+ let(:ref_line){create(:line)}
+ let(:referential){create(:referential)}
+ let(:start){2.days.ago}
+ let(:period_1){(10.days.ago..8.days.ago)}
+ let(:period_2){(5.days.ago..1.days.ago)}
+
+ subject(:line){ReferentialOverview::Line.new ref_line, referential, start, {}}
+
+ before(:each) do
+ create(:referential_metadata, referential: referential, line_ids: [ref_line.id], periodes: [period_1, period_2].compact)
+ end
+
+ describe "#width" do
+ it "should have the right value" do
+ expect(line.width).to eq ReferentialOverview::Day::WIDTH * referential.metadatas_period.count
+ end
+ end
+
+ describe "#periods" do
+ context "when the periodes are split into several metadatas" do
+ let(:period_2){nil}
+ before do
+ create(:referential_metadata, referential: referential, line_ids: [ref_line.id], periodes: [(17.days.ago..11.days.ago)])
+ end
+ it "should find them all" do
+ expect(line.periods.count).to eq 2
+ expect(line.periods[0].empty?).to be_falsy
+ expect(line.periods[1].empty?).to be_falsy
+ end
+
+ context "when the periodes overlap" do
+ let(:period_2){nil}
+ before do
+ create(:referential_metadata, referential: referential, line_ids: [ref_line.id], periodes: [(17.days.ago..9.days.ago)])
+ end
+ it "should merge them" do
+ expect(line.periods.count).to eq 1
+ expect(line.periods[0].empty?).to be_falsy
+ expect(line.periods[0].start).to eq 17.days.ago.to_date
+ expect(line.periods[0].end).to eq 8.days.ago.to_date
+ end
+ end
+ end
+ end
+
+ describe "#fill_periods" do
+ it "should fill the voids" do
+ expect(line.periods.count).to eq 3
+ expect(line.periods[0].empty?).to be_falsy
+ expect(line.periods[1].empty?).to be_truthy
+ expect(line.periods[1].accepted?).to be_truthy
+ expect(line.periods[2].empty?).to be_falsy
+ end
+
+ context "with no void" do
+ let(:period_1){(10.days.ago..8.days.ago)}
+ let(:period_2){(7.days.ago..1.days.ago)}
+
+ it "should find no void" do
+ expect(line.periods.count).to eq 2
+ expect(line.periods[0].empty?).to be_falsy
+ expect(line.periods[1].empty?).to be_falsy
+ end
+ end
+
+ context "with a large void" do
+ let(:period_1){(20.days.ago..19.days.ago)}
+ let(:period_2){(2.days.ago..1.days.ago)}
+
+ it "should fill the void" do
+ expect(line.periods.count).to eq 3
+ expect(line.periods[0].empty?).to be_falsy
+ expect(line.periods[1].empty?).to be_truthy
+ expect(line.periods[1].accepted?).to be_falsy
+ expect(line.periods[2].empty?).to be_falsy
+ end
+ end
+
+ context "with a void at the end" do
+ before do
+ create(:referential_metadata, referential: referential, periodes: [(2.days.ago..1.days.ago)])
+ end
+ let(:period_1){(20.days.ago..19.days.ago)}
+ let(:period_2){nil}
+
+ it "should fill the void" do
+ expect(line.periods.count).to eq 2
+ expect(line.periods[0].empty?).to be_falsy
+ expect(line.periods[1].empty?).to be_truthy
+ expect(line.periods[1].accepted?).to be_falsy
+ expect(line.periods[1].end).to eq 1.days.ago.to_date
+ end
+ end
+
+ context "with a void at the beginning" do
+ before do
+ create(:referential_metadata, referential: referential, periodes: [(200.days.ago..199.days.ago)])
+ end
+ let(:period_1){(20.days.ago..19.days.ago)}
+ let(:period_2){nil}
+
+ it "should fill the void" do
+ expect(line.periods.count).to eq 2
+ expect(line.periods[0].start).to eq 200.days.ago.to_date
+ expect(line.periods[0].empty?).to be_truthy
+ expect(line.periods[0].accepted?).to be_falsy
+ expect(line.periods[1].empty?).to be_falsy
+ end
+ end
+ end
+end
+
+RSpec.describe ReferentialOverview::Line::Period do
+
+ let(:period){(1.day.ago.to_date..Time.now.to_date)}
+ let(:start){2.days.ago.to_date}
+
+ subject(:line_period){ReferentialOverview::Line::Period.new period, start, nil}
+
+ describe "#width" do
+ it "should have the right value" do
+ expect(line_period.width).to eq ReferentialOverview::Day::WIDTH * 2
+ end
+ end
+
+ describe "#left" do
+ it "should have the right value" do
+ expect(line_period.left).to eq ReferentialOverview::Day::WIDTH * 1
+ end
+ end
+end
diff --git a/spec/services/zip_service_spec.rb b/spec/services/zip_service_spec.rb
index 98cb9026d..1eadaa3bf 100644
--- a/spec/services/zip_service_spec.rb
+++ b/spec/services/zip_service_spec.rb
@@ -1,68 +1,167 @@
-RSpec.describe ZipService do
+RSpec.describe ZipService, type: :zip do
- let( :zip_service ){ described_class }
- let( :unzipper ){ zip_service.new(zip_data) }
- let( :zip_data ){ File.read zip_file }
+ let( :unzipper ){ described_class.new( zip_data, allowed_lines ) }
+ subject { unzipper.subdirs }
+ let( :allowed_lines ){ Set.new(%w{C00108 C00109}) }
+ let( :zip_data ){ zip_archive.data }
+ let( :zip_archive ){ make_zip zip_name, zip_content }
- context 'correct test data' do
- before do
- subdir_names.each do | subdir_name |
- File.unlink( subdir_file subdir_name, suffix: '.zip' ) rescue nil
- Dir.unlink( subdir_file subdir_name ) rescue nil
+ context 'one, legal, referential' do
+ let( :zip_name ){ 'one_referential_ok.zip' }
+ let( :zip_content ){ first_referential_ok_data }
+
+ it 'yields correct output' do
+ subject.each do | subdir |
+ expect_correct_subdir subdir, make_zip('expected.zip', first_referential_ok_data)
end
end
- let( :subdir_names ){ %w<OFFRE_TRANSDEV_20170301122517 OFFRE_TRANSDEV_20170301122519> }
- let( :expected_chksums ){
- checksum_trees( subdir_names.map{ |sn| subdir_file(sn, prefix: 'source_') } )
- }
+ end
- let( :zip_file ){ fixtures_path 'OFFRE_TRANSDEV_2017030112251.zip' }
- #
- # Remove potential test artefacts
+ context 'two, legal, referentials' do
+ let( :zip_name ){ 'two_referential_ok.zip' }
+ let( :zip_content ){ first_referential_ok_data.merge( second_referential_ok_data ) }
+ let( :expected_zips ){ [
+ make_zip('expected.zip', first_referential_ok_data),
+ make_zip('expected.zip', second_referential_ok_data)
+ ] }
- it 'yields the correct content' do
- # Write ZipService Streams to files and inflate them to file system
- unzipper.subdirs.each do | subdir |
- expect( subdir.spurious ).to be_empty
- File.open(subdir_file( subdir.name, suffix: '.zip' ), 'wb'){ |f| f.write subdir.stream.string }
- unzip_subdir subdir
+ it 'yields correct output' do
+ subject.zip(expected_zips).each do | subdir, expected_zip |
+ expect_correct_subdir subdir, expected_zip
end
- # Represent the inflated file_system as a checksum tree
- actual_checksums =
- checksum_trees( subdir_names.map{ |sn| subdir_file(sn, prefix: 'target/') } )
- expect( actual_checksums ).to eq( expected_chksums )
end
+ end
+
+ context 'one referential with a spurious directory' do
+ let( :zip_name ){ 'one_referential_spurious.zip' }
+ let( :zip_content ){ first_referential_spurious_data }
+ it 'returns a not ok object' do
+ expect_incorrect_subdir subject.first, expected_spurious: %w{SPURIOUS}
+ end
end
- context 'test data with spurious directories' do
- let( :zip_file ){ fixtures_path 'OFFRE_WITH_EXTRA.zip' }
+ context 'one referential with a foreign line' do
+ let( :zip_name ){ 'one_referential_foreign.zip' }
+ let( :zip_content ){ first_referential_foreign_data }
- it 'returns the extra dir in the spurious field of the entry' do
- expect( unzipper.subdirs.first.spurious ).to eq(%w{EXTRA})
+ it 'returns a not ok object' do
+ expect_incorrect_subdir subject.first, expected_foreign_lines: %w{C00110}
end
end
+ context '1st ref ok, 2nd foreign line, 3rd spurious' do
+ let( :zip_name ){ '3-mixture.zip' }
+ let( :zip_content ){ first_referential_ok_data
+ .merge(first_referential_foreign_data)
+ .merge(first_referential_spurious_data) }
+
+ it 'returns 3 objects accordingly' do
+ subdirs = subject.to_a
- def checksum_trees *dirs
- dirs.flatten.inject({},&method(:checksum_tree))
+ expect_correct_subdir subdirs.first, make_zip('expected.zip', first_referential_ok_data)
+
+ expect_incorrect_subdir subdirs.second, expected_foreign_lines: %w{C00110}
+ expect_incorrect_subdir subdirs.third, expected_spurious: %W{SPURIOUS}
+ end
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
+
+ context 'one messed up' do
+ let( :zip_name ){ 'one_messed_up.zip' }
+ let( :zip_content ){ messed_up_referential_data }
+
+ it 'returns a not ok object (all error information provided)' do
+ expect_incorrect_subdir subject.first,
+ expected_foreign_lines: %w{C00110 C00111},
+ expected_spurious: %w{SPURIOUS1 SPURIOUS2}
+ end
+
+ end
+
+ # Regression treated in #5281
+ context 'one_first_level_dir' do
+ let( :zip_data ){ File.read fixtures_path('regression-5281.zip') }
+ let( :zip_name ){ 'regression_5281' }
+
+ let( :allowed_lines ){
+ Set.new([*164..168, 171].map{|line| "C00#{line}"})
+ }
+
+ let( :subdirs ){ subject.to_a }
+
+ it 'returns one not ok object' do
+ expect( subdirs.size ).to eq(1)
+ expect( subdirs.first ).not_to be_ok
+ expect( subdirs.first.spurious ).to eq(%w{OFFRE_SNTYO_1_20170820120001 OFFRE_SNTYO_2_20170820120001})
end
- repr
end
- def subdir_file( subdir, prefix: 'target_', suffix: '' )
- fixtures_path("#{prefix}#{subdir}#{suffix}")
+ # Behaviour
+ # ---------
+ def expect_correct_subdir subdir, expected_zip
+ expect( subdir ).to be_ok
+ expect( subdir.foreign_lines ).to be_empty
+ expect( subdir.spurious ).to be_empty
+ subdir.stream.tap do | stream |
+ stream.rewind
+ expect( stream.read ).to eq(expected_zip.data)
+ end
end
- def unzip_subdir subdir
- %x{unzip -oqq #{subdir_file subdir.name, suffix: '.zip'} -d #{fixture_path}/target}
+ def expect_incorrect_subdir subdir, expected_spurious: [], expected_foreign_lines: []
+ expect( subdir ).not_to be_ok
+ expect( subdir.foreign_lines ).to eq(expected_foreign_lines)
+ expect( subdir.spurious ).to eq(expected_spurious)
end
-end
+ # Data
+ # ----
+ let :first_referential_ok_data do
+ {
+ 'Referential1/calendriers.xml' => 'calendriers',
+ 'Referential1/commun.xml' => 'common',
+ 'Referential1/offre_C00108_9.xml' => 'line 108 ref 1',
+ 'Referential1/offre_C00109_10.xml' => 'line 109 ref 1'
+ }
+ end
+ let :first_referential_foreign_data do
+ {
+ 'Referential2/calendriers.xml' => 'calendriers',
+ 'Referential2/commun.xml' => 'common',
+ 'Referential2/offre_C00110_11.xml' => 'foreign line ref 1',
+ 'Referential2/offre_C00108_9.xml' => 'line 108 ref 1',
+ 'Referential2/offre_C00109_10.xml' => 'line 109 ref 1'
+ }
+ end
+ let :first_referential_spurious_data do
+ {
+ 'Referential3/calendriers.xml' => 'calendriers',
+ 'Referential3/commun.xml' => 'common',
+ 'Referential3/SPURIOUS/commun.xml' => 'common',
+ 'Referential3/offre_C00108_9.xml' => 'line 108 ref 1',
+ 'Referential3/offre_C00109_10.xml' => 'line 109 ref 1'
+ }
+ end
+ let :second_referential_ok_data do
+ {
+ 'Referential4/calendriers.xml' => 'calendriers',
+ 'Referential4/commun.xml' => 'common',
+ 'Referential4/offre_C00108_9.xml' => 'line 108 ref 2',
+ 'Referential4/offre_C00109_10.xml' => 'line 109 ref 2'
+ }
+ end
+ let :messed_up_referential_data do
+ {
+ 'Referential5/calendriers.xml' => 'calendriers',
+ 'Referential5/commun.xml' => 'common',
+ 'Referential5/SPURIOUS1/commun.xml' => 'common',
+ 'Referential5/SPURIOUS2/commun.xml' => 'common',
+ 'Referential5/offre_C00110_11.xml' => 'foreign line ref 1',
+ 'Referential5/offre_C00111_11.xml' => 'foreign line ref 1',
+ 'Referential5/offre_C00108_9.xml' => 'line 108 ref 1',
+ 'Referential5/offre_C00109_10.xml' => 'line 109 ref 1'
+ }
+ end
+
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 9679952df..cde252236 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -64,11 +64,11 @@ RSpec.configure do |config|
Capybara.javascript_driver = :poltergeist
# :meta tests can be run seperately in case of doubt about the tests themselves
# they serve mainly as an explanataion of complicated tests (as e.g. PG information_schema introspection)
- config.filter_run_excluding :meta => true
- config.filter_run_excluding :js => true
- config.filter_run :wip => true
+ config.filter_run_excluding meta: true
+ config.filter_run_excluding truncation: true
+ config.filter_run_excluding wip: true
config.run_all_when_everything_filtered = true
- config.include TokenInputHelper, :type => :feature
+ config.include TokenInputHelper, type: :feature
# ## Mock Framework
#
@@ -93,14 +93,13 @@ RSpec.configure do |config|
# You can disable this behaviour by removing the line below, and instead
# explicitly tag your specs with their type, e.g.:
#
- # RSpec.describe UsersController, :type => :controller do
+ # RSpec.describe UsersController, type: :controller do
# # ...
# end
#
# The different available types are documented in the features, such as in
# https://relishapp.com/rspec/rspec-rails/docs
config.infer_spec_type_from_file_location!
-
end
Shoulda::Matchers.configure do |config|
diff --git a/spec/support/checksum_support.rb b/spec/support/checksum_support.rb
index 14ea3c55e..f8dffb1b7 100644
--- a/spec/support/checksum_support.rb
+++ b/spec/support/checksum_support.rb
@@ -1,25 +1,23 @@
-shared_examples 'checksum support' do |factory_name|
- let(:instance) { create(factory_name) }
-
+shared_examples 'checksum support' do
describe '#current_checksum_source' do
let(:attributes) { ['code_value', 'label_value'] }
- let(:seperator) { ChecksumSupport::SEPARATOR }
+ let(:separator) { ChecksumSupport::SEPARATOR }
let(:nil_value) { ChecksumSupport::VALUE_FOR_NIL_ATTRIBUTE }
before do
- allow_any_instance_of(instance.class).to receive(:checksum_attributes).and_return(attributes)
+ allow_any_instance_of(subject.class).to receive(:checksum_attributes).and_return(attributes)
end
- it 'should separate attribute by seperator' do
- expect(instance.current_checksum_source).to eq("code_value#{seperator}label_value")
+ it 'should separate attribute by separator' do
+ expect(subject.current_checksum_source).to eq("code_value#{separator}label_value")
end
context 'nil value' do
let(:attributes) { ['code_value', nil] }
it 'should replace nil attributes by default value' do
- source = "code_value#{seperator}#{nil_value}"
- expect(instance.current_checksum_source).to eq(source)
+ source = "code_value#{separator}#{nil_value}"
+ expect(subject.current_checksum_source).to eq(source)
end
end
@@ -27,27 +25,62 @@ shared_examples 'checksum support' do |factory_name|
let(:attributes) { ['code_value', []] }
it 'should convert to nil' do
- source = "code_value#{seperator}#{nil_value}"
- expect(instance.current_checksum_source).to eq(source)
+ source = "code_value#{separator}#{nil_value}"
+ expect(subject.current_checksum_source).to eq(source)
+ end
+ end
+
+ context 'array value' do
+ let(:attributes) { [['v1', 'v2', 'v3'], 'code_value'] }
+
+ it 'should convert to list' do
+ source = "v1,v2,v3#{separator}code_value"
+ expect(subject.current_checksum_source).to eq(source)
+ end
+ end
+
+ context 'array of array value' do
+ let(:attributes) { [[['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']], 'code_value'] }
+
+ it 'should convert to list' do
+ source = "(a1,a2,a3),(b1,b2,b3)#{separator}code_value"
+ expect(subject.current_checksum_source).to eq(source)
+ end
+ end
+
+ context 'array of array value, with empty array' do
+ let(:attributes) { [[['a1', 'a2', 'a3'], []], 'code_value'] }
+
+ it 'should convert to list' do
+ source = "(a1,a2,a3),-#{separator}code_value"
+ expect(subject.current_checksum_source).to eq(source)
end
end
end
it 'should save checksum on create' do
- expect(instance.checksum).to_not be_nil
+ expect(subject.checksum).to_not be_nil
end
it 'should save checksum_source' do
- expect(instance.checksum_source).to_not be_nil
+ expect(subject.checksum_source).to_not be_nil
end
it 'should trigger set_current_checksum_source on save' do
- expect(instance).to receive(:set_current_checksum_source)
- instance.save
+ expect(subject).to receive(:set_current_checksum_source).at_least(:once)
+ subject.save
end
it 'should trigger update_checksum on save' do
- expect(instance).to receive(:update_checksum)
- instance.save
+ expect(subject).to receive(:update_checksum).at_least(:once)
+ subject.save
+ end
+
+ it "doesn't change the checksum on save if the source hasn't been changed" do
+ checksum = subject.checksum
+
+ subject.save
+
+ expect(subject.checksum).to eq(checksum)
end
end
diff --git a/spec/support/controller_spec_helper.rb b/spec/support/controller_spec_helper.rb
new file mode 100644
index 000000000..dbc7d582b
--- /dev/null
+++ b/spec/support/controller_spec_helper.rb
@@ -0,0 +1,33 @@
+module ControllerSpecHelper
+ def with_permission permission, &block
+ context "with permission #{permission}" do
+ login_user
+ before(:each) do
+ @user.permissions << permission
+ @user.save!
+ sign_in @user
+ end
+ context('', &block) if block_given?
+ end
+ end
+
+ def with_feature feature, &block
+ context "with feature #{feature}" do
+ login_user
+ before(:each) do
+ organisation = @user.organisation
+ unless organisation.has_feature?(feature)
+ organisation.features << feature
+ organisation.save!
+ end
+ sign_in @user
+ end
+ context('', &block) if block_given?
+ end
+ end
+
+end
+
+RSpec.configure do |config|
+ config.extend ControllerSpecHelper, type: :controller
+end
diff --git a/spec/support/decorator_helpers.rb b/spec/support/decorator_helpers.rb
index ffedd479b..b2c41e842 100644
--- a/spec/support/decorator_helpers.rb
+++ b/spec/support/decorator_helpers.rb
@@ -1,27 +1,35 @@
module Support
-
module DecoratorHelpers
def self.included(into)
into.instance_eval do
subject{ object.decorate }
let( :policy ){ ::Pundit.policy(user_context, object) }
let( :user_context ){ UserContext.new(user, referential: referential) }
-
+ let( :features ){ [] }
+ let( :filtered_action_links){}
before do
allow_any_instance_of(Draper::HelperProxy).to receive(:policy).and_return policy
+ allow_any_instance_of(AF83::Decorator::Link).to receive(:check_feature){|f|
+ features.include?(f)
+ }
end
end
end
- def expect_action_link_hrefs
- expect( subject.action_links.select(&Link.method(:===)).map(&:href) )
+ def expect_action_link_hrefs(action=:index)
+ if subject.action_links.is_a? AF83::Decorator::ActionLinks
+ expect( subject.action_links(action).map(&:href) )
+ else
+ expect( subject.action_links.select(&Link.method(:===)).map(&:href) )
+ end
end
- def expect_action_link_elements
- expect( subject.action_links.select(&HTMLElement.method(:===)).map(&:content) )
+
+ def expect_action_link_elements(action=:index)
+ if subject.action_links.is_a? AF83::Decorator::ActionLinks
+ expect( subject.action_links(action).map(&:content) )
+ else
+ expect( subject.action_links.select(&HTMLElement.method(:===)).map(&:content) )
+ end
end
end
end
-
-RSpec.configure do | c |
- c.include Support::DecoratorHelpers, type: :decorator
-end
diff --git a/spec/support/helpers/tree_walker.rb b/spec/support/helpers/tree_walker.rb
new file mode 100644
index 000000000..b86c3a8e1
--- /dev/null
+++ b/spec/support/helpers/tree_walker.rb
@@ -0,0 +1,15 @@
+module TreeWalker extend self
+ MAX_LEVEL = 5
+ def walk_tree path, max_level: MAX_LEVEL, level: 0, yield_dirs: :no, &blk
+ raise RuntimeError, "too many levels in tree walk, > #{max_level}" if level > max_level
+ Dir.glob(File.join(path, '*')) do | file |
+ if File.directory?( file )
+ blk.(:dir, file) if yield_dirs == :before
+ walk_tree(file, max_level: max_level, level: level.succ, yield_dirs: yield_dirs, &blk)
+ blk.(:dir, file) if yield_dirs == :after
+ else
+ blk.(:file, file)
+ end
+ end
+ end
+end
diff --git a/spec/support/integration_spec_helper.rb b/spec/support/integration_spec_helper.rb
new file mode 100644
index 000000000..7ba7e9f92
--- /dev/null
+++ b/spec/support/integration_spec_helper.rb
@@ -0,0 +1,78 @@
+module IntegrationSpecHelper
+
+ def paginate_collection klass, decorator, page=1, context={}
+ collection = klass.page(page)
+ if decorator
+ if decorator < AF83::Decorator
+ collection = decorator.decorate(collection, context: context)
+ else
+ collection = ModelDecorator.decorate(collection, with: decorator, context: context)
+ end
+ end
+ collection
+ end
+
+ def build_paginated_collection factory, decorator, opts={}
+ context = opts.delete(:context) || {}
+ count = opts.delete(:count) || 2
+ page = opts.delete(:page) || 1
+ klass = nil
+ count.times { klass = create(factory, opts).class }
+ paginate_collection klass, decorator, page, context
+ end
+
+ module Methods
+ def with_permission permission, &block
+ context "with permission #{permission}" do
+ let(:permissions){ [permission] }
+ context('', &block) if block_given?
+ end
+ end
+
+ def with_feature feature, &block
+ context "with feature #{feature}" do
+ let(:features){ [feature] }
+ context('', &block) if block_given?
+ end
+ end
+ end
+
+ def self.included into
+ into.extend Methods
+ end
+end
+
+RSpec.configure do |config|
+ config.include IntegrationSpecHelper, type: :view
+end
+
+RSpec::Matchers.define :have_link_for_each_item do |collection, name, opts|
+ opts = {href: opts} unless opts.is_a? Hash
+ href = opts[:href]
+ method = opts[:method]
+ method_selector = method.present? ? "[data-method='#{method.downcase}']": ""
+ match do |actual|
+ collection.each do |item|
+ @selector = "tr.#{TableBuilderHelper.item_row_class_name(collection)}-#{item.id} .actions a[href='#{href.call(item)}']#{method_selector}"
+ expect(rendered).to have_selector(@selector, count: 1)
+ end
+ end
+ description { "have #{name} link for each item" }
+ failure_message do
+ "expected view to have one #{name} link for each item, failed with selector: \"#{@selector}\""
+ end
+end
+
+RSpec::Matchers.define :have_the_right_number_of_links do |collection, count|
+ match do
+ collection.each do |item|
+ @selector = "tr.#{TableBuilderHelper.item_row_class_name(collection)}-#{item.id} .actions a"
+ expect(rendered).to have_selector(@selector, count: count)
+ end
+ end
+ description { "have #{count} links for each item" }
+ failure_message do
+ actual = Capybara::Node::Simple.new(rendered).all(@selector).count
+ "expected #{count} links for each item, got #{actual} for \"#{@selector}\""
+ end
+end
diff --git a/spec/support/journey_pattern_helper.rb b/spec/support/journey_pattern_helper.rb
new file mode 100644
index 000000000..3ba1c501b
--- /dev/null
+++ b/spec/support/journey_pattern_helper.rb
@@ -0,0 +1,19 @@
+module Support
+ module JourneyPatternHelper
+ def generate_journey_pattern_costs distance, time
+ costs = {}
+ (journey_pattern.stop_points.size - 1).times do |i|
+ start, finish = journey_pattern.stop_points[i..i+1]
+ costs["#{start.stop_area_id}-#{finish.stop_area_id}"] = {
+ distance: (distance.respond_to?(:call) ? distance.call(i) : distance),
+ time: (time.respond_to?(:call) ? time.call(i) : time)
+ }
+ end
+ costs
+ end
+ end
+end
+
+RSpec.configure do | config |
+ config.include Support::JourneyPatternHelper, type: :model
+end
diff --git a/spec/support/permissions.rb b/spec/support/permissions.rb
index dde530871..95afd6c1c 100644
--- a/spec/support/permissions.rb
+++ b/spec/support/permissions.rb
@@ -18,6 +18,7 @@ module Support
calendars
footnotes
imports
+ merges
journey_patterns
referentials
routes
diff --git a/spec/support/pundit/policies.rb b/spec/support/pundit/policies.rb
index a3489d9db..d8d12d735 100644
--- a/spec/support/pundit/policies.rb
+++ b/spec/support/pundit/policies.rb
@@ -12,11 +12,14 @@ module Support
UserContext.new(user, referential: referential)
end
+ def finalise_referential
+ referential.referential_suite_id = random_int
+ end
+
def remove_permissions(*permissions, from_user:, save: false)
from_user.permissions -= permissions.flatten
from_user.save! if save
end
-
end
module PoliciesMacros
diff --git a/spec/support/pundit/pundit_view_policy.rb b/spec/support/pundit/pundit_view_policy.rb
index b8434cac0..63970de02 100644
--- a/spec/support/pundit/pundit_view_policy.rb
+++ b/spec/support/pundit/pundit_view_policy.rb
@@ -1,16 +1,21 @@
module Pundit
module PunditViewPolicy
- extend ActiveSupport::Concern
-
- included do
- before do
- controller.singleton_class.class_eval do
- def policy(instance)
- Class.new do
- def method_missing(*args, &block); true; end
- end.new
- end
- helper_method :policy
+ def self.included into
+ into.let(:permissions){ nil }
+ into.let(:current_referential){ referential || build_stubbed(:referential, organisation: organisation) }
+ into.let(:current_user){ create :user, permissions: permissions, organisation: organisation }
+ into.let(:pundit_user){ UserContext.new(current_user, referential: current_referential) }
+ into.let(:current_offer_workbench) { create :workbench, organisation: organisation}
+ into.before do
+ allow(view).to receive(:pundit_user) { pundit_user }
+ allow(view).to receive(:current_user) { current_user }
+ allow(view).to receive(:current_organisation).and_return(organisation)
+ allow(view).to receive(:current_offer_workbench).and_return(current_offer_workbench)
+ allow(view).to receive(:current_workgroup).and_return(current_offer_workbench.workgroup)
+ allow(view).to receive(:has_feature?){ |f| features.include?(f)}
+ allow(view).to receive(:user_signed_in?).and_return true
+ allow(view).to receive(:policy) do |instance|
+ ::Pundit.policy pundit_user, instance
end
end
end
diff --git a/spec/support/pundit/shared_examples.rb b/spec/support/pundit/shared_examples.rb
index 49f915626..13f537c6d 100644
--- a/spec/support/pundit/shared_examples.rb
+++ b/spec/support/pundit/shared_examples.rb
@@ -1,6 +1,6 @@
RSpec.shared_examples 'always allowed' do
- | permission, archived: false|
+ | permission, archived_and_finalised: false |
context 'same organisation →' do
before do
user.organisation_id = referential.organisation_id
@@ -8,11 +8,16 @@ RSpec.shared_examples 'always allowed' do
it "allows a user with the same organisation" do
expect_it.to permit(user_context, record)
end
- if archived
+ if archived_and_finalised
it 'does not remove permission for archived referentials' do
referential.archived_at = 42.seconds.ago
expect_it.to permit(user_context, record)
end
+
+ it 'does not remove permission for finalised referentials' do
+ finalise_referential
+ expect_it.to permit(user_context, record)
+ end
end
end
@@ -23,27 +28,33 @@ RSpec.shared_examples 'always allowed' do
it "allows a user with a different organisation" do
expect_it.to permit(user_context, record)
end
- if archived
+ if archived_and_finalised
it 'does not remove permission for archived referentials' do
referential.archived_at = 42.seconds.ago
expect_it.to permit(user_context, record)
end
+ it 'does not remove permission for finalised referentials' do
+ finalise_referential
+ expect_it.to permit(user_context, record)
+ end
end
end
end
RSpec.shared_examples 'always forbidden' do
- | permission, archived: false|
+ | permission, archived_and_finalised: false|
context 'same organisation →' do
before do
user.organisation_id = referential.organisation_id
end
+
it "allows a user with the same organisation" do
expect_it.not_to permit(user_context, record)
end
- if archived
+
+ if archived_and_finalised
it 'still no permission for archived referentials' do
- referential.archived_at = 42.seconds.ago
+ finalise_referential
expect_it.not_to permit(user_context, record)
end
end
@@ -56,17 +67,22 @@ RSpec.shared_examples 'always forbidden' do
it "denies a user with a different organisation" do
expect_it.not_to permit(user_context, record)
end
- if archived
+ if archived_and_finalised
it 'still no permission for archived referentials' do
referential.archived_at = 42.seconds.ago
expect_it.not_to permit(user_context, record)
end
+
+ it 'still no permission for finalised referentials' do
+ finalise_referential
+ expect_it.not_to permit(user_context, record)
+ end
end
end
end
RSpec.shared_examples 'permitted policy and same organisation' do
- | permission, archived: false|
+ | permission, archived_and_finalised: false |
context 'permission absent → ' do
it "denies a user with a different organisation" do
@@ -92,18 +108,24 @@ RSpec.shared_examples 'permitted policy and same organisation' do
expect_it.to permit(user_context, record)
end
- if archived
+ if archived_and_finalised
it 'removes the permission for archived referentials' do
user.organisation_id = referential.organisation_id
referential.archived_at = 42.seconds.ago
expect_it.not_to permit(user_context, record)
end
+
+ it 'removes the permission for finalised referentials' do
+ user.organisation_id = referential.organisation_id
+ finalise_referential
+ expect_it.not_to permit(user_context, record)
+ end
end
end
end
RSpec.shared_examples 'permitted policy' do
- | permission, archived: false|
+ | permission, archived_and_finalised: false|
context 'permission absent → ' do
it "denies user" do
@@ -120,12 +142,17 @@ RSpec.shared_examples 'permitted policy' do
expect_it.to permit(user_context, record)
end
- if archived
+ if archived_and_finalised
it 'removes the permission for archived referentials' do
user.organisation_id = referential.organisation_id
referential.archived_at = 42.seconds.ago
expect_it.not_to permit(user_context, record)
end
+ it 'removes the permission for finalised referentials' do
+ user.organisation_id = referential.organisation_id
+ finalise_referential
+ expect_it.not_to permit(user_context, record)
+ end
end
end
end
@@ -148,4 +175,4 @@ RSpec.shared_examples 'permitted policy outside referential' do
expect_it.to permit(user_context, record)
end
end
-end \ No newline at end of file
+end
diff --git a/spec/support/referential.rb b/spec/support/referential.rb
index b615491da..9acdce73a 100644
--- a/spec/support/referential.rb
+++ b/spec/support/referential.rb
@@ -11,8 +11,8 @@ module ReferentialHelper
def self.included(base)
base.class_eval do
extend ClassMethods
- alias_method :referential, :first_referential
- alias_method :organisation, :first_organisation
+ base.let(:referential){ first_referential }
+ base.let(:organisation){ first_organisation }
end
end
@@ -29,7 +29,6 @@ module ReferentialHelper
end
end
-
end
end
@@ -78,7 +77,7 @@ RSpec.configure do |config|
first_referential.switch
end
- config.before(:each, :js => true) do
+ config.before(:each, truncation: true) do
DatabaseCleaner.strategy = :truncation, { except: %w[spatial_ref_sys] }
end
diff --git a/spec/support/shared_examples/compliance_control_validation.rb b/spec/support/shared_examples/compliance_control_validation.rb
index d4ab9f41d..b23c2984f 100644
--- a/spec/support/shared_examples/compliance_control_validation.rb
+++ b/spec/support/shared_examples/compliance_control_validation.rb
@@ -1,43 +1,54 @@
RSpec.shared_examples_for 'has min_max_values' do
context "is valid" do
- it 'if no value is provided' do
+ it { should validate_numericality_of(:minimum) }
+ it { should validate_numericality_of(:maximum) }
+
+ it 'if maximum is greater than minimum' do
+ min = random_int
+ max = min + 100
+ subject.assign_attributes maximum: max, minimum: min
expect_it.to be_valid
end
+ end
+
+ context "is invalid" do
+ it 'if no value is provided' do
+ subject.minimum = nil
+ subject.maximum = nil
+ expect_it.not_to be_valid
+ end
+
it 'if minimum is provided alone' do
subject.minimum = 42
- expect_it.to be_valid
+ subject.maximum = nil
+ expect_it.not_to be_valid
end
+
it 'if maximum is provided alone' do
+ subject.minimum = nil
subject.maximum = 42
- expect_it.to be_valid
- end
-
- it 'if maximum is not smaller than minimum' do
- 100.times do
- min = random_int
- max = min + random_int(20)
- subject.assign_attributes maximum: max, minimum: min
- subject.assign_attributes maximum: min, minimum: min
- expect_it.to be_valid
- end
+ expect_it.not_to be_valid
end
- end
- context "is invalid" do
it 'if maximum is smaller than minimum' do
- 100.times do
- min = random_int
- max = min - random_int(20) - 1
- subject.assign_attributes maximum: max, minimum: min
- expect_it.not_to be_valid
- end
+ min = random_int
+ max = min - 1
+ subject.assign_attributes maximum: max, minimum: min
+ expect_it.not_to be_valid
end
it 'and has a correct error message' do
subject.assign_attributes maximum: 1, minimum: 2
expect_it.not_to be_valid
- expect( subject.errors.messages[:min_max_values].first ).to match("la valeur de minimum (2) ne doit pas être superieur à la valuer du maximum (1)")
+ expect( subject.errors.messages[:minimum].first ).to match(I18n.t("compliance_controls.min_max_values", min: 2, max: 1))
end
end
end
+
+
+RSpec.shared_examples_for "has target attribute" do
+ context "is valid" do
+ it { should validate_presence_of(:target) }
+ end
+end
diff --git a/spec/support/snapshot_support.rb b/spec/support/snapshot_support.rb
new file mode 100644
index 000000000..b1ade5288
--- /dev/null
+++ b/spec/support/snapshot_support.rb
@@ -0,0 +1,60 @@
+module SnaphostSpecHelper
+
+ module Methods
+ def set_invariant expr, val=nil
+ val ||= expr
+ chain = expr.split(".")
+ method = chain.pop
+
+ before(:each) do
+ allow(eval(chain.join('.'))).to receive(method){ val }
+ end
+ end
+ end
+
+ def self.included into
+ into.extend Methods
+ end
+end
+
+RSpec.configure do |config|
+ config.include SnaphostSpecHelper, type: :view
+end
+
+
+RSpec::Matchers.define :match_actions_links_snapshot do |name|
+ match do |actual|
+ @content = Capybara::Node::Simple.new(rendered).find('.page_header').native.inner_html
+ expect(@content).to match_snapshot(name)
+ end
+
+ failure_message do |actual|
+ out = ["Snapshots did not match."]
+ snap_path = File.dirname(method_missing(:class).metadata[:file_path]) + "/__snapshots__/#{name}.snap"
+ temp_path = Pathname.new "#{Rails.root}/tmp/__snapshots__/#{name}.failed.snap"
+ FileUtils.mkdir_p temp_path.dirname
+ tmp = File.new temp_path, "w"
+ tmp.write @content
+ tmp.close()
+ expected = File.read snap_path
+ out << "Expected: #{expected}"
+ out << "Actual: #{@content}"
+ out << "\n\n --- DIFF ---"
+ out << differ.diff_as_string(@content, expected)
+ out << "\n\n --- Previews : ---"
+ out << "Expected: \n" + snapshot_url(snap: snap_path, layout: :actions_links)
+ out << " \nActual: \n" + snapshot_url(snap: tmp.path, layout: :actions_links)
+ out.join("\n")
+ end
+
+ def snapshot_url snap:, layout:
+ "http://localhost:3000/snap/?snap=#{URI.encode(snap.to_s)}&layout=#{URI.encode(layout.to_s)}"
+ end
+
+ def differ
+ RSpec::Support::Differ.new(
+ :object_preparer => lambda { |object| RSpec::Matchers::Composable.surface_descriptions_in(object) },
+ :color => RSpec::Matchers.configuration.color?
+ )
+ end
+end
diff --git a/spec/support/zip_support.rb b/spec/support/zip_support.rb
new file mode 100644
index 000000000..3d9b2f97c
--- /dev/null
+++ b/spec/support/zip_support.rb
@@ -0,0 +1,25 @@
+require_relative 'helpers/tree_walker'
+module ZipSupport
+
+ module Helper extend self
+ def remove
+ -> filetype, path do
+ filetype == :file ? File.unlink(path) : Dir.unlink(path)
+ end
+ end
+ end
+
+ def zip_fixtures_path(file_name)
+ fixtures_path(File.join('zip', file_name))
+ end
+
+ def clear_all_zip_fixtures! relpath = ''
+ raise ArgumentError, 'up dir not allowed (..)' if %r{\.\.} === relpath
+ TreeWalker.walk_tree zip_fixtures_path(relpath), yield_dirs: :after, &Helper.remove
+ end
+end
+
+RSpec.configure do |conf|
+ conf.include ZipSupport, type: :zip
+end
+
diff --git a/spec/support/zip_support/create_zip_data.rb b/spec/support/zip_support/create_zip_data.rb
new file mode 100644
index 000000000..250d67f74
--- /dev/null
+++ b/spec/support/zip_support/create_zip_data.rb
@@ -0,0 +1,70 @@
+require_relative '../helpers/tree_walker'
+module ZipSupport
+ module CreateZipData
+
+ class ZipData < Struct.new(:name, :data)
+
+ def write_to file
+ File.write(file, data)
+ end
+
+ end
+
+ class Implementation
+
+ attr_reader :name, :prefix, :zip
+
+ def initialize name
+ @name = name
+ @prefix = "#{name}/"
+ @zip = ZipData.new(name, '')
+ end
+
+ def make_from names_to_content_map
+ os = Zip::OutputStream.write_buffer do | zio |
+ names_to_content_map.each(&add_entries(zio))
+ end
+ zip.data = os.string
+ zip
+ end
+
+ def make_from_tree
+ os = Zip::OutputStream.write_buffer do | zio |
+ TreeWalker.walk_tree(name, &add_entry(zio))
+ end
+ zip.data = os.string
+ zip
+ end
+
+ private
+
+ def add_entry zio
+ -> _, path do
+ rel_path = path.sub(prefix, '')
+ zio.put_next_entry(rel_path)
+ zio.write(File.read(path))
+ end
+ end
+
+ def add_entries zio
+ -> name, content do
+ zio.put_next_entry(name)
+ zio.write(content)
+ end
+ end
+ end
+
+
+ def make_zip(name, names_to_content_map = {})
+ Implementation.new(name).make_from(names_to_content_map)
+ end
+
+ def make_zip_from_tree(dir)
+ Implementation.new(dir).make_from_tree
+ end
+ end
+end
+
+RSpec.configure do |conf|
+ conf.include ZipSupport::CreateZipData, type: :zip
+end
diff --git a/spec/views/companies/__snapshots__/companies/index.snap b/spec/views/companies/__snapshots__/companies/index.snap
new file mode 100644
index 000000000..2c5c23400
--- /dev/null
+++ b/spec/views/companies/__snapshots__/companies/index.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/companies/__snapshots__/companies/index_create.snap b/spec/views/companies/__snapshots__/companies/index_create.snap
new file mode 100644
index 000000000..df36d5f49
--- /dev/null
+++ b/spec/views/companies/__snapshots__/companies/index_create.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><a class="btn btn-default" href="/line_referentials/99/companies/new">Ajouter un transporteur</a></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/companies/__snapshots__/companies/index_destroy.snap b/spec/views/companies/__snapshots__/companies/index_destroy.snap
new file mode 100644
index 000000000..2c5c23400
--- /dev/null
+++ b/spec/views/companies/__snapshots__/companies/index_destroy.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/companies/__snapshots__/companies/index_update.snap b/spec/views/companies/__snapshots__/companies/index_update.snap
new file mode 100644
index 000000000..2c5c23400
--- /dev/null
+++ b/spec/views/companies/__snapshots__/companies/index_update.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/companies/__snapshots__/companies/show.snap b/spec/views/companies/__snapshots__/companies/show.snap
new file mode 100644
index 000000000..8fe847427
--- /dev/null
+++ b/spec/views/companies/__snapshots__/companies/show.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Transporteur Company Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/companies/__snapshots__/companies/show_create.snap b/spec/views/companies/__snapshots__/companies/show_create.snap
new file mode 100644
index 000000000..8fe847427
--- /dev/null
+++ b/spec/views/companies/__snapshots__/companies/show_create.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Transporteur Company Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/companies/__snapshots__/companies/show_destroy.snap b/spec/views/companies/__snapshots__/companies/show_destroy.snap
new file mode 100644
index 000000000..5d574e460
--- /dev/null
+++ b/spec/views/companies/__snapshots__/companies/show_destroy.snap
@@ -0,0 +1,7 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Transporteur Company Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right"><a data-confirm="Etes vous sûr de supprimer ce transporteur ?" class="btn btn-primary" rel="nofollow" data-method="delete" href="/line_referentials/99/companies/909"><span class="fa fa-trash mr-xs"></span>Supprimer ce transporteur</a></div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/companies/__snapshots__/companies/show_update.snap b/spec/views/companies/__snapshots__/companies/show_update.snap
new file mode 100644
index 000000000..c2fbd3297
--- /dev/null
+++ b/spec/views/companies/__snapshots__/companies/show_update.snap
@@ -0,0 +1,7 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Transporteur Company Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action">
+<div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div>
+<a class="btn btn-default" href="/line_referentials/99/companies/909/edit">Editer ce transporteur</a>
+</div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/companies/index.html.erb_spec.rb b/spec/views/companies/index.html.erb_spec.rb
index 9db689ba6..8ed5f2c21 100644
--- a/spec/views/companies/index.html.erb_spec.rb
+++ b/spec/views/companies/index.html.erb_spec.rb
@@ -3,7 +3,10 @@ require 'spec_helper'
RSpec.describe "/companies/index", :type => :view do
let!(:line_referential) { assign :line_referential, create(:line_referential) }
- let!(:companies) { assign :companies, CompanyDecorator.decorate_collection(Array.new(2) { create(:company, line_referential: line_referential) }.paginate) }
+ let(:context){{referential: line_referential}}
+ let!(:companies) do
+ assign :companies, build_paginated_collection(:company, CompanyDecorator, line_referential: line_referential, context: context)
+ end
let!(:search) { assign :q, Ransack::Search.new(Chouette::Company) }
# Fixme #1795
@@ -22,4 +25,28 @@ RSpec.describe "/companies/index", :type => :view do
# expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{new_line_referential_company_path(line_referential)}']")
# end
+ before(:each) do
+ allow(view).to receive(:collection).and_return(companies)
+ allow(view).to receive(:decorated_collection).and_return(companies)
+ allow(view).to receive(:current_referential).and_return(line_referential)
+ controller.request.path_parameters[:line_referential_id] = line_referential.id
+ allow(view).to receive(:params).and_return({action: :index})
+ end
+
+ describe "action links" do
+ set_invariant "line_referential.id", "99"
+
+ before(:each){
+ render template: "companies/index", layout: "layouts/application"
+ }
+
+ it { should match_actions_links_snapshot "companies/index" }
+
+ %w(create update destroy).each do |p|
+ with_permission "companies.#{p}" do
+ it { should match_actions_links_snapshot "companies/index_#{p}" }
+ end
+ end
+ end
+
end
diff --git a/spec/views/companies/show.html.erb_spec.rb b/spec/views/companies/show.html.erb_spec.rb
index aeb93aebb..b127bdf44 100644
--- a/spec/views/companies/show.html.erb_spec.rb
+++ b/spec/views/companies/show.html.erb_spec.rb
@@ -2,11 +2,38 @@ require 'spec_helper'
describe "/companies/show", :type => :view do
- let!(:company) { assign(:company, create(:company)) }
+ let!(:company) { c = create(:company); assign(:company, c.decorate(context: {referential: c.line_referential})) }
let!(:line_referential) { assign :line_referential, company.line_referential }
# it "should display a map with class 'company'" do
# render
# expect(rendered).to have_selector("#map", :class => 'company')
# end
+
+ before(:each) do
+ allow(view).to receive(:current_referential).and_return(line_referential)
+ allow(view).to receive(:resource).and_return(company)
+ controller.request.path_parameters[:line_referential_id] = line_referential.id
+ controller.request.path_parameters[:id] = company.id
+ allow(view).to receive(:params).and_return({action: :show})
+ end
+
+ describe "action links" do
+ set_invariant "line_referential.id", "99"
+ set_invariant "company.object.id", "909"
+ set_invariant "company.object.name", "Company Name"
+ set_invariant "company.object.updated_at", "2018/01/23".to_time
+
+ before(:each){
+ render template: "companies/show", layout: "layouts/application"
+ }
+
+ it { should match_actions_links_snapshot "companies/show" }
+
+ %w(create update destroy).each do |p|
+ with_permission "companies.#{p}" do
+ it { should match_actions_links_snapshot "companies/show_#{p}" }
+ end
+ end
+ end
end
diff --git a/spec/views/connection_links/index.html.erb_spec.rb b/spec/views/connection_links/index.html.erb_spec.rb
index a01380094..1f133e31e 100644
--- a/spec/views/connection_links/index.html.erb_spec.rb
+++ b/spec/views/connection_links/index.html.erb_spec.rb
@@ -17,9 +17,11 @@ describe "/connection_links/index", :type => :view do
end
end
- it "should render a link to create a new group" do
- render
- expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{new_referential_connection_link_path(referential)}']")
+ with_permission "connection_links.create" do
+ it "should render a link to create a new group" do
+ render
+ expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{new_referential_connection_link_path(referential)}']")
+ end
end
end
diff --git a/spec/views/connection_links/show.html.erb_spec.rb b/spec/views/connection_links/show.html.erb_spec.rb
deleted file mode 100644
index c04a4f3f1..000000000
--- a/spec/views/connection_links/show.html.erb_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-require 'spec_helper'
-
-describe "/connection_links/show", :type => :view do
-
- assign_referential
- let!(:connection_link) { assign(:connection_link, create(:connection_link)) }
- let!(:map) { assign(:map, double(:to_html => '<div id="map"/>'.html_safe)) }
-
- before do
- allow(view).to receive_messages(current_organisation: referential.organisation)
- end
-
- it "should render h2 with the connection_link name" do
- render
- expect(rendered).to have_selector("h2", :text => Regexp.new(connection_link.name))
- end
-
-# it "should display a map with class 'connection_link'" do
-# pending ": map not yet implemented"
-# render
-# expect(rendered).to have_selector("#map", :class => 'connection_link')
-# end
-
- it "should render a link to edit the connection_link" do
- render
- expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{view.edit_referential_connection_link_path(referential, connection_link)}']")
- end
-
- it "should render a link to remove the connection_link" do
- render
- expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{view.referential_connection_link_path(referential, connection_link)}'][class='remove']")
- end
-
-end
-
diff --git a/spec/views/connection_links/show.html.slim_spec.rb b/spec/views/connection_links/show.html.slim_spec.rb
new file mode 100644
index 000000000..afe94fc6c
--- /dev/null
+++ b/spec/views/connection_links/show.html.slim_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe "/connection_links/show", :type => :view do
+
+ assign_referential
+ let!(:connection_link) { assign(:connection_link, create(:connection_link)) }
+ let!(:map) { assign(:map, double(:to_html => '<div id="map"/>'.html_safe)) }
+
+ before do
+ allow(view).to receive_messages(current_organisation: referential.organisation)
+ end
+
+ it "should render h2 with the connection_link name" do
+ render
+ expect(rendered).to have_selector("h2", :text => Regexp.new(connection_link.name))
+ end
+
+ with_permission "connection_links.update" do
+ it "should render a link to edit the connection_link" do
+ render
+ expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{view.edit_referential_connection_link_path(referential, connection_link)}']")
+ end
+ end
+
+ with_permission "connection_links.destroy" do
+ it "should render a link to remove the connection_link" do
+ render
+ expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{view.referential_connection_link_path(referential, connection_link)}'][class='remove']")
+ end
+ end
+
+end
diff --git a/spec/views/imports/show.html.slim_spec.rb b/spec/views/imports/show.html.slim_spec.rb
new file mode 100644
index 000000000..faf473758
--- /dev/null
+++ b/spec/views/imports/show.html.slim_spec.rb
@@ -0,0 +1,35 @@
+RSpec.describe '/imports/show', type: :view do
+ let(:workbench){ create :workbench }
+ let(:workbench_import){ create :workbench_import, workbench: workbench }
+ let!( :messages ) {[
+ create(:corrupt_zip_file, import: workbench_import),
+ create(:inconsistent_zip_file, import: workbench_import),
+ ]}
+
+
+ before do
+ assign :import, workbench_import.decorate( context: {workbench: workbench} )
+ render
+ end
+
+ it 'shows the correct record...' do
+ # ... zip file name
+ expect(rendered).to have_selector('.dl-def') do
+ with_text workbench_import.file
+ end
+
+ # ... messages
+ messages.each do | message |
+ # require 'htmlbeautifier'
+ # b = HtmlBeautifier.beautify(rendered, indent: ' ')
+ expect(rendered).to have_selector('.import_message-list li') do
+ with_text rendered_message( message )
+ end
+ end
+ end
+
+ def rendered_message message
+ return I18n.t message.message_key, message.message_attributes.symbolize_keys
+ end
+
+end
diff --git a/spec/views/line_referentials/show.html.slim_spec.rb b/spec/views/line_referentials/show.html.slim_spec.rb
new file mode 100644
index 000000000..0516677cb
--- /dev/null
+++ b/spec/views/line_referentials/show.html.slim_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe "/line_referentials/show", :type => :view do
+
+ let!(:line_referential) { assign :line_referential, create(:line_referential) }
+
+ before :each do
+ render
+ end
+
+ it "should not present syncing infos and button" do
+ expect(view.content_for(:page_header_actions)).to_not have_selector("a[href=\"#{view.sync_line_referential_path(line_referential)}\"]")
+ expect(view.content_for(:page_header_meta)).to_not have_selector(".last-update")
+ end
+
+ with_permission "line_referentials.synchronize" do
+ it "should present syncing infos and button" do
+ expect(view.content_for(:page_header_actions)).to have_selector("a[href=\"#{view.sync_line_referential_path(line_referential)}\"]", count: 1)
+ expect(view.content_for(:page_header_meta)).to have_selector(".last-update", count: 1)
+ end
+ end
+end
diff --git a/spec/views/line_referentials/stop_area_referentials/show.html.slim_spec.rb b/spec/views/line_referentials/stop_area_referentials/show.html.slim_spec.rb
new file mode 100644
index 000000000..71a8d16f5
--- /dev/null
+++ b/spec/views/line_referentials/stop_area_referentials/show.html.slim_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe "/stop_area_referentials/show", :type => :view do
+
+ let!(:stop_area_referential) { assign :stop_area_referential, create(:stop_area_referential) }
+
+ before :each do
+ render
+ end
+
+ it "should not present syncing infos and button" do
+ expect(view.content_for(:page_header_actions)).to_not have_selector("a[href=\"#{view.sync_stop_area_referential_path(stop_area_referential)}\"]")
+ expect(view.content_for(:page_header_meta)).to_not have_selector(".last-update")
+ end
+
+ with_permission "stop_area_referentials.synchronize" do
+ it "should present syncing infos and button" do
+ expect(view.content_for(:page_header_actions)).to have_selector("a[href=\"#{view.sync_stop_area_referential_path(stop_area_referential)}\"]", count: 1)
+ expect(view.content_for(:page_header_meta)).to have_selector(".last-update", count: 1)
+ end
+ end
+end
diff --git a/spec/views/lines/__snapshots__/lines/index.snap b/spec/views/lines/__snapshots__/lines/index.snap
new file mode 100644
index 000000000..2c5c23400
--- /dev/null
+++ b/spec/views/lines/__snapshots__/lines/index.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/lines/__snapshots__/lines/index_create.snap b/spec/views/lines/__snapshots__/lines/index_create.snap
new file mode 100644
index 000000000..4e4f54e7f
--- /dev/null
+++ b/spec/views/lines/__snapshots__/lines/index_create.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><a class="btn btn-default" href="/line_referentials/99/lines/new">Ajouter une ligne</a></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/lines/__snapshots__/lines/index_destroy.snap b/spec/views/lines/__snapshots__/lines/index_destroy.snap
new file mode 100644
index 000000000..2c5c23400
--- /dev/null
+++ b/spec/views/lines/__snapshots__/lines/index_destroy.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/lines/__snapshots__/lines/index_update.snap b/spec/views/lines/__snapshots__/lines/index_update.snap
new file mode 100644
index 000000000..2c5c23400
--- /dev/null
+++ b/spec/views/lines/__snapshots__/lines/index_update.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/lines/__snapshots__/lines/show.snap b/spec/views/lines/__snapshots__/lines/show.snap
new file mode 100644
index 000000000..30eb6786e
--- /dev/null
+++ b/spec/views/lines/__snapshots__/lines/show.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Ligne Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/line_referentials/99/networks/99">Voir le réseau</a><a class="btn btn-primary" href="/line_referentials/99/companies/99">Voir le transporteur principal</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/lines/__snapshots__/lines/show_create.snap b/spec/views/lines/__snapshots__/lines/show_create.snap
new file mode 100644
index 000000000..30eb6786e
--- /dev/null
+++ b/spec/views/lines/__snapshots__/lines/show_create.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Ligne Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/line_referentials/99/networks/99">Voir le réseau</a><a class="btn btn-primary" href="/line_referentials/99/companies/99">Voir le transporteur principal</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/lines/__snapshots__/lines/show_destroy.snap b/spec/views/lines/__snapshots__/lines/show_destroy.snap
new file mode 100644
index 000000000..8ed08a90d
--- /dev/null
+++ b/spec/views/lines/__snapshots__/lines/show_destroy.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Ligne Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/line_referentials/99/networks/99">Voir le réseau</a><a class="btn btn-primary" href="/line_referentials/99/companies/99">Voir le transporteur principal</a><a data-confirm="Etes vous sûr de supprimer cette ligne ?" class="btn btn-primary" rel="nofollow" data-method="delete" href="/line_referentials/99/lines/99"><span class="fa fa-trash mr-xs"></span>Supprimer cette ligne</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/lines/__snapshots__/lines/show_update.snap b/spec/views/lines/__snapshots__/lines/show_update.snap
new file mode 100644
index 000000000..30eb6786e
--- /dev/null
+++ b/spec/views/lines/__snapshots__/lines/show_update.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Ligne Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/line_referentials/99/networks/99">Voir le réseau</a><a class="btn btn-primary" href="/line_referentials/99/companies/99">Voir le transporteur principal</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/lines/index.html.erb_spec.rb b/spec/views/lines/index.html.erb_spec.rb
deleted file mode 100644
index dbc3cbdb7..000000000
--- a/spec/views/lines/index.html.erb_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-require 'spec_helper'
-
-describe "/lines/index", :type => :view do
-
- let!(:line_referential) { assign :line_referential, create(:line_referential) }
- let!(:network) { create :network }
- let!(:company) { create :company }
- let!(:lines) { assign :lines, Array.new(2) { create(:line, line_referential: line_referential, network: network, company: company) }.paginate }
- let!(:q) { assign :q, Ransack::Search.new(Chouette::Line) }
-
- before :each do
- allow(view).to receive(:link_with_search).and_return("#")
- end
-
- # it "should render a show link for each group" do
- # render
- # lines.each do |line|
- # expect(rendered).to have_selector(".line a[href='#{view.line_referential_line_path(line_referential, line)}']", :text => line.name)
- # end
- # end
- #
- # it "should render a link to create a new group" do
- # render
- # expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{new_line_referential_line_path(line_referential)}']")
- # end
-
-end
diff --git a/spec/views/lines/index.html.slim_spec.rb b/spec/views/lines/index.html.slim_spec.rb
new file mode 100644
index 000000000..20e1783e3
--- /dev/null
+++ b/spec/views/lines/index.html.slim_spec.rb
@@ -0,0 +1,93 @@
+require 'spec_helper'
+
+describe "/lines/index", :type => :view do
+ let(:deactivated_line){ nil }
+ let(:line_referential) { assign :line_referential, create(:line_referential) }
+ let(:current_organisation) { current_user.organisation }
+ let(:context) {
+ {
+ current_organisation: current_organisation,
+ line_referential: line_referential
+ }
+ }
+ let(:lines) do
+ assign :lines, build_paginated_collection(:line, LineDecorator, line_referential: line_referential, context: context)
+ end
+ let!(:q) { assign :q, Ransack::Search.new(Chouette::Line) }
+
+ before :each do
+ deactivated_line
+ allow(view).to receive(:collection).and_return(lines)
+ allow(view).to receive(:decorated_collection).and_return(lines)
+ allow(view).to receive(:current_referential).and_return(line_referential)
+ allow(view).to receive(:params).and_return({action: :index})
+ controller.request.path_parameters[:line_referential_id] = line_referential.id
+ controller.request.path_parameters[:action] = "index"
+ render
+ end
+
+ describe "action links" do
+ set_invariant "line_referential.id", "99"
+ set_invariant "line_referential.name", "Name"
+
+ before(:each){
+ render template: "lines/index", layout: "layouts/application"
+ }
+
+ it { should match_actions_links_snapshot "lines/index" }
+
+ %w(create update destroy).each do |p|
+ with_permission "lines.#{p}" do
+ it { should match_actions_links_snapshot "lines/index_#{p}" }
+ end
+ end
+ end
+
+ context "links" do
+ common_items = ->{
+ it { should have_link_for_each_item(lines, "show", -> (line){ view.line_referential_line_path(line_referential, line) }) }
+ it { should have_link_for_each_item(lines, "network", -> (line){ view.line_referential_network_path(line_referential, line.network) }) }
+ it { should have_link_for_each_item(lines, "company", -> (line){ view.line_referential_company_path(line_referential, line.company) }) }
+ }
+
+ common_items.call()
+ it { should have_the_right_number_of_links(lines, 3) }
+
+ with_permission "lines.change_status" do
+ common_items.call()
+ it { should have_link_for_each_item(lines, "deactivate", -> (line){ view.deactivate_line_referential_line_path(line_referential, line) }) }
+ it { should have_the_right_number_of_links(lines, 4) }
+ end
+
+ with_permission "lines.destroy" do
+ common_items.call()
+ it {
+ should have_link_for_each_item(lines, "destroy", {
+ href: ->(line){ view.line_referential_line_path(line_referential, line)},
+ method: :delete
+ })
+ }
+ it { should have_the_right_number_of_links(lines, 4) }
+ end
+
+ context "with a deactivated item" do
+ with_permission "lines.change_status" do
+ let(:deactivated_line){ create :line, deactivated: true }
+
+ common_items.call()
+ it "should display an activate link for the deactivated one" do
+ lines.each do |line|
+ if line == deactivated_line
+ href = view.activate_line_referential_line_path(line_referential, line)
+ else
+ href = view.deactivate_line_referential_line_path(line_referential, line)
+ end
+ selector = "tr.#{TableBuilderHelper.item_row_class_name(lines)}-#{line.id} .actions a[href='#{href}']"
+ expect(rendered).to have_selector(selector, count: 1)
+ end
+ end
+ it { should have_the_right_number_of_links(lines, 4) }
+ end
+ end
+ end
+end
diff --git a/spec/views/lines/show.html.erb_spec.rb b/spec/views/lines/show.html.erb_spec.rb
index 9649d9c8e..effdcd014 100644
--- a/spec/views/lines/show.html.erb_spec.rb
+++ b/spec/views/lines/show.html.erb_spec.rb
@@ -15,6 +15,30 @@ describe "/lines/show", :type => :view do
let!(:map) { assign(:map, double(:to_html => '<div id="map"/>'.html_safe)) }
before do
- allow(view).to receive_messages(current_organisation: referential.organisation)
+ allow(view).to receive_messages(current_organisation: referential.organisation, resource: line)
+ controller.request.path_parameters[:line_referential_id] = line_referential.id
+ controller.request.path_parameters[:id] = line.id
+ allow(view).to receive(:params).and_return({action: :show})
+ end
+
+ describe "action links" do
+ set_invariant "line_referential.id", "99"
+ set_invariant "line.object.id", "99"
+ set_invariant "line.object.name", "Name"
+ set_invariant "line.company.id", "99"
+ set_invariant "line.network.id", "99"
+ set_invariant "line.updated_at", "2018/01/23".to_time
+
+ before(:each){
+ render template: "lines/show", layout: "layouts/application"
+ }
+
+ it { should match_actions_links_snapshot "lines/show" }
+
+ %w(create update destroy).each do |p|
+ with_permission "lines.#{p}" do
+ it { should match_actions_links_snapshot "lines/show_#{p}" }
+ end
+ end
end
end
diff --git a/spec/views/networks/__snapshots__/networks/index.snap b/spec/views/networks/__snapshots__/networks/index.snap
new file mode 100644
index 000000000..2c5c23400
--- /dev/null
+++ b/spec/views/networks/__snapshots__/networks/index.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/networks/__snapshots__/networks/index_create.snap b/spec/views/networks/__snapshots__/networks/index_create.snap
new file mode 100644
index 000000000..afd4aa41b
--- /dev/null
+++ b/spec/views/networks/__snapshots__/networks/index_create.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><a class="btn btn-default" href="/line_referentials/99/networks/new">Ajouter un réseau</a></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/networks/__snapshots__/networks/index_destroy.snap b/spec/views/networks/__snapshots__/networks/index_destroy.snap
new file mode 100644
index 000000000..2c5c23400
--- /dev/null
+++ b/spec/views/networks/__snapshots__/networks/index_destroy.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/networks/__snapshots__/networks/index_update.snap b/spec/views/networks/__snapshots__/networks/index_update.snap
new file mode 100644
index 000000000..2c5c23400
--- /dev/null
+++ b/spec/views/networks/__snapshots__/networks/index_update.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/networks/__snapshots__/networks/show.snap b/spec/views/networks/__snapshots__/networks/show.snap
new file mode 100644
index 000000000..8f2992065
--- /dev/null
+++ b/spec/views/networks/__snapshots__/networks/show.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Réseau Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/networks/__snapshots__/networks/show_create.snap b/spec/views/networks/__snapshots__/networks/show_create.snap
new file mode 100644
index 000000000..8f2992065
--- /dev/null
+++ b/spec/views/networks/__snapshots__/networks/show_create.snap
@@ -0,0 +1,4 @@
+<div class="container-fluid"><div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Réseau Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div></div></div>
+</div></div> \ No newline at end of file
diff --git a/spec/views/networks/__snapshots__/networks/show_destroy.snap b/spec/views/networks/__snapshots__/networks/show_destroy.snap
new file mode 100644
index 000000000..c525c05b7
--- /dev/null
+++ b/spec/views/networks/__snapshots__/networks/show_destroy.snap
@@ -0,0 +1,7 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Réseau Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right"><a data-confirm="Etes vous sûr de supprimer ce réseau ?" class="btn btn-primary" rel="nofollow" data-method="delete" href="/line_referentials/99/networks/909"><span class="fa fa-trash mr-xs"></span>Supprimer ce réseau</a></div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/networks/__snapshots__/networks/show_update.snap b/spec/views/networks/__snapshots__/networks/show_update.snap
new file mode 100644
index 000000000..35f8ee9ac
--- /dev/null
+++ b/spec/views/networks/__snapshots__/networks/show_update.snap
@@ -0,0 +1,7 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>Réseau Name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 23/01/2018 <br> Par web service</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right"><a class="btn btn-primary" href="/line_referentials/99/networks/909/edit">Editer ce réseau</a></div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/networks/index.html.erb_spec.rb b/spec/views/networks/index.html.erb_spec.rb
index d2dde7f87..80e755163 100644
--- a/spec/views/networks/index.html.erb_spec.rb
+++ b/spec/views/networks/index.html.erb_spec.rb
@@ -3,7 +3,11 @@ require 'spec_helper'
describe "/networks/index", :type => :view do
let!(:line_referential) { assign :line_referential, create(:line_referential) }
- let!(:networks) { assign :networks, Array.new(2){ create(:network, line_referential: line_referential) }.paginate }
+ let(:context){{line_referential: line_referential}}
+ let!(:networks) do
+ assign :networks, build_paginated_collection(:network, NetworkDecorator, line_referential: line_referential, context: context)
+ end
+
let!(:search) { assign :q, Ransack::Search.new(Chouette::Network) }
# it "should render a show link for each group" do
@@ -18,5 +22,27 @@ describe "/networks/index", :type => :view do
# render
# expect(view.content_for(:sidebar)).to have_selector("a[href='#{new_line_referential_network_path(line_referential)}']")
# end
+ before(:each) do
+ allow(view).to receive(:collection).and_return(networks)
+ allow(view).to receive(:decorated_collection).and_return(networks)
+ allow(view).to receive(:current_referential).and_return(line_referential)
+ controller.request.path_parameters[:line_referential_id] = line_referential.id
+ allow(view).to receive(:params).and_return({action: :index})
+ end
+
+ describe "action links" do
+ set_invariant "line_referential.id", "99"
+
+ before(:each){
+ render template: "networks/index", layout: "layouts/application"
+ }
+
+ it { should match_actions_links_snapshot "networks/index" }
+ %w(create update destroy).each do |p|
+ with_permission "networks.#{p}" do
+ it { should match_actions_links_snapshot "networks/index_#{p}" }
+ end
+ end
+ end
end
diff --git a/spec/views/networks/show.html.erb_spec.rb b/spec/views/networks/show.html.erb_spec.rb
index 3926ead14..998e8ac44 100644
--- a/spec/views/networks/show.html.erb_spec.rb
+++ b/spec/views/networks/show.html.erb_spec.rb
@@ -11,8 +11,30 @@ describe "/networks/show", :type => :view do
let!(:map) { assign(:map, double(:to_html => '<div id="map"/>'.html_safe)) }
let!(:line_referential) { assign :line_referential, network.line_referential }
- # it "should display a map with class 'network'" do
- # render
- # expect(rendered).to have_selector("#map")
- # end
+ before(:each) do
+ allow(view).to receive(:current_referential).and_return(line_referential)
+ allow(view).to receive(:resource).and_return(network)
+ controller.request.path_parameters[:line_referential_id] = line_referential.id
+ controller.request.path_parameters[:id] = network.id
+ allow(view).to receive(:params).and_return({action: :show})
+ end
+
+ describe "action links" do
+ set_invariant "line_referential.id", "99"
+ set_invariant "network.object.id", "909"
+ set_invariant "network.object.updated_at", "2018/01/23".to_time
+ set_invariant "network.object.name", "Name"
+
+ before(:each){
+ render template: "networks/show", layout: "layouts/application"
+ }
+
+ it { should match_actions_links_snapshot "networks/show" }
+
+ %w(create update destroy).each do |p|
+ with_permission "networks.#{p}" do
+ it { should match_actions_links_snapshot "networks/show_#{p}" }
+ end
+ end
+ end
end
diff --git a/spec/views/offer_workbenches/show.html.erb_spec.rb b/spec/views/offer_workbenches/show.html.erb_spec.rb
index 40b09268a..2a2642911 100644
--- a/spec/views/offer_workbenches/show.html.erb_spec.rb
+++ b/spec/views/offer_workbenches/show.html.erb_spec.rb
@@ -1,5 +1,62 @@
-require 'rails_helper'
+require 'spec_helper'
-RSpec.describe "workbenches/show.html.erb", :type => :view do
+RSpec::Matchers.define :have_box_for_item do |item, disabled|
+ match do |actual|
+ klass = "#{TableBuilderHelper.item_row_class_name([item])}-#{item.id}"
+ if disabled
+ selector = "tr.#{klass} [type=checkbox][disabled][value='#{item.id}']"
+ else
+ selector = "tr.#{klass} [type=checkbox][value='#{item.id}']:not([disabled])"
+ end
+ expect(actual).to have_selector(selector, count: 1)
+ end
+ description { "have a #{disabled ? "disabled ": ""}box for the item ##{item.id}" }
+end
+
+describe "workbenches/show", :type => :view do
+ let!(:ids) { ['STIF:CODIFLIGNE:Line:C00840', 'STIF:CODIFLIGNE:Line:C00086'] }
+ let!(:lines) {
+ ids.map do |id|
+ create :line, objectid: id, line_referential: workbench.line_referential
+ end
+ }
+ let!(:workbench){ assign :workbench, create(:workbench) }
+ let!(:same_organisation_referential){ create :workbench_referential, workbench: workbench, metadatas: [create(:referential_metadata, lines: lines)] }
+ let!(:different_organisation_referential) do
+ create(
+ :workbench_referential,
+ workbench: create(:workbench, workgroup: workbench.workgroup),
+ metadatas: [create(:referential_metadata, lines: lines)]
+ )
+ end
+ let!(:referentials){
+ same_organisation_referential && different_organisation_referential
+ assign :wbench_refs, paginate_collection(Referential, ReferentialDecorator)
+ }
+ let!(:q) { assign :q_for_form, Ransack::Search.new(Referential) }
+ before :each do
+ lines
+ controller.request.path_parameters[:id] = workbench.id
+ expect(workbench.referentials).to include same_organisation_referential
+ expect(workbench.referentials).to_not include different_organisation_referential
+ expect(workbench.all_referentials).to include same_organisation_referential
+ expect(workbench.all_referentials).to include different_organisation_referential
+ render
+ end
+
+ it { should have_link_for_each_item(referentials, "show", -> (referential){ view.referential_path(referential) }) }
+
+ context "without permission" do
+ it "should disable all the checkboxes" do
+ expect(rendered).to have_box_for_item same_organisation_referential, false
+ expect(rendered).to have_box_for_item different_organisation_referential, true
+ end
+ end
+ with_permission "referentials.destroy" do
+ it "should enable the checkbox for the referential which belongs to the same organisation and disable the other one" do
+ expect(rendered).to have_box_for_item same_organisation_referential, false
+ expect(rendered).to have_box_for_item different_organisation_referential, true
+ end
+ end
end
diff --git a/spec/views/referentials/__snapshots__/referentials/show.snap b/spec/views/referentials/__snapshots__/referentials/show.snap
new file mode 100644
index 000000000..83531ac0e
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_create.snap b/spec/views/referentials/__snapshots__/referentials/show_create.snap
new file mode 100644
index 000000000..e5d309b96
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_create.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a><a class="btn btn-primary" href="/referentials/new?from=99">Dupliquer</a><a class="btn btn-primary" href="/referentials/99/select_compliance_control_set">Valider</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_destroy.snap b/spec/views/referentials/__snapshots__/referentials/show_destroy.snap
new file mode 100644
index 000000000..d90198391
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_destroy.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a><a data-confirm="Etes vous sûr de vouloir supprimer ce jeu de données ?" class="btn btn-primary" rel="nofollow" data-method="delete" href="/referentials/99"><span class="fa fa-trash mr-xs"></span>Supprimer</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_purchase_windows.snap b/spec/views/referentials/__snapshots__/referentials/show_purchase_windows.snap
new file mode 100644
index 000000000..83531ac0e
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_purchase_windows.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_purchase_windows_create.snap b/spec/views/referentials/__snapshots__/referentials/show_purchase_windows_create.snap
new file mode 100644
index 000000000..e5d309b96
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_purchase_windows_create.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a><a class="btn btn-primary" href="/referentials/new?from=99">Dupliquer</a><a class="btn btn-primary" href="/referentials/99/select_compliance_control_set">Valider</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_purchase_windows_destroy.snap b/spec/views/referentials/__snapshots__/referentials/show_purchase_windows_destroy.snap
new file mode 100644
index 000000000..d90198391
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_purchase_windows_destroy.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a><a data-confirm="Etes vous sûr de vouloir supprimer ce jeu de données ?" class="btn btn-primary" rel="nofollow" data-method="delete" href="/referentials/99"><span class="fa fa-trash mr-xs"></span>Supprimer</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_purchase_windows_update.snap b/spec/views/referentials/__snapshots__/referentials/show_purchase_windows_update.snap
new file mode 100644
index 000000000..32d46beda
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_purchase_windows_update.snap
@@ -0,0 +1,12 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action">
+<div class="small last-update">Dernière mise à jour le 01/01/2000</div>
+<a class="btn btn-default" href="/referentials/99/edit">Editer</a>
+</div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a><a class="btn btn-primary" rel="nofollow" data-method="put" href="/referentials/99/archive">Conserver</a><button type="button" data-toggle="modal" data-target="#purgeModal" class="btn btn-primary">Purger</button>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_readonly.snap b/spec/views/referentials/__snapshots__/referentials/show_readonly.snap
new file mode 100644
index 000000000..83531ac0e
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_readonly.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_readonly_create.snap b/spec/views/referentials/__snapshots__/referentials/show_readonly_create.snap
new file mode 100644
index 000000000..82a77521a
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_readonly_create.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a><a class="btn btn-primary" href="/referentials/new?from=99">Dupliquer</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_readonly_destroy.snap b/spec/views/referentials/__snapshots__/referentials/show_readonly_destroy.snap
new file mode 100644
index 000000000..83531ac0e
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_readonly_destroy.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_readonly_update.snap b/spec/views/referentials/__snapshots__/referentials/show_readonly_update.snap
new file mode 100644
index 000000000..83531ac0e
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_readonly_update.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys.snap b/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys.snap
new file mode 100644
index 000000000..83531ac0e
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_create.snap b/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_create.snap
new file mode 100644
index 000000000..e5d309b96
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_create.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a><a class="btn btn-primary" href="/referentials/new?from=99">Dupliquer</a><a class="btn btn-primary" href="/referentials/99/select_compliance_control_set">Valider</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_destroy.snap b/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_destroy.snap
new file mode 100644
index 000000000..d90198391
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_destroy.snap
@@ -0,0 +1,9 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action"><div class="small last-update">Dernière mise à jour le 01/01/2000</div></div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a><a data-confirm="Etes vous sûr de vouloir supprimer ce jeu de données ?" class="btn btn-primary" rel="nofollow" data-method="delete" href="/referentials/99"><span class="fa fa-trash mr-xs"></span>Supprimer</a>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_update.snap b/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_update.snap
new file mode 100644
index 000000000..32d46beda
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_referential_vehicle_journeys_update.snap
@@ -0,0 +1,12 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action">
+<div class="small last-update">Dernière mise à jour le 01/01/2000</div>
+<a class="btn btn-default" href="/referentials/99/edit">Editer</a>
+</div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a><a class="btn btn-primary" rel="nofollow" data-method="put" href="/referentials/99/archive">Conserver</a><button type="button" data-toggle="modal" data-target="#purgeModal" class="btn btn-primary">Purger</button>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/__snapshots__/referentials/show_update.snap b/spec/views/referentials/__snapshots__/referentials/show_update.snap
new file mode 100644
index 000000000..32d46beda
--- /dev/null
+++ b/spec/views/referentials/__snapshots__/referentials/show_update.snap
@@ -0,0 +1,12 @@
+<div class="container-fluid">
+<div class="row">
+<div class="col-lg-9 col-md-8 col-sm-7 col-xs-7"><div class="page-title"><h1>referential_full_name</h1></div></div>
+<div class="col-lg-3 col-md-4 col-sm-5 col-xs-5 text-right"><div class="page-action">
+<div class="small last-update">Dernière mise à jour le 01/01/2000</div>
+<a class="btn btn-default" href="/referentials/99/edit">Editer</a>
+</div></div>
+</div>
+<div class="row mb-sm"><div class="col-lg-12 text-right">
+<a class="btn btn-primary" href="/referentials/99/vehicle_journeys">Courses</a><a class="btn btn-primary" href="/referentials/99/purchase_windows">Calendriers commerciaux</a><a class="btn btn-primary" href="/referentials/99/time_tables">Calendriers</a><a class="btn btn-primary" rel="nofollow" data-method="put" href="/referentials/99/archive">Conserver</a><button type="button" data-toggle="modal" data-target="#purgeModal" class="btn btn-primary">Purger</button>
+</div></div>
+</div> \ No newline at end of file
diff --git a/spec/views/referentials/show.html.erb_spec.rb b/spec/views/referentials/show.html.erb_spec.rb
index f1fa7188a..ea3bc1fe1 100644
--- a/spec/views/referentials/show.html.erb_spec.rb
+++ b/spec/views/referentials/show.html.erb_spec.rb
@@ -1,4 +1,73 @@
require 'spec_helper'
describe "referentials/show", type: :view do
+ let!(:referential) do
+ referential = create(:referential, organisation: organisation)
+ assign :referential, referential.decorate(context: {
+ current_organisation: referential.organisation
+ })
+ end
+ let(:permissions){ [] }
+ let(:current_organisation) { organisation }
+ let(:current_offer_workbench) { create :workbench, organisation: organisation}
+ let(:current_workgroup) { current_offer_workbench.workgroup }
+ let(:readonly){ false }
+
+ before :each do
+ assign :reflines, []
+ allow(view).to receive(:current_offer_workbench).and_return(current_offer_workbench)
+ allow(view).to receive(:current_organisation).and_return(current_organisation)
+ allow(view).to receive(:current_workgroup).and_return(current_workgroup)
+ allow(view).to receive(:current_user).and_return(current_user)
+
+ allow(view).to receive(:resource).and_return(referential)
+ allow(view).to receive(:has_feature?).and_return(true)
+ allow(view).to receive(:user_signed_in?).and_return true
+ controller.request.path_parameters[:id] = referential.id
+ allow(view).to receive(:params).and_return({action: :show})
+
+ allow(referential).to receive(:referential_read_only?){ readonly }
+ end
+
+ describe "action links" do
+ set_invariant "referential.object.full_name", "referential_full_name"
+ set_invariant "referential.object.updated_at", "01/01/2000 00:00".to_time
+ set_invariant "referential.object.id", "99"
+
+ before(:each){
+ render template: "referentials/show", layout: "layouts/application"
+ }
+ context "with a readonly referential" do
+ let(:readonly){ true }
+ it { should match_actions_links_snapshot "referentials/show_readonly" }
+
+ %w(create destroy update).each do |p|
+ with_permission "referentials.#{p}" do
+ it { should match_actions_links_snapshot "referentials/show_readonly_#{p}" }
+ end
+ end
+ end
+
+ context "with a non-readonly referential" do
+ it { should match_actions_links_snapshot "referentials/show" }
+
+ %w(create destroy update).each do |p|
+ with_permission "referentials.#{p}" do
+ it { should match_actions_links_snapshot "referentials/show_#{p}" }
+ end
+ end
+ end
+
+ %w(purchase_windows referential_vehicle_journeys).each do |f|
+ with_feature f do
+ it { should match_actions_links_snapshot "referentials/show_#{f}" }
+
+ %w(create update destroy).each do |p|
+ with_permission "referentials.#{p}" do
+ it { should match_actions_links_snapshot "referentials/show_#{f}_#{p}" }
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/views/stop_areas/edit.html.erb_spec.rb b/spec/views/stop_areas/edit.html.erb_spec.rb
index 5105bff4b..bfbb0bb55 100644
--- a/spec/views/stop_areas/edit.html.erb_spec.rb
+++ b/spec/views/stop_areas/edit.html.erb_spec.rb
@@ -6,6 +6,10 @@ describe "/stop_areas/edit", :type => :view do
let!(:stop_area) { assign(:stop_area, create(:stop_area)) }
let!(:map) { assign(:map, double(:to_html => '<div id="map"/>'.html_safe)) }
+ before do
+ allow(view).to receive(:has_feature?)
+ end
+
describe "form" do
it "should render input for name" do
render
@@ -13,6 +17,5 @@ describe "/stop_areas/edit", :type => :view do
with_tag "input[type=text][name='stop_area[name]'][value=?]", stop_area.name
end
end
-
end
end
diff --git a/spec/views/stop_areas/index.html.erb_spec.rb b/spec/views/stop_areas/index.html.erb_spec.rb
deleted file mode 100644
index 2dfae1bfd..000000000
--- a/spec/views/stop_areas/index.html.erb_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-require 'spec_helper'
-
-describe "/stop_areas/index", :type => :view do
-
- let!(:stop_area_referential) { assign :stop_area_referential, create(:stop_area_referential) }
- let!(:stop_areas) { assign :stop_areas, Array.new(2) { create(:stop_area, stop_area_referential: stop_area_referential) }.paginate }
- let!(:q) { assign :q, Ransack::Search.new(Chouette::StopArea) }
-
- before :each do
- allow(view).to receive(:link_with_search).and_return("#")
- end
-
- # it "should render a show link for each group" do
- # render
- # stop_areas.each do |stop_area|
- # expect(rendered).to have_selector(".stop_area a[href='#{view.stop_area_referential_stop_area_path(stop_area_referential, stop_area)}']", :text => stop_area.name)
- # end
- # end
- #
- # it "should render a link to create a new group" do
- # render
- # expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{new_stop_area_referential_stop_area_path(stop_area_referential)}']")
- # end
-
-end
diff --git a/spec/views/stop_areas/index.html.slim_spec.rb b/spec/views/stop_areas/index.html.slim_spec.rb
new file mode 100644
index 000000000..6e66c5ab9
--- /dev/null
+++ b/spec/views/stop_areas/index.html.slim_spec.rb
@@ -0,0 +1,77 @@
+require 'spec_helper'
+
+describe "/stop_areas/index", :type => :view do
+ let(:deactivated_stop_area){ nil }
+ let(:stop_area_referential) { assign :stop_area_referential, create(:stop_area_referential) }
+ let(:stop_areas) do
+ assign :stop_areas, build_paginated_collection(:stop_area, StopAreaDecorator, stop_area_referential: stop_area_referential)
+ end
+ let!(:q) { assign :q, Ransack::Search.new(Chouette::StopArea) }
+
+ before :each do
+ deactivated_stop_area
+ allow(view).to receive(:link_with_search).and_return("#")
+ allow(view).to receive(:collection).and_return(stop_areas)
+ allow(view).to receive(:current_referential).and_return(stop_area_referential)
+ allow(view).to receive(:params).and_return({action: :index})
+ controller.request.path_parameters[:stop_area_referential_id] = stop_area_referential.id
+ render
+ end
+
+ common_items = ->{
+ it { should have_link_for_each_item(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) }
+ }
+
+ common_items.call()
+ it { should have_the_right_number_of_links(stop_areas, 1) }
+
+ with_permission "stop_areas.create" do
+ common_items.call()
+ it { should_not have_link_for_each_item(stop_areas, "create", -> (stop_area){ view.new_stop_area_referential_stop_area_path(stop_area_referential) }) }
+ it { should have_the_right_number_of_links(stop_areas, 1) }
+ end
+
+ with_permission "stop_areas.update" do
+ common_items.call()
+ it { should have_link_for_each_item(stop_areas, "edit", -> (stop_area){ view.edit_stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) }
+ it { should have_the_right_number_of_links(stop_areas, 2) }
+ end
+
+ with_permission "stop_areas.change_status" do
+ common_items.call()
+ it { should have_link_for_each_item(stop_areas, "deactivate", -> (stop_area){ view.deactivate_stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) }
+ it { should have_the_right_number_of_links(stop_areas, 2) }
+ end
+
+ with_permission "stop_areas.destroy" do
+ common_items.call()
+ it {
+ should have_link_for_each_item(stop_areas, "destroy", {
+ href: ->(stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area)},
+ method: :delete
+ })
+ }
+ it { should have_the_right_number_of_links(stop_areas, 2) }
+ end
+
+ context "with a deactivated item" do
+ with_permission "stop_areas.change_status" do
+ let(:deactivated_stop_area){ create :stop_area, :deactivated, stop_area_referential: stop_area_referential }
+
+ common_items.call()
+ it "should display an activate link for the deactivated one" do
+ stop_areas.each do |stop_area|
+ if stop_area == deactivated_stop_area
+ href = view.activate_stop_area_referential_stop_area_path(stop_area_referential, stop_area)
+ else
+ href = view.deactivate_stop_area_referential_stop_area_path(stop_area_referential, stop_area)
+ end
+ selector = "tr.#{TableBuilderHelper.item_row_class_name(stop_areas)}-#{stop_area.id} .actions a[href='#{href}']"
+ expect(rendered).to have_selector(selector, count: 1)
+ end
+ end
+ it { should have_the_right_number_of_links(stop_areas, 2) }
+ end
+ end
+
+end
diff --git a/spec/views/stop_areas/new.html.erb_spec.rb b/spec/views/stop_areas/new.html.erb_spec.rb
index 749782349..23f7387fa 100644
--- a/spec/views/stop_areas/new.html.erb_spec.rb
+++ b/spec/views/stop_areas/new.html.erb_spec.rb
@@ -5,6 +5,10 @@ describe "/stop_areas/new", :type => :view do
let!(:stop_area_referential) { assign :stop_area_referential, stop_area.stop_area_referential }
let!(:stop_area) { assign(:stop_area, build(:stop_area)) }
+ before do
+ allow(view).to receive(:has_feature?)
+ end
+
describe "form" do
it "should render input for name" do
diff --git a/spec/views/vehicle_journeys/index.html.slim_spec.rb b/spec/views/vehicle_journeys/index.html.slim_spec.rb
new file mode 100644
index 000000000..920067fa9
--- /dev/null
+++ b/spec/views/vehicle_journeys/index.html.slim_spec.rb
@@ -0,0 +1,31 @@
+require 'spec_helper'
+
+describe "/vehicle_journeys/index", :type => :view do
+
+ let!(:referential) { assign :referential, create(:referential) }
+ let!(:line) { assign :line, create(:line) }
+ let!(:route) { assign :route, create(:route, line: line) }
+ let!(:vehicle_journeys) do
+ assign :vehicle_journeys, build_paginated_collection(:vehicle_journey, nil, route: route)
+ end
+
+ before :each do
+ allow(view).to receive(:link_with_search).and_return("#")
+ allow(view).to receive(:collection).and_return(vehicle_journeys)
+ allow(view).to receive(:current_referential).and_return(referential)
+ allow(view).to receive(:has_feature?).and_return(true)
+ controller.request.path_parameters[:referential_id] = referential.id
+ render
+ end
+
+ context "with an opposite_route" do
+ let!(:route) { assign :route, create(:route, :with_opposite, line: line) }
+
+ it "should have an 'oppposite route timetable' button" do
+ href = view.referential_line_route_vehicle_journeys_path(referential, line, route.opposite_route)
+ oppposite_button_selector = "a[href=\"#{href}\"]"
+
+ expect(view.content_for(:page_header_content)).to have_selector oppposite_button_selector
+ end
+ end
+end
diff --git a/spec/views/vehicle_journeys/new.html.erb_spec.rb b/spec/views/vehicle_journeys/new.html.erb_spec.rb
index 546e89ac8..3408a8a26 100644
--- a/spec/views/vehicle_journeys/new.html.erb_spec.rb
+++ b/spec/views/vehicle_journeys/new.html.erb_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe "/vehicle_journeys/new", :type => :view do
-
+
assign_referential
let!(:line) { assign :line, create(:line) }
let!(:route) { assign :route, create(:route, :line => line) }
@@ -13,4 +13,3 @@ describe "/vehicle_journeys/new", :type => :view do
end
end
-
diff --git a/spec/workers/referential_cloning_worker_spec.rb b/spec/workers/referential_cloning_worker_spec.rb
index 7e4a2357a..74e83c3b2 100644
--- a/spec/workers/referential_cloning_worker_spec.rb
+++ b/spec/workers/referential_cloning_worker_spec.rb
@@ -2,52 +2,35 @@ require 'spec_helper'
require 'ostruct'
RSpec.describe ReferentialCloningWorker do
+ alias_method :worker, :subject
context "given a referential cloning" do
+ let(:id) { double }
+ let(:referential_cloning) { double }
- let( :id ){ double }
+ it "invokes the clone! method of the associated ReferentialCloning" do
+ expect(ReferentialCloning).to receive(:find).with(id).and_return(referential_cloning)
+ expect(referential_cloning).to receive(:clone_with_status!)
- let( :worker ){ described_class.new }
-
- def make_referential(schema_name)
- return OpenStruct.new( slug: schema_name )
- end
-
- let( :source_schema ){ "source_schema" }
- let( :target_schema ){ "target_schema" }
- let( :referential_cloning ){ OpenStruct.new(source_referential: make_referential(source_schema),
- target_referential: make_referential(target_schema)) }
- let( :cloner ){ 'cloner' }
-
-
- before do
- expect( ReferentialCloning ).to receive(:find).with(id).and_return(referential_cloning)
- expect( AF83::SchemaCloner ).to receive(:new).with( source_schema, target_schema ).and_return(cloner)
- expect( cloner ).to receive(:clone_schema)
-
- expect( referential_cloning ).to receive(:run!)
- end
-
- it "invokes the correct stored procedure, updates the database and the AASM" do
- expect( referential_cloning ).to receive(:successful!)
worker.perform(id)
end
end
- it "should clone an existing Referential" do
- source_referential = create :referential
-
- source_referential.switch
- source_time_table = create :time_table
+ context 'with existing Referential' do
+ it "preserve existing data" do
+ source_referential = create :referential
- target_referential = create :referential, created_from: source_referential
+ source_referential.switch
+ source_time_table = create :time_table
- cloning = ReferentialCloning.create source_referential: source_referential, target_referential: target_referential
- ReferentialCloningWorker.new.perform(cloning)
+ target_referential = create :referential, created_from: source_referential
- target_referential.switch
- expect(Chouette::TimeTable.where(objectid: source_time_table.objectid).exists?)
- end
+ cloning = ReferentialCloning.create source_referential: source_referential, target_referential: target_referential
+ worker.perform(cloning.id)
+ target_referential.switch
+ expect(Chouette::TimeTable.where(objectid: source_time_table.objectid).exists?)
+ end
+ end
end
diff --git a/spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb b/spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb
deleted file mode 100644
index 47626f5a1..000000000
--- a/spec/workers/workbench_import/workbench_import_with_corrupt_zip_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-RSpec.describe WorkbenchImportWorker do
-
- shared_examples_for 'corrupt zipfile data' do
- subject { described_class.new }
- let( :workbench_import ){ create :workbench_import, status: :pending }
-
- before do
- # Let us make sure that the name Enterprise will never be forgotten by history,
- # ahem, I meant, that nothing is uploaded, by forbidding any message to be sent
- # to HTTPService
- expect_it.to receive(:download).and_return(downloaded)
- end
-
- it 'does not upload' do
- stub_const 'HTTPService', double('HTTPService')
- subject.perform(workbench_import.id)
- end
-
- it 'does create a message' do
- expect{ subject.perform(workbench_import.id) }.to change{ workbench_import.messages.count }.by(1)
-
- message = workbench_import.messages.last
- expect( message.criticity ).to eq('error')
- expect( message.message_key ).to eq('corrupt_zip_file')
- expect( message.message_attributes ).to eq( 'source_filename' => workbench_import.file.file.file )
- end
-
- it 'does not change current step' do
- expect{ subject.perform(workbench_import.id) }.not_to change{ workbench_import.current_step }
- end
-
- it "sets the workbench_import.status to failed" do
- subject.perform(workbench_import.id)
- expect( workbench_import.reload.status ).to eq('failed')
- end
- end
-
- context 'empty zip file' do
- let( :downloaded ){ '' }
- it_should_behave_like 'corrupt zipfile data'
- end
-
- context 'corrupt data' do
- let( :downloaded ){ very_random }
- it_should_behave_like 'corrupt zipfile data'
- end
-end
diff --git a/spec/workers/workbench_import/workbench_import_worker_spec.rb b/spec/workers/workbench_import/workbench_import_worker_spec.rb
deleted file mode 100644
index 47ca2b4ff..000000000
--- a/spec/workers/workbench_import/workbench_import_worker_spec.rb
+++ /dev/null
@@ -1,169 +0,0 @@
-RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do
-
- let( :worker ) { described_class.new }
- let( :import ){ build_stubbed :import, token_download: download_token, file: zip_file }
-
- let( :workbench ){ import.workbench }
- let( :referential ){ import.referential }
- let( :api_key ){ build_stubbed :api_key, referential: referential, token: "#{referential.id}-#{random_hex}" }
-
- # http://www.example.com/workbenches/:workbench_id/imports/:id/download
- let( :host ){ Rails.configuration.rails_host }
- let( :path ){ download_workbench_import_path(workbench, import) }
-
- let( :downloaded_zip ){ double("downloaded zip") }
- let( :download_zip_response ){ OpenStruct.new( body: downloaded_zip ) }
- let( :download_token ){ random_string }
-
- let( :upload_path ) { api_v1_netex_imports_path(format: :json) }
-
- let( :spurious ){ [[], [], []] }
- let( :subdirs ) do
- entry_count.times.map do |i|
- ZipService::Subdir.new(
- "subdir #{i}",
- double("subdir #{i}", rewind: 0, read: ''),
- spurious[i]
- )
- end
- end
-
- let( :zip_service ){ double("zip service") }
- let( :zip_file ){ open_fixture('multiple_references_import.zip') }
-
- 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)
-
- # That should be `build_stubbed's` job, no?
- allow(Import).to receive(:find).with(import.id).and_return(import)
-
- 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(:subdirs).and_return(subdirs)
- expect( import ).to receive(:update).with(
- status: 'running',
- started_at: Time.now
- )
- end
-
- after do
- Timecop.return
- end
-
-
- context 'multireferential zipfile, no errors' do
- let( :entry_count ){ 2 }
-
- it 'downloads a zip file, cuts it, and uploads all pieces' do
-
- expect(HTTPService).to receive(:get_resource)
- .with(host: host, path: path, params: {token: download_token})
- .and_return( download_zip_response )
-
- subdirs.each do |subdir|
- mock_post subdir, post_response_ok
- end
-
- expect( import ).to receive(:update).with(total_steps: 2)
- expect( import ).to receive(:update).with(current_step: 1)
- expect( import ).to receive(:update).with(current_step: 2)
- expect( import ).to receive(:update).with(ended_at: Time.now)
-
- worker.perform import.id
-
- end
- end
-
- context 'multireferential zipfile with error' do
- let( :entry_count ){ 3 }
- let( :post_response_failure ){ double(status: 406, body: {error: 'What was you thinking'}) }
-
- it 'downloads a zip file, cuts it, and uploads some pieces' do
- expect(HTTPService).to receive(:get_resource)
- .with(host: host, path: path, params: {token: download_token})
- .and_return( download_zip_response )
-
- # First subdir succeeds
- subdirs[0..0].each do |subdir|
- mock_post subdir, post_response_ok
- 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).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')
-
- expect { worker.perform import.id }.to raise_error(StopIteration)
- end
- end
-
- context 'multireferential zipfile with spurious directories' do
- let( :entry_count ){ 2 }
- let( :spurious1 ){ [random_string] }
- let( :spurious2 ){ [random_string, random_string] }
- let( :spurious ){ [spurious1, spurious2] }
- let( :messages ){ double('messages') }
- let( :message_attributes ){{criticity: :warning, message_key: 'inconsistent_zip_file'}}
- let( :message1_attributes ){ message_attributes.merge(message_attributes: {'source_filename' => import.file.file.file, 'spurious_dirs' => spurious1.join(', ')}) }
- let( :message2_attributes ){ message_attributes.merge(message_attributes: {'source_filename' => import.file.file.file, 'spurious_dirs' => spurious2.join(', ')}) }
-
- before do
- allow(import).to receive(:messages).and_return(messages)
- end
-
- it 'downloads a zip file, cuts it, and uploads all pieces and adds messages' do
-
- expect(HTTPService).to receive(:get_resource)
- .with(host: host, path: path, params: {token: download_token})
- .and_return( download_zip_response )
-
- subdirs.each do |subdir|
- mock_post subdir, post_response_ok
- end
-
- expect( import ).to receive(:update).with(total_steps: 2)
- expect( import ).to receive(:update).with(current_step: 1)
- expect( messages ).to receive(:create).with(message1_attributes)
- expect( import ).to receive(:update).with(current_step: 2)
- expect( messages ).to receive(:create).with(message2_attributes)
- expect( import ).to receive(:update).with(ended_at: Time.now)
-
- worker.perform import.id
-
- end
-
- end
-
- def mock_post subdir, response
- allow(HTTPService).to receive(:upload)
- expect( HTTPService ).to receive(:post_resource)
- .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
diff --git a/spec/workers/workbench_import_worker_spec.rb b/spec/workers/workbench_import_worker_spec.rb
new file mode 100644
index 000000000..310693e1e
--- /dev/null
+++ b/spec/workers/workbench_import_worker_spec.rb
@@ -0,0 +1,102 @@
+RSpec.describe WorkbenchImportWorker, type: [:worker, :request, :zip] do
+
+ def self.expect_upload_with *entry_names, &blk
+ let(:expected_upload_names){ Set.new(entry_names.flatten) }
+
+ it "uploads the following entries: #{entry_names.flatten.inspect}" do
+ allow( HTTPService ).to receive(:post_resource)
+ .with(host: host, path: upload_path, params: anything) { |params|
+ name = params[:params][:netex_import][:name]
+ raise RuntimeError, "unexpected upload of entry #{name}" unless expected_upload_names.delete?(name)
+ OpenStruct.new(status: 201)
+ }
+ instance_eval(&blk)
+ expect( expected_upload_names ).to be_empty, "the following expected uploads were not executed: #{expected_upload_names.to_a.inspect}"
+ end
+ end
+
+ let( :lines ){ %w{*:C00109 *:C00108}.to_json }
+ let!( :organisation ){ workbench.organisation.update sso_attributes: {'functional_scope' => lines}}
+
+ let( :worker ) { described_class.new }
+ let( :workbench_import ){ create :workbench_import, token_download: download_token }
+
+ let( :workbench ){ workbench_import.workbench }
+
+ # http://www.example.com/workbenches/:workbench_id/imports/:id/download
+ let( :host ){ Rails.configuration.rails_host }
+ let( :path ){ download_workbench_import_path(workbench, workbench_import) }
+ let( :upload_path ){ api_v1_netex_imports_path(format: :json) }
+
+ let( :downloaded_zip_archive ){ make_zip_from_tree zip_data_dir }
+ let( :downloaded_zip_data ){ downloaded_zip_archive.data }
+ let( :download_token ){ random_string }
+
+ before do
+ stub_request(:get, "#{ host }#{ path }?token=#{ workbench_import.token_download }").
+ to_return(body: downloaded_zip_data, status: :success)
+ end
+
+ context 'correct workbench_import' do
+ let( :zip_data_dir ){ fixtures_path 'two_referentials_ok' }
+
+ expect_upload_with %w{ OFFRE_TRANSDEV_20170301122517 OFFRE_TRANSDEV_20170301122519 } do
+ expect{ worker.perform( workbench_import.id ) }.not_to change{ workbench_import.messages.count }
+ expect( workbench_import.reload.attributes.values_at(*%w{current_step total_steps}) )
+ .to eq([2, 2])
+ expect( workbench_import.reload.status ).to eq('running')
+ end
+
+ end
+
+ context 'correct but spurious directories' do
+ let( :zip_data_dir ){ fixtures_path 'extra_file_nok' }
+
+ expect_upload_with [] do
+ expect{ worker.perform( workbench_import.id ) }.to change{ workbench_import.messages.count }.by(1)
+ expect( workbench_import.reload.attributes.values_at(*%w{current_step total_steps}) )
+ .to eq([0, 0])
+ expect( workbench_import.messages.last.message_key ).to eq('inconsistent_zip_file')
+ expect( workbench_import.reload.status ).to eq('running')
+ end
+ end
+
+ context 'foreign lines' do
+ let( :zip_data_dir ){ fixtures_path 'some_foreign_mixed' }
+
+ expect_upload_with %w{ OFFRE_TRANSDEV_20170301122517 OFFRE_TRANSDEV_20170301122519 } do
+ expect{ worker.perform( workbench_import.id ) }.to change{ workbench_import.messages.count }.by(1)
+ expect( workbench_import.reload.attributes.values_at(*%w{current_step total_steps}) )
+ .to eq([2, 2])
+ expect( workbench_import.messages.last.message_key ).to eq('foreign_lines_in_referential')
+ expect( workbench_import.reload.status ).to eq('running')
+ end
+
+ end
+
+ context 'foreign and spurious' do
+ let( :zip_data_dir ){ fixtures_path 'foreign_and_spurious' }
+
+ expect_upload_with %w{ OFFRE_TRANSDEV_20170301122517 OFFRE_TRANSDEV_20170301122519 } do
+ expect{ worker.perform( workbench_import.id ) }.to change{ workbench_import.messages.count }.by(2)
+ expect( workbench_import.reload.attributes.values_at(*%w{current_step total_steps}) )
+ .to eq([2, 2])
+ expect( workbench_import.messages.last(2).map(&:message_key).sort )
+ .to eq(%w{foreign_lines_in_referential inconsistent_zip_file})
+ expect( workbench_import.reload.status ).to eq('running')
+ end
+ end
+
+ context 'corrupt zip file' do
+ let( :downloaded_zip_archive ){ OpenStruct.new(data: '') }
+
+ it 'will not upload anything' do
+ expect(HTTPService).not_to receive(:post_resource)
+ expect{ worker.perform( workbench_import.id ) }.to change{ workbench_import.messages.count }.by(1)
+ expect( workbench_import.messages.last.message_key ).to eq('corrupt_zip_file')
+ expect( workbench_import.reload.status ).to eq('failed')
+ end
+
+ end
+
+end
diff --git a/yarn.lock b/yarn.lock
index be9f38ae1..b32d906dd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,9 +2,17 @@
# yarn lockfile v1
-"@rails/webpacker@3.0.2":
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/@rails/webpacker/-/webpacker-3.0.2.tgz#574b021c1f3d700b40a934576c9bdac5c9f9c744"
+"@babel/code-frame@^7.0.0-beta.35":
+ version "7.0.0-beta.37"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.37.tgz#2da1dd3b1b57bfdea777ddc378df7cd12fe40171"
+ dependencies:
+ chalk "^2.0.0"
+ esutils "^2.0.2"
+ js-tokens "^3.0.0"
+
+"@rails/webpacker@3.2.0":
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/@rails/webpacker/-/webpacker-3.2.0.tgz#e9e98a4da4a3e09441c71d2cbd66461659971055"
dependencies:
babel-core "^6.26.0"
babel-loader "^7.1.2"
@@ -12,25 +20,27 @@
babel-plugin-transform-class-properties "^6.24.1"
babel-plugin-transform-object-rest-spread "^6.26.0"
babel-polyfill "^6.26.0"
- babel-preset-env "^1.6.0"
- coffee-loader "^0.8.0"
- compression-webpack-plugin "^1.0.0"
- css-loader "^0.28.5"
- extract-text-webpack-plugin "^3.0.0"
- file-loader "^0.11.2"
+ babel-preset-env "^1.6.1"
+ case-sensitive-paths-webpack-plugin "^2.1.1"
+ compression-webpack-plugin "^1.0.1"
+ css-loader "^0.28.7"
+ extract-text-webpack-plugin "^3.0.2"
+ file-loader "^1.1.5"
glob "^7.1.2"
- js-yaml "^3.9.1"
- node-sass "^4.5.3"
+ js-yaml "^3.10.0"
+ node-sass "^4.7.2"
path-complete-extname "^0.1.0"
postcss-cssnext "^3.0.2"
- postcss-loader "^2.0.6"
- postcss-smart-import "^0.7.5"
- rails-erb-loader "^5.2.1"
- resolve-url-loader "^2.1.0"
+ postcss-import "^11.0.0"
+ postcss-loader "^2.0.9"
sass-loader "^6.0.6"
- style-loader "^0.18.2"
- webpack "^3.5.5"
- webpack-manifest-plugin "^1.3.1"
+ style-loader "^0.19.0"
+ webpack "^3.10.0"
+ webpack-manifest-plugin "^1.3.2"
+
+"@types/node@*":
+ version "9.3.0"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-9.3.0.tgz#3a129cda7c4e5df2409702626892cb4b96546dd5"
abab@^1.0.3:
version "1.0.4"
@@ -53,13 +63,13 @@ acorn-dynamic-import@^2.0.0:
dependencies:
acorn "^4.0.3"
-acorn-globals@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf"
+acorn-globals@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.1.0.tgz#ab716025dbe17c54d3ef81d32ece2b2d99fe2538"
dependencies:
- acorn "^4.0.4"
+ acorn "^5.0.0"
-acorn@^4.0.3, acorn@^4.0.4:
+acorn@^4.0.3:
version "4.0.13"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
@@ -67,17 +77,9 @@ acorn@^5.0.0:
version "5.1.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7"
-adjust-sourcemap-loader@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.1.0.tgz#412d92404eb61e4113635012cba53a33d008e0e2"
- dependencies:
- assert "^1.3.0"
- camelcase "^1.2.1"
- loader-utils "^1.0.2"
- lodash.assign "^4.0.1"
- lodash.defaults "^3.1.2"
- object-path "^0.9.2"
- regex-parser "^2.2.1"
+acorn@^5.1.2:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822"
ajv-keywords@^2.0.0:
version "2.1.0"
@@ -145,10 +147,6 @@ ansi-styles@^3.1.0, ansi-styles@^3.2.0:
dependencies:
color-convert "^1.9.0"
-any-promise@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-0.1.0.tgz#830b680aa7e56f33451d4b049f3bd8044498ee27"
-
anymatch@^1.3.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a"
@@ -162,7 +160,7 @@ append-transform@^0.4.0:
dependencies:
default-require-extensions "^1.0.0"
-aproba@^1.0.3:
+aproba@^1.0.3, aproba@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -173,7 +171,7 @@ are-we-there-yet@~1.1.2:
delegates "^1.0.0"
readable-stream "^2.0.6"
-argparse@^1.0.7:
+argparse@^1.0.2, argparse@^1.0.7:
version "1.0.9"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
dependencies:
@@ -254,7 +252,7 @@ assert-plus@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
-assert@^1.1.1, assert@^1.3.0:
+assert@^1.1.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
dependencies:
@@ -272,13 +270,7 @@ async-foreach@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
-async@2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7"
- dependencies:
- lodash "^4.14.0"
-
-async@^1.4.0, async@^1.5.2:
+async@^1.4.0, async@^1.5.0, async@^1.5.2, async@~1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
@@ -292,10 +284,6 @@ asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
-atob@~1.1.0:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773"
-
autoprefixer@^6.3.1:
version "6.7.7"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014"
@@ -330,7 +318,7 @@ aws4@^1.2.1, aws4@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
-babel-code-frame@^6.11.0, babel-code-frame@^6.26.0:
+babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
dependencies:
@@ -338,7 +326,7 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.26.0:
esutils "^2.0.2"
js-tokens "^3.0.2"
-babel-core@^6.0.0, babel-core@^6.0.14, babel-core@^6.26.0:
+babel-core@^6.0.0, babel-core@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8"
dependencies:
@@ -484,12 +472,12 @@ babel-helpers@^6.24.1:
babel-runtime "^6.22.0"
babel-template "^6.24.1"
-babel-jest@21.2.0, babel-jest@^21.2.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-21.2.0.tgz#2ce059519a9374a2c46f2455b6fbef5ad75d863e"
+babel-jest@22.0.4, babel-jest@^22.0.4:
+ version "22.0.4"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-22.0.4.tgz#533c46de37d7c9d7612f408c76314be9277e0c26"
dependencies:
- babel-plugin-istanbul "^4.0.0"
- babel-preset-jest "^21.2.0"
+ babel-plugin-istanbul "^4.1.5"
+ babel-preset-jest "^22.0.3"
babel-loader@^7.1.2:
version "7.1.2"
@@ -505,13 +493,13 @@ babel-messages@^6.23.0:
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-check-es2015-constants@^6.22.0, babel-plugin-check-es2015-constants@^6.3.13:
+babel-plugin-check-es2015-constants@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-istanbul@^4.0.0:
+babel-plugin-istanbul@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.5.tgz#6760cdd977f411d3e175bb064f2bc327d99b2b6e"
dependencies:
@@ -519,9 +507,9 @@ babel-plugin-istanbul@^4.0.0:
istanbul-lib-instrument "^1.7.5"
test-exclude "^4.1.1"
-babel-plugin-jest-hoist@^21.2.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-21.2.0.tgz#2cef637259bd4b628a6cace039de5fcd14dbb006"
+babel-plugin-jest-hoist@^22.0.3:
+ version "22.0.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.0.3.tgz#62cde5fe962fd41ae89c119f481ca5cd7dd48bb4"
babel-plugin-syntax-async-functions@^6.8.0:
version "6.13.0"
@@ -572,19 +560,19 @@ babel-plugin-transform-class-properties@^6.24.1:
babel-runtime "^6.22.0"
babel-template "^6.24.1"
-babel-plugin-transform-es2015-arrow-functions@^6.22.0, babel-plugin-transform-es2015-arrow-functions@^6.3.13:
+babel-plugin-transform-es2015-arrow-functions@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-block-scoped-functions@^6.22.0, babel-plugin-transform-es2015-block-scoped-functions@^6.3.13:
+babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-block-scoping@^6.18.0, babel-plugin-transform-es2015-block-scoping@^6.23.0:
+babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f"
dependencies:
@@ -594,7 +582,7 @@ babel-plugin-transform-es2015-block-scoping@^6.18.0, babel-plugin-transform-es20
babel-types "^6.26.0"
lodash "^4.17.4"
-babel-plugin-transform-es2015-classes@^6.18.0, babel-plugin-transform-es2015-classes@^6.23.0:
+babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
dependencies:
@@ -608,33 +596,33 @@ babel-plugin-transform-es2015-classes@^6.18.0, babel-plugin-transform-es2015-cla
babel-traverse "^6.24.1"
babel-types "^6.24.1"
-babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.3.13:
+babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
dependencies:
babel-runtime "^6.22.0"
babel-template "^6.24.1"
-babel-plugin-transform-es2015-destructuring@^6.18.0, babel-plugin-transform-es2015-destructuring@^6.23.0:
+babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.6.0:
+babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
dependencies:
babel-runtime "^6.22.0"
babel-types "^6.24.1"
-babel-plugin-transform-es2015-for-of@^6.18.0, babel-plugin-transform-es2015-for-of@^6.23.0:
+babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.9.0:
+babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
dependencies:
@@ -642,13 +630,13 @@ babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es20
babel-runtime "^6.22.0"
babel-types "^6.24.1"
-babel-plugin-transform-es2015-literals@^6.22.0, babel-plugin-transform-es2015-literals@^6.3.13:
+babel-plugin-transform-es2015-literals@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-modules-amd@^6.18.0, babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1:
+babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
dependencies:
@@ -656,7 +644,7 @@ babel-plugin-transform-es2015-modules-amd@^6.18.0, babel-plugin-transform-es2015
babel-runtime "^6.22.0"
babel-template "^6.24.1"
-babel-plugin-transform-es2015-modules-commonjs@^6.18.0, babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
+babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a"
dependencies:
@@ -665,7 +653,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.18.0, babel-plugin-transform-e
babel-template "^6.26.0"
babel-types "^6.26.0"
-babel-plugin-transform-es2015-modules-systemjs@^6.18.0, babel-plugin-transform-es2015-modules-systemjs@^6.23.0:
+babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
dependencies:
@@ -673,7 +661,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.18.0, babel-plugin-transform-e
babel-runtime "^6.22.0"
babel-template "^6.24.1"
-babel-plugin-transform-es2015-modules-umd@^6.18.0, babel-plugin-transform-es2015-modules-umd@^6.23.0:
+babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
dependencies:
@@ -681,14 +669,14 @@ babel-plugin-transform-es2015-modules-umd@^6.18.0, babel-plugin-transform-es2015
babel-runtime "^6.22.0"
babel-template "^6.24.1"
-babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.3.13:
+babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
dependencies:
babel-helper-replace-supers "^6.24.1"
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-parameters@^6.18.0, babel-plugin-transform-es2015-parameters@^6.23.0:
+babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
dependencies:
@@ -699,20 +687,20 @@ babel-plugin-transform-es2015-parameters@^6.18.0, babel-plugin-transform-es2015-
babel-traverse "^6.24.1"
babel-types "^6.24.1"
-babel-plugin-transform-es2015-shorthand-properties@^6.18.0, babel-plugin-transform-es2015-shorthand-properties@^6.22.0:
+babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
dependencies:
babel-runtime "^6.22.0"
babel-types "^6.24.1"
-babel-plugin-transform-es2015-spread@^6.22.0, babel-plugin-transform-es2015-spread@^6.3.13:
+babel-plugin-transform-es2015-spread@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.3.13:
+babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
dependencies:
@@ -720,19 +708,19 @@ babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es201
babel-runtime "^6.22.0"
babel-types "^6.24.1"
-babel-plugin-transform-es2015-template-literals@^6.22.0, babel-plugin-transform-es2015-template-literals@^6.6.0:
+babel-plugin-transform-es2015-template-literals@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-typeof-symbol@^6.18.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0:
+babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.3.13:
+babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
dependencies:
@@ -790,7 +778,7 @@ babel-plugin-transform-react-jsx@^6.24.1:
babel-plugin-syntax-jsx "^6.8.0"
babel-runtime "^6.22.0"
-babel-plugin-transform-regenerator@^6.16.0, babel-plugin-transform-regenerator@^6.22.0:
+babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
dependencies:
@@ -803,15 +791,7 @@ babel-plugin-transform-strict-mode@^6.24.1:
babel-runtime "^6.22.0"
babel-types "^6.24.1"
-babel-polyfill@6.16.0:
- version "6.16.0"
- resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.16.0.tgz#2d45021df87e26a374b6d4d1a9c65964d17f2422"
- dependencies:
- babel-runtime "^6.9.1"
- core-js "^2.4.0"
- regenerator-runtime "^0.9.5"
-
-babel-polyfill@^6.26.0:
+babel-polyfill@6.26.0, babel-polyfill@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153"
dependencies:
@@ -819,9 +799,9 @@ babel-polyfill@^6.26.0:
core-js "^2.5.0"
regenerator-runtime "^0.10.5"
-babel-preset-env@^1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.0.tgz#2de1c782a780a0a5d605d199c957596da43c44e4"
+babel-preset-env@^1.6.1:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48"
dependencies:
babel-plugin-check-es2015-constants "^6.22.0"
babel-plugin-syntax-trailing-function-commas "^6.22.0"
@@ -854,34 +834,34 @@ babel-preset-env@^1.6.0:
invariant "^2.2.2"
semver "^5.3.0"
-babel-preset-es2015@6.18.0:
- version "6.18.0"
- resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.18.0.tgz#b8c70df84ec948c43dcf2bf770e988eb7da88312"
- dependencies:
- babel-plugin-check-es2015-constants "^6.3.13"
- babel-plugin-transform-es2015-arrow-functions "^6.3.13"
- babel-plugin-transform-es2015-block-scoped-functions "^6.3.13"
- babel-plugin-transform-es2015-block-scoping "^6.18.0"
- babel-plugin-transform-es2015-classes "^6.18.0"
- babel-plugin-transform-es2015-computed-properties "^6.3.13"
- babel-plugin-transform-es2015-destructuring "^6.18.0"
- babel-plugin-transform-es2015-duplicate-keys "^6.6.0"
- babel-plugin-transform-es2015-for-of "^6.18.0"
- babel-plugin-transform-es2015-function-name "^6.9.0"
- babel-plugin-transform-es2015-literals "^6.3.13"
- babel-plugin-transform-es2015-modules-amd "^6.18.0"
- babel-plugin-transform-es2015-modules-commonjs "^6.18.0"
- babel-plugin-transform-es2015-modules-systemjs "^6.18.0"
- babel-plugin-transform-es2015-modules-umd "^6.18.0"
- babel-plugin-transform-es2015-object-super "^6.3.13"
- babel-plugin-transform-es2015-parameters "^6.18.0"
- babel-plugin-transform-es2015-shorthand-properties "^6.18.0"
- babel-plugin-transform-es2015-spread "^6.3.13"
- babel-plugin-transform-es2015-sticky-regex "^6.3.13"
- babel-plugin-transform-es2015-template-literals "^6.6.0"
- babel-plugin-transform-es2015-typeof-symbol "^6.18.0"
- babel-plugin-transform-es2015-unicode-regex "^6.3.13"
- babel-plugin-transform-regenerator "^6.16.0"
+babel-preset-es2015@6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
+ dependencies:
+ babel-plugin-check-es2015-constants "^6.22.0"
+ babel-plugin-transform-es2015-arrow-functions "^6.22.0"
+ babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
+ babel-plugin-transform-es2015-block-scoping "^6.24.1"
+ babel-plugin-transform-es2015-classes "^6.24.1"
+ babel-plugin-transform-es2015-computed-properties "^6.24.1"
+ babel-plugin-transform-es2015-destructuring "^6.22.0"
+ babel-plugin-transform-es2015-duplicate-keys "^6.24.1"
+ babel-plugin-transform-es2015-for-of "^6.22.0"
+ babel-plugin-transform-es2015-function-name "^6.24.1"
+ babel-plugin-transform-es2015-literals "^6.22.0"
+ babel-plugin-transform-es2015-modules-amd "^6.24.1"
+ babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
+ babel-plugin-transform-es2015-modules-systemjs "^6.24.1"
+ babel-plugin-transform-es2015-modules-umd "^6.24.1"
+ babel-plugin-transform-es2015-object-super "^6.24.1"
+ babel-plugin-transform-es2015-parameters "^6.24.1"
+ babel-plugin-transform-es2015-shorthand-properties "^6.24.1"
+ babel-plugin-transform-es2015-spread "^6.22.0"
+ babel-plugin-transform-es2015-sticky-regex "^6.24.1"
+ babel-plugin-transform-es2015-template-literals "^6.22.0"
+ babel-plugin-transform-es2015-typeof-symbol "^6.22.0"
+ babel-plugin-transform-es2015-unicode-regex "^6.24.1"
+ babel-plugin-transform-regenerator "^6.24.1"
babel-preset-flow@^6.23.0:
version "6.23.0"
@@ -889,11 +869,11 @@ babel-preset-flow@^6.23.0:
dependencies:
babel-plugin-transform-flow-strip-types "^6.22.0"
-babel-preset-jest@^21.2.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-21.2.0.tgz#ff9d2bce08abd98e8a36d9a8a5189b9173b85638"
+babel-preset-jest@^22.0.3:
+ version "22.0.3"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-22.0.3.tgz#e2bb6f6b4a509d3ea0931f013db78c5a84856693"
dependencies:
- babel-plugin-jest-hoist "^21.2.0"
+ babel-plugin-jest-hoist "^22.0.3"
babel-plugin-syntax-object-rest-spread "^6.13.0"
babel-preset-react@6.24.1:
@@ -919,7 +899,7 @@ babel-register@^6.26.0:
mkdirp "^0.5.1"
source-map-support "^0.4.15"
-babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0, babel-runtime@^6.9.1:
+babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
dependencies:
@@ -959,12 +939,9 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26
lodash "^4.17.4"
to-fast-properties "^1.0.3"
-babelify@7.3.0:
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5"
- dependencies:
- babel-core "^6.0.14"
- object-assign "^4.0.0"
+babelify@8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/babelify/-/babelify-8.0.0.tgz#6f60f5f062bfe7695754ef2403b842014a580ed3"
babylon@^6.18.0:
version "6.18.0"
@@ -1010,6 +987,10 @@ block-stream@*:
dependencies:
inherits "~2.0.0"
+bluebird@^3.5.0:
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
+
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
version "4.11.8"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
@@ -1029,6 +1010,21 @@ body-parser@1.18.2:
raw-body "2.3.2"
type-is "~1.6.15"
+body-parser@~1.14.0:
+ version "1.14.2"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.14.2.tgz#1015cb1fe2c443858259581db53332f8d0cf50f9"
+ dependencies:
+ bytes "2.2.0"
+ content-type "~1.0.1"
+ debug "~2.2.0"
+ depd "~1.1.0"
+ http-errors "~1.3.1"
+ iconv-lite "0.4.13"
+ on-finished "~2.3.0"
+ qs "5.2.0"
+ raw-body "~2.1.5"
+ type-is "~1.6.10"
+
bonjour@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5"
@@ -1081,6 +1077,10 @@ brorand@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+browser-process-hrtime@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e"
+
browser-resolve@^1.11.2:
version "1.11.2"
resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce"
@@ -1183,10 +1183,36 @@ builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
+bytes@2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.2.0.tgz#fd35464a403f6f9117c2de3609ecff9cae000588"
+
+bytes@2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339"
+
bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+cacache@^10.0.1:
+ version "10.0.2"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.2.tgz#105a93a162bbedf3a25da42e1939ed99ffb145f8"
+ dependencies:
+ bluebird "^3.5.0"
+ chownr "^1.0.1"
+ glob "^7.1.2"
+ graceful-fs "^4.1.11"
+ lru-cache "^4.1.1"
+ mississippi "^1.3.0"
+ mkdirp "^0.5.1"
+ move-concurrently "^1.0.1"
+ promise-inflight "^1.0.1"
+ rimraf "^2.6.1"
+ ssri "^5.0.0"
+ unique-filename "^1.1.0"
+ y18n "^3.2.1"
+
callsites@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
@@ -1198,7 +1224,7 @@ camelcase-keys@^2.0.0:
camelcase "^2.0.0"
map-obj "^1.0.0"
-camelcase@^1.0.2, camelcase@^1.2.1:
+camelcase@^1.0.2:
version "1.2.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
@@ -1210,7 +1236,7 @@ camelcase@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
-camelcase@^4.0.0, camelcase@^4.1.0:
+camelcase@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
@@ -1240,6 +1266,14 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000744:
version "1.0.30000746"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000746.tgz#c64f95a3925cfd30207a308ed76c1ae96ea09ea0"
+case-sensitive-paths-webpack-plugin@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.1.1.tgz#3d29ced8c1f124bf6f53846fb3f5894731fdc909"
+
+caseless@~0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7"
+
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@@ -1251,7 +1285,7 @@ center-align@^0.1.1:
align-text "^0.1.3"
lazy-cache "^1.0.3"
-chalk@^1.1.1, chalk@^1.1.3:
+chalk@^1.1.1, chalk@^1.1.3, chalk@~1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
dependencies:
@@ -1261,6 +1295,14 @@ chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
+chalk@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba"
+ dependencies:
+ ansi-styles "^3.1.0"
+ escape-string-regexp "^1.0.5"
+ supports-color "^4.0.0"
+
chalk@^2.0.1, chalk@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e"
@@ -1284,6 +1326,10 @@ chokidar@^1.6.0, chokidar@^1.7.0:
optionalDependencies:
fsevents "^1.0.0"
+chownr@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181"
+
ci-info@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.1.tgz#47b44df118c48d2597b56d342e7e25791060171a"
@@ -1301,9 +1347,9 @@ clap@^1.0.9:
dependencies:
chalk "^1.1.3"
-clean-webpack-plugin@0.1.17:
- version "0.1.17"
- resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-0.1.17.tgz#71c57242e6d47204d46f809413176e7bed28ec49"
+clean-webpack-plugin@^0.1.18:
+ version "0.1.18"
+ resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-0.1.18.tgz#2e2173897c76646031bff047c14b9c22c80d8c4a"
dependencies:
rimraf "^2.6.1"
@@ -1323,6 +1369,14 @@ cliui@^3.2.0:
strip-ansi "^3.0.1"
wrap-ansi "^2.0.0"
+cliui@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.0.0.tgz#743d4650e05f36d1ed2575b59638d87322bfbbcc"
+ dependencies:
+ string-width "^2.1.1"
+ strip-ansi "^4.0.0"
+ wrap-ansi "^2.0.0"
+
clone-deep@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.3.0.tgz#348c61ae9cdbe0edfe053d91ff4cc521d790ede8"
@@ -1350,12 +1404,16 @@ code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
-coffee-loader@^0.8.0:
- version "0.8.0"
- resolved "https://registry.yarnpkg.com/coffee-loader/-/coffee-loader-0.8.0.tgz#ec48e7327da8e3a99047a99d9bdcfcac12df3694"
+coffee-loader@^0.9.0:
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/coffee-loader/-/coffee-loader-0.9.0.tgz#6deabd336062ddc6d773da4dfd16367fc7107bd6"
dependencies:
loader-utils "^1.0.2"
+coffee-script@~1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.10.0.tgz#12938bcf9be1948fa006f92e0c4c9e81705108c0"
+
coffeescript@1.12.7:
version "1.12.7"
resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.12.7.tgz#e57ee4c4867cf7f606bfc4a0f2d550c0981ddd27"
@@ -1416,29 +1474,28 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
dependencies:
delayed-stream "~1.0.0"
-commander@~2.11.0:
- version "2.11.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
+commander@^2.9.0, commander@~2.12.1:
+ version "2.12.2"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555"
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
-complex.js@2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.0.4.tgz#d8e7cfb9652d1e853e723386421c1a0ca7a48373"
-
compressible@~2.0.11:
version "2.0.11"
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.11.tgz#16718a75de283ed8e604041625a2064586797d8a"
dependencies:
mime-db ">= 1.29.0 < 2"
-compression-webpack-plugin@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-1.0.1.tgz#7f0a2af9f642b4f87b5989516a3b9e9b41bb4b3f"
+compression-webpack-plugin@^1.0.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-1.1.3.tgz#4b936c627eda09304e3153499ece7830289ab95a"
dependencies:
- async "2.4.1"
+ async "^2.4.1"
+ cacache "^10.0.1"
+ find-cache-dir "^1.0.0"
+ serialize-javascript "^1.4.0"
webpack-sources "^1.0.1"
compression@^1.5.2:
@@ -1457,6 +1514,14 @@ concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+concat-stream@^1.5.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
+ dependencies:
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
connect-history-api-fallback@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz#e51d17f8f0ef0db90a64fdb47de3051556e9f169"
@@ -1483,15 +1548,11 @@ content-type-parser@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.1.tgz#c3e56988c53c65127fb46d4032a3a900246fdc94"
-content-type@~1.0.4:
+content-type@~1.0.1, content-type@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
-convert-source-map@^0.3.3:
- version "0.3.5"
- resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190"
-
-convert-source-map@^1.1.1, convert-source-map@^1.4.0, convert-source-map@^1.5.0:
+convert-source-map@^1.4.0, convert-source-map@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5"
@@ -1503,6 +1564,17 @@ cookie@0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
+copy-concurrently@^1.0.0:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
+ dependencies:
+ aproba "^1.1.1"
+ fs-write-stream-atomic "^1.0.8"
+ iferr "^0.1.5"
+ mkdirp "^0.5.1"
+ rimraf "^2.5.4"
+ run-queue "^1.0.0"
+
core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
@@ -1609,22 +1681,22 @@ css-color-names@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
-css-loader@^0.28.5:
- version "0.28.7"
- resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.7.tgz#5f2ee989dd32edd907717f953317656160999c1b"
+css-loader@^0.28.7:
+ version "0.28.8"
+ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.8.tgz#ff36381464dea18fe60f2601a060ba6445886bd5"
dependencies:
- babel-code-frame "^6.11.0"
+ babel-code-frame "^6.26.0"
css-selector-tokenizer "^0.7.0"
- cssnano ">=2.6.1 <4"
+ cssnano "^3.10.0"
icss-utils "^2.1.0"
loader-utils "^1.0.2"
lodash.camelcase "^4.3.0"
- object-assign "^4.0.1"
+ object-assign "^4.1.1"
postcss "^5.0.6"
- postcss-modules-extract-imports "^1.0.0"
- postcss-modules-local-by-default "^1.0.1"
- postcss-modules-scope "^1.0.0"
- postcss-modules-values "^1.1.0"
+ postcss-modules-extract-imports "^1.1.0"
+ postcss-modules-local-by-default "^1.2.0"
+ postcss-modules-scope "^1.1.0"
+ postcss-modules-values "^1.3.0"
postcss-value-parser "^3.3.0"
source-list-map "^2.0.0"
@@ -1640,20 +1712,11 @@ css-unit-converter@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996"
-css@^2.0.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc"
- dependencies:
- inherits "^2.0.1"
- source-map "^0.1.38"
- source-map-resolve "^0.3.0"
- urix "^0.1.0"
-
cssesc@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
-"cssnano@>=2.6.1 <4":
+cssnano@^3.10.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38"
dependencies:
@@ -1713,6 +1776,10 @@ currently-unhandled@^0.4.1:
dependencies:
array-find-index "^1.0.1"
+cyclist@~0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
+
d@1:
version "1.0.0"
resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
@@ -1729,6 +1796,13 @@ date-now@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
+dateformat@~1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9"
+ dependencies:
+ get-stdin "^4.0.1"
+ meow "^3.3.0"
+
debug@2.6.9, debug@^2.2.0, debug@^2.6.3, debug@^2.6.6, debug@^2.6.8:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -1741,17 +1815,19 @@ debug@^3.1.0:
dependencies:
ms "2.0.0"
+debug@~2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
+ dependencies:
+ ms "0.7.1"
+
decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
-decimal.js@7.2.3:
- version "7.2.3"
- resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-7.2.3.tgz#6434c3b8a8c375780062fc633d0d2bbdb264cc78"
-
-deep-diff@0.3.4:
- version "0.3.4"
- resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.4.tgz#aac5c39952236abe5f037a2349060ba01b00ae48"
+deep-diff@^0.3.5:
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84"
deep-equal@^1.0.1:
version "1.0.1"
@@ -1801,7 +1877,7 @@ delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
-depd@1.1.1, depd@~1.1.1:
+depd@1.1.1, depd@~1.1.0, depd@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
@@ -1822,11 +1898,15 @@ detect-indent@^4.0.0:
dependencies:
repeating "^2.0.0"
+detect-newline@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
+
detect-node@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127"
-diff@^3.2.0:
+diff@^3.1.0, diff@^3.2.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c"
@@ -1859,6 +1939,19 @@ domain-browser@^1.1.1:
version "1.1.7"
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc"
+domexception@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.0.tgz#81fe5df81b3f057052cde3a9fa9bf536a85b9ab0"
+
+duplexify@^3.1.2, duplexify@^3.4.2:
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd"
+ dependencies:
+ end-of-stream "^1.0.0"
+ inherits "^2.0.1"
+ readable-stream "^2.0.0"
+ stream-shift "^1.0.0"
+
ecc-jsbn@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
@@ -1899,6 +1992,12 @@ encoding@^0.1.11:
dependencies:
iconv-lite "~0.4.13"
+end-of-stream@^1.0.0, end-of-stream@^1.1.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206"
+ dependencies:
+ once "^1.4.0"
+
enhanced-resolve@^3.4.0:
version "3.4.1"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e"
@@ -1908,7 +2007,7 @@ enhanced-resolve@^3.4.0:
object-assign "^4.0.1"
tapable "^0.2.7"
-errno@^0.1.3, errno@^0.1.4:
+errno@^0.1.3:
version "0.1.4"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d"
dependencies:
@@ -1920,6 +2019,16 @@ error-ex@^1.2.0:
dependencies:
is-arrayish "^0.2.1"
+es-abstract@^1.5.1:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864"
+ dependencies:
+ es-to-primitive "^1.1.1"
+ function-bind "^1.1.1"
+ has "^1.0.1"
+ is-callable "^1.1.3"
+ is-regex "^1.0.4"
+
es-abstract@^1.7.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.9.0.tgz#690829a07cae36b222e7fd9b75c0d0573eb25227"
@@ -1964,9 +2073,9 @@ es6-map@^0.1.3:
es6-symbol "~3.1.1"
event-emitter "~0.3.5"
-es6-object-assign@1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.0.3.tgz#40a192e0fda5ee44ee8cf6f5b5d9b47cd0f69b14"
+es6-object-assign@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
es6-set@~0.1.5:
version "0.1.5"
@@ -2002,7 +2111,7 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
-escodegen@^1.6.1:
+escodegen@^1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.0.tgz#9811a2f265dc1cd3894420ee3717064b632b8852"
dependencies:
@@ -2060,6 +2169,10 @@ event-emitter@~0.3.5:
d "1"
es5-ext "~0.10.14"
+eventemitter2@~0.4.13:
+ version "0.4.14"
+ resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab"
+
eventemitter3@1.x.x:
version "1.2.0"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508"
@@ -2099,6 +2212,10 @@ execa@^0.7.0:
signal-exit "^3.0.0"
strip-eof "^1.0.0"
+exit@~0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
+
expand-brackets@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
@@ -2111,18 +2228,18 @@ expand-range@^1.8.1:
dependencies:
fill-range "^2.1.0"
-expect@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/expect/-/expect-21.2.1.tgz#003ac2ac7005c3c29e73b38a272d4afadd6d1d7b"
+expect@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-22.0.5.tgz#a7b64c689e430c8af49a3460eb98adf0e51b5196"
dependencies:
ansi-styles "^3.2.0"
- jest-diff "^21.2.1"
- jest-get-type "^21.2.0"
- jest-matcher-utils "^21.2.1"
- jest-message-util "^21.2.1"
- jest-regex-util "^21.2.0"
+ jest-diff "^22.0.5"
+ jest-get-type "^22.0.3"
+ jest-matcher-utils "^22.0.5"
+ jest-message-util "^22.0.3"
+ jest-regex-util "^22.0.5"
-express@^4.13.3:
+express@^4.16.2:
version "4.16.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c"
dependencies:
@@ -2167,9 +2284,9 @@ extglob@^0.3.1:
dependencies:
is-extglob "^1.0.0"
-extract-text-webpack-plugin@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.1.tgz#605a8893faca1dd49bb0d2ca87493f33fd43d102"
+extract-text-webpack-plugin@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz#5f043eaa02f9750a9258b78c0a6e0dc1408fb2f7"
dependencies:
async "^2.4.1"
loader-utils "^1.1.0"
@@ -2192,7 +2309,7 @@ fastparse@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"
-faye-websocket@^0.10.0:
+faye-websocket@^0.10.0, faye-websocket@~0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
dependencies:
@@ -2210,7 +2327,7 @@ fb-watchman@^2.0.0:
dependencies:
bser "^2.0.0"
-fbjs@^0.8.4:
+fbjs@^0.8.16:
version "0.8.16"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db"
dependencies:
@@ -2222,11 +2339,12 @@ fbjs@^0.8.4:
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"
-file-loader@^0.11.2:
- version "0.11.2"
- resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-0.11.2.tgz#4ff1df28af38719a6098093b88c82c71d1794a34"
+file-loader@^1.1.5:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-1.1.6.tgz#7b9a8f2c58f00a77fddf49e940f7ac978a3ea0e8"
dependencies:
loader-utils "^1.0.2"
+ schema-utils "^0.3.0"
filename-regex@^2.0.0:
version "2.0.1"
@@ -2282,10 +2400,23 @@ find-up@^2.0.0, find-up@^2.1.0:
dependencies:
locate-path "^2.0.0"
+findup-sync@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16"
+ dependencies:
+ glob "~5.0.0"
+
flatten@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
+flush-write-stream@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.2.tgz#c81b90d8746766f1a609a46809946c45dd8ae417"
+ dependencies:
+ inherits "^2.0.1"
+ readable-stream "^2.0.4"
+
flux-standard-action@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/flux-standard-action/-/flux-standard-action-0.6.1.tgz#6f34211b94834ea1c3cc30f4e7afad3d0fbf71a2"
@@ -2336,24 +2467,27 @@ form-data@~2.3.1:
combined-stream "^1.0.5"
mime-types "^2.1.12"
-formatio@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9"
+formatio@1.2.0, formatio@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb"
dependencies:
- samsam "~1.1"
+ samsam "1.x"
forwarded@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
-fraction.js@4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.0.2.tgz#0eae896626f334b1bde763371347a83b5575d7f0"
-
fresh@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+from2@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
+ dependencies:
+ inherits "^2.0.1"
+ readable-stream "^2.0.0"
+
fs-extra@^0.30.0:
version "0.30.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0"
@@ -2364,6 +2498,15 @@ fs-extra@^0.30.0:
path-is-absolute "^1.0.0"
rimraf "^2.2.8"
+fs-write-stream-atomic@^1.0.8:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
+ dependencies:
+ graceful-fs "^4.1.2"
+ iferr "^0.1.5"
+ imurmurhash "^0.1.4"
+ readable-stream "1 || 2"
+
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -2415,6 +2558,16 @@ gaze@^1.0.0:
dependencies:
globule "^1.0.0"
+generate-function@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74"
+
+generate-object-property@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
+ dependencies:
+ is-property "^1.0.0"
+
get-caller-file@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
@@ -2427,6 +2580,10 @@ get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
+getobject@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/getobject/-/getobject-0.1.0.tgz#047a449789fa160d018f5486ed91320b6ec7885c"
+
getpass@^0.1.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
@@ -2446,6 +2603,16 @@ glob-parent@^2.0.0:
dependencies:
is-glob "^2.0.0"
+glob@^6.0.4:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22"
+ dependencies:
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "2 || 3"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1:
version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
@@ -2457,6 +2624,27 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1:
once "^1.3.0"
path-is-absolute "^1.0.0"
+glob@~5.0.0:
+ version "5.0.15"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
+ dependencies:
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "2 || 3"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+glob@~7.0.0:
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a"
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.2"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
globals@^9.18.0:
version "9.18.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
@@ -2479,12 +2667,6 @@ globule@^1.0.0:
lodash "~4.17.4"
minimatch "~3.0.2"
-gonzales-pe@^4.0.3:
- version "4.2.2"
- resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.2.tgz#f50a8c17842f13a9007909b7cb32188266e4d74c"
- dependencies:
- minimist "1.1.x"
-
graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
@@ -2493,6 +2675,82 @@ growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
+grunt-cli@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/grunt-cli/-/grunt-cli-1.2.0.tgz#562b119ebb069ddb464ace2845501be97b35b6a8"
+ dependencies:
+ findup-sync "~0.3.0"
+ grunt-known-options "~1.1.0"
+ nopt "~3.0.6"
+ resolve "~1.1.0"
+
+grunt-contrib-watch@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz#84a1a7a1d6abd26ed568413496c73133e990018f"
+ dependencies:
+ async "^1.5.0"
+ gaze "^1.0.0"
+ lodash "^3.10.1"
+ tiny-lr "^0.2.1"
+
+grunt-known-options@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/grunt-known-options/-/grunt-known-options-1.1.0.tgz#a4274eeb32fa765da5a7a3b1712617ce3b144149"
+
+grunt-legacy-log-utils@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz#a7b8e2d0fb35b5a50f4af986fc112749ebc96f3d"
+ dependencies:
+ chalk "~1.1.1"
+ lodash "~4.3.0"
+
+grunt-legacy-log@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/grunt-legacy-log/-/grunt-legacy-log-1.0.0.tgz#fb86f1809847bc07dc47843f9ecd6cacb62df2d5"
+ dependencies:
+ colors "~1.1.2"
+ grunt-legacy-log-utils "~1.0.0"
+ hooker "~0.2.3"
+ lodash "~3.10.1"
+ underscore.string "~3.2.3"
+
+grunt-legacy-util@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz#386aa78dc6ed50986c2b18957265b1b48abb9b86"
+ dependencies:
+ async "~1.5.2"
+ exit "~0.1.1"
+ getobject "~0.1.0"
+ hooker "~0.2.3"
+ lodash "~4.3.0"
+ underscore.string "~3.2.3"
+ which "~1.2.1"
+
+grunt-watch-change@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/grunt-watch-change/-/grunt-watch-change-0.1.1.tgz#fab1281eb66f44aef02a7f2f1335944c6c05ec08"
+
+grunt@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/grunt/-/grunt-1.0.1.tgz#e8778764e944b18f32bb0f10b9078475c9dfb56b"
+ dependencies:
+ coffee-script "~1.10.0"
+ dateformat "~1.0.12"
+ eventemitter2 "~0.4.13"
+ exit "~0.1.1"
+ findup-sync "~0.3.0"
+ glob "~7.0.0"
+ grunt-cli "~1.2.0"
+ grunt-known-options "~1.1.0"
+ grunt-legacy-log "~1.0.0"
+ grunt-legacy-util "~1.0.0"
+ iconv-lite "~0.4.13"
+ js-yaml "~3.5.2"
+ minimatch "~3.0.0"
+ nopt "~3.0.6"
+ path-is-absolute "~1.0.0"
+ rimraf "~2.2.8"
+
handle-thing@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
@@ -2515,6 +2773,15 @@ har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
+har-validator@~2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d"
+ dependencies:
+ chalk "^1.1.1"
+ commander "^2.9.0"
+ is-my-json-valid "^2.12.4"
+ pinkie-promise "^2.0.0"
+
har-validator@~4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
@@ -2607,9 +2874,9 @@ hoek@4.x.x:
version "4.2.0"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d"
-hoist-non-react-statics@^1.0.3:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
+hoist-non-react-statics@^2.2.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0"
home-or-tmp@^2.0.0:
version "2.0.0"
@@ -2618,6 +2885,10 @@ home-or-tmp@^2.0.0:
os-homedir "^1.0.0"
os-tmpdir "^1.0.1"
+hooker@~0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/hooker/-/hooker-0.2.3.tgz#b834f723cc4a242aa65963459df6d984c5d3d959"
+
hosted-git-info@^2.1.4:
version "2.5.0"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
@@ -2658,6 +2929,13 @@ http-errors@1.6.2, http-errors@~1.6.2:
setprototypeof "1.0.3"
statuses ">= 1.3.1 < 2"
+http-errors@~1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942"
+ dependencies:
+ inherits "~2.0.1"
+ statuses "1"
+
http-parser-js@>=0.4.0:
version "0.4.9"
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.9.tgz#ea1a04fb64adff0242e9974f297dd4c3cad271e1"
@@ -2720,6 +2998,17 @@ ieee754@^1.1.4:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
+iferr@^0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
+
+import-local@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/import-local/-/import-local-0.1.1.tgz#b1179572aacdc11c6a91009fb430dbcab5f668a8"
+ dependencies:
+ pkg-dir "^2.0.0"
+ resolve-cwd "^2.0.0"
+
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
@@ -2873,6 +3162,10 @@ is-fullwidth-code-point@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+is-generator-fn@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a"
+
is-glob@^2.0.0, is-glob@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
@@ -2885,6 +3178,15 @@ is-glob@^3.1.0:
dependencies:
is-extglob "^2.1.0"
+is-my-json-valid@^2.12.4:
+ version "2.17.1"
+ resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471"
+ dependencies:
+ generate-function "^2.0.0"
+ generate-object-property "^1.1.0"
+ jsonpointer "^4.0.0"
+ xtend "^4.0.0"
+
is-number@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
@@ -2931,6 +3233,10 @@ is-primitive@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
+is-property@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
+
is-regex@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
@@ -2963,6 +3269,10 @@ is-wsl@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
+isarray@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -2996,33 +3306,33 @@ isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
-istanbul-api@^1.1.1:
- version "1.1.14"
- resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.1.14.tgz#25bc5701f7c680c0ffff913de46e3619a3a6e680"
+istanbul-api@^1.1.14:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.2.1.tgz#0c60a0515eb11c7d65c6b50bba2c6e999acd8620"
dependencies:
async "^2.1.4"
fileset "^2.0.2"
istanbul-lib-coverage "^1.1.1"
- istanbul-lib-hook "^1.0.7"
- istanbul-lib-instrument "^1.8.0"
- istanbul-lib-report "^1.1.1"
- istanbul-lib-source-maps "^1.2.1"
- istanbul-reports "^1.1.2"
+ istanbul-lib-hook "^1.1.0"
+ istanbul-lib-instrument "^1.9.1"
+ istanbul-lib-report "^1.1.2"
+ istanbul-lib-source-maps "^1.2.2"
+ istanbul-reports "^1.1.3"
js-yaml "^3.7.0"
mkdirp "^0.5.1"
once "^1.4.0"
-istanbul-lib-coverage@^1.0.1, istanbul-lib-coverage@^1.1.1:
+istanbul-lib-coverage@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da"
-istanbul-lib-hook@^1.0.7:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz#dd6607f03076578fe7d6f2a630cf143b49bacddc"
+istanbul-lib-hook@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz#8538d970372cb3716d53e55523dd54b557a8d89b"
dependencies:
append-transform "^0.4.0"
-istanbul-lib-instrument@^1.4.2, istanbul-lib-instrument@^1.7.5, istanbul-lib-instrument@^1.8.0:
+istanbul-lib-instrument@^1.7.5, istanbul-lib-instrument@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.8.0.tgz#66f6c9421cc9ec4704f76f2db084ba9078a2b532"
dependencies:
@@ -3034,16 +3344,28 @@ istanbul-lib-instrument@^1.4.2, istanbul-lib-instrument@^1.7.5, istanbul-lib-ins
istanbul-lib-coverage "^1.1.1"
semver "^5.3.0"
-istanbul-lib-report@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#f0e55f56655ffa34222080b7a0cd4760e1405fc9"
+istanbul-lib-instrument@^1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz#250b30b3531e5d3251299fdd64b0b2c9db6b558e"
+ dependencies:
+ babel-generator "^6.18.0"
+ babel-template "^6.16.0"
+ babel-traverse "^6.18.0"
+ babel-types "^6.18.0"
+ babylon "^6.18.0"
+ istanbul-lib-coverage "^1.1.1"
+ semver "^5.3.0"
+
+istanbul-lib-report@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.2.tgz#922be27c13b9511b979bd1587359f69798c1d425"
dependencies:
istanbul-lib-coverage "^1.1.1"
mkdirp "^0.5.1"
path-parse "^1.0.5"
supports-color "^3.1.2"
-istanbul-lib-source-maps@^1.1.0, istanbul-lib-source-maps@^1.2.1:
+istanbul-lib-source-maps@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz#a6fe1acba8ce08eebc638e572e294d267008aa0c"
dependencies:
@@ -3053,240 +3375,279 @@ istanbul-lib-source-maps@^1.1.0, istanbul-lib-source-maps@^1.2.1:
rimraf "^2.6.1"
source-map "^0.5.3"
-istanbul-reports@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.2.tgz#0fb2e3f6aa9922bd3ce45d05d8ab4d5e8e07bd4f"
+istanbul-lib-source-maps@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.2.tgz#750578602435f28a0c04ee6d7d9e0f2960e62c1c"
dependencies:
- handlebars "^4.0.3"
+ debug "^3.1.0"
+ istanbul-lib-coverage "^1.1.1"
+ mkdirp "^0.5.1"
+ rimraf "^2.6.1"
+ source-map "^0.5.3"
-javascript-natural-sort@0.7.1:
- version "0.7.1"
- resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59"
+istanbul-reports@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.3.tgz#3b9e1e8defb6d18b1d425da8e8b32c5a163f2d10"
+ dependencies:
+ handlebars "^4.0.3"
-jest-changed-files@^21.2.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-21.2.0.tgz#5dbeecad42f5d88b482334902ce1cba6d9798d29"
+jest-changed-files@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-22.0.5.tgz#ff944a1100172e9095869f4f5432e3fff09ab4ab"
dependencies:
throat "^4.0.0"
-jest-cli@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-21.2.1.tgz#9c528b6629d651911138d228bdb033c157ec8c00"
+jest-cli@^22.0.4:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-22.0.5.tgz#a8c7e8bf9371cb0997fa3da97e13e01da8a47593"
dependencies:
ansi-escapes "^3.0.0"
chalk "^2.0.1"
glob "^7.1.2"
graceful-fs "^4.1.11"
is-ci "^1.0.10"
- istanbul-api "^1.1.1"
- istanbul-lib-coverage "^1.0.1"
- istanbul-lib-instrument "^1.4.2"
- istanbul-lib-source-maps "^1.1.0"
- jest-changed-files "^21.2.0"
- jest-config "^21.2.1"
- jest-environment-jsdom "^21.2.1"
- jest-haste-map "^21.2.0"
- jest-message-util "^21.2.1"
- jest-regex-util "^21.2.0"
- jest-resolve-dependencies "^21.2.0"
- jest-runner "^21.2.1"
- jest-runtime "^21.2.1"
- jest-snapshot "^21.2.1"
- jest-util "^21.2.1"
+ istanbul-api "^1.1.14"
+ istanbul-lib-coverage "^1.1.1"
+ istanbul-lib-instrument "^1.8.0"
+ istanbul-lib-source-maps "^1.2.1"
+ jest-changed-files "^22.0.5"
+ jest-config "^22.0.5"
+ jest-environment-jsdom "^22.0.5"
+ jest-get-type "^22.0.3"
+ jest-haste-map "^22.0.3"
+ jest-message-util "^22.0.3"
+ jest-regex-util "^22.0.5"
+ jest-resolve-dependencies "^22.0.5"
+ jest-runner "^22.0.5"
+ jest-runtime "^22.0.5"
+ jest-snapshot "^22.0.5"
+ jest-util "^22.0.5"
+ jest-worker "^22.0.3"
micromatch "^2.3.11"
- node-notifier "^5.0.2"
- pify "^3.0.0"
+ node-notifier "^5.1.2"
+ realpath-native "^1.0.0"
+ rimraf "^2.5.4"
slash "^1.0.0"
string-length "^2.0.0"
strip-ansi "^4.0.0"
which "^1.2.12"
- worker-farm "^1.3.1"
- yargs "^9.0.0"
+ yargs "^10.0.3"
-jest-config@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-21.2.1.tgz#c7586c79ead0bcc1f38c401e55f964f13bf2a480"
+jest-config@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-22.0.5.tgz#86471137c5172f1fafdbe3af07f9d516873c8d11"
dependencies:
chalk "^2.0.1"
glob "^7.1.1"
- jest-environment-jsdom "^21.2.1"
- jest-environment-node "^21.2.1"
- jest-get-type "^21.2.0"
- jest-jasmine2 "^21.2.1"
- jest-regex-util "^21.2.0"
- jest-resolve "^21.2.0"
- jest-util "^21.2.1"
- jest-validate "^21.2.1"
- pretty-format "^21.2.1"
-
-jest-diff@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-21.2.1.tgz#46cccb6cab2d02ce98bc314011764bb95b065b4f"
+ jest-environment-jsdom "^22.0.5"
+ jest-environment-node "^22.0.5"
+ jest-get-type "^22.0.3"
+ jest-jasmine2 "^22.0.5"
+ jest-regex-util "^22.0.5"
+ jest-resolve "^22.0.4"
+ jest-util "^22.0.5"
+ jest-validate "^22.0.5"
+ pretty-format "^22.0.5"
+
+jest-context@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/jest-context/-/jest-context-2.1.0.tgz#8d92b636323ce0698f801b6282029feb987c9545"
+
+jest-diff@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-22.0.5.tgz#dbd7e7ff28601179a87777291c1020a3140d9ad4"
dependencies:
chalk "^2.0.1"
diff "^3.2.0"
- jest-get-type "^21.2.0"
- pretty-format "^21.2.1"
+ jest-get-type "^22.0.3"
+ pretty-format "^22.0.5"
-jest-docblock@^21.2.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414"
+jest-docblock@^22.0.3:
+ version "22.0.3"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-22.0.3.tgz#c33aa22682b9fc68a5373f5f82994428a2ded601"
+ dependencies:
+ detect-newline "^2.1.0"
+
+jest-environment-jsdom-global@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom-global/-/jest-environment-jsdom-global-1.0.2.tgz#b3449e016e0b13cb0779704e29a1377f927b38a3"
-jest-environment-jsdom@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-21.2.1.tgz#38d9980c8259b2a608ec232deee6289a60d9d5b4"
+jest-environment-jsdom@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-22.0.5.tgz#7b479452e387aef5b4bf8b9fe03e8be77493f5ea"
dependencies:
- jest-mock "^21.2.0"
- jest-util "^21.2.1"
- jsdom "^9.12.0"
+ jest-mock "^22.0.5"
+ jest-util "^22.0.5"
+ jsdom "^11.5.1"
-jest-environment-node@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-21.2.1.tgz#98c67df5663c7fbe20f6e792ac2272c740d3b8c8"
+jest-environment-node@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-22.0.5.tgz#3d77468c5ce763455a46f9469532e35a2f1d94d4"
dependencies:
- jest-mock "^21.2.0"
- jest-util "^21.2.1"
+ jest-mock "^22.0.5"
+ jest-util "^22.0.5"
-jest-get-type@^21.2.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.2.0.tgz#f6376ab9db4b60d81e39f30749c6c466f40d4a23"
+jest-get-type@^22.0.3:
+ version "22.0.3"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.0.3.tgz#fa894b677c0fcd55eff3fd8ee28c7be942e32d36"
-jest-haste-map@^21.2.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.2.0.tgz#1363f0a8bb4338f24f001806571eff7a4b2ff3d8"
+jest-haste-map@^22.0.3:
+ version "22.0.3"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-22.0.3.tgz#c9ecb5c871c5465d4bde4139e527fa0dc784aa2d"
dependencies:
fb-watchman "^2.0.0"
graceful-fs "^4.1.11"
- jest-docblock "^21.2.0"
+ jest-docblock "^22.0.3"
+ jest-worker "^22.0.3"
micromatch "^2.3.11"
sane "^2.0.0"
- worker-farm "^1.3.1"
-jest-jasmine2@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-21.2.1.tgz#9cc6fc108accfa97efebce10c4308548a4ea7592"
+jest-jasmine2@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-22.0.5.tgz#daf1c91f6ecc3d1e04bc9e52eef11bd04adfeff3"
dependencies:
+ callsites "^2.0.0"
chalk "^2.0.1"
- expect "^21.2.1"
+ co "^4.6.0"
+ expect "^22.0.5"
graceful-fs "^4.1.11"
- jest-diff "^21.2.1"
- jest-matcher-utils "^21.2.1"
- jest-message-util "^21.2.1"
- jest-snapshot "^21.2.1"
- p-cancelable "^0.3.0"
+ is-generator-fn "^1.0.0"
+ jest-diff "^22.0.5"
+ jest-matcher-utils "^22.0.5"
+ jest-message-util "^22.0.3"
+ jest-snapshot "^22.0.5"
+ source-map-support "^0.5.0"
+
+jest-leak-detector@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-22.0.5.tgz#277f792b6a71fa3a412ddfbd5d14aa190c29bea5"
+ dependencies:
+ pretty-format "^22.0.5"
-jest-matcher-utils@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-21.2.1.tgz#72c826eaba41a093ac2b4565f865eb8475de0f64"
+jest-matcher-utils@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-22.0.5.tgz#f65628364b345703e6042d27fd9cf158f6eb23d3"
dependencies:
chalk "^2.0.1"
- jest-get-type "^21.2.0"
- pretty-format "^21.2.1"
+ jest-get-type "^22.0.3"
+ pretty-format "^22.0.5"
-jest-message-util@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-21.2.1.tgz#bfe5d4692c84c827d1dcf41823795558f0a1acbe"
+jest-message-util@^22.0.3:
+ version "22.0.3"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-22.0.3.tgz#bf674b2762ef2dd53facf2136423fcca264976df"
dependencies:
+ "@babel/code-frame" "^7.0.0-beta.35"
chalk "^2.0.1"
micromatch "^2.3.11"
slash "^1.0.0"
+ stack-utils "^1.0.1"
-jest-mock@^21.2.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-21.2.0.tgz#7eb0770e7317968165f61ea2a7281131534b3c0f"
+jest-mock@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-22.0.5.tgz#c05b87c1ecc98de5b1eb88d4fcd01ee512a6963a"
-jest-regex-util@^21.2.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-21.2.0.tgz#1b1e33e63143babc3e0f2e6c9b5ba1eb34b2d530"
+jest-regex-util@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-22.0.5.tgz#e05eef614d7211d6320ac443f2996064890aa224"
-jest-resolve-dependencies@^21.2.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-21.2.0.tgz#9e231e371e1a736a1ad4e4b9a843bc72bfe03d09"
+jest-resolve-dependencies@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-22.0.5.tgz#d25e2e97ffbb3002c4a2f215520e0e44718b6cb0"
dependencies:
- jest-regex-util "^21.2.0"
+ jest-regex-util "^22.0.5"
-jest-resolve@^21.2.0:
- version "21.2.0"
- resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-21.2.0.tgz#068913ad2ba6a20218e5fd32471f3874005de3a6"
+jest-resolve@^22.0.4:
+ version "22.0.4"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-22.0.4.tgz#a6e47f55e9388c7341b5e9732aedc6fe30906121"
dependencies:
browser-resolve "^1.11.2"
chalk "^2.0.1"
- is-builtin-module "^1.0.0"
-jest-runner@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-21.2.1.tgz#194732e3e518bfb3d7cbfc0fd5871246c7e1a467"
- dependencies:
- jest-config "^21.2.1"
- jest-docblock "^21.2.0"
- jest-haste-map "^21.2.0"
- jest-jasmine2 "^21.2.1"
- jest-message-util "^21.2.1"
- jest-runtime "^21.2.1"
- jest-util "^21.2.1"
- pify "^3.0.0"
+jest-runner@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-22.0.5.tgz#69c352828aa8d5ac7ea62b9ac2d8a36cf4a63c53"
+ dependencies:
+ jest-config "^22.0.5"
+ jest-docblock "^22.0.3"
+ jest-haste-map "^22.0.3"
+ jest-jasmine2 "^22.0.5"
+ jest-leak-detector "^22.0.5"
+ jest-message-util "^22.0.3"
+ jest-runtime "^22.0.5"
+ jest-util "^22.0.5"
+ jest-worker "^22.0.3"
throat "^4.0.0"
- worker-farm "^1.3.1"
-jest-runtime@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-21.2.1.tgz#99dce15309c670442eee2ebe1ff53a3cbdbbb73e"
+jest-runtime@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-22.0.5.tgz#e155adb25f4a5f099987dad502acd597790e5096"
dependencies:
babel-core "^6.0.0"
- babel-jest "^21.2.0"
- babel-plugin-istanbul "^4.0.0"
+ babel-jest "^22.0.4"
+ babel-plugin-istanbul "^4.1.5"
chalk "^2.0.1"
convert-source-map "^1.4.0"
graceful-fs "^4.1.11"
- jest-config "^21.2.1"
- jest-haste-map "^21.2.0"
- jest-regex-util "^21.2.0"
- jest-resolve "^21.2.0"
- jest-util "^21.2.1"
+ jest-config "^22.0.5"
+ jest-haste-map "^22.0.3"
+ jest-regex-util "^22.0.5"
+ jest-resolve "^22.0.4"
+ jest-util "^22.0.5"
json-stable-stringify "^1.0.1"
micromatch "^2.3.11"
+ realpath-native "^1.0.0"
slash "^1.0.0"
strip-bom "3.0.0"
write-file-atomic "^2.1.0"
- yargs "^9.0.0"
+ yargs "^10.0.3"
-jest-snapshot@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-21.2.1.tgz#29e49f16202416e47343e757e5eff948c07fd7b0"
+jest-set@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/jest-set/-/jest-set-2.0.0.tgz#977c2120120e83086e86519c1a84c2a1c800f419"
+
+jest-snapshot@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-22.0.5.tgz#ab52cc5c65c9caacdbc0c6369dc653ffbcace5ed"
dependencies:
chalk "^2.0.1"
- jest-diff "^21.2.1"
- jest-matcher-utils "^21.2.1"
+ jest-diff "^22.0.5"
+ jest-matcher-utils "^22.0.5"
mkdirp "^0.5.1"
natural-compare "^1.4.0"
- pretty-format "^21.2.1"
+ pretty-format "^22.0.5"
-jest-util@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-21.2.1.tgz#a274b2f726b0897494d694a6c3d6a61ab819bb78"
+jest-util@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-22.0.5.tgz#d124387b714bfcf3cd46a5b1aa00cc5491d26716"
dependencies:
callsites "^2.0.0"
chalk "^2.0.1"
graceful-fs "^4.1.11"
- jest-message-util "^21.2.1"
- jest-mock "^21.2.0"
- jest-validate "^21.2.1"
+ is-ci "^1.0.10"
+ jest-message-util "^22.0.3"
+ jest-validate "^22.0.5"
mkdirp "^0.5.1"
-jest-validate@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.2.1.tgz#cc0cbca653cd54937ba4f2a111796774530dd3c7"
+jest-validate@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-22.0.5.tgz#fbc6b9c0d2f583f73070f079e0c53be1c88adba5"
dependencies:
chalk "^2.0.1"
- jest-get-type "^21.2.0"
+ jest-get-type "^22.0.3"
leven "^2.1.0"
- pretty-format "^21.2.1"
+ pretty-format "^22.0.5"
+
+jest-worker@^22.0.3:
+ version "22.0.3"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-22.0.3.tgz#30433faca67814a8f80559f75ab2ceaa61332fd2"
+ dependencies:
+ merge-stream "^1.0.1"
-jest@21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/jest/-/jest-21.2.1.tgz#c964e0b47383768a1438e3ccf3c3d470327604e1"
+jest@22.0.4:
+ version "22.0.4"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-22.0.4.tgz#d3cf560ece6b825b115dce80b9826ceb40f87961"
dependencies:
- jest-cli "^21.2.1"
+ jest-cli "^22.0.4"
jquery-mousewheel@~3.1.13:
version "3.1.13"
@@ -3304,13 +3665,20 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
-js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.9.1:
+js-yaml@^3.10.0, js-yaml@^3.4.3, js-yaml@^3.7.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc"
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
+js-yaml@~3.5.2:
+ version "3.5.5"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.5.5.tgz#0377c38017cabc7322b0d1fbcd25a491641f2fbe"
+ dependencies:
+ argparse "^1.0.2"
+ esprima "^2.6.0"
+
js-yaml@~3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
@@ -3322,28 +3690,33 @@ jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
-jsdom@^9.12.0:
- version "9.12.0"
- resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.12.0.tgz#e8c546fffcb06c00d4833ca84410fed7f8a097d4"
+jsdom@^11.5.1:
+ version "11.5.1"
+ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.5.1.tgz#5df753b8d0bca20142ce21f4f6c039f99a992929"
dependencies:
abab "^1.0.3"
- acorn "^4.0.4"
- acorn-globals "^3.1.0"
+ acorn "^5.1.2"
+ acorn-globals "^4.0.0"
array-equal "^1.0.0"
+ browser-process-hrtime "^0.1.2"
content-type-parser "^1.0.1"
cssom ">= 0.3.2 < 0.4.0"
cssstyle ">= 0.2.37 < 0.3.0"
- escodegen "^1.6.1"
+ domexception "^1.0.0"
+ escodegen "^1.9.0"
html-encoding-sniffer "^1.0.1"
- nwmatcher ">= 1.3.9 < 2.0.0"
- parse5 "^1.5.1"
- request "^2.79.0"
+ left-pad "^1.2.0"
+ nwmatcher "^1.4.3"
+ parse5 "^3.0.2"
+ pn "^1.0.0"
+ request "^2.83.0"
+ request-promise-native "^1.0.3"
sax "^1.2.1"
symbol-tree "^3.2.1"
- tough-cookie "^2.3.2"
- webidl-conversions "^4.0.0"
+ tough-cookie "^2.3.3"
+ webidl-conversions "^4.0.2"
whatwg-encoding "^1.0.1"
- whatwg-url "^4.3.0"
+ whatwg-url "^6.3.0"
xml-name-validator "^2.0.1"
jsesc@^1.3.0:
@@ -3394,6 +3767,10 @@ jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
+jsonpointer@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
+
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
@@ -3403,6 +3780,14 @@ jsprim@^1.2.2:
json-schema "0.2.3"
verror "1.10.0"
+just-extend@^1.1.26:
+ version "1.1.27"
+ resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905"
+
+killable@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.0.tgz#da8b84bd47de5395878f95d64d02f2449fe05e6b"
+
kind-of@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-2.0.1.tgz#018ec7a4ce7e3a86cb9141be519d24c8faa981b5"
@@ -3441,6 +3826,10 @@ lcid@^1.0.0:
dependencies:
invert-kv "^1.0.0"
+left-pad@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.2.0.tgz#d30a73c6b8201d8f7d8e7956ba9616087a68e0ee"
+
leven@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
@@ -3452,6 +3841,10 @@ levn@~0.3.0:
prelude-ls "~1.1.2"
type-check "~0.3.2"
+livereload-js@^2.2.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.2.2.tgz#6c87257e648ab475bc24ea257457edcc1f8d0bc2"
+
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -3475,7 +3868,7 @@ loader-runner@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
-loader-utils@^1.0.0, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0:
+loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
dependencies:
@@ -3490,58 +3883,19 @@ locate-path@^2.0.0:
p-locate "^2.0.0"
path-exists "^3.0.0"
-lodash-es@^4.2.1:
+lodash-es@^4.2.0, lodash-es@^4.2.1:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7"
-lodash._baseassign@^3.0.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
- dependencies:
- lodash._basecopy "^3.0.0"
- lodash.keys "^3.0.0"
-
-lodash._basecopy@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
-
lodash._basefor@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash._basefor/-/lodash._basefor-3.0.3.tgz#7550b4e9218ef09fad24343b612021c79b4c20c2"
-lodash._bindcallback@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
-
-lodash._createassigner@^3.0.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11"
- dependencies:
- lodash._bindcallback "^3.0.0"
- lodash._isiterateecall "^3.0.0"
- lodash.restparam "^3.0.0"
-
-lodash._getnative@^3.0.0:
- version "3.9.1"
- resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
-
-lodash._isiterateecall@^3.0.0:
- version "3.0.9"
- resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
-
lodash._reinterpolate@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
-lodash.assign@^3.0.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa"
- dependencies:
- lodash._baseassign "^3.0.0"
- lodash._createassigner "^3.0.0"
- lodash.keys "^3.0.0"
-
-lodash.assign@^4.0.1, lodash.assign@^4.2.0:
+lodash.assign@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
@@ -3553,16 +3907,9 @@ lodash.clonedeep@^4.3.2:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
-lodash.defaults@^3.1.2:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-3.1.2.tgz#c7308b18dbf8bc9372d701a73493c61192bd2e2c"
- dependencies:
- lodash.assign "^3.0.0"
- lodash.restparam "^3.0.0"
-
-lodash.defaults@^4.0.0, lodash.defaults@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
+lodash.get@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
lodash.isarguments@^3.0.0:
version "3.1.0"
@@ -3580,14 +3927,6 @@ lodash.isplainobject@^3.2.0:
lodash.isarguments "^3.0.0"
lodash.keysin "^3.0.0"
-lodash.keys@^3.0.0:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
- dependencies:
- lodash._getnative "^3.0.0"
- lodash.isarguments "^3.0.0"
- lodash.isarray "^3.0.0"
-
lodash.keysin@^3.0.0:
version "3.0.8"
resolved "https://registry.yarnpkg.com/lodash.keysin/-/lodash.keysin-3.0.8.tgz#22c4493ebbedb1427962a54b445b2c8a767fb47f"
@@ -3603,9 +3942,9 @@ lodash.mergewith@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55"
-lodash.restparam@^3.0.0:
- version "3.6.1"
- resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
+lodash.sortby@^4.7.0:
+ version "4.7.0"
+ resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
lodash.tail@^4.1.1:
version "4.1.1"
@@ -3628,23 +3967,35 @@ lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
-lodash@4.17.4, "lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@~4.17.4:
+lodash@4.17.4, "lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@~4.17.4:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+lodash@^3.10.1, lodash@~3.10.1:
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
+
+lodash@~4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.3.0.tgz#efd9c4a6ec53f3b05412429915c3e4824e4d25a4"
+
loglevel@^1.4.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.5.1.tgz#189078c94ab9053ee215a0acdbf24244ea0f6502"
-lolex@1.3.2:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31"
+lolex@^1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6"
+
+lolex@^2.2.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.3.1.tgz#3d2319894471ea0950ef64692ead2a5318cff362"
longest@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
-loose-envify@^1.0.0, loose-envify@^1.1.0:
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
dependencies:
@@ -3657,7 +4008,7 @@ loud-rejection@^1.0.0:
currently-unhandled "^0.4.1"
signal-exit "^3.0.0"
-lru-cache@^4.0.1:
+lru-cache@^4.0.1, lru-cache@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
dependencies:
@@ -3688,18 +4039,6 @@ math-expression-evaluator@^1.2.14:
version "1.2.17"
resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac"
-mathjs@^3.11.5:
- version "3.16.4"
- resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-3.16.4.tgz#6223a5e423ff79a8f5da0b4f2991c78044bdf3de"
- dependencies:
- complex.js "2.0.4"
- decimal.js "7.2.3"
- fraction.js "4.0.2"
- javascript-natural-sort "0.7.1"
- seed-random "2.2.0"
- tiny-emitter "2.0.0"
- typed-function "0.10.5"
-
md5.js@^1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d"
@@ -3743,6 +4082,12 @@ merge-descriptors@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+merge-stream@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1"
+ dependencies:
+ readable-stream "^2.0.1"
+
merge@^1.1.3:
version "1.2.0"
resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da"
@@ -3802,7 +4147,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
-minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2:
+"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.0, minimatch@~3.0.2:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
@@ -3812,10 +4157,6 @@ minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
-minimist@1.1.x:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
-
minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
@@ -3824,6 +4165,21 @@ minimist@~0.0.1:
version "0.0.10"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
+mississippi@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-1.3.0.tgz#d201583eb12327e3c5c1642a404a9cacf94e34f5"
+ dependencies:
+ concat-stream "^1.5.0"
+ duplexify "^3.4.2"
+ end-of-stream "^1.1.0"
+ flush-write-stream "^1.0.0"
+ from2 "^2.1.0"
+ parallel-transform "^1.1.0"
+ pump "^1.0.0"
+ pumpify "^1.3.3"
+ stream-each "^1.1.0"
+ through2 "^2.0.0"
+
mixin-object@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e"
@@ -3837,6 +4193,21 @@ mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkd
dependencies:
minimist "0.0.8"
+move-concurrently@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
+ dependencies:
+ aproba "^1.1.1"
+ copy-concurrently "^1.0.0"
+ fs-write-stream-atomic "^1.0.8"
+ mkdirp "^0.5.1"
+ rimraf "^2.5.4"
+ run-queue "^1.0.3"
+
+ms@0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
+
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -3864,6 +4235,16 @@ negotiator@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
+nise@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/nise/-/nise-1.2.0.tgz#079d6cadbbcb12ba30e38f1c999f36ad4d6baa53"
+ dependencies:
+ formatio "^1.2.0"
+ just-extend "^1.1.26"
+ lolex "^1.6.0"
+ path-to-regexp "^1.7.0"
+ text-encoding "^0.6.4"
+
node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
@@ -3925,7 +4306,7 @@ node-libs-browser@^2.0.0:
util "^0.10.3"
vm-browserify "0.0.4"
-node-notifier@^5.0.2:
+node-notifier@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.1.2.tgz#2fa9e12605fa10009d44549d6fcd8a63dde0e4ff"
dependencies:
@@ -3949,9 +4330,9 @@ node-pre-gyp@^0.6.36:
tar "^2.2.1"
tar-pack "^3.4.0"
-node-sass@^4.5.3:
- version "4.5.3"
- resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.5.3.tgz#d09c9d1179641239d1b97ffc6231fdcec53e1568"
+node-sass@^4.7.2:
+ version "4.7.2"
+ resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.2.tgz#9366778ba1469eb01438a9e8592f4262bcb6794e"
dependencies:
async-foreach "^0.1.3"
chalk "^1.1.1"
@@ -3968,11 +4349,12 @@ node-sass@^4.5.3:
nan "^2.3.2"
node-gyp "^3.3.1"
npmlog "^4.0.0"
- request "^2.79.0"
- sass-graph "^2.1.1"
+ request "~2.79.0"
+ sass-graph "^2.2.4"
stdout-stream "^1.4.0"
+ "true-case-path" "^1.0.2"
-"nopt@2 || 3":
+"nopt@2 || 3", nopt@~3.0.6:
version "3.0.6"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
dependencies:
@@ -4036,7 +4418,7 @@ number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
-"nwmatcher@>= 1.3.9 < 2.0.0":
+nwmatcher@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.3.tgz#64348e3b3d80f035b40ac11563d278f8b72db89c"
@@ -4044,7 +4426,7 @@ oauth-sign@~0.8.1, oauth-sign@~0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
-object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@@ -4052,9 +4434,12 @@ object-keys@^1.0.8:
version "1.0.11"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
-object-path@^0.9.2:
- version "0.9.2"
- resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.9.2.tgz#0fd9a74fc5fad1ae3968b586bda5c632bd6c05a5"
+object.getownpropertydescriptors@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
+ dependencies:
+ define-properties "^1.1.2"
+ es-abstract "^1.5.1"
object.omit@^2.0.0:
version "2.0.1"
@@ -4077,7 +4462,7 @@ on-headers@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
-once@^1.3.0, once@^1.3.3, once@^1.4.0:
+once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
dependencies:
@@ -4150,10 +4535,6 @@ osenv@0, osenv@^0.1.4:
os-homedir "^1.0.0"
os-tmpdir "^1.0.0"
-p-cancelable@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa"
-
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
@@ -4176,6 +4557,14 @@ pako@~0.2.0:
version "0.2.9"
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
+parallel-transform@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06"
+ dependencies:
+ cyclist "~0.2.2"
+ inherits "^2.0.3"
+ readable-stream "^2.1.5"
+
parse-asn1@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712"
@@ -4201,11 +4590,13 @@ parse-json@^2.2.0:
dependencies:
error-ex "^1.2.0"
-parse5@^1.5.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94"
+parse5@^3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
+ dependencies:
+ "@types/node" "*"
-parseurl@~1.3.2:
+parseurl@~1.3.0, parseurl@~1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
@@ -4227,7 +4618,7 @@ path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
-path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
+path-is-absolute@^1.0.0, path-is-absolute@^1.0.1, path-is-absolute@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@@ -4247,6 +4638,12 @@ path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+path-to-regexp@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
+ dependencies:
+ isarray "0.0.1"
+
path-type@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@@ -4318,6 +4715,10 @@ pleeease-filters@^4.0.0:
onecolor "^3.0.4"
postcss "^6.0.1"
+pn@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
+
portfinder@^1.0.9:
version "1.0.13"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
@@ -4553,6 +4954,15 @@ postcss-image-set-polyfill@^0.3.5:
postcss "^6.0.1"
postcss-media-query-parser "^0.2.3"
+postcss-import@^11.0.0:
+ version "11.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-11.0.0.tgz#a962e2df82d3bc5a6da6a386841747204f41ef5b"
+ dependencies:
+ postcss "^6.0.1"
+ postcss-value-parser "^3.2.3"
+ read-cache "^1.0.0"
+ resolve "^1.1.7"
+
postcss-initial@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-2.0.0.tgz#72715f7336e0bb79351d99ee65c4a253a8441ba4"
@@ -4583,9 +4993,9 @@ postcss-load-plugins@^2.3.0:
cosmiconfig "^2.1.1"
object-assign "^4.1.0"
-postcss-loader@^2.0.6:
- version "2.0.7"
- resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.0.7.tgz#4d2da1489cee0a14f72c0d9440c9ee7eded34345"
+postcss-loader@^2.0.9:
+ version "2.0.10"
+ resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-2.0.10.tgz#090db0540140bd56a7a7f717c41bc29aeef4c674"
dependencies:
loader-utils "^1.1.0"
postcss "^6.0.0"
@@ -4663,27 +5073,27 @@ postcss-minify-selectors@^2.0.4:
postcss "^5.0.14"
postcss-selector-parser "^2.0.0"
-postcss-modules-extract-imports@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz#66140ecece38ef06bf0d3e355d69bf59d141ea85"
+postcss-modules-extract-imports@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb"
dependencies:
postcss "^6.0.1"
-postcss-modules-local-by-default@^1.0.1:
+postcss-modules-local-by-default@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069"
dependencies:
css-selector-tokenizer "^0.7.0"
postcss "^6.0.1"
-postcss-modules-scope@^1.0.0:
+postcss-modules-scope@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90"
dependencies:
css-selector-tokenizer "^0.7.0"
postcss "^6.0.1"
-postcss-modules-values@^1.1.0:
+postcss-modules-values@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20"
dependencies:
@@ -4758,20 +5168,6 @@ postcss-replace-overflow-wrap@^2.0.0:
dependencies:
postcss "^6.0.1"
-postcss-sass@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.1.0.tgz#0d2a655b5d241ec8f419bb3da38de5ca11746ddb"
- dependencies:
- gonzales-pe "^4.0.3"
- mathjs "^3.11.5"
- postcss "^5.2.6"
-
-postcss-scss@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-1.0.2.tgz#ff45cf3354b879ee89a4eb68680f46ac9bb14f94"
- dependencies:
- postcss "^6.0.3"
-
postcss-selector-matches@^3.0.0, postcss-selector-matches@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-3.0.1.tgz#e5634011e13950881861bbdd58c2d0111ffc96ab"
@@ -4794,22 +5190,6 @@ postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2, postcss-selector
indexes-of "^1.0.1"
uniq "^1.0.1"
-postcss-smart-import@^0.7.5:
- version "0.7.5"
- resolved "https://registry.yarnpkg.com/postcss-smart-import/-/postcss-smart-import-0.7.5.tgz#df9a9c6dd60d916e5e0670d1c57d03af5d3dcc31"
- dependencies:
- babel-runtime "^6.23.0"
- lodash "^4.17.4"
- object-assign "^4.1.1"
- postcss "^6.0.6"
- postcss-sass "^0.1.0"
- postcss-scss "^1.0.2"
- postcss-value-parser "^3.3.0"
- promise-each "^2.2.0"
- read-cache "^1.0.0"
- resolve "^1.3.3"
- sugarss "^1.0.0"
-
postcss-svgo@^2.1.1:
version "2.1.6"
resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d"
@@ -4839,7 +5219,7 @@ postcss-zindex@^2.0.1:
postcss "^5.0.4"
uniqs "^2.0.0"
-postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16, postcss@^5.2.6:
+postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.16:
version "5.2.18"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5"
dependencies:
@@ -4848,7 +5228,7 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0
source-map "^0.5.6"
supports-color "^3.2.3"
-postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.13, postcss@^6.0.3, postcss@^6.0.5, postcss@^6.0.6:
+postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.13, postcss@^6.0.5, postcss@^6.0.6:
version "6.0.13"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.13.tgz#b9ecab4ee00c89db3ec931145bd9590bbf3f125f"
dependencies:
@@ -4868,9 +5248,9 @@ preserve@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
-pretty-format@^21.2.1:
- version "21.2.1"
- resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.2.1.tgz#ae5407f3cf21066cd011aa1ba5fce7b6a2eddb36"
+pretty-format@^22.0.5:
+ version "22.0.5"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-22.0.5.tgz#8bad3f12b2b84c76fc57a976bde6770eb4043c69"
dependencies:
ansi-regex "^3.0.0"
ansi-styles "^3.2.0"
@@ -4887,15 +5267,13 @@ process@^0.11.0:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
-promise-each@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/promise-each/-/promise-each-2.2.0.tgz#3353174eff2694481037e04e01f77aa0fb6d1b60"
- dependencies:
- any-promise "^0.1.0"
+promise-inflight@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
-promise-polyfill@6.0.2:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-6.0.2.tgz#d9c86d3dc4dc2df9016e88946defd69b49b41162"
+promise-polyfill@7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-7.0.0.tgz#c665b6da1f97e21c3f2f7aa0543c90209127cb15"
promise@^7.1.1:
version "7.3.1"
@@ -4903,6 +5281,14 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
+prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0:
+ version "15.6.0"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856"
+ dependencies:
+ fbjs "^0.8.16"
+ loose-envify "^1.3.1"
+ object-assign "^4.1.1"
+
proxy-addr@~2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec"
@@ -4928,6 +5314,21 @@ public-encrypt@^4.0.0:
parse-asn1 "^5.0.0"
randombytes "^2.0.1"
+pump@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954"
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+pumpify@^1.3.3:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.3.5.tgz#1b671c619940abcaeac0ad0e3a3c164be760993b"
+ dependencies:
+ duplexify "^3.1.2"
+ inherits "^2.0.1"
+ pump "^1.0.0"
+
punycode@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
@@ -4936,14 +5337,30 @@ punycode@^1.2.4, punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+punycode@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d"
+
q@^1.1.2:
version "1.5.0"
resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1"
+qs@5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-5.2.0.tgz#a9f31142af468cb72b25b30136ba2456834916be"
+
qs@6.5.1, qs@~6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
+qs@~5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-5.1.0.tgz#4d932e5c7ea411cca76a312d39a606200fd50cd9"
+
+qs@~6.3.0:
+ version "6.3.2"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c"
+
qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
@@ -4971,13 +5388,6 @@ querystringify@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb"
-rails-erb-loader@^5.2.1:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/rails-erb-loader/-/rails-erb-loader-5.2.1.tgz#399b7781b88c129bc621a8256329ed2f855398e9"
- dependencies:
- loader-utils "^1.1.0"
- lodash.defaults "^4.2.0"
-
randomatic@^1.1.3:
version "1.1.7"
resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c"
@@ -5004,6 +5414,14 @@ raw-body@2.3.2:
iconv-lite "0.4.19"
unpipe "1.0.0"
+raw-body@~2.1.5:
+ version "2.1.7"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.1.7.tgz#adfeace2e4fb3098058014d08c072dcc59758774"
+ dependencies:
+ bytes "2.4.0"
+ iconv-lite "0.4.13"
+ unpipe "1.0.0"
+
rc@^1.1.7:
version "1.2.1"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95"
@@ -5013,43 +5431,54 @@ rc@^1.1.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
-react-addons-test-utils@15.3.2:
- version "15.3.2"
- resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.3.2.tgz#c09a44f583425a4a9c1b38444d7a6c3e6f0f41f6"
+react-addons-test-utils@15.6.2:
+ version "15.6.2"
+ resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz#c12b6efdc2247c10da7b8770d185080a7b047156"
-react-dom@15.3.2:
- version "15.3.2"
- resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.3.2.tgz#c46b0aa5380d7b838e7a59c4a7beff2ed315531f"
+react-dom@16.2.0:
+ version "16.2.0"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044"
+ dependencies:
+ fbjs "^0.8.16"
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+ prop-types "^15.6.0"
-react-redux@4.4.5:
- version "4.4.5"
- resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-4.4.5.tgz#f509a2981be2252d10c629ef7c559347a4aec457"
+react-redux@5.0.6:
+ version "5.0.6"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.6.tgz#23ed3a4f986359d68b5212eaaa681e60d6574946"
dependencies:
- hoist-non-react-statics "^1.0.3"
+ hoist-non-react-statics "^2.2.1"
invariant "^2.0.0"
lodash "^4.2.0"
+ lodash-es "^4.2.0"
loose-envify "^1.1.0"
+ prop-types "^15.5.10"
-react-select2-wrapper@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/react-select2-wrapper/-/react-select2-wrapper-1.0.3.tgz#67f47ff350abd7d339632ae7cf3eb929604c979a"
+react-select2-wrapper@^1.0.4-beta5:
+ version "1.0.4-beta5"
+ resolved "https://registry.yarnpkg.com/react-select2-wrapper/-/react-select2-wrapper-1.0.4-beta5.tgz#50714f618a9cef379c54f6eddf8bd82d4bba4daa"
dependencies:
+ prop-types "^15.5.8"
select2 "^4.0.0"
shallow-equal-fuzzy "^0.0.2"
-react-select2@4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/react-select2/-/react-select2-4.0.3.tgz#89cc79e7eafcdff1a2f31f096e8deb483b7503ea"
+react-test-renderer@^16.2.0:
+ version "16.2.0"
+ resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.2.0.tgz#bddf259a6b8fcd8555f012afc8eacc238872a211"
dependencies:
- react-select2-wrapper "^1.0.3"
+ fbjs "^0.8.16"
+ object-assign "^4.1.1"
+ prop-types "^15.6.0"
-react@15.3.2:
- version "15.3.2"
- resolved "https://registry.yarnpkg.com/react/-/react-15.3.2.tgz#a7bccd2fee8af126b0317e222c28d1d54528d09e"
+react@16.2.0:
+ version "16.2.0"
+ resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba"
dependencies:
- fbjs "^0.8.4"
+ fbjs "^0.8.16"
loose-envify "^1.1.0"
- object-assign "^4.1.0"
+ object-assign "^4.1.1"
+ prop-types "^15.6.0"
read-cache@^1.0.0:
version "1.0.0"
@@ -5087,7 +5516,7 @@ read-pkg@^2.0.0:
normalize-package-data "^2.3.2"
path-type "^2.0.0"
-readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.6, readable-stream@^2.2.9:
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.9:
version "2.3.3"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
dependencies:
@@ -5108,6 +5537,12 @@ readdirp@^2.0.0:
readable-stream "^2.0.2"
set-immediate-shim "^1.0.1"
+realpath-native@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.0.tgz#7885721a83b43bd5327609f0ddecb2482305fdf0"
+ dependencies:
+ util.promisify "^1.0.0"
+
redent@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
@@ -5136,11 +5571,11 @@ reduce-function-call@^1.0.1, reduce-function-call@^1.0.2:
dependencies:
balanced-match "^0.4.2"
-redux-logger@2.7.4:
- version "2.7.4"
- resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-2.7.4.tgz#891e5d29e7f111d08b5781a237b9965b5858c7f8"
+redux-logger@3.0.6:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf"
dependencies:
- deep-diff "0.3.4"
+ deep-diff "^0.3.5"
redux-promise@0.5.3:
version "0.5.3"
@@ -5148,18 +5583,18 @@ redux-promise@0.5.3:
dependencies:
flux-standard-action "^0.6.1"
-redux-thunk@2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.1.0.tgz#c724bfee75dbe352da2e3ba9bc14302badd89a98"
+redux-thunk@2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5"
-redux@3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/redux/-/redux-3.6.0.tgz#887c2b3d0b9bd86eca2be70571c27654c19e188d"
+redux@3.7.2:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b"
dependencies:
lodash "^4.2.1"
lodash-es "^4.2.1"
loose-envify "^1.1.0"
- symbol-observable "^1.0.2"
+ symbol-observable "^1.0.3"
regenerate@^1.2.1:
version "1.3.3"
@@ -5173,10 +5608,6 @@ regenerator-runtime@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1"
-regenerator-runtime@^0.9.5:
- version "0.9.6"
- resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz#d33eb95d0d2001a4be39659707c51b0cb71ce029"
-
regenerator-transform@^0.10.0:
version "0.10.1"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
@@ -5191,10 +5622,6 @@ regex-cache@^0.4.2:
dependencies:
is-equal-shallow "^0.1.3"
-regex-parser@^2.2.1:
- version "2.2.8"
- resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.8.tgz#da4c0cda5a828559094168930f455f532b6ffbac"
-
regexpu-core@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b"
@@ -5239,7 +5666,21 @@ repeating@^2.0.0:
dependencies:
is-finite "^1.0.0"
-request@2, request@^2.79.0:
+request-promise-core@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6"
+ dependencies:
+ lodash "^4.13.1"
+
+request-promise-native@^1.0.3:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5"
+ dependencies:
+ request-promise-core "1.1.1"
+ stealthy-require "^1.1.0"
+ tough-cookie ">=2.3.3"
+
+request@2, request@^2.83.0:
version "2.83.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356"
dependencies:
@@ -5293,6 +5734,31 @@ request@2.81.0:
tunnel-agent "^0.6.0"
uuid "^3.0.0"
+request@~2.79.0:
+ version "2.79.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
+ dependencies:
+ aws-sign2 "~0.6.0"
+ aws4 "^1.2.1"
+ caseless "~0.11.0"
+ combined-stream "~1.0.5"
+ extend "~3.0.0"
+ forever-agent "~0.6.1"
+ form-data "~2.1.1"
+ har-validator "~2.0.6"
+ hawk "~3.1.3"
+ http-signature "~1.1.0"
+ is-typedarray "~1.0.0"
+ isstream "~0.1.2"
+ json-stringify-safe "~5.0.1"
+ mime-types "~2.1.7"
+ oauth-sign "~0.8.1"
+ qs "~6.3.0"
+ stringstream "~0.0.4"
+ tough-cookie "~2.3.0"
+ tunnel-agent "~0.4.1"
+ uuid "^3.0.0"
+
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@@ -5309,45 +5775,26 @@ requires-port@1.0.x, requires-port@1.x.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
-resolve-url-loader@^2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-2.1.1.tgz#5354e87381aae348371e555172c50816708e6c1c"
- dependencies:
- adjust-sourcemap-loader "^1.1.0"
- camelcase "^4.0.0"
- convert-source-map "^1.1.1"
- loader-utils "^1.0.0"
- lodash.defaults "^4.0.0"
- rework "^1.0.1"
- rework-visit "^1.0.0"
- source-map "^0.5.6"
- urix "^0.1.0"
+resolve-cwd@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
+ dependencies:
+ resolve-from "^3.0.0"
-resolve-url@~0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
+resolve-from@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
-resolve@1.1.7:
+resolve@1.1.7, resolve@~1.1.0:
version "1.1.7"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
-resolve@^1.3.3:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86"
+resolve@^1.1.7:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
dependencies:
path-parse "^1.0.5"
-rework-visit@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/rework-visit/-/rework-visit-1.0.0.tgz#9945b2803f219e2f7aca00adb8bc9f640f842c9a"
-
-rework@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/rework/-/rework-1.0.1.tgz#30806a841342b54510aa4110850cd48534144aa7"
- dependencies:
- convert-source-map "^0.3.3"
- css "^2.0.0"
-
rgb-hex@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/rgb-hex/-/rgb-hex-2.1.0.tgz#c773c5fe2268a25578d92539a82a7a5ce53beda6"
@@ -5362,12 +5809,16 @@ right-align@^0.1.1:
dependencies:
align-text "^0.1.1"
-rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1:
+rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
dependencies:
glob "^7.0.5"
+rimraf@~2.2.8:
+ version "2.2.8"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582"
+
ripemd160@^2.0.0, ripemd160@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7"
@@ -5375,17 +5826,19 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^2.0.0"
inherits "^2.0.1"
+run-queue@^1.0.0, run-queue@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
+ dependencies:
+ aproba "^1.1.1"
+
safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
-samsam@1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567"
-
-samsam@~1.1:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621"
+samsam@1.x:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50"
sane@^2.0.0:
version "2.2.0"
@@ -5401,7 +5854,7 @@ sane@^2.0.0:
optionalDependencies:
fsevents "^1.1.1"
-sass-graph@^2.1.1:
+sass-graph@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49"
dependencies:
@@ -5437,10 +5890,6 @@ scss-tokenizer@^0.2.3:
js-base64 "^2.1.8"
source-map "^0.4.2"
-seed-random@2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/seed-random/-/seed-random-2.2.0.tgz#2a9b19e250a817099231a5b99a4daf80b7fbed54"
-
select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
@@ -5484,6 +5933,10 @@ send@0.16.1:
range-parser "~1.2.0"
statuses "~1.3.1"
+serialize-javascript@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.4.0.tgz#7c958514db6ac2443a8abc062dc9f7886a7f6005"
+
serve-index@^1.7.2:
version "1.9.1"
resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
@@ -5569,14 +6022,17 @@ simple-swizzle@^0.2.2:
dependencies:
is-arrayish "^0.3.1"
-sinon@1.17.7:
- version "1.17.7"
- resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf"
+sinon@4.1.3:
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.1.3.tgz#fc599eda47ed9f1a694ce774b94ab44260bd7ac5"
dependencies:
- formatio "1.1.1"
- lolex "1.3.2"
- samsam "1.1.2"
- util ">=0.10.3 <1"
+ diff "^3.1.0"
+ formatio "1.2.0"
+ lodash.get "^4.4.2"
+ lolex "^2.2.0"
+ nise "^1.2.0"
+ supports-color "^4.4.0"
+ type-detect "^4.0.5"
slash@^1.0.0:
version "1.0.0"
@@ -5622,30 +6078,17 @@ source-list-map@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
-source-map-resolve@^0.3.0:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761"
- dependencies:
- atob "~1.1.0"
- resolve-url "~0.2.1"
- source-map-url "~0.3.0"
- urix "~0.1.0"
-
source-map-support@^0.4.15:
version "0.4.18"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
dependencies:
source-map "^0.5.6"
-source-map-url@~0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9"
-
-source-map@^0.1.38:
- version "0.1.43"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346"
+source-map-support@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.0.tgz#2018a7ad2bdf8faf2691e5fddab26bed5a2bacab"
dependencies:
- amdefine ">=0.0.4"
+ source-map "^0.6.0"
source-map@^0.4.2, source-map@^0.4.4:
version "0.4.4"
@@ -5657,7 +6100,7 @@ source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3, sour
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
-source-map@^0.6.1:
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
@@ -5716,6 +6159,20 @@ sshpk@^1.7.0:
jsbn "~0.1.0"
tweetnacl "~0.14.0"
+ssri@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.0.0.tgz#13c19390b606c821f2a10d02b351c1729b94d8cf"
+ dependencies:
+ safe-buffer "^5.1.0"
+
+stack-utils@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620"
+
+statuses@1:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
+
"statuses@>= 1.3.1 < 2", statuses@~1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
@@ -5726,6 +6183,10 @@ stdout-stream@^1.4.0:
dependencies:
readable-stream "^2.0.1"
+stealthy-require@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
+
stream-browserify@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
@@ -5733,6 +6194,13 @@ stream-browserify@^2.0.1:
inherits "~2.0.1"
readable-stream "^2.0.2"
+stream-each@^1.1.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd"
+ dependencies:
+ end-of-stream "^1.1.0"
+ stream-shift "^1.0.0"
+
stream-http@^2.3.1:
version "2.7.2"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad"
@@ -5743,6 +6211,10 @@ stream-http@^2.3.1:
to-arraybuffer "^1.0.0"
xtend "^4.0.0"
+stream-shift@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
+
strict-uri-encode@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
@@ -5762,7 +6234,7 @@ string-width@^1.0.1, string-width@^1.0.2:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
-string-width@^2.0.0:
+string-width@^2.0.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
dependencies:
@@ -5819,19 +6291,13 @@ strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
-style-loader@^0.18.2:
- version "0.18.2"
- resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.18.2.tgz#cc31459afbcd6d80b7220ee54b291a9fd66ff5eb"
+style-loader@^0.19.0:
+ version "0.19.1"
+ resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.19.1.tgz#591ffc80bcefe268b77c5d9ebc0505d772619f85"
dependencies:
loader-utils "^1.0.2"
schema-utils "^0.3.0"
-sugarss@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-1.0.0.tgz#65e51b3958432fb70d5451a68bb33e32d0cf1ef7"
- dependencies:
- postcss "^6.0.0"
-
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@@ -5860,9 +6326,9 @@ svgo@^0.7.0:
sax "~1.2.1"
whet.extend "~0.9.9"
-symbol-observable@^1.0.2:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d"
+symbol-observable@^1.0.3:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.1.0.tgz#5c68fd8d54115d9dfb72a84720549222e8db9b32"
symbol-tree@^3.2.1:
version "3.2.2"
@@ -5903,10 +6369,21 @@ test-exclude@^4.1.1:
read-pkg-up "^1.0.1"
require-main-filename "^1.0.1"
+text-encoding@^0.6.4:
+ version "0.6.4"
+ resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19"
+
throat@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
+through2@^2.0.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
+ dependencies:
+ readable-stream "^2.1.5"
+ xtend "~4.0.1"
+
thunky@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e"
@@ -5921,9 +6398,16 @@ timers-browserify@^2.0.2:
dependencies:
setimmediate "^1.0.4"
-tiny-emitter@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.0.tgz#bad327adb1804b42a231afa741532bd884cd09ad"
+tiny-lr@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-0.2.1.tgz#b3fdba802e5d56a33c2f6f10794b32e477ac729d"
+ dependencies:
+ body-parser "~1.14.0"
+ debug "~2.2.0"
+ faye-websocket "~0.10.0"
+ livereload-js "^2.2.0"
+ parseurl "~1.3.0"
+ qs "~5.1.0"
tmpl@1.0.x:
version "1.0.4"
@@ -5937,15 +6421,17 @@ to-fast-properties@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
-tough-cookie@^2.3.2, tough-cookie@~2.3.0, tough-cookie@~2.3.3:
+tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.3.0, tough-cookie@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
dependencies:
punycode "^1.4.1"
-tr46@~0.0.3:
- version "0.0.3"
- resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
+tr46@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
+ dependencies:
+ punycode "^2.1.0"
trim-newlines@^1.0.0:
version "1.0.0"
@@ -5955,6 +6441,12 @@ trim-right@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
+"true-case-path@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.2.tgz#7ec91130924766c7f573be3020c34f8fdfd00d62"
+ dependencies:
+ glob "^6.0.4"
+
tty-browserify@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
@@ -5965,6 +6457,10 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"
+tunnel-agent@~0.4.1:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
+
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
@@ -5975,27 +6471,31 @@ type-check@~0.3.2:
dependencies:
prelude-ls "~1.1.2"
-type-is@~1.6.15:
+type-detect@^4.0.5:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.5.tgz#d70e5bc81db6de2a381bcaca0c6e0cbdc7635de2"
+
+type-is@~1.6.10, type-is@~1.6.15:
version "1.6.15"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
dependencies:
media-typer "0.3.0"
mime-types "~2.1.15"
-typed-function@0.10.5:
- version "0.10.5"
- resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-0.10.5.tgz#2e0f18abd065219fab694a446a65c6d1981832c0"
+typedarray@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
ua-parser-js@^0.7.9:
version "0.7.16"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.16.tgz#50bce6df788dc5f13cdd2e1241332ffe18092243"
-uglify-js@3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.1.3.tgz#d61f0453b4718cab01581f3162aa90bab7520b42"
+uglify-js@3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.2.tgz#517af20aad7abe15e1e4c9aa33c0cc72aa0107ab"
dependencies:
- commander "~2.11.0"
- source-map "~0.5.1"
+ commander "~2.12.1"
+ source-map "~0.6.1"
uglify-js@^2.6, uglify-js@^2.8.29:
version "2.8.29"
@@ -6022,6 +6522,10 @@ uid-number@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
+underscore.string@~3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.2.3.tgz#806992633665d5e5fcb4db1fb3a862eb68e9e6da"
+
uniq@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
@@ -6036,6 +6540,18 @@ uniqs@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02"
+unique-filename@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3"
+ dependencies:
+ unique-slug "^2.0.0"
+
+unique-slug@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.0.tgz#db6676e7c7cc0629878ff196097c78855ae9f4ab"
+ dependencies:
+ imurmurhash "^0.1.4"
+
units-css@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/units-css/-/units-css-0.4.0.tgz#d6228653a51983d7c16ff28f8b9dc3b1ffed3a07"
@@ -6047,10 +6563,6 @@ unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
-urix@^0.1.0, urix@~0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
-
url-parse@1.0.x:
version "1.0.5"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b"
@@ -6076,7 +6588,14 @@ util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
-util@0.10.3, "util@>=0.10.3 <1", util@^0.10.3:
+util.promisify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
+ dependencies:
+ define-properties "^1.1.2"
+ object.getownpropertydescriptors "^2.0.3"
+
+util@0.10.3, util@^0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
dependencies:
@@ -6154,11 +6673,7 @@ wbuf@^1.1.0, wbuf@^1.7.2:
dependencies:
minimalistic-assert "^1.0.0"
-webidl-conversions@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
-
-webidl-conversions@^4.0.0:
+webidl-conversions@^4.0.1, webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
@@ -6172,9 +6687,9 @@ webpack-dev-middleware@^1.11.0:
range-parser "^1.0.3"
time-stamp "^2.0.0"
-webpack-dev-server@2.9.1:
- version "2.9.1"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-2.9.1.tgz#7ac9320b61b00eb65b2109f15c82747fc5b93585"
+webpack-dev-server@2.9.7:
+ version "2.9.7"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-2.9.7.tgz#100ad6a14775478924d417ca6dcfb9d52a98faed"
dependencies:
ansi-html "0.0.7"
array-includes "^3.0.3"
@@ -6182,12 +6697,15 @@ webpack-dev-server@2.9.1:
chokidar "^1.6.0"
compression "^1.5.2"
connect-history-api-fallback "^1.3.0"
+ debug "^3.1.0"
del "^3.0.0"
- express "^4.13.3"
+ express "^4.16.2"
html-entities "^1.2.0"
http-proxy-middleware "~0.17.4"
+ import-local "^0.1.1"
internal-ip "1.2.0"
ip "^1.1.5"
+ killable "^1.0.0"
loglevel "^1.4.1"
opn "^5.1.0"
portfinder "^1.0.9"
@@ -6201,7 +6719,7 @@ webpack-dev-server@2.9.1:
webpack-dev-middleware "^1.11.0"
yargs "^6.6.0"
-webpack-manifest-plugin@^1.3.1:
+webpack-manifest-plugin@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-1.3.2.tgz#5ea8ee5756359ddc1d98814324fe43496349a7d4"
dependencies:
@@ -6215,9 +6733,9 @@ webpack-sources@^1.0.1:
source-list-map "^2.0.0"
source-map "~0.5.3"
-webpack@^3.5.5:
- version "3.7.1"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.7.1.tgz#6046b5c415ff7df7a0dc54c5b6b86098e8b952da"
+webpack@^3.10.0:
+ version "3.10.0"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.10.0.tgz#5291b875078cf2abf42bdd23afe3f8f96c17d725"
dependencies:
acorn "^5.0.0"
acorn-dynamic-import "^2.0.0"
@@ -6263,12 +6781,13 @@ whatwg-fetch@2.0.3, whatwg-fetch@>=0.10.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
-whatwg-url@^4.3.0:
- version "4.8.0"
- resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.8.0.tgz#d2981aa9148c1e00a41c5a6131166ab4683bbcc0"
+whatwg-url@^6.3.0:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.4.0.tgz#08fdf2b9e872783a7a1f6216260a1d66cc722e08"
dependencies:
- tr46 "~0.0.3"
- webidl-conversions "^3.0.0"
+ lodash.sortby "^4.7.0"
+ tr46 "^1.0.0"
+ webidl-conversions "^4.0.1"
whet.extend@~0.9.9:
version "0.9.9"
@@ -6288,6 +6807,12 @@ which@1, which@^1.2.12, which@^1.2.9:
dependencies:
isexe "^2.0.0"
+which@~1.2.1:
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5"
+ dependencies:
+ isexe "^2.0.0"
+
wide-align@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710"
@@ -6310,13 +6835,6 @@ wordwrap@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
-worker-farm@^1.3.1:
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.0.tgz#adfdf0cd40581465ed0a1f648f9735722afd5c8d"
- dependencies:
- errno "^0.1.4"
- xtend "^4.0.1"
-
wrap-ansi@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
@@ -6340,7 +6858,7 @@ xml-name-validator@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635"
-xtend@^4.0.0, xtend@^4.0.1:
+xtend@^4.0.0, xtend@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
@@ -6370,6 +6888,29 @@ yargs-parser@^7.0.0:
dependencies:
camelcase "^4.1.0"
+yargs-parser@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950"
+ dependencies:
+ camelcase "^4.1.0"
+
+yargs@^10.0.3:
+ version "10.1.1"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.1.tgz#5fe1ea306985a099b33492001fa19a1e61efe285"
+ dependencies:
+ cliui "^4.0.0"
+ decamelize "^1.1.1"
+ find-up "^2.1.0"
+ get-caller-file "^1.0.1"
+ os-locale "^2.0.0"
+ require-directory "^2.1.1"
+ require-main-filename "^1.0.1"
+ set-blocking "^2.0.0"
+ string-width "^2.0.0"
+ which-module "^2.0.0"
+ y18n "^3.2.1"
+ yargs-parser "^8.1.0"
+
yargs@^6.6.0:
version "6.6.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208"
@@ -6424,24 +6965,6 @@ yargs@^8.0.2:
y18n "^3.2.1"
yargs-parser "^7.0.0"
-yargs@^9.0.0:
- version "9.0.1"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c"
- dependencies:
- camelcase "^4.1.0"
- cliui "^3.2.0"
- decamelize "^1.1.1"
- get-caller-file "^1.0.1"
- os-locale "^2.0.0"
- read-pkg-up "^2.0.0"
- require-directory "^2.1.1"
- require-main-filename "^1.0.1"
- set-blocking "^2.0.0"
- string-width "^2.0.0"
- which-module "^2.0.0"
- y18n "^3.2.1"
- yargs-parser "^7.0.0"
-
yargs@~3.10.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"