diff options
| author | Robert | 2017-04-24 14:16:52 +0200 |
|---|---|---|
| committer | Robert | 2017-04-24 14:16:52 +0200 |
| commit | 2d19e65fa8d8ac037c7f00a638111788b7ee002c (patch) | |
| tree | 830fe41ac13743f75f2c16f41dfd1ff399b99a9b | |
| parent | 5003acfc533baa824fed11cf6f82f86393b3a0f6 (diff) | |
| parent | 1cbed80c913420c76ac7d3716b9d8c4bf4e14278 (diff) | |
| download | chouette-core-2d19e65fa8d8ac037c7f00a638111788b7ee002c.tar.bz2 | |
conflict resolution and asset recompilation
250 files changed, 6121 insertions, 1678 deletions
@@ -1,8 +1,8 @@ -# coding: iso-8859-1 +# coding: utf-8 source 'http://rubygems.org' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 4.1.10' +gem 'rails', '~> 4.2.8' # Use SCSS for stylesheets gem 'sass-rails', '~> 4.0.3' @@ -56,7 +56,7 @@ platforms :ruby do gem 'sqlite3' end -gem 'activerecord-postgis-adapter' +gem 'activerecord-postgis-adapter', "~> 3.0.0" gem 'polylines' # Codifligne API @@ -82,11 +82,11 @@ gem 'georuby', '2.3.0' # Fix version for georuby-ext because api has changed gem 'mimemagic' # User interface -gem 'language_engine', '0.0.6' +gem 'language_engine', github: 'af83/language_engine' gem 'calendar_helper', '0.2.5' gem 'cocoon' gem 'slim-rails', '~> 3.1' -gem 'formtastic', '2.3.1' +gem 'formtastic', '3.1.5' gem 'RedCloth', '~> 4.3.0' gem 'simple_form', '~> 3.1.0' gem 'font-awesome-sass', '~> 4.7' @@ -105,15 +105,14 @@ gem 'google-analytics-rails' # Model gem 'will_paginate' gem 'ransack' -gem 'squeel' +gem "squeel", :git => "git://github.com/activerecord-hackery/squeel.git" gem 'active_attr' gem 'draper' gem 'enumerize', '~> 0.10.0' -gem 'foreigner', '~> 1.7.4' gem 'deep_cloneable', '~> 2.0.0' -gem 'acts-as-taggable-on', '>= 3' +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' @@ -136,12 +135,13 @@ group :development do gem 'capistrano', '2.13.5' gem 'capistrano-ext' gem 'capistrano-npm', require: false - gem 'guard' - gem 'guard-rspec' + # Issue #3017 Requires ruby_dep which requires ruby > 2.2.3 + # gem 'guard' + # gem 'guard-rspec', "~> 4.5.0" gem 'rails-erd' # MetaRequest is incompatible with rgeo-activerecord # gem 'meta_request' - gem 'quiet_assets', '~> 1.0' + gem 'quiet_assets' gem 'license_finder' gem 'bundler-audit' @@ -166,7 +166,8 @@ end group :test, :development do gem 'awesome_print' gem 'pry-rails' - gem 'rspec-rails', '~> 3.1.0' + gem 'pry-byebug' + gem 'rspec-rails', '~> 3.5.0' gem 'fakeweb' gem 'webmock' gem 'capybara', '~> 2.4.0' @@ -177,7 +178,7 @@ group :test, :development do gem 'rb-inotify', require: RUBY_PLATFORM.include?('linux') && 'rb-inotify' gem 'rb-fsevent', require: RUBY_PLATFORM.include?('darwin') && 'rb-fsevent' gem 'transpec' - gem 'shoulda-matchers' + gem 'shoulda-matchers', '~> 3.1' gem "teaspoon-jasmine" gem "phantomjs" end diff --git a/Gemfile.lock b/Gemfile.lock index 1ed5de7ae..49ab0c9ac 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,4 +1,20 @@ GIT + remote: git://github.com/activerecord-hackery/squeel.git + revision: 5542266d502db8022e14105f9dfb455a79d6fc4a + specs: + squeel (1.2.3) + activerecord (>= 3.0) + activesupport (>= 3.0) + polyamorous (~> 1.1.0) + +GIT + remote: git://github.com/af83/language_engine.git + revision: c4d7d5af781b55c1df4806c3960caf3c22f1ee96 + specs: + language_engine (0.0.7) + rails (~> 4.2) + +GIT remote: git://github.com/af83/whenever.git revision: b7963381a11243affe4f35881c85be0710f434e3 specs: @@ -34,69 +50,78 @@ GEM specs: RedCloth (4.3.2) SyslogLogger (2.0) - aasm (4.5.2) - actionmailer (4.1.10) - actionpack (= 4.1.10) - actionview (= 4.1.10) + aasm (4.12.0) + concurrent-ruby (~> 1.0) + actionmailer (4.2.8) + actionpack (= 4.2.8) + actionview (= 4.2.8) + activejob (= 4.2.8) mail (~> 2.5, >= 2.5.4) - actionpack (4.1.10) - actionview (= 4.1.10) - activesupport (= 4.1.10) - rack (~> 1.5.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (4.2.8) + actionview (= 4.2.8) + activesupport (= 4.2.8) + rack (~> 1.6) rack-test (~> 0.6.2) - actionview (4.1.10) - activesupport (= 4.1.10) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.8) + activesupport (= 4.2.8) builder (~> 3.1) erubis (~> 2.7.0) - active_attr (0.9.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + active_attr (0.10.0) activemodel (>= 3.0.2, < 5.1) activesupport (>= 3.0.2, < 5.1) - activemodel (4.1.10) - activesupport (= 4.1.10) + activejob (4.2.8) + activesupport (= 4.2.8) + globalid (>= 0.3.0) + activemodel (4.2.8) + activesupport (= 4.2.8) builder (~> 3.1) - activerecord (4.1.10) - activemodel (= 4.1.10) - activesupport (= 4.1.10) - arel (~> 5.0.0) - activerecord-postgis-adapter (2.2.2) - activerecord (>= 4.0.0, < 4.2.0) - rgeo-activerecord (~> 1.2) - activesupport (4.1.10) - i18n (~> 0.6, >= 0.6.9) - json (~> 1.7, >= 1.7.7) + activerecord (4.2.8) + activemodel (= 4.2.8) + activesupport (= 4.2.8) + arel (~> 6.0) + activerecord-postgis-adapter (3.0.0) + activerecord (~> 4.2) + rgeo-activerecord (~> 4.0) + activesupport (4.2.8) + i18n (~> 0.7) minitest (~> 5.1) - thread_safe (~> 0.1) + thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - acts-as-taggable-on (3.5.0) - activerecord (>= 3.2, < 5) + acts-as-taggable-on (4.0.0) + activerecord (>= 4.0) acts_as_list (0.6.0) activerecord (>= 3.0) acts_as_tree (2.1.0) activerecord (>= 3.0.0) - addressable (2.3.7) - apartment (1.0.0) + addressable (2.3.8) + apartment (1.0.2) activerecord (>= 3.1.2, < 5.0) rack (>= 1.3.6) - arel (5.0.1.20140414130214) - ast (2.0.0) - astrolabe (1.3.0) - parser (>= 2.2.0.pre.3, < 3.0) - awesome_print (1.6.1) + arel (6.0.4) + ast (2.3.0) + astrolabe (1.3.1) + parser (~> 2.2) + awesome_print (1.7.0) bcrypt (3.1.11) - bcrypt (3.1.11-java) better_errors (2.1.1) coderay (>= 1.0.0) erubis (>= 2.6.6) rack (>= 0.9.0) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) - breadcrumbs_on_rails (2.3.0) + breadcrumbs_on_rails (3.0.1) browserify-rails (1.1.0) railties (>= 4.0.0, < 5.0) - builder (3.2.2) + builder (3.2.3) bundler-audit (0.5.0) bundler (~> 1.2) thor (~> 0.18) + byebug (9.0.6) calendar_helper (0.2.5) open4 capistrano (2.13.5) @@ -119,23 +144,20 @@ GEM activemodel (>= 4.0.0) activesupport (>= 4.0.0) mime-types (>= 1.16) - celluloid (0.16.0) - timers (~> 4.0.0) - choice (0.1.7) + choice (0.2.0) chronic (0.10.2) cliver (0.3.2) - cocoon (1.2.6) - coderay (1.1.0) + cocoon (1.2.9) + coderay (1.1.1) coffee-rails (4.0.1) coffee-script (>= 2.2.0) railties (>= 4.0.0, < 5.0) - coffee-script (2.3.0) + coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.9.1) - concurrent-ruby (1.0.2) - concurrent-ruby (1.0.2-java) - connection_pool (2.2.0) + coffee-script-source (1.12.2) + concurrent-ruby (1.0.5) + connection_pool (2.2.1) crack (0.4.3) safe_yaml (~> 1.0.0) cucumber (2.4.0) @@ -148,16 +170,16 @@ GEM multi_test (>= 0.1.2) cucumber-core (1.5.0) gherkin (~> 4.0) - cucumber-rails (1.4.4) + cucumber-rails (1.4.5) capybara (>= 1.1.2, < 3) - cucumber (>= 1.3.8, < 3) + cucumber (>= 1.3.8, < 4) mime-types (>= 1.16, < 4) nokogiri (~> 1.5) railties (>= 3, < 5.1) cucumber-wire (0.0.1) - daemons (1.1.9) - database_cleaner (1.4.1) - dbf (3.0.3) + daemons (1.2.4) + database_cleaner (1.5.3) + dbf (3.1.0) debug_inspector (0.0.2) deep_cloneable (2.0.2) activerecord (>= 3.1.0, < 5.0.0) @@ -168,18 +190,18 @@ GEM responders thread_safe (~> 0.1) warden (~> 1.2.3) - devise-async (0.9.0) - devise (~> 3.2) + devise-async (0.10.2) + devise (>= 3.2, < 4.0) devise-encryptable (0.2.0) devise (>= 2.1.0) - devise-i18n (0.11.4) - devise_cas_authenticatable (1.9.0) + devise-i18n (1.1.2) + devise_cas_authenticatable (1.10.0) devise (>= 1.2.0) rubycas-client (>= 2.2.1) - devise_invitable (1.4.1) - actionmailer (>= 3.2.6, < 5) + devise_invitable (1.6.1) + actionmailer (>= 3.2.6) devise (>= 3.2.0) - diff-lcs (1.2.5) + diff-lcs (1.3) docile (1.1.5) dr-ffi-proj4 (0.0.3) ffi (>= 1.0.0) @@ -195,32 +217,28 @@ GEM enumerize (0.10.1) activesupport (>= 3.2) erubis (2.7.0) - execjs (2.6.0) + execjs (2.7.0) fabrication (2.14.1) - factory_girl (4.5.0) + factory_girl (4.8.0) activesupport (>= 3.0.0) - factory_girl_rails (4.5.0) - factory_girl (~> 4.5.0) + factory_girl_rails (4.8.0) + factory_girl (~> 4.8.0) railties (>= 3.0.0) faker (1.7.3) i18n (~> 0.5) fakeweb (1.3.0) - faraday (0.9.1) + faraday (0.9.2) multipart-post (>= 1.2, < 3) - faraday_middleware (0.9.1) + faraday_middleware (0.9.2) faraday (>= 0.7.4, < 0.10) ffaker (2.1.0) - ffi (1.9.10) - ffi (1.9.10-java) - ffi-geos (1.1.0) + ffi (1.9.18) + ffi-geos (1.2.0) ffi (>= 1.0.0) font-awesome-sass (4.7.0) sass (>= 3.2) - foreigner (1.7.4) - activerecord (>= 3.0.0) - formatador (0.2.5) - formtastic (2.3.1) - actionpack (>= 3.0) + formtastic (3.1.5) + actionpack (>= 3.2.13) geokit (1.6.7) multi_json (>= 1.3.2) georuby (2.3.0) @@ -232,222 +250,199 @@ GEM geokit (= 1.6.7) georuby (>= 1.9.8) rgeo (>= 0.3.20) - gherkin (4.0.0) - google-analytics-rails (0.0.6) - guard (2.12.4) - formatador (>= 0.2.4) - listen (~> 2.7) - lumberjack (~> 1.0) - nenv (~> 0.1) - notiffany (~> 0.0) - pry (>= 0.9.12) - shellany (~> 0.0) - thor (>= 0.18.1) - guard-compat (1.2.1) - guard-rspec (4.5.0) - guard (~> 2.1) - guard-compat (~> 1.1) - rspec (>= 2.99.0, < 4.0) - has_scope (0.6.0) - actionpack (>= 3.2, < 5) - activesupport (>= 3.2, < 5) - hashdiff (0.3.0) - highline (1.7.1) + gherkin (4.1.1) + globalid (0.3.7) + activesupport (>= 4.1.0) + google-analytics-rails (1.1.0) + has_scope (0.7.0) + actionpack (>= 4.1, < 5.1) + activesupport (>= 4.1, < 5.1) + hashdiff (0.3.2) + highline (1.7.8) hike (1.2.3) - hitimes (1.2.2) - hitimes (1.2.2-java) httparty (0.14.0) multi_xml (>= 0.5.2) - i18n (0.7.0) - i18n-tasks (0.8.6) - activesupport + i18n (0.8.1) + i18n-tasks (0.9.13) + activesupport (>= 4.0.2) + ast (>= 2.1.0) easy_translate (>= 0.5.0) erubis - highline + highline (>= 1.7.3) i18n - term-ansicolor + parser (>= 2.2.3.0) + rainbow (~> 2.2) terminal-table (>= 1.5.1) - inherited_resources (1.6.0) - actionpack (>= 3.2, < 5) - has_scope (~> 0.6.0.rc) - railties (>= 3.2, < 5) + inherited_resources (1.7.1) + actionpack (>= 3.2, < 5.1) + has_scope (~> 0.6) + railties (>= 3.2, < 5.1) responders - jbuilder (2.2.11) - activesupport (>= 3.0.0, < 5) + jbuilder (2.6.3) + activesupport (>= 3.0.0, < 5.2) multi_json (~> 1.2) jquery-rails (3.1.4) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) - json (1.8.3) - json (1.8.3-java) - language_engine (0.0.6) - rails (~> 4.1.1) + json (1.8.6) launchy (2.4.3) addressable (~> 2.3) - launchy (2.4.3-java) - addressable (~> 2.3) - spoon (~> 0.0.1) letter_opener (1.4.1) launchy (~> 2.2) - libv8 (3.16.14.11) - license_finder (2.1.2) + libv8 (3.16.14.19) + license_finder (3.0.0) bundler httparty rubyzip thor + with_env (> 1.0) xml-simple - listen (2.8.6) - celluloid (>= 0.15.2) - rb-fsevent (>= 0.9.3) - rb-inotify (>= 0.9) - lumberjack (1.0.9) - mail (2.6.3) - mime-types (>= 1.16, < 3) + loofah (2.0.3) + nokogiri (>= 1.5.9) + mail (2.6.4) + mime-types (>= 1.16, < 4) map_layers (0.0.4) method_source (0.8.2) - mime-types (2.4.3) - mimemagic (0.3.0) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mimemagic (0.3.2) mini_portile2 (2.1.0) - minitest (5.9.1) - multi_json (1.11.2) + minitest (5.10.1) + multi_json (1.12.1) multi_test (0.1.2) - multi_xml (0.5.5) + multi_xml (0.6.0) multipart-post (2.0.0) - nenv (0.2.0) net-scp (1.2.1) net-ssh (>= 2.6.5) net-sftp (2.1.2) net-ssh (>= 2.6.5) - net-ssh (2.9.2) - net-ssh-gateway (1.2.0) - net-ssh (>= 2.6.5) - newrelic_rpm (3.11.2.286) - nokogiri (1.7.0.1) + net-ssh (4.1.0) + net-ssh-gateway (2.0.0) + net-ssh (>= 4.0.0) + newrelic_rpm (4.0.0.332) + nokogiri (1.7.1) mini_portile2 (~> 2.1.0) - nokogiri (1.7.0.1-java) - notiffany (0.0.6) - nenv (~> 0.1) - shellany (~> 0.0) open4 (1.3.4) orm_adapter (0.5.0) - parser (2.2.0.3) - ast (>= 1.1, < 3.0) - pg (0.19.0) + parser (2.4.0.0) + ast (~> 2.2) + pg (0.20.0) phantomjs (2.1.1.0) - poltergeist (1.6.0) + poltergeist (1.14.0) capybara (~> 2.1) cliver (~> 0.3.1) - multi_json (~> 1.0) websocket-driver (>= 0.2.0) polyamorous (1.1.0) activerecord (>= 3.0) polylines (0.3.0) - pry (0.10.1) - coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) - pry (0.10.1-java) + pry (0.10.4) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - spoon (~> 0.0) - pry-rails (0.3.4) - pry (>= 0.9.10) + pry-byebug (3.4.2) + byebug (~> 9.0) + pry (~> 0.10) + pry-rails (0.3.6) + pry (>= 0.10.4) pundit (1.1.0) activesupport (>= 3.0.0) quiet_assets (1.1.0) railties (>= 3.1, < 5.0) - rabl (0.11.6) + rabl (0.13.1) activesupport (>= 2.3.14) - rack (1.5.5) + rack (1.6.5) rack-protection (1.5.3) rack rack-test (0.6.3) rack (>= 1.0) - rails (4.1.10) - actionmailer (= 4.1.10) - actionpack (= 4.1.10) - actionview (= 4.1.10) - activemodel (= 4.1.10) - activerecord (= 4.1.10) - activesupport (= 4.1.10) + rails (4.2.8) + actionmailer (= 4.2.8) + actionpack (= 4.2.8) + actionview (= 4.2.8) + activejob (= 4.2.8) + activemodel (= 4.2.8) + activerecord (= 4.2.8) + activesupport (= 4.2.8) bundler (>= 1.3.0, < 2.0) - railties (= 4.1.10) - sprockets-rails (~> 2.0) - rails-assets-bootstrap-sass-official (3.3.4) - rails-assets-jquery (>= 1.9.0) + railties (= 4.2.8) + sprockets-rails + rails-assets-bootstrap-sass-official (3.3.7) + rails-assets-jquery (>= 1.9.1, < 4) rails-assets-footable (2.0.3) rails-assets-jquery (>= 1.4.4) - rails-assets-jquery (2.1.4) + rails-assets-jquery (3.2.1) rails-assets-jquery-tokeninput (1.7.0) rails-assets-jquery (>= 1.5) rails-assets-modernizr (2.0.6) rails-assets-respond (1.4.2) rails-assets-tagmanager (3.0.1) rails-assets-jquery (>= 1.0.0) - rails-erd (1.3.1) + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.8) + activesupport (>= 4.2.0.beta, < 5.0) + nokogiri (~> 1.6) + rails-deprecated_sanitizer (>= 1.0.1) + rails-erd (1.5.0) activerecord (>= 3.2) activesupport (>= 3.2) - choice (~> 0.1.6) - ruby-graphviz (~> 1.0.4) - rails-i18n (4.0.4) - i18n (~> 0.6) + choice (~> 0.2.0) + ruby-graphviz (~> 1.2) + rails-html-sanitizer (1.0.3) + loofah (~> 2.0) + rails-i18n (4.0.9) + i18n (~> 0.7) railties (~> 4.0) rails-observers (0.1.2) activemodel (~> 4.0) - railties (4.1.10) - actionpack (= 4.1.10) - activesupport (= 4.1.10) + railties (4.2.8) + actionpack (= 4.2.8) + activesupport (= 4.2.8) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rainbow (2.0.0) - rake (11.3.0) - ransack (1.6.3) + rainbow (2.2.1) + rake (12.0.0) + ransack (1.6.5) actionpack (>= 3.0) activerecord (>= 3.0) activesupport (>= 3.0) i18n polyamorous (~> 1.1) - rb-fsevent (0.9.4) - rb-inotify (0.9.5) + rb-fsevent (0.9.8) + rb-inotify (0.9.8) ffi (>= 0.5.0) - rdoc (4.2.0) - json (~> 1.4) - redis (3.3.1) + rdoc (4.3.0) + redis (3.3.3) ref (2.0.0) - request_store (1.3.1) - responders (1.1.2) - railties (>= 3.2, < 4.2) - rgeo (0.5.2) - rgeo-activerecord (1.2.0) - activerecord (~> 4.0) + request_store (1.3.2) + responders (2.3.0) + railties (>= 4.2.0, < 5.1) + rgeo (0.5.3) + rgeo-activerecord (4.0.5) + activerecord (~> 4.2) rgeo (~> 0.3) - roo (1.13.2) - nokogiri - rubyzip - spreadsheet (> 0.6.4) - rspec (3.1.0) - rspec-core (~> 3.1.0) - rspec-expectations (~> 3.1.0) - rspec-mocks (~> 3.1.0) - rspec-core (3.1.7) - rspec-support (~> 3.1.0) - rspec-expectations (3.1.2) + roo (2.7.1) + nokogiri (~> 1) + rubyzip (~> 1.1, < 2.0.0) + rspec-core (3.5.4) + rspec-support (~> 3.5.0) + rspec-expectations (3.5.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.1.0) - rspec-mocks (3.1.3) - rspec-support (~> 3.1.0) - rspec-rails (3.1.0) + rspec-support (~> 3.5.0) + rspec-mocks (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-rails (3.5.2) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.1.0) - rspec-expectations (~> 3.1.0) - rspec-mocks (~> 3.1.0) - rspec-support (~> 3.1.0) - rspec-support (3.1.2) - ruby-graphviz (1.0.9) - ruby-ole (1.2.11.8) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) + rspec-support (~> 3.5.0) + rspec-support (3.5.0) + ruby-graphviz (1.2.3) rubycas-client (2.3.9) activesupport rubyzip (1.1.7) @@ -461,112 +456,100 @@ GEM sawyer (0.6.0) addressable (~> 2.3.5) faraday (~> 0.8, < 0.10) - sdoc (0.4.1) + sdoc (0.4.2) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) select2-rails (4.0.3) thor (~> 0.14) - shellany (0.0.1) - shoulda-matchers (2.8.0) - activesupport (>= 3.0.0) - sidekiq (4.1.0) + shoulda-matchers (3.1.1) + activesupport (>= 4.0.0) + sidekiq (4.2.10) concurrent-ruby (~> 1.0) connection_pool (~> 2.2, >= 2.2.0) + rack-protection (>= 1.5.0) redis (~> 3.2, >= 3.2.1) - simple_form (3.1.0) + simple_form (3.1.1) actionpack (~> 4.0) activemodel (~> 4.0) - simplecov (0.10.0) + simplecov (0.14.1) docile (~> 1.1.0) - json (~> 1.8) + json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.0) simplecov-rcov (0.2.3) simplecov (>= 0.4.1) - sinatra (1.4.7) + sinatra (1.4.8) rack (~> 1.5) rack-protection (~> 1.4) tilt (>= 1.3, < 3) slim (3.0.7) temple (~> 0.7.6) tilt (>= 1.3.3, < 2.1) - slim-rails (3.1.0) + slim-rails (3.1.2) actionpack (>= 3.1) railties (>= 3.1) slim (~> 3.0) slop (3.6.0) - spoon (0.0.4) - ffi - spreadsheet (1.0.2) - ruby-ole (>= 1.0) - spring (1.7.2) - sprockets (2.12.3) + spring (2.0.1) + activesupport (>= 4.2) + sprockets (2.12.4) hike (~> 1.2) multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - sprockets-rails (2.2.4) + sprockets-rails (2.3.3) actionpack (>= 3.0) activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) - sqlite3 (1.3.10) - squeel (1.2.3) - activerecord (>= 3.0) - activesupport (>= 3.0) - polyamorous (~> 1.1.0) + sqlite3 (1.3.13) teaspoon (1.1.5) railties (>= 3.2.5, < 6) teaspoon-jasmine (2.3.4) teaspoon (>= 1.0.0) temple (0.7.7) - term-ansicolor (1.3.2) - tins (~> 1.0) - terminal-table (1.6.0) - therubyracer (0.12.2) - libv8 (~> 3.16.14.0) + terminal-table (1.7.3) + unicode-display_width (~> 1.1.1) + therubyracer (0.12.3) + libv8 (~> 3.16.14.15) ref thor (0.19.4) thread (0.2.2) - thread_safe (0.3.5) - thread_safe (0.3.5-java) + thread_safe (0.3.6) tilt (1.4.1) - timers (4.0.1) - hitimes - tins (1.10.2) - transpec (3.1.0) - activesupport (>= 3.0, < 5.0) + transpec (3.3.0) + activesupport (>= 3.0, < 6.0) astrolabe (~> 1.2) bundler (~> 1.3) - json (~> 1.8) - parser (~> 2.2) + json (>= 1.8, < 3.0) + parser (>= 2.3.0.7) rainbow (>= 1.99.1, < 3.0) - turbolinks (2.5.3) - coffee-rails - tzinfo (1.2.2) + turbolinks (5.0.1) + turbolinks-source (~> 5) + turbolinks-source (5.0.0) + tzinfo (1.2.3) thread_safe (~> 0.1) uglifier (2.7.2) execjs (>= 0.3.0) json (>= 1.8.0) - warden (1.2.6) + unicode-display_width (1.1.3) + warden (1.2.7) rack (>= 1.0) - webmock (2.1.0) + webmock (3.0.0) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff - websocket-driver (0.5.3) - websocket-extensions (>= 0.1.0) - websocket-driver (0.5.3-java) + websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.2) will_paginate (3.1.5) will_paginate-bootstrap (1.0.1) will_paginate (>= 3.0.3) + with_env (1.1.0) xml-simple (1.1.5) xpath (2.0.0) nokogiri (~> 1.3) PLATFORMS - java ruby DEPENDENCIES @@ -574,8 +557,8 @@ DEPENDENCIES SyslogLogger aasm active_attr - activerecord-postgis-adapter - acts-as-taggable-on (>= 3) + activerecord-postgis-adapter (~> 3.0.0) + acts-as-taggable-on (~> 4.0.0) acts_as_list (~> 0.6.0) acts_as_tree (~> 2.1.0) apartment (~> 1.0.0) @@ -614,20 +597,17 @@ DEPENDENCIES faraday_middleware (~> 0.9.1) ffaker (~> 2.1.0) font-awesome-sass (~> 4.7) - foreigner (~> 1.7.4) - formtastic (= 2.3.1) + formtastic (= 3.1.5) georuby (= 2.3.0) georuby-ext (= 0.0.5) google-analytics-rails - guard - guard-rspec has_array_of! i18n-tasks inherited_resources jbuilder (~> 2.0) jquery-rails (~> 3.1.4) json - language_engine (= 0.0.6) + language_engine! launchy letter_opener license_finder @@ -638,11 +618,12 @@ DEPENDENCIES phantomjs poltergeist polylines + pry-byebug pry-rails pundit - quiet_assets (~> 1.0) + quiet_assets rabl - rails (~> 4.1.10) + rails (~> 4.2.8) rails-assets-bootstrap-sass-official (~> 3.3.0)! rails-assets-footable (~> 2.0.3)! rails-assets-jquery-tokeninput (~> 1.7.0)! @@ -659,13 +640,13 @@ DEPENDENCIES reflex! rgeo (~> 0.5.2) roo - rspec-rails (~> 3.1.0) + rspec-rails (~> 3.5.0) rubyzip (~> 1.1.7) sass-rails (~> 4.0.3) sawyer (~> 0.6.0) sdoc (~> 0.4.0) select2-rails (~> 4.0, >= 4.0.3) - shoulda-matchers + shoulda-matchers (~> 3.1) sidekiq simple_form (~> 3.1.0) simplecov @@ -674,7 +655,7 @@ DEPENDENCIES slim-rails (~> 3.1) spring sqlite3 - squeel + squeel! teaspoon-jasmine therubyracer (~> 0.12) transpec @@ -686,4 +667,4 @@ DEPENDENCIES will_paginate-bootstrap BUNDLED WITH - 1.13.6 + 1.14.6 diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 000000000..7bfcb7074 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,80 @@ +# 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/): + + rvm install 2.3.0 + +Add the bundler gem + + gem install bundler + +Go into your local repro and install the gems + + bundle + +### Caveats + +`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 + +or + gem install libv8 -v '<version>' -- --with-system-v8 + bundle + +You will get the correct value of `<version>` from bundler's error message. + +## 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. + +### Postgres + +#### Create user + + createuser -s -U $USER -P chouette + ^ ^ ^ + | | +---- prompt for passwd + | +----- as your default postgres user (remove in case of different config) + +---------- superuser + +When promted for the password enter the highly secure string `chouette`. + + +#### Create database + + bundle exec rake db:create + bundle exec rake db:migrate + + RAILS_ENV=test bundle exec rake db:create + RAILS_ENV=test bundle exec rake db:migrate + +#### Install node.js packages + + bundle exec rake npm:install + +### SSO Configuration + +Get yourself an invitation to [Stif Portail](http://stif-portail-dev.af83.priv/) and be sure to update your information +on your [profile page](http://stif-portail-dev.af83.priv/users/edit) + + +# Troubleshouting + +If PG complains about illegal type `hstore` in your tests that is probably because the shared extension is not installed, here is waht to do: + + bundle exec rake db:test:purge + +Thanks to `lib/tasks/extensions.rake`. @@ -94,7 +94,7 @@ Configure for Generating URLs in Action Mailer Views. * 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_assets``` +* 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``` @@ -144,7 +144,7 @@ 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_assets``` to false in [production.rb](./config/environments/production.rb) +so change parameter ```serve_static_files``` to false in [production.rb](./config/environments/production.rb) Test ---- diff --git a/app/assets/fonts/sBoiv/sboiv.svg b/app/assets/fonts/sBoiv/sboiv.svg index 76f038bd7..be313bfcc 100644 --- a/app/assets/fonts/sBoiv/sboiv.svg +++ b/app/assets/fonts/sBoiv/sboiv.svg @@ -8,6 +8,12 @@ <missing-glyph horiz-adv-x="1024" /> <glyph unicode=" " horiz-adv-x="512" d="" /> <glyph unicode="" glyph-name="update-vj" d="M1017.856 448c0 266.935-216.393 483.328-483.328 483.328v-99.84c211.677-0.291 383.197-171.81 383.488-383.46zM918.016 448c0-0.071 0-0.154 0-0.238 0-211.795-171.693-383.488-383.488-383.488-187.627 0-343.782 134.745-376.977 312.746l-102.767 2.371c29.828-240.928 233.283-425.583 479.866-425.583 266.935 0 483.328 216.393 483.328 483.328 0 3.82-0.044 7.629-0.132 11.427zM534.528 755.2c169.662 0 307.2-137.538 307.2-307.2h-307.2zM460.8 669.184c-0.283-17.134-14.098-30.949-31.205-31.232h-136.731v-136.192c0.003-0.152 0.004-0.332 0.004-0.512 0-17.249-13.983-31.232-31.232-31.232-0.001 0-0.003 0-0.004 0h-62.976c-17.31 0.288-31.232 14.388-31.232 31.74 0 0.001 0 0.003 0 0.004v136.192h-136.192c-17.249 0-31.232 13.983-31.232 31.232v62.976c0 17.249 13.983 31.232 31.232 31.232h136.192v136.704c0.283 17.134 14.098 30.949 31.205 31.232h63.003c17.249 0 31.232-13.983 31.232-31.232v-136.704h136.192c0.001 0 0.003 0 0.004 0 17.352 0 31.452-13.922 31.74-31.205z" /> +<<<<<<< HEAD <glyph unicode="" glyph-name="preparing" d="M1011.2 614.4l-80.384 80.384c-7.765 8.206-18.732 13.313-30.891 13.313-0.12 0-0.239 0-0.359-0.001-0.129 0.002-0.303 0.003-0.478 0.003-11.952 0-22.709-5.119-30.196-13.285l-56.859-56.35 142.336-142.848 56.832 54.784c7.9 7.644 12.803 18.342 12.803 30.185 0 0.188-0.001 0.376-0.004 0.563 0.035 0.625 0.055 1.389 0.055 2.159 0 12.138-4.911 23.129-12.855 31.094zM504.32 330.752v-142.848h142.848l285.184 285.696-142.336 142.336zM805.888 544.256l-185.856-185.856c-0.834-0.338-1.802-0.535-2.816-0.535s-1.982 0.196-2.868 0.553c-0.285-0.079-0.672-0.113-1.067-0.113-3.676 0-6.656 2.98-6.656 6.656 0 0.395 0.034 0.782 0.1 1.159-0.322 0.797-0.505 1.765-0.505 2.776s0.183 1.979 0.518 2.873l188.397 183.751c0.834 0.338 1.802 0.535 2.816 0.535s1.982-0.196 2.868-0.553c0.285 0.079 0.672 0.113 1.067 0.113 3.676 0 6.656-2.98 6.656-6.656 0-0.395-0.034-0.782-0.1-1.159-0.528-1.405-1.409-2.616-2.539-3.532zM592.384 231.936v44.032h-44.032v36.864l31.232 31.232 80.384-80.384-31.232-31.232zM0 239.616h416.256v-51.2h-416.256v51.2z" /> <glyph unicode="" glyph-name="current-ref" d="M530.944 258.048l-70.144 71.68c-18.016 18.227-43.018 29.516-70.656 29.516s-52.64-11.288-70.647-29.506l-30.217 30.198c18.443 18.335 29.94 43.639 30.208 71.629-0.796 26.612-12.010 50.408-29.674 67.614l-70.677 71.701c-17.884 17.891-42.593 28.957-69.888 28.957s-52.004-11.066-69.888-28.957l-51.2-51.2c-17.891-17.884-28.957-42.593-28.957-69.888s11.066-52.004 28.957-69.888l74.24-69.632c18.016-18.227 43.018-29.516 70.656-29.516s52.64 11.288 70.647 29.506l30.217-30.198c-18.443-18.335-29.94-43.639-30.208-71.629-0.004-0.365-0.006-0.735-0.006-1.106 0-25.725 9.933-49.13 26.173-66.589l70.601-71.62c17.858-17.739 42.465-28.702 69.632-28.702s51.774 10.963 69.638 28.707l51.194 51.195c18.015 17.826 29.171 42.554 29.171 69.888s-11.156 52.062-29.163 69.88zM241.152 404.992c-11.264 11.264-20.992 24.576-38.4 24.576-18.097 0-32.768-14.671-32.768-32.768 0-17.408 13.312-27.136 24.576-38.4-5.932-6.614-14.505-10.756-24.046-10.756-0.186 0-0.372 0.002-0.558 0.005-0.198-0.006-0.465-0.009-0.732-0.009-8.862 0-16.902 3.518-22.8 9.233l-71.159 71.672c-5.852 5.917-9.468 14.056-9.468 23.040s3.615 17.123 9.471 23.043l51.197 51.197c6.111 5.71 14.344 9.216 23.396 9.216 0.055 0 0.11 0 0.164 0 0.003 0 0.017 0 0.031 0 9.18 0 17.492-3.717 23.513-9.728l69.632-72.192c6.346-6.071 10.291-14.607 10.291-24.064s-3.945-17.993-10.279-24.052zM493.568 188.416c-0.074-9.019-3.78-17.157-9.725-23.037l-51.203-51.203c-5.968-5.407-13.923-8.716-22.652-8.716-0.317 0-0.632 0.004-0.947 0.013-0.18-0.007-0.447-0.010-0.714-0.010-8.862 0-16.902 3.518-22.8 9.233l-69.111 72.184c-6.346 6.071-10.291 14.607-10.291 24.064s3.945 17.993 10.279 24.052c11.276-11.252 21.004-24.564 38.412-24.564 0.612-0.041 1.328-0.064 2.048-0.064 18.097 0 32.768 14.671 32.768 32.768 0 0.023 0 0.045 0 0.068 0 17.404-13.312 27.132-24.576 38.396 5.719 7.519 14.538 12.425 24.517 12.798 0.070 0.002 0.084 0.002 0.098 0.002 9.18 0 17.492-3.717 23.513-9.728l71.168-71.168c6.006-5.864 9.731-14.041 9.731-23.089 0-0.163-0.001-0.325-0.004-0.488zM1013.76 794.624l-51.2 51.2c-6.51 6.641-15.574 10.757-25.6 10.757s-19.090-4.116-25.594-10.751l-245.766-244.23-108.032 108.544c-6.51 6.641-15.574 10.757-25.6 10.757s-19.090-4.116-25.594-10.751l-51.206-51.206c-6.641-6.51-10.757-15.574-10.757-25.6s4.116-19.090 10.751-25.594l135.686-134.15 51.2-51.2c6.51-6.641 15.574-10.757 25.6-10.757s19.090 4.116 25.594 10.751l51.206 51.206 269.312 270.336c6.641 6.51 10.757 15.574 10.757 25.6s-4.116 19.090-10.751 25.594z" /> +======= +<glyph unicode="" glyph-name="preparing" d="M1011.173 614.391l-80.38 80.38c-7.765 8.206-18.731 13.312-30.889 13.312-0.12 0-0.239 0-0.359-0.001-0.129 0.002-0.303 0.003-0.478 0.003-11.951 0-22.708-5.119-30.194-13.284l-56.856-56.347 142.328-142.84 56.829 54.781c7.9 7.644 12.802 18.341 12.802 30.183 0 0.188-0.001 0.376-0.004 0.563 0.035 0.625 0.055 1.389 0.055 2.159 0 12.137-4.911 23.128-12.854 31.092zM504.32 330.758v-142.84h142.84l285.17 285.681-142.328 142.328zM805.872 544.251l-185.847-185.847c-0.834-0.338-1.802-0.535-2.816-0.535s-1.982 0.196-2.868 0.553c-0.285-0.079-0.672-0.113-1.067-0.113-3.676 0-6.656 2.98-6.656 6.656 0 0.395 0.034 0.782 0.1 1.159-0.322 0.797-0.505 1.765-0.505 2.776s0.183 1.979 0.518 2.873l188.387 183.741c0.834 0.338 1.802 0.535 2.816 0.535s1.982-0.196 2.868-0.553c0.285 0.079 0.672 0.113 1.067 0.113 3.676 0 6.656-2.98 6.656-6.656 0-0.395-0.034-0.782-0.1-1.159-0.528-1.405-1.409-2.616-2.539-3.532zM592.38 231.948v44.030h-44.030v36.862l31.23 31.23 80.38-80.38-31.23-31.23zM0.028 239.627h416.234v-51.197h-416.234v51.197z" /> +<glyph unicode="" glyph-name="current-ref" d="M530.92 258.291l-70.054 71.588c-17.993 18.204-42.963 29.478-70.566 29.478s-52.573-11.274-70.557-29.468l-30.178 30.159c18.419 18.312 29.902 43.583 30.169 71.537-0.795 26.578-11.995 50.343-29.636 67.527l-70.586 71.609c-17.861 17.868-42.538 28.92-69.798 28.92s-51.937-11.052-69.798-28.92l-51.134-51.134c-17.868-17.861-28.92-42.538-28.92-69.798s11.052-51.937 28.92-69.798l74.145-69.543c17.993-18.204 42.963-29.478 70.566-29.478s52.573 11.274 70.557 29.468l30.178-30.159c-18.419-18.312-29.902-43.583-30.169-71.537-0.004-0.365-0.006-0.734-0.006-1.105 0-25.692 9.92-49.067 26.139-66.504l70.511-71.528c17.835-17.716 42.411-28.665 69.543-28.665s51.708 10.949 69.549 28.67l51.128 51.129c17.992 17.803 29.134 42.5 29.134 69.798s-11.142 51.995-29.126 69.791zM241.499 405.047c-11.25 11.25-20.965 24.545-38.351 24.545-18.074 0-32.726-14.652-32.726-32.726 0-17.386 13.295-27.101 24.545-38.351-5.924-6.606-14.486-10.742-24.015-10.742-0.186 0-0.372 0.002-0.557 0.005-0.198-0.006-0.464-0.009-0.731-0.009-8.851 0-16.88 3.513-22.771 9.221l-71.068 71.58c-5.845 5.909-9.456 14.038-9.456 23.010s3.61 17.101 9.459 23.013l51.131 51.131c6.103 5.703 14.326 9.204 23.366 9.204 0.055 0 0.11 0 0.164 0 0.003 0 0.017 0 0.031 0 9.168 0 17.47-3.712 23.483-9.716l69.543-72.1c6.338-6.063 10.278-14.588 10.278-24.033s-3.94-17.97-10.266-24.021zM493.592 188.748c-0.074-9.007-3.775-17.135-9.713-23.007l-51.137-51.137c-5.96-5.4-13.905-8.705-22.623-8.705-0.317 0-0.631 0.004-0.946 0.013-0.18-0.007-0.446-0.010-0.713-0.010-8.851 0-16.88 3.513-22.771 9.221l-69.022 72.092c-6.338 6.063-10.278 14.588-10.278 24.033s3.94 17.97 10.266 24.021c11.262-11.238 20.977-24.533 38.363-24.533 0.611-0.041 1.326-0.064 2.045-0.064 18.074 0 32.726 14.652 32.726 32.726 0 0.023 0 0.045 0 0.068 0 17.382-13.295 27.097-24.545 38.347 5.712 7.509 14.519 12.409 24.486 12.782 0.070 0.002 0.084 0.002 0.098 0.002 9.168 0 17.47-3.712 23.483-9.716l71.077-71.077c5.998-5.856 9.719-14.023 9.719-23.059 0-0.163-0.001-0.325-0.004-0.487zM1013.117 794.18l-51.134 51.134c-6.502 6.632-15.554 10.743-25.567 10.743s-19.066-4.111-25.561-10.737l-245.451-243.917-107.894 108.405c-6.502 6.632-15.554 10.743-25.567 10.743s-19.066-4.111-25.561-10.737l-51.14-51.14c-6.632-6.502-10.743-15.554-10.743-25.567s4.111-19.066 10.737-25.561l135.512-133.978 51.134-51.134c6.502-6.632 15.554-10.743 25.567-10.743s19.066 4.111 25.561 10.737l51.14 51.14 268.967 269.99c6.632 6.502 10.743 15.554 10.743 25.567s-4.111 19.066-10.737 25.561z" /> +<glyph unicode="" glyph-name="chrono" horiz-adv-x="931" d="M440.957-64c243.751 0 440.957 196.267 440.957 438.857 0 225.524-171.483 412.038-391.962 436.419v51.2h73.493v97.524h-244.976v-97.524h73.493v-51.2c-220.478-24.381-391.962-209.676-391.962-436.419 0-242.59 197.206-438.857 440.957-438.857zM756.974 864.917l-71.043-70.705c71.043-41.448 131.062-101.181 172.708-171.886l71.055 70.705c-44.108 69.486-104.115 128-172.72 171.886z" /> +>>>>>>> master </font></defs></svg>
\ No newline at end of file diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/actions/index.js b/app/assets/javascripts/es6_browserified/journey_patterns/actions/index.js index 709686f21..54d62f999 100644 --- a/app/assets/javascripts/es6_browserified/journey_patterns/actions/index.js +++ b/app/assets/javascripts/es6_browserified/journey_patterns/actions/index.js @@ -130,9 +130,10 @@ const actions = { if(next) { dispatch(next) } else { - if(json.length != window.journeyPatternsPerPage){ - dispatch(actions.updateTotalCount(window.journeyPatternsPerPage - json.length)) + if(json.length != window.currentItemsLength){ + dispatch(actions.updateTotalCount(window.currentItemsLength - json.length)) } + window.currentItemsLength = json.length dispatch(actions.receiveJourneyPatterns(json)) } } @@ -196,6 +197,7 @@ const actions = { }) } } + window.currentItemsLength = journeyPatterns.length dispatch(actions.receiveJourneyPatterns(journeyPatterns)) } }) diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/components/CreateModal.js b/app/assets/javascripts/es6_browserified/journey_patterns/components/CreateModal.js index 573ebf228..aa2d208df 100644 --- a/app/assets/javascripts/es6_browserified/journey_patterns/components/CreateModal.js +++ b/app/assets/javascripts/es6_browserified/journey_patterns/components/CreateModal.js @@ -17,7 +17,7 @@ class CreateModal extends Component { } render() { - if(this.props.status.isFetching == true) { + if(this.props.status.isFetching == true || this.props.status.policy['journey_patterns.edit'] == false) { return false } if(this.props.status.fetchSuccess == true) { diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js b/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js index 3dae38d74..d9f6d5550 100644 --- a/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js +++ b/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js @@ -14,7 +14,7 @@ class JourneyPattern extends Component{ let vjURL = routeURL + '/vehicle_journeys?jp=' + jpOid return ( - <a href={vjURL}>Horaires des courses</a> + <a data-no-turbolink="true" href={vjURL}>Horaires des courses</a> ) } @@ -34,7 +34,7 @@ class JourneyPattern extends Component{ type='checkbox' id={sp.id} checked={sp.checked} - disabled={this.props.value.deletable ? 'disabled' : ''} + disabled={(this.props.value.deletable || this.props.status.policy['journey_patterns.edit'] == false) ? 'disabled' : ''} > </input> <span className='radio-label'></span> @@ -74,29 +74,30 @@ class JourneyPattern extends Component{ <span className='fa fa-cog'></span> </div> <ul className='dropdown-menu'> - <li className={this.props.value.deletable ? 'disabled' : ''}> - <a - href='#' + <li className={(this.props.value.deletable || this.props.status.policy['journey_patterns.edit'] == false) ? 'disabled' : ''}> + <button + type='button' onClick={this.props.onOpenEditModal} data-toggle='modal' data-target='#JourneyPatternModal' > Editer - </a> + </button> </li> <li className={this.props.value.object_id ? '' : 'disabled'}> {this.vehicleJourneyURL(this.props.value.object_id)} </li> - <li className='delete-action'> - <a - href='#' + <li className={'delete-action' + ((this.props.status.policy['journey_patterns.edit'] == false)? ' disabled' : '')}> + <button + type='button' + disabled={(this.props.status.policy['journey_patterns.edit'] == false)? 'disabled' : ''} onClick={(e) => { e.preventDefault() this.props.onDeleteJourneyPattern(this.props.index)} } > - <span className='fa fa-trash'></span>Supprimer - </a> + <span className='fa fa-trash'></span>Supprimer + </button> </li> </ul> </div> diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPatterns.js b/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPatterns.js index 37a0a5126..e0557d651 100644 --- a/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPatterns.js +++ b/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPatterns.js @@ -116,6 +116,7 @@ class JourneyPatterns extends Component{ onCheckboxChange= {(e) => this.props.onCheckboxChange(e, index)} onOpenEditModal= {() => this.props.onOpenEditModal(index, journeyPattern)} onDeleteJourneyPattern={() => this.props.onDeleteJourneyPattern(index)} + status= {this.props.status} /> )} </div> diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/components/Navigate.js b/app/assets/javascripts/es6_browserified/journey_patterns/components/Navigate.js index 3ca860e2e..5747aa5ce 100644 --- a/app/assets/javascripts/es6_browserified/journey_patterns/components/Navigate.js +++ b/app/assets/javascripts/es6_browserified/journey_patterns/components/Navigate.js @@ -31,7 +31,7 @@ let Navigate = ({ dispatch, journeyPatterns, pagination, status }) => { data-toggle='' data-target='#ConfirmModal' className={'previous_page' + (pagination.page == firstPage ? ' disabled' : '')} - disabled={'previous_page' + (pagination.page == firstPage ? ' disabled' : '')} + disabled={(pagination.page == firstPage ? ' disabled' : '')} > </button> <button @@ -43,7 +43,7 @@ let Navigate = ({ dispatch, journeyPatterns, pagination, status }) => { data-toggle='' data-target='#ConfirmModal' className={'next_page' + (pagination.page == lastPage ? ' disabled' : '')} - disabled={'next_page' + (pagination.page == lastPage ? ' disabled' : '')} + disabled={(pagination.page == lastPage ? 'disabled' : '')} > </button> </form> diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/components/SaveJourneyPattern.js b/app/assets/javascripts/es6_browserified/journey_patterns/components/SaveJourneyPattern.js index 6e09430a0..93dfa8c6b 100644 --- a/app/assets/javascripts/es6_browserified/journey_patterns/components/SaveJourneyPattern.js +++ b/app/assets/javascripts/es6_browserified/journey_patterns/components/SaveJourneyPattern.js @@ -15,7 +15,7 @@ class SaveJourneyPattern extends Component{ } render() { - if(this.props.status.isFetching == true) { + if(this.props.status.isFetching == true || (this.props.status.policy['journey_patterns.edit'] == false)) { return false } if(this.props.status.fetchSuccess == true) { diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/index.js b/app/assets/javascripts/es6_browserified/journey_patterns/index.js index a2e1c2fb6..b06957e0f 100644 --- a/app/assets/javascripts/es6_browserified/journey_patterns/index.js +++ b/app/assets/javascripts/es6_browserified/journey_patterns/index.js @@ -13,6 +13,7 @@ var App = require('./components/App') var initialState = { status: { + policy: window.perms, fetchSuccess: true, isFetching: false }, diff --git a/app/assets/javascripts/es6_browserified/time_tables/actions/index.js b/app/assets/javascripts/es6_browserified/time_tables/actions/index.js new file mode 100644 index 000000000..a9fbb94cf --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/actions/index.js @@ -0,0 +1,195 @@ +const _ = require('lodash') + +const actions = { + strToArrayDayTypes: (str) =>{ + let weekDays = ['Di', 'Lu', 'Ma', 'Me', 'Je', 'Ve', 'Sa'] + return weekDays.map((day, i) => str.indexOf(day) !== -1) + }, + + fetchingApi: () =>({ + type: 'FETCH_API' + }), + unavailableServer: () => ({ + type: 'UNAVAILABLE_SERVER' + }), + receiveMonth: (json) => ({ + type: 'RECEIVE_MONTH', + json + }), + receiveTimeTables: (json) => ({ + type: 'RECEIVE_TIME_TABLES', + json + }), + goToPreviousPage : (dispatch, pagination) => ({ + type: 'GO_TO_PREVIOUS_PAGE', + dispatch, + pagination, + nextPage : false + }), + goToNextPage : (dispatch, pagination) => ({ + type: 'GO_TO_NEXT_PAGE', + dispatch, + pagination, + nextPage : true + }), + changePage : (dispatch, pagination, val) => ({ + type: 'CHANGE_PAGE', + dispatch, + page: val + }), + updateDayTypes: (index) => ({ + type: 'UPDATE_DAY_TYPES', + index + }), + updateComment: (comment) => ({ + type: 'UPDATE_COMMENT', + comment + }), + updateColor: (color) => ({ + type: 'UPDATE_COLOR', + color + }), + select2Tags: (selectedTag) => ({ + type: 'UPDATE_SELECT_TAG', + selectedItem: { + id: selectedTag.id, + name: selectedTag.name + } + }), + unselect2Tags: (selectedTag) => ({ + type: 'UPDATE_UNSELECT_TAG', + selectedItem: { + id: selectedTag.id, + name: selectedTag.name + } + }), + deletePeriod: (index, dayTypes) => ({ + type: 'DELETE_PERIOD', + index, + dayTypes + }), + openAddPeriodForm: () => ({ + type: 'OPEN_ADD_PERIOD_FORM' + }), + openEditPeriodForm: (period, index) => ({ + type: 'OPEN_EDIT_PERIOD_FORM', + period, + index + }), + closePeriodForm: () => ({ + type: 'CLOSE_PERIOD_FORM' + }), + updatePeriodForm: (val, group, selectType) => ({ + type: 'UPDATE_PERIOD_FORM', + val, + group, + selectType + }), + includeDateInPeriod: (index, day, dayTypes) => ({ + type: 'INCLUDE_DATE_IN_PERIOD', + index, + day, + dayTypes + }), + excludeDateFromPeriod: (index, day, dayTypes) => ({ + type: 'EXCLUDE_DATE_FROM_PERIOD', + index, + day, + dayTypes + }), + + monthName(strDate) { + let monthList = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"] + var date = new Date(strDate) + return monthList[date.getMonth()] + }, + getHumanDate(strDate, mLimit) { + let origin = strDate.split('-') + let D = origin[2] + let M = actions.monthName(strDate).toLowerCase() + let Y = origin[0] + + if(mLimit && M.length > mLimit) { + M = M.substr(0, mLimit) + '.' + } + + return (D + ' ' + M + ' ' + Y) + }, + + updateSynthesis: (state, daytypes) => { + let periods = state.time_table_periods + + let isInPeriod = function(d){ + let currentMonth = state.current_periode_range.split('-') + let twodigitsDay = d.mday < 10 ? ('0' + d.mday) : d.mday + let currentDate = new Date(currentMonth[0] + '-' + currentMonth[1] + '-' + twodigitsDay) + + // We compare periods & currentDate, to determine if it is included or not + let testDate = false + periods.map((p, i) => { + if(p.deleted){ + return false + } + let begin = new Date(p.period_start) + let end = new Date(p.period_end) + + if(testDate === false){ + if(currentDate >= begin && currentDate <= end) { + if(daytypes[d.wday] === false) { + testDate = false + } else { + testDate = true + } + } + } + }) + return testDate + } + + let improvedCM = state.current_month.map((d, i) => { + return _.assign({}, state.current_month[i], { + in_periods: isInPeriod(state.current_month[i]) + }) + }) + return improvedCM + }, + + checkConfirmModal: (event, callback, stateChanged,dispatch) => { + if(stateChanged === true){ + return actions.openConfirmModal(callback) + }else{ + dispatch(actions.fetchingApi()) + return callback + } + }, + fetchTimeTables: (dispatch, nextPage) => { + let urlJSON = window.location.pathname.split('/', 5).join('/') + // console.log(nextPage) + if(nextPage) { + urlJSON += "/month.json?date=" + nextPage + }else{ + urlJSON += ".json" + } + let hasError = false + fetch(urlJSON, { + credentials: 'same-origin', + }).then(response => { + if(response.status == 500) { + hasError = true + } + return response.json() + }).then((json) => { + if(hasError == true) { + dispatch(actions.unavailableServer()) + } else { + if(nextPage){ + dispatch(actions.receiveMonth(json)) + }else{ + dispatch(actions.receiveTimeTables(json)) + } + } + }) + }, +} + +module.exports = actions diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js b/app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js new file mode 100644 index 000000000..13615a6ef --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js @@ -0,0 +1,65 @@ +var React = require('react') +var Component = require('react').Component +var PropTypes = require('react').PropTypes +var actions = require('../actions') + +class ExceptionsInDay extends Component { + constructor(props) { + super(props) + } + + render() { + {/* display add or remove link, only if true in daytypes */} + if(this.props.outFromDaytypes == true) { + {/* display add or remove link, according to context (presence in period, or not) */} + if(this.props.value.current_month[this.props.index].in_periods == true) { + return ( + <div className='td'> + <button + type='button' + className='btn btn-circle' + data-actiontype='remove' + onClick={(e) => { + $(e.currentTarget).toggleClass('active') + this.props.onExcludeDateFromPeriod(this.props.index, this.props.value.current_month[this.props.index], this.props.metas.day_types) + }} + > + <span className='fa fa-times'></span> + </button> + </div> + ) + } else { + return ( + <div className='td'> + <button + type='button' + className='btn btn-circle' + data-actiontype='add' + onClick={(e) => { + $(e.currentTarget).toggleClass('active') + this.props.onIncludeDateInPeriod(this.props.index, this.props.value.current_month[this.props.index], this.props.metas.day_types) + }} + > + <span className='fa fa-plus'></span> + </button> + </div> + ) + } + } else { + return ( + <div className='td'></div> + ) + } + } +} + +ExceptionsInDay.propTypes = { + value: PropTypes.object.isRequired, + metas: PropTypes.object.isRequired, + outFromDaytypes: PropTypes.bool.isRequired, + onExcludeDateFromPeriod: PropTypes.func.isRequired, + onIncludeDateInPeriod: PropTypes.func.isRequired, + index: PropTypes.number.isRequired +} + +module.exports = ExceptionsInDay diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/Metas.js b/app/assets/javascripts/es6_browserified/time_tables/components/Metas.js new file mode 100644 index 000000000..943b781f5 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/components/Metas.js @@ -0,0 +1,139 @@ +var React = require('react') +var PropTypes = require('react').PropTypes +let weekDays = ['D', 'L', 'Ma', 'Me', 'J', 'V', 'S'] +var TagsSelect2 = require('./TagsSelect2') + +const Metas = ({metas, onUpdateDayTypes, onUpdateComment, onUpdateColor, onSelect2Tags, onUnselect2Tags}) => { + let colorList = ["", "#9B9B9B", "#FFA070", "#C67300", "#7F551B", "#41CCE3", "#09B09C", "#3655D7", "#6321A0", "#E796C6", "#DD2DAA"] + return ( + <div className="row"> + <div className="col-lg-6 col-lg-offset-3 col-md-8 col-md-offset-2 col-sm-10 col-sm-offset-1"> + <div className='form-horizontal'> + <div className="row"> + <div className="col-lg-12"> + {/* comment (name) */} + <div className="form-group"> + <label htmlFor="" className="control-label col-sm-4 required"> + Nom <abbr title="Champ requis">*</abbr> + </label> + <div className="col-sm-8"> + <input + type='text' + className='form-control' + value={metas.comment} + onChange={(e) => (onUpdateComment(e.currentTarget.value))} + /> + </div> + </div> + + {/* color */} + <div className="form-group"> + <label htmlFor="" className="control-label col-sm-4">Couleur associée</label> + <div className="col-sm-8"> + <div className="dropdown color_selector"> + <button + type='button' + className="btn btn-default dropdown-toggle" + id='dpdwn_color' + data-toggle='dropdown' + aria-haspopup='true' + aria-expanded='true' + > + <span + className='fa fa-circle mr-xs' + style={{color: (metas.color == '') ? 'transparent' : metas.color}} + ></span> + <span className='caret'></span> + </button> + + <div className="form-group dropdown-menu" aria-labelledby='dpdwn_color'> + {colorList.map((c, i) => + <span + className="radio" + key={i} + onClick={() => {onUpdateColor(c)}} + > + <label htmlFor=""> + <input + type='radio' + className='color_selector' + value={c} + /> + <span + className='fa fa-circle' + style={{color: ((c == '') ? 'transparent' : c)}} + ></span> + </label> + </span> + )} + </div> + </div> + </div> + </div> + + {/* tags */} + {/* <div className="form-group"> + <label htmlFor="" className="control-label col-sm-4">Etiquettes</label> + <div className="col-sm-8"> + <TagsSelect2 + tags={metas.tags} + onSelect2Tags={(e) => onSelect2Tags(e)} + onUnselect2Tags={(e) => onUnselect2Tags(e)} + /> + <input type="text" value='ton papa' className='form-control'/> + </div> + </div> + */} + + {/* calendar */} + <div className="form-group"> + <label htmlFor="" className="control-label col-sm-4">Modèle de calendrier associé</label> + <div className="col-sm-8"> + <span>{metas.calendar.name}</span> + </div> + </div> + {/* day_types */} + <div className="form-group"> + <label htmlFor="" className="control-label col-sm-4"> + Journées d'applications pour les périodes ci-dessous + </label> + <div className="col-sm-8"> + <div className="form-group labelled-checkbox-group"> + {metas.day_types.map((day, i) => + <div className="lcbx-group-item" + key={i} + > + <div className="checkbox"> + <label> + <input + onChange={(e) => {onUpdateDayTypes(i)}} + id={i} + type="checkbox" + checked={day ? 'checked' : ''} + /> + <span className='lcbx-group-item-label'>{weekDays[i]}</span> + </label> + </div> + </div> + )} + </div> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + ) +} + +Metas.propTypes = { + metas: PropTypes.object.isRequired, + onUpdateDayTypes: PropTypes.func.isRequired, + onUpdateColor: PropTypes.func.isRequired, + onUpdateColor: PropTypes.func.isRequired, + onSelect2Tags: PropTypes.func.isRequired, + onUnselect2Tags: PropTypes.func.isRequired +} + +module.exports = Metas diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/Navigate.js b/app/assets/javascripts/es6_browserified/time_tables/components/Navigate.js new file mode 100644 index 000000000..5db373f9c --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/components/Navigate.js @@ -0,0 +1,96 @@ +var React = require('react') +var Component = require('react').Component +var PropTypes = require('react').PropTypes +var actions = require('../actions') +var _ = require('lodash') + +let Navigate = ({ dispatch, metas, timetable, pagination, status, filters}) => { + if(status.isFetching == true) { + return false + } + if(status.fetchSuccess == true) { + let pageIndex = pagination.periode_range.indexOf(pagination.currentPage) + let firstPage = pageIndex == 0 + let lastPage = pageIndex == pagination.periode_range.length - 1 + return ( + <div className="row mt-md"> + <div className="col-lg-8 col-lg-offset-2 col-md-8 col-md-offset-2 col-sm-10 col-sm-offset-1 text-right"> + <div className="pagination"> + <form className='form-inline' onSubmit={e => {e.preventDefault()}}> + {/* date selector */} + <div className="form-group"> + <div className="dropdown month_selector" style={{display: 'inline-block'}}> + <div + className='btn btn-default dropdown-toggle' + id='date_selector' + data-toggle='dropdown' + aria-haspopup='true' + aria-expanded='true' + > + {pagination.currentPage ? (actions.monthName(pagination.currentPage) + ' ' + new Date(pagination.currentPage).getFullYear()) : ''} + <span className='caret'></span> + </div> + <ul + className='dropdown-menu' + aria-labelledby='date_selector' + > + {_.map(pagination.periode_range, (month, i) => ( + <li key={i}> + <button + type='button' + value={month} + onClick={e => { + e.preventDefault() + dispatch(actions.checkConfirmModal(e, actions.changePage(dispatch, pagination, e.currentTarget.value), pagination.stateChanged, dispatch)) + }} + > + {actions.monthName(month) + ' ' + new Date(month).getFullYear()} + </button> + </li> + ))} + </ul> + </div> + </div> + + {/* prev/next */} + <div className="form-group"> + <div className="page_links"> + <button + onClick={e => { + e.preventDefault() + dispatch(actions.checkConfirmModal(e, actions.goToPreviousPage(dispatch, pagination), pagination.stateChanged, dispatch)) + }} + type='button' + data-target='#ConfirmModal' + className={(firstPage ? 'disabled ' : '') + 'previous_page'} + disabled={(firstPage ? 'disabled' : '')} + ></button> + <button + onClick={e => { + e.preventDefault() + dispatch(actions.checkConfirmModal(e, actions.goToNextPage(dispatch, pagination), pagination.stateChanged, dispatch)) + }} + type='button' + data-target='#ConfirmModal' + className={(lastPage ? 'disabled ' : '') + 'next_page'} + disabled={(lastPage ? 'disabled' : '')} + ></button> + </div> + </div> + </form> + </div> + </div> + </div> + ) + } else { + return false + } +} + +Navigate.propTypes = { + status: PropTypes.object.isRequired, + pagination: PropTypes.object.isRequired, + dispatch: PropTypes.func.isRequired +} + +module.exports = Navigate diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js new file mode 100644 index 000000000..274429af8 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js @@ -0,0 +1,90 @@ +var React = require('react') +var PropTypes = require('react').PropTypes +let monthsArray = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'] + +const formatNumber = (val) => { + return ("0" + val).slice(-2) +} + +const makeDaysOptions = (daySelected) => { + let arr = [] + for(let i = 1; i < 32; i++) { + arr.push(<option value={formatNumber(i)} key={i}>{formatNumber(i)}</option>) + } + return arr +} + +const makeMonthsOptions = (monthSelected) => { + let arr = [] + for(let i = 1; i < 13; i++) { + arr.push(<option value={formatNumber(i)} key={i}>{monthsArray[i - 1]}</option>) + } + return arr +} + +const makeYearsOptions = (yearSelected) => { + let arr = [] + let startYear = new Date().getFullYear() - 3 + for(let i = startYear; i <= startYear + 6; i++) { + arr.push(<option key={i}>{i}</option>) + } + return arr +} + +const PeriodForm = ({modal, timetable, onOpenAddPeriodForm, onClosePeriodForm, onUpdatePeriodForm}) => ( + <div> + {modal.modalProps.active && + <div className="form-group date filter_menu-item"> + <label className="date required control-label" >Du <abbr title="Champ requis">*</abbr></label> + <div className="form-inline"> + <select value={formatNumber(modal.modalProps.begin.day)} onChange={(e) => onUpdatePeriodForm(e.currentTarget.value, 'begin', 'day')} id="q_validity_period_begin_gteq_3i" className="date required form-control"> + {makeDaysOptions(modal.modalProps.begin.day)} + </select> + <select value={formatNumber(modal.modalProps.begin.month)} onChange={(e) => onUpdatePeriodForm(e.currentTarget.value, 'begin', 'month')} id="q_validity_period_begin_gteq_2i" className="date required form-control"> + {makeMonthsOptions(modal.modalProps.begin.month)} + </select> + <select value={modal.modalProps.begin.year} onChange={(e) => onUpdatePeriodForm(e.currentTarget.value, 'begin', 'year')} id="q_validity_period_begin_gteq_1i" className="date required form-control"> + {makeYearsOptions(modal.modalProps.begin.year)} + </select> + </div> + <label className="date required control-label" >Au <abbr title="Champ requis">*</abbr></label> + <div className="form-inline"> + <select value={formatNumber(modal.modalProps.end.day)} onChange={(e) => onUpdatePeriodForm(e.currentTarget.value, 'end', 'day')} id="q_validity_period_end_gteq_3i" className="date required form-control"> + {makeDaysOptions(modal.modalProps.end.day)} + </select> + <select value={formatNumber(modal.modalProps.end.month)} onChange={(e) => onUpdatePeriodForm(e.currentTarget.value, 'end', 'month')} id="q_validity_period_end_gteq_2i" className="date required form-control"> + {makeMonthsOptions(modal.modalProps.end.month)} + </select> + <select value={modal.modalProps.end.year} onChange={(e) => onUpdatePeriodForm(e.currentTarget.value, 'end', 'year')} id="q_validity_period_end_gteq_1i" className="date required form-control"> + {makeYearsOptions(modal.modalProps.end.year)} + </select> + </div> + <div> + <button + onClick={onClosePeriodForm} + > + Annuler + </button> + <button>Valider</button> + </div> + </div> + } + {!modal.modalProps.active && + <button + onClick={onOpenAddPeriodForm} + > + Ajouter une période + </button> + } + </div> +) + +PeriodForm.propTypes = { + modal: PropTypes.object.isRequired, + onOpenAddPeriodForm: PropTypes.func.isRequired, + onClosePeriodForm: PropTypes.func.isRequired, + onUpdatePeriodForm: PropTypes.func.isRequired, + timetable: PropTypes.object.isRequired +} + +module.exports = PeriodForm diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js new file mode 100644 index 000000000..de3f31ee0 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js @@ -0,0 +1,65 @@ +var React = require('react') +var Component = require('react').Component +var PropTypes = require('react').PropTypes +var actions = require('../actions') + +class PeriodManager extends Component { + constructor(props) { + super(props) + } + + render() { + return ( + <div + className='period_manager' + id={this.props.value.id} + > + <p className='strong'> + {actions.getHumanDate(this.props.value.period_start, 3).substr(0, 7) + ' > ' + actions.getHumanDate(this.props.value.period_end, 3)} + </p> + + <div className='dropdown'> + <div + className='btn dropdown-toggle' + id='period_actions' + data-toggle='dropdown' + aria-haspopup='true' + aria-expanded='true' + > + <span className='fa fa-cog'></span> + </div> + <ul + className='dropdown-menu' + aria-labelledby='date_selector' + > + <li> + <button + type='button' + onClick={() => this.props.onOpenEditPeriodForm(this.props.value, this.props.index)} + > + Modifier + </button> + </li> + <li className='delete-action'> + <button + type='button' + onClick={() => this.props.onDeletePeriod(this.props.index, this.props.metas.day_types)} + > + <span className='fa fa-trash'></span> + Supprimer + </button> + </li> + </ul> + </div> + </div> + ) + } +} + +PeriodManager.propTypes = { + value: PropTypes.object.isRequired, + onDeletePeriod: PropTypes.func.isRequired, + onOpenEditPeriodForm: PropTypes.func.isRequired +} + +module.exports = PeriodManager diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodsInDay.js b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodsInDay.js new file mode 100644 index 000000000..93a8fe433 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodsInDay.js @@ -0,0 +1,78 @@ +var React = require('react') +var Component = require('react').Component +var PropTypes = require('react').PropTypes +var PeriodManager = require('./PeriodManager') + +class PeriodsInDay extends Component { + constructor(props) { + super(props) + } + + isIn(date) { + let currentDate = date.getTime() + let cls = 'td' + let periods = this.props.value + + periods.map((p, i) => { + if (!p.deleted){ + let begin = new Date(p.period_start).getTime() + let end = new Date(p.period_end).getTime() + + if(currentDate >= begin && currentDate <= end) { + if(currentDate == begin) { + cls += ' in_periods start_period' + } else if(currentDate == end) { + cls += ' in_periods end_period' + } else { + cls += ' in_periods' + } + } + } + }) + return cls + } + + render() { + return ( + <div + className={this.isIn(this.props.currentDate)} + > + {this.props.value.map((p, i) => { + if(!p.deleted){ + let begin = new Date(p.period_start).getTime() + let end = new Date(p.period_end).getTime() + let d = this.props.currentDate.getTime() + + if(d >= begin && d <= end) { + if(d == begin || (this.props.currentDate.getUTCDate() == 1)) { + return ( + <PeriodManager + key={i} + index={i} + value={p} + onDeletePeriod={this.props.onDeletePeriod} + onOpenEditPeriodForm={this.props.onOpenEditPeriodForm} + metas={this.props.metas} + /> + ) + } else { + return false + } + } + }else{ + return false + } + })} + </div> + ) + } +} + +PeriodsInDay.propTypes = { + value: PropTypes.array.isRequired, + currentDate: PropTypes.object.isRequired, + index: PropTypes.number.isRequired, + onDeletePeriod: PropTypes.func.isRequired +} + +module.exports = PeriodsInDay diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/TagsSelect2.js b/app/assets/javascripts/es6_browserified/time_tables/components/TagsSelect2.js new file mode 100644 index 000000000..16ebc250a --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/components/TagsSelect2.js @@ -0,0 +1,73 @@ +var _ = require('lodash') +var React = require('react') +var PropTypes = require('react').PropTypes +var Select2 = require('react-select2') + +// get JSON full path +var origin = window.location.origin +var path = window.location.pathname.split('/', 4).join('/') +var _ = require('lodash') + +class TagsSelect2 extends React.Component{ + constructor(props) { + super(props) + } + + mapKeys(array){ + return array.map((item) => + _.mapKeys(item, (v, k) => + ((k == 'name') ? 'text' : k) + ) + ) + } + + render() { + return ( + <Select2 + value={(this.props.tags.length) ? _.map(this.props.tags, 'id') : undefined} + data={(this.props.tags.length) ? this.mapKeys(this.props.tags) : undefined} + onSelect={(e) => this.props.onSelect2Tags(e)} + onUnselect={(e) => setTimeout( () => this.props.onUnselect2Tags(e, 150))} + multiple={true} + ref='tags_id' + options={{ + allowClear: true, + theme: 'bootstrap', + width: '100%', + placeholder: 'Cherchez un tag...', + ajax: { + url: origin + path + '/tags.json', + dataType: 'json', + delay: '500', + data: function(params) { + return { + tag: params.term, + }; + }, + processResults: function(data, params) { + + return { + results: data.map( + item => _.assign( + {}, + item, + {text: item.name} + ) + ) + }; + }, + cache: true + }, + minimumInputLength: 3, + templateResult: formatRepo + }} + /> + ) + } +} + +const formatRepo = (props) => { + if(props.name) return props.name +} + +module.exports = TagsSelect2 diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/TimeTableDay.js b/app/assets/javascripts/es6_browserified/time_tables/components/TimeTableDay.js new file mode 100644 index 000000000..29c894565 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/components/TimeTableDay.js @@ -0,0 +1,35 @@ +var React = require('react') +var Component = require('react').Component +var PropTypes = require('react').PropTypes + +class TimeTableDay extends Component { + constructor(props) { + super(props) + } + + render() { + return ( + <span + className={'day' + (this.props.value.wday == 0 ? ' last_wday' : '')} + data-wday={'S' + this.props.value.wnumber} + > + <span className='dayname'> + {((this.props.value.day).charAt(0) == 'm') ? (this.props.value.day).substr(0, 2) : (this.props.value.day).charAt(0)} + </span> + <span + className={'daynumber' + (((this.props.value.in_periods && this.props.dayTypeActive && !this.props.value.excluded_date) || (this.props.value.include_date && this.props.dayTypeActive)) ? ' included' : '')} + > + {this.props.value.mday} + </span> + </span> + ) + } +} + +TimeTableDay.propTypes = { + value: PropTypes.object.isRequired, + index: PropTypes.number.isRequired, + dayTypeActive: PropTypes.bool.isRequired +} + +module.exports = TimeTableDay diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js b/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js new file mode 100644 index 000000000..65aae0e11 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js @@ -0,0 +1,103 @@ +var React = require('react') +var Component = require('react').Component +var PropTypes = require('react').PropTypes +var TimeTableDay = require('./TimeTableDay') +var PeriodsInDay = require('./PeriodsInDay') +var ExceptionsInDay = require('./ExceptionsInDay') +var actions = require('../actions') + +class Timetable extends Component{ + constructor(props){ + super(props) + } + + currentDate(mFirstday, day) { + let currentMonth = mFirstday.split('-') + let twodigitsDay = day < 10 ? ('0' + day) : day + let currentDate = new Date(currentMonth[0] + '-' + currentMonth[1] + '-' + twodigitsDay) + + return currentDate + } + + render() { + return ( + <div className='row'> + <div className="col-lg-8 col-lg-offset-2 col-md-8 col-md-offset-2 col-sm-10 col-sm-offset-1"> + <div className="table table-2entries mb-sm"> + <div className="t2e-head w20"> + <div className="th"> + <div className="strong">Synthèse</div> + </div> + <div className="td"><span>Journées d'application</span></div> + <div className="td"><span>Périodes</span></div> + <div className="td"><span>Exceptions</span></div> + </div> + <div className="t2e-item-list w80"> + <div> + <div className="t2e-item"> + <div className="th"> + <div className="strong monthName"> + {actions.monthName(this.props.timetable.current_periode_range)} + </div> + + <div className='monthDays'> + {this.props.timetable.current_month.map((d, i) => + <TimeTableDay + key={i} + index={i} + value={d} + dayTypeActive={this.props.metas.day_types[d.wday]} + /> + )} + </div> + </div> + + {this.props.timetable.current_month.map((d, i) => + <div + key={i} + className={'td-group' + (this.props.metas.day_types[d.wday] ? '' : ' out_from_daytypes') + (d.wday == 0 ? ' last_wday' : '')} + > + {/* day_types */} + <div className="td"></div> + + {/* periods */} + <PeriodsInDay + index={i} + value={this.props.timetable.time_table_periods} + currentDate={this.currentDate(this.props.timetable.current_periode_range, d.mday)} + onDeletePeriod={this.props.onDeletePeriod} + onOpenEditPeriodForm={this.props.onOpenEditPeriodForm} + metas={this.props.metas} + /> + + {/* exceptions */} + <ExceptionsInDay + index={i} + value={this.props.timetable} + metas={this.props.metas} + outFromDaytypes={this.props.metas.day_types[d.wday]} + onExcludeDateFromPeriod={this.props.onExcludeDateFromPeriod} + onIncludeDateInPeriod={this.props.onIncludeDateInPeriod} + /> + </div> + )} + </div> + </div> + </div> + </div> + </div> + </div> + ) + } +} + +Timetable.propTypes = { + metas: PropTypes.object.isRequired, + timetable: PropTypes.object.isRequired, + status: PropTypes.object.isRequired, + onDeletePeriod: PropTypes.func.isRequired, + onExcludeDateFromPeriod: PropTypes.func.isRequired, + onIncludeDateInPeriod: PropTypes.func.isRequired +} + +module.exports = Timetable diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/App.js b/app/assets/javascripts/es6_browserified/time_tables/containers/App.js new file mode 100644 index 000000000..fede03aec --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/containers/App.js @@ -0,0 +1,38 @@ +var React = require('react') +var connect = require('react-redux').connect +var Component = require('react').Component +var actions = require('../actions') +var Metas = require('./Metas') +var Timetable = require('./Timetable') +var Navigate = require('./Navigate') +var PeriodForm = require('./PeriodForm') + +class App extends Component { + componentDidMount(){ + this.props.onLoadFirstPage() + } + + render(){ + return( + <div> + <Metas /> + <Navigate /> + <Timetable /> + <PeriodForm /> + </div> + ) + } +} + +const mapDispatchToProps = (dispatch) => { + return { + onLoadFirstPage: () =>{ + dispatch(actions.fetchingApi()) + actions.fetchTimeTables(dispatch) + } + } +} + +const timeTableApp = connect(null, mapDispatchToProps)(App) + +module.exports = timeTableApp diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/Metas.js b/app/assets/javascripts/es6_browserified/time_tables/containers/Metas.js new file mode 100644 index 000000000..514ed2347 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/containers/Metas.js @@ -0,0 +1,33 @@ +var actions = require('../actions') +var connect = require('react-redux').connect +var MetasComponent = require('../components/Metas') + +const mapStateToProps = (state) => { + return { + metas: state.metas + } +} + +const mapDispatchToProps = (dispatch) => { + return { + onUpdateDayTypes: (index) => { + dispatch(actions.updateDayTypes(index)) + }, + onUpdateComment: (comment) => { + dispatch(actions.updateComment(comment)) + }, + onUpdateColor: (color) => { + dispatch(actions.updateColor(color)) + }, + onSelect2Tags: (e) => { + dispatch(actions.select2Tags(e.params.data)) + }, + onUnselect2Tags: (e) => { + dispatch(actions.unselect2Tags(e.params.data)) + } + } +} + +const Metas = connect(mapStateToProps, mapDispatchToProps)(MetasComponent) + +module.exports = Metas diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/Navigate.js b/app/assets/javascripts/es6_browserified/time_tables/containers/Navigate.js new file mode 100644 index 000000000..c70583c25 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/containers/Navigate.js @@ -0,0 +1,18 @@ +var React = require('react') +var connect = require('react-redux').connect +var actions = require('../actions') +var NavigateComponent = require('../components/Navigate') + +const mapStateToProps = (state) => { + return { + metas: state.metas, + timetable: state.timetable, + status: state.status, + pagination: state.pagination + } +} + + +const Navigate = connect(mapStateToProps)(NavigateComponent) + +module.exports = Navigate diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js b/app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js new file mode 100644 index 000000000..0a785c680 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js @@ -0,0 +1,28 @@ +var connect = require('react-redux').connect +var PeriodFormComponent = require('../components/PeriodForm') +var actions = require('../actions') + +const mapStateToProps = (state) => { + return { + modal: state.modal, + timetable: state.timetable + } +} + +const mapDispatchToProps = (dispatch) => { + return { + onOpenAddPeriodForm: () => { + dispatch(actions.openAddPeriodForm()) + }, + onClosePeriodForm: () => { + dispatch(actions.closePeriodForm()) + }, + onUpdatePeriodForm: (val, group, selectType) => { + dispatch(actions.updatePeriodForm(val, group, selectType)) + } + } +} + +const PeriodForm = connect(mapStateToProps, mapDispatchToProps)(PeriodFormComponent) + +module.exports = PeriodForm diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js b/app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js new file mode 100644 index 000000000..2a17d3dea --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js @@ -0,0 +1,32 @@ +var connect = require('react-redux').connect +var TimetableComponent = require('../components/Timetable') +var actions = require('../actions') + +const mapStateToProps = (state) => { + return { + metas: state.metas, + timetable: state.timetable, + status: state.status + } +} + +const mapDispatchToProps = (dispatch) => { + return { + onDeletePeriod: (index, dayTypes) =>{ + dispatch(actions.deletePeriod(index, dayTypes)) + }, + onExcludeDateFromPeriod: (index, day, dayTypes) => { + dispatch(actions.excludeDateFromPeriod(index, day, dayTypes)) + }, + onIncludeDateInPeriod: (index, day, dayTypes) => { + dispatch(actions.includeDateInPeriod(index, day, dayTypes)) + }, + onOpenEditPeriodForm: (period, index) => { + dispatch(actions.openEditPeriodForm(period, index)) + } + } +} + +const Timetable = connect(mapStateToProps, mapDispatchToProps)(TimetableComponent) + +module.exports = Timetable diff --git a/app/assets/javascripts/es6_browserified/time_tables/index.js b/app/assets/javascripts/es6_browserified/time_tables/index.js new file mode 100644 index 000000000..69b7fdd7c --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/index.js @@ -0,0 +1,69 @@ +var React = require('react') +var render = require('react-dom').render +var Provider = require('react-redux').Provider +var createStore = require('redux').createStore +var timeTablesApp = require('./reducers') +var App = require('./containers/App') + +// 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') + +var initialState = { + status: { + policy: window.perms, + fetchSuccess: true, + isFetching: false + }, + timetable: { + current_month: [], + current_periode_range: '', + periode_range: [], + time_table_periods: [] + }, + metas: { + comment: '', + day_types: [], + tags: [], + color: '', + calendar: {} + }, + 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()) + } + }, + 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/assets/javascripts/es6_browserified/time_tables/reducers/index.js b/app/assets/javascripts/es6_browserified/time_tables/reducers/index.js new file mode 100644 index 000000000..5b05aadda --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/index.js @@ -0,0 +1,16 @@ +var combineReducers = require('redux').combineReducers +var status = require('./status') +var pagination = require('./pagination') +var modal = require('./modal') +var timetable = require('./timetable') +var metas = require('./metas') + +const timeTablesApp = combineReducers({ + timetable, + metas, + status, + pagination, + modal +}) + +module.exports = timeTablesApp diff --git a/app/assets/javascripts/es6_browserified/time_tables/reducers/metas.js b/app/assets/javascripts/es6_browserified/time_tables/reducers/metas.js new file mode 100644 index 000000000..555730908 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/metas.js @@ -0,0 +1,33 @@ +const _ = require('lodash') +const actions = require('../actions') + +const metas = (state = {}, action) => { + switch (action.type) { + case 'RECEIVE_TIME_TABLES': + return _.assign({}, state, { + comment: action.json.comment, + day_types: actions.strToArrayDayTypes(action.json.day_types), + tags: action.json.tags, + color: action.json.color, + calendar: action.json.calendar ? action.json.calendar : {name : 'Aucun'} + }) + case 'UPDATE_DAY_TYPES': + let dayTypes = state.day_types.slice(0) + dayTypes[action.index] = !dayTypes[action.index] + return _.assign({}, state, {day_types: dayTypes}) + case 'UPDATE_COMMENT': + return _.assign({}, state, {comment: action.comment}) + case 'UPDATE_COLOR': + return _.assign({}, state, {color: action.color}) + case 'UPDATE_SELECT_TAG': + let tags = [...state.tags] + tags.push(action.selectedItem) + return _.assign({}, state, {tags: tags}) + case 'UPDATE_UNSELECT_TAG': + return _.assign({}, state, {tags: _.filter(state.tags, (t) => (t.id != action.selectedItem.id))}) + default: + return state + } +} + +module.exports = metas diff --git a/app/assets/javascripts/es6_browserified/time_tables/reducers/modal.js b/app/assets/javascripts/es6_browserified/time_tables/reducers/modal.js new file mode 100644 index 000000000..e9c0c2fb9 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/modal.js @@ -0,0 +1,42 @@ +var _ = require('lodash') +let newModalProps = {} + +const modal = (state = {}, action) => { + switch (action.type) { + case 'CLOSE_PERIOD_FORM': + let emptyDate = { + begin: '', + month: '', + year: '' + } + newModalProps = _.assign({}, state.modalProps, {active: false, begin: emptyDate, end: emptyDate, index: false}) + return _.assign({}, state, {modalProps: newModalProps}) + case 'OPEN_EDIT_PERIOD_FORM': + let period_start = action.period.period_start.split('-') + let period_end = action.period.period_end.split('-') + newModalProps = JSON.parse(JSON.stringify(state.modalProps)) + + newModalProps.begin.year = period_start[0] + newModalProps.begin.month = period_start[1] + newModalProps.begin.day = period_start[2] + + newModalProps.end.year = period_end[0] + newModalProps.end.month = period_end[1] + newModalProps.end.day = period_end[2] + + newModalProps.active = true + newModalProps.index = action.index + return _.assign({}, state, {modalProps: newModalProps}) + case 'OPEN_ADD_PERIOD_FORM': + newModalProps = _.assign({}, state.modalProps, {active: true}) + return _.assign({}, state, {modalProps: newModalProps}) + case 'UPDATE_PERIOD_FORM': + newModalProps = JSON.parse(JSON.stringify(state.modalProps)) + newModalProps[action.group][action.selectType] = action.val + return _.assign({}, state, {modalProps: newModalProps}) + default: + return state + } +} + +module.exports = modal diff --git a/app/assets/javascripts/es6_browserified/time_tables/reducers/pagination.js b/app/assets/javascripts/es6_browserified/time_tables/reducers/pagination.js new file mode 100644 index 000000000..35b9b3cd8 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/pagination.js @@ -0,0 +1,30 @@ +var _ = require('lodash') + +const pagination = (state = {}, action) => { + switch (action.type) { + case 'RECEIVE_TIME_TABLES': + return _.assign({}, state, { + currentPage: action.json.current_periode_range, + periode_range: action.json.periode_range + }) + case 'GO_TO_PREVIOUS_PAGE': + case 'GO_TO_NEXT_PAGE': + let nextPage = action.nextPage ? 1 : -1 + let newPage = action.pagination.periode_range[action.pagination.periode_range.indexOf(action.pagination.currentPage) + nextPage] + toggleOnConfirmModal() + return _.assign({}, state, {currentPage : newPage, stateChanged: false}) + case 'CHANGE_PAGE': + toggleOnConfirmModal() + return _.assign({}, state, {currentPage : action.page, stateChanged: false}) + default: + return state + } +} + +const toggleOnConfirmModal = (arg = '') =>{ + $('.confirm').each(function(){ + $(this).data('toggle','') + }) +} + +module.exports = pagination diff --git a/app/assets/javascripts/es6_browserified/time_tables/reducers/status.js b/app/assets/javascripts/es6_browserified/time_tables/reducers/status.js new file mode 100644 index 000000000..fc205d0ae --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/status.js @@ -0,0 +1,17 @@ +var _ = require('lodash') + +const status = (state = {}, action) => { + switch (action.type) { + case 'UNAVAILABLE_SERVER': + return _.assign({}, state, {fetchSuccess: false}) + case 'FETCH_API': + return _.assign({}, state, {isFetching: true}) + case 'RECEIVE_TIME_TABLES': + case 'RECEIVE_MONTH': + return _.assign({}, state, {fetchSuccess: true, isFetching: false}) + default: + return state + } +} + +module.exports = status diff --git a/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js b/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js new file mode 100644 index 000000000..b052b5fcc --- /dev/null +++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js @@ -0,0 +1,63 @@ +const _ = require('lodash') +var actions = require('../actions') +let newState = {} + +const timetable = (state = {}, action) => { + switch (action.type) { + case 'RECEIVE_TIME_TABLES': + let fetchedState = _.assign({}, state, { + current_month: action.json.current_month, + current_periode_range: action.json.current_periode_range, + periode_range: action.json.periode_range, + time_table_periods: action.json.time_table_periods + }) + return _.assign({}, fetchedState, {current_month: actions.updateSynthesis(fetchedState, actions.strToArrayDayTypes(action.json.day_types))}) + case 'RECEIVE_MONTH': + newState = _.assign({}, state, { + current_month: action.json.days + }) + return _.assign({}, newState, {current_month: actions.updateSynthesis(newState, actions.strToArrayDayTypes(action.json.day_types))}) + case 'GO_TO_PREVIOUS_PAGE': + case 'GO_TO_NEXT_PAGE': + let nextPage = action.nextPage ? 1 : -1 + let newPage = action.pagination.periode_range[action.pagination.periode_range.indexOf(action.pagination.currentPage) + nextPage] + $('#ConfirmModal').modal('hide') + actions.fetchTimeTables(action.dispatch, newPage) + return _.assign({}, state, {current_periode_range: newPage}) + case 'CHANGE_PAGE': + $('#ConfirmModal').modal('hide') + actions.fetchTimeTables(action.dispatch, action.page) + return _.assign({}, state, {current_periode_range: action.page}) + case 'DELETE_PERIOD': + let ttperiods = state.time_table_periods.map((period, i) =>{ + if(i == action.index){ + period.deleted = true + } + return period + }) + newState = _.assign({}, state, {time_table_periods : ttperiods}) + return _.assign({}, newState, {current_month: actions.updateSynthesis(newState, action.dayTypes)}) + case 'INCLUDE_DATE_IN_PERIOD': + let newCMi = state.current_month.map((d, i) => { + if(i == action.index){ + d.include_date = !d.include_date + } + return d + }) + newState = _.assign({}, state, {current_month: newCMi}) + return _.assign({}, newState, {current_month: actions.updateSynthesis(newState, action.dayTypes)}) + case 'EXCLUDE_DATE_FROM_PERIOD': + let newCMe = state.current_month.map((d, i) => { + if(i == action.index){ + d.excluded_date = !d.excluded_date + } + return d + }) + newState = _.assign({}, state, {current_month: newCMe}) + return _.assign({}, newState, {current_month: actions.updateSynthesis(newState, action.dayTypes)}) + default: + return state + } +} + +module.exports = timetable diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js index 4e67482da..81bbcdbb0 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js @@ -315,9 +315,12 @@ const actions = { selected: false, published_journey_name: val.published_journey_name || 'non renseigné', published_journey_identifier: val.published_journey_name || 'non renseigné', - company_id: val.published_journey_name || 'non renseigné' + company_id: val.published_journey_name || 'non renseigné', + transport_mode: val.route.line.transport_mode || 'non renseigné', + transport_mode: val.route.line.transport_submode || 'non renseigné' }) } + window.currentItemsLength = vehicleJourneys.length dispatch(actions.receiveVehicleJourneys(vehicleJourneys)) dispatch(actions.receiveTotalCount(json.total)) } @@ -348,9 +351,10 @@ const actions = { if(next) { dispatch(next) } else { - if(json.length != window.vehicleJourneysPerPage){ - dispatch(actions.updateTotalCount(window.vehicleJourneysPerPage - json.length)) + if(json.length != window.currentItemsLength){ + dispatch(actions.updateTotalCount(window.currentItemsLength - json.length)) } + window.currentItemsLength = json.length dispatch(actions.receiveVehicleJourneys(json)) } } @@ -362,13 +366,29 @@ const actions = { return obj.selected }) }, - pad: (d) => { + simplePad: (d) => { if(d.toString().length == 1){ return (d < 10) ? '0' + d.toString() : d.toString(); }else{ return d.toString() } }, + pad: (d, timeUnit) => { + let val = d.toString() + if(d.toString().length == 1){ + val = (d < 10) ? '0' + d.toString() : d.toString(); + } + if(val.length > 2){ + val = val.substr(1) + } + if(timeUnit == 'minute' && parseInt(val) > 59){ + val = '59' + } + if(timeUnit == 'hour' && parseInt(val) > 23){ + val = '23' + } + return val + }, encodeParams: (params) => { let esc = encodeURIComponent let queryString = Object.keys(params).map((k) => esc(k) + '=' + esc(params[k])).join('&') @@ -390,20 +410,61 @@ const actions = { return vjas }, checkSchedules: (schedule) => { + let hours = 0 + let minutes = 0 if (parseInt(schedule.departure_time.minute) > 59){ - schedule.departure_time.minute = actions.pad(parseInt(schedule.departure_time.minute) - 60) - schedule.departure_time.hour = actions.pad(parseInt(schedule.departure_time.hour) + 1) + hours = Math.floor(parseInt(schedule.departure_time.minute) / 60) + minutes = parseInt(schedule.departure_time.minute) % 60 + schedule.departure_time.minute = actions.simplePad(minutes, 'minute') + schedule.departure_time.hour = parseInt(schedule.departure_time.hour) + hours } if (parseInt(schedule.arrival_time.minute) > 59){ - schedule.arrival_time.minute = actions.pad(parseInt(schedule.arrival_time.minute) - 60) - schedule.arrival_time.hour = actions.pad(parseInt(schedule.arrival_time.hour) + 1) + hours = Math.floor(parseInt(schedule.arrival_time.minute) / 60) + minutes = parseInt(schedule.arrival_time.minute) % 60 + schedule.arrival_time.minute = actions.simplePad(minutes, 'minute') + schedule.arrival_time.hour = parseInt(schedule.arrival_time.hour) + hours } - if (parseInt(schedule.departure_time.hour) > 23){ - schedule.departure_time.hour = actions.pad(parseInt(schedule.departure_time.hour) - 24) + if (parseInt(schedule.departure_time.minute) < 0){ + hours = Math.floor(parseInt(schedule.departure_time.minute) / 60) + minutes = (parseInt(schedule.departure_time.minute) % 60) + 60 + schedule.departure_time.minute = actions.simplePad(minutes, 'minute') + schedule.departure_time.hour = parseInt(schedule.departure_time.hour) + hours } - if (parseInt(schedule.arrival_time.hour) > 23){ - schedule.arrival_time.hour = actions.pad(parseInt(schedule.arrival_time.hour) - 24) + if (parseInt(schedule.arrival_time.minute) < 0){ + hours = Math.floor(parseInt(schedule.arrival_time.minute) / 60) + minutes = (parseInt(schedule.arrival_time.minute) % 60) + 60 + schedule.arrival_time.minute = actions.simplePad(minutes, 'minute') + schedule.arrival_time.hour = parseInt(schedule.arrival_time.hour) + hours } + + if(schedule.departure_time.hour > 23){ + schedule.departure_time.hour = '23' + schedule.departure_time.minute = '59' + } + if(schedule.arrival_time.hour > 23){ + schedule.arrival_time.hour = '23' + schedule.arrival_time.minute = '59' + } + + if(schedule.departure_time.hour < 0){ + schedule.departure_time.hour = '00' + schedule.departure_time.minute = '00' + } + if(schedule.arrival_time.hour > 23){ + schedule.arrival_time.hour = '00' + schedule.arrival_time.minute = '00' + } + + schedule.departure_time.hour = actions.simplePad(parseInt(schedule.departure_time.hour), 'hour') + schedule.arrival_time.hour = actions.simplePad(parseInt(schedule.arrival_time.hour), 'hour') + // if (parseInt(schedule.departure_time.hour) > 23){ + // schedule.departure_time.hour = parseInt(schedule.departure_time.hour) - 24 + // } + // if (parseInt(schedule.arrival_time.hour) > 23){ + // schedule.arrival_time.hour = parseInt(schedule.arrival_time.hour) - 24 + // } + // schedule.departure_time.hour = actions.pad(schedule.departure_time.hour, 'hour') + // schedule.arrival_time.hour = actions.pad(schedule.arrival_time.hour, 'hour') } } diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Filters.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Filters.js index bddb29434..6f07dd880 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Filters.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Filters.js @@ -97,7 +97,7 @@ const Filters = ({filters, pagination, onFilter, onResetFilters, onUpdateStartTi onChange={onToggleWithoutSchedule} checked={filters.query.withoutSchedule} ></input> - <span className='switch-label' data-checkedvalue='Oui' data-uncheckedvalue='Non'></span> + <span className='switch-label' data-checkedvalue='Non' data-uncheckedvalue='Oui'></span> </label> </div> </div> diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Navigate.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Navigate.js index 2d5923a4d..a62e034ae 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Navigate.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Navigate.js @@ -29,7 +29,7 @@ let Navigate = ({ dispatch, vehicleJourneys, pagination, status, filters}) => { type='button' data-target='#ConfirmModal' className={(pagination.page == firstPage ? 'disabled ' : '') + 'previous_page'} - disabled={(pagination.page == firstPage ? true : false)} + disabled={(pagination.page == firstPage ? 'disabled' : '')} ></button> <button onClick={e => { @@ -39,7 +39,7 @@ let Navigate = ({ dispatch, vehicleJourneys, pagination, status, filters}) => { type='button' data-target='#ConfirmModal' className={(pagination.page == lastPage ? 'disabled ' : '') + 'next_page'} - disabled={(pagination.page == lastPage ? true : false)} + disabled={(pagination.page == lastPage ? 'disabled' : '')} ></button> </form> </div> diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/SaveVehicleJourneys.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/SaveVehicleJourneys.js index b22e1d826..bd34ae114 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/SaveVehicleJourneys.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/SaveVehicleJourneys.js @@ -15,7 +15,7 @@ class SaveVehicleJourneys extends Component{ } render() { - if(this.props.status.isFetching == true) { + if(this.props.status.isFetching == true || this.props.filters.policy['vehicle_journeys.edit'] == false) { return false } if(this.props.status.fetchSuccess == true) { @@ -46,7 +46,8 @@ class SaveVehicleJourneys extends Component{ SaveVehicleJourneys.propTypes = { vehicleJourneys: PropTypes.array.isRequired, page: PropTypes.number.isRequired, - status: PropTypes.object.isRequired + status: PropTypes.object.isRequired, + filters: PropTypes.object.isRequired } module.exports = SaveVehicleJourneys diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js index dc0621f76..0645fdd19 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js @@ -54,7 +54,7 @@ class VehicleJourney extends Component { <div key={i}>{this.timeTableURL(tt.id)}</div> )} - {this.isDisabled(this.props.filters.policy['vehicle_journeys.edit'], this.props.filters.policy['vehicle_journeys.destroy']) && + {(this.props.filters.policy['vehicle_journeys.edit'] == true) && <div className={(this.props.value.deletable ? 'disabled ' : '') + 'checkbox'}> <input id={this.props.index} @@ -73,14 +73,14 @@ class VehicleJourney extends Component { <div key={i} className='td text-center'> <div className={'cellwrap' + (vj.dummy ? ' headlined' : '') + (this.cityNameChecker(vj) ? ' headlined' : '')}> {this.props.filters.toggleArrivals && - <div data-headline='Départ à '> - <span className={((this.props.value.deletable && (!vj.dummy)) ? 'disabled ' : '') + 'input-group time'}> + <div data-headline='Arrivée à '> + <span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.edit'] == false) ? 'disabled ' : '') + 'input-group time'}> <input type='number' min='00' max='23' className='form-control' - disabled={(this.props.value.deletable && (!vj.dummy))} + disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.edit'] == false)} onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'hour', false, false)}} value={vj.arrival_time['hour']} /> @@ -90,7 +90,7 @@ class VehicleJourney extends Component { min='00' max='59' className='form-control' - disabled={((this.props.value.deletable) && (!vj.dummy))} + disabled={((this.isDisabled(this.props.value.deletable), vj.dummy) || this.props.filters.policy['vehicle_journeys.edit'] == false)} onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'minute', false, false)}} value={vj.arrival_time['minute']} /> @@ -102,14 +102,14 @@ class VehicleJourney extends Component { <span className='sb sb-chrono sb-lg text-warning' data-textinside={vj.delta}></span> } </div> - <div data-headline='Arrivée à '> - <span className={(this.isDisabled(this.props.value.deletable, vj.dummy) ? 'disabled ' : '') + 'input-group time'}> + <div data-headline='Départ à '> + <span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.edit'] == false) ? 'disabled ' : '') + 'input-group time'}> <input type='number' min='00' max='23' className='form-control' - disabled={this.isDisabled(this.props.value.deletable, vj.dummy)} + disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.edit'] == false)} onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, 'hour', true, this.props.filters.toggleArrivals)}} value={vj.departure_time['hour']} /> @@ -119,7 +119,7 @@ class VehicleJourney extends Component { min='00' max='59' className='form-control' - disabled={this.isDisabled(this.props.value.deletable, vj.dummy)} + disabled={(this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.edit'] == false)} onChange={(e) => {this.props.onUpdateTime(e, i, this.props.index, "minute", true, this.props.filters.toggleArrivals)}} value={vj.departure_time['minute']} /> diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CalendarsEditVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CalendarsEditVehicleJourney.js index 19a5af869..e32c873e6 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CalendarsEditVehicleJourney.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CalendarsEditVehicleJourney.js @@ -22,15 +22,15 @@ class CalendarsEditVehicleJourney extends Component { if(this.props.status.fetchSuccess == true) { return ( <li className='st_action'> - <a - href='#' - className={(actions.getSelected(this.props.vehicleJourneys).length > 0 && this.props.filters.policy['vehicle_journeys.edit']) ? '' : 'disabled'} + <button + type='button' + disabled={(actions.getSelected(this.props.vehicleJourneys).length > 0 && this.props.filters.policy['vehicle_journeys.edit']) ? '' : 'disabled'} data-toggle='modal' data-target='#CalendarsEditVehicleJourneyModal' onClick={() => this.props.onOpenCalendarsEditModal(actions.getSelected(this.props.vehicleJourneys))} > <span className='fa fa-calendar'></span> - </a> + </button> <div className={ 'modal fade ' + ((this.props.modal.type == 'duplicate') ? 'in' : '') } id='CalendarsEditVehicleJourneyModal'> <div className='modal-container'> diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js index 1a1588f85..1273921e7 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js @@ -25,15 +25,15 @@ class CreateModal extends Component { if(this.props.status.fetchSuccess == true) { return ( <li className='st_action'> - <a - href='#' - className={((this.props.filters.policy['vehicle_journeys.create']) ? '' : 'disabled')} + <button + type='button' + disabled={((this.props.filters.policy['vehicle_journeys.edit'] == true) ? '' : 'disabled')} data-toggle='modal' data-target='#NewVehicleJourneyModal' onClick={this.props.onOpenCreateModal} > <span className='fa fa-plus'></span> - </a> + </button> <div className={ 'modal fade ' + ((this.props.modal.type == 'create') ? 'in' : '') } id='NewVehicleJourneyModal'> <div className='modal-container'> diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DeleteVehicleJourneys.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DeleteVehicleJourneys.js index e2425cc22..c98b794a8 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DeleteVehicleJourneys.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DeleteVehicleJourneys.js @@ -5,9 +5,9 @@ var actions = require('../../actions') const DeleteVehicleJourneys = ({onDeleteVehicleJourneys, vehicleJourneys, filters}) => { return ( <li className='st_action'> - <a - href='#' - className={(actions.getSelected(vehicleJourneys).length > 0 && filters.policy['vehicle_journeys.destroy']) ? '' : 'disabled'} + <button + type='button' + disabled={(actions.getSelected(vehicleJourneys).length > 0 && filters.policy['vehicle_journeys.destroy']) ? '' : 'disabled'} onClick={e => { e.preventDefault() onDeleteVehicleJourneys() @@ -15,7 +15,7 @@ const DeleteVehicleJourneys = ({onDeleteVehicleJourneys, vehicleJourneys, filter title='Supprimer' > <span className='fa fa-trash'></span> - </a> + </button> </li> ) } diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js index b0cb1c850..7448aa06e 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js @@ -23,15 +23,15 @@ class DuplicateVehicleJourney extends Component { if(this.props.status.fetchSuccess == true) { return ( <li className='st_action'> - <a - href='#' - className={((actions.getSelected(this.props.vehicleJourneys).length == 1 && this.props.filters.policy['vehicle_journeys.edit']) ? '' : 'disabled')} + <button + type='button' + disabled={((actions.getSelected(this.props.vehicleJourneys).length == 1 && this.props.filters.policy['vehicle_journeys.edit']) ? '' : 'disabled')} data-toggle='modal' data-target='#DuplicateVehicleJourneyModal' onClick={this.props.onOpenDuplicateModal} > <span className='fa fa-files-o'></span> - </a> + </button> <div className={ 'modal fade ' + ((this.props.modal.type == 'duplicate') ? 'in' : '') } id='DuplicateVehicleJourneyModal'> <div className='modal-container'> @@ -68,7 +68,7 @@ class DuplicateVehicleJourney extends Component { <input type='number' ref='additional_time' - min='0' + min='-59' max='59' className='form-control' onKeyDown={(e) => actions.resetValidation(e.currentTarget)} diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js index f7726dad9..9a4790051 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js @@ -24,15 +24,15 @@ class EditVehicleJourney extends Component { if(this.props.status.fetchSuccess == true) { return ( <li className='st_action'> - <a - href='#' - className={(actions.getSelected(this.props.vehicleJourneys).length == 1 && this.props.filters.policy['vehicle_journeys.edit']) ? '' : 'disabled'} + <button + type='button' + disabled={(actions.getSelected(this.props.vehicleJourneys).length == 1 && this.props.filters.policy['vehicle_journeys.edit']) ? '' : 'disabled'} data-toggle='modal' data-target='#EditVehicleJourneyModal' onClick={() => this.props.onOpenEditModal(actions.getSelected(this.props.vehicleJourneys)[0])} > <span className='fa fa-info'></span> - </a> + </button> <div className={ 'modal fade ' + ((this.props.modal.type == 'duplicate') ? 'in' : '') } id='EditVehicleJourneyModal'> <div className='modal-container'> @@ -74,22 +74,51 @@ class EditVehicleJourney extends Component { <div className='row'> <div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'> - <label className='control-label is-required'>Numéro de train</label> - <input - type='text' - ref='published_journey_identifier' - className='form-control' - defaultValue={this.props.modal.modalProps.vehicleJourney.published_journey_identifier} - onKeyDown={(e) => actions.resetValidation(e.currentTarget)} - required + <div className='form-group'> + <label className='control-label is-required'>Numéro de train</label> + <input + type='text' + ref='published_journey_identifier' + className='form-control' + defaultValue={this.props.modal.modalProps.vehicleJourney.published_journey_identifier} + onKeyDown={(e) => actions.resetValidation(e.currentTarget)} + required /> + </div> </div> <div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'> - <label className='control-label'>Transporteur</label> + <div className='form-group'> + <label className='control-label'>Transporteur</label> <CompanySelect2 company = {this.props.modal.modalProps.vehicleJourney.company} onSelect2Company = {(e) => this.props.onSelect2Company(e)} /> + </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'>Mode de transport</label> + <input + type='text' + className='form-control' + value={(this.props.modal.modalProps.vehicleJourney.transport_mode || 'non renseigné')} + 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> + <input + type='text' + className='form-control' + value={(this.props.modal.modalProps.vehicleJourney.transport_submode || 'non renseigné')} + disabled={true} + /> + </div> </div> </div> </div> diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/NotesEditVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/NotesEditVehicleJourney.js index 7c5df3333..ca8b2ec7d 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/NotesEditVehicleJourney.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/NotesEditVehicleJourney.js @@ -44,15 +44,15 @@ class NotesEditVehicleJourney extends Component { if(this.props.status.fetchSuccess == true) { return ( <li className='st_action'> - <a - href='#' - className={(actions.getSelected(this.props.vehicleJourneys).length == 1 && this.props.filters.policy['vehicle_journeys.edit']) ? '' : 'disabled'} + <button + type='button' + disabled={(actions.getSelected(this.props.vehicleJourneys).length == 1 && this.props.filters.policy['vehicle_journeys.edit']) ? '' : 'disabled'} data-toggle='modal' data-target='#NotesEditVehicleJourneyModal' onClick={() => this.props.onOpenNotesEditModal(actions.getSelected(this.props.vehicleJourneys)[0])} > <span className='fa fa-sticky-note'></span> - </a> + </button> <div className={ 'modal fade ' + ((this.props.modal.type == 'duplicate') ? 'in' : '') } id='NotesEditVehicleJourneyModal'> <div className='modal-container'> diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/ShiftVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/ShiftVehicleJourney.js index a373ed1e5..ee7d01cf5 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/ShiftVehicleJourney.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/ShiftVehicleJourney.js @@ -23,15 +23,15 @@ class ShiftVehicleJourney extends Component { if(this.props.status.fetchSuccess == true) { return ( <li className='st_action'> - <a - href='#' - className={(actions.getSelected(this.props.vehicleJourneys).length == 1 && this.props.filters.policy['vehicle_journeys.edit']) ? '' : 'disabled'} + <button + type='button' + disabled={(actions.getSelected(this.props.vehicleJourneys).length == 1 && this.props.filters.policy['vehicle_journeys.edit']) ? '' : 'disabled'} data-toggle='modal' data-target='#ShiftVehicleJourneyModal' onClick={this.props.onOpenShiftModal} > <span className='sb sb-update-vj'></span> - </a> + </button> <div className={ 'modal fade ' + ((this.props.modal.type == 'shift') ? 'in' : '') } id='ShiftVehicleJourneyModal'> <div className='modal-container'> @@ -54,7 +54,7 @@ class ShiftVehicleJourney extends Component { <input type='number' ref='additional_time' - min='0' + min='-59' max='59' className='form-control' onKeyDown={(e) => actions.resetValidation(e.currentTarget)} diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js index 7837cdbff..1f5e5e98f 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js @@ -6,6 +6,7 @@ var Select2 = require('react-select2') // get JSON full path var origin = window.location.origin var path = window.location.pathname.split('/', 3).join('/') +var line = window.location.pathname.split('/')[4] class BSelect4 extends React.Component{ @@ -27,7 +28,7 @@ class BSelect4 extends React.Component{ width: '100%', placeholder: 'Filtrer par transporteur...', ajax: { - url: origin + path + '/companies.json', + url: origin + path + '/companies.json' + '?line_id=' + line, dataType: 'json', delay: '500', data: function(params) { diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/SaveVehicleJourneys.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/SaveVehicleJourneys.js index 5af30ab82..87bbe5353 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/SaveVehicleJourneys.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/SaveVehicleJourneys.js @@ -7,7 +7,8 @@ const mapStateToProps = (state) => { return { vehicleJourneys: state.vehicleJourneys, page: state.pagination.page, - status: state.status + status: state.status, + filters: state.filters } } diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js index 1b9ff8f41..4c9423c1f 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js @@ -21,7 +21,7 @@ if (window.journeyPatternId) var initialState = { filters: { selectedJourneyPatterns : selectedJP, - policy: perms, + policy: window.perms, toggleArrivals: false, queryString: '', query: { @@ -44,7 +44,7 @@ var initialState = { timetable: { comment: '' }, - withoutSchedule: false + withoutSchedule: true } }, diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/filters.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/filters.js index 4b67dc4df..cd065e362 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/filters.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/filters.js @@ -15,14 +15,14 @@ const filters = (state = {}, action) => { minute: '59' } } - newQuery = _.assign({}, state.query, {interval: interval, journeyPattern: {}, timetable: {}, withoutSchedule: false }) + newQuery = _.assign({}, state.query, {interval: interval, journeyPattern: {}, timetable: {}, withoutSchedule: true }) return _.assign({}, state, {query: newQuery, queryString: ''}) case 'TOGGLE_WITHOUT_SCHEDULE': newQuery = _.assign({}, state.query, {withoutSchedule: !state.query.withoutSchedule}) return _.assign({}, state, {query: newQuery}) case 'UPDATE_END_TIME_FILTER': newInterval = JSON.parse(JSON.stringify(state.query.interval)) - newInterval.end[action.unit] = actions.pad(action.val) + newInterval.end[action.unit] = actions.pad(action.val, action.unit) if(parseInt(newInterval.start.hour + newInterval.start.minute) < parseInt(newInterval.end.hour + newInterval.end.minute)){ newQuery = _.assign({}, state.query, {interval: newInterval}) return _.assign({}, state, {query: newQuery}) @@ -31,7 +31,7 @@ const filters = (state = {}, action) => { } case 'UPDATE_START_TIME_FILTER': newInterval = JSON.parse(JSON.stringify(state.query.interval)) - newInterval.start[action.unit] = actions.pad(action.val) + newInterval.start[action.unit] = actions.pad(action.val, action.unit) if(parseInt(newInterval.start.hour + newInterval.start.minute) < parseInt(newInterval.end.hour + newInterval.end.minute)){ newQuery = _.assign({}, state.query, {interval: newInterval}) return _.assign({}, state, {query: newQuery}) @@ -54,7 +54,8 @@ const filters = (state = {}, action) => { 'q[journey_pattern_id_eq]': state.query.journeyPattern.id || undefined, 'q[time_tables_id_eq]': state.query.timetable.id || undefined, 'q[vehicle_journey_at_stops_departure_time_gteq]': (state.query.interval.start.hour + ':' + state.query.interval.start.minute), - 'q[vehicle_journey_at_stops_departure_time_lteq]': (state.query.interval.end.hour + ':' + state.query.interval.end.minute) + 'q[vehicle_journey_at_stops_departure_time_lteq]': (state.query.interval.end.hour + ':' + state.query.interval.end.minute), + 'q[vehicle_journey_without_departure_time]' : state.query.withoutSchedule } let queryString = actions.encodeParams(params) return _.assign({}, state, {queryString: queryString}) diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js index 5924f5cc7..2db76deae 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js @@ -47,19 +47,26 @@ const vehicleJourney= (state = {}, action) => { case 'SHIFT_VEHICLEJOURNEY': let shiftedArray, shiftedSchedule, shiftedVjas shiftedArray = state.vehicle_journey_at_stops.map((vjas, i) => { - shiftedSchedule = { - departure_time: { - hour: vjas.departure_time.hour, - minute: String(parseInt(vjas.departure_time.minute) + parseInt(action.data.additional_time.value)) - }, - arrival_time: { - hour: vjas.arrival_time.hour, - minute: String(parseInt(vjas.arrival_time.minute) + parseInt(action.data.additional_time.value)) + if (!vjas.dummy){ + shiftedSchedule = { + departure_time: { + hour: vjas.departure_time.hour, + minute: actions.simplePad(parseInt(vjas.departure_time.minute) + parseInt(action.data.additional_time.value)) + }, + arrival_time: { + hour: vjas.arrival_time.hour, + minute: actions.simplePad(parseInt(vjas.arrival_time.minute) + parseInt(action.data.additional_time.value)) + } } + actions.checkSchedules(shiftedSchedule) + shiftedVjas = _.assign({}, state.vehicle_journey_at_stops[i], shiftedSchedule) + vjas = _.assign({}, state.vehicle_journey_at_stops[i], shiftedVjas) + delete vjas['id'] + return vjas + }else { + delete vjas['id'] + return vjas } - actions.checkSchedules(shiftedSchedule) - shiftedVjas = _.assign({}, state.vehicle_journey_at_stops[i], shiftedSchedule) - return _.assign({}, state.vehicle_journey_at_stops[i], shiftedVjas) }) return _.assign({}, state, {vehicle_journey_at_stops: shiftedArray}) case 'UPDATE_TIME': @@ -71,14 +78,20 @@ const vehicleJourney= (state = {}, action) => { arrival_time: _.assign({}, vjas.arrival_time) } if (action.isDeparture){ - newSchedule.departure_time[action.timeUnit] = actions.pad(action.val) + newSchedule.departure_time[action.timeUnit] = actions.pad(action.val, action.timeUnit) if(!action.isArrivalsToggled) - newSchedule.arrival_time[action.timeUnit] = actions.pad(action.val) + newSchedule.arrival_time[action.timeUnit] = actions.pad(action.val, action.timeUnit) newSchedule = actions.getDelta(newSchedule) + if(newSchedule.delta < 0){ + return vjas + } 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) + newSchedule.arrival_time[action.timeUnit] = actions.pad(action.val, action.timeUnit) newSchedule = actions.getDelta(newSchedule) + if(newSchedule.delta < 0){ + return vjas + } return _.assign({}, state.vehicle_journey_at_stops[action.subIndex], {arrival_time: newSchedule.arrival_time, departure_time: newSchedule.departure_time, delta: newSchedule.delta}) } }else{ @@ -160,11 +173,12 @@ const vehicleJourneys = (state = [], action) => { let dupeVj let dupes = [] let selectedIndex + let val = action.data.additional_time.value state.map((vj, i) => { if(vj.selected){ selectedIndex = i for (i = 0; i< action.data.duplicate_number.value; i++){ - action.data.additional_time.value *= (i + 1) + action.data.additional_time.value = val * (i + 1) dupeVj = vehicleJourney(vj, action) dupeVj.published_journey_name = dupeVj.published_journey_name + '-' + i dupeVj.selected = false diff --git a/app/assets/javascripts/forms.coffee b/app/assets/javascripts/forms.coffee index 9d884edcd..6b00e9c26 100644 --- a/app/assets/javascripts/forms.coffee +++ b/app/assets/javascripts/forms.coffee @@ -30,9 +30,21 @@ isEdge = !isIE && !!window.StyleMedia if isIE || isEdge $('.formSubmitr').off() -$(document).on 'ready page:load', togglableFilter -$(document).on 'ready page:load', submitMover -$(document).on 'ready page:load', switchInput +@colorSelector = -> + $('.form-group .dropdown.color_selector').each -> + selectedStatus = $(this).children('.dropdown-toggle').children('.fa-circle') + + $(this).on 'click', "input[type='radio']", (e) -> + selectedValue = e.currentTarget.value + if selectedValue == '' + $(selectedStatus).css('color', 'transparent') + else + $(selectedStatus).css('color', selectedValue) + +$(document).on 'turbolinks:load', togglableFilter +$(document).on 'turbolinks:load', submitMover +$(document).on 'turbolinks:load', switchInput +$(document).on 'turbolinks:load', colorSelector if isIE || isEdge $(document).on 'click', '.formSubmitr', (e)-> diff --git a/app/assets/javascripts/main_menu.coffee b/app/assets/javascripts/main_menu.coffee index 9357cff34..2e0cd3470 100644 --- a/app/assets/javascripts/main_menu.coffee +++ b/app/assets/javascripts/main_menu.coffee @@ -1,4 +1,4 @@ -$(document).on 'ready page:load', -> +$(document).on 'turbolinks:load', -> link = [] ptitleCont = "" @@ -49,5 +49,6 @@ $(document).on 'ready page:load', -> $('#main_nav').removeClass 'sticky' if $('#menu_top').find('.sticky-content').length > 0 - $('.page-action .small').after(link) + if !$('.page-action').find('.formSubmitr').length + $('.page-action .small').after(link) $('.sticky-content').remove() diff --git a/app/assets/javascripts/nav_panels.coffee b/app/assets/javascripts/nav_panels.coffee index b254b9f94..829db5ad0 100644 --- a/app/assets/javascripts/nav_panels.coffee +++ b/app/assets/javascripts/nav_panels.coffee @@ -1,4 +1,4 @@ -$(document).on 'ready page:load', -> +$(document).on 'turbolinks:load', -> $('#menu_top [data-panel="toggle"]').on 'click', (e) -> e.preventDefault() $(this).siblings().removeClass 'active' diff --git a/app/assets/javascripts/routing_constraint_zones.coffee b/app/assets/javascripts/routing_constraint_zones.coffee new file mode 100644 index 000000000..458189b36 --- /dev/null +++ b/app/assets/javascripts/routing_constraint_zones.coffee @@ -0,0 +1,27 @@ +fill_stop_points_options = -> + stop_point_select = $('#routing_constraint_zone_stop_point_ids') + stop_point_select.empty() + referential_id = document.location.pathname.match(/\d+/g)[0] + line_id = document.location.pathname.match(/\d+/g)[1] + route_id = $('#routing_constraint_zone_route_id').val() + if errors_on_form() + stop_point_ids = eval($('#stop_point_ids').val()) + $.ajax + url: "/referentials/#{referential_id}/lines/#{line_id}/routes/#{route_id}/stop_points" + dataType: 'json' + success: (data, textStatus, jqXHR) -> + for stop_point in data + selected = $.inArray(stop_point.id, stop_point_ids) != -1 + stop_point_select.append "<option value='#{stop_point.id}'" + "#{if selected then ' selected' else ''}" + ">#{stop_point.name}</option>" + error: (jqXHR, textStatus, errorThrown) -> + console.log textStatus + console.log errorThrown + +errors_on_form = -> + document.location.pathname.endsWith('routing_constraint_zones') && $('#new_routing_constraint_zone').length + +$(document).on 'turbolinks:load', -> + if document.location.pathname.endsWith('new') || errors_on_form() + fill_stop_points_options() + $('#routing_constraint_zone_route_id').change(fill_stop_points_options) + diff --git a/app/assets/javascripts/select2.coffee b/app/assets/javascripts/select2.coffee index edd4c476d..1870f7f9a 100644 --- a/app/assets/javascripts/select2.coffee +++ b/app/assets/javascripts/select2.coffee @@ -7,5 +7,13 @@ placeholder: target.data('select2ed-placeholder') allowClear: true + $('select.form-control.tags').each -> + target = $(this) + target.select2 + theme: 'bootstrap' + language: 'fr' + allowClear: true + tags: true + -$(document).on 'ready page:load', select_2 +$(document).on 'turbolinks:load', select_2 diff --git a/app/assets/javascripts/selectable_table.coffee b/app/assets/javascripts/selectable_table.coffee index 4d9f5122a..4086bf6c2 100644 --- a/app/assets/javascripts/selectable_table.coffee +++ b/app/assets/javascripts/selectable_table.coffee @@ -53,4 +53,4 @@ .addClass 'noselect' .children('.info-msg').children('span').text(selection.length) -$(document).on 'ready page:load', selectTable +$(document).on 'turbolinks:load', selectTable diff --git a/app/assets/stylesheets/application.sass b/app/assets/stylesheets/application.sass index e4a2a5445..47cccba65 100644 --- a/app/assets/stylesheets/application.sass +++ b/app/assets/stylesheets/application.sass @@ -15,3 +15,4 @@ @import 'modules/routes_stopoints' @import 'modules/jp_collection' @import 'modules/vj_collection' +@import 'modules/timetables' diff --git a/app/assets/stylesheets/base/_config.sass b/app/assets/stylesheets/base/_config.sass index ae8b386e6..65444479f 100644 --- a/app/assets/stylesheets/base/_config.sass +++ b/app/assets/stylesheets/base/_config.sass @@ -21,3 +21,4 @@ $green: #70b12b $red: #da2f36 $orange: #ed7f00 +$gold: #ffcc00 diff --git a/app/assets/stylesheets/components/_buttons.sass b/app/assets/stylesheets/components/_buttons.sass index 00551f7cb..fd3561dc8 100644 --- a/app/assets/stylesheets/components/_buttons.sass +++ b/app/assets/stylesheets/components/_buttons.sass @@ -5,15 +5,45 @@ .btn font-weight: 700 - .fa + span + .fa + span:not(.caret) padding-left: 0.5em span + .fa padding-left: 0.5em - &.btn-link + &.btn-link, &.btn-circle &, &:focus outline: none + &.btn-circle + position: relative + top: 50% + transform: translateY(-50%) + border: 1px solid $blue + background-color: transparent + width: 22px + height: 22px + line-height: 22px + text-align: center + border-radius: 50% + padding: 0 + color: $grey + + > .fa + display: block + line-height: 20px + + &[data-actiontype='add'] + &:hover, &.active + border-color: $green + background-color: $green + color: #fff + + &[data-actiontype='remove'] + &:hover, &.active + border-color: $red + background-color: $red + color: #fff + &.btn-default background-color: #fff border-color: rgba(#fff, 0.5) @@ -113,12 +143,12 @@ table, .table border-radius: 0 box-shadow: 0 0 3px rgba($darkgrey, 0.25) - > li > a + > li > a, > li > button padding: 5px 15px > li.delete-action - - > a + > a, > button + display: block position: relative margin-top: 11px diff --git a/app/assets/stylesheets/components/_calendar.sass b/app/assets/stylesheets/components/_calendar.sass new file mode 100644 index 000000000..c3d93d325 --- /dev/null +++ b/app/assets/stylesheets/components/_calendar.sass @@ -0,0 +1,73 @@ +//-----------// +// CALENDARS // +//-----------// + +table.calendar + display: table + width: 100% + table-layout: fixed + margin-bottom: 20px + + th, td + border: 1px solid $darkgrey + text-align: center + padding: 0.35em 0.5em + + th + padding: 0.5em + + thead + tr + > th + border: none + + &:first-child + text-transform: uppercase + + tbody + tr > td + &.weekNumber + border: none + padding: 0.5em 0.5em 0.5em 0 + + &.outsideMonth + color: rgba($darkgrey, 0.35) + + &.weekend + font-weight: bold + + &.selected_period, &.selected_date, &.overlaped_date + > a + display: block + margin: 0 auto + width: 24px + height: 24px + line-height: 24px + color: $darkgrey + background-color: rgba($gold, 0.75) + border-radius: 50% + + &:hover, &:focus + color: $darkgrey + text-decoration: none + +.col-xs-6 + &:nth-child(2n +1) + clear: both + +.col-sm-4 + @media (min-width: 768px) + &:nth-child(2n +1) + clear: none + &:nth-child(3n+1) + clear: both + +// .col-md-4 +// @media (min-width: 992px) + +.col-lg-3 + @media (min-width: 1200px) + &:nth-child(2n +1), &:nth-child(3n+1) + clear: none + &:nth-child(4n+1) + clear: both diff --git a/app/assets/stylesheets/components/_dropdown.sass b/app/assets/stylesheets/components/_dropdown.sass index ee26aaeb5..99dc6292e 100644 --- a/app/assets/stylesheets/components/_dropdown.sass +++ b/app/assets/stylesheets/components/_dropdown.sass @@ -3,6 +3,22 @@ //-------------// .dropdown-menu - > .disabled > a + > li > button + display: block + width: 100% + text-align: left + border: none + background-color: transparent + color: #333 + + &:hover, &:focus + color: #262626 + background-color: whitesmoke + outline: none + + > .disabled > a, > .disabled > button + cursor: not-allowed &, &:hover, &:focus color: rgba($darkgrey, 0.5) + background-color: transparent + outline: none diff --git a/app/assets/stylesheets/components/_forms.sass b/app/assets/stylesheets/components/_forms.sass index 3b7a135d5..8419c2345 100644 --- a/app/assets/stylesheets/components/_forms.sass +++ b/app/assets/stylesheets/components/_forms.sass @@ -77,6 +77,57 @@ input border-color: #4cae4c box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px #5cb85c +// BS horizontal form label positionning fix +.form-horizontal + .form-group + position: relative + + > .control-label + &[class*='col-sm-'] + float: none + padding-top: 0 + position: absolute + left: 0 + right: 0 + top: 50% + transform: translateY(-50%) + + + [class*='col-sm-'] + float: right + +// Colors dropdown +.dropdown.color_selector + .btn.btn-default + &, &:hover, &:focus + border: 1px solid #cccccc + background-color: #fff + font-weight: normal + color: $darkgrey + + .dropdown-menu + position: absolute + margin: 2px 0 0 0 + min-width: 56px + + > .radio + position: relative + padding: 3px 20px + // cursor: pointer + + &:hover, &:focus + background-color: #f5f5f5 + + > label + padding: 0 + + input.color_selector, input[type='radio'] + position: absolute + cursor: pointer + z-index: 1 + width: 100% + margin: 0 + opacity: 0 + // Search bar .search_bar position: relative @@ -646,6 +697,59 @@ table, .table .control-label.time min-width: 60px +// Form group checkboxes +$grp-cbx-size: 34px +.form-group.labelled-checkbox-group + margin: 0 + + > .lcbx-group-item + display: inline-block + margin: 0 5px + + &:first-child + margin-left: 0 + + > .checkbox + display: block + width: $grp-cbx-size + height: $grp-cbx-size + line-height: $grp-cbx-size + margin: 0 + padding: 0 + + > label + position: relative + min-height: 0 + padding: 0 + margin: 0 + + > input + &[type='checkbox']:not(:checked), &[type='checkbox']:checked + position: absolute + left: -9999px + margin: 0 + + + .lcbx-group-item-label + position: relative + cursor: pointer + font-weight: bold + display: inline-block + vertical-align: top + width: $grp-cbx-size + height: $grp-cbx-size + line-height: $grp-cbx-size - 2px + text-align: center + margin: 0 + background-color: rgba($grey, 0.15) + color: rgba($grey, 0.5) + border: 1px solid rgba($grey, 0.5) + border-radius: 3px + + &[type='checkbox']:checked + .lcbx-group-item-label + background-color: $blue + border-color: $blue + color: #fff + // Nested fields .nested-fields margin: 0 @@ -727,7 +831,7 @@ table, .table margin: 0 padding: 0 5px - + .nested-fields + + .nested-fields, + .links.nested-linker border-top: 2px solid $darkgrey .wrapper diff --git a/app/assets/stylesheets/components/_labels.sass b/app/assets/stylesheets/components/_labels.sass index 3514bce81..9607a97b8 100644 --- a/app/assets/stylesheets/components/_labels.sass +++ b/app/assets/stylesheets/components/_labels.sass @@ -8,7 +8,15 @@ font-weight: inherit padding: 0.35em 0.4em border-radius: 2px + border: 1px solid + + + .label + margin-left: 0.5em &.label-default - background-color: rgba(#fff, 0.3) - color: #fff + background-color: #fff + color: $darkgrey + border-color: rgba($grey, 0.5) + + &.disabled + color: rgba($grey, 0.5) diff --git a/app/assets/stylesheets/components/_select2.sass b/app/assets/stylesheets/components/_select2.sass index 5e3741bf0..cbb3a80da 100644 --- a/app/assets/stylesheets/components/_select2.sass +++ b/app/assets/stylesheets/components/_select2.sass @@ -50,9 +50,19 @@ .form-filter .form-group.select2ed - .select2-container--bootstrap .select2-selection--single - height: 31px - padding: 4px 24px 5px 12px + .select2-container--bootstrap + .select2-selection--single, .select2-selection--multiple + height: 31px + padding: 0px 3px 4px 6px + + .select2-selection--single + line-height: 31px + + .select2-selection--multiple + min-height: 31px + + .select2-search--inline .select2-search__field + height: 28px .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 ade9bacf4..bc04b49e3 100644 --- a/app/assets/stylesheets/components/_tables.sass +++ b/app/assets/stylesheets/components/_tables.sass @@ -118,13 +118,15 @@ height: 35px margin: 5px - > a + > a, > button display: block height: 35px + width: 100% text-align: center line-height: 35px border-radius: 50% background-color: $blue + border: none color: #fff &:focus @@ -139,7 +141,7 @@ &:hover background-color: darken($red, 5%) - &.disabled + &.disabled, &:disabled &, &[title='Supprimer'], &:hover, &:focus background-color: rgba($grey, 0.3) cursor: not-allowed @@ -262,3 +264,11 @@ &.disabled color: rgba($darkgrey, 0.5) background-color: rgba(#fff, 0.5) + + // TD group + > .td-group + display: inline-block + vertical-align: top + + > .td + display: block diff --git a/app/assets/stylesheets/main/time_tables.sass b/app/assets/stylesheets/main/time_tables.sass index de2ae8253..6918bec1e 100644 --- a/app/assets/stylesheets/main/time_tables.sass +++ b/app/assets/stylesheets/main/time_tables.sass @@ -28,13 +28,13 @@ z-index: 100001 .validity_out - color: $brand-danger + color: red .validity_out_soon - color: $brand-warning + color: orange .validity_regular - color: $brand-success + color: green span.included_day_type font-weight: bolder diff --git a/app/assets/stylesheets/modules/_jp_collection.sass b/app/assets/stylesheets/modules/_jp_collection.sass index eff1e2abc..d1f864e5c 100644 --- a/app/assets/stylesheets/modules/_jp_collection.sass +++ b/app/assets/stylesheets/modules/_jp_collection.sass @@ -78,3 +78,7 @@ &:after bottom: -6px + + .t2e-head > .td:last-child > div > span + &:after + bottom: 50% diff --git a/app/assets/stylesheets/modules/_timetables.sass b/app/assets/stylesheets/modules/_timetables.sass new file mode 100644 index 000000000..27188060f --- /dev/null +++ b/app/assets/stylesheets/modules/_timetables.sass @@ -0,0 +1,195 @@ +//---------------// +// Time Tables // +//---------------// + +#periods + .t2e-head + > .th + height: 135px + text-align: left + border-color: $darkgrey + border-top-width: 2px + + > .strong + padding-top: 123px + transform: translateY(-1.4em) + + .t2e-head > .td, .t2e-item > .td-group > .td + height: 65px + + .t2e-head > .td + line-height: 50px + + > span + display: inline-block + vertical-align: middle + line-height: 1.4 + + .t2e-item-list > div + border-color: #fff + + .t2e-item + .th + padding: 6px 0 0 0 + border-color: $darkgrey + border-top-width: 2px + + > .monthName + padding: 0 0 6px 8px + + .monthDays + white-space: nowrap + + .day + display: inline-block + width: 40px + padding: 20px 0 6px 0 + + &.last_wday + &:not(:last-child) + border-right: 2px solid + + &:before + content: attr(data-wday) + display: block + text-align: left + color: rgba($grey, 0.5) + padding-bottom: 10px + + .dayname + display: block + text-align: center + text-transform: capitalize + padding-bottom: 2px + + .daynumber + display: block + margin: 0 auto + width: 24px + height: 24px + line-height: 24px + text-align: center + font-weight: bold + border-radius: 50% + background-color: transparent + + &.included + background-color: rgba($gold, 0.75) + + > .td-group + width: 40px + > .td + border-right: 1px solid rgba($grey, 0.5) + + &.last_wday + &:not(:last-child) > .td + border-right: 2px solid $darkgrey + + &.out_from_daytypes + background-image: linear-gradient(45deg, rgba($grey, 0.15) 0%, rgba($grey, 0.15) 49%, rgba($grey, 0.5) 50%, rgba($grey, 0.15) 51%, rgba($grey, 0.15) 99%, rgba($grey, 0.15) 100%) + background-size: 25px 25px + + > .td + &.in_periods + background-color: rgba($gold, 0.5) + border-left-color: rgba($gold, 0.5) + border-right-color: rgba($gold, 0.5) + + &.start_period + border-left-color: rgba($grey, 0.5) + &.end_period + border-right-color: rgba($grey, 0.5) + + .form-group > .month_selector + > .btn.btn-default + background-color: rgba($grey, 0.15) + color: $darkgrey + border: none + border-radius: 0 + padding: 8px 15px 7px 15px + + &:active, &.active + box-shadow: none + + > .caret + margin-left: 10px + color: $blue + + > .dropdown-menu + margin-top: 1px + border-radius: 0 0 4px 4px + max-height: 230px + overflow: auto + + .period_manager + display: block + height: auto + word-wrap: normal + white-space: nowrap + position: absolute + left: 8px + top: 50% + transform: translateY(-50%) + z-index: 5 + + > * + display: inline-block + vertical-align: middle + margin: 0 + + &.dropdown + margin-left: 5px + + .btn.dropdown-toggle + color: $blue + background-color: rgba(#fff, 0) + padding: 1px 5px + border-radius: 0 + transition: 0.2s + + &:hover, &:focus, &:active, &.active + background-color: rgba(#fff, 1) + border-color: $blue + outline: none + box-shadow: none + transition: 0.2s + + .open > .btn.dropdown-toggle + background-color: rgba(#fff, 1) + border-color: $blue + box-shadow: none + transition: 0.2s + + .dropdown-menu + margin: 0 + border-radius: 0 + box-shadow: 0 0 3px rgba($darkgrey, 0.25) + min-width: 120px + + > li > a, > li > button + padding: 5px 15px + + > 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 + + .td-group.last_wday ~ .td-group.last_wday ~ .td-group.last_wday ~ .td-group.last_wday + > .td, ~ .td-group > .td + > .period_manager .dropdown-menu + left: auto + right: 0 diff --git a/app/assets/stylesheets/typography/_fonts.sass b/app/assets/stylesheets/typography/_fonts.sass index 0bb0fd2db..0cc387d74 100644 --- a/app/assets/stylesheets/typography/_fonts.sass +++ b/app/assets/stylesheets/typography/_fonts.sass @@ -35,6 +35,6 @@ //-- sBoiv --// @font-face font-family: 'sboiv' - src: url(asset-path('sBoiv/sboiv.woff?5l6pxj')) format('woff'), url(asset-path('sBoiv/sboiv.ttf?5l6pxj')) format('ttf') + src: url(asset-path('sBoiv/sboiv.woff?vhxdui')) format('woff'), url(asset-path('sBoiv/sboiv.ttf?vhxdui')) format('ttf') font-weight: normal font-style: normal diff --git a/app/assets/stylesheets/typography/_sboiv.sass b/app/assets/stylesheets/typography/_sboiv.sass index cd3af8ab7..1f89bad74 100644 --- a/app/assets/stylesheets/typography/_sboiv.sass +++ b/app/assets/stylesheets/typography/_sboiv.sass @@ -18,6 +18,8 @@ &[data-textinside] position: relative + // width: 1em + // height: 1em &:after content: attr(data-textinside) font-family: $base-font-family @@ -50,6 +52,7 @@ &.sb-5x font-size: 5em + .sb-update-vj:before content: '\e900' @@ -58,3 +61,6 @@ .sb-current-ref:before content: '\e902' + +.sb-chrono:before + content: '\e903' diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c2414f5bb..2bdf8078a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -15,6 +15,10 @@ class ApplicationController < ActionController::Base I18n.locale = session[:language] || I18n.default_locale end + def pundit_user + UserContext.new(current_user, referential: self.try(:current_referential)) + end + protected def user_not_authorized diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb index c68a60804..accf119a3 100644 --- a/app/controllers/errors_controller.rb +++ b/app/controllers/errors_controller.rb @@ -1,9 +1,14 @@ class ErrorsController < ApplicationController def not_found - render :status => 404, :formats => [:html] + render template: 'errors/not_found', status: 404, formats: [:html] end def server_error - render :status => 500, :formats => [:html] + render template: 'errors/server_error', status: 500, formats: [:html] end -end
\ No newline at end of file + + def not_allowed + render template: 'errors/not_found', status: 403, formats: [:html] + end +end + diff --git a/app/controllers/journey_patterns_collections_controller.rb b/app/controllers/journey_patterns_collections_controller.rb index 51cc48c2a..ba54ddf26 100644 --- a/app/controllers/journey_patterns_collections_controller.rb +++ b/app/controllers/journey_patterns_collections_controller.rb @@ -1,6 +1,7 @@ class JourneyPatternsCollectionsController < ChouetteController respond_to :html respond_to :json + before_action :user_permissions, only: :show belongs_to :referential do belongs_to :line, :parent_class => Chouette::Line do @@ -41,6 +42,14 @@ class JourneyPatternsCollectionsController < ChouetteController @stop_points_list = @stop_points_list.sort_by {|a| a[:position] } end + def user_permissions + @perms = {}.tap do |perm| + ['journey_patterns.create', 'journey_patterns.edit', 'journey_patterns.destroy'].each do |name| + perm[name] = policy(:journey_pattern).send("#{name.split('.').last}?") + end + end.to_json + end + def update state = JSON.parse request.raw_post Chouette::JourneyPattern.state_update route, state diff --git a/app/controllers/line_footnotes_controller.rb b/app/controllers/line_footnotes_controller.rb index 7bc048731..c42aa785b 100644 --- a/app/controllers/line_footnotes_controller.rb +++ b/app/controllers/line_footnotes_controller.rb @@ -1,7 +1,6 @@ class LineFootnotesController < BreadcrumbController defaults :resource_class => Chouette::Line include PolicyChecker - before_action :check_policy, only: [:edit, :update, :destroy] respond_to :json, :only => :show belongs_to :referential @@ -27,7 +26,6 @@ class LineFootnotesController < BreadcrumbController end protected - # overrides default def check_policy authorize resource, "#{action_name}_footnote?".to_sym diff --git a/app/controllers/referential_companies_controller.rb b/app/controllers/referential_companies_controller.rb index 0966389b4..e8b104d14 100644 --- a/app/controllers/referential_companies_controller.rb +++ b/app/controllers/referential_companies_controller.rb @@ -27,7 +27,12 @@ class ReferentialCompaniesController < ChouetteController end def collection - @q = referential.workbench.companies.search(params[:q]) + scope = referential.line_referential.companies + if params[:line_id] + scope = referential.line_referential.lines.find(params[:line_id]).companies + end + + @q = scope.search(params[:q]) if sort_column && sort_direction @companies ||= @q.result(:distinct => true).order(sort_column + ' ' + sort_direction).paginate(:page => params[:page]) diff --git a/app/controllers/referentials_controller.rb b/app/controllers/referentials_controller.rb index ce875b6ba..f46cd188d 100644 --- a/app/controllers/referentials_controller.rb +++ b/app/controllers/referentials_controller.rb @@ -1,7 +1,7 @@ class ReferentialsController < BreadcrumbController defaults :resource_class => Referential include PolicyChecker - before_action :check_policy, :only => [:edit, :update, :archive, :unarchive] # overrides default + before_action :check_policy, :only => [:edit, :update, :destroy, :archive, :unarchive] # overrides default respond_to :html respond_to :json, :only => :show diff --git a/app/controllers/route_stop_points_controller.rb b/app/controllers/route_stop_points_controller.rb new file mode 100644 index 000000000..e12acb33b --- /dev/null +++ b/app/controllers/route_stop_points_controller.rb @@ -0,0 +1,18 @@ +class RouteStopPointsController < ChouetteController + defaults resource_class: Chouette::StopPoint + actions :index + respond_to :json, only: :index + + belongs_to :referential do + belongs_to :line, :parent_class => Chouette::Line do + belongs_to :route, :parent_class => Chouette::Route + end + end + + def index + respond_to do |format| + format.json { render json: referential.lines.find(params[:line_id]).routes.find(params[:route_id]).stop_points.map { |sp| { id: sp.id, name: sp.name } } } + end + end +end + diff --git a/app/controllers/routing_constraint_zones_controller.rb b/app/controllers/routing_constraint_zones_controller.rb index c39c50326..f2f74e801 100644 --- a/app/controllers/routing_constraint_zones_controller.rb +++ b/app/controllers/routing_constraint_zones_controller.rb @@ -3,6 +3,8 @@ class RoutingConstraintZonesController < ChouetteController respond_to :html, :xml, :json + before_action :remove_empty_stop_point, only: [:create, :update] + belongs_to :referential do belongs_to :line, parent_class: Chouette::Line end @@ -11,7 +13,10 @@ class RoutingConstraintZonesController < ChouetteController private def routing_constraint_zone_params - params.require(:routing_constraint_zone).permit(:name, { stop_area_ids: [] }, :line_id, :objectid, :object_version, :creator_id) + params.require(:routing_constraint_zone).permit(:name, { stop_point_ids: [] }, :line_id, :route_id, :objectid, :object_version, :creator_id) end + def remove_empty_stop_point + params.require(:routing_constraint_zone)[:stop_point_ids].delete('') + end end diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb index bdde5d3ab..eedfef07c 100644 --- a/app/controllers/time_tables_controller.rb +++ b/app/controllers/time_tables_controller.rb @@ -18,6 +18,11 @@ class TimeTablesController < ChouetteController end end + def month + @date = params['date'] ? Date.parse(params['date']) : Date.today + @time_table = resource + end + def new @autocomplete_items = ActsAsTaggableOn::Tag.all new! do @@ -88,19 +93,25 @@ class TimeTablesController < ChouetteController protected def collection - ransack_params = params[:q] - # Hack to delete params can't be used by ransack - tag_search = ransack_params["tag_search"].split(",").collect(&:strip) if ransack_params.present? && ransack_params["tag_search"].present? - ransack_params.delete("tag_search") if ransack_params.present? + scope = select_time_tables + if params[:q] && params[:q]["tag_search"] + tags = params[:q]["tag_search"].reject {|c| c.empty?} + params[:q].delete("tag_search") + scope = select_time_tables.tagged_with(tags, :wild => true, :any => true) if tags.any? + end - selected_time_tables = tag_search ? select_time_tables.tagged_with(tag_search, :wild => true, :any => true) : select_time_tables - @q = selected_time_tables.search(ransack_params) - @time_tables ||= @q.result(:distinct => true).order(:comment).paginate(:page => params[:page]) + @q = scope.search(params[:q]) + if sort_column && sort_direction + @time_tables ||= @q.result(:distinct => true).order("#{sort_column} #{sort_direction}") + else + @time_tables ||= @q.result(:distinct => true).order(:comment) + end + @time_tables = @time_tables.paginate(page: params[:page], per_page: 10) end def select_time_tables if params[:route_id] - referential.time_tables.joins( vehicle_journeys: :route).where( "routes.id IN (#{params[:route_id]})") + referential.time_tables.joins(vehicle_journeys: :route).where( "routes.id IN (#{params[:route_id]})") else referential.time_tables end @@ -115,8 +126,34 @@ class TimeTablesController < ChouetteController end private + def sort_column + referential.time_tables.column_names.include?(params[:sort]) ? params[:sort] : 'comment' + end + def sort_direction + %w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc' + end def time_table_params - params.require(:time_table).permit( :objectid, :object_version, :creator_id, :calendar_id, :version, :comment, :int_day_types, :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday, :start_date, :end_date, { :dates_attributes => [:date, :in_out, :id, :_destroy] }, { :periods_attributes => [:period_start, :period_end, :_destroy, :id] }, :tag_list, :tag_search ) + params.require(:time_table).permit( + :objectid, + :object_version, + :creator_id, + :calendar_id, + :version, :comment, :color, + :int_day_types, + :monday, + :tuesday, + :wednesday, + :thursday, + :friday, + :saturday, + :sunday, + :start_date, + :end_date, + { :dates_attributes => [:date, :in_out, :id, :_destroy] }, + { :periods_attributes => [:period_start, :period_end, :_destroy, :id] }, + {tag_list: []}, + :tag_search + ) end end diff --git a/app/controllers/vehicle_journeys_controller.rb b/app/controllers/vehicle_journeys_controller.rb index 5199d8632..c084b592a 100644 --- a/app/controllers/vehicle_journeys_controller.rb +++ b/app/controllers/vehicle_journeys_controller.rb @@ -1,8 +1,6 @@ class VehicleJourneysController < ChouetteController defaults :resource_class => Chouette::VehicleJourney - before_action :check_policy, only: [:edit, :update, :destroy] before_action :user_permissions, only: :index - before_action :ransack_params, only: :index respond_to :json, :only => :index respond_to :js, :only => [:select_journey_pattern, :edit, :new, :index] @@ -61,8 +59,7 @@ class VehicleJourneysController < ChouetteController } end - @jp_origin = Chouette::JourneyPattern.find_by(objectid: params[:jp]) - + @jp_origin = Chouette::JourneyPattern.find_by(objectid: params[:jp]) index! do if collection.out_of_bounds? @@ -80,14 +77,39 @@ class VehicleJourneysController < ChouetteController protected def collection + scope = route.vehicle_journeys.joins(:journey_pattern).joins('LEFT JOIN "vehicle_journey_at_stops" ON "vehicle_journey_at_stops"."vehicle_journey_id" = "vehicle_journeys"."id"') + + @q = scope.search filtered_ransack_params + grouping = ransack_periode_filter + @q.build_grouping(grouping) if grouping + @ppage = 20 - @q = route.sorted_vehicle_journeys('vehicle_journeys').search params[:q] - @vehicle_journeys = @q.result.paginate(:page => params[:page], :per_page => @ppage) + @vehicle_journeys = @q.result(distinct: true).paginate(:page => params[:page], :per_page => @ppage) @footnotes = route.line.footnotes.to_json @matrix = resource_class.matrix(@vehicle_journeys) @vehicle_journeys end + def ransack_periode_filter + if params[:q] && params[:q][:vehicle_journey_at_stops_departure_time_gteq] + params[:q] = params[:q].reject{|k| params[:q][k] == 'undefined'} + between = [:departure_time_gteq, :departure_time_lteq].map do |filter| + "2000-01-01 #{params[:q]["vehicle_journey_at_stops_#{filter}"]}:00 UTC" + end + { + :m => 'or', + :vehicle_journey_at_stops_departure_time_between => between.join(' to '), + :vehicle_journey_at_stops_id_null => params[:q][:vehicle_journey_without_departure_time] + } + end + end + + def filtered_ransack_params + if params[:q] + params[:q].except(:vehicle_journey_at_stops_departure_time_gteq, :vehicle_journey_at_stops_departure_time_lteq) + end + end + def adapted_params params.tap do |adapted_params| adapted_params.merge!( :route => parent) @@ -107,30 +129,15 @@ class VehicleJourneysController < ChouetteController @matrix = resource_class.matrix(@vehicle_journeys) end - def check_policy - authorize resource - end - def user_permissions @perms = {}.tap do |perm| ['vehicle_journeys.create', 'vehicle_journeys.edit', 'vehicle_journeys.destroy'].each do |name| - perm[name] = current_user.permissions.include?(name) + perm[name] = policy(:vehicle_journey).send("#{name.split('.').last}?") end - end - @perms = @perms.to_json + end.to_json end private - def ransack_params - if params[:q] - params[:q] = params[:q].reject{|k| params[:q][k] == 'undefined'} - [:departure_time_gteq, :departure_time_lteq].each do |filter| - time = params[:q]["vehicle_journey_at_stops_#{filter}"] - params[:q]["vehicle_journey_at_stops_#{filter}"] = "2000-01-01 #{time}:00 UTC" - end - end - end - def vehicle_journey_params params.require(:vehicle_journey).permit( { footnote_ids: [] } , :journey_pattern_id, :number, :published_journey_name, :published_journey_identifier, :comment, :transport_mode, diff --git a/app/controllers/workbenches_controller.rb b/app/controllers/workbenches_controller.rb index 1424fe03c..d621a28d7 100644 --- a/app/controllers/workbenches_controller.rb +++ b/app/controllers/workbenches_controller.rb @@ -37,10 +37,11 @@ class WorkbenchesController < BreadcrumbController end def sort_result collection - col = (Workbench.find(params[:id]).referentials.column_names + %w{lines}).include?(params[:sort]) ? params[:sort] : 'name' + col = (Workbench.find(params[:id]).referentials.column_names + %w{lines validity_period}).include?(params[:sort]) ? params[:sort] : 'name' dir = %w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc' - if col == "lines" - collection.joins(:metadatas).group("referentials.id").order("sum(array_length(referential_metadata.line_ids,1)) #{dir}") + + if ['lines', 'validity_period'].include?(col) + collection.send("order_by_#{col}", dir) else collection.order("#{col} #{dir}") end diff --git a/app/helpers/access_links_helper.rb b/app/helpers/access_links_helper.rb new file mode 100644 index 000000000..8df452f65 --- /dev/null +++ b/app/helpers/access_links_helper.rb @@ -0,0 +1,7 @@ +module AccessLinksHelper + def access_link_type_label_pairs + Chouette::AccessLink + .access_link_types + .zip_map { |type| t("connection_link_types.label.#{type}") } + end +end diff --git a/app/helpers/access_points_helper.rb b/app/helpers/access_points_helper.rb index c5e9f672e..c954e6cad 100644 --- a/app/helpers/access_points_helper.rb +++ b/app/helpers/access_points_helper.rb @@ -1,28 +1,14 @@ module AccessPointsHelper - 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 + + + def access_point_type_label_pairs + Chouette::AccessPoint + .access_point_types + .zip_map { |access_point_type| t("access_types.label.#{access_point_type}") } end - + def pair_key(access_link) "#{access_link.access_point.id}-#{access_link.stop_area.id}" end - + end diff --git a/app/helpers/common_helpers.rb b/app/helpers/common_helpers.rb new file mode 100644 index 000000000..29cabddac --- /dev/null +++ b/app/helpers/common_helpers.rb @@ -0,0 +1,26 @@ + +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/connection_links_helper.rb b/app/helpers/connection_links_helper.rb new file mode 100644 index 000000000..d9c201028 --- /dev/null +++ b/app/helpers/connection_links_helper.rb @@ -0,0 +1,8 @@ +module ConnectionLinksHelper + + def connection_link_type_label_pairs + Chouette::ConnectionLink + .connection_link_types + .zip_map { |type| t("connection_link_types.label.#{type}") } + end +end diff --git a/app/helpers/core_helper.rb b/app/helpers/core_helper.rb new file mode 100644 index 000000000..af2f6664c --- /dev/null +++ b/app/helpers/core_helper.rb @@ -0,0 +1,7 @@ +module CoreHelper + module ::Enumerable + def zip_map + map { |ele| [ele, yield(ele)] } + end + end +end diff --git a/app/helpers/networks_helper.rb b/app/helpers/networks_helper.rb new file mode 100644 index 000000000..b881ce078 --- /dev/null +++ b/app/helpers/networks_helper.rb @@ -0,0 +1,7 @@ +module NetworksHelper + + def source_type_name_label_pairs + Chouette::Network.source_type_names + .zip_map { |source_type_name| t("source_types.label.#{source_type_name}") } + end +end diff --git a/app/helpers/newapplication_helper.rb b/app/helpers/newapplication_helper.rb index c9da544d1..42fca489f 100644 --- a/app/helpers/newapplication_helper.rb +++ b/app/helpers/newapplication_helper.rb @@ -16,7 +16,7 @@ module NewapplicationHelper end columns.map do |k, v| - if ["ID Codif", "Oid", "OiD", "ID Reflex", "Arrêt de départ", "Arrêt d'arrivée"].include? k + if ["ID Codif", "Oid", "OiD", "ID Reflex", "Arrêt de départ", "Arrêt d'arrivée", "Période de validité englobante"].include? k hcont << content_tag(:th, k) else hcont << content_tag(:th, sortable_columns(collection, k)) @@ -30,6 +30,7 @@ module NewapplicationHelper body = content_tag :tbody do collection.collect do |item| + content_tag :tr do bcont = [] @@ -47,17 +48,17 @@ module NewapplicationHelper else item.try(attribute) end - if attribute == 'name' + if attribute == 'name' or attribute == 'comment' lnk = [] - unless item.class.to_s == 'Calendar' or item.class.to_s == 'Referential' + unless item.class == Calendar or item.class == Referential if current_referential lnk << current_referential lnk << item.line if item.respond_to? :line - lnk << item if item.class.to_s == 'Chouette::RoutingConstraintZone' + lnk << item.route.line if item.class == Chouette::RoutingConstraintZone lnk << item if item.respond_to? :line_referential lnk << item.stop_area if item.respond_to? :stop_area - lnk << item if item.respond_to? :stop_points + lnk << item if item.respond_to? :stop_points or item.class.to_s == 'Chouette::TimeTable' elsif item.respond_to? :referential lnk << item.referential end @@ -101,14 +102,14 @@ module NewapplicationHelper polymorph_url << action end - unless item.class.to_s == 'Calendar' or item.class.to_s == 'Referential' + unless item.class == Calendar or item.class == Referential if current_referential polymorph_url << current_referential polymorph_url << item.line if item.respond_to? :line - polymorph_url << item if item.class.to_s == 'Chouette::RoutingConstraintZone' + polymorph_url << item.route.line if item.class == 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 + polymorph_url << item if item.respond_to? :stop_points or item.class.to_s == 'Chouette::TimeTable' elsif item.respond_to? :referential polymorph_url << item.referential end diff --git a/app/helpers/rule_parameter_sets_helper.rb b/app/helpers/rule_parameter_sets_helper.rb index 538a5cddd..bb210d9cd 100644 --- a/app/helpers/rule_parameter_sets_helper.rb +++ b/app/helpers/rule_parameter_sets_helper.rb @@ -18,6 +18,11 @@ module RuleParameterSetsHelper t "false" end + def transport_mode_label_pairs + Chouette::TransportMode + .all + .zip_map { |mode| t("transport_modes.label.#{mode}") } + end end diff --git a/app/helpers/stop_area_copies_helper.rb b/app/helpers/stop_area_copies_helper.rb new file mode 100644 index 000000000..023a9d750 --- /dev/null +++ b/app/helpers/stop_area_copies_helper.rb @@ -0,0 +1,8 @@ +module StopAreaCopiesHelper + + def label_stop_area_types(*stop_area_types) + stop_area_types + .flatten + .zip_map { |stop_area_type| t("area_types.label.#{stop_area_type}") } + end +end diff --git a/app/helpers/stop_areas_helper.rb b/app/helpers/stop_areas_helper.rb index 2188a272d..3e04fac7d 100644 --- a/app/helpers/stop_areas_helper.rb +++ b/app/helpers/stop_areas_helper.rb @@ -33,27 +33,6 @@ module StopAreasHelper @stop_area.stop_area_type == 'stop_place' || @stop_area.stop_area_type == 'commercial_stop_point' end - 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 def pair_key(access_link) "#{access_link.access_point.id}-#{access_link.stop_area.id}" diff --git a/app/helpers/time_tables_helper.rb b/app/helpers/time_tables_helper.rb index 9fdb791b1..b380a2b0a 100644 --- a/app/helpers/time_tables_helper.rb +++ b/app/helpers/time_tables_helper.rb @@ -1,3 +1,178 @@ +require 'date' + module TimeTablesHelper -end + def month_periode_enum(years) + start_date = Date.today - years.years + end_date = Date.today + years.years + (start_date..end_date).map(&:beginning_of_month).uniq.map(&:to_s) + end + + def new_alt_calendar(options = {}, &block) + raise(ArgumentError, "No year given") unless options.has_key?(:year) + raise(ArgumentError, "No month given") unless options.has_key?(:month) + + block ||= Proc.new {|d| nil} + + month_names = (!defined?(I18n) || I18n.t("date.month_names").include?("missing")) ? Date::MONTHNAMES.dup : I18n.t("date.month_names") + + defaults = { + :table_id => "calendar-#{options[:year]}-#{"%02d" % options[:month]}", + :table_class => 'calendar', + :month_name_class => 'monthName', + :other_month_class => 'outsideMonth', + :day_name_class => 'dayName', + :day_class => 'day', + :abbrev => false, + :first_day_of_week => 0, + :accessible => false, + :show_today => true, + :previous_month_text => nil, + :next_month_text => nil, + :month_header => true, + :calendar_title => month_names[options[:month]], + :summary => "Calendrier pour #{month_names[options[:month]]} #{options[:year]}" + } + options = defaults.merge options + + first = Date.civil(options[:year], options[:month], 1) + last = Date.civil(options[:year], options[:month], -1) + + first_weekday = first_day_of_week(options[:first_day_of_week]) + last_weekday = last_day_of_week(options[:first_day_of_week]) + + day_names = (!defined?(I18n) || I18n.t("date.day_names").include?("missing")) ? Date::DAYNAMES : I18n.t("date.day_names") + abbr_day_names = (!defined?(I18n) || I18n.t("date.abbr_day_names").include?("missing")) ? Date::ABBR_DAYNAMES : I18n.t("date.abbr_day_names") + week_days = (0..6).to_a + first_weekday.times do + week_days.push(week_days.shift) + end + + # TODO Use some kind of builder instead of straight HTML + cal = %(<table id="#{options[:table_id]}" class="#{options[:table_class]}" border="0" cellspacing="0" cellpadding="0" summary="#{options[:summary]}">) + cal << %(<thead>) + + if (options[:month_header]) + cal << %(<tr>) + cal << %(<th class='weekNumber' scope="col"></th>) + if options[:previous_month_text] or options[:next_month_text] + cal << %(<th colspan="2">#{options[:previous_month_text]}</th>) + colspan=3 + else + colspan=7 + end + cal << %(<th colspan="#{colspan}" class="#{options[:month_name_class]}">#{options[:calendar_title]}</th>) + cal << %(<th colspan="2">#{options[:next_month_text]}</th>) if options[:next_month_text] + cal << %(</tr>) + end + + cal << %(<tr class="#{options[:day_name_class]}">) + cal << %(<th class='weekNumber' scope="col"></th>) + + week_days.each do |wday| + cal << %(<th id="#{th_id(Date::DAYNAMES[wday], options[:table_id])}" scope="col">) + cal << (options[:abbrev] ? %(<abbr title="#{day_names[wday]}">#{t("calendars.days.#{Date::DAYNAMES[wday].downcase}")}</abbr>) : t("calendars.days.#{Date::DAYNAMES[wday].downcase}")) + cal << %(</th>) + end + + cal << "</tr></thead><tbody><tr>" + + # previous month + beginning_of_week(first, first_weekday).upto(first - 1) do |d| + cal << "<td class='weekNumber'>S#{d.strftime("%W").to_s}</td>" if d.wday == first_weekday + cal << generate_other_month_cell(d, options) + end unless first.wday == first_weekday + + first.upto(last) do |cur| + cell_text, cell_attrs = block.call(cur) + cell_text ||= cur.mday + cell_attrs ||= {} + cell_attrs[:headers] = th_id(cur, options[:table_id]) + cell_attrs[:class] ||= options[:day_class] + cell_attrs[:class] += " weekend" if [0, 6].include?(cur.wday) + today = (Time.respond_to?(:zone) && !(zone = Time.zone).nil? ? zone.now.to_date : Date.today) + cell_attrs[:class] += " today" if (cur == today) and options[:show_today] + + cal << "<td class='weekNumber'>S#{cur.strftime("%W").to_s}</td>" if cur.wday == first_weekday + + cal << generate_cell(cell_text, cell_attrs) + cal << "</tr><tr>" if cur.wday == last_weekday + end + + # next month + (last + 1).upto(beginning_of_week(last + 7, first_weekday) - 1) do |d| + cal << generate_other_month_cell(d, options) + end unless last.wday == last_weekday + + cal << "</tr></tbody></table>" + cal.respond_to?(:html_safe) ? cal.html_safe : cal + end + + private + + def first_day_of_week(day) + day + end + + def last_day_of_week(day) + if day > 0 + day - 1 + else + 6 + end + end + + def days_between(first, second) + if first > second + second + (7 - first) + else + second - first + end + end + + def beginning_of_week(date, start = 1) + days_to_beg = days_between(start, date.wday) + date - days_to_beg + end + + def generate_cell(cell_text, cell_attrs) + cell_attrs = cell_attrs.map {|k, v| %(#{k}="#{v}") }.join(" ") + "<td #{cell_attrs}>#{cell_text}</td>" + end + + def generate_other_month_cell(date, options) + cell_attrs = {} + cell_attrs[:headers] = th_id(date, options[:table_id]) + cell_attrs[:class] = options[:other_month_class] + cell_attrs[:class] += " weekend" if weekend?(date) + cell_attrs[:title] ||= date.strftime("%W").to_i if options[:first_day_of_week] == 1 + + cell_text = date.day + if options[:accessible] + cell_text += %(<span class="hidden"> #{month_names[date.month]}</span>) + end + + generate_cell(date.day, cell_attrs) + end + + # Calculates id for th element. + # derived from calendar_id and dow. + # + # Params: + # `day` can be either Date or DOW('Sunday', 'Monday') + def th_id(day, calendar_id) + return th_id(Date::DAYNAMES[day.wday], calendar_id) if day.is_a?(Date) + "#{calendar_id}-#{day[0..2].downcase}" + end + + def weekend?(date) + [0, 6].include?(date.wday) + end + + class Engine < Rails::Engine # :nodoc: + ActiveSupport.on_load(:action_view) do + include CalendarHelper + end + end if defined? Rails::Engine + +end diff --git a/app/helpers/vehicle_journeys_helper.rb b/app/helpers/vehicle_journeys_helper.rb index e70f2954b..6877abd11 100644 --- a/app/helpers/vehicle_journeys_helper.rb +++ b/app/helpers/vehicle_journeys_helper.rb @@ -41,6 +41,12 @@ module VehicleJourneysHelper end end + def route_journey_pattern_label_pairs route + route + .journey_patterns + .zip_map { |jp| journey_name(jp) } + end + def edit_vehicle_title( vehicle) return t('vehicle_journeys.edit.title_stopless', :name => vehicle_name( vehicle)) if vehicle.vehicle_journey_at_stops.empty? first_vjas = vehicle.vehicle_journey_at_stops.first diff --git a/app/inputs/tags_input.rb b/app/inputs/tags_input.rb index 4fbf0465f..1dc6129ee 100644 --- a/app/inputs/tags_input.rb +++ b/app/inputs/tags_input.rb @@ -1,19 +1,16 @@ -class TagsInput < Formtastic::Inputs::StringInput - - def to_html - input_wrapping do - label_html << - '<span id="tagsContainer"></span>'.html_safe << - builder.text_field(method, input_html_options) - end +class TagsInput < SimpleForm::Inputs::CollectionInput + enable :placeholder + + def input(wrapper_options = {}) + @collection ||= @builder.object.send(attribute_name) + label_method, value_method = detect_collection_methods + + merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) + merged_input_options.reverse_merge!(multiple: true) + + @builder.collection_select( + attribute_name, collection, value_method, label_method, + input_options, merged_input_options + ) end - - def input_html_options - super.merge({ - :required => nil, - :autofocus => nil, - :class => 'tm-input', - }) - end - end diff --git a/app/models/chouette/line.rb b/app/models/chouette/line.rb index 27a37a7f4..f44375e7d 100644 --- a/app/models/chouette/line.rb +++ b/app/models/chouette/line.rb @@ -14,20 +14,20 @@ class Chouette::Line < Chouette::ActiveRecord belongs_to :company belongs_to :network + belongs_to :line_referential has_array_of :secondary_companies, class_name: 'Chouette::Company' has_many :routes, :dependent => :destroy has_many :journey_patterns, :through => :routes has_many :vehicle_journeys, :through => :journey_patterns + has_many :routing_constraint_zones, through: :routes has_and_belongs_to_many :group_of_lines, :class_name => 'Chouette::GroupOfLine', :order => 'group_of_lines.name' has_many :footnotes, :inverse_of => :line, :validate => :true, :dependent => :destroy accepts_nested_attributes_for :footnotes, :reject_if => :all_blank, :allow_destroy => true - has_many :routing_constraint_zones - attr_reader :group_of_line_tokens # validates_presence_of :network @@ -76,4 +76,8 @@ class Chouette::Line < Chouette::ActiveRecord [name, company.try(:name)].compact.join(' - ') end + def companies + line_referential.companies.where(id: ([company_id] + Array(secondary_company_ids)).compact) + end + end diff --git a/app/models/chouette/route.rb b/app/models/chouette/route.rb index 9de7d7470..429189ff5 100644 --- a/app/models/chouette/route.rb +++ b/app/models/chouette/route.rb @@ -5,7 +5,7 @@ class Chouette::Route < Chouette::TridentActiveRecord extend ActiveModel::Naming enumerize :direction, in: %i(straight_forward backward clockwise counter_clockwise north north_west west south_west south south_east east north_east) - enumerize :wayback, in: %i(straight_forward backward), default: :backward + enumerize :wayback, in: %i(straight_forward backward), default: :straight_forward # FIXME http://jira.codehaus.org/browse/JRUBY-6358 self.primary_key = "id" @@ -16,6 +16,7 @@ class Chouette::Route < Chouette::TridentActiveRecord belongs_to :line + has_many :routing_constraint_zones has_many :journey_patterns, :dependent => :destroy has_many :vehicle_journeys, :dependent => :destroy do def timeless diff --git a/app/models/chouette/routing_constraint_zone.rb b/app/models/chouette/routing_constraint_zone.rb index 681069416..6a8847e4d 100644 --- a/app/models/chouette/routing_constraint_zone.rb +++ b/app/models/chouette/routing_constraint_zone.rb @@ -1,9 +1,24 @@ class Chouette::RoutingConstraintZone < Chouette::TridentActiveRecord - belongs_to :line - has_array_of :stop_areas, class_name: 'Chouette::StopArea' + belongs_to :route + has_array_of :stop_points, class_name: 'Chouette::StopPoint' - validates_presence_of :name, :stop_area_ids, :line_id - validates :stop_areas, length: { minimum: 2 } + validates_presence_of :name, :stop_point_ids, :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 - self.primary_key = 'id' + def stop_points_belong_to_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 + 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 + + def stop_points_count + stop_points.count + end + + def route_name + route.name + end end diff --git a/app/models/chouette/stop_point.rb b/app/models/chouette/stop_point.rb index b77189fc1..e0f947487 100644 --- a/app/models/chouette/stop_point.rb +++ b/app/models/chouette/stop_point.rb @@ -2,7 +2,7 @@ module Chouette class StopPoint < TridentActiveRecord include ForBoardingEnumerations include ForAlightingEnumerations - + # FIXME http://jira.codehaus.org/browse/JRUBY-6358 self.primary_key = "id" @@ -16,7 +16,9 @@ module Chouette validates_presence_of :stop_area validate :stop_area_id_validation - scope :default_order, order("position") + scope :default_order, -> { order("position") } + + delegate :name, to: :stop_area before_destroy :remove_dependent_journey_pattern_stop_points def remove_dependent_journey_pattern_stop_points @@ -25,7 +27,7 @@ module Chouette jp.stop_point_ids = jp.stop_point_ids - [id] end end - end + end def stop_area_id_validation if stop_area_id.nil? diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb index 7afdc4529..086e6fa77 100644 --- a/app/models/chouette/time_table.rb +++ b/app/models/chouette/time_table.rb @@ -43,6 +43,19 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord [Chouette::TimeTable.maximum(:end_date)].compact.max end + def month_inspect(date) + (date.beginning_of_month..date.end_of_month).map do |d| + { + day: I18n.l(d, format: '%A'), + 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) @@ -454,4 +467,3 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord tt end end - diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb index 0aab9d0ed..4d7d596d8 100644 --- a/app/models/chouette/vehicle_journey.rb +++ b/app/models/chouette/vehicle_journey.rb @@ -49,27 +49,61 @@ module Chouette def vehicle_journey_at_stops_matrix at_stops = self.vehicle_journey_at_stops.to_a.dup - filling = route.stop_points.map(&:id) - at_stops.map(&:stop_point_id) - filling.each do |id| - at_stops.insert(route.stop_points.map(&:id).index(id), Chouette::VehicleJourneyAtStop.new()) + (route.stop_points.map(&:id) - at_stops.map(&:stop_point_id)).each do |id| + # Set stop_point id for fake vjas with no departure time yep. + params = {} + params[:stop_point_id] = id if journey_pattern.stop_points.map(&:id).include?(id) + at_stops.insert(route.stop_points.map(&:id).index(id), Chouette::VehicleJourneyAtStop.new(params)) end at_stops end + def create_or_find_vjas_from_state vjas + return vehicle_journey_at_stops.find(vjas['id']) if vjas['id'] + stop_point = Chouette::StopPoint.find_by(objectid: vjas['stop_point_objectid']) + stop = vehicle_journey_at_stops.create(stop_point: stop_point) + vjas['id'] = stop.id + vjas['new_record'] = true + stop + end + def update_vjas_from_state state state.each do |vjas| next if vjas["dummy"] - stop = vehicle_journey_at_stops.find(vjas['id']) if vjas['id'] - if stop - 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") - end + 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") + end + end + stop = create_or_find_vjas_from_state(vjas) + stop.update_attributes(params) + vjas.delete('errors') + vjas['errors'] = stop.errors if stop.errors.any? + end + end + + def state_update_vjas? vehicle_journey_at_stops + departure_times = vehicle_journey_at_stops.map do |vjas| + "#{vjas['departure_time']['hour']}:#{vjas['departure_time']['minute']}" + end + times = departure_times.uniq + (times.count == 1 && times[0] == '00:00') ? false : true + end + + def update_has_and_belongs_to_many_from_state item + ['time_tables', 'footnotes'].each do |assos| + saved = self.send(assos).map(&:id) + + (saved - item[assos].map{|t| t['id']}).each do |id| + self.send(assos).delete(self.send(assos).find(id)) + end + + item[assos].each do |t| + klass = "Chouette::#{assos.classify}".constantize + unless saved.include?(t['id']) + self.send(assos) << klass.find(t['id']) end - stop.update_attributes(params) - vjas.delete('errors') - vjas['errors'] = stop.errors if stop.errors.any? end end end @@ -81,17 +115,30 @@ module Chouette vj = find_by(objectid: item['objectid']) || state_create_instance(route, item) next if item['deletable'] && vj.persisted? && vj.destroy - vj.update_vjas_from_state(item['vehicle_journey_at_stops']) + if vj.state_update_vjas?(item['vehicle_journey_at_stops']) + vj.update_vjas_from_state(item['vehicle_journey_at_stops']) + end + vj.update_attributes(state_permited_attributes(item)) + vj.update_has_and_belongs_to_many_from_state(item) item['errors'] = vj.errors if vj.errors.any? end + + # Delete ids of new object from state if we had to rollback if state.any? {|item| item['errors']} - state.map {|item| item.delete('objectid') if item['new_record']} + state.map do |item| + item.delete('objectid') if item['new_record'] + item['vehicle_journey_at_stops'].map {|vjas| vjas.delete('id') if vjas['new_record'] } + end raise ::ActiveRecord::Rollback end end - state.map {|item| item.delete('new_record')} + # Remove new_record flag && deleted item from state if transaction has been saved + state.map do |item| + item.delete('new_record') + item['vehicle_journey_at_stops'].map {|vjas| vjas.delete('new_record') } + end state.delete_if {|item| item['deletable']} end diff --git a/app/models/import.rb b/app/models/import.rb index c407daa78..d0736ab0b 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -4,11 +4,12 @@ class Import < ActiveRecord::Base belongs_to :referential extend Enumerize - enumerize :status, in: %i(new pending successful failed canceled) + enumerize :status, in: %i(new pending successful failed running aborted canceled) validates :file, presence: true before_create do self.token_download = SecureRandom.urlsafe_base64 + self.status = Import.status.new end end diff --git a/app/models/netex_import.rb b/app/models/netex_import.rb index 27f5846af..0da008d2e 100644 --- a/app/models/netex_import.rb +++ b/app/models/netex_import.rb @@ -1,3 +1,13 @@ +require 'net/http' class NetexImport < Import + after_create :launch_java_import + def launch_java_import + logger.warn "Call iev get #{Rails.configuration.iev_url}/boiv_iev/referentials/importer/new?id=#{id}" + begin + Net::HTTP.get(Rails.configuration.iev_url, "/boiv_iev/referentials/importer/new?id=#{id}") + rescue + logger.error("IEV server error") + end + end end diff --git a/app/models/referential.rb b/app/models/referential.rb index b6a83c6c3..50db32637 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -45,6 +45,8 @@ class Referential < ActiveRecord::Base scope :ready, -> { where(ready: true) } scope :in_periode, ->(periode) { where(id: referential_ids_in_periode(periode)) } 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}") } def lines if metadatas.blank? @@ -232,11 +234,19 @@ class Referential < ActiveRecord::Base def self.referential_ids_in_periode(range) subquery = "SELECT DISTINCT(public.referential_metadata.referential_id) FROM public.referential_metadata, LATERAL unnest(periodes) period " - subquery << "WHERE period && '#{ActiveRecord::ConnectionAdapters::PostgreSQLColumn.range_to_string(range)}'" + subquery << "WHERE period && '#{range_to_string(range)}'" query = "SELECT * FROM public.referentials WHERE referentials.id IN (#{subquery})" self.connection.select_values(query).map(&:to_i) end + # Copied from Rails 4.1 activerecord/lib/active_record/connection_adapters/postgresql/cast.rb + # TODO: Relace with the appropriate Rais 4.2 / 5.x helper if one is found. + def self.range_to_string(object) + from = object.begin.respond_to?(:infinite?) && object.begin.infinite? ? '' : object.begin + to = object.end.respond_to?(:infinite?) && object.end.infinite? ? '' : object.end + "[#{from},#{to}#{object.exclude_end? ? ')' : ']'}" + end + def overlapped_referential_ids return [] unless metadatas.present? @@ -248,7 +258,7 @@ class Referential < ActiveRecord::Base not_myself = "and referential_id != #{id}" if persisted? periods_query = periodes.map do |periode| - "period && '#{ActiveRecord::ConnectionAdapters::PostgreSQLColumn.range_to_string(periode)}'" + "period && '[#{periode.begin},#{periode.end})'" end.join(" OR ") query = "select distinct(public.referential_metadata.referential_id) FROM public.referential_metadata, unnest(line_ids) line, LATERAL unnest(periodes) period diff --git a/app/models/referential_metadata.rb b/app/models/referential_metadata.rb index 62faf5541..3ec8398e0 100644 --- a/app/models/referential_metadata.rb +++ b/app/models/referential_metadata.rb @@ -12,6 +12,25 @@ class ReferentialMetadata < ActiveRecord::Base scope :include_lines, -> (line_ids) { where('line_ids && ARRAY[?]::bigint[]', line_ids) } scope :include_dateranges, -> (dateranges) { where('periodes && ARRAY[?]', dateranges) } +# Transform Wed, 22 Feb 2017...Fri, 24 Feb 2017 into Wed, 22 Feb 2017..Thu, 23 Feb 2017 + def periodes + attributes["periodes"].tap do | periods | + return periods unless periods + return adapted_periods(periods) + end + end + + def adapted_periods(periods) + periods.map do | period | + if period.try(:exclude_end?) + period.begin .. (period.end - 1) + else + period + end + end + end + private :adapted_periods + class Period include ActiveAttr::Model include ActiveAttr::MultiParameterAttributes diff --git a/app/models/user.rb b/app/models/user.rb index b921cdef8..8e73aa1d5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -21,7 +21,6 @@ class User < ActiveRecord::Base validates :organisation, :presence => true validates :email, :presence => true, :uniqueness => true validates :name, :presence => true - validate :permissions_unique_and_nonempty before_validation(:on => :create) do self.password ||= Devise.friendly_token.first(6) @@ -32,16 +31,14 @@ class User < ActiveRecord::Base @@edit_offer_permissions = ['routes.create', 'routes.edit', 'routes.destroy', 'journey_patterns.create', 'journey_patterns.edit', 'journey_patterns.destroy', 'vehicle_journeys.create', 'vehicle_journeys.edit', 'vehicle_journeys.destroy', 'time_tables.create', 'time_tables.edit', 'time_tables.destroy', 'footnotes.edit', 'footnotes.create', 'footnotes.destroy', 'routing_constraint_zones.create', 'routing_constraint_zones.edit', - 'routing_constraint_zones.destroy'] + 'routing_constraint_zones.destroy', 'referentials.create', 'referentials.edit', 'referentials.destroy'] def cas_extra_attributes=(extra_attributes) extra = extra_attributes.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo} self.name = extra[:full_name] self.email = extra[:email] self.organisation = Organisation.sync_update extra[:organisation_code], extra[:organisation_name], extra[:functional_scope] - if extra[:permissions] && extra[:permissions].include?('boiv:edit-offer') - self.permissions = @@edit_offer_permissions - end + self.permissions = extra[:permissions].include?('boiv:edit-offer') ? @@edit_offer_permissions : [] end def self.portail_api_request @@ -69,10 +66,7 @@ class User < ActiveRecord::Base user.locked_at = el['locked_at'] user.organisation = Organisation.sync_update el['organization_code'], el['organization_name'], el['functional_scope'] user.synced_at = Time.now - - if el['permissions'] && el['permissions'].include?('boiv:edit-offer') - user.permissions = @@edit_offer_permissions - end + user.permissions = el['permissions'].include?('boiv:edit-offer') ? @@edit_offer_permissions : [] user.save puts "✓ user #{user.username} has been updated" unless Rails.env.test? end @@ -91,10 +85,4 @@ class User < ActiveRecord::Base end end - def permissions_unique_and_nonempty - if permissions && permissions.any? - errors.add(:permissions, I18n.t('activerecord.errors.models.calendar.attributes.permissions.must_be_unique')) if permissions.uniq.length != permissions.length - errors.add(:permissions, I18n.t('activerecord.errors.models.calendar.attributes.permissions.must_be_nonempty')) if permissions.include? '' - end - end end diff --git a/app/models/user_context.rb b/app/models/user_context.rb new file mode 100644 index 000000000..e0a856e4b --- /dev/null +++ b/app/models/user_context.rb @@ -0,0 +1,8 @@ +class UserContext + attr_reader :user, :context + + def initialize(user, context = {}) + @user = user + @context = context + end +end diff --git a/app/policies/acces_point_policy.rb b/app/policies/acces_point_policy.rb index 4f604693c..904b7a242 100644 --- a/app/policies/acces_point_policy.rb +++ b/app/policies/acces_point_policy.rb @@ -10,11 +10,11 @@ class AccessPointPolicy < ApplicationPolicy end def edit? - organisation_match?(via_referential: true) && user.has_permission?('access_points.edit') + organisation_match? && user.has_permission?('access_points.edit') end def destroy? - organisation_match?(via_referential: true) && user.has_permission?('access_points.destroy') + organisation_match? && user.has_permission?('access_points.destroy') end def update? ; edit? end diff --git a/app/policies/access_link_policy.rb b/app/policies/access_link_policy.rb index 8e7a86490..73b2d1baa 100644 --- a/app/policies/access_link_policy.rb +++ b/app/policies/access_link_policy.rb @@ -10,11 +10,11 @@ class AccessLinkPolicy < ApplicationPolicy end def edit? - organisation_match?(via_referential: true) && user.has_permission?('access_links.edit') + organisation_match? && user.has_permission?('access_links.edit') end def destroy? - organisation_match?(via_referential: true) && user.has_permission?('access_links.destroy') + organisation_match? && user.has_permission?('access_links.destroy') end def update? ; edit? end diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb index 07138b38e..4a2d760fb 100644 --- a/app/policies/application_policy.rb +++ b/app/policies/application_policy.rb @@ -1,11 +1,21 @@ class ApplicationPolicy attr_reader :user, :record - def initialize(user, record) - @user = user + def initialize(user_context, record) + @user = user_context.user + @referential = user_context.context[:referential] @record = record end + attr_accessor :referential + def referential + @referential ||= record_referential + end + + def record_referential + record.referential if record.respond_to?(:referential) + end + def index? false end @@ -38,8 +48,14 @@ class ApplicationPolicy Pundit.policy_scope!(user, record.class) end - def organisation_match?(via_referential: false) - eval("user.organisation == record#{'.referential' if via_referential}.organisation") + def organisation_match? + user.organisation == organisation + end + + def organisation + # When sending permission to react UI, we don't have access to record object for edit & destroy.. actions + organisation = record.is_a?(Symbol) ? nil : record.try(:organisation) + organisation or referential.try :organisation end class Scope diff --git a/app/policies/connection_link_policy.rb b/app/policies/connection_link_policy.rb index cc49f575f..abefd741c 100644 --- a/app/policies/connection_link_policy.rb +++ b/app/policies/connection_link_policy.rb @@ -10,11 +10,11 @@ class ConnectionLinkPolicy < ApplicationPolicy end def edit? - organisation_match?(via_referential: true) && user.has_permission?('connection_links.edit') + organisation_match? && user.has_permission?('connection_links.edit') end def destroy? - organisation_match?(via_referential: true) && user.has_permission?('connection_links.destroy') + organisation_match? && user.has_permission?('connection_links.destroy') end def update? ; edit? end diff --git a/app/policies/journey_pattern_policy.rb b/app/policies/journey_pattern_policy.rb index a11fd6bcc..56f32613c 100644 --- a/app/policies/journey_pattern_policy.rb +++ b/app/policies/journey_pattern_policy.rb @@ -6,15 +6,16 @@ class JourneyPatternPolicy < ApplicationPolicy end def create? - user.has_permission?('journey_patterns.create') # organisation match via referential is checked in the view + # organisation match via referential is checked in the view + user.has_permission?('journey_patterns.create') end def edit? - organisation_match?(via_referential: true) && user.has_permission?('journey_patterns.edit') + organisation_match? && user.has_permission?('journey_patterns.edit') end def destroy? - organisation_match?(via_referential: true) && user.has_permission?('journey_patterns.destroy') + organisation_match? && user.has_permission?('journey_patterns.destroy') end def update? ; edit? end diff --git a/app/policies/referential_policy.rb b/app/policies/referential_policy.rb index 1175ba5c6..8d366aff7 100644 --- a/app/policies/referential_policy.rb +++ b/app/policies/referential_policy.rb @@ -6,24 +6,30 @@ class ReferentialPolicy < ApplicationPolicy end def create? - true + user.has_permission?('referentials.create') end def edit? - organisation_match? + organisation_match? && user.has_permission?('referentials.edit') end - def update? - edit? && !record.archived? + def destroy? + organisation_match? && user.has_permission?('referentials.destroy') end def archive? edit? end + def clone? + organisation_match? && create? + end + def unarchive? ; archive? end - def new? ; create? end - def destroy? ; edit? end + def update? ; edit? end + def new? ; create? end end + + diff --git a/app/policies/route_policy.rb b/app/policies/route_policy.rb index 0f42b7f08..c4d048f2a 100644 --- a/app/policies/route_policy.rb +++ b/app/policies/route_policy.rb @@ -10,11 +10,11 @@ class RoutePolicy < ApplicationPolicy end def edit? - organisation_match?(via_referential: true) && user.has_permission?('routes.edit') + organisation_match? && user.has_permission?('routes.edit') end def destroy? - organisation_match?(via_referential: true) && user.has_permission?('routes.destroy') + organisation_match? && user.has_permission?('routes.destroy') end def update? ; edit? end diff --git a/app/policies/routing_constraint_zone_policy.rb b/app/policies/routing_constraint_zone_policy.rb index fbf322066..3126241f0 100644 --- a/app/policies/routing_constraint_zone_policy.rb +++ b/app/policies/routing_constraint_zone_policy.rb @@ -10,11 +10,11 @@ class RoutingConstraintZonePolicy < ApplicationPolicy end def edit? - organisation_match?(via_referential: true) && user.has_permission?('routing_constraint_zones.edit') + organisation_match? && user.has_permission?('routing_constraint_zones.edit') end def destroy? - organisation_match?(via_referential: true) && user.has_permission?('routing_constraint_zones.destroy') + organisation_match? && user.has_permission?('routing_constraint_zones.destroy') end def update? ; edit? end diff --git a/app/policies/time_table_policy.rb b/app/policies/time_table_policy.rb index 1d14c646a..6ca02f451 100644 --- a/app/policies/time_table_policy.rb +++ b/app/policies/time_table_policy.rb @@ -10,11 +10,11 @@ class TimeTablePolicy < ApplicationPolicy end def edit? - organisation_match?(via_referential: true) && user.has_permission?('time_tables.edit') + organisation_match? && user.has_permission?('time_tables.edit') end def destroy? - organisation_match?(via_referential: true) && user.has_permission?('time_tables.destroy') + organisation_match? && user.has_permission?('time_tables.destroy') end def update? ; edit? end diff --git a/app/policies/vehicle_journey_policy.rb b/app/policies/vehicle_journey_policy.rb index 785c2bb1f..ae3680adf 100644 --- a/app/policies/vehicle_journey_policy.rb +++ b/app/policies/vehicle_journey_policy.rb @@ -10,11 +10,11 @@ class VehicleJourneyPolicy < ApplicationPolicy end def edit? - organisation_match?(via_referential: true) && user.has_permission?('vehicle_journeys.edit') + organisation_match? && user.has_permission?('vehicle_journeys.edit') end def destroy? - organisation_match?(via_referential: true) && user.has_permission?('vehicle_journeys.destroy') + organisation_match? && user.has_permission?('vehicle_journeys.destroy') end def update? ; edit? end diff --git a/app/views/access_links/_form.html.slim b/app/views/access_links/_form.html.slim index 463cdf9e3..429656115 100644 --- a/app/views/access_links/_form.html.slim +++ b/app/views/access_links/_form.html.slim @@ -5,7 +5,7 @@ = form.input :stop_area_id , as: :hidden = form.input :link_orientation_type , as: :hidden = form.input :name - = form.input :access_link_type, as: :select, collection: Chouette::AccessLink.access_link_types, include_blank: true, member_label: Proc.new { |type| t("connection_link_types.label.#{type}") } + = form.input :access_link_type, as: :select, collection: access_link_type_label_pairs, include_blank: true = form.input :comment = form.input :link_distance = form.input :mobility_restricted_suitability, as: :select, collection: [[t("true"), true], [t("false"), false]], include_blank: true @@ -21,4 +21,4 @@ = form.actions do = form.action :submit, as: :button - = form.action :cancel, as: :link
\ No newline at end of file + = form.action :cancel, as: :link diff --git a/app/views/access_points/_form.html.slim b/app/views/access_points/_form.html.slim index 1874644d5..5ba7a6863 100644 --- a/app/views/access_points/_form.html.slim +++ b/app/views/access_points/_form.html.slim @@ -7,9 +7,8 @@ = form.input :name = form.input :access_point_type, as: :select, :input_html => {:disabled => !@access_point.new_record? }, - :collection => Chouette::AccessPoint.access_point_types, - include_blank: false, - :member_label => Proc.new { |access_point_type| t("access_types.label.#{access_point_type}") } + :collection => access_point_type_label_pairs, + include_blank: false = form.input :street_name = form.input :country_code = form.input :zip_code @@ -41,4 +40,4 @@ = form.actions do = form.action :submit, as: :button - = form.action :cancel, as: :link
\ No newline at end of file + = form.action :cancel, as: :link diff --git a/app/views/connection_links/_form.html.slim b/app/views/connection_links/_form.html.slim index afef3bba7..a3774ec88 100644 --- a/app/views/connection_links/_form.html.slim +++ b/app/views/connection_links/_form.html.slim @@ -1,9 +1,9 @@ = semantic_form_for [@referential, @connection_link] do |form| = form.inputs do = form.input :name - = form.input :connection_link_type, as: :select, :collection => Chouette::ConnectionLink.connection_link_types, :include_blank => true, :member_label => Proc.new { |type| t("connection_link_types.label.#{type}") } + = form.input :connection_link_type, as: :select, collection: connection_link_type_label_pairs, include_blank: true = form.input :comment - = form.input :link_distance, input_html: { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.connection_link.link_distance") } + = form.input :link_distance, input_html: { title: t("formtastic.titles#{format_restriction_for_locales(@referential)}.connection_link.link_distance") } = form.input :mobility_restricted_suitability, as: :select, :collection => [[t("true"), true], [t("false"), false]], include_blank: true = form.input :stairs_availability, as: :select, :collection => [[t("true"), true], [t("false"), false]], include_blank: true = form.input :lift_availability, as: :select, :collection => [[t("true"), true], [t("false"), false]], include_blank: true @@ -18,4 +18,4 @@ = form.actions do = form.action :submit, as: :button - = form.action :cancel, as: :link
\ No newline at end of file + = form.action :cancel, as: :link diff --git a/app/views/errors/not_allowed.html.slim b/app/views/errors/not_allowed.html.slim new file mode 100644 index 000000000..6c94328cc --- /dev/null +++ b/app/views/errors/not_allowed.html.slim @@ -0,0 +1,21 @@ +/ PageHeader += pageheader 'bug', + 'Erreur 403', + '' + +.page_content + .container-fluid + .row + .col-lg-12 + .alert.alert-danger + - if I18n.locale == :fr + 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." + + - else + p + strong = "You are not allowed to access the page you were looking for." + + p = "You can still continue the use the IBOO application. Thank you for understanding." diff --git a/app/views/journey_patterns_collections/show.html.slim b/app/views/journey_patterns_collections/show.html.slim index 33e13e3bb..b5607090f 100644 --- a/app/views/journey_patterns_collections/show.html.slim +++ b/app/views/journey_patterns_collections/show.html.slim @@ -11,9 +11,10 @@ .col-lg-12 #journey_patterns - = javascript_tag do | window.stopPoints = #{(@stop_points_list.to_json).html_safe}; | window.journeyPatternLength = #{@journey_patterns.total_entries()}; - | window.journeyPatternsPerPage = #{@ppage} + | window.journeyPatternsPerPage = #{@ppage}; + | window.perms = #{raw @perms} + = javascript_include_tag 'es6_browserified/journey_patterns/index.js' diff --git a/app/views/lines/index.html.slim b/app/views/lines/index.html.slim index ce4930d92..d7b6be5c8 100644 --- a/app/views/lines/index.html.slim +++ b/app/views/lines/index.html.slim @@ -20,6 +20,7 @@ { 'Oid' => Proc.new { |n| n.objectid.local_id }, :number => 'number', :name => 'name', + :deactivated => Proc.new{|n| n.deactivated? ? t('false') : t('true')}, 'networks.name' => Proc.new { |n| n.try(:network).try(:name) }, 'companies.name' => Proc.new { |n| n.try(:company).try(:name) }, :transport_mode => Proc.new { |n| n.transport_mode.nil? ? '-' : t("enumerize.line.transport_mode.#{n.try(:transport_mode)}") }, diff --git a/app/views/networks/_form.html.slim b/app/views/networks/_form.html.slim index f7b97c27d..7b048edc9 100644 --- a/app/views/networks/_form.html.slim +++ b/app/views/networks/_form.html.slim @@ -6,10 +6,10 @@ = form.input :version_date, as: :date_picker = form.input :description = form.input :source_name - = form.input :source_type_name, as: :select, :collection => Chouette::Network.source_type_names, :include_blank => true, :member_label => Proc.new { |mode| t("source_types.label.#{mode}") } + = form.input :source_type_name, as: :select, :collection => source_type_name_label_pairs, :include_blank => true = form.input :source_identifier = form.input :objectid, :required => !@network.new_record?, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.network.objectid")} = form.actions do = form.action :submit, as: :button - = form.action :cancel, as: :link
\ No newline at end of file + = form.action :cancel, as: :link diff --git a/app/views/referential_networks/_form.html.slim b/app/views/referential_networks/_form.html.slim index e7020ef68..a92fc7121 100644 --- a/app/views/referential_networks/_form.html.slim +++ b/app/views/referential_networks/_form.html.slim @@ -1,15 +1,15 @@ = semantic_form_for [@referential, @network] do |form| = form.inputs do - = form.input :name, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.network.name")} - = form.input :registration_number, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.network.registration_number")} + = form.input :name, input_html: { title: t("formtastic.titles#{format_restriction_for_locales(@referential)}.network.name")} + = form.input :registration_number, input_html: { title: t("formtastic.titles#{format_restriction_for_locales(@referential)}.network.registration_number")} = form.input :comment = form.input :version_date, as: :date_picker = form.input :description = form.input :source_name - = form.input :source_type_name, as: :select, :collection => Chouette::Network.source_type_names, :include_blank => true, :member_label => Proc.new { |mode| t("source_types.label.#{mode}") } + = form.input :source_type_name, as: :select, collection: source_type_name_label_pairs, include_blank: true = form.input :source_identifier - = form.input :objectid, :required => !@network.new_record?, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.network.objectid")} + = form.input :objectid, required: !@network.new_record?, input_html: { title: t("formtastic.titles#{format_restriction_for_locales(@referential)}.network.objectid")} = form.actions do = form.action :submit, as: :button - = form.action :cancel, as: :link
\ No newline at end of file + = form.action :cancel, as: :link diff --git a/app/views/referentials/index.html.slim b/app/views/referentials/index.html.slim index 8186f725f..8943d419c 100644 --- a/app/views/referentials/index.html.slim +++ b/app/views/referentials/index.html.slim @@ -13,7 +13,6 @@ ul.actions li = link_to 'Données Reflex', stop_area_referential_path(1) li = link_to 'Données CodifLigne', line_referential_path(1) - li= link_to t('calendars.standard_calendars'), calendars_path - / FIXME #823 + li = link_to t('calendars.standard_calendars'), calendars_path - if false li = link_to t('referentials.actions.new'), new_referential_path, class: 'add' diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim index 04f93738e..fd6ebf91a 100644 --- a/app/views/referentials/show.html.slim +++ b/app/views/referentials/show.html.slim @@ -5,10 +5,12 @@ t('last_update', time: l(@referential.updated_at, format: :short)), ((@referential.archived? || !policy(@referential).edit?) ? '' : link_to(t('actions.edit'), edit_referential_path(@referential), class: 'btn btn-default')) do - / Below is secundary actions & optional contents (filters, ...) + / Below is secondary actions & optional contents (filters, ...) .row.mb-sm .col-lg-12.text-right - - if policy(@referential).new? + = link_to t('time_tables.index.title'), referential_time_tables_path(@referential), class: 'btn btn-primary' + + - if policy(@referential).clone? = link_to t('actions.clone'), new_referential_path(from: @referential.id), class: 'btn btn-primary' - if policy(@referential).edit? diff --git a/app/views/routes/show.html.slim b/app/views/routes/show.html.slim index 21a64b61e..9f84b31ad 100644 --- a/app/views/routes/show.html.slim +++ b/app/views/routes/show.html.slim @@ -39,7 +39,6 @@ :deleted_at => Proc.new{|s| s.try(:stop_area).deleted_at ? t('false') : t('true')}, :zip_code => Proc.new {|s| s.try(:stop_area).try(:zip_code)}, :city_name => Proc.new {|s| s.try(:stop_area).try(:city_name)}, - :area_type => Proc.new {|s| t("area_types.label.#{s.try(:stop_area).try(:area_type)}")}, :for_boarding => Proc.new {|s| t("stop_points.stop_point.for_boarding.#{s.for_boarding}")}, :for_alighting => Proc.new {|s| t("stop_points.stop_point.for_alighting.#{s.for_alighting}")}, :position => 'position' }, diff --git a/app/views/routing_constraint_zones/_form.html.slim b/app/views/routing_constraint_zones/_form.html.slim index afc993a0f..b1c77a44b 100644 --- a/app/views/routing_constraint_zones/_form.html.slim +++ b/app/views/routing_constraint_zones/_form.html.slim @@ -4,10 +4,16 @@ = f.input :name .row .col-lg-6.col-sm-12 - / Temporarily limit the collection to 10 items... otherwise it kills RoR - = f.input :stop_area_ids, as: :select, collection: Chouette::StopArea.limit(10), selected: @routing_constraint_zone.stop_area_ids, label: Chouette::StopArea.model_name.human.pluralize.capitalize, label_method: :name, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Sélection de arrêts', 'multiple': 'multiple', style: 'width: 100%' } + = f.input :route_id, collection: @line.routes.select { |route| route.stop_points.count > 2 }, include_blank: false + .row + .col-lg-6.col-sm-12 + - stop_points_collection = @routing_constraint_zone.persisted? ? @routing_constraint_zone.route.stop_points : [] + = f.input :stop_point_ids, as: :select, collection: stop_points_collection, selected: @routing_constraint_zone.stop_point_ids, label: Chouette::StopPoint.model_name.human.pluralize.capitalize, label_method: :name, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Sélection des arrêts sur séquence d\'arrêts', 'multiple': 'multiple', style: 'width: 100%' } .row .col-lg-12.text-right = link_to 'Annuler', :back, class: 'btn btn-link' = f.button :submit, class: 'btn btn-danger' + + += hidden_field_tag 'stop_point_ids', @routing_constraint_zone.stop_point_ids.to_s, id: 'stop_point_ids' diff --git a/app/views/routing_constraint_zones/index.html.slim b/app/views/routing_constraint_zones/index.html.slim index 9061fbdfd..620b0f7db 100644 --- a/app/views/routing_constraint_zones/index.html.slim +++ b/app/views/routing_constraint_zones/index.html.slim @@ -1,11 +1,11 @@ = title_tag Chouette::RoutingConstraintZone.model_name.human.pluralize(:fr) - if policy(Chouette::RoutingConstraintZone).create? && @referential.organisation == current_organisation - = link_to t('routing_constraint_zones.actions.new'), new_referential_line_routing_constraint_zone_path + = link_to t('routing_constraint_zones.actions.new'), new_referential_line_routing_constraint_zone_path(@referential, @line) - if @routing_constraint_zones.any? = table_builder @routing_constraint_zones, - { :name => 'name' }, + { objectid: 'objectid', name: 'name', route: 'route_name', stop_points_count: 'stop_points_count' }, [:show, :edit, :delete], [], 'table table-bordered' diff --git a/app/views/routing_constraint_zones/show.html.slim b/app/views/routing_constraint_zones/show.html.slim index 0f88f5b3f..351784ecc 100644 --- a/app/views/routing_constraint_zones/show.html.slim +++ b/app/views/routing_constraint_zones/show.html.slim @@ -5,14 +5,13 @@ p = @routing_constraint_zone.name p - label => "#{Chouette::Line.model_name.human.capitalize} : " - = link_to @routing_constraint_zone.line.name, referential_line_path(@referential, @line) + label => "#{Chouette::Route.model_name.human.capitalize} : " + = link_to @routing_constraint_zone.route.name, referential_line_route_path(@referential, @line, @routing_constraint_zone.route) p - label => "#{Chouette::StopArea.model_name.human.pluralize.capitalize} : " + label => "#{Chouette::StopPoint.model_name.human.pluralize.capitalize} : " br - - @routing_constraint_zone.stop_areas.each do |stop_area| - = link_to stop_area.name, referential_stop_area_path(@referential, stop_area) + - @routing_constraint_zone.stop_points.each do |stop_point| + = link_to stop_point.name, referential_stop_area_path(@referential, stop_point.stop_area) br - diff --git a/app/views/rule_parameter_sets/_transport_mode_parameter_set_fields.html.slim b/app/views/rule_parameter_sets/_transport_mode_parameter_set_fields.html.slim index a60c966e2..ede7e2b75 100644 --- a/app/views/rule_parameter_sets/_transport_mode_parameter_set_fields.html.slim +++ b/app/views/rule_parameter_sets/_transport_mode_parameter_set_fields.html.slim @@ -1,9 +1,9 @@ = f.inputs class: 'transport_mode_parameter_sets nested-fields' do - = f.input :transport_mode, as: :select, :collection => Chouette::TransportMode.all, include_blank: false, member_label: Proc.new { |mode| t("transport_modes.label.#{mode}") }, label: "transport_mode", wrapper_html: { class: 'fl1' } + = f.input :transport_mode, as: :select, collection: transport_mode_label_pairs, include_blank: false, label: "transport_mode", wrapper_html: { class: 'fl1' } = f.input :inter_stop_area_distance_min, as: :number, label: "inter_stop_area_distance_min", wrapper_html: { class: 'fl1' } = f.input :inter_stop_area_distance_max, as: :number, label: "inter_stop_area_distance_max", wrapper_html: { class: 'fl2' } = f.input :speed_min, as: :number, label: "speed_min", wrapper_html: { class: 'fl2' } = f.input :speed_max, as: :number, label: "speed_max", wrapper_html: { class: 'fl2' } = f.input :inter_stop_duration_variation_max, as: :number, label: "inter_stop_duration_variation_max", wrapper_html: { class: 'fl2' } - = link_to_remove_association t('actions.destroy'), f
\ No newline at end of file + = link_to_remove_association t('actions.destroy'), f diff --git a/app/views/stop_area_copies/new.html.slim b/app/views/stop_area_copies/new.html.slim index a4c0c8bde..1a8764cbc 100644 --- a/app/views/stop_area_copies/new.html.slim +++ b/app/views/stop_area_copies/new.html.slim @@ -8,13 +8,21 @@ - if @stop_area_copy.hierarchy == "child" - if @stop_area.area_type.underscore == "stop_place" - = form.input :area_type, as: :select, :collection => ["stop_place","commercial_stop_point"], :include_blank => false, :member_label => Proc.new { |stop_area_type| t("area_types.label.#{stop_area_type}") } + = form.input :area_type, + as: :select, + collection: label_stop_area_types( "stop_place","commercial_stop_point" ), + include_blank: false - else - = form.input :area_type, as: :select, :collection => ["boarding_position","quay"], :include_blank => false, :member_label => Proc.new { |stop_area_type| t("area_types.label.#{stop_area_type}") } - + = form.input :area_type, + as: :select, + collection: label_stop_area_types( "boarding_position","quay" ), + include_blank: false - else - = form.input :area_type, as: :select, :collection => [@stop_area_copy.area_type], :include_blank => false, :member_label => Proc.new { |stop_area_type| t("area_types.label.#{stop_area_type}") } + = form.input :area_type, + as: :select, + collection: label_stop_area_types(@stop_area_copy.area_type), + include_blank: false = form.actions do = form.action :submit, as: :button , label: t('formtastic.duplicate') - = form.action :cancel, as: :link
\ No newline at end of file + = form.action :cancel, as: :link diff --git a/app/views/stop_areas/index.html.slim b/app/views/stop_areas/index.html.slim index c9ff2cecd..bc1529e68 100644 --- a/app/views/stop_areas/index.html.slim +++ b/app/views/stop_areas/index.html.slim @@ -17,7 +17,7 @@ .row .col-lg-12 = table_builder @stop_areas, - { 'Oid' => Proc.new { |n| n.try(:objectid).try(:local_id) }, + { 'Oid' => Proc.new { |n| n.try(:user_objectid) }, :name => 'name', :registration_number => 'registration_number', :zip_code => 'zip_code', :city_name => 'city_name', :area_type => Proc.new{|s| (s.area_type.nil? ? '-' : t("enumerize.stop_area.area_type.#{s.try(:area_type)}"))} }, [:show, :edit, :delete], diff --git a/app/views/stop_areas/show.html.slim b/app/views/stop_areas/show.html.slim index 9affba08e..58a2dbde3 100644 --- a/app/views/stop_areas/show.html.slim +++ b/app/views/stop_areas/show.html.slim @@ -22,7 +22,7 @@ = definition_list t('metadatas'), { @stop_area.human_attribute_name(:stop_area_type) => t("area_types.label.#{@stop_area.stop_area_type}"), @stop_area.human_attribute_name(:registration_number) => @stop_area.registration_number, - 'Code Reflex' => @stop_area.try(:objectid), + 'Code Reflex' => @stop_area.user_objectid, '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, diff --git a/app/views/time_tables/_date_fields.html.slim b/app/views/time_tables/_date_fields.html.slim index f17fcaa2c..1599dd7ff 100644 --- a/app/views/time_tables/_date_fields.html.slim +++ b/app/views/time_tables/_date_fields.html.slim @@ -1,5 +1,14 @@ -= f.inputs class: 'nested-fields date' do - = f.label @time_table.human_attribute_name("date"), class: 'col-md-1' - = f.input :date, as: :date_picker, :label => false, :input_html => { class: 'form-control col-md-3' } - = f.input :in_out, as: :hidden, :input_html => {:value => true} - = link_to_remove_association t('actions.destroy'), f, class: "col-md-3"
\ No newline at end of file +.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 :date, as: :date, label: false, wrapper_html: { class: 'date' } + = f.input :in_out, as: :hidden, :input_html => {:value => true} + 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/time_tables/_excluded_date_fields.html.slim b/app/views/time_tables/_excluded_date_fields.html.slim index 294d103fc..dba5bf952 100644 --- a/app/views/time_tables/_excluded_date_fields.html.slim +++ b/app/views/time_tables/_excluded_date_fields.html.slim @@ -1,5 +1,15 @@ -= f.inputs class: 'nested-fields date' do - = f.label @time_table.human_attribute_name("date"), class: 'col-md-1' - = f.input :date, as: :date_picker, :label => false, :input_html => { class: 'form-control col-md-3' } - = f.input :in_out, as: :hidden, :input_html => {:value => false} - = link_to_remove_association t('actions.destroy'), f, class: "col-md-3"
\ No newline at end of file +.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.label @time_table.human_attribute_name("date"), class: 'col-md-1' + = f.input :date, as: :date, label: false, wrapper_html: { class: 'date' } + = f.input :in_out, as: :hidden, input_html: {value: false} + 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/time_tables/_form.html.slim b/app/views/time_tables/_form.html.slim index 8652f7cb5..97df72fd3 100644 --- a/app/views/time_tables/_form.html.slim +++ b/app/views/time_tables/_form.html.slim @@ -1,73 +1,102 @@ -= semantic_form_for [@referential, @time_table] do |form| - = form.inputs do - = form.input :comment, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.time_table.comment")} - = form.input :version - = form.input :tag_search, as: :tags, :input_html => { :id => "tag_search",:placeholder => t("formtastic.placeholders.time_table.tag_search") } - = form.input :tag_list, as: :hidden, :input_html => { :id => "tag_list" } - = form.input :objectid, :required => !@time_table.new_record?, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.time_table.objectid")} - - if @time_table.new_record? - = form.input :calendar, as: :select, collection: current_organisation.calendars - - h3.time_table_periods = @time_table.human_attribute_name("periods") - - #periods_content - = form.inputs class: 'day_type' do - label.day_type_label = @time_table.human_attribute_name("day_types") - = form.input :monday, as: :boolean, class: "others" - = form.input :tuesday, as: :boolean - = form.input :wednesday, as: :boolean - = form.input :thursday, as: :boolean - = form.input :friday, as: :boolean - = form.input :saturday, as: :boolean - = form.input :sunday, as: :boolean - - #periods - = form.semantic_fields_for :periods do |p| - == render "period_fields", :f => p - - = link_to_add_association t("time_tables.actions.add_period"), form, :periods , :"data-association-insertion-method" => "append", :"data-association-insertion-node" => "div#periods" - - h3.time_table_dates = @time_table.human_attribute_name("dates") - - #dates_content - #dates - = form.semantic_fields_for :dates, @time_table.dates.to_a.select {|d| d.in_out == true} do |p| - == render "date_fields", :f => p - - = link_to_add_association t("time_tables.actions.add_date"), form, :dates, :"data-association-insertion-method" => "append", :"partial" => "date_fields", :"data-association-insertion-node" => "div#dates" - - h3.time_table_dates = @time_table.human_attribute_name("excluded_dates") - - #excluded_dates_content - #excluded_dates - = form.semantic_fields_for :dates, @time_table.dates.to_a.select {|d| d.in_out == false} do |p| - == render "excluded_date_fields", :f => p - - = link_to_add_association t("time_tables.actions.add_excluded_date"), form, :dates, :"data-association-insertion-method" => "append", :"partial" => "excluded_date_fields", :"data-association-insertion-node" => "div#excluded_dates" - - = form.actions do - = form.action :submit, as: :button - = form.action :cancel, as: :link - -= javascript_tag "var items = #{ @time_table.tag_list.to_a };" - -javascript: - $("#tag_search").tagsManager({ - prefilled: items, - output: '#tag_list', - tagsContainer: '#tagsContainer' - }); - - var time_tables_tag_list = new Bloodhound({ - datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'), - queryTokenizer: Bloodhound.tokenizers.whitespace, - remote: "#{tags_referential_time_tables_path(@referential, format: 'json')}?tag=%QUERY", - }); - - time_tables_tag_list.initialize(); - - $("#tag_search").typeahead(null, { - name: 'time_tables_tag_list', - displayKey: 'name', - source: time_tables_tag_list.ttAdapter() - }); += simple_form_for [@referential, @time_table], html: {class: 'form-horizontal', id: 'timetable_form'}, wrapper: :horizontal_form do |form| + + .row + .col-lg-12 + = form.input :comment, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.time_table.comment")} + + .form-group + = form.label @time_table.human_attribute_name(:color), required: false, class: 'control-label col-sm-4' + + .col-sm-8 + .dropdown.color_selector + button.btn.btn-default.dropdown-toggle type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" + span.fa.fa-circle.mr-xs style="color:#{@time_table.color.nil? ? 'transparent' : @time_table.color}" + span.caret + + = form.input :color, as: :radio_buttons, label: false, collection: ["", "#9B9B9B", "#FFA070", "#C67300", "#7F551B", "#41CCE3", "#09B09C", "#3655D7", "#6321A0", "#E796C6", "#DD2DAA"], input_html: {class: 'color_selector'}, label_method: lambda{|c| ("<span class='fa fa-circle' style='color:" + (c.empty? ? 'transparent' : c) + "'></span>").html_safe}, wrapper_html: { class: 'dropdown-menu', 'aria-labelledby': "dropdownMenu1"}, include_blank: true + + / = form.input :tag_list, as: :tags + + .form-group + label.control-label.col-sm-4 + = "Journées d'applications pour les périodes ci-dessous" + + .col-sm-8 + .form-group.labelled-checkbox-group + = form.input :monday, as: :boolean, label: ("<span class='lcbx-group-item-label'>L</span>").html_safe, wrapper_html: { class: 'lcbx-group-item' } + = form.input :tuesday, as: :boolean, label: ("<span class='lcbx-group-item-label'>Ma</span>").html_safe, wrapper_html: { class: 'lcbx-group-item' } + = form.input :wednesday, as: :boolean, label: ("<span class='lcbx-group-item-label'>Me</span>").html_safe, wrapper_html: { class: 'lcbx-group-item' } + = form.input :thursday, as: :boolean, label: ("<span class='lcbx-group-item-label'>J</span>").html_safe, wrapper_html: { class: 'lcbx-group-item' } + = form.input :friday, as: :boolean, label: ("<span class='lcbx-group-item-label'>V</span>").html_safe, wrapper_html: { class: 'lcbx-group-item' } + = form.input :saturday, as: :boolean, label: ("<span class='lcbx-group-item-label'>S</span>").html_safe, wrapper_html: { class: 'lcbx-group-item' } + = form.input :sunday, as: :boolean, label: ("<span class='lcbx-group-item-label'>D</span>").html_safe, wrapper_html: { class: 'lcbx-group-item' } + + - if @time_table.new_record? + = form.input :calendar, as: :select, collection: current_organisation.calendars + + .separator + + .row + .col-lg-8.col-lg-offset-4 + .subform + .nested-head + .wrapper + div + .form-group + label.control-label.required + = t('simple_form.labels.referential.metadatas.periods.begin') + abbr title='requis' * + div + .form-group + label.control-label.required + = t('simple_form.labels.referential.metadatas.periods.end') + abbr title='requis' * + div + + = form.simple_fields_for :periods do |p| + = render "period_fields", f: p + + .links.nested-linker + = link_to_add_association t("time_tables.actions.add_period"), form, :periods, class: 'btn btn-outline-primary' + + .row + .col-lg-12.mb-sm.mt-md + #time_tables + .alert.alert-warning + |Les éléments ci-dessous sont à supprimer. + + .row + .col-lg-6.col-md-6.col-sm-12.col-xs-12 + .subform + .nested-head + .wrapper + div + .form-group + label.control-label + = @time_table.human_attribute_name("dates") + div + + = form.simple_fields_for :dates, @time_table.dates.to_a.select {|d| d.in_out == true} do |p| + = render "date_fields", f: p + + .links.nested-linker + = link_to_add_association t("time_tables.actions.add_date"), form, :dates, partial: 'date_fields', class: 'btn btn-outline-primary' + + .col-lg-6.col-md-6.col-sm-12.col-xs-12 + .subform + .nested-head + .wrapper + div + .form-group + label.control-label + = @time_table.human_attribute_name("excluded_dates") + div + + = form.simple_fields_for :dates, @time_table.dates.to_a.select {|d| d.in_out == false} do |q| + = render "excluded_date_fields", f: q + + .links.nested-linker + = link_to_add_association t("time_tables.actions.add_excluded_date"), form, :dates, partial: 'excluded_date_fields', class: 'btn btn-outline-primary' + + + = form.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'timetable_form' diff --git a/app/views/time_tables/_period_fields.html.slim b/app/views/time_tables/_period_fields.html.slim index cefa68df5..f879ded00 100644 --- a/app/views/time_tables/_period_fields.html.slim +++ b/app/views/time_tables/_period_fields.html.slim @@ -1,8 +1,15 @@ -= f.inputs class: 'nested-fields period' do - = f.label @time_table.human_attribute_name("period_start"), class: "col-md-1" - = f.input :period_start, as: :date_picker, :label => false, :input_html => { class: 'form-control col-md-3' } - - = f.label @time_table.human_attribute_name("period_end"), class: "col-md-1" - = f.input :period_end, as: :date_picker, :label => false, :input_html => { class: 'form-control col-md-3' } - - = link_to_remove_association t('actions.destroy'), f, class: "col-md-2"
\ No newline at end of file +.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 :period_start, as: :date, label: false, wrapper_html: { class: 'date' } + div + = f.input :period_end, as: :date, label: false, wrapper_html: { class: '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/time_tables/_periods.html.slim b/app/views/time_tables/_periods.html.slim deleted file mode 100644 index e3c6d5f39..000000000 --- a/app/views/time_tables/_periods.html.slim +++ /dev/null @@ -1,5 +0,0 @@ -ul.periods - - @time_table.periods.each do |tmp| - li.period - = "#{('time_tables.show.from')} #{l tmp.period_start}" - = "#{t('time_tables.show.to')} #{l tmp.period_end}"
\ No newline at end of file diff --git a/app/views/time_tables/_show_time_table.html.slim b/app/views/time_tables/_show_time_table.html.slim index 419d13c96..ebfe9d283 100644 --- a/app/views/time_tables/_show_time_table.html.slim +++ b/app/views/time_tables/_show_time_table.html.slim @@ -1,94 +1,25 @@ -#time_table_show.time_table_show - p - span class="state-code #{@time_table.presenter.time_table_state_code}" - i.fa.fa-certificate - - label - - if @time_table.bounding_dates.empty? - = t(".resume_empty") - - else - = t(".resume", :start_date => l(@time_table.bounding_dates.min), :end_date => l(@time_table.bounding_dates.max)) - - p - label = "#{@time_table.human_attribute_name('tag_list')} : " - = @time_table.tag_list - - ul.nav.nav-tabs id="tabs" data-tabs="tabs" - li.active - a href="#time_tables" data-toggle="tab" - = @time_table.human_attribute_name("calendars") - - li - a href="#time_tables_datas" data-toggle="tab" - = @time_table.human_attribute_name("calendar_details") - - #my-tab-content.tab-content - #time_tables.tab-pane.active - #associated_calendar - => "#{t('calendars.standard_calendar')} : " - - if @time_table.calendar - = link_to @time_table.calendar.name, @time_table.calendar - - else - = '--' - - .well.legend - span.title = t(".legend") - span.label.excluded_date X - = t(".excluded_date") - span.label.overlaped_date X - = t(".overlap_date") - span.label.selected_date X - = t(".selected_date") - span.label.selected_period X - = t(".selected_period") - - #calendars - .year_choice - span.previous = link_to("<", referential_time_table_path(@referential, @time_table, year: (@year - 1)) ) - span.year = "#{@year}" - span.next = link_to(">", referential_time_table_path(@referential, @time_table, year: (@year + 1)) ) - - .calendar_helper - - cal = "" - - (1..12).each do |month| - - cal << calendar(year: @year, month: month, first_day_of_week: 1) do |d| - - if @time_table.excluded_date?(d) - - [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {class: "day excluded_date"}] - - elsif @time_table.include_in_overlap_dates?(d) - - [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {class: "day overlaped_date"}] - - elsif @time_table.include_in_dates?(d) - - [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {class: "day selected_date"}] - - elsif @time_table.include_in_periods?(d) - - [link_to(d.mday, edit_referential_time_table_path(@referential, @time_table) ), {class: "day selected_period"}] - - = cal.html_safe - - #time_tables_datas.tab-pane - .summary - p - label = "#{@time_table.human_attribute_name('version')} : " - = @time_table.version - - p - label = "#{@time_table.human_attribute_name('day_types')} : " - - if @time_table.int_day_types & 508 == 0 - label = "#{@time_table.human_attribute_name('none')} : " - - else - - %w(monday tuesday wednesday thursday friday saturday sunday).each do |day_type| - span class="#{@time_table.send(day_type) ? 'included_day_type' :'excluded_day_type'}" - = @time_table.human_attribute_name(day_type) - - - if @time_table.periods.present? - h3.time_table_periods = @time_table.human_attribute_name("periods") - .periods.content - == render 'time_tables/periods' - - - 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" +.row + - (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" diff --git a/app/views/time_tables/edit.html.slim b/app/views/time_tables/edit.html.slim index 1746b48c7..7f4cd18df 100644 --- a/app/views/time_tables/edit.html.slim +++ b/app/views/time_tables/edit.html.slim @@ -1,3 +1,12 @@ -= title_tag t('time_tables.edit.title', :time_table => @time_table.comment) +/ PageHeader += pageheader 'map-marker', + @time_table.comment, + '', + '' -== render 'form'
\ No newline at end of file +/ PageContent +.page_content + .container-fluid + #periods + += javascript_include_tag 'es6_browserified/time_tables/index.js' diff --git a/app/views/time_tables/index.html.slim b/app/views/time_tables/index.html.slim index 64d2372a5..65d0787e8 100644 --- a/app/views/time_tables/index.html.slim +++ b/app/views/time_tables/index.html.slim @@ -1,37 +1,51 @@ -= title_tag t('time_tables.index.title') - -= search_form_for @q, :url => referential_time_tables_path(@referential), remote: true, :html => {:method => :get, class: "form-inline", :id => "search", role: "form"} do |f| - .panel.panel-default - .panel-heading - .input-group.col-md-9 - = f.text_field :comment_cont, :placeholder => "#{t('.comment')}", class: 'form-control' - - .input-group-btn - button.btn.btn-default type="submit" - i.fa.fa-search - - a data-toggle="collapse" data-parent="#search" href="#advanced_search" - i.fa.fa-plus - = "#{t('.advanced_search')}" - - #advanced_search.panel-collapse.collapse - .panel-body - div - label = "#{t('.from')}" - = f.text_field :start_date_gteq, :placeholder => "#{t('.start_date')}", class: 'form-control date_picker', :type => "date" - - label = "#{t('.to')}" - = f.text_field :end_date_lteq, :placeholder => "#{t('.end_date')}", class: 'form-control date_picker', :type => "date" - - div - = f.text_field :tag_search, :placeholder => "#{t('.tag_search')}", class: 'form-control' - -#time_tables - == render 'time_tables' - -- content_for :sidebar do - ul.actions - li - - if policy(Chouette::TimeTable).create? && @referential.organisation == current_organisation - = link_to t('time_tables.actions.new'), new_referential_time_table_path(@referential), class: "add" - br +/ PageHeader += pageheader 'map-marker', + t('time_tables.index.title'), + '', + ((policy(Chouette::TimeTable).create? && @referential.organisation == current_organisation) ? link_to(t('actions.add'), new_referential_time_table_path(@referential), class: 'btn btn-default') : '') + +/ PageContent +.page_content + .container-fluid + .row + .col-lg-12 + = 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 + = f.text_field :comment_cont, :placeholder => "#{t('.comment')}", class: 'form-control' + span.input-group-btn + button.btn.btn-default type='submit' + span.fa.fa-search + + .ffg-row + .form-group + = f.label @time_tables.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 + + .form-group.togglable + = f.label @time_tables.human_attribute_name(:bounding_dates), required: false, class: 'control-label' + .filter_menu + = f.input :start_date_gteq, as: :date, label: t('simple_form.from'), wrapper_html: { class: 'date filter_menu-item' } + = f.input :end_date_lteq, as: :date, label: t('simple_form.to'), wrapper_html: { class: 'date filter_menu-item' } + + + .actions + = link_to 'Effacer', @workbench, class: 'btn btn-link' + = f.submit 'Filtrer', class: 'btn btn-default' + + - if @time_tables.any? + .row + .col-lg-12 + = table_builder @time_tables, + { :comment => 'comment', :color => Proc.new{|tt| tt.color ? content_tag(:span, '', class: 'fa fa-circle', style: "color:#{tt.color}") : '-' }, + "Période de validité englobante" => Proc.new{ |tt| tt.bounding_dates.empty? ? '-' : t('bounding_dates', debut: l(tt.bounding_dates.min), end: l(tt.bounding_dates.max)) }, :calendar => Proc.new{ |tt| tt.calendar ? tt.calendar.try(:name) : '-' }, :updated_at => Proc.new {|tt| l(tt.updated_at, format: :short)} }, + [:show, :edit, :duplicate, :delete], + [], + 'table has-search' + + = new_pagination @time_tables, 'pull-right' + + - unless @time_tables.any? + .row.mt-xs + .col-lg-12 + = replacement_msg t('time_tables.search_no_results') diff --git a/app/views/time_tables/index.js.slim b/app/views/time_tables/index.js.slim deleted file mode 100644 index bc9585c4b..000000000 --- a/app/views/time_tables/index.js.slim +++ /dev/null @@ -1 +0,0 @@ -| $('#time_tables').html("#{escape_javascript(render('time_tables'))}");
\ No newline at end of file diff --git a/app/views/time_tables/index.json.rabl b/app/views/time_tables/index.json.rabl deleted file mode 100644 index 443cb13a2..000000000 --- a/app/views/time_tables/index.json.rabl +++ /dev/null @@ -1,9 +0,0 @@ -collection @time_tables, :object_root => false - -node do |time_table| - { :id => time_table.id, :comment => time_table.comment, - :time_table_bounding => time_table_bounding( time_table), - :composition_info => composition_info(time_table), - :tags => time_table.tags.join(','), - :day_types => %w(monday tuesday wednesday thursday friday saturday sunday).select{ |d| time_table.send(d) }.map{ |d| time_table.human_attribute_name(d).first(2)}.join('')} -end diff --git a/app/views/time_tables/index.rabl b/app/views/time_tables/index.rabl new file mode 100644 index 000000000..d8b7c6e0c --- /dev/null +++ b/app/views/time_tables/index.rabl @@ -0,0 +1,2 @@ +collection @time_tables, :object_root => false +extends "time_tables/show" diff --git a/app/views/time_tables/month.rabl b/app/views/time_tables/month.rabl new file mode 100644 index 000000000..5b8b67f6c --- /dev/null +++ b/app/views/time_tables/month.rabl @@ -0,0 +1,9 @@ +object @time_table + +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/time_tables/new.html.slim b/app/views/time_tables/new.html.slim index bc15f7032..8770a59b2 100644 --- a/app/views/time_tables/new.html.slim +++ b/app/views/time_tables/new.html.slim @@ -1,3 +1,12 @@ -= title_tag t('time_tables.new.title') +/ PageHeader += pageheader 'map-marker', + t('time_tables.new.title'), + '', + '' -== render 'form'
\ No newline at end of file +/ PageContent +.page_content + .container-fluid + .row + .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-10.col-sm-offset-1 + == render 'form' diff --git a/app/views/time_tables/show.html.slim b/app/views/time_tables/show.html.slim index 436886faa..6e6833cf4 100644 --- a/app/views/time_tables/show.html.slim +++ b/app/views/time_tables/show.html.slim @@ -1,27 +1,51 @@ - require 'calendar_helper' -= title_tag t('time_tables.show.title', :time_table => @time_table.comment ) +/ PageHeader += pageheader 'map-marker', + @time_table.comment, + '', + (policy(@time_table).edit? ? link_to(t('actions.edit'), edit_referential_time_table_path(@referential, @time_table), class: 'btn btn-default') : '') -== render 'time_table_combinations/combine' + / Below is secundary actions & optional contents (filters, ...) + .row.mb-sm + .col-lg-12.text-right + / - if policy(@time_table).create? && @referential.organisation == current_organisation + / = link_to t('time_tables.actions.new'), new_referential_time_table_path(@referential), class: 'btn btn-primary' -== render 'show_time_table' + /- if policy(@time_table).create? && @referential.organisation == current_organisation + = link_to t('actions.combine'), new_referential_time_table_time_table_combination_path(@referential, @time_table), {remote: true, 'data-toggle' => "modal", 'data-target' => '#modal_combine', class: 'btn btn-primary' } -- content_for :sidebar do - ul.actions - li - if policy(@time_table).create? && @referential.organisation == current_organisation - = link_to t('time_tables.actions.new'), new_referential_time_table_path(@referential), class: 'add' - li - - if policy(@time_table).edit? - = link_to t('time_tables.actions.edit'), edit_referential_time_table_path(@referential, @time_table), class: "edit" - li + = link_to t('actions.clone'), duplicate_referential_time_table_path(@referential, @time_table), class: 'btn btn-primary' + - if policy(@time_table).destroy? - = link_to t('time_tables.actions.destroy'), referential_time_table_path(@referential, @time_table), :method => :delete, :data => {:confirm => t('time_tables.actions.destroy_confirm')}, class: "remove" - li - - if policy(@time_table).create? && @referential.organisation == current_organisation - = link_to t('time_tables.actions.duplicate'), duplicate_referential_time_table_path(@referential, @time_table), class: "clone" - li - /- if policy(@time_table).create? && @referential.organisation == current_organisation - = link_to t('time_tables.actions.combine'), new_referential_time_table_time_table_combination_path(@referential, @time_table), {:remote => true, 'data-toggle' => "modal", 'data-target' => '#modal_combine', class: "merge"} + = link_to referential_time_table_path(@referential, @time_table), method: :delete, data: {confirm: t('time_tables.actions.destroy_confirm')}, class: 'btn btn-primary' do + span.fa.fa-trash + span = t('actions.destroy') + +/ PageContent +.page_content + .container-fluid + .row + .col-lg-6.col-md-6.col-sm-12.col-xs-12 + = definition_list t('metadatas'), + { "Période d'application" => (@time_table.bounding_dates.empty? ? '-' : t('bounding_dates', debut: l(@time_table.bounding_dates.min), end: l(@time_table.bounding_dates.max))), + 'Couleur associée' => 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 } + + .row + .col-lg-12.mb-sm + .pagination.pull-right + = @year + .page_links + = 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' - = creation_tag(@time_table) + .row + .col-lg-12 + / WTF ??! + = render 'time_table_combinations/combine' diff --git a/app/views/time_tables/show.rabl b/app/views/time_tables/show.rabl new file mode 100644 index 000000000..a0a799985 --- /dev/null +++ b/app/views/time_tables/show.rabl @@ -0,0 +1,26 @@ +object @time_table + +attributes :id, :comment +node do |tt| + { + time_table_bounding: tt.presenter.time_table_bounding, + tags: tt.tags.map{ |tag| {id: tag.id, name: tag.name}}, + 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, + color: tt.color ? tt.color : '' + } +end + +child(:periods, object_root: false) do + attributes :id, :period_start, :period_end +end + +child(:dates, object_root: false) do + attributes :id, :date, :in_out +end + +child(:calendar) do + attributes :id, :name +end diff --git a/app/views/vehicle_journeys/_form.html.slim b/app/views/vehicle_journeys/_form.html.slim index c738b8b00..ca200a5f7 100644 --- a/app/views/vehicle_journeys/_form.html.slim +++ b/app/views/vehicle_journeys/_form.html.slim @@ -2,7 +2,7 @@ == render 'shared/form_messages', { errors: vehicle_journey.errors } = form.inputs do - = form.input :journey_pattern, as: :select, :collection => @route.journey_patterns, :member_label => Proc.new { |jp| journey_name(jp) } + = form.input :journey_pattern, as: :select, collection: route_journey_pattern_label_pairs(@route) = form.input :number = form.input :published_journey_name = form.input :published_journey_identifier diff --git a/app/views/vehicle_journeys/show.rabl b/app/views/vehicle_journeys/show.rabl index 86edfafa8..6b7608342 100644 --- a/app/views/vehicle_journeys/show.rabl +++ b/app/views/vehicle_journeys/show.rabl @@ -8,6 +8,12 @@ child(:company) do |company| attributes :id, :objectid, :name end +child(:route) do |route| + child(:line) do |line| + attributes :transport_mode, :transport_submode + end +end + child(:journey_pattern) do |journey_pattern| attributes :id, :objectid, :name, :published_name end @@ -29,6 +35,9 @@ child(:vehicle_journey_at_stops_matrix, :object_root => false) do |vehicle_stops node(:stop_area_object_id) do vehicle_stop.stop_point ? vehicle_stop.stop_point.stop_area.objectid : nil end + node(:stop_point_objectid) do + vehicle_stop.stop_point ? vehicle_stop.stop_point.objectid : nil + end node(:stop_area_name) do vehicle_stop.stop_point ? vehicle_stop.stop_point.stop_area.name : nil end diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim index 2d13501b7..1025c1658 100644 --- a/app/views/workbenches/show.html.slim +++ b/app/views/workbenches/show.html.slim @@ -7,7 +7,9 @@ / Below is secundary actions & optional contents (filters, ...) .row.mb-sm .col-lg-12.text-right - = link_to t('referentials.actions.new'), new_referential_path(workbench_id: @workbench), class: 'btn btn-primary' + = link_to Import.model_name.human.pluralize.capitalize, workbench_imports_path(@workbench), class: 'btn btn-primary' + - if policy(Referential).create? + = link_to t('referentials.actions.new'), new_referential_path(workbench_id: @workbench), class: 'btn btn-primary' / PageContent .page_content diff --git a/app/workers/referential_cloning_worker.rb b/app/workers/referential_cloning_worker.rb index dda569d7c..ef3acd529 100644 --- a/app/workers/referential_cloning_worker.rb +++ b/app/workers/referential_cloning_worker.rb @@ -1,24 +1,33 @@ class ReferentialCloningWorker include Sidekiq::Worker + sidekiq_options queue: 'wip' + # Replace default apartment created schema with clone schema from source referential def perform(id) - # Replace default apartment created schema with clone schema from source referential ref_cloning = ReferentialCloning.find id - sql_func = "CREATE OR REPLACE FUNCTION clone_schema( source_schema text, dest_schema text, include_recs boolean) RETURNS void AS $BODY$ DECLARE src_oid oid; tbl_oid oid; func_oid oid; object text; buffer text; srctbl text; default_ text; column_ text; qry text; dest_qry text; v_def text; seqval bigint; sq_last_value bigint; sq_max_value bigint; sq_start_value bigint; sq_increment_by bigint; sq_min_value bigint; sq_cache_value bigint; sq_log_cnt bigint; sq_is_called boolean; sq_is_cycled boolean; sq_cycled char(10); BEGIN SELECT oid INTO src_oid FROM pg_namespace WHERE nspname = quote_ident(source_schema); IF NOT FOUND THEN RAISE NOTICE 'source schema % does not exist!', source_schema; RETURN ; END IF; PERFORM nspname FROM pg_namespace WHERE nspname = quote_ident(dest_schema); IF FOUND THEN RAISE NOTICE 'dest schema % already exists!', dest_schema; RETURN ; END IF; EXECUTE 'CREATE SCHEMA ' || quote_ident(dest_schema) ; FOR object IN SELECT sequence_name::text FROM information_schema.sequences WHERE sequence_schema = quote_ident(source_schema) LOOP EXECUTE 'CREATE SEQUENCE ' || quote_ident(dest_schema) || '.' || quote_ident(object); srctbl := quote_ident(source_schema) || '.' || quote_ident(object); EXECUTE 'SELECT last_value, max_value, start_value, increment_by, min_value, cache_value, log_cnt, is_cycled, is_called FROM ' || quote_ident(source_schema) || '.' || quote_ident(object) || ';' INTO sq_last_value, sq_max_value, sq_start_value, sq_increment_by, sq_min_value, sq_cache_value, sq_log_cnt, sq_is_cycled, sq_is_called ; IF sq_is_cycled THEN sq_cycled := 'CYCLE'; ELSE sq_cycled := 'NO CYCLE'; END IF; EXECUTE 'ALTER SEQUENCE ' || quote_ident(dest_schema) || '.' || quote_ident(object) || ' INCREMENT BY ' || sq_increment_by || ' MINVALUE ' || sq_min_value || ' MAXVALUE ' || sq_max_value || ' START WITH ' || sq_start_value || ' RESTART ' || sq_min_value || ' CACHE ' || sq_cache_value || sq_cycled || ' ;' ; buffer := quote_ident(dest_schema) || '.' || quote_ident(object); IF include_recs THEN EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_last_value || ', ' || sq_is_called || ');' ; ELSE EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_start_value || ', ' || sq_is_called || ');' ; END IF; END LOOP; FOR object IN SELECT TABLE_NAME::text FROM information_schema.tables WHERE table_schema = quote_ident(source_schema) AND table_type = 'BASE TABLE' LOOP buffer := dest_schema || '.' || quote_ident(object); EXECUTE 'CREATE TABLE ' || buffer || '(LIKE ' || quote_ident(source_schema) || '.' || quote_ident(object) || ' INCLUDING ALL)'; IF include_recs THEN EXECUTE 'INSERT INTO ' || buffer || ' SELECT * FROM ' || quote_ident(source_schema) || '.' || quote_ident(object) || ';'; END IF; FOR column_, default_ IN SELECT column_name::text, REPLACE(column_default::text, source_schema, dest_schema) FROM information_schema.COLUMNS WHERE table_schema = dest_schema AND TABLE_NAME = object AND column_default LIKE 'nextval(%' || quote_ident(source_schema) || '%::regclass)' LOOP EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_; END LOOP; END LOOP; FOR qry IN SELECT 'ALTER TABLE ' || quote_ident(dest_schema) || '.' || quote_ident(rn.relname) || ' ADD CONSTRAINT ' || quote_ident(ct.conname) || ' ' || pg_get_constraintdef(ct.oid) || ';' FROM pg_constraint ct JOIN pg_class rn ON rn.oid = ct.conrelid WHERE connamespace = src_oid AND rn.relkind = 'r' AND ct.contype = 'f' LOOP EXECUTE qry; END LOOP; FOR object IN SELECT table_name::text, view_definition FROM information_schema.views WHERE table_schema = quote_ident(source_schema) LOOP buffer := dest_schema || '.' || quote_ident(object); SELECT view_definition INTO v_def FROM information_schema.views WHERE table_schema = quote_ident(source_schema) AND table_name = quote_ident(object); EXECUTE 'CREATE OR REPLACE VIEW ' || buffer || ' AS ' || v_def || ';' ; END LOOP; FOR func_oid IN SELECT oid FROM pg_proc WHERE pronamespace = src_oid LOOP SELECT pg_get_functiondef(func_oid) INTO qry; SELECT replace(qry, source_schema, dest_schema) INTO dest_qry; EXECUTE dest_qry; END LOOP; RETURN; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100;" - sql_clone = "SELECT clone_schema('#{ref_cloning.source_referential.slug}', '#{ref_cloning.target_referential.slug}_tmp', TRUE);" - sql_drop = "DROP SCHEMA #{ref_cloning.target_referential.slug} CASCADE;" - sql_rename = "ALTER SCHEMA #{ref_cloning.target_referential.slug}_tmp RENAME TO #{ref_cloning.target_referential.slug};" + + source_schema = ref_cloning.source_referential.slug + target_schema = "#{source_schema}_tmp" + + clone_schema ref_cloning, source_schema, target_schema + end + + private + + def clone_schema ref_cloning, source_schema, target_schema ref_cloning.run! - begin - ActiveRecord::Base.connection.execute sql_func - ActiveRecord::Base.connection.execute sql_clone - ActiveRecord::Base.connection.execute sql_drop - ActiveRecord::Base.connection.execute sql_rename - ref_cloning.successful! - rescue Exception => e - Rails.logger.error "ReferentialCloningWorker : #{e}" - ref_cloning.failed! - end + StoredProcedures.invoke_stored_procedure(:clone_schema, source_schema, target_schema, true) + execute_sql "DROP SCHEMA #{source_schema} CASCADE;" + execute_sql "ALTER SCHEMA #{target_schema} RENAME TO #{source_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 end end diff --git a/config/application.rb b/config/application.rb index 70b927855..06f931765 100644 --- a/config/application.rb +++ b/config/application.rb @@ -31,6 +31,7 @@ module ChouetteIhm config.browserify_rails.commandline_options = "-t [ babelify --presets [ react es2015 ] ]" config.active_record.observers = :route_observer + config.active_record.raise_in_transactional_callbacks = true unless Rails.env.production? # Work around sprockets+teaspoon mismatch: diff --git a/config/environment.rb b/config/environment.rb index 592eda45a..4d27bfaec 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -6,4 +6,4 @@ require File.expand_path('../application', __FILE__) Rails.application.initialize! # Fix version -APP_VERSION = 'Itération 7' +APP_VERSION = 'Itération 9' diff --git a/config/environments/development.rb b/config/environments/development.rb index 61a0b97e9..0b4eab7d2 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -78,6 +78,9 @@ Rails.application.configure do config.codifligne_url = "https://pprod.codifligne.stif.info" config.portal_url = "http://stif-boiv-staging.af83.priv" + # IEV url + config.iev_url = "localhost:8080" + # file to data for demo config.demo_data = "tmp/demo.zip" diff --git a/config/environments/production.rb b/config/environments/production.rb index 71fe99fe8..41b31b1e8 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -19,7 +19,7 @@ Rails.application.configure do # config.action_dispatch.rack_cache = true # Disable Rails's static asset server (Apache or nginx will already do this). - config.serve_static_assets = false + config.serve_static_files = false # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier diff --git a/config/environments/test.rb b/config/environments/test.rb index b77a26273..d83b4fd85 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -15,7 +15,7 @@ Rails.application.configure do config.eager_load = false # Configure static asset server for tests with Cache-Control for performance. - config.serve_static_assets = true + config.serve_static_files = true config.static_cache_control = 'public, max-age=3600' # Show full error reports and disable caching. diff --git a/config/initializers/active_record.rb b/config/initializers/active_record.rb index cb4bf65b4..bdf9e0b4b 100644 --- a/config/initializers/active_record.rb +++ b/config/initializers/active_record.rb @@ -1,2 +1,5 @@ +require_relative '../../lib/af83/stored_procedures' + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "bigserial primary key" +StoredProcedures.create_stored_procedure(:clone_schema) diff --git a/config/initializers/apartment.rb b/config/initializers/apartment.rb index 602c4b51d..2c2632f40 100644 --- a/config/initializers/apartment.rb +++ b/config/initializers/apartment.rb @@ -41,7 +41,9 @@ Apartment.configure do |config| "CleanUpResult", "Calendar", "Import", - "NetexImport" + "NetexImport", + "ImportMessage", + "ImportResource" ] # use postgres schemas? diff --git a/config/initializers/formtastic.rb b/config/initializers/formtastic.rb index 2cdc37243..e2341f037 100644 --- a/config/initializers/formtastic.rb +++ b/config/initializers/formtastic.rb @@ -74,3 +74,9 @@ Formtastic::FormBuilder.default_text_area_width = 50 # this to false. Doing so will add a `novalidate` attribute to the `<form>` tag. # See http://diveintohtml5.org/forms.html#validation for more info. # Formtastic::FormBuilder.perform_browser_validations = true + + +# ------------------------------------------------------------------------------------ +# Preparing Formtastic 4.0 +Formtastic::FormBuilder.action_class_finder = Formtastic::ActionClassFinder +Formtastic::FormBuilder.input_class_finder = Formtastic::InputClassFinder diff --git a/config/initializers/postgresql_adapter_patch.rb b/config/initializers/postgresql_adapter_patch.rb deleted file mode 100644 index 2e4d73f85..000000000 --- a/config/initializers/postgresql_adapter_patch.rb +++ /dev/null @@ -1,54 +0,0 @@ -# module ::ArJdbc -# module PostgreSQL -# def quote_column_name(name) -# if name.is_a?(Array) -# name.collect { |n| %("#{n.to_s.gsub("\"", "\"\"")}") }.join(',') -# else -# %("#{name.to_s.gsub("\"", "\"\"")}") -# end -# end -# end -# end -# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:primary_key] = "bigserial primary key" - -# Add missing double-quote to write array of daterange in SQL query -# See #1782 - -class ActiveRecord::ConnectionAdapters::PostgreSQLColumn - - def self.array_to_string(value, column, adapter) - casted_values = value.map do |val| - if String === val - if val == "NULL" - "\"#{val}\"" - else - quote_and_escape(adapter.type_cast(val, column, true)) - end - elsif Range === val - casted_value = adapter.type_cast(val, column, true) - "\"#{casted_value}\"" - else - adapter.type_cast(val, column, true) - end - end - "{#{casted_values.join(',')}}" - end - -end - -module ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID - class DateRange < Range - # Unnormalize daterange - # [2016-11-19,2016-12-26) -> 2016-11-19..2016-12-25 - def type_cast(value) - result = super value - - if result.respond_to?(:exclude_end?) && result.exclude_end? - ::Range.new(result.begin, result.end - 1, false) - else - result - end - end - end - register_type 'daterange', DateRange.new(:date) -end diff --git a/config/initializers/ransack.rb b/config/initializers/ransack.rb new file mode 100644 index 000000000..659ee4a79 --- /dev/null +++ b/config/initializers/ransack.rb @@ -0,0 +1,13 @@ +Ransack.configure do |config| + config.add_predicate 'between', + arel_predicate: 'between', + formatter: proc { |v| v.split(' to ') }, + type: :string +end +module Arel + module Predications + def between other + gteq(other[0]).and(lt(other[1])) + end + end +end diff --git a/config/initializers/squeel.rb b/config/initializers/squeel.rb index 821e72952..9fb8b24b2 100644 --- a/config/initializers/squeel.rb +++ b/config/initializers/squeel.rb @@ -1,8 +1,8 @@ -Squeel.configure do |config| +# Squeel.configure do |config| # To load hash extensions (to allow for AND (&), OR (|), and NOT (-) against # hashes of conditions): # - config.load_core_extensions :hash + # config.load_core_extensions :hash # To load symbol extensions (for a subset of the old MetaWhere functionality, # via Arel predicate methods on Symbols: :name.matches, etc): @@ -21,4 +21,4 @@ Squeel.configure do |config| # "less_than_any" and "less_than_all" as well: # # config.alias_predicate :less_than, :lt -end +# end diff --git a/config/locales/actions.en.yml b/config/locales/actions.en.yml index e4b0bcb28..5bfd9d9fb 100644 --- a/config/locales/actions.en.yml +++ b/config/locales/actions.en.yml @@ -9,8 +9,10 @@ en: archive: "Archive" unarchive: "Unarchive" clone: 'Clone' + duplicate: 'Clone' clean_up: 'Clean up' sync: 'Synchronize' + combine: 'Combine' or: "or" cancel: "Cancel" search_hint: "Type in a search term" diff --git a/config/locales/actions.fr.yml b/config/locales/actions.fr.yml index 0cd3de8e5..94afc1393 100644 --- a/config/locales/actions.fr.yml +++ b/config/locales/actions.fr.yml @@ -10,8 +10,10 @@ fr: archive: 'Conserver' unarchive: 'Déconserver' clone: 'Dupliquer' + duplicate: 'Dupliquer' clean_up: 'Purger' sync: 'Synchroniser' + combine: 'Combiner' or: "ou" cancel: "Annuler" search_hint: "Entrez un texte à rechercher" diff --git a/config/locales/calendars.en.yml b/config/locales/calendars.en.yml index cb63afde5..17dc8baf1 100644 --- a/config/locales/calendars.en.yml +++ b/config/locales/calendars.en.yml @@ -1,5 +1,13 @@ en: calendars: + days: + monday: M + tuesday: Tu + wednesday: W + thursday: Th + friday: F + saturday: Sa + sunday: Su standard_calendars: Standard calendars standard_calendar: Standard calendar actions: diff --git a/config/locales/calendars.fr.yml b/config/locales/calendars.fr.yml index 81254c81e..32e3c66d2 100644 --- a/config/locales/calendars.fr.yml +++ b/config/locales/calendars.fr.yml @@ -1,5 +1,26 @@ fr: calendars: + 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 standard_calendars: Calendriers standards standard_calendar: Calendrier standard actions: diff --git a/config/locales/en.yml b/config/locales/en.yml index 77ad82605..5ed0b9ec5 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -16,4 +16,5 @@ en: last_update: 'Last update on<br>%{time}' last_sync: 'Last sync on %{time}' validity_range: '%{debut} > %{end}' + bounding_dates: '%{debut} > %{end}' metadatas: 'Informations' diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 5ac6bb8b1..db8a3608d 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -16,4 +16,5 @@ fr: last_update: 'Dernière mise à jour<br>le %{time}' last_sync: 'Dernière mise à jour le %{time}' validity_range: '%{debut} > %{end}' + bounding_dates: '%{debut} > %{end}' metadatas: 'Informations' diff --git a/config/locales/routing_constraint_zones.en.yml b/config/locales/routing_constraint_zones.en.yml index 7012a1493..2d4412dba 100644 --- a/config/locales/routing_constraint_zones.en.yml +++ b/config/locales/routing_constraint_zones.en.yml @@ -9,6 +9,17 @@ en: line: Line created_at: Created at updated_at: Updated at + objectid: Object ID + stop_points_count: Number of stop points + route: Route + errors: + models: + routing_constraint_zone: + attributes: + stop_points: + not_enough_stop_points: 'You should specify at least 2 stop points.' + stop_points_not_from_route: 'Stop point does not belong to the Route of this Routing constraint zone.' + all_stop_points_selected: 'All stop points from route cannot be selected.' routing_constraint_zones: actions: new: New routing constraint zone @@ -21,3 +32,4 @@ en: title: "Update routing constraint zone %{routing_constraint_zone}" show: title: "Routing constraint zone %{routing_constraint_zone}" + diff --git a/config/locales/routing_constraint_zones.fr.yml b/config/locales/routing_constraint_zones.fr.yml index bb4d8bcd2..36dcf9301 100644 --- a/config/locales/routing_constraint_zones.fr.yml +++ b/config/locales/routing_constraint_zones.fr.yml @@ -9,6 +9,17 @@ fr: line: Ligne created_at: "Créé le" updated_at: "Edité le" + objectid: Object ID + stop_points_count: Nombre d'arrêts + route: Itinéraire + errors: + models: + routing_constraint_zone: + attributes: + stop_points: + not_enough_stop_points: "Il faut mettre au moins deux arrêts sur séquence d'arrêts." + stop_points_not_from_route: "Arrêt sur séquence d'arrêts n'appartient pas à la Route de cette Zone de contrainte." + all_stop_points_selected: "Une zone de contrainte ne peut pas couvrir tous les arrêts d'une ligne." routing_constraint_zones: actions: new: Ajouter une zone de contrainte diff --git a/config/locales/time_tables.en.yml b/config/locales/time_tables.en.yml index e783f5b18..5127675e8 100644 --- a/config/locales/time_tables.en.yml +++ b/config/locales/time_tables.en.yml @@ -64,6 +64,8 @@ en: attributes: time_table: comment: "Name" + color: "Associated color" + bounding_dates: 'Global validity period' version: "Short name" day_types: "Period day types" none: "none" diff --git a/config/locales/time_tables.fr.yml b/config/locales/time_tables.fr.yml index d67227c26..dc4d4572f 100644 --- a/config/locales/time_tables.fr.yml +++ b/config/locales/time_tables.fr.yml @@ -64,6 +64,8 @@ fr: attributes: time_table: comment: "Nom" + color: "Couleur associée" + bounding_dates: 'Période de validité englobante' version: "Abréviation" day_types: "Jours d'application des périodes" none: "aucun" diff --git a/config/routes.rb b/config/routes.rb index 33f3961b1..538c069ed 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -123,6 +123,7 @@ ChouetteIhm::Application.routes.draw do end resources :vehicle_journey_imports resources :vehicle_journey_exports + resources :stop_points, only: :index, controller: 'route_stop_points' end resources :routing_constraint_zones end @@ -165,6 +166,7 @@ ChouetteIhm::Application.routes.draw do end member do get 'duplicate' + get 'month', defaults: { format: :json } end resources :time_table_dates resources :time_table_periods @@ -211,8 +213,11 @@ ChouetteIhm::Application.routes.draw do get '/help/(*slug)' => 'help#show' - get '/404', :to => 'errors#not_found' - get '/422', :to => 'errors#server_error' - get '/500', :to => 'errors#server_error' + if Rails.env.production? + get '404', to: 'errors#not_found' + get '403', to: 'errors#not_allowed' + get '422', to: 'errors#server_error' + get '500', to: 'errors#server_error' + end end diff --git a/db/migrate/20120515134710_create_imports.rb b/db/migrate/20120515134710_create_imports.rb index 5bc5b367b..5da398fc9 100644 --- a/db/migrate/20120515134710_create_imports.rb +++ b/db/migrate/20120515134710_create_imports.rb @@ -1,13 +1,11 @@ class CreateImports < ActiveRecord::Migration def change - unless table_exists? :imports - create_table :imports do |t| - t.belongs_to :referential - t.string :status + create_table :imports do |t| + t.belongs_to :referential + t.string :status - t.timestamps - end - add_index :imports, :referential_id + t.timestamps end + add_index :imports, :referential_id end end diff --git a/db/migrate/20130207123618_add_foreign_keys.ninoxe_engine.rb b/db/migrate/20130207123618_add_foreign_keys.ninoxe_engine.rb index cab9d13f0..da4ee27de 100644 --- a/db/migrate/20130207123618_add_foreign_keys.ninoxe_engine.rb +++ b/db/migrate/20130207123618_add_foreign_keys.ninoxe_engine.rb @@ -2,277 +2,165 @@ require "forwardable" class AddForeignKeys < ActiveRecord::Migration - def up - # t.remove_foreign_key does not works if foreign key doesn't exists so check before if keys already exists - change_table :access_links do |t| - if @connection.foreign_keys(:access_links).any? - @connection.foreign_keys(:access_links).map do |f| - name = f.options[:name] - if (name == "aclk_acpt_fkey" || name == "aclk_area_fkey" ) - remove_foreign_key :access_links, :name => name - end - end - end - t.foreign_key :access_points, :dependent => :delete, :name => 'aclk_acpt_fkey' - t.foreign_key :stop_areas, :dependent => :delete, :name => 'aclk_area_fkey' - end - change_table :access_points do |t| - if @connection.foreign_keys(:access_points).any? - @connection.foreign_keys(:access_points).map do |f| - name = f.options[:name] - if (name == "access_area_fkey" ) - remove_foreign_key :access_points, :name => name - end - end - end - t.foreign_key :stop_areas, :dependent => :delete, :name => 'access_area_fkey' - end - change_table :connection_links do |t| - if @connection.foreign_keys(:connection_links).any? - @connection.foreign_keys(:connection_links).map do |f| - name = f.options[:name] - if (name == "colk_endarea_fkey" || name == "colk_startarea_fkey" ) - remove_foreign_key :connection_links, :name => name - end - end - end - t.foreign_key :stop_areas, :dependent => :delete, :column => 'arrival_id', :name => 'colk_endarea_fkey' - t.foreign_key :stop_areas, :dependent => :delete, :column => 'departure_id', :name => 'colk_startarea_fkey' - end - change_table :group_of_lines_lines do |t| - if @connection.foreign_keys(:group_of_lines_lines).any? - @connection.foreign_keys(:group_of_lines_lines).map do |f| - name = f.options[:name] - if (name == "groupofline_group_fkey" || name == "groupofline_line_fkey" ) - remove_foreign_key :group_of_lines_lines, :name => name - end - end - end - t.foreign_key :group_of_lines, :dependent => :delete, :name => 'groupofline_group_fkey' - t.foreign_key :lines, :dependent => :delete, :name => 'groupofline_line_fkey' - end - change_table :journey_patterns do |t| - if @connection.foreign_keys(:journey_patterns).any? - @connection.foreign_keys(:journey_patterns).map do |f| - name = f.options[:name] - if (name == "arrival_point_fkey" || name == "departure_point_fkey" || name == "jp_route_fkey") - remove_foreign_key :journey_patterns, :name => name - end - end - end - t.foreign_key :stop_points, :dependent => :nullify, :column => 'arrival_stop_point_id', :name => 'arrival_point_fkey' - t.foreign_key :stop_points, :dependent => :nullify, :column => 'departure_stop_point_id', :name => 'departure_point_fkey' - t.foreign_key :routes, :dependent => :delete, :name => 'jp_route_fkey' - end - change_table :journey_patterns_stop_points do |t| - if @connection.foreign_keys(:journey_patterns_stop_points).any? - @connection.foreign_keys(:journey_patterns_stop_points).map do |f| - name = f.options[:name] - if (name == "jpsp_jp_fkey" || name == "jpsp_stoppoint_fkey" ) - remove_foreign_key :journey_patterns_stop_points, :name => name - end - end - end - t.foreign_key :journey_patterns, :dependent => :delete, :name => 'jpsp_jp_fkey' - t.foreign_key :stop_points, :dependent => :delete, :name => 'jpsp_stoppoint_fkey' - end - change_table :lines do |t| - if @connection.foreign_keys(:lines).any? - @connection.foreign_keys(:lines).map do |f| - name = f.options[:name] - if (name == "line_company_fkey" || name == "line_ptnetwork_fkey" ) - remove_foreign_key :lines, :name => name - end - end - end - t.foreign_key :companies, :dependent => :nullify, :name => 'line_company_fkey' - t.foreign_key :networks, :dependent => :nullify, :name => 'line_ptnetwork_fkey' - end - change_table :routes do |t| - if @connection.foreign_keys(:routes).any? - @connection.foreign_keys(:routes).map do |f| - name = f.options[:name] - if (name == "route_line_fkey" ) - remove_foreign_key :routes, :name => name - end - end - end - t.foreign_key :lines, :dependent => :delete, :name => 'route_line_fkey' - end - change_table :routing_constraints_lines do |t| - if @connection.foreign_keys(:routing_constraints_lines).any? - @connection.foreign_keys(:routing_constraints_lines).map do |f| - name = f.options[:name] - if (name == "routingconstraint_line_fkey" || name == "routingconstraint_stoparea_fkey" ) - remove_foreign_key :routing_constraints_lines, :name => name - end - end - end - t.foreign_key :lines, :dependent => :delete, :name => 'routingconstraint_line_fkey' - t.foreign_key :stop_areas, :dependent => :delete, :name => 'routingconstraint_stoparea_fkey' - end - change_table :stop_areas do |t| - if @connection.foreign_keys(:stop_areas).any? - @connection.foreign_keys(:stop_areas).map do |f| - name = f.options[:name] - if (name == "area_parent_fkey" ) - remove_foreign_key :stop_areas, :name => name - end - end - end - t.foreign_key :stop_areas, :dependent => :nullify, :column => 'parent_id', :name => 'area_parent_fkey' - end - change_table :stop_areas_stop_areas do |t| - if @connection.foreign_keys(:stop_areas_stop_areas).any? - @connection.foreign_keys(:stop_areas_stop_areas).map do |f| - name = f.options[:name] - if (name == "stoparea_child_fkey" || name == "stoparea_parent_fkey" ) - remove_foreign_key :stop_areas_stop_areas, :name => name - end - end - end - t.foreign_key :stop_areas, :dependent => :delete, :column => 'child_id', :name => 'stoparea_child_fkey' - t.foreign_key :stop_areas, :dependent => :delete, :column => 'parent_id', :name => 'stoparea_parent_fkey' - end - change_table :stop_points do |t| - if @connection.foreign_keys(:stop_points).any? - @connection.foreign_keys(:stop_points).map do |f| - name = f.options[:name] - if (name == "stoppoint_area_fkey" || name == "stoppoint_route_fkey" ) - remove_foreign_key :stop_points, :name => name - end - end - end - t.foreign_key :stop_areas, :name => 'stoppoint_area_fkey' - t.foreign_key :routes, :dependent => :delete, :name => 'stoppoint_route_fkey' - end - change_table :time_table_dates do |t| - if @connection.foreign_keys(:time_table_dates).any? - @connection.foreign_keys(:time_table_dates).map do |f| - name = f.options[:name] - if (name == "tm_date_fkey" ) - remove_foreign_key :time_table_dates, :name => name - end - end - end - t.foreign_key :time_tables, :dependent => :delete, :name => 'tm_date_fkey' - end - change_table :time_table_periods do |t| - if @connection.foreign_keys(:time_table_periods).any? - @connection.foreign_keys(:time_table_periods).map do |f| - name = f.options[:name] - if (name == "tm_period_fkey" ) - remove_foreign_key :time_table_periods, :name => name - end - end - end - t.foreign_key :time_tables, :dependent => :delete, :name => 'tm_period_fkey' - end - change_table :time_tables_vehicle_journeys do |t| - if @connection.foreign_keys(:time_tables_vehicle_journeys).any? - @connection.foreign_keys(:time_tables_vehicle_journeys).map do |f| - name = f.options[:name] - if (name == "vjtm_tm_fkey" || name == "vjtm_vj_fkey" ) - remove_foreign_key :time_tables_vehicle_journeys, :name => name - end - end - end - t.foreign_key :time_tables, :dependent => :delete, :name => 'vjtm_tm_fkey' - t.foreign_key :vehicle_journeys, :dependent => :delete, :name => 'vjtm_vj_fkey' - end - change_table :vehicle_journey_at_stops do |t| - if @connection.foreign_keys(:vehicle_journey_at_stops).any? - @connection.foreign_keys(:vehicle_journey_at_stops).map do |f| - name = f.options[:name] - if (name == "vjas_sp_fkey" || name == "vjas_vj_fkey" ) - remove_foreign_key :vehicle_journey_at_stops, :name => name + def disable_foreign_key(table, name) + if foreign_key?(table, name) + remove_foreign_key table, name: name end end - end - t.foreign_key :stop_points, :dependent => :delete, :name => 'vjas_sp_fkey' - t.foreign_key :vehicle_journeys, :dependent => :delete, :name => 'vjas_vj_fkey' - end - change_table :vehicle_journeys do |t| - if @connection.foreign_keys(:vehicle_journeys).any? - @connection.foreign_keys(:vehicle_journeys).map do |f| - name = f.options[:name] - if (name == "vj_company_fkey" || name == "vj_jp_fkey" || name == "vj_route_fkey") - remove_foreign_key :vehicle_journeys, :name => name + + def foreign_key?(table, name) + @connection.foreign_keys(table).any? do |foreign_key| + foreign_key.options[:name] == name.to_s end end - end - t.foreign_key :companies, :dependent => :nullify, :name => 'vj_company_fkey' - t.foreign_key :journey_patterns, :dependent => :delete, :name => 'vj_jp_fkey' - t.foreign_key :routes, :dependent => :delete, :name => 'vj_route_fkey' - end - + + def up + disable_foreign_key :access_links, :aclk_acpt_fkey + disable_foreign_key :access_links, :aclk_area_fkey + + add_foreign_key :access_links, :access_points, dependent: :cascade, :name => 'aclk_acpt_fkey' + add_foreign_key :access_links, :stop_areas, dependent: :cascade, :name => 'aclk_area_fkey' + + disable_foreign_key :access_points, :access_area_fkey + add_foreign_key :access_points, :stop_areas, dependent: :cascade, name: :access_area_fkey + + disable_foreign_key :connection_links, :colk_endarea_fkey + disable_foreign_key :connection_links, :colk_startarea_fkey + + add_foreign_key :connection_links, :stop_areas, :on_delete => :cascade, :column => 'arrival_id', :name => 'colk_endarea_fkey' + add_foreign_key :connection_links, :stop_areas, :on_delete => :cascade, :column => 'departure_id', :name => 'colk_startarea_fkey' + + disable_foreign_key :group_of_lines_lines, :groupofline_group_fkey + disable_foreign_key :group_of_lines_lines, :groupofline_line_fkey + + add_foreign_key :group_of_lines_lines, :group_of_lines, :on_delete => :cascade, :name => 'groupofline_group_fkey' + add_foreign_key :group_of_lines_lines, :lines, :on_delete => :cascade, :name => 'groupofline_line_fkey' + + + disable_foreign_key :journey_patterns, :arrival_point_fkey + disable_foreign_key :journey_patterns, :departure_point_fkey + disable_foreign_key :journey_patterns, :jp_route_fkey + + add_foreign_key :journey_patterns, :stop_points, :on_delete => :nullify, :column => 'arrival_stop_point_id', :name => 'arrival_point_fkey' + add_foreign_key :journey_patterns, :stop_points, :on_delete => :nullify, :column => 'departure_stop_point_id', :name => 'departure_point_fkey' + add_foreign_key :journey_patterns, :routes, :on_delete => :cascade, :name => 'jp_route_fkey' + + disable_foreign_key :journey_patterns_stop_points, :jpsp_jp_fkey + disable_foreign_key :journey_patterns_stop_points, :jpsp_stoppoint_fkey + + add_foreign_key :journey_patterns_stop_points, :journey_patterns, :on_delete => :cascade, :name => 'jpsp_jp_fkey' + add_foreign_key :journey_patterns_stop_points, :stop_points, :on_delete => :cascade, :name => 'jpsp_stoppoint_fkey' + + disable_foreign_key :lines, :line_company_fkey + disable_foreign_key :lines, :line_ptnetwork_fkey + + add_foreign_key :lines, :companies, :on_delete => :nullify, :name => 'line_company_fkey' + add_foreign_key :lines, :networks, :on_delete => :nullify, :name => 'line_ptnetwork_fkey' + + disable_foreign_key :routes, :route_line_fkey + add_foreign_key :routes, :lines, :on_delete => :cascade, :name => 'route_line_fkey' + + + disable_foreign_key :routing_constraints_lines, :routingconstraint_line_fkey + disable_foreign_key :routing_constraints_lines, :routingconstraint_stoparea_fkey + + add_foreign_key :routing_constraints_lines, :lines, :on_delete => :cascade, :name => 'routingconstraint_line_fkey' + add_foreign_key :routing_constraints_lines, :stop_areas, :on_delete => :cascade, :name => 'routingconstraint_stoparea_fkey' + + + + disable_foreign_key :stop_areas, :area_parent_fkey + add_foreign_key :stop_areas, :stop_areas, :on_delete => :nullify, :column => 'parent_id', :name => 'area_parent_fkey' + + disable_foreign_key :stop_areas_stop_areas, :stoparea_child_fkey + disable_foreign_key :stop_areas_stop_areas, :stoparea_parent_fkey + + add_foreign_key :stop_areas_stop_areas, :stop_areas, :on_delete => :cascade, :column => 'child_id', :name => 'stoparea_child_fkey' + add_foreign_key :stop_areas_stop_areas, :stop_areas, :on_delete => :cascade, :column => 'parent_id', :name => 'stoparea_parent_fkey' + + disable_foreign_key :stop_points, :stoppoint_area_fkey + disable_foreign_key :stop_points, :stoppoint_route_fkey + + add_foreign_key :stop_points, :stop_areas, :name => 'stoppoint_area_fkey' + add_foreign_key :stop_points, :routes, :on_delete => :cascade, :name => 'stoppoint_route_fkey' + + disable_foreign_key :time_table_dates, :tm_date_fkey + add_foreign_key :time_table_dates, :time_tables, :on_delete => :cascade, :name => 'tm_date_fkey' + + + disable_foreign_key :time_table_periods, :tm_period_fkey + add_foreign_key :time_table_periods, :time_tables, :on_delete => :cascade, :name => 'tm_period_fkey' + + disable_foreign_key :time_tables_vehicle_journeys, :vjtm_tm_fkey + disable_foreign_key :time_tables_vehicle_journeys, :vjtm_vj_fkey + add_foreign_key :time_tables_vehicle_journeys, :time_tables, :on_delete => :cascade, :name => 'vjtm_tm_fkey' + add_foreign_key :time_tables_vehicle_journeys, :vehicle_journeys, :on_delete => :cascade, :name => 'vjtm_vj_fkey' + + + disable_foreign_key :vehicle_journey_at_stops, :vjas_sp_fkey + disable_foreign_key :vehicle_journey_at_stops, :vjas_vj_fkey + add_foreign_key :vehicle_journey_at_stops, :stop_points, :on_delete => :cascade, :name => 'vjas_sp_fkey' + add_foreign_key :vehicle_journey_at_stops, :vehicle_journeys, :on_delete => :cascade, :name => 'vjas_vj_fkey' + + + disable_foreign_key :vehicle_journeys, :vj_company_fkey + disable_foreign_key :vehicle_journeys, :vj_jp_fkey + disable_foreign_key :vehicle_journeys, :vj_route_fkey + + add_foreign_key :vehicle_journeys, :companies, :on_delete => :nullify, :name => 'vj_company_fkey' + add_foreign_key :vehicle_journeys, :journey_patterns, :on_delete => :cascade, :name => 'vj_jp_fkey' + add_foreign_key :vehicle_journeys, :routes, :on_delete => :cascade, :name => 'vj_route_fkey' end + def down - change_table :access_links do |t| - t.remove_foreign_key :name => :aclk_acpt_fkey - t.remove_foreign_key :name => :aclk_area_fkey - end - change_table :access_points do |t| - t.remove_foreign_key :name => :access_area_fkey - end - change_table :connection_links do |t| - t.remove_foreign_key :name => :colk_endarea_fkey - t.remove_foreign_key :name => :colk_startarea_fkey - end - change_table :group_of_lines_lines do |t| - t.remove_foreign_key :name => :groupofline_group_fkey - t.remove_foreign_key :name => :groupofline_line_fkey - end - change_table :journey_patterns do |t| - t.remove_foreign_key :name => :arrival_point_fkey - t.remove_foreign_key :name => :departure_point_fkey - t.remove_foreign_key :name => :jp_route_fkey - end - change_table :journey_patterns_stop_points do |t| - t.remove_foreign_key :name => :jpsp_jp_fkey - t.remove_foreign_key :name => :jpsp_stoppoint_fkey - end - change_table :lines do |t| - t.remove_foreign_key :name => :line_company_fkey - t.remove_foreign_key :name => :line_ptnetwork_fkey - end - change_table :routes do |t| - t.remove_foreign_key :name => :route_line_fkey - end - change_table :routing_constraints_lines do |t| - t.remove_foreign_key :name => :routingconstraint_line_fkey - t.remove_foreign_key :name => :routingconstraint_stoparea_fkey - end - change_table :stop_areas do |t| - t.remove_foreign_key :name => :area_parent_fkey - end - change_table :stop_areas_stop_areas do |t| - t.remove_foreign_key :name => :stoparea_child_fkey - t.remove_foreign_key :name => :stoparea_parent_fkey - end - change_table :stop_points do |t| - t.remove_foreign_key :name => :stoppoint_area_fkey - t.remove_foreign_key :name => :stoppoint_route_fkey - end - change_table :time_table_dates do |t| - t.remove_foreign_key :name => :tm_date_fkey - end - change_table :time_table_periods do |t| - t.remove_foreign_key :name => :tm_period_fkey - end - change_table :time_tables_vehicle_journeys do |t| - t.remove_foreign_key :name => :vjtm_tm_fkey - t.remove_foreign_key :name => :vjtm_vj_fkey - end - change_table :vehicle_journey_at_stops do |t| - t.remove_foreign_key :name => :vjas_sp_fkey - t.remove_foreign_key :name => :vjas_vj_fkey - end - change_table :vehicle_journeys do |t| - t.remove_foreign_key :name => :vj_company_fkey - t.remove_foreign_key :name => :vj_jp_fkey - t.remove_foreign_key :name => :vj_route_fkey - end + remove_foreign_key :access_links, :name => :aclk_acpt_fkey + remove_foreign_key :access_links, :name => :aclk_area_fkey + + remove_foreign_key :access_points, :name => :access_area_fkey + + remove_foreign_key :connection_links, :name => :colk_endarea_fkey + remove_foreign_key :connection_links, :name => :colk_startarea_fkey + + remove_foreign_key :group_of_lines_lines, :name => :groupofline_group_fkey + remove_foreign_key :group_of_lines_lines, :name => :groupofline_line_fkey + + remove_foreign_key :journey_patterns, :name => :arrival_point_fkey + remove_foreign_key :journey_patterns, :name => :departure_point_fkey + remove_foreign_key :journey_patterns, :name => :jp_route_fkey + + remove_foreign_key :journey_patterns_stop_points, :name => :jpsp_jp_fkey + remove_foreign_key :journey_patterns_stop_points, :name => :jpsp_stoppoint_fkey + + remove_foreign_key :lines, :name => :line_company_fkey + remove_foreign_key :lines, :name => :line_ptnetwork_fkey + + remove_foreign_key :routes, :name => :route_line_fkey + + remove_foreign_key :routing_constraints_lines, :name => :routingconstraint_line_fkey + remove_foreign_key :routing_constraints_lines, :name => :routingconstraint_stoparea_fkey + + remove_foreign_key :stop_areas, :name => :area_parent_fkey + + remove_foreign_key :stop_areas_stop_areas, :name => :stoparea_child_fkey + remove_foreign_key :stop_areas_stop_areas, :name => :stoparea_parent_fkey + + remove_foreign_key :stop_points, :name => :stoppoint_area_fkey + remove_foreign_key :stop_points, :name => :stoppoint_route_fkey + + remove_foreign_key :time_table_dates, :name => :tm_date_fkey + + remove_foreign_key :time_table_periods, :name => :tm_period_fkey + + remove_foreign_key :time_tables_vehicle_journeys, :name => :vjtm_tm_fkey + remove_foreign_key :time_tables_vehicle_journeys, :name => :vjtm_vj_fkey + + remove_foreign_key :vehicle_journey_at_stops, :name => :vjas_sp_fkey + remove_foreign_key :vehicle_journey_at_stops, :name => :vjas_vj_fkey + + remove_foreign_key :vehicle_journeys, :name => :vj_company_fkey + remove_foreign_key :vehicle_journeys, :name => :vj_jp_fkey + remove_foreign_key :vehicle_journeys, :name => :vj_route_fkey + end end diff --git a/db/migrate/20131029110239_create_import_tasks.rb b/db/migrate/20131029110239_create_import_tasks.rb index fa2faec37..ae1c45e40 100644 --- a/db/migrate/20131029110239_create_import_tasks.rb +++ b/db/migrate/20131029110239_create_import_tasks.rb @@ -13,8 +13,8 @@ class CreateImportTasks < ActiveRecord::Migration t.text :result # import report : objects statistics t.text :progress_info # percentage of progress and step code t.timestamps - t.foreign_key :referentials, :dependent => :delete end + add_foreign_key :import_tasks, :referentials, :on_delete => :cascade end end diff --git a/db/migrate/20131029115751_create_compliance_check_tasks.rb b/db/migrate/20131029115751_create_compliance_check_tasks.rb index 9195556b2..897700a1e 100644 --- a/db/migrate/20131029115751_create_compliance_check_tasks.rb +++ b/db/migrate/20131029115751_create_compliance_check_tasks.rb @@ -11,9 +11,9 @@ class CreateComplianceCheckTasks < ActiveRecord::Migration t.string :user_name # name of the user who has requested this task t.text :progress_info # percentage of progress and step code t.timestamps - t.foreign_key :referentials, :dependent => :delete - t.foreign_key :import_tasks, :dependent => :delete end + add_foreign_key :compliance_check_tasks, :referentials, :on_delete => :cascade + add_foreign_key :compliance_check_tasks, :import_tasks, :on_delete => :cascade end end diff --git a/db/migrate/20131029115820_create_compliance_check_results.rb b/db/migrate/20131029115820_create_compliance_check_results.rb index 8b72aa4c0..7f5c8e436 100644 --- a/db/migrate/20131029115820_create_compliance_check_results.rb +++ b/db/migrate/20131029115820_create_compliance_check_results.rb @@ -9,8 +9,8 @@ class CreateComplianceCheckResults < ActiveRecord::Migration t.integer :violation_count # number of violation occurences t.text :detail # detail of violation location t.timestamps - t.foreign_key :compliance_check_tasks, :dependent => :delete end + add_foreign_key :compliance_check_results, :compliance_check_tasks, :on_delete => :cascade end end diff --git a/db/migrate/20150312104557_set_default_value_for_data_format_in_organisation.rb b/db/migrate/20150312104557_set_default_value_for_data_format_in_organisation.rb index 03d48e0bb..cc99366b1 100644 --- a/db/migrate/20150312104557_set_default_value_for_data_format_in_organisation.rb +++ b/db/migrate/20150312104557_set_default_value_for_data_format_in_organisation.rb @@ -1,7 +1,22 @@ class SetDefaultValueForDataFormatInOrganisation < ActiveRecord::Migration def change - Organisation.where(data_format: nil).update_all(data_format: "neptune") - execute "update referentials set data_format = organisations.data_format from organisations where referentials.data_format is null and referentials.organisation_id = organisations.id" + Organisation.all.each do |organisation| + if organisation.data_format.neptune? + organisation.update_attribute(:data_format, "neptune") + end + end + Referential.all.each do |referential| + if referential.data_format.neptune? + referential.update_attribute :data_format, "neptune" + elsif referential.data_format.netex? + referential.update_attribute :data_format, "netex" + elsif referential.data_format.gtfs? + referential.update_attribute :data_format, "gtfs" + elsif referential.data_format.hub? + referential.update_attribute :data_format, "hub" + end + end + change_column :organisations, :data_format, :string, :default => "neptune" end end diff --git a/db/migrate/20150526081746_add_foreign_key_to_routes.ninoxe_engine.rb b/db/migrate/20150526081746_add_foreign_key_to_routes.ninoxe_engine.rb index 32e2a05e4..3594bfe49 100644 --- a/db/migrate/20150526081746_add_foreign_key_to_routes.ninoxe_engine.rb +++ b/db/migrate/20150526081746_add_foreign_key_to_routes.ninoxe_engine.rb @@ -2,28 +2,15 @@ class AddForeignKeyToRoutes < ActiveRecord::Migration require "forwardable" def up - Chouette::Route.all.map do |route| - if route.opposite_route_id.present? && !Chouette::Route.exists?(route.opposite_route_id) + Chouette::Route.all.map do |route| + if route.opposite_route_id.present? && !Chouette::Route.exists?(route.opposite_route_id) route.update_attributes :opposite_route_id => nil - end - end - change_table :routes do |t| - if @connection.foreign_keys(:routes).any? - @connection.foreign_keys(:routes).map do |f| - name = f.options[:name] - if (name == "route_opposite_route_fkey" ) - remove_foreign_key :routes, :name => name - end - end - end - t.foreign_key :routes, :dependent => :nullify, :column => 'opposite_route_id', :name => 'route_opposite_route_fkey' + end end - + add_foreign_key :routes, :routes, dependent: :nullify, name: 'route_opposite_route_fkey', column: 'opposite_route_id' end def down - change_table :routes do |t| - t.remove_foreign_key :name => :route_opposite_route_fkey - end + remove_foreign_key :routes, name: :route_opposite_route_fkey end end diff --git a/db/migrate/20151203132113_create_journey_pattern_sections.ninoxe_engine.rb b/db/migrate/20151203132113_create_journey_pattern_sections.ninoxe_engine.rb index 254e64567..3cfb245cf 100644 --- a/db/migrate/20151203132113_create_journey_pattern_sections.ninoxe_engine.rb +++ b/db/migrate/20151203132113_create_journey_pattern_sections.ninoxe_engine.rb @@ -5,11 +5,11 @@ class CreateJourneyPatternSections < ActiveRecord::Migration t.references :journey_pattern, null: false, index: true, limit: 8 t.references :route_section, null: false, index: true, limit: 8 t.integer :rank, null: false - t.foreign_key :journey_patterns, dependent: :delete - t.foreign_key :route_sections, dependent: :delete - t.timestamps end + add_foreign_key :journey_pattern_sections, :journey_patterns, on_delete: :cascade + add_foreign_key :journey_pattern_sections, :route_sections, on_delete: :cascade + add_index :journey_pattern_sections, [:journey_pattern_id, :route_section_id, :rank], unique: true, name: 'index_jps_on_journey_pattern_id_and_route_section_id_and_rank' end diff --git a/db/migrate/20151215175635_add_limit_and_foreign_key_to_journey_frequencies.ninoxe_engine.rb b/db/migrate/20151215175635_add_limit_and_foreign_key_to_journey_frequencies.ninoxe_engine.rb index fc8869f1c..c69ae12f5 100644 --- a/db/migrate/20151215175635_add_limit_and_foreign_key_to_journey_frequencies.ninoxe_engine.rb +++ b/db/migrate/20151215175635_add_limit_and_foreign_key_to_journey_frequencies.ninoxe_engine.rb @@ -3,8 +3,8 @@ class AddLimitAndForeignKeyToJourneyFrequencies < ActiveRecord::Migration def up change_column :journey_frequencies, :vehicle_journey_id, :integer, limit: 8 change_column :journey_frequencies, :timeband_id, :integer, limit: 8 - add_foreign_key :journey_frequencies, :vehicle_journeys, dependent: :nullify - add_foreign_key :journey_frequencies, :timebands, dependent: :nullify + add_foreign_key :journey_frequencies, :vehicle_journeys, on_delete: :nullify + add_foreign_key :journey_frequencies, :timebands, on_delete: :nullify end def down diff --git a/db/migrate/20170123131243_set_user_permissions.rb b/db/migrate/20170123131243_set_user_permissions.rb deleted file mode 100644 index d9f18c10a..000000000 --- a/db/migrate/20170123131243_set_user_permissions.rb +++ /dev/null @@ -1,7 +0,0 @@ -class SetUserPermissions < ActiveRecord::Migration - def change - User.update_all(permissions: ['routes.create', 'routes.edit', 'routes.destroy', 'journey_patterns.create', 'journey_patterns.edit', 'journey_patterns.destroy', - 'vehicle_journeys.create', 'vehicle_journeys.edit', 'vehicle_journeys.destroy', 'time_tables.create', 'time_tables.edit', 'time_tables.destroy', - 'footnotes.edit', 'footnotes.create', 'footnotes.destroy', 'routing_constraint_zones.create', 'routing_constraint_zones.edit', 'routing_constraint_zones.destroy']) - end -end diff --git a/db/migrate/20170207102136_set_referentials_user_permissions.rb b/db/migrate/20170207102136_set_referentials_user_permissions.rb deleted file mode 100644 index 2e4424db2..000000000 --- a/db/migrate/20170207102136_set_referentials_user_permissions.rb +++ /dev/null @@ -1,11 +0,0 @@ -class SetReferentialsUserPermissions < ActiveRecord::Migration - def change - User.update_all(permissions: ['routes.create', 'routes.edit', 'routes.destroy', 'journey_patterns.create', 'journey_patterns.edit', 'journey_patterns.destroy', - 'vehicle_journeys.create', 'vehicle_journeys.edit', 'vehicle_journeys.destroy', 'time_tables.create', 'time_tables.edit', 'time_tables.destroy', - 'footnotes.edit', 'footnotes.create', 'footnotes.destroy', 'routing_constraint_zones.create', 'routing_constraint_zones.edit', 'routing_constraint_zones.destroy', - 'access_points.create', 'access_points.edit', 'access_points.destroy', 'access_links.create', 'access_links.edit', 'access_links.destroy', - 'connection_links.create', 'connection_links.edit', 'connection_links.destroy', 'route_sections.create', 'route_sections.edit', 'route_sections.destroy']) - end -end - - diff --git a/db/migrate/20170403155202_add_departure_arrival_day_offsets_to_vjas.rb b/db/migrate/20170403155202_add_departure_arrival_day_offsets_to_vjas.rb new file mode 100644 index 000000000..ac580b990 --- /dev/null +++ b/db/migrate/20170403155202_add_departure_arrival_day_offsets_to_vjas.rb @@ -0,0 +1,6 @@ +class AddDepartureArrivalDayOffsetsToVjas < ActiveRecord::Migration + def change + add_column :vehicle_journey_at_stops, :departure_day_offset, :integer + add_column :vehicle_journey_at_stops, :arrival_day_offset, :integer + end +end diff --git a/db/migrate/20170404122930_add_route_rm_line_from_routing_constraint_zone.rb b/db/migrate/20170404122930_add_route_rm_line_from_routing_constraint_zone.rb new file mode 100644 index 000000000..f53c0b503 --- /dev/null +++ b/db/migrate/20170404122930_add_route_rm_line_from_routing_constraint_zone.rb @@ -0,0 +1,6 @@ +class AddRouteRmLineFromRoutingConstraintZone < ActiveRecord::Migration + def change + remove_column :routing_constraint_zones, :line_id, :bigint + add_column :routing_constraint_zones, :route_id, :bigint + end +end diff --git a/db/migrate/20170405122823_rm_stop_areas_add_stop_points_to_routing_constraint_zone.rb b/db/migrate/20170405122823_rm_stop_areas_add_stop_points_to_routing_constraint_zone.rb new file mode 100644 index 000000000..67bc2623c --- /dev/null +++ b/db/migrate/20170405122823_rm_stop_areas_add_stop_points_to_routing_constraint_zone.rb @@ -0,0 +1,6 @@ +class RmStopAreasAddStopPointsToRoutingConstraintZone < ActiveRecord::Migration + def change + remove_column :routing_constraint_zones, :stop_area_ids, :integer, array: true + add_column :routing_constraint_zones, :stop_point_ids, :bigint, array: true + end +end diff --git a/db/migrate/20170410134931_add_color_to_timetables.rb b/db/migrate/20170410134931_add_color_to_timetables.rb new file mode 100644 index 000000000..c297bc537 --- /dev/null +++ b/db/migrate/20170410134931_add_color_to_timetables.rb @@ -0,0 +1,5 @@ +class AddColorToTimetables < ActiveRecord::Migration + def change + add_column :time_tables, :color, :string + end +end diff --git a/db/migrate/20170414080922_set_default_for_calendars_shared.rb b/db/migrate/20170414080922_set_default_for_calendars_shared.rb new file mode 100644 index 000000000..a82a04275 --- /dev/null +++ b/db/migrate/20170414080922_set_default_for_calendars_shared.rb @@ -0,0 +1,6 @@ +class SetDefaultForCalendarsShared < ActiveRecord::Migration + def change + change_column_default :calendars, :shared, :false + Calendar.where(shared: nil).update_all(shared: false) + end +end diff --git a/db/schema.rb b/db/schema.rb index afa8d08b9..9c1379002 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,14 +11,14 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170322131100) do +ActiveRecord::Schema.define(version: 20170414080922) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" enable_extension "postgis" enable_extension "hstore" - create_table "access_links", force: true do |t| + create_table "access_links", id: :bigserial, force: :cascade do |t| t.integer "access_point_id", limit: 8 t.integer "stop_area_id", limit: 8 t.string "objectid", null: false @@ -41,9 +41,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "access_links", ["objectid"], :name => "access_links_objectid_key", :unique => true + add_index "access_links", ["objectid"], name: "access_links_objectid_key", unique: true, using: :btree - create_table "access_points", force: true do |t| + create_table "access_points", id: :bigserial, force: :cascade do |t| t.string "objectid" t.integer "object_version", limit: 8 t.string "creator_id" @@ -69,9 +69,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "access_points", ["objectid"], :name => "access_points_objectid_key", :unique => true + add_index "access_points", ["objectid"], name: "access_points_objectid_key", unique: true, using: :btree - create_table "api_keys", force: true do |t| + create_table "api_keys", id: :bigserial, force: :cascade do |t| t.integer "referential_id", limit: 8 t.string "token" t.string "name" @@ -79,21 +79,21 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - create_table "calendars", force: true do |t| + create_table "calendars", id: :bigserial, force: :cascade do |t| t.string "name" t.string "short_name" - t.daterange "date_ranges", array: true - t.date "dates", array: true - t.boolean "shared" + t.daterange "date_ranges", array: true + t.date "dates", array: true + t.boolean "shared", default: false t.integer "organisation_id", limit: 8 t.datetime "created_at" t.datetime "updated_at" end - add_index "calendars", ["organisation_id"], :name => "index_calendars_on_organisation_id" - add_index "calendars", ["short_name"], :name => "index_calendars_on_short_name", :unique => true + 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 - create_table "clean_up_results", force: true do |t| + create_table "clean_up_results", id: :bigserial, force: :cascade do |t| t.string "message_key" t.hstore "message_attributs" t.integer "clean_up_id", limit: 8 @@ -101,9 +101,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "clean_up_results", ["clean_up_id"], :name => "index_clean_up_results_on_clean_up_id" + add_index "clean_up_results", ["clean_up_id"], name: "index_clean_up_results_on_clean_up_id", using: :btree - create_table "clean_ups", force: true do |t| + create_table "clean_ups", id: :bigserial, force: :cascade do |t| t.string "status" t.datetime "started_at" t.datetime "ended_at" @@ -114,9 +114,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "end_date" end - add_index "clean_ups", ["referential_id"], :name => "index_clean_ups_on_referential_id" + add_index "clean_ups", ["referential_id"], name: "index_clean_ups_on_referential_id", using: :btree - create_table "companies", force: true do |t| + create_table "companies", id: :bigserial, force: :cascade do |t| t.string "objectid", null: false t.integer "object_version", limit: 8 t.string "creator_id" @@ -137,11 +137,11 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "companies", ["line_referential_id"], :name => "index_companies_on_line_referential_id" - add_index "companies", ["objectid"], :name => "companies_objectid_key", :unique => true - add_index "companies", ["registration_number"], :name => "companies_registration_number_key" + add_index "companies", ["line_referential_id"], name: "index_companies_on_line_referential_id", using: :btree + add_index "companies", ["objectid"], name: "companies_objectid_key", unique: true, using: :btree + add_index "companies", ["registration_number"], name: "companies_registration_number_key", using: :btree - create_table "connection_links", force: true do |t| + create_table "connection_links", id: :bigserial, force: :cascade do |t| t.integer "departure_id", limit: 8 t.integer "arrival_id", limit: 8 t.string "objectid", null: false @@ -163,9 +163,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "connection_links", ["objectid"], :name => "connection_links_objectid_key", :unique => true + add_index "connection_links", ["objectid"], name: "connection_links_objectid_key", unique: true, using: :btree - create_table "exports", force: true do |t| + create_table "exports", id: :bigserial, force: :cascade do |t| t.integer "referential_id", limit: 8 t.string "status" t.string "type" @@ -176,9 +176,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.string "reference_ids" end - add_index "exports", ["referential_id"], :name => "index_exports_on_referential_id" + add_index "exports", ["referential_id"], name: "index_exports_on_referential_id", using: :btree - create_table "facilities", force: true do |t| + create_table "facilities", id: :bigserial, force: :cascade do |t| t.integer "stop_area_id", limit: 8 t.integer "line_id", limit: 8 t.integer "connection_link_id", limit: 8 @@ -202,14 +202,14 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.string "contained_in" end - add_index "facilities", ["objectid"], :name => "facilities_objectid_key", :unique => true + add_index "facilities", ["objectid"], name: "facilities_objectid_key", unique: true, using: :btree - create_table "facilities_features", id: false, force: true do |t| + create_table "facilities_features", id: false, force: :cascade do |t| t.integer "facility_id", limit: 8 t.integer "choice_code" end - create_table "footnotes", force: true do |t| + create_table "footnotes", id: :bigserial, force: :cascade do |t| t.integer "line_id", limit: 8 t.string "code" t.string "label" @@ -217,12 +217,12 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - create_table "footnotes_vehicle_journeys", id: false, force: true do |t| + create_table "footnotes_vehicle_journeys", id: false, force: :cascade do |t| t.integer "vehicle_journey_id", limit: 8 t.integer "footnote_id", limit: 8 end - create_table "group_of_lines", force: true do |t| + create_table "group_of_lines", id: :bigserial, force: :cascade do |t| t.string "objectid", null: false t.integer "object_version", limit: 8 t.string "creator_id" @@ -235,15 +235,15 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "group_of_lines", ["line_referential_id"], :name => "index_group_of_lines_on_line_referential_id" - add_index "group_of_lines", ["objectid"], :name => "group_of_lines_objectid_key", :unique => true + add_index "group_of_lines", ["line_referential_id"], name: "index_group_of_lines_on_line_referential_id", using: :btree + add_index "group_of_lines", ["objectid"], name: "group_of_lines_objectid_key", unique: true, using: :btree - create_table "group_of_lines_lines", id: false, force: true do |t| + create_table "group_of_lines_lines", id: false, force: :cascade do |t| t.integer "group_of_line_id", limit: 8 t.integer "line_id", limit: 8 end - create_table "import_messages", force: true do |t| + create_table "import_messages", id: :bigserial, force: :cascade do |t| t.integer "criticity" t.string "message_key" t.hstore "message_attributs" @@ -254,10 +254,10 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.hstore "resource_attributes" end - add_index "import_messages", ["import_id"], :name => "index_import_messages_on_import_id" - add_index "import_messages", ["resource_id"], :name => "index_import_messages_on_resource_id" + add_index "import_messages", ["import_id"], name: "index_import_messages_on_import_id", using: :btree + add_index "import_messages", ["resource_id"], name: "index_import_messages_on_resource_id", using: :btree - create_table "import_resources", force: true do |t| + create_table "import_resources", id: :bigserial, force: :cascade do |t| t.integer "import_id", limit: 8 t.string "status" t.datetime "created_at" @@ -268,9 +268,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.hstore "metrics" end - add_index "import_resources", ["import_id"], :name => "index_import_resources_on_import_id" + add_index "import_resources", ["import_id"], name: "index_import_resources_on_import_id", using: :btree - create_table "imports", force: true do |t| + create_table "imports", id: :bigserial, force: :cascade do |t| t.string "status" t.string "current_step_id" t.float "current_step_progress" @@ -286,10 +286,10 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.string "type" end - add_index "imports", ["referential_id"], :name => "index_imports_on_referential_id" - add_index "imports", ["workbench_id"], :name => "index_imports_on_workbench_id" + add_index "imports", ["referential_id"], name: "index_imports_on_referential_id", using: :btree + add_index "imports", ["workbench_id"], name: "index_imports_on_workbench_id", using: :btree - create_table "journey_frequencies", force: true do |t| + create_table "journey_frequencies", id: :bigserial, force: :cascade do |t| t.integer "vehicle_journey_id", limit: 8 t.time "scheduled_headway_interval", null: false t.time "first_departure_time", null: false @@ -300,10 +300,10 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.integer "timeband_id", limit: 8 end - add_index "journey_frequencies", ["timeband_id"], :name => "index_journey_frequencies_on_timeband_id" - add_index "journey_frequencies", ["vehicle_journey_id"], :name => "index_journey_frequencies_on_vehicle_journey_id" + add_index "journey_frequencies", ["timeband_id"], name: "index_journey_frequencies_on_timeband_id", using: :btree + add_index "journey_frequencies", ["vehicle_journey_id"], name: "index_journey_frequencies_on_vehicle_journey_id", using: :btree - create_table "journey_pattern_sections", force: true do |t| + create_table "journey_pattern_sections", id: :bigserial, force: :cascade do |t| t.integer "journey_pattern_id", limit: 8, null: false t.integer "route_section_id", limit: 8, null: false t.integer "rank", null: false @@ -311,11 +311,11 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "journey_pattern_sections", ["journey_pattern_id", "route_section_id", "rank"], :name => "index_jps_on_journey_pattern_id_and_route_section_id_and_rank", :unique => true - add_index "journey_pattern_sections", ["journey_pattern_id"], :name => "index_journey_pattern_sections_on_journey_pattern_id" - add_index "journey_pattern_sections", ["route_section_id"], :name => "index_journey_pattern_sections_on_route_section_id" + add_index "journey_pattern_sections", ["journey_pattern_id", "route_section_id", "rank"], name: "index_jps_on_journey_pattern_id_and_route_section_id_and_rank", unique: true, using: :btree + add_index "journey_pattern_sections", ["journey_pattern_id"], name: "index_journey_pattern_sections_on_journey_pattern_id", using: :btree + add_index "journey_pattern_sections", ["route_section_id"], name: "index_journey_pattern_sections_on_route_section_id", using: :btree - create_table "journey_patterns", force: true do |t| + create_table "journey_patterns", id: :bigserial, force: :cascade do |t| t.integer "route_id", limit: 8 t.string "objectid", null: false t.integer "object_version", limit: 8 @@ -331,22 +331,22 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "journey_patterns", ["objectid"], :name => "journey_patterns_objectid_key", :unique => true + add_index "journey_patterns", ["objectid"], name: "journey_patterns_objectid_key", unique: true, using: :btree - create_table "journey_patterns_stop_points", id: false, force: true do |t| + create_table "journey_patterns_stop_points", id: false, force: :cascade do |t| t.integer "journey_pattern_id", limit: 8 t.integer "stop_point_id", limit: 8 end - add_index "journey_patterns_stop_points", ["journey_pattern_id"], :name => "index_journey_pattern_id_on_journey_patterns_stop_points" + add_index "journey_patterns_stop_points", ["journey_pattern_id"], name: "index_journey_pattern_id_on_journey_patterns_stop_points", using: :btree - create_table "line_referential_memberships", force: true do |t| + create_table "line_referential_memberships", id: :bigserial, force: :cascade do |t| t.integer "organisation_id", limit: 8 t.integer "line_referential_id", limit: 8 t.boolean "owner" end - create_table "line_referential_sync_messages", force: true do |t| + create_table "line_referential_sync_messages", id: :bigserial, force: :cascade do |t| t.integer "criticity" t.string "message_key" t.hstore "message_attributs" @@ -355,9 +355,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "line_referential_sync_messages", ["line_referential_sync_id"], :name => "line_referential_sync_id" + add_index "line_referential_sync_messages", ["line_referential_sync_id"], name: "line_referential_sync_id", using: :btree - create_table "line_referential_syncs", force: true do |t| + create_table "line_referential_syncs", id: :bigserial, force: :cascade do |t| t.integer "line_referential_id", limit: 8 t.datetime "created_at" t.datetime "updated_at" @@ -366,16 +366,16 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.string "status" end - add_index "line_referential_syncs", ["line_referential_id"], :name => "index_line_referential_syncs_on_line_referential_id" + add_index "line_referential_syncs", ["line_referential_id"], name: "index_line_referential_syncs_on_line_referential_id", using: :btree - create_table "line_referentials", force: true do |t| + create_table "line_referentials", id: :bigserial, force: :cascade do |t| t.string "name" t.datetime "created_at" t.datetime "updated_at" t.integer "sync_interval", default: 1 end - create_table "lines", force: true do |t| + create_table "lines", id: :bigserial, force: :cascade do |t| t.integer "network_id", limit: 8 t.integer "company_id", limit: 8 t.string "objectid", null: false @@ -403,12 +403,12 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "lines", ["line_referential_id"], :name => "index_lines_on_line_referential_id" - add_index "lines", ["objectid"], :name => "lines_objectid_key", :unique => true - add_index "lines", ["registration_number"], :name => "lines_registration_number_key" - add_index "lines", ["secondary_company_ids"], :name => "index_lines_on_secondary_company_ids" + add_index "lines", ["line_referential_id"], name: "index_lines_on_line_referential_id", using: :btree + add_index "lines", ["objectid"], name: "lines_objectid_key", unique: true, using: :btree + 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 "networks", force: true do |t| + create_table "networks", id: :bigserial, force: :cascade do |t| t.string "objectid", null: false t.integer "object_version", limit: 8 t.string "creator_id" @@ -426,11 +426,11 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "networks", ["line_referential_id"], :name => "index_networks_on_line_referential_id" - add_index "networks", ["objectid"], :name => "networks_objectid_key", :unique => true - add_index "networks", ["registration_number"], :name => "networks_registration_number_key" + add_index "networks", ["line_referential_id"], name: "index_networks_on_line_referential_id", using: :btree + add_index "networks", ["objectid"], name: "networks_objectid_key", unique: true, using: :btree + add_index "networks", ["registration_number"], name: "networks_registration_number_key", using: :btree - create_table "organisations", force: true do |t| + create_table "organisations", id: :bigserial, force: :cascade do |t| t.string "name" t.datetime "created_at" t.datetime "updated_at" @@ -440,9 +440,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.hstore "sso_attributes" end - add_index "organisations", ["code"], :name => "index_organisations_on_code", :unique => true + add_index "organisations", ["code"], name: "index_organisations_on_code", unique: true, using: :btree - create_table "pt_links", force: true do |t| + create_table "pt_links", id: :bigserial, force: :cascade do |t| t.integer "start_of_link_id", limit: 8 t.integer "end_of_link_id", limit: 8 t.integer "route_id", limit: 8 @@ -456,9 +456,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "pt_links", ["objectid"], :name => "pt_links_objectid_key", :unique => true + add_index "pt_links", ["objectid"], name: "pt_links_objectid_key", unique: true, using: :btree - create_table "referential_clonings", force: true do |t| + create_table "referential_clonings", id: :bigserial, force: :cascade do |t| t.string "status" t.datetime "started_at" t.datetime "ended_at" @@ -468,10 +468,10 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "referential_clonings", ["source_referential_id"], :name => "index_referential_clonings_on_source_referential_id" - add_index "referential_clonings", ["target_referential_id"], :name => "index_referential_clonings_on_target_referential_id" + add_index "referential_clonings", ["source_referential_id"], name: "index_referential_clonings_on_source_referential_id", using: :btree + add_index "referential_clonings", ["target_referential_id"], name: "index_referential_clonings_on_target_referential_id", using: :btree - create_table "referential_metadata", force: true do |t| + create_table "referential_metadata", id: :bigserial, force: :cascade do |t| t.integer "referential_id", limit: 8 t.integer "line_ids", limit: 8, array: true t.integer "referential_source_id", limit: 8 @@ -480,11 +480,11 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.daterange "periodes", array: true end - add_index "referential_metadata", ["line_ids"], :name => "index_referential_metadata_on_line_ids" - add_index "referential_metadata", ["referential_id"], :name => "index_referential_metadata_on_referential_id" - add_index "referential_metadata", ["referential_source_id"], :name => "index_referential_metadata_on_referential_source_id" + add_index "referential_metadata", ["line_ids"], name: "index_referential_metadata_on_line_ids", using: :gin + add_index "referential_metadata", ["referential_id"], name: "index_referential_metadata_on_referential_id", using: :btree + add_index "referential_metadata", ["referential_source_id"], name: "index_referential_metadata_on_referential_source_id", using: :btree - create_table "referentials", force: true do |t| + create_table "referentials", id: :bigserial, force: :cascade do |t| t.string "name" t.string "slug" t.datetime "created_at" @@ -506,23 +506,23 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.boolean "ready", default: false end - add_index "referentials", ["created_from_id"], :name => "index_referentials_on_created_from_id" + add_index "referentials", ["created_from_id"], name: "index_referentials_on_created_from_id", using: :btree - create_table "route_sections", force: true do |t| + create_table "route_sections", id: :bigserial, force: :cascade do |t| t.integer "departure_id", limit: 8 t.integer "arrival_id", limit: 8 + t.geometry "input_geometry", limit: {:srid=>4326, :type=>"line_string"} + t.geometry "processed_geometry", limit: {:srid=>4326, :type=>"line_string"} t.string "objectid", null: false t.integer "object_version", limit: 8 t.string "creator_id" t.float "distance" t.boolean "no_processing" - t.spatial "input_geometry", limit: {:srid=>4326, :type=>"line_string"} - t.spatial "processed_geometry", limit: {:srid=>4326, :type=>"line_string"} t.datetime "created_at" t.datetime "updated_at" end - create_table "routes", force: true do |t| + create_table "routes", id: :bigserial, force: :cascade do |t| t.integer "line_id", limit: 8 t.string "objectid", null: false t.integer "object_version", limit: 8 @@ -538,27 +538,25 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "routes", ["objectid"], :name => "routes_objectid_key", :unique => true + add_index "routes", ["objectid"], name: "routes_objectid_key", unique: true, using: :btree - create_table "routing_constraint_zones", force: true do |t| + create_table "routing_constraint_zones", id: :bigserial, force: :cascade do |t| t.string "name" - t.integer "stop_area_ids", array: true - t.integer "line_id", limit: 8 t.datetime "created_at" t.datetime "updated_at" t.string "objectid", null: false t.integer "object_version", limit: 8 t.string "creator_id" + t.integer "route_id", limit: 8 + t.integer "stop_point_ids", limit: 8, array: true end - add_index "routing_constraint_zones", ["line_id"], :name => "index_routing_constraint_zones_on_line_id" - - create_table "routing_constraints_lines", id: false, force: true do |t| + create_table "routing_constraints_lines", id: false, force: :cascade do |t| t.integer "stop_area_id", limit: 8 t.integer "line_id", limit: 8 end - create_table "rule_parameter_sets", force: true do |t| + create_table "rule_parameter_sets", id: :bigserial, force: :cascade do |t| t.text "parameters" t.string "name" t.datetime "created_at" @@ -566,13 +564,13 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.integer "organisation_id", limit: 8 end - create_table "stop_area_referential_memberships", force: true do |t| + create_table "stop_area_referential_memberships", id: :bigserial, force: :cascade do |t| t.integer "organisation_id", limit: 8 t.integer "stop_area_referential_id", limit: 8 t.boolean "owner" end - create_table "stop_area_referential_sync_messages", force: true do |t| + create_table "stop_area_referential_sync_messages", id: :bigserial, force: :cascade do |t| t.integer "criticity" t.string "message_key" t.hstore "message_attributs" @@ -581,9 +579,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "stop_area_referential_sync_messages", ["stop_area_referential_sync_id"], :name => "stop_area_referential_sync_id" + add_index "stop_area_referential_sync_messages", ["stop_area_referential_sync_id"], name: "stop_area_referential_sync_id", using: :btree - create_table "stop_area_referential_syncs", force: true do |t| + create_table "stop_area_referential_syncs", id: :bigserial, force: :cascade do |t| t.integer "stop_area_referential_id", limit: 8 t.datetime "created_at" t.datetime "updated_at" @@ -592,15 +590,15 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.string "status" end - add_index "stop_area_referential_syncs", ["stop_area_referential_id"], :name => "index_stop_area_referential_syncs_on_stop_area_referential_id" + add_index "stop_area_referential_syncs", ["stop_area_referential_id"], name: "index_stop_area_referential_syncs_on_stop_area_referential_id", using: :btree - create_table "stop_area_referentials", force: true do |t| + create_table "stop_area_referentials", id: :bigserial, force: :cascade do |t| t.string "name" t.datetime "created_at" t.datetime "updated_at" end - create_table "stop_areas", force: true do |t| + create_table "stop_areas", id: :bigserial, force: :cascade do |t| t.integer "parent_id", limit: 8 t.string "objectid", null: false t.integer "object_version", limit: 8 @@ -633,17 +631,17 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.string "stif_type" end - add_index "stop_areas", ["name"], :name => "index_stop_areas_on_name" - add_index "stop_areas", ["objectid"], :name => "stop_areas_objectid_key", :unique => true - add_index "stop_areas", ["parent_id"], :name => "index_stop_areas_on_parent_id" - add_index "stop_areas", ["stop_area_referential_id"], :name => "index_stop_areas_on_stop_area_referential_id" + add_index "stop_areas", ["name"], name: "index_stop_areas_on_name", using: :btree + add_index "stop_areas", ["objectid"], name: "stop_areas_objectid_key", unique: true, using: :btree + add_index "stop_areas", ["parent_id"], name: "index_stop_areas_on_parent_id", using: :btree + add_index "stop_areas", ["stop_area_referential_id"], name: "index_stop_areas_on_stop_area_referential_id", using: :btree - create_table "stop_areas_stop_areas", id: false, force: true do |t| + create_table "stop_areas_stop_areas", id: false, force: :cascade do |t| t.integer "child_id", limit: 8 t.integer "parent_id", limit: 8 end - create_table "stop_points", force: true do |t| + create_table "stop_points", id: :bigserial, force: :cascade do |t| t.integer "route_id", limit: 8 t.integer "stop_area_id", limit: 8 t.string "objectid", null: false @@ -656,9 +654,9 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "stop_points", ["objectid"], :name => "stop_points_objectid_key", :unique => true + add_index "stop_points", ["objectid"], name: "stop_points_objectid_key", unique: true, using: :btree - create_table "taggings", force: true do |t| + create_table "taggings", id: :bigserial, force: :cascade do |t| t.integer "tag_id", limit: 8 t.integer "taggable_id", limit: 8 t.string "taggable_type" @@ -668,35 +666,35 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "created_at" end - add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], :name => "taggings_idx", :unique => true - add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context" + add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true, using: :btree + add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree - create_table "tags", force: true do |t| + create_table "tags", id: :bigserial, force: :cascade do |t| t.string "name" t.integer "taggings_count", default: 0 end - add_index "tags", ["name"], :name => "index_tags_on_name", :unique => true + add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree - create_table "time_table_dates", force: true do |t| + create_table "time_table_dates", id: :bigserial, force: :cascade do |t| t.integer "time_table_id", limit: 8, null: false t.date "date" t.integer "position", null: false t.boolean "in_out" end - add_index "time_table_dates", ["time_table_id"], :name => "index_time_table_dates_on_time_table_id" + add_index "time_table_dates", ["time_table_id"], name: "index_time_table_dates_on_time_table_id", using: :btree - create_table "time_table_periods", force: true do |t| + create_table "time_table_periods", id: :bigserial, force: :cascade do |t| t.integer "time_table_id", limit: 8, null: false t.date "period_start" t.date "period_end" t.integer "position", null: false end - add_index "time_table_periods", ["time_table_id"], :name => "index_time_table_periods_on_time_table_id" + add_index "time_table_periods", ["time_table_id"], name: "index_time_table_periods_on_time_table_id", using: :btree - create_table "time_tables", force: true do |t| + create_table "time_tables", id: :bigserial, force: :cascade do |t| t.string "objectid", null: false t.integer "object_version", limit: 8, default: 1 t.string "creator_id" @@ -708,20 +706,21 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.integer "calendar_id", limit: 8 t.datetime "created_at" t.datetime "updated_at" + t.string "color" end - add_index "time_tables", ["calendar_id"], :name => "index_time_tables_on_calendar_id" - add_index "time_tables", ["objectid"], :name => "time_tables_objectid_key", :unique => true + add_index "time_tables", ["calendar_id"], name: "index_time_tables_on_calendar_id", using: :btree + add_index "time_tables", ["objectid"], name: "time_tables_objectid_key", unique: true, using: :btree - create_table "time_tables_vehicle_journeys", id: false, force: true do |t| + create_table "time_tables_vehicle_journeys", id: false, force: :cascade do |t| t.integer "time_table_id", limit: 8 t.integer "vehicle_journey_id", limit: 8 end - add_index "time_tables_vehicle_journeys", ["time_table_id"], :name => "index_time_tables_vehicle_journeys_on_time_table_id" - add_index "time_tables_vehicle_journeys", ["vehicle_journey_id"], :name => "index_time_tables_vehicle_journeys_on_vehicle_journey_id" + add_index "time_tables_vehicle_journeys", ["time_table_id"], name: "index_time_tables_vehicle_journeys_on_time_table_id", using: :btree + add_index "time_tables_vehicle_journeys", ["vehicle_journey_id"], name: "index_time_tables_vehicle_journeys_on_vehicle_journey_id", using: :btree - create_table "timebands", force: true do |t| + create_table "timebands", id: :bigserial, force: :cascade do |t| t.string "objectid", null: false t.integer "object_version", limit: 8 t.string "creator_id" @@ -732,7 +731,7 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - create_table "users", force: true do |t| + create_table "users", id: :bigserial, force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "" t.string "reset_password_token" @@ -767,12 +766,12 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.string "permissions", array: true end - add_index "users", ["email"], :name => "index_users_on_email", :unique => true - add_index "users", ["invitation_token"], :name => "index_users_on_invitation_token", :unique => true - add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true - add_index "users", ["username"], :name => "index_users_on_username", :unique => true + add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree + add_index "users", ["invitation_token"], name: "index_users_on_invitation_token", unique: true, using: :btree + add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree + add_index "users", ["username"], name: "index_users_on_username", unique: true, using: :btree - create_table "vehicle_journey_at_stops", force: true do |t| + create_table "vehicle_journey_at_stops", id: :bigserial, force: :cascade do |t| t.integer "vehicle_journey_id", limit: 8 t.integer "stop_point_id", limit: 8 t.string "connecting_service_id" @@ -781,12 +780,14 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.time "departure_time" t.string "for_boarding" t.string "for_alighting" + t.integer "departure_day_offset" + t.integer "arrival_day_offset" end - add_index "vehicle_journey_at_stops", ["stop_point_id"], :name => "index_vehicle_journey_at_stops_on_stop_pointid" - add_index "vehicle_journey_at_stops", ["vehicle_journey_id"], :name => "index_vehicle_journey_at_stops_on_vehicle_journey_id" + add_index "vehicle_journey_at_stops", ["stop_point_id"], name: "index_vehicle_journey_at_stops_on_stop_pointid", using: :btree + add_index "vehicle_journey_at_stops", ["vehicle_journey_id"], name: "index_vehicle_journey_at_stops_on_vehicle_journey_id", using: :btree - create_table "vehicle_journeys", force: true do |t| + create_table "vehicle_journeys", id: :bigserial, force: :cascade do |t| t.integer "route_id", limit: 8 t.integer "journey_pattern_id", limit: 8 t.integer "company_id", limit: 8 @@ -808,10 +809,10 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.datetime "updated_at" end - add_index "vehicle_journeys", ["objectid"], :name => "vehicle_journeys_objectid_key", :unique => true - add_index "vehicle_journeys", ["route_id"], :name => "index_vehicle_journeys_on_route_id" + add_index "vehicle_journeys", ["objectid"], name: "vehicle_journeys_objectid_key", unique: true, using: :btree + add_index "vehicle_journeys", ["route_id"], name: "index_vehicle_journeys_on_route_id", using: :btree - create_table "workbenches", force: true do |t| + create_table "workbenches", id: :bigserial, force: :cascade do |t| t.string "name" t.integer "organisation_id", limit: 8 t.datetime "created_at" @@ -820,44 +821,33 @@ ActiveRecord::Schema.define(version: 20170322131100) do t.integer "stop_area_referential_id", limit: 8 end - add_index "workbenches", ["line_referential_id"], :name => "index_workbenches_on_line_referential_id" - add_index "workbenches", ["organisation_id"], :name => "index_workbenches_on_organisation_id" - add_index "workbenches", ["stop_area_referential_id"], :name => "index_workbenches_on_stop_area_referential_id" - - Foreigner.load - add_foreign_key "group_of_lines_lines", "group_of_lines", name: "groupofline_group_fkey", dependent: :delete - - add_foreign_key "journey_frequencies", "timebands", name: "journey_frequencies_timeband_id_fk", dependent: :nullify - add_foreign_key "journey_frequencies", "vehicle_journeys", name: "journey_frequencies_vehicle_journey_id_fk", dependent: :nullify - - add_foreign_key "journey_pattern_sections", "journey_patterns", name: "journey_pattern_sections_journey_pattern_id_fk", dependent: :delete - add_foreign_key "journey_pattern_sections", "route_sections", name: "journey_pattern_sections_route_section_id_fk", dependent: :delete - - add_foreign_key "journey_patterns", "routes", name: "jp_route_fkey", dependent: :delete - add_foreign_key "journey_patterns", "stop_points", name: "arrival_point_fkey", column: "arrival_stop_point_id", dependent: :nullify - add_foreign_key "journey_patterns", "stop_points", name: "departure_point_fkey", column: "departure_stop_point_id", dependent: :nullify - - add_foreign_key "journey_patterns_stop_points", "journey_patterns", name: "jpsp_jp_fkey", dependent: :delete - add_foreign_key "journey_patterns_stop_points", "stop_points", name: "jpsp_stoppoint_fkey", dependent: :delete - - add_foreign_key "routes", "routes", name: "route_opposite_route_fkey", column: "opposite_route_id", dependent: :nullify - - add_foreign_key "stop_areas", "stop_areas", name: "area_parent_fkey", column: "parent_id", dependent: :nullify - - add_foreign_key "stop_areas_stop_areas", "stop_areas", name: "stoparea_child_fkey", column: "child_id", dependent: :delete - add_foreign_key "stop_areas_stop_areas", "stop_areas", name: "stoparea_parent_fkey", column: "parent_id", dependent: :delete - - add_foreign_key "time_table_dates", "time_tables", name: "tm_date_fkey", dependent: :delete - - add_foreign_key "time_table_periods", "time_tables", name: "tm_period_fkey", dependent: :delete - - add_foreign_key "time_tables_vehicle_journeys", "time_tables", name: "vjtm_tm_fkey", dependent: :delete - add_foreign_key "time_tables_vehicle_journeys", "vehicle_journeys", name: "vjtm_vj_fkey", dependent: :delete - - add_foreign_key "vehicle_journey_at_stops", "stop_points", name: "vjas_sp_fkey", dependent: :delete - add_foreign_key "vehicle_journey_at_stops", "vehicle_journeys", name: "vjas_vj_fkey", dependent: :delete - - add_foreign_key "vehicle_journeys", "journey_patterns", name: "vj_jp_fkey", dependent: :delete - add_foreign_key "vehicle_journeys", "routes", name: "vj_route_fkey", dependent: :delete - + 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_foreign_key "access_links", "access_points", name: "aclk_acpt_fkey" + add_foreign_key "group_of_lines_lines", "group_of_lines", name: "groupofline_group_fkey", on_delete: :cascade + add_foreign_key "journey_frequencies", "timebands", on_delete: :nullify + add_foreign_key "journey_frequencies", "vehicle_journeys", on_delete: :nullify + add_foreign_key "journey_pattern_sections", "journey_patterns", on_delete: :cascade + add_foreign_key "journey_pattern_sections", "route_sections", on_delete: :cascade + add_foreign_key "journey_patterns", "routes", name: "jp_route_fkey", on_delete: :cascade + add_foreign_key "journey_patterns", "stop_points", column: "arrival_stop_point_id", name: "arrival_point_fkey", on_delete: :nullify + add_foreign_key "journey_patterns", "stop_points", column: "departure_stop_point_id", name: "departure_point_fkey", on_delete: :nullify + add_foreign_key "journey_patterns_stop_points", "journey_patterns", name: "jpsp_jp_fkey", on_delete: :cascade + add_foreign_key "journey_patterns_stop_points", "stop_points", name: "jpsp_stoppoint_fkey", on_delete: :cascade + add_foreign_key "route_sections", "stop_areas", column: "arrival_id" + add_foreign_key "route_sections", "stop_areas", column: "departure_id" + add_foreign_key "routes", "routes", column: "opposite_route_id", name: "route_opposite_route_fkey" + add_foreign_key "stop_areas", "stop_areas", column: "parent_id", name: "area_parent_fkey", on_delete: :nullify + add_foreign_key "stop_areas_stop_areas", "stop_areas", column: "child_id", name: "stoparea_child_fkey", on_delete: :cascade + add_foreign_key "stop_areas_stop_areas", "stop_areas", column: "parent_id", name: "stoparea_parent_fkey", on_delete: :cascade + add_foreign_key "time_table_dates", "time_tables", name: "tm_date_fkey", on_delete: :cascade + add_foreign_key "time_table_periods", "time_tables", name: "tm_period_fkey", on_delete: :cascade + add_foreign_key "time_tables_vehicle_journeys", "time_tables", name: "vjtm_tm_fkey", on_delete: :cascade + add_foreign_key "time_tables_vehicle_journeys", "vehicle_journeys", name: "vjtm_vj_fkey", on_delete: :cascade + add_foreign_key "vehicle_journey_at_stops", "stop_points", name: "vjas_sp_fkey", on_delete: :cascade + add_foreign_key "vehicle_journey_at_stops", "vehicle_journeys", name: "vjas_vj_fkey", on_delete: :cascade + add_foreign_key "vehicle_journeys", "journey_patterns", name: "vj_jp_fkey", on_delete: :cascade + add_foreign_key "vehicle_journeys", "routes", name: "vj_route_fkey", on_delete: :cascade end diff --git a/db/seeds.rb b/db/seeds.rb index 7526330ed..e3fa4c69d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -7,25 +7,9 @@ # cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) # Mayor.create(:name => 'Emanuel', :city => cities.first) - -stop_area_referential = StopAreaReferential.find_or_create_by(name: "Reflex") -line_referential = LineReferential.find_or_create_by(name: "CodifLigne") - stif = Organisation.find_or_create_by!(name: "STIF") do |org| org.code = 'STIF' end -operator = Organisation.find_or_create_by!(code: 'transporteur-a') do |organisation| - organisation.name = "Transporteur A" -end - -line_referential.add_member stif, owner: true -line_referential.add_member operator - -stop_area_referential.add_member stif, owner: true -stop_area_referential.add_member operator - -line_referential.save -stop_area_referential.save stif.users.find_or_create_by!(username: "admin") do |user| user.email = 'stif-boiv@af83.com' @@ -33,18 +17,33 @@ stif.users.find_or_create_by!(username: "admin") do |user| user.name = "STIF Administrateur" end + +operator = Organisation.find_or_create_by!(code: 'transporteur-a') do |organisation| + organisation.name = "Transporteur A" +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 +stop_area_referential = StopAreaReferential.find_or_create_by!(name: "Reflex") do |referential| + referential.add_member stif, owner: true + referential.add_member operator +end + 10.times do |n| - stop_area_referential.stop_areas.find_or_create_by name: "Test #{n}", area_type: "Quay", objectid: "StopArea: #{n}" + stop_area_referential.stop_areas.find_or_create_by! name: "Test #{n}", area_type: "zdep", objectid: "StopArea: #{n}" +end + +line_referential = LineReferential.find_or_create_by!(name: "CodifLigne") do |referential| + referential.add_member stif, owner: true + referential.add_member operator end -LineReferentialSync.find_or_create_by(line_referential: line_referential) -StopAreaReferentialSync.find_or_create_by(stop_area_referential: stop_area_referential) +LineReferentialSync.find_or_create_by!(line_referential: line_referential) +StopAreaReferentialSync.find_or_create_by!(stop_area_referential: stop_area_referential) 10.times do |n| line_referential.lines.find_or_create_by name: "Test #{n}" do |l| @@ -53,6 +52,8 @@ StopAreaReferentialSync.find_or_create_by(stop_area_referential: stop_area_refer end workbench = Workbench.find_by(name: "Gestion de l'offre") +workbench.update_attributes(line_referential: line_referential, + stop_area_referential: stop_area_referential) [["parissudest201604", "Paris Sud-Est Avril 2016"], ["parissudest201605", "Paris Sud-Est Mai 2016"]].each do |slug, name| @@ -62,3 +63,6 @@ workbench = Workbench.find_by(name: "Gestion de l'offre") referential.workbench = workbench end end + +# Clone last referential +# Referential.new_from(Referential.last) diff --git a/lib/af83/stored_procedures.rb b/lib/af83/stored_procedures.rb new file mode 100644 index 000000000..698f3861d --- /dev/null +++ b/lib/af83/stored_procedures.rb @@ -0,0 +1,44 @@ +module StoredProcedures extend self + + def invoke_stored_procedure(name, *params) + name = name.to_s + raise ArgumentError, "no such stored procedure #{name.inspect}" unless stored_procedures[name] + invocation = "#{name}(#{quote_params(params)})" + ActiveRecord::Base.connection.execute "SELECT #{invocation}" + end + + def create_stored_procedure(name) + name = name.to_s + sql_file = File.expand_path("../../sql/#{name}.sql", __FILE__) + raise ArgumentError, "missing sql file #{sql_file.inspect}" unless File.readable? sql_file + + # We could store the file's content for reload without application restart if desired. + stored_procedures[name] = true + + ActiveRecord::Base.connection.execute File.read(sql_file) + end + + private + def quote_params(params) + params + .map(&method(:quote_param)) + .join(", ") + end + + def quote_param(param) + case param + when String + "'#{param}'" + when TrueClass + "TRUE" + when FalseClass + "FALSE" + else + param + end + end + + def stored_procedures + @__stored_procedures__ ||= {} + end +end diff --git a/lib/sql/clone_schema.sql b/lib/sql/clone_schema.sql new file mode 100644 index 000000000..9fb88466b --- /dev/null +++ b/lib/sql/clone_schema.sql @@ -0,0 +1,114 @@ +CREATE OR REPLACE FUNCTION clone_schema( source_schema text, dest_schema text, include_recs boolean) RETURNS void AS +$BODY$ + DECLARE + src_oid oid; + tbl_oid oid; + func_oid oid; + object text; + buffer text; + srctbl text; + default_ text; + column_ text; + qry text; + dest_qry text; + v_def text; + seqval bigint; + sq_last_value bigint; + sq_max_value bigint; + sq_start_value bigint; + sq_increment_by bigint; + sq_min_value bigint; + sq_cache_value bigint; + sq_log_cnt bigint; + sq_is_called boolean; + sq_is_cycled boolean; + sq_cycled char(10); + BEGIN + -- Assure that source_schema exists + SELECT oid INTO src_oid FROM pg_namespace WHERE nspname = quote_ident(source_schema); + IF NOT FOUND THEN + RAISE NOTICE 'source schema % does not exist!', source_schema; + RETURN; + END IF; + + -- Refute that dest_schema exists and then create it + PERFORM nspname FROM pg_namespace WHERE nspname = quote_ident(dest_schema); + IF FOUND THEN + RAISE NOTICE 'dest schema % already exists!', dest_schema; + RETURN; + END IF; + EXECUTE 'CREATE SCHEMA ' || quote_ident(dest_schema) ; + + -- loop over sequences, creating the same one in the destination namespace, ... + FOR object IN + SELECT sequence_name::text FROM information_schema.sequences WHERE sequence_schema = quote_ident(source_schema) + LOOP + EXECUTE 'CREATE SEQUENCE ' || quote_ident(dest_schema) || '.' || quote_ident(object); + + -- ...storing the attributes of the sequence from the source namespace in local variables, ... + srctbl := quote_ident(source_schema) || '.' || quote_ident(object); + EXECUTE 'SELECT last_value, max_value, start_value, increment_by, min_value, cache_value, log_cnt, is_cycled, is_called FROM ' || srctbl || ';' INTO sq_last_value, sq_max_value, sq_start_value, sq_increment_by, sq_min_value, sq_cache_value, sq_log_cnt, sq_is_cycled, sq_is_called; + IF sq_is_cycled THEN + sq_cycled := 'CYCLE'; + ELSE + sq_cycled := 'NO CYCLE'; + END IF; + EXECUTE 'ALTER SEQUENCE ' || (dest_schema) || '.' || quote_ident(object) || ' INCREMENT BY ' || sq_increment_by || ' MINVALUE ' || sq_min_value || ' MAXVALUE ' || sq_max_value || ' START WITH ' || sq_start_value || ' RESTART ' || sq_min_value || ' CACHE ' || sq_cache_value || sq_cycled || ' ;' ; + + buffer := quote_ident(dest_schema) || '.' || quote_ident(object); + IF include_recs THEN + EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_last_value || ', ' || sq_is_called || ');' ; + ELSE + EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_start_value || ', ' || sq_is_called || ');' ; + END IF; + END LOOP; + + -- loop over tables in source schema,... + FOR object IN + SELECT TABLE_NAME::text FROM information_schema.tables WHERE table_schema = quote_ident(source_schema) AND table_type = 'BASE TABLE' + LOOP + -- ...creating the table in the destination schema, potentially including the records + buffer := dest_schema || '.' || quote_ident(object); + EXECUTE 'CREATE TABLE ' || buffer || '(LIKE ' || quote_ident(source_schema) || '.' || quote_ident(object) || ' INCLUDING ALL)'; + IF include_recs THEN + EXECUTE 'INSERT INTO ' || buffer || ' SELECT * FROM ' || quote_ident(source_schema) || '.' || quote_ident(object) || ';'; + END IF; + + -- alter table, assuring the destination schema's table has: + -- * the same defaults + FOR column_, default_ + IN SELECT column_name::text, REPLACE(column_default::text, source_schema, dest_schema) + FROM information_schema.COLUMNS + WHERE table_schema = dest_schema AND TABLE_NAME = object AND column_default LIKE 'nextval(%' || quote_ident(source_schema) || '%::regclass)' + LOOP + EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_; + END LOOP; + END LOOP; + + /* SELECT 'ALTER TABLE ' || quote_ident(dest_schema) || '.' || quote_ident(rn.relname) || ' ADD CONSTRAINT ' || quote_ident(ct.conname) || ' ' || pg_get_constraintdef(ct.oid) || ';' FROM pg_constraint ct JOIN pg_class rn ON rn.oid = ct.conrelid WHERE connamespace = src_oid AND rn.relkind = 'r' AND ct.contype = 'f' LIMIT 2; */ + -- apply all constraints on tables in destination schema + FOR qry IN + SELECT 'ALTER TABLE ' || quote_ident(dest_schema) || '.' || quote_ident(rn.relname) || ' ADD CONSTRAINT ' || quote_ident(ct.conname) || ' ' || REPLACE(pg_get_constraintdef(ct.oid), source_schema || '.', dest_schema || '.') || ';' + FROM pg_constraint ct JOIN pg_class rn ON rn.oid = ct.conrelid WHERE connamespace = src_oid AND rn.relkind = 'r' AND ct.contype = 'f' + LOOP + EXECUTE qry; + END LOOP; + + -- create views from source schema in destination schema + FOR object IN + SELECT table_name::text, view_definition FROM information_schema.views WHERE table_schema = quote_ident(source_schema) + LOOP + buffer := dest_schema || '.' || quote_ident(object); + SELECT view_definition INTO v_def FROM information_schema.views WHERE table_schema = quote_ident(source_schema) AND table_name = quote_ident(object); + EXECUTE 'CREATE OR REPLACE VIEW ' || buffer || ' AS ' || v_def || ';' ; + END LOOP; + + FOR func_oid IN SELECT oid FROM pg_proc WHERE pronamespace = src_oid + LOOP + SELECT pg_get_functiondef(func_oid) INTO qry; + SELECT replace(qry, source_schema, dest_schema) INTO dest_qry; + EXECUTE dest_qry; + END LOOP; + RETURN; + END; +$BODY$ LANGUAGE plpgsql VOLATILE COST 100; diff --git a/lib/stif/reflex_synchronization.rb b/lib/stif/reflex_synchronization.rb index fee54f4c1..a7dda7e30 100644 --- a/lib/stif/reflex_synchronization.rb +++ b/lib/stif/reflex_synchronization.rb @@ -153,6 +153,7 @@ module Stif :city_name => 'Town', :stif_type => 'OBJECT_STATUS' }.each do |k, v| stop[k] = entry[v] end + # TODO: use stop.update_attributes instead of the above if entry['gml:pos'] stop['longitude'] = entry['gml:pos'][:lng] diff --git a/lib/tasks/ci.rake b/lib/tasks/ci.rake index 52bab7aa4..85d1cbdf9 100644 --- a/lib/tasks/ci.rake +++ b/lib/tasks/ci.rake @@ -29,7 +29,7 @@ namespace :ci do desc "Deploy after CI" task :deploy do - sh "cap #{deploy_env} deploy:migrations deploy:seed" + sh "cap #{deploy_env} deploy:migrations" end desc "Clean test files" diff --git a/package.json b/package.json index 4e975de5c..9a46403f3 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,10 @@ "react-redux": "4.4.5", "react-select2": "4.0.2", "redux": "3.6.0", - "whatwg-fetch": "2.0.3" + "whatwg-fetch": "2.0.3", + "redux-logger": "2.7.4", + "redux-thunk": "2.1.0", + "redux-promise": "0.5.3" }, "license": "MIT", "engines": { @@ -23,9 +26,6 @@ "devDependencies": { "es6-object-assign": "1.0.3", "react-addons-test-utils": "15.3.2", - "sinon": "1.17.7", - "redux-logger": "2.7.4", - "redux-thunk": "2.1.0", - "redux-promise": "0.5.3" + "sinon": "1.17.7" } } diff --git a/public/uploads/import/file/1/terminated_job.json b/public/uploads/import/file/1/terminated_job.json new file mode 100644 index 000000000..417bd62ad --- /dev/null +++ b/public/uploads/import/file/1/terminated_job.json @@ -0,0 +1,578 @@ +< HTTP/1.1 200 OK +< Connection: keep-alive +< Cache-Control: no-transform, max-age=2147483647 +< X-Powered-By: Undertow/1 +* Server WildFly/8 is not blacklisted +< Server: WildFly/8 +< Transfer-Encoding: chunked +< Content-Type: application/json +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/data/9151/Citura_050115_220215.zip>; rel="data" +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/data/9151/action_parameters.json>; rel="action_params" +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/data/9151/validation_parameters.json>; rel="validation_params" +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/reports/9151>; rel="location" +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/reports/9151>; rel="delete" +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/data/9151/validation.json>; rel="validation" +< Date: Fri, 13 Mar 2015 09:18:07 GMT +< +{ + "id": 9151, + "referential": "tatrotest", + "action": "importer", + "type": "neptune", + "created": 1425984896098, + "updated": 1425984896542, + "status": "TERMINATED", + "action_report": { + "result": "OK", + "zip_file": { + "status": "OK", + "name": "Citura_050115_220215.zip" + }, + "files": [ + { + "name": "C_NEPTUNE_reseau_5_39901717.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901712.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901718.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901710.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901709.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901727.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901746.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901719.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901715.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901716.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901721.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901734.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901725.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901731.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901711.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901722.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901724.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901733.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901726.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901732.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901736.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901708.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901730.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901720.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901745.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901713.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901723.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901729.xml", + "status": "OK", + "error": [] + } + ], + "lines": [ + { + "name": "03 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 95, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "17", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 66, + "access_point_count": 0, + "vehicle_journey_count": 45, + "journey_pattern_count": 2 + } + }, + { + "name": "TRAMWAY", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 10, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 67, + "access_point_count": 0, + "vehicle_journey_count": 769, + "journey_pattern_count": 10 + } + }, + { + "name": "02", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 3, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 68, + "access_point_count": 0, + "vehicle_journey_count": 388, + "journey_pattern_count": 3 + } + }, + { + "name": "01", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 6, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 84, + "access_point_count": 0, + "vehicle_journey_count": 385, + "journey_pattern_count": 6 + } + }, + { + "name": "10", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 6, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 79, + "access_point_count": 0, + "vehicle_journey_count": 253, + "journey_pattern_count": 6 + } + }, + { + "name": "15", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 31, + "access_point_count": 0, + "vehicle_journey_count": 8, + "journey_pattern_count": 2 + } + }, + { + "name": "13 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 22, + "access_point_count": 0, + "vehicle_journey_count": 17, + "journey_pattern_count": 2 + } + }, + { + "name": "05", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 14, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 109, + "access_point_count": 0, + "vehicle_journey_count": 378, + "journey_pattern_count": 14 + } + }, + { + "name": "02 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 68, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "08", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 9, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 104, + "access_point_count": 0, + "vehicle_journey_count": 236, + "journey_pattern_count": 9 + } + }, + { + "name": "05 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 94, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "12", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 6, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 100, + "access_point_count": 0, + "vehicle_journey_count": 236, + "journey_pattern_count": 6 + } + }, + { + "name": "13", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 4, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 101, + "access_point_count": 0, + "vehicle_journey_count": 81, + "journey_pattern_count": 4 + } + }, + { + "name": "03", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 5, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 97, + "access_point_count": 0, + "vehicle_journey_count": 387, + "journey_pattern_count": 5 + } + }, + { + "name": "07", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 4, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 105, + "access_point_count": 0, + "vehicle_journey_count": 238, + "journey_pattern_count": 4 + } + }, + { + "name": "11", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 96, + "access_point_count": 0, + "vehicle_journey_count": 251, + "journey_pattern_count": 2 + } + }, + { + "name": "09 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 29, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "CITADINE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 61, + "access_point_count": 0, + "vehicle_journey_count": 77, + "journey_pattern_count": 2 + } + }, + { + "name": "14", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 2, + "stop_area_count": 65, + "access_point_count": 0, + "vehicle_journey_count": 130, + "journey_pattern_count": 2 + } + }, + { + "name": "01 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 4, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 84, + "access_point_count": 0, + "vehicle_journey_count": 11, + "journey_pattern_count": 4 + } + }, + { + "name": "04 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 102, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "07 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 50, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "09", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 4, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 105, + "access_point_count": 0, + "vehicle_journey_count": 268, + "journey_pattern_count": 4 + } + }, + { + "name": "18", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 3, + "connection_link_count": 0, + "time_table_count": 4, + "stop_area_count": 27, + "access_point_count": 0, + "vehicle_journey_count": 8, + "journey_pattern_count": 3 + } + }, + { + "name": "04", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 8, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 112, + "access_point_count": 0, + "vehicle_journey_count": 381, + "journey_pattern_count": 8 + } + }, + { + "name": "06", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 5, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 67, + "access_point_count": 0, + "vehicle_journey_count": 279, + "journey_pattern_count": 5 + } + }, + { + "name": "16", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 4, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 63, + "access_point_count": 0, + "vehicle_journey_count": 42, + "journey_pattern_count": 4 + } + } + ], + "stats": { + "line_count": 28, + "route_count": 119, + "connection_link_count": 0, + "time_table_count": 60, + "stop_area_count": 2151, + "access_point_count": 0, + "vehicle_journey_count": 4928, + "journey_pattern_count": 119 + } + } +} diff --git a/public/uploads/import/file/2/terminated_job.json b/public/uploads/import/file/2/terminated_job.json new file mode 100644 index 000000000..417bd62ad --- /dev/null +++ b/public/uploads/import/file/2/terminated_job.json @@ -0,0 +1,578 @@ +< HTTP/1.1 200 OK +< Connection: keep-alive +< Cache-Control: no-transform, max-age=2147483647 +< X-Powered-By: Undertow/1 +* Server WildFly/8 is not blacklisted +< Server: WildFly/8 +< Transfer-Encoding: chunked +< Content-Type: application/json +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/data/9151/Citura_050115_220215.zip>; rel="data" +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/data/9151/action_parameters.json>; rel="action_params" +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/data/9151/validation_parameters.json>; rel="validation_params" +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/reports/9151>; rel="location" +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/reports/9151>; rel="delete" +< Link: <http://localhost:8080/mobi.chouette.api/referentials/tatrotest/data/9151/validation.json>; rel="validation" +< Date: Fri, 13 Mar 2015 09:18:07 GMT +< +{ + "id": 9151, + "referential": "tatrotest", + "action": "importer", + "type": "neptune", + "created": 1425984896098, + "updated": 1425984896542, + "status": "TERMINATED", + "action_report": { + "result": "OK", + "zip_file": { + "status": "OK", + "name": "Citura_050115_220215.zip" + }, + "files": [ + { + "name": "C_NEPTUNE_reseau_5_39901717.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901712.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901718.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901710.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901709.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901727.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901746.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901719.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901715.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901716.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901721.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901734.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901725.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901731.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901711.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901722.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901724.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901733.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901726.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901732.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901736.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901708.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901730.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901720.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901745.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901713.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901723.xml", + "status": "OK", + "error": [] + }, + { + "name": "C_NEPTUNE_reseau_5_39901729.xml", + "status": "OK", + "error": [] + } + ], + "lines": [ + { + "name": "03 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 95, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "17", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 66, + "access_point_count": 0, + "vehicle_journey_count": 45, + "journey_pattern_count": 2 + } + }, + { + "name": "TRAMWAY", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 10, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 67, + "access_point_count": 0, + "vehicle_journey_count": 769, + "journey_pattern_count": 10 + } + }, + { + "name": "02", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 3, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 68, + "access_point_count": 0, + "vehicle_journey_count": 388, + "journey_pattern_count": 3 + } + }, + { + "name": "01", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 6, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 84, + "access_point_count": 0, + "vehicle_journey_count": 385, + "journey_pattern_count": 6 + } + }, + { + "name": "10", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 6, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 79, + "access_point_count": 0, + "vehicle_journey_count": 253, + "journey_pattern_count": 6 + } + }, + { + "name": "15", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 31, + "access_point_count": 0, + "vehicle_journey_count": 8, + "journey_pattern_count": 2 + } + }, + { + "name": "13 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 22, + "access_point_count": 0, + "vehicle_journey_count": 17, + "journey_pattern_count": 2 + } + }, + { + "name": "05", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 14, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 109, + "access_point_count": 0, + "vehicle_journey_count": 378, + "journey_pattern_count": 14 + } + }, + { + "name": "02 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 68, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "08", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 9, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 104, + "access_point_count": 0, + "vehicle_journey_count": 236, + "journey_pattern_count": 9 + } + }, + { + "name": "05 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 94, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "12", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 6, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 100, + "access_point_count": 0, + "vehicle_journey_count": 236, + "journey_pattern_count": 6 + } + }, + { + "name": "13", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 4, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 101, + "access_point_count": 0, + "vehicle_journey_count": 81, + "journey_pattern_count": 4 + } + }, + { + "name": "03", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 5, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 97, + "access_point_count": 0, + "vehicle_journey_count": 387, + "journey_pattern_count": 5 + } + }, + { + "name": "07", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 4, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 105, + "access_point_count": 0, + "vehicle_journey_count": 238, + "journey_pattern_count": 4 + } + }, + { + "name": "11", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 96, + "access_point_count": 0, + "vehicle_journey_count": 251, + "journey_pattern_count": 2 + } + }, + { + "name": "09 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 29, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "CITADINE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 61, + "access_point_count": 0, + "vehicle_journey_count": 77, + "journey_pattern_count": 2 + } + }, + { + "name": "14", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 2, + "stop_area_count": 65, + "access_point_count": 0, + "vehicle_journey_count": 130, + "journey_pattern_count": 2 + } + }, + { + "name": "01 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 4, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 84, + "access_point_count": 0, + "vehicle_journey_count": 11, + "journey_pattern_count": 4 + } + }, + { + "name": "04 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 102, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "07 SOIREE", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 2, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 50, + "access_point_count": 0, + "vehicle_journey_count": 10, + "journey_pattern_count": 2 + } + }, + { + "name": "09", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 4, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 105, + "access_point_count": 0, + "vehicle_journey_count": 268, + "journey_pattern_count": 4 + } + }, + { + "name": "18", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 3, + "connection_link_count": 0, + "time_table_count": 4, + "stop_area_count": 27, + "access_point_count": 0, + "vehicle_journey_count": 8, + "journey_pattern_count": 3 + } + }, + { + "name": "04", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 8, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 112, + "access_point_count": 0, + "vehicle_journey_count": 381, + "journey_pattern_count": 8 + } + }, + { + "name": "06", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 5, + "connection_link_count": 0, + "time_table_count": 3, + "stop_area_count": 67, + "access_point_count": 0, + "vehicle_journey_count": 279, + "journey_pattern_count": 5 + } + }, + { + "name": "16", + "status": "OK", + "stats": { + "line_count": 1, + "route_count": 4, + "connection_link_count": 0, + "time_table_count": 1, + "stop_area_count": 63, + "access_point_count": 0, + "vehicle_journey_count": 42, + "journey_pattern_count": 4 + } + } + ], + "stats": { + "line_count": 28, + "route_count": 119, + "connection_link_count": 0, + "time_table_count": 60, + "stop_area_count": 2151, + "access_point_count": 0, + "vehicle_journey_count": 4928, + "journey_pattern_count": 119 + } + } +} diff --git a/spec/controllers/route_stop_points_controller_spec.rb b/spec/controllers/route_stop_points_controller_spec.rb new file mode 100644 index 000000000..2f5fa41c7 --- /dev/null +++ b/spec/controllers/route_stop_points_controller_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +RSpec.describe RouteStopPointsController, type: :controller do + login_user + + let(:referential) { Referential.first } + let!(:line) { create :line } + let!(:route) { create :route, line: line } + + describe 'GET index' do + before(:each) { get :index, referential_id: referential.id, line_id: line.id, route_id: route.id, format: :json } + + it 'returns HTTP success' do + expect(response).to be_success + end + + it 'returns a JSON of stop areas' do + expect(response.body).to eq(route.stop_points.map { |sp| { id: sp.id, name: sp.name } }.to_json) + end + end +end + + diff --git a/spec/controllers/routes_controller_spec.rb b/spec/controllers/routes_controller_spec.rb index de6d16c8b..18067dec7 100644 --- a/spec/controllers/routes_controller_spec.rb +++ b/spec/controllers/routes_controller_spec.rb @@ -9,7 +9,7 @@ describe RoutesController, :type => :controller do shared_examples_for "redirected to referential_line_path(referential,line)" do it "should redirect_to referential_line_path(referential,line)" do - #response.should redirect_to( referential_line_path(referential,route.line) ) + # expect(response).to redirect_to( referential_line_path(referential,route.line) ) end end shared_examples_for "line and referential linked" do diff --git a/spec/controllers/vehicle_journey_imports_controller_spec.rb b/spec/controllers/vehicle_journey_imports_controller_spec.rb index ef1ec882a..633f90b70 100644 --- a/spec/controllers/vehicle_journey_imports_controller_spec.rb +++ b/spec/controllers/vehicle_journey_imports_controller_spec.rb @@ -2,6 +2,4 @@ require 'spec_helper' describe ImportTasksController, :type => :controller do login_user - - end diff --git a/spec/factories/chouette_routing_constraint_zones.rb b/spec/factories/chouette_routing_constraint_zones.rb index 9a2529483..8ef2ddb43 100644 --- a/spec/factories/chouette_routing_constraint_zones.rb +++ b/spec/factories/chouette_routing_constraint_zones.rb @@ -1,7 +1,10 @@ FactoryGirl.define do factory :routing_constraint_zone, class: Chouette::RoutingConstraintZone do sequence(:name) { |n| "Routing constraint zone #{n}" } - stop_area_ids { [create(:stop_area).id, create(:stop_area).id] } - association :line, factory: :line + association :route, factory: :route + after(:build) do |zone| + route = Chouette::Route.find(zone.route_id) + zone.stop_point_ids = route.stop_points.pluck(:id).first(2) + end end end diff --git a/spec/features/lines_spec.rb b/spec/features/lines_spec.rb index bbe3c757b..e7e1e601c 100644 --- a/spec/features/lines_spec.rb +++ b/spec/features/lines_spec.rb @@ -20,10 +20,10 @@ describe "Lines", :type => :feature do end it 'allows only R in CRUD' do - expect(page).to have_content(I18n.t('actions.show')) - expect(page).not_to have_content(I18n.t('actions.edit')) - expect(page).not_to have_content(I18n.t('actions.destroy')) - expect(page).not_to have_content(I18n.t('actions.add')) + expect(page).to have_link(I18n.t('actions.show')) + expect(page).not_to have_link(I18n.t('actions.edit'), href: edit_referential_line_path(referential, lines.first)) + expect(page).not_to have_link(I18n.t('actions.destroy'), href: referential_line_path(referential, lines.first)) + expect(page).not_to have_link(I18n.t('actions.add'), href: new_referential_line_path(referential)) end context 'filtering' do diff --git a/spec/features/networks_spec.rb b/spec/features/networks_spec.rb index 523b2e898..75070e7fa 100644 --- a/spec/features/networks_spec.rb +++ b/spec/features/networks_spec.rb @@ -81,7 +81,7 @@ describe "Networks", :type => :feature do # click_link "Supprimer ce réseau" # page.evaluate_script('window.confirm = function() { return true; }') # click_button "Valider" - # page.should have_no_content(subject.name) + # expect(page).to have_no_content(subject.name) # end # end diff --git a/spec/features/referentials_spec.rb b/spec/features/referentials_spec.rb index ebaf70bca..3c2258a3a 100644 --- a/spec/features/referentials_spec.rb +++ b/spec/features/referentials_spec.rb @@ -55,6 +55,59 @@ describe "Referentials", :type => :feature do expect(page).to have_link(I18n.t('actions.edit'), href: edit_referential_path(referential)) end end + + context 'user has the permission to create referentials' do + it 'shows the clone link for referetnial' do + expect(page).to have_link(I18n.t('actions.clone'), href: new_referential_path(from: referential.id)) + end + end + + context 'user does not have the permission to create referentials' do + it 'does not show the clone link for referetnial' do + @user.update_attribute(:permissions, []) + visit referential_path(referential) + expect(page).not_to have_link(I18n.t('actions.clone'), href: new_referential_path(from: referential.id)) + end + end + + context 'user has the permission to edit referentials' do + it 'shows the link to edit the referential' do + expect(page).to have_link(I18n.t('actions.edit'), href: edit_referential_path(referential)) + end + + it 'shows the link to archive the referential' do + expect(page).to have_link(I18n.t('actions.archive'), href: archive_referential_path(referential)) + end + end + + context 'user does not have the permission to edit referentials' do + before(:each) do + @user.update_attribute(:permissions, []) + visit referential_path(referential) + end + + it 'does not show the link to edit the referential' do + expect(page).not_to have_link(I18n.t('actions.edit'), href: edit_referential_path(referential)) + end + + it 'does not show the link to archive the referential' do + expect(page).not_to have_link(I18n.t('actions.archive'), href: archive_referential_path(referential)) + end + end + + context 'user has the permission to destroy referentials' do + it 'shows the link to destroy the referential' do + expect(page).to have_link(I18n.t('actions.destroy'), href: referential_path(referential)) + end + end + + context 'user does not have the permission to destroy referentials' do + it 'does not show the destroy link for referetnial' do + @user.update_attribute(:permissions, []) + visit referential_path(referential) + expect(page).not_to have_link(I18n.t('actions.destroy'), href: referential_path(referential)) + end + end end describe "create" do diff --git a/spec/features/routes_spec.rb b/spec/features/routes_spec.rb index 36d0e8f87..4b90a6ec6 100644 --- a/spec/features/routes_spec.rb +++ b/spec/features/routes_spec.rb @@ -102,7 +102,7 @@ describe "Routes", :type => :feature do it 'does not show edit buttons for routes' do @user.update_attribute(:permissions, []) visit referential_line_path(referential, line) - expect(page).not_to have_content(I18n.t('actions.edit')) + expect(page).not_to have_link(I18n.t('actions.edit'), href: edit_referential_line_route_path(referential, line, route)) end end @@ -136,7 +136,7 @@ describe "Routes", :type => :feature do it 'does not show destroy buttons for routes' do @user.update_attribute(:permissions, []) visit referential_line_path(referential, line) - expect(page).not_to have_content(I18n.t('actions.destroy')) + expect(page).not_to have_link(I18n.t('actions.destroy'), href: referential_line_route_path(referential, line, route)) end end end diff --git a/spec/features/routing_constraint_zones_spec.rb b/spec/features/routing_constraint_zones_spec.rb index d1c39e211..9e8c7dad4 100644 --- a/spec/features/routing_constraint_zones_spec.rb +++ b/spec/features/routing_constraint_zones_spec.rb @@ -6,7 +6,8 @@ describe 'RoutingConstraintZones', type: :feature do let(:referential) { Referential.first } let!(:line) { create :line } - let!(:routing_constraint_zones) { Array.new(2) { create :routing_constraint_zone, line: line } } + let!(:route) { create :route, line: line } + let!(:routing_constraint_zones) { Array.new(2) { create :routing_constraint_zone, route: route } } let(:routing_constraint_zone) { routing_constraint_zones.first } describe 'index' do diff --git a/spec/features/time_tables_spec.rb b/spec/features/time_tables_spec.rb index 8e0b62c89..06ae9bac3 100644 --- a/spec/features/time_tables_spec.rb +++ b/spec/features/time_tables_spec.rb @@ -18,7 +18,7 @@ describe "TimeTables", :type => :feature do context 'user has permission to create time tables' do it 'shows a create link for time tables' do - expect(page).to have_content(I18n.t('time_tables.actions.new')) + expect(page).to have_content(I18n.t('actions.add')) end end @@ -26,13 +26,13 @@ describe "TimeTables", :type => :feature do it 'does not show a create link for time tables' do @user.update_attribute(:permissions, []) visit referential_time_tables_path(referential) - expect(page).not_to have_content(I18n.t('time_tables.actions.new')) + expect(page).not_to have_content(I18n.t('actions.add')) end end context 'user has permission to edit time tables' do it 'shows an edit button for time tables' do - expect(page).to have_css('span.fa.fa-pencil') + expect(page).to have_content(I18n.t('actions.edit')) end end @@ -40,13 +40,13 @@ describe "TimeTables", :type => :feature do it 'does not show a edit link for time tables' do @user.update_attribute(:permissions, []) visit referential_time_tables_path(referential) - expect(page).not_to have_css('span.fa.fa-pencil') + expect(page).not_to have_content(I18n.t('actions.add')) end end context 'user has permission to destroy time tables' do it 'shows a destroy button for time tables' do - expect(page).to have_css('span.fa.fa-trash-o') + expect(page).to have_content(I18n.t('actions.delete')) end end @@ -54,7 +54,7 @@ describe "TimeTables", :type => :feature do it 'does not show a destroy button for time tables' do @user.update_attribute(:permissions, []) visit referential_time_tables_path(referential) - expect(page).not_to have_css('span.fa.fa-trash-o') + expect(page).not_to have_content(I18n.t('actions.delete')) end end @@ -67,33 +67,33 @@ describe "TimeTables", :type => :feature do expect(page).to have_content(time_tables.first.comment) end - context 'user has permission to create time tables' do - it 'shows a create link for time tables' do - expect(page).to have_content(I18n.t('time_tables.actions.new')) - end - - it 'does not show link to duplicate the time table' do - expect(page).to have_content(I18n.t('time_tables.actions.duplicate')) - end - end + # context 'user has permission to create time tables' do + # it 'shows a create link for time tables' do + # expect(page).to have_content(I18n.t('time_tables.actions.new')) + # end + # + # it 'does not show link to duplicate the time table' do + # expect(page).to have_content(I18n.t('time_tables.actions.duplicate')) + # end + # end context 'user does not have permission to create time tables' do it 'does not show a create link for time tables' do @user.update_attribute(:permissions, []) visit referential_time_table_path(referential, time_table) - expect(page).not_to have_content(I18n.t('time_tables.actions.new')) + expect(page).not_to have_content(I18n.t('actions.add')) end it 'does not show link to duplicate the time table' do @user.update_attribute(:permissions, []) visit referential_time_table_path(referential, time_table) - expect(page).not_to have_content(I18n.t('time_tables.actions.duplicate')) + expect(page).not_to have_content(I18n.t('actions.duplicate')) end end context 'user has permission to edit time tables' do it 'shows the edit link for time table' do - expect(page).to have_content(I18n.t('time_tables.actions.edit')) + expect(page).to have_content(I18n.t('actions.edit')) end end @@ -101,13 +101,13 @@ describe "TimeTables", :type => :feature do it 'does not show the edit link for time table' do @user.update_attribute(:permissions, []) visit referential_time_table_path(referential, time_table) - expect(page).not_to have_content(I18n.t('time_tables.actions.edit')) + expect(page).not_to have_content(I18n.t('actions.edit')) end end context 'user has permission to destroy time tables' do it 'shows the destroy link for time table' do - expect(page).to have_content(I18n.t('time_tables.actions.destroy')) + expect(page).to have_content(I18n.t('actions.destroy')) end end @@ -115,30 +115,11 @@ describe "TimeTables", :type => :feature do it 'does not show a destroy link for time table' do @user.update_attribute(:permissions, []) visit referential_time_table_path(referential, time_table) - expect(page).not_to have_content(I18n.t('time_tables.actions.destroy')) + expect(page).not_to have_content(I18n.t('actions.destroy')) end end end - describe "new" do - it "creates time_table and return to show" do - visit referential_time_tables_path(referential) - click_link "Ajouter un calendrier" - fill_in "Nom", :with => "TimeTable 1" - fill_in "Identifiant Neptune", :with => "test:Timetable:1" - click_button("Créer calendrier") - expect(page).to have_content("TimeTable 1") - end - end - - describe "edit and return to show" do - it "edit time_table" do - visit referential_time_table_path(referential, subject) - click_link "Editer ce calendrier" - fill_in "Nom", :with => "TimeTable Modified" - click_button("Editer calendrier") - expect(page).to have_content("TimeTable Modified") - end - end + # No more test for the form, as it is now managed by React/Redux. end diff --git a/spec/features/workbenches_spec.rb b/spec/features/workbenches_spec.rb index 608746e56..0a71a0b6b 100644 --- a/spec/features/workbenches_spec.rb +++ b/spec/features/workbenches_spec.rb @@ -18,11 +18,26 @@ describe 'Workbenches', type: :feature do let!(:ready_referential) { create :referential, workbench: workbench, metadatas: referential_metadatas, ready: true, organisation: @user.organisation } let!(:unready_referential) { create :referential, workbench: workbench } + before(:each) { visit workbench_path(workbench) } + it 'shows ready referentials belonging to that workbench by default' do - visit workbench_path(workbench) expect(page).to have_content(ready_referential.name) expect(page).not_to have_content(unready_referential.name) end + + context 'user has the permission to create referentials' do + it 'shows the link for a new referetnial' do + expect(page).to have_link(I18n.t('referentials.actions.new'), href: new_referential_path(workbench_id: workbenches.first)) + end + end + + context 'user does not have the permission to create referentials' do + it 'does not show the clone link for referetnial' do + @user.update_attribute(:permissions, []) + visit referential_path(referential) + expect(page).not_to have_link(I18n.t('referentials.actions.new'), href: new_referential_path(workbench_id: workbenches.first)) + end + end end describe 'create new Referential' do diff --git a/spec/fixtures/users.json b/spec/fixtures/users.json index f4236a29e..6f50e402c 100644 --- a/spec/fixtures/users.json +++ b/spec/fixtures/users.json @@ -58,7 +58,8 @@ "locked_at": null, "profile": "Administrateur", "organization_name": "STIF", - "organization_code": "STIF" + "organization_code": "STIF", + "permissions": [] }, { "id": 5, "username": "laure.dubuc", @@ -71,7 +72,8 @@ "locked_at": null, "profile": "Administrateur", "organization_name": "STIF", - "organization_code": "STIF" + "organization_code": "STIF", + "permissions": [] }, { "id": 6, "username": "thomas.haddad", @@ -84,7 +86,8 @@ "locked_at": null, "profile": "Administrateur", "organization_name": "STIF", - "organization_code": "STIF" + "organization_code": "STIF", + "permissions": [] }, { "id": 7, "username": "jean-paul.lescouzeres", @@ -97,7 +100,8 @@ "locked_at": null, "profile": "Administrateur", "organization_name": "STIF", - "organization_code": "STIF" + "organization_code": "STIF", + "permissions": [] }, { "id": 8, "username": "xinhui.xu", @@ -110,7 +114,8 @@ "locked_at": null, "profile": "Administrateur", "organization_name": "STIF", - "organization_code": "STIF" + "organization_code": "STIF", + "permissions": [] }, { "id": 9, "username": "edouard.maffert", @@ -123,7 +128,8 @@ "locked_at": null, "profile": "Administrateur", "organization_name": "STIF", - "organization_code": "STIF" + "organization_code": "STIF", + "permissions": [] }, { "id": 9, "username": "vlatka.pavisic", @@ -152,7 +158,8 @@ "locked_at": null, "profile": "Référent IV Transporteur", "organization_name": "RATP", - "organization_code": "RATP" + "organization_code": "RATP", + "permissions": [] }, { "id": 11, "username": "jane.doe", @@ -165,5 +172,6 @@ "locked_at": "2016-08-05T12:34:03.995Z", "profile": "Référent IV Transporteur", "organization_name": "RATP", - "organization_code": "RATP" + "organization_code": "RATP", + "permissions": [] }] diff --git a/spec/helpers/exports_helper_spec.rb b/spec/helpers/exports_helper_spec.rb index fec8252d5..3d6b8e70e 100644 --- a/spec/helpers/exports_helper_spec.rb +++ b/spec/helpers/exports_helper_spec.rb @@ -6,7 +6,7 @@ require 'spec_helper' # describe ExportsHelper do # describe "string concat" do # it "concats two strings with spaces" do -# helper.concat_strings("this","that").should == "this that" +# expect(helper.concat_strings("this","that")).to == "this that" # end # end # end diff --git a/spec/helpers/help_helper_spec.rb b/spec/helpers/help_helper_spec.rb index 3df091c10..0b0de512b 100644 --- a/spec/helpers/help_helper_spec.rb +++ b/spec/helpers/help_helper_spec.rb @@ -6,7 +6,7 @@ require 'spec_helper' # describe HelpHelper do # describe "string concat" do # it "concats two strings with spaces" do -# helper.concat_strings("this","that").should == "this that" +# expect(helper.concat_strings("this","that")).to == "this that" # end # end # end diff --git a/spec/helpers/imports_helper_spec.rb b/spec/helpers/imports_helper_spec.rb index ec3bb05c5..12cddeb25 100644 --- a/spec/helpers/imports_helper_spec.rb +++ b/spec/helpers/imports_helper_spec.rb @@ -6,7 +6,7 @@ require 'spec_helper' # describe ImportsHelper do # describe "string concat" do # it "concats two strings with spaces" do -# helper.concat_strings("this","that").should == "this that" +# expect(helper.concat_strings("this","that")).to == "this that" # end # end # end diff --git a/spec/helpers/referentials_helper_spec.rb b/spec/helpers/referentials_helper_spec.rb index 6efc13822..6b659dc8b 100644 --- a/spec/helpers/referentials_helper_spec.rb +++ b/spec/helpers/referentials_helper_spec.rb @@ -6,7 +6,7 @@ require 'spec_helper' # describe ReferentialsHelper do # describe "string concat" do # it "concats two strings with spaces" do -# helper.concat_strings("this","that").should == "this that" +# expect(helper.concat_strings("this","that")).to == "this that" # end # end # end diff --git a/spec/javascripts/time_table/actions_spec.js b/spec/javascripts/time_table/actions_spec.js new file mode 100644 index 000000000..c628a0f57 --- /dev/null +++ b/spec/javascripts/time_table/actions_spec.js @@ -0,0 +1,27 @@ +var actions = require('es6_browserified/time_tables/actions') + +describe('actions', () => { + it('should create an action to update dayTypes', () => { + const expectedAction = { + type: 'UPDATE_DAY_TYPES', + index: 1 + } + expect(actions.updateDayTypes(1)).toEqual(expectedAction) + }) + + it('should create an action to update comment', () => { + const expectedAction = { + type: 'UPDATE_COMMENT', + comment: 'test' + } + expect(actions.updateComment('test')).toEqual(expectedAction) + }) + + it('should create an action to update color', () => { + const expectedAction = { + type: 'UPDATE_COLOR', + color: '#ffffff' + } + expect(actions.updateColor('#ffffff')).toEqual(expectedAction) + }) +}) diff --git a/spec/javascripts/time_table/reducers/metas_spec.js b/spec/javascripts/time_table/reducers/metas_spec.js new file mode 100644 index 000000000..e3729dc2a --- /dev/null +++ b/spec/javascripts/time_table/reducers/metas_spec.js @@ -0,0 +1,49 @@ +var metasReducer = require('es6_browserified/time_tables/reducers/metas') + +let state = {} + +describe('status reducer', () => { + beforeEach(() => { + state = { + comment: 'test', + day_types: [true, true, true, true, true, true, true], + tags: ['t1'], + color: 'blue' + } + }) + + it('should return the initial state', () => { + expect( + metasReducer(undefined, {}) + ).toEqual({}) + }) + + it('should handle UPDATE_DAY_TYPES', () => { + const arr = [false, true, true, true, true, true, true] + expect( + metasReducer(state, { + type: 'UPDATE_DAY_TYPES', + index: 0 + }) + ).toEqual(Object.assign({}, state, {day_types: arr})) + }) + + it('should handle UPDATE_COMMENT', () => { + expect( + metasReducer(state, { + type: 'UPDATE_COMMENT', + comment: 'title' + }) + ).toEqual(Object.assign({}, state, {comment: 'title'})) + }) + + it('should handle UPDATE_COLOR', () => { + expect( + metasReducer(state, { + type: 'UPDATE_COLOR', + color: '#ffffff' + }) + ).toEqual(Object.assign({}, state, {color: '#ffffff'})) + }) + +}) diff --git a/spec/javascripts/vehicle_journeys/reducers/filters_spec.js b/spec/javascripts/vehicle_journeys/reducers/filters_spec.js index 84608243b..d5cdff430 100644 --- a/spec/javascripts/vehicle_journeys/reducers/filters_spec.js +++ b/spec/javascripts/vehicle_journeys/reducers/filters_spec.js @@ -29,7 +29,7 @@ describe('filters reducer', () => { }, journeyPattern: {}, timetable: {}, - withoutSchedule: false, + withoutSchedule: true, }, queryString: '' } @@ -61,7 +61,7 @@ describe('filters reducer', () => { it('should handle TOGGLE_WITHOUT_SCHEDULE', () => { let rslt = JSON.parse(JSON.stringify(state.query)) - rslt.withoutSchedule = true + rslt.withoutSchedule = false expect( statusReducer(state, { type: 'TOGGLE_WITHOUT_SCHEDULE' @@ -143,8 +143,8 @@ describe('filters reducer', () => { ).toEqual(Object.assign({}, state, {query: newQuery})) }) - it('should handle SELECT_JP_FILTER', () => { - let strResult = "q%5Bjourney_pattern_id_eq%5D=undefined&q%5Btime_tables_id_eq%5D=undefined&q%5Bvehicle_journey_at_stops_departure_time_gteq%5D=11%3A11&q%5Bvehicle_journey_at_stops_departure_time_lteq%5D=22%3A22" + it('should handle CREATE_QUERY_STRING', () => { + let strResult = "q%5Bjourney_pattern_id_eq%5D=undefined&q%5Btime_tables_id_eq%5D=undefined&q%5Bvehicle_journey_at_stops_departure_time_gteq%5D=11%3A11&q%5Bvehicle_journey_at_stops_departure_time_lteq%5D=22%3A22&q%5Bvehicle_journey_without_departure_time%5D=true" expect( statusReducer(state, { type: 'CREATE_QUERY_STRING', diff --git a/spec/lib/af83/stored_procedure_spec.rb b/spec/lib/af83/stored_procedure_spec.rb new file mode 100644 index 000000000..2530d7fc1 --- /dev/null +++ b/spec/lib/af83/stored_procedure_spec.rb @@ -0,0 +1,20 @@ +require 'rails_helper' + +RSpec.describe StoredProcedures do + + + before do + described_class.create_stored_procedure(:clone_schema) + end + + let( :source_schema_name ){ "parissudest201604" } + let( :dest_schema_name ){ "#{source_schema_name}_v1"} + + context "Error cases" do + it "raises an error if stored procedure does not exist" do + expect{ described_class.invoke_stored_procedure(:idonotexist) } + .to raise_error(ArgumentError, %r{no such stored procedure "idonotexist"}) + end + end + +end diff --git a/spec/lib/af83/stored_procedures/clone_schema_spec.rb b/spec/lib/af83/stored_procedures/clone_schema_spec.rb new file mode 100755 index 000000000..4de3379ea --- /dev/null +++ b/spec/lib/af83/stored_procedures/clone_schema_spec.rb @@ -0,0 +1,166 @@ +require 'spec_helper' + +include Support::PGCatalog + +RSpec.describe StoredProcedures do + let( :source_schema ){ "source_schema" } + let( :target_schema ){ "target_schema" } + let( :child_table ){ "children" } + let( :parent_table ){ "parents" } + + before do + create_schema_with_tables + StoredProcedures.create_stored_procedure :clone_schema + end + + context "meta specs describe source schema's introspection" do + it "table information is correctly read" do + expect(get_table_information(source_schema, child_table)) + .to eq([{"table_schema"=>"source_schema", + "table_name"=>"children", + "table_type"=>"BASE TABLE", + "self_referencing_column_name"=>nil, + "reference_generation"=>nil, + "user_defined_type_catalog"=>nil, + "user_defined_type_schema"=>nil, + "user_defined_type_name"=>nil, + "is_insertable_into"=>"YES", + "is_typed"=>"NO", + "commit_action"=>nil}]) + + expect( get_table_information(target_schema, child_table) ).to be_empty + end + + it "sequences are correctly read", :meta do + expect(get_sequences(source_schema, child_table)) + .to eq([{"sequence_name"=>"#{child_table}_id_seq", + "last_value"=>"1", + "start_value"=>"1", + "increment_by"=>"1", + "max_value"=>"9223372036854775807", + "min_value"=>"1", + "cache_value"=>"1", + "log_cnt"=>"0", + "is_cycled"=>"f", + "is_called"=>"f"}]) + + expect(get_sequences(source_schema, parent_table)) + .to eq([{"sequence_name"=>"#{parent_table}_id_seq", + "last_value"=>"1", + "start_value"=>"1", + "increment_by"=>"1", + "max_value"=>"9223372036854775807", + "min_value"=>"1", + "cache_value"=>"1", + "log_cnt"=>"0", + "is_cycled"=>"f", + "is_called"=>"f"}]) + end + + it "shows foreign key constraints are correctly read" do + expect( get_foreign_keys(source_schema, child_table) ) + .to eq([{ + "constraint_name" => "children_parents", + "constraint_def" => "FOREIGN KEY (parents_id) REFERENCES source_schema.parents(id)"}]) + end + end + + context "before cloning" do + it "target schema does not exist" do + expect( get_schema_oid(target_schema) ).to be_nil + end + end + + context "after cloning" do + before do + described_class.invoke_stored_procedure(:clone_schema, source_schema, target_schema, false) + end + + it "target schema does exist" do + expect( get_schema_oid(target_schema) ).not_to be_nil + end + + it "table information is correctly read" do + expect(get_table_information(source_schema, child_table)) + .to eq([{"table_schema"=>"source_schema", + "table_name"=>"children", + "table_type"=>"BASE TABLE", + "self_referencing_column_name"=>nil, + "reference_generation"=>nil, + "user_defined_type_catalog"=>nil, + "user_defined_type_schema"=>nil, + "user_defined_type_name"=>nil, + "is_insertable_into"=>"YES", + "is_typed"=>"NO", + "commit_action"=>nil}]) + + expect( get_table_information(target_schema, child_table)) + .to eq([{"table_schema"=>"target_schema", + "table_name"=>"children", + "table_type"=>"BASE TABLE", + "self_referencing_column_name"=>nil, + "reference_generation"=>nil, + "user_defined_type_catalog"=>nil, + "user_defined_type_schema"=>nil, + "user_defined_type_name"=>nil, + "is_insertable_into"=>"YES", + "is_typed"=>"NO", + "commit_action"=>nil}]) + end + + it "has the correct sequences" do + expect(get_sequences(target_schema, child_table)) + .to eq([{"sequence_name"=>"#{child_table}_id_seq", + "last_value"=>"1", + "start_value"=>"1", + "increment_by"=>"1", + "max_value"=>"9223372036854775807", + "min_value"=>"1", + "cache_value"=>"1", + "log_cnt"=>"0", + "is_cycled"=>"f", + "is_called"=>"f"}]) + + expect(get_sequences(target_schema, parent_table)) + .to eq([{"sequence_name"=>"#{parent_table}_id_seq", + "last_value"=>"1", + "start_value"=>"1", + "increment_by"=>"1", + "max_value"=>"9223372036854775807", + "min_value"=>"1", + "cache_value"=>"1", + "log_cnt"=>"0", + "is_cycled"=>"f", + "is_called"=>"f"}]) + end + + it "has the correct foreign keys" do + expect( get_foreign_keys(target_schema, child_table) ) + .to eq([{ + "constraint_name" => "children_parents", + "constraint_def" => "FOREIGN KEY (parents_id) REFERENCES target_schema.parents(id)"}]) + end + + end + +end + +def create_schema_with_tables + execute("CREATE SCHEMA IF NOT EXISTS #{source_schema}") + execute <<-EOSQL + DROP SCHEMA IF EXISTS #{source_schema} CASCADE; + CREATE SCHEMA #{source_schema}; + + CREATE TABLE #{source_schema}.#{parent_table} ( + id bigserial PRIMARY KEY + ); + CREATE TABLE #{source_schema}.#{child_table} ( + id bigserial PRIMARY KEY, + #{parent_table}_id bigint + ); + ALTER TABLE #{source_schema}.#{child_table} + ADD CONSTRAINT #{child_table}_#{parent_table} + FOREIGN KEY( #{parent_table}_id ) REFERENCES #{source_schema}.#{parent_table}(id); + EOSQL +end + diff --git a/spec/models/chouette/routing_constraint_zone_spec.rb b/spec/models/chouette/routing_constraint_zone_spec.rb index d991538ba..87ee9e9ac 100644 --- a/spec/models/chouette/routing_constraint_zone_spec.rb +++ b/spec/models/chouette/routing_constraint_zone_spec.rb @@ -3,11 +3,48 @@ require 'spec_helper' describe Chouette::RoutingConstraintZone, type: :model do subject { create(:routing_constraint_zone) } + let!(:routing_constraint_zone) { create(:routing_constraint_zone) } it { is_expected.to validate_presence_of :name } - it { is_expected.to validate_presence_of :stop_area_ids } - it { is_expected.to validate_presence_of :line_id } # shoulda matcher to validate length of array ? - xit { is_expected.to validate_length_of(:stop_area_ids).is_at_least(2) } + xit { is_expected.to validate_length_of(:stop_point_ids).is_at_least(2) } + + describe 'validations' do + it 'validates the presence of route_id' do + expect { + routing_constraint_zone.update!(route_id: nil) + }.to raise_error(NoMethodError) + end + + it 'validates the presence of stop_point_ids' do + expect { + routing_constraint_zone.update!(stop_point_ids: []) + }.to raise_error(ActiveRecord::RecordInvalid) + end + + it 'validates that stop points belong to the route' do + route = create(:route) + expect { + routing_constraint_zone.update!(route_id: route.id) + }.to raise_error(ActiveRecord::RecordInvalid) + end + + it 'validates that not all stop points from the route are selected' do + routing_constraint_zone.stop_points = routing_constraint_zone.route.stop_points + expect { + routing_constraint_zone.save! + }.to raise_error(ActiveRecord::RecordInvalid) + end + end + + describe 'deleted stop areas' do + it 'does not have them in stop_area_ids' do + stop_point = routing_constraint_zone.route.stop_points.last + routing_constraint_zone.stop_points << stop_point + routing_constraint_zone.save! + routing_constraint_zone.route.stop_points.last.destroy! + expect(routing_constraint_zone.stop_points.map(&:id)).not_to include(stop_point.id) + end + end end diff --git a/spec/models/chouette/vehicle_journey_spec.rb b/spec/models/chouette/vehicle_journey_spec.rb index fab9cd5e8..b394dd504 100644 --- a/spec/models/chouette/vehicle_journey_spec.rb +++ b/spec/models/chouette/vehicle_journey_spec.rb @@ -1,23 +1,30 @@ require 'spec_helper' describe Chouette::VehicleJourney, :type => :model do describe "state_update" do + + def vehicle_journey_at_stop_to_state vjas + at_stop = {'stop_area_object_id' => vjas.stop_point.stop_area.objectid } + [:id, :connecting_service_id, :boarding_alighting_possibility].map do |att| + 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'), + } + end + at_stop + end + def vehicle_journey_to_state vj vj.attributes.slice('objectid', 'published_journey_name', 'journey_pattern_id', 'company_id').tap do |item| item['vehicle_journey_at_stops'] = [] + item['time_tables'] = [] + item['footnotes'] = [] - vj.vehicle_journey_at_stops.each do |vs| - at_stops = {'stop_area_object_id' => vs.stop_point.stop_area.objectid } - [:id, :connecting_service_id, :boarding_alighting_possibility].map do |att| - at_stops[att.to_s] = vs.send(att) unless vs.send(att).nil? - end - - [:arrival_time, :departure_time].map do |att| - at_stops[att.to_s] = { - 'hour' => vs.send(att).strftime('%H'), - 'minute' => vs.send(att).strftime('%M'), - } - end - item['vehicle_journey_at_stops'] << at_stops + vj.vehicle_journey_at_stops.each do |vjas| + item['vehicle_journey_at_stops'] << vehicle_journey_at_stop_to_state(vjas) end end end @@ -40,7 +47,36 @@ describe Chouette::VehicleJourney, :type => :model do expect(vj.published_journey_name).to eq 'dummy' end - it 'should update vj journey_pattern' do + it 'should save vehicle_journey_at_stops of newly created vj' do + new_vj = build(:vehicle_journey, objectid: nil, published_journey_name: 'dummy', route: route, journey_pattern: journey_pattern) + new_vj.vehicle_journey_at_stops << build(:vehicle_journey_at_stop, + :vehicle_journey => new_vj, + :stop_point => create(:stop_point), + :arrival_time => '2000-01-01 01:00:00 UTC', + :departure_time => '2000-01-01 03:00:00 UTC') + + collection << vehicle_journey_to_state(new_vj) + expect { + Chouette::VehicleJourney.state_update(route, collection) + }.to change {Chouette::VehicleJourneyAtStop.count}.by(1) + end + + it 'should not save vehicle_journey_at_stops of newly created vj if all departure time is set to 00:00' do + new_vj = build(:vehicle_journey, objectid: nil, published_journey_name: 'dummy', route: route, journey_pattern: journey_pattern) + 2.times do + new_vj.vehicle_journey_at_stops << build(:vehicle_journey_at_stop, + :vehicle_journey => new_vj, + :stop_point => create(:stop_point), + :arrival_time => '2000-01-01 00:00:00 UTC', + :departure_time => '2000-01-01 00:00:00 UTC') + end + collection << vehicle_journey_to_state(new_vj) + expect { + Chouette::VehicleJourney.state_update(route, collection) + }.not_to change {Chouette::VehicleJourneyAtStop.count} + end + + it 'should update vj journey_pattern association' do state['journey_pattern'] = create(:journey_pattern).attributes.slice('id', 'name', 'objectid') Chouette::VehicleJourney.state_update(route, collection) @@ -48,6 +84,36 @@ describe Chouette::VehicleJourney, :type => :model do expect(vehicle_journey.reload.journey_pattern_id).to eq state['journey_pattern']['id'] end + it 'should update vj time_tables association from state' do + 2.times{state['time_tables'] << create(:time_table).attributes.slice('id', 'comment', 'objectid')} + vehicle_journey.update_has_and_belongs_to_many_from_state(state) + + expect(vehicle_journey.reload.time_tables.map(&:id)).to eq(state['time_tables'].map{|tt| tt['id']}) + end + + it 'should clear vj time_tableas association when remove from state' do + vehicle_journey.time_tables << create(:time_table) + state['time_tables'] = [] + vehicle_journey.update_has_and_belongs_to_many_from_state(state) + + expect(vehicle_journey.reload.time_tables).to be_empty + end + + it 'should update vj footnote association from state' do + 2.times{state['footnotes'] << create(:footnote, line: route.line).attributes.slice('id', 'code', 'label', 'line_id')} + vehicle_journey.update_has_and_belongs_to_many_from_state(state) + + expect(vehicle_journey.reload.footnotes.map(&:id)).to eq(state['footnotes'].map{|tt| tt['id']}) + end + + it 'should clear vj footnote association from state' do + vehicle_journey.footnotes << create(:footnote) + state['footnotes'] = [] + vehicle_journey.update_has_and_belongs_to_many_from_state(state) + + expect(vehicle_journey.reload.footnotes).to be_empty + end + it 'should update vj company' do state['company'] = create(:company).attributes.slice('id', 'name', 'objectid') Chouette::VehicleJourney.state_update(route, collection) @@ -124,14 +190,22 @@ describe Chouette::VehicleJourney, :type => :model do describe '.vehicle_journey_at_stops_matrix' do it 'should fill missing VehicleJourneyAtStop with dummy' do - vehicle_journey.vehicle_journey_at_stops.last.destroy - expect(vehicle_journey.reload.vehicle_journey_at_stops.map(&:id).count).to eq(route.stop_points.map(&:id).count - 1) + vehicle_journey.journey_pattern.stop_points.delete_all + vehicle_journey.vehicle_journey_at_stops.delete_all + expect(vehicle_journey.reload.vehicle_journey_at_stops).to be_empty at_stops = vehicle_journey.reload.vehicle_journey_at_stops_matrix - expect(at_stops.last.id).to be_nil + at_stops.map{|stop| expect(stop.stop_point_id).to be_nil } expect(at_stops.count).to eq route.stop_points.count end + it 'should fill VehicleJourneyAtStop with new vjas when vj has been save without departure time' do + vehicle_journey.vehicle_journey_at_stops.destroy_all + + at_stops = vehicle_journey.reload.vehicle_journey_at_stops_matrix + expect(at_stops.map(&:stop_point_id)).to eq vehicle_journey.journey_pattern.stop_points.map(&:id) + end + it 'should keep index order of VehicleJourneyAtStop' do vehicle_journey.vehicle_journey_at_stops[3].destroy at_stops = vehicle_journey.reload.vehicle_journey_at_stops_matrix diff --git a/spec/models/compliance_check_task_spec.rb b/spec/models/compliance_check_task_spec.rb index 2e5379de7..a062fdb58 100644 --- a/spec/models/compliance_check_task_spec.rb +++ b/spec/models/compliance_check_task_spec.rb @@ -1,5 +1,8 @@ # require 'spec_helper' +# TODO: Can we get rid of this??? +# ************************* + # describe ComplianceCheckTask, :type => :model do # subject { Factory( :compliance_check_task ) } @@ -274,19 +277,19 @@ # # # # it "should create a ComplianceCheckResult :started when started" do # # subject.validate -# # subject.compliance_check_results.first.should be_log_message(:key => "started") + # expect(subject.compliance_check_results.first).to be_log_message(:key => "started") # # end # # # # it "should create a ComplianceCheckResult :completed when completed" do # # subject.validate -# # subject.compliance_check_results.last.should be_log_message(:key => "completed") + # expect(subject.compliance_check_results.last).to be_log_message(:key => "completed") # # end # # # # it "should create a ComplianceCheckResult :failed when failed" do # # pending # # # subject.loader.stub(:export).and_raise("export failed") # # subject.validate -# # subject.compliance_check_results.last.should be_log_message(:key => "failed") + # expect(subject.compliance_check_results.last).to be_log_message(:key => "failed") # # end # # # # end diff --git a/spec/models/import_spec.rb b/spec/models/import_spec.rb index e34f368ae..a2855d086 100644 --- a/spec/models/import_spec.rb +++ b/spec/models/import_spec.rb @@ -4,7 +4,7 @@ RSpec.describe Import, :type => :model do it { should belong_to(:referential) } it { should belong_to(:workbench) } - it { should enumerize(:status).in(:new, :pending, :successful, :failed, :canceled) } + it { should enumerize(:status).in(:new, :pending, :successful, :failed, :canceled, :running, :aborted ) } it { should validate_presence_of(:file) } end diff --git a/spec/models/ninoxe_extension_spec.rb b/spec/models/ninoxe_extension_spec.rb index b8892f053..016e10496 100644 --- a/spec/models/ninoxe_extension_spec.rb +++ b/spec/models/ninoxe_extension_spec.rb @@ -8,23 +8,23 @@ describe Chouette::StopArea do # FIXME #821 # it "should return referential projection " do # subject.referential.projection_type='27572' - # subject.projection.should == subject.referential.projection_type + # expect(subject.projection).to eq(subject.referential.projection_type) # end # it "should return projection coordinates when referential has projection" do # subject.latitude = 45 # subject.longitude = 0 # subject.referential.projection_type='27572' - # subject.projection_x.should_not be_nil - # subject.projection_y.should_not be_nil + # expect(subject.projection_x).not_to be_nil + # expect(subject.projection_y).not_to be_nil # end # it "should return nil projection coordinates when referential has no projection" do # subject.latitude = 45 # subject.longitude = 0 # subject.referential.projection_type=nil - # subject.projection_x.should be_nil - # subject.projection_y.should be_nil + # expect(subject.projection_x).to be_nil + # expect(subject.projection_y).to be_nil # end end @@ -34,25 +34,25 @@ describe Chouette::AccessPoint do subject {create(:access_point)} - it "should return referential projection " do + it "should return referential projection" do subject.referential.projection_type='27572' - subject.projection.should == subject.referential.projection_type + expect(subject.projection).to eq(subject.referential.projection_type) end it "should return projection coordinates when referential has projection" do subject.latitude = 45 subject.longitude = 0 subject.referential.projection_type='27572' - subject.projection_x.should_not be_nil - subject.projection_y.should_not be_nil + expect(subject.projection_x).not_to be_nil + expect(subject.projection_y).not_to be_nil end it "should return nil projection coordinates when referential has no projection" do subject.latitude = 45 subject.longitude = 0 subject.referential.projection_type=nil - subject.projection_x.should be_nil - subject.projection_y.should be_nil + expect(subject.projection_x).to be_nil + expect(subject.projection_y).to be_nil end end diff --git a/spec/models/organisation_spec.rb b/spec/models/organisation_spec.rb index 9b4235755..527f71015 100644 --- a/spec/models/organisation_spec.rb +++ b/spec/models/organisation_spec.rb @@ -10,7 +10,7 @@ describe Organisation, :type => :model do it "create a rule_parameter_set" do organisation = create(:organisation) - organisation.rule_parameter_sets.size.should == 1 + expect(organisation.rule_parameter_sets.size).to eq(1) end describe "Portail sync" do diff --git a/spec/models/referential_metadata_spec.rb b/spec/models/referential_metadata_spec.rb index ede589860..0f628c8d1 100644 --- a/spec/models/referential_metadata_spec.rb +++ b/spec/models/referential_metadata_spec.rb @@ -118,6 +118,19 @@ RSpec.describe ReferentialMetadata, :type => :model do end + describe "#periodes" do + + let(:referential_metadata) { create(:referential_metadata).reload } + + it "should not exclude end" do + expect(referential_metadata.periodes).to_not be_empty + referential_metadata.periodes.each do |periode| + expect(periode).to_not be_exclude_end + end + end + + end + describe "before_validation" do let(:referential_metadata) do create(:referential_metadata).tap do |metadata| diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index f56680fc0..5c7aa0b98 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -14,7 +14,7 @@ describe User, :type => :model do :organisation_code => '0083', :organisation_name => 'af83', :functional_scope => "[\"STIF:CODIFLIGNE:Line:C00840\", \"STIF:CODIFLIGNE:Line:C00086\"]", - :permissions => nil + :permissions => [] } ticket.user = "john.doe" ticket.success = true @@ -119,27 +119,11 @@ describe User, :type => :model do it 'should give edit permissions to user if user has "edit offer" permission in portail' do User.portail_sync expect(User.find_by(username: 'vlatka.pavisic').permissions).not_to be_empty - expect(User.find_by(username: 'pierre.vabre').permissions).to be_nil + expect(User.find_by(username: 'pierre.vabre').permissions).to be_empty end end end - describe 'validations' do - it 'validates uniqueness of pemissions' do - user = build :user, permissions: Array.new(2, 'calendars.shared') - expect { - user.save! - }.to raise_error(ActiveRecord::RecordInvalid) - end - - it 'validates no pemission is an empty string' do - user = build :user, permissions: [''] - expect { - user.save! - }.to raise_error(ActiveRecord::RecordInvalid) - end - end - describe "#destroy" do let!(:organisation){create(:organisation)} let!(:user){create(:user, :organisation => organisation)} diff --git a/spec/models/vehicle_journey_import_spec.rb b/spec/models/vehicle_journey_import_spec.rb index c4d452f84..a743bdecb 100644 --- a/spec/models/vehicle_journey_import_spec.rb +++ b/spec/models/vehicle_journey_import_spec.rb @@ -119,7 +119,7 @@ describe VehicleJourneyImport, :type => :model do it "should return false when stop points in file are not the same in the route" do vehicle_journey_import = VehicleJourneyImport.new(:route => other_route, :file => valid_file) - expect { vehicle_journey_import.load_imported_vehicle_journeys }.to raise_exception + expect { vehicle_journey_import.load_imported_vehicle_journeys }.to raise_error(RuntimeError) end # it "should return errors when vehicle journeys in file are invalid" do @@ -130,7 +130,7 @@ describe VehicleJourneyImport, :type => :model do it "should return errors when vehicle journey at stops in file are invalid" do vehicle_journey_import = VehicleJourneyImport.new(:route => route, :file => invalid_file_on_vjas) - expect { vehicle_journey_import.load_imported_vehicle_journeys }.to raise_exception + expect { vehicle_journey_import.load_imported_vehicle_journeys }.to raise_error(ArgumentError) end it "should return errors when vehicle journey at stops are not in ascendant order" do diff --git a/spec/routing/companies_spec.rb b/spec/routing/companies_spec.rb index df16079f3..774431dc3 100644 --- a/spec/routing/companies_spec.rb +++ b/spec/routing/companies_spec.rb @@ -3,19 +3,19 @@ require 'spec_helper' describe CompaniesController do describe "routing" do it "not recognize #routes" do - get( "/line_referentials/1/companies/2/routes").should_not route_to( + expect(get( "/line_referentials/1/companies/2/routes")).not_to route_to( :controller => "companies", :action => "routes", :line_referential_id => "1", :id => "2" ) end it "not recognize #lines" do - get( "/line_referentials/1/companies/2/lines").should_not route_to( + expect(get( "/line_referentials/1/companies/2/lines")).not_to route_to( :controller => "companies", :action => "lines", :line_referential_id => "1", :id => "2" ) end it "recognize and generate #show" do - get( "/line_referentials/1/companies/2").should route_to( + expect(get( "/line_referentials/1/companies/2")).to route_to( :controller => "companies", :action => "show", :line_referential_id => "1", :id => "2" ) diff --git a/spec/routing/group_of_lines_spec.rb b/spec/routing/group_of_lines_spec.rb index 8bc437249..2a7262893 100644 --- a/spec/routing/group_of_lines_spec.rb +++ b/spec/routing/group_of_lines_spec.rb @@ -3,19 +3,19 @@ require 'spec_helper' describe GroupOfLinesController do describe "routing" do it "not recognize #routes" do - get( "/line_referentials/1/group_of_lines/2/routes").should_not route_to( + expect(get( "/line_referentials/1/group_of_lines/2/routes")).not_to route_to( :controller => "group_of_lines", :action => "routes", :line_referential_id => "1", :id => "2" ) end it "not recognize #lines" do - get( "/line_referentials/1/group_of_lines/2/lines").should_not route_to( + expect(get( "/line_referentials/1/group_of_lines/2/lines")).not_to route_to( :controller => "group_of_lines", :action => "lines", :line_referential_id => "1", :id => "2" ) end it "recognize and generate #show" do - get( "/line_referentials/1/group_of_lines/2").should route_to( + expect(get( "/line_referentials/1/group_of_lines/2")).to route_to( :controller => "group_of_lines", :action => "show", :line_referential_id => "1", :id => "2" ) diff --git a/spec/routing/networks_spec.rb b/spec/routing/networks_spec.rb index 8d5366f88..941f98c1e 100644 --- a/spec/routing/networks_spec.rb +++ b/spec/routing/networks_spec.rb @@ -3,19 +3,19 @@ require 'spec_helper' describe NetworksController do describe "routing" do it "not recognize #routes" do - get( "/line_referentials/1/networks/2/routes").should_not route_to( + expect(get( "/line_referentials/1/networks/2/routes")).not_to route_to( :controller => "networks", :action => "routes", :line_referential_id => "1", :id => "2" ) end it "not recognize #lines" do - get( "/line_referentials/1/networks/2/lines").should_not route_to( + expect(get( "/line_referentials/1/networks/2/lines")).not_to route_to( :controller => "networks", :action => "lines", :line_referential_id => "1", :id => "2" ) end it "recognize and generate #show" do - get( "/line_referentials/1/networks/2").should route_to( + expect(get( "/line_referentials/1/networks/2")).to route_to( :controller => "networks", :action => "show", :line_referential_id => "1", :id => "2" ) diff --git a/spec/routing/time_tables_spec.rb b/spec/routing/time_tables_spec.rb index 45e426f4c..720ae0815 100644 --- a/spec/routing/time_tables_spec.rb +++ b/spec/routing/time_tables_spec.rb @@ -3,25 +3,25 @@ require 'spec_helper' describe TimeTablesController do describe "routing" do it "not recognize #routes" do - get( "/referentials/1/time_tables/2/routes").should_not route_to( + expect(get( "/referentials/1/time_tables/2/routes")).not_to route_to( :controller => "time_tables", :action => "routes", :referential_id => "1", :id => "2" ) end it "not recognize #lines" do - get( "/referentials/1/time_tables/2/lines").should_not route_to( + expect(get( "/referentials/1/time_tables/2/lines")).not_to route_to( :controller => "time_tables", :action => "lines", :referential_id => "1", :id => "2" ) end it "not recognize #time_table_periods" do - get( "/referentials/1/time_tables/2/time_table_periods").should_not route_to( + expect(get( "/referentials/1/time_tables/2/time_table_periods")).not_to route_to( "time_table_periods#index", :referential_id => "1", :time_table_id => "2" ) end it "recognize and generate #show" do - get( "/referentials/1/time_tables/2").should route_to( + expect(get( "/referentials/1/time_tables/2")).to route_to( :controller => "time_tables", :action => "show", :referential_id => "1", :id => "2" ) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index dd062bc84..f66d721c9 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -51,7 +51,8 @@ RSpec.configure do |config| #Capybara.exact = true Capybara.javascript_driver = :poltergeist - config.filter_run_excluding :js => true + config.filter_run_excluding :js => true + config.filter_run :wip => true config.run_all_when_everything_filtered = true config.include TokenInputHelper, :type => :feature @@ -87,3 +88,20 @@ RSpec.configure do |config| config.infer_spec_type_from_file_location! end + +Shoulda::Matchers.configure do |config| + config.integrate do |with| + # Choose a test framework: + with.test_framework :rspec + # with.test_framework :minitest + # with.test_framework :minitest_4 + # with.test_framework :test_unit + + # Choose one or more libraries: + # with.library :active_record + # with.library :active_model + # with.library :action_controller + # Or, choose the following (which implies all of the above): + with.library :rails + end +end diff --git a/spec/support/devise.rb b/spec/support/devise.rb index 0e3ceefac..14e316bea 100644 --- a/spec/support/devise.rb +++ b/spec/support/devise.rb @@ -8,7 +8,8 @@ module DeviseRequestHelper 'vehicle_journeys.create', 'vehicle_journeys.edit', 'vehicle_journeys.destroy', 'time_tables.create', 'time_tables.edit', 'time_tables.destroy', 'footnotes.edit', 'footnotes.create', 'footnotes.destroy', 'routing_constraint_zones.create', 'routing_constraint_zones.edit', 'routing_constraint_zones.destroy', 'access_points.create', 'access_points.edit', 'access_points.destroy', 'access_links.create', 'access_links.edit', 'access_links.destroy', - 'connection_links.create', 'connection_links.edit', 'connection_links.destroy', 'route_sections.create', 'route_sections.edit', 'route_sections.destroy']) + 'connection_links.create', 'connection_links.edit', 'connection_links.destroy', 'route_sections.create', 'route_sections.edit', 'route_sections.destroy', + 'referentials.create', 'referentials.edit', 'referentials.destroy']) login_as @user, :scope => :user # post_via_redirect user_session_path, 'user[email]' => @user.email, 'user[password]' => @user.password end @@ -44,7 +45,8 @@ module DeviseControllerHelper 'vehicle_journeys.create', 'vehicle_journeys.edit', 'vehicle_journeys.destroy', 'time_tables.create', 'time_tables.edit', 'time_tables.destroy', 'footnotes.edit', 'footnotes.create', 'footnotes.destroy', 'routing_constraint_zones.create', 'routing_constraint_zones.edit', 'routing_constraint_zones.destroy', 'access_points.create', 'access_points.edit', 'access_points.destroy', 'access_links.create', 'access_links.edit', 'access_links.destroy', - 'connection_links.create', 'connection_links.edit', 'connection_links.destroy', 'route_sections.create', 'route_sections.edit', 'route_sections.destroy']) + 'connection_links.create', 'connection_links.edit', 'connection_links.destroy', 'route_sections.create', 'route_sections.edit', 'route_sections.destroy', + 'referentials.create', 'referentials.edit', 'referentials.destroy']) sign_in @user end end diff --git a/spec/support/pg_catalog.rb b/spec/support/pg_catalog.rb new file mode 100644 index 000000000..30992168e --- /dev/null +++ b/spec/support/pg_catalog.rb @@ -0,0 +1,82 @@ +module Support + module PGCatalog + + def get_columns(schema_name, table_name) + execute("SELECT * from information_schema.columns WHERE table_name = '#{table_name}' AND table_schema = '#{schema_name}'") + end + def get_foreign_keys(schema_oid, table_name) + schema_oid = get_schema_oid(schema_oid) unless Integer === schema_oid + return [] unless schema_oid + execute(foreign_key_query(schema_oid, table_name)) + .to_a + end + + def get_schema_oid(schema_name) + execute("SELECT oid FROM pg_namespace WHERE nspname = '#{schema_name}'") + .values + .flatten + .first + end + + def get_sequences(schema_name, table_name) + sequences = execute <<-EOSQL + SELECT sequence_name FROM information_schema.sequences + WHERE sequence_schema = '#{schema_name}' AND sequence_name LIKE '#{table_name}%' + EOSQL + sequences.values.flatten.map do | sequence | + execute "SELECT * from #{schema_name}.#{sequence}" + end.flat_map(&:to_a) + end + + def get_table_information(schema_name, table_name) + execute("SELECT * FROM information_schema.tables WHERE table_name = '#{table_name}' AND table_schema = '#{schema_name}'") + .to_a + .map(&without_keys("table_catalog")) + end + + + private + def base_connection + ActiveRecord::Base.connection + end + + def execute(sql) + base_connection.execute(sql) + end + + def foreign_key_query(schema_oid, table_name) + key = [:foreign_key_query, schema_oid, table_name] + get_or_create_query(key){ <<-EOQ + SELECT ct.conname AS constraint_name, pg_get_constraintdef(ct.oid) AS constraint_def + FROM pg_constraint ct JOIN pg_class rn ON rn.oid = ct.conrelid + WHERE connamespace = #{schema_oid} AND rn.relname = '#{table_name}' AND rn.relkind = 'r' AND ct.contype = 'f' + EOQ + } + end + + def sequence_properties_query(schema_name, sequence_name) + key = [:sequence_properies_query, schema_name, sequence_name] + get_or_create_query(key){ <<-EOQ + Coming Soon + EOQ + } + + end + + def get_or_create_query(query_key, &query_value) + queries.fetch(query_key){ queries[query_key] = query_value.() } + end + + def queries + @__queries__ ||= {} + end + + def without_keys(*keys) + -> hashy do + hashy.inject({}) do |h, (k,v)| + keys.include?(k) ? h : h.merge(k => v) + end + end + end + end +end diff --git a/spec/support/type_ids_modelable_spec.rb b/spec/support/type_ids_modelable.rb index 9ed341810..9ed341810 100644 --- a/spec/support/type_ids_modelable_spec.rb +++ b/spec/support/type_ids_modelable.rb diff --git a/spec/views/companies/show.html.erb_spec.rb b/spec/views/companies/show.html.erb_spec.rb index f0a8a99d4..dbc544f63 100644 --- a/spec/views/companies/show.html.erb_spec.rb +++ b/spec/views/companies/show.html.erb_spec.rb @@ -12,7 +12,7 @@ describe "/companies/show", :type => :view do # it "should display a map with class 'company'" do # render - # rendered.should have_selector("#map", :class => 'company') + # expect(rendered).to have_selector("#map", :class => 'company') # end it "should render a link to edit the company" do diff --git a/spec/views/connection_links/show.html.erb_spec.rb b/spec/views/connection_links/show.html.erb_spec.rb index 1a7ad3d16..c04a4f3f1 100644 --- a/spec/views/connection_links/show.html.erb_spec.rb +++ b/spec/views/connection_links/show.html.erb_spec.rb @@ -18,7 +18,7 @@ describe "/connection_links/show", :type => :view do # it "should display a map with class 'connection_link'" do # pending ": map not yet implemented" # render -# rendered.should have_selector("#map", :class => 'connection_link') +# expect(rendered).to have_selector("#map", :class => 'connection_link') # end it "should render a link to edit the connection_link" do diff --git a/spec/views/layouts/application.html.erb_spec.rb b/spec/views/layouts/application.html.erb_spec.rb index 700084922..80e3e6f86 100644 --- a/spec/views/layouts/application.html.erb_spec.rb +++ b/spec/views/layouts/application.html.erb_spec.rb @@ -12,7 +12,7 @@ describe "/layouts/application", :type => :view do it "should display referential name as title" #do # render - # rendered.should_not have_selector("h1") + # expect(rendered).not_to have_selector("h1") # end end diff --git a/spec/views/lines/show.html.erb_spec.rb b/spec/views/lines/show.html.erb_spec.rb index 939d6bc83..3a9efa0ce 100644 --- a/spec/views/lines/show.html.erb_spec.rb +++ b/spec/views/lines/show.html.erb_spec.rb @@ -19,7 +19,7 @@ describe "/lines/show", :type => :view do # it "should display a map with class 'line'" do # render - # rendered.should have_selector("#map", :class => 'line') + # expect(rendered).to have_selector("#map", :class => 'line') # end # FIXME #2018 xit "should render a link to edit the line" do diff --git a/spec/views/organisations/show.html.erb b/spec/views/organisations/show.html.erb index 69f5e2956..84af3b044 100644 --- a/spec/views/organisations/show.html.erb +++ b/spec/views/organisations/show.html.erb @@ -10,7 +10,7 @@ describe "/organisations/show" do it "should render each User" do render organisation.users.each do |user| - rendered.should have_selector("div.user span.name", :text => user.name) + expect(rendered).to have_selector("div.user span.name", :text => user.name) end end diff --git a/spec/views/routes/show.html.erb_spec.rb b/spec/views/routes/show.html.erb_spec.rb index 787bf72d0..7557ede27 100644 --- a/spec/views/routes/show.html.erb_spec.rb +++ b/spec/views/routes/show.html.erb_spec.rb @@ -26,7 +26,7 @@ describe "/routes/show", :type => :view do # it "should display a map with class 'line'" do # render - # rendered.should have_selector("#map", :class => 'line') + # expect(rendered).to have_selector("#map", :class => 'line') # end # it "should render a link to edit the route" do diff --git a/spec/views/stop_areas/show.html.erb_spec.rb b/spec/views/stop_areas/show.html.erb_spec.rb index 0c9c6663b..a22379402 100644 --- a/spec/views/stop_areas/show.html.erb_spec.rb +++ b/spec/views/stop_areas/show.html.erb_spec.rb @@ -14,7 +14,7 @@ describe "/stop_areas/show", :type => :view do # it "should display a map with class 'stop_area'" do # render - # rendered.should have_selector("#map", :class => 'stop_area') + # expect(rendered).to have_selector("#map", :class => 'stop_area') # end it "should render a link to edit the stop_area" do diff --git a/spec/views/time_tables/edit.html.erb_spec.rb b/spec/views/time_tables/edit.html.erb_spec.rb index 18c5d6d85..c84c5eb74 100644 --- a/spec/views/time_tables/edit.html.erb_spec.rb +++ b/spec/views/time_tables/edit.html.erb_spec.rb @@ -5,19 +5,11 @@ describe "/time_tables/edit", :type => :view do let!(:time_table) { assign(:time_table, create(:time_table) ) } describe "test" do - it "should render h2 with the group comment" do - render - expect(rendered).to have_selector("h2", :text => Regexp.new(time_table.comment)) - end - end - - describe "form" do - it "should render input for comment" do + it "should render h1 with the group comment" do render - expect(rendered).to have_selector("form") do - with_tag "input[type=text][comment='time_table[comment]'][value=?]", time_table.comment - end + expect(rendered).to have_selector("h1", :text => Regexp.new(time_table.comment)) end - end + + # No more test for the form, as it is now managed by React/Redux. end diff --git a/spec/views/time_tables/index.html.erb_spec.rb b/spec/views/time_tables/index.html.erb_spec.rb index 2679964c1..cea172ce9 100644 --- a/spec/views/time_tables/index.html.erb_spec.rb +++ b/spec/views/time_tables/index.html.erb_spec.rb @@ -10,16 +10,16 @@ describe "/time_tables/index", :type => :view do allow(view).to receive_messages(current_organisation: referential.organisation) end - it "should render a show link for each group" do - render - time_tables.each do |time_table| - expect(rendered).to have_selector(".time_table a[href='#{view.referential_time_table_path(referential, time_table)}']", :text => time_table.comment) - 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_time_table_path(referential)}']") - end + # it "should render a show link for each group" do + # render + # time_tables.each do |time_table| + # expect(rendered).to have_selector("a[href='#{view.referential_time_table_path(referential, time_table)}']", :text => time_table.comment) + # end + # end + # + # it "should render a link to create a new group" do + # render + # expect(rendered).to have_selector("a[href='#{new_referential_time_table_path(referential)}']") + # end end diff --git a/spec/views/time_tables/show.html.erb_spec.rb b/spec/views/time_tables/show.html.erb_spec.rb index 3b5d7f1f1..f429f9dec 100644 --- a/spec/views/time_tables/show.html.erb_spec.rb +++ b/spec/views/time_tables/show.html.erb_spec.rb @@ -13,18 +13,17 @@ describe "/time_tables/show", :type => :view do it "should render h2 with the time_table comment" do render - expect(rendered).to have_selector("h2", :text => Regexp.new(time_table.comment)) + expect(rendered).to have_selector("h1", :text => Regexp.new(time_table.comment)) end it "should render a link to edit the time_table" do render - expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{view.edit_referential_time_table_path(referential, time_table)}']") + expect(rendered).to have_selector(" a[href='#{view.edit_referential_time_table_path(referential, time_table)}']") end it "should render a link to remove the time_table" do render - expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{view.referential_time_table_path(referential, time_table)}'][class='remove']") + expect(rendered).to have_selector(" a[href='#{view.referential_time_table_path(referential, time_table)}']") end end - diff --git a/spec/workers/referential_cloning_worker_spec.rb b/spec/workers/referential_cloning_worker_spec.rb index dd7b33f23..85d771742 100644 --- a/spec/workers/referential_cloning_worker_spec.rb +++ b/spec/workers/referential_cloning_worker_spec.rb @@ -1,4 +1,45 @@ -require 'rails_helper' -RSpec.describe ReferentialCloningWorker, type: :worker do - pending "add some examples to (or delete) #{__FILE__}" +require 'spec_helper' +require 'ostruct' + +RSpec.describe ReferentialCloningWorker do + + context "given a refererntial cloning" do + + let( :id ){ double } + + let( :worker ){ described_class.new } + + + let( :source_schema ){ "source_schema" } + let( :target_schema ){ "#{source_schema}_tmp" } + let( :referential_cloning ){ OpenStruct.new(source_referential: OpenStruct.new(slug: source_schema)) } + + before do + expect( ReferentialCloning ).to receive(:find).with(id).and_return(referential_cloning) + expect( StoredProcedures ) + .to receive(:invoke_stored_procedure) + .with(:clone_schema, source_schema, target_schema, true) + + expect( worker ).to receive(:execute_sql).with( "DROP SCHEMA #{source_schema} CASCADE;" ) + + expect( referential_cloning ).to receive(:run!) + end + + it "invokes the correct stored procedure, updates the database and the AASM" do + expect( worker ).to receive(:execute_sql).with( "ALTER SCHEMA #{target_schema} RENAME TO #{source_schema};" ) + expect( referential_cloning ).to receive(:successful!) + worker.perform(id) + end + + it "handles failure correctly" do + expect( worker ) + .to receive(:execute_sql) + .with( "ALTER SCHEMA #{target_schema} RENAME TO #{source_schema};" ) + .and_raise(RuntimeError) + + expect( referential_cloning ).to receive(:failed!) + worker.perform(id) + end + end + end |
