diff options
| author | Luc Donnet | 2018-02-19 11:04:29 +0100 |
|---|---|---|
| committer | Luc Donnet | 2018-02-19 11:04:29 +0100 |
| commit | 7b17deff51545358009cb417cbb9d796565e7540 (patch) | |
| tree | a43a5586ad39d838dd607e600dbc15ff18a58ab3 | |
| parent | 89428163fc93a7e09ebb0ca47939f8558afeb5eb (diff) | |
| parent | 5f6008d165df4499319a2121a71842657d6ac3c9 (diff) | |
| download | chouette-core-7b17deff51545358009cb417cbb9d796565e7540.tar.bz2 | |
Merge branch 'master' into 0000-docker
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 ``` @@ -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. @@ -1,20 +1,15 @@ # Chouette2 [](https://travis-ci.org/afimb/chouette2) [](https://gemnasium.com/afimb/chouette2) [](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"> + ({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">×</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">×</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">×</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 Binary files differdeleted file mode 100644 index 97ea3f513..000000000 --- a/spec/fixtures/OFFRE_WITH_EXTRA.zip +++ /dev/null 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 Binary files differnew file mode 100644 index 000000000..2ff4ec66d --- /dev/null +++ b/spec/fixtures/regression-5281.zip 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&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&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&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&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&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 @@ -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" |
