diff options
230 files changed, 4845 insertions, 2859 deletions
@@ -1 +1 @@ -rvm ruby-1.8.7-p374 +rvm ruby-1.9.3-p448 diff --git a/.travis.yml b/.travis.yml index d91cd343e..3b34b286e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,18 @@ language: ruby rvm: - - 1.8.7 - - jruby-18mode + - 1.9.3 + - jruby-19mode jdk: - oraclejdk7 - openjdk7 matrix: exclude: - - rvm: 1.8.7 - jdk: openjdk7 - rvm: 1.9.3 jdk: openjdk7 +notifications: + - mflorisson@cityway.fr + - ldonnet@cityway.fr + - metienne@cityway.fr before_install: - sudo apt-get update - sudo apt-get install build-essential ruby-dev libproj-dev libgeos-dev libffi-dev libsparsehash-dev zlib1g-dev libxslt1-dev libxml2-dev libbz2-dev @@ -1,36 +1,29 @@ source 'http://rubygems.org' -gem 'rails', '3.2.6' +gem 'rails', '3.2.6' platforms :jruby do gem 'activerecord-jdbcpostgresql-adapter', '1.2.9' gem 'activerecord-jdbcsqlite3-adapter' gem 'jruby-openssl' gem "jruby-rack-worker" - gem 'warbler' - gem 'therubyrhino' + gem 'warbler' + gem 'therubyrhino' end platforms :ruby do - gem 'therubyracer', '~> 0.10.2' - gem 'pg', '~> 0.11.0' + gem 'therubyracer', '~> 0.10.2' + gem 'pg', '~> 0.11.0' gem 'sqlite3' end -gem 'google-analytics-rails' - # Authentication gem 'devise', '2.1.3' gem 'devise_invitable' # Map, Geolocalization gem "map_layers", "0.0.4" -gem "georuby-ext", :git => 'https://github.com/dryade/georuby-ext.git' , :ref => '69e3460141d831f0ad76780ee2b3f0a925a744f8' -gem "geokit","1.6.5" -gem "dbf","2.0.5" -gem "json_pure","1.7.7" -gem "multi_json","1.7.7" - +gem "georuby-ext", :git => 'git://github.com/dryade/georuby-ext.git' #gem "georuby-ext", "0.0.2" # User interface @@ -42,6 +35,9 @@ gem 'formtastic' gem 'RedCloth' gem 'jquery-rails', '2.2.1' gem "modernizr-rails", "~> 2.0.6" +gem 'morrisjs-rails' +gem 'raphael-rails' +gem 'font-awesome-sass' # Format Output gem 'json' @@ -58,6 +54,7 @@ gem 'squeel' gem 'ninoxe', '0.1.3' gem 'acts_as_list', '0.1.6' gem "acts_as_tree-1.8", '1.1.0', :require => "acts_as_tree" +gem "active_enum" gem 'delayed_job_active_record' gem 'dr-apartment', :require => "apartment" @@ -74,20 +71,20 @@ group :assets do gem 'uglifier', '>= 1.0.3' end -group :development do +group :development do gem 'capistrano' - gem 'capistrano-ext' + gem 'capistrano-ext' gem 'guard' gem 'guard-rspec' - gem 'rails-erd' + gem 'rails-erd' end group :test, :development do gem "rspec-rails", "~> 2.0" - gem "remarkable", "~> 4.0.0.alpha4" - gem "remarkable_activerecord", "~> 4.0.0.alpha4" + gem "remarkable", "~> 4.0.0.alpha4" + gem "remarkable_activerecord", "~> 4.0.0.alpha4" gem "shoulda-matchers" - gem 'capybara' + gem 'capybara' gem 'launchy' gem 'factory_girl_rails', '1.7' gem 'rb-inotify', :require => RUBY_PLATFORM.include?('linux') && 'rb-inotify' @@ -95,7 +92,6 @@ group :test, :development do end group :production do - gem "SyslogLogger" - gem "daemons" + gem "SyslogLogger" end diff --git a/Gemfile.lock b/Gemfile.lock index bfd5cf59b..9cd208a8f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,6 @@ GIT - remote: https://github.com/dryade/georuby-ext.git + remote: git://github.com/dryade/georuby-ext.git revision: 69e3460141d831f0ad76780ee2b3f0a925a744f8 - ref: 69e3460141d831f0ad76780ee2b3f0a925a744f8 specs: georuby-ext (0.0.2) activesupport @@ -33,6 +32,8 @@ GEM rack-cache (~> 1.2) rack-test (~> 0.6.1) sprockets (~> 2.1.3) + active_enum (0.9.12) + activesupport (~> 3.0) activemodel (3.2.6) activesupport (= 3.2.6) builder (~> 3.0.0) @@ -57,8 +58,8 @@ GEM acts_as_list (0.1.6) acts_as_tree-1.8 (1.1.0) activerecord (>= 3.0.0) - addressable (2.2.8) - arel (3.0.2) + addressable (2.3.5) + arel (3.0.3) bcrypt-ruby (3.0.1) bcrypt-ruby (3.0.1-java) bouncy-castle-java (1.5.0146.1) @@ -80,8 +81,8 @@ GEM rack-test (>= 0.5.4) selenium-webdriver (~> 2.0) xpath (~> 0.1.4) - childprocess (0.3.5) - ffi (~> 1.0, >= 1.0.6) + childprocess (0.3.9) + ffi (~> 1.0, >= 1.0.11) choice (0.1.6) cocoon (1.1.2) coffee-rails (3.2.2) @@ -91,7 +92,6 @@ GEM coffee-script-source execjs coffee-script-source (1.3.3) - daemons (1.1.6) dbf (2.0.5) fastercsv (~> 1.5.4) delayed_job (3.0.3) @@ -125,6 +125,8 @@ GEM ffi (1.0.11-java) ffi-geos (0.1.1) ffi (>= 1.0.0) + font-awesome-sass (4.0.2) + sass-rails (>= 3.1.1) foreigner (1.4.0) activerecord (>= 3.0.0) formtastic (2.2.1) @@ -132,20 +134,21 @@ GEM geokit (1.6.5) multi_json georuby (1.9.8) - google-analytics-rails (0.0.4) gravatar_image_tag (1.1.3) guard (1.3.2) listen (>= 0.4.2) thor (>= 0.14.6) guard-rspec (1.2.1) guard (>= 1.1) - has_scope (0.5.1) + has_scope (0.6.0.rc) + actionpack (>= 3.2, < 5) + activesupport (>= 3.2, < 5) highline (1.6.15) - hike (1.2.2) - i18n (0.6.5) - inherited_resources (1.3.1) - has_scope (~> 0.5.0) - responders (~> 0.6) + hike (1.2.3) + i18n (0.6.9) + inherited_resources (1.4.1) + has_scope (~> 0.6.0.rc) + responders (~> 1.0.0.rc) jdbc-postgres (9.2.1002.1) jdbc-sqlite3 (3.7.2.1) journey (1.0.4) @@ -158,18 +161,12 @@ GEM jruby-rack (1.1.9) jruby-rack-worker (0.4-java) jruby-rack (>= 1.1.1) - json (1.7.7) - json (1.7.7-java) - json_pure (1.7.7) - launchy (2.1.0) - addressable (~> 2.2.6) - launchy (2.1.0-java) - addressable (~> 2.2.6) - ffi (~> 1.0.9) - spoon (~> 0.0.1) + json (1.8.1) + json (1.8.1-java) + json_pure (1.8.0) + launchy (2.3.0) + addressable (~> 2.3) libv8 (3.3.10.4) - libwebsocket (0.1.5) - addressable listen (0.4.7) rb-fchange (~> 0.0.5) rb-fsevent (~> 0.9.1) @@ -179,9 +176,11 @@ GEM mime-types (~> 1.16) treetop (~> 1.4.8) map_layers (0.0.4) - mime-types (1.19) + mime-types (1.25.1) modernizr-rails (2.0.6) - multi_json (1.7.7) + morrisjs-rails (0.4.3) + railties (> 3.1, < 5) + multi_json (1.8.2) net-scp (1.0.4) net-ssh (>= 1.99.1) net-sftp (2.0.5) @@ -232,11 +231,12 @@ GEM rake (>= 0.8.7) rdoc (~> 3.4) thor (>= 0.14.6, < 2.0) - rake (10.0.4) + rake (10.1.0) ransack (0.7.0) actionpack (~> 3.0) activerecord (~> 3.0) polyamorous (~> 0.5.0) + raphael-rails (2.1.2) rb-fchange (0.0.5) ffi rb-fsevent (0.9.1) @@ -253,8 +253,8 @@ GEM remarkable (~> 4.0.0.alpha4) remarkable_activemodel (~> 4.0.0.alpha4) rspec (>= 2.0.0.alpha11) - responders (0.9.2) - railties (~> 3.1) + responders (1.0.0) + railties (>= 3.2, < 5) rgeo (0.3.20) rspec (2.13.0) rspec-core (~> 2.13.0) @@ -278,14 +278,13 @@ GEM railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) - selenium-webdriver (2.25.0) + selenium-webdriver (2.35.1) childprocess (>= 0.2.5) - libwebsocket (~> 0.1.3) multi_json (~> 1.0) - rubyzip + rubyzip (< 1.0.0) + websocket (~> 1.0.4) shoulda-matchers (1.2.0) activesupport (>= 3.0.0) - spoon (0.0.1) sprockets (2.1.3) hike (~> 1.2) rack (~> 1.0) @@ -301,11 +300,11 @@ GEM therubyrhino_jar (>= 1.7.3) therubyrhino_jar (1.7.4) thor (0.18.1) - tilt (1.3.6) - treetop (1.4.12) + tilt (1.4.1) + treetop (1.4.15) polyglot polyglot (>= 0.3.1) - tzinfo (0.3.37) + tzinfo (0.3.38) uglifier (1.2.7) execjs (>= 0.3.0) multi_json (~> 1.3) @@ -318,6 +317,7 @@ GEM rubyzip (>= 0.9.4) warden (1.2.1) rack (>= 1.0) + websocket (1.0.7) will_paginate (3.0.3) xpath (0.1.4) nokogiri (~> 1.3) @@ -329,6 +329,7 @@ PLATFORMS DEPENDENCIES RedCloth SyslogLogger + active_enum activerecord-jdbcpostgresql-adapter (= 1.2.9) activerecord-jdbcsqlite3-adapter acts_as_list (= 0.1.6) @@ -340,17 +341,14 @@ DEPENDENCIES cocoon (= 1.1.2) coffee-rails (~> 3.2.1) coffee-script-source - daemons - dbf (= 2.0.5) delayed_job_active_record devise (= 2.1.3) devise_invitable dr-apartment factory_girl_rails (= 1.7) + font-awesome-sass formtastic - geokit (= 1.6.5) georuby-ext! - google-analytics-rails gravatar_image_tag guard guard-rspec @@ -359,17 +357,17 @@ DEPENDENCIES jruby-openssl jruby-rack-worker json - json_pure (= 1.7.7) launchy map_layers (= 0.0.4) modernizr-rails (~> 2.0.6) - multi_json (= 1.7.7) + morrisjs-rails ninoxe (= 0.1.3) pg (~> 0.11.0) rabl rails (= 3.2.6) rails-erd ransack + raphael-rails rb-fsevent rb-inotify remarkable (~> 4.0.0.alpha4) diff --git a/app/assets/images/import-completed.png b/app/assets/images/compliance_check_task-completed.png Binary files differindex a76d76b13..a76d76b13 100644 --- a/app/assets/images/import-completed.png +++ b/app/assets/images/compliance_check_task-completed.png diff --git a/app/assets/images/import-failed.png b/app/assets/images/compliance_check_task-failed.png Binary files differindex f13b19234..f13b19234 100644 --- a/app/assets/images/import-failed.png +++ b/app/assets/images/compliance_check_task-failed.png diff --git a/app/assets/images/import-pending.png b/app/assets/images/compliance_check_task-pending.png Binary files differindex 1e50e36ac..1e50e36ac 100644 --- a/app/assets/images/import-pending.png +++ b/app/assets/images/compliance_check_task-pending.png diff --git a/app/assets/images/compliance_check_task-processing.png b/app/assets/images/compliance_check_task-processing.png Binary files differnew file mode 100644 index 000000000..1e50e36ac --- /dev/null +++ b/app/assets/images/compliance_check_task-processing.png diff --git a/app/assets/images/icons/collapse.png b/app/assets/images/icons/collapse.png Binary files differnew file mode 100644 index 000000000..5411a1b91 --- /dev/null +++ b/app/assets/images/icons/collapse.png diff --git a/app/assets/images/icons/expand.png b/app/assets/images/icons/expand.png Binary files differnew file mode 100644 index 000000000..8cad0129b --- /dev/null +++ b/app/assets/images/icons/expand.png diff --git a/app/assets/images/icons/file_basic.png b/app/assets/images/icons/file_basic.png Binary files differnew file mode 100644 index 000000000..ec5bec65f --- /dev/null +++ b/app/assets/images/icons/file_basic.png diff --git a/app/assets/images/icons/file_xml.png b/app/assets/images/icons/file_xml.png Binary files differnew file mode 100644 index 000000000..bff923f27 --- /dev/null +++ b/app/assets/images/icons/file_xml.png diff --git a/app/assets/images/icons/file_xml_md.png b/app/assets/images/icons/file_xml_md.png Binary files differnew file mode 100644 index 000000000..6e471ca2a --- /dev/null +++ b/app/assets/images/icons/file_xml_md.png diff --git a/app/assets/images/icons/file_zip.png b/app/assets/images/icons/file_zip.png Binary files differnew file mode 100644 index 000000000..9893c5cfb --- /dev/null +++ b/app/assets/images/icons/file_zip.png diff --git a/app/assets/images/icons/help-contents.png b/app/assets/images/icons/help-contents.png Binary files differnew file mode 100644 index 000000000..a6a986e19 --- /dev/null +++ b/app/assets/images/icons/help-contents.png diff --git a/app/assets/images/icons/help.png b/app/assets/images/icons/help.png Binary files differnew file mode 100644 index 000000000..e6edf6ba2 --- /dev/null +++ b/app/assets/images/icons/help.png diff --git a/app/assets/images/icons/link_page.png b/app/assets/images/icons/link_page.png Binary files differnew file mode 100644 index 000000000..a2c53bf3e --- /dev/null +++ b/app/assets/images/icons/link_page.png diff --git a/app/assets/images/icons/notice.png b/app/assets/images/icons/notice.png Binary files differnew file mode 100644 index 000000000..16510c9c4 --- /dev/null +++ b/app/assets/images/icons/notice.png diff --git a/app/assets/images/icons/status_na.png b/app/assets/images/icons/status_na.png Binary files differnew file mode 100644 index 000000000..4a892e60c --- /dev/null +++ b/app/assets/images/icons/status_na.png diff --git a/app/assets/images/icons/status_nok.png b/app/assets/images/icons/status_nok.png Binary files differnew file mode 100644 index 000000000..8dd9d2968 --- /dev/null +++ b/app/assets/images/icons/status_nok.png diff --git a/app/assets/images/icons/status_ok.png b/app/assets/images/icons/status_ok.png Binary files differnew file mode 100644 index 000000000..ab7c378c0 --- /dev/null +++ b/app/assets/images/icons/status_ok.png diff --git a/app/assets/images/import_task-completed.png b/app/assets/images/import_task-completed.png Binary files differnew file mode 100644 index 000000000..a76d76b13 --- /dev/null +++ b/app/assets/images/import_task-completed.png diff --git a/app/assets/images/import_task-failed.png b/app/assets/images/import_task-failed.png Binary files differnew file mode 100644 index 000000000..f13b19234 --- /dev/null +++ b/app/assets/images/import_task-failed.png diff --git a/app/assets/images/import_task-pending.png b/app/assets/images/import_task-pending.png Binary files differnew file mode 100644 index 000000000..1e50e36ac --- /dev/null +++ b/app/assets/images/import_task-pending.png diff --git a/app/assets/images/import_task-processing.png b/app/assets/images/import_task-processing.png Binary files differnew file mode 100644 index 000000000..1e50e36ac --- /dev/null +++ b/app/assets/images/import_task-processing.png diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 69d083fe7..6b7b38a3a 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -9,5 +9,6 @@ //= require jquery-ui //= require modernizr //= require cocoon -//= require_directory ./public +//= require raphael +//= require morris //= require_directory . diff --git a/app/assets/javascripts/compliance_check_tasks.js.coffee b/app/assets/javascripts/compliance_check_tasks.js.coffee new file mode 100644 index 000000000..feed5de2d --- /dev/null +++ b/app/assets/javascripts/compliance_check_tasks.js.coffee @@ -0,0 +1,14 @@ +jQuery -> + compliance_check_task_references_type_change = (event) -> + references_type = $(event.target).val() + + toggle_input = (li) -> + enabled = (li.data("type") == references_type) + # Hide li block + li.toggle(enabled) + # Disable textarea to ignore it in POST data + li.find("textarea").attr("disabled", ! enabled) + + toggle_input($(li)) for li in $(event.target).parents('form').find("li.compliance_check_task_reference_ids") + + $('select[name="compliance_check_task[references_type]"]').change(compliance_check_task_references_type_change) diff --git a/app/assets/javascripts/exports.js.coffee b/app/assets/javascripts/exports.js.coffee index 71b565e91..045b95e2e 100644 --- a/app/assets/javascripts/exports.js.coffee +++ b/app/assets/javascripts/exports.js.coffee @@ -1,5 +1,5 @@ jQuery -> - export_references_type_change = (event) -> + export_references_type_change = (event) -> references_type = $(event.target).val() toggle_input = (li) -> @@ -15,7 +15,7 @@ jQuery -> $('#export_type_submit').hide() - export_type_change = (event) -> + export_type_change = (event) -> export_type = $("input:radio:checked").attr("value") $(form).toggle($(form).is("#" + export_type + "_new")) for form in $('form.export[method = "post"]') diff --git a/app/assets/javascripts/import_tasks.js.coffee b/app/assets/javascripts/import_tasks.js.coffee new file mode 100644 index 000000000..690d86976 --- /dev/null +++ b/app/assets/javascripts/import_tasks.js.coffee @@ -0,0 +1,10 @@ +jQuery -> + + import_format_change = (event) -> + import_task_type = $("input:radio:checked").attr("value") + console.log("import_task_type="+import_task_type) + $(form).toggle($(form).is("#" + import_task_type + "_new")) for form in $('form.import_task[method = "post"]') + + $("#import_task_format_input :radio[name='import_task[format]']").change(import_format_change) + + $('.import_tasks [title]').tipsy({gravity: 'w'})
\ No newline at end of file diff --git a/app/assets/javascripts/imports.js.coffee b/app/assets/javascripts/imports.js.coffee deleted file mode 100644 index ea6473595..000000000 --- a/app/assets/javascripts/imports.js.coffee +++ /dev/null @@ -1,9 +0,0 @@ -jQuery -> - $('#import_type_submit').hide() - - import_type_change = (event) -> - import_type = $("input:radio:checked").attr("value") - console.log("import_type="+import_type) - $(form).toggle($(form).is("#" + import_type + "_new")) for form in $('form.import[method = "post"]') - - $("#import_type_input :radio[name='import[type]']").change(import_type_change) diff --git a/app/assets/javascripts/plugins.js b/app/assets/javascripts/plugins.js new file mode 100644 index 000000000..6f6a902ae --- /dev/null +++ b/app/assets/javascripts/plugins.js @@ -0,0 +1 @@ +//= require_directory ./plugins diff --git a/app/assets/javascripts/plugins/bootstrap.min.js b/app/assets/javascripts/plugins/bootstrap.min.js new file mode 100644 index 000000000..fb820c1a2 --- /dev/null +++ b/app/assets/javascripts/plugins/bootstrap.min.js @@ -0,0 +1,11 @@ +/*! + * Bootstrap v3.0.3 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + ++function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function f(){e.trigger("closed.bs.alert").remove()}var c=a(this),d=c.attr("data-target");d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));var e=a(d);b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.trigger(b=a.Event("close.bs.alert"));if(b.isDefaultPrevented())return;e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.one(a.support.transition.end,f).emulateTransitionEnd(150):f()};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]'),b=!0;if(a.length){var c=this.$element.find("input");c.prop("type")==="radio"&&(c.prop("checked")&&this.$element.hasClass("active")?b=!1:a.find(".active").removeClass("active")),b&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}b&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f=typeof c=="object"&&c;e||d.data("bs.button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){function e(){a(b).remove(),a(c).each(function(b){var c=f(a(this));if(!c.hasClass("open"))return;c.trigger(b=a.Event("hide.bs.dropdown"));if(b.isDefaultPrevented())return;c.removeClass("open").trigger("hidden.bs.dropdown")})}function f(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}"use strict";var b=".dropdown-backdrop",c="[data-toggle=dropdown]",d=function(b){a(b).on("click.bs.dropdown",this.toggle)};d.prototype.toggle=function(b){var c=a(this);if(c.is(".disabled, :disabled"))return;var d=f(c),g=d.hasClass("open");e();if(!g){"ontouchstart"in document.documentElement&&!d.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",e),d.trigger(b=a.Event("show.bs.dropdown"));if(b.isDefaultPrevented())return;d.toggleClass("open").trigger("shown.bs.dropdown"),c.focus()}return!1},d.prototype.keydown=function(b){if(!/(38|40|27)/.test(b.keyCode))return;var d=a(this);b.preventDefault(),b.stopPropagation();if(d.is(".disabled, :disabled"))return;var e=f(d),g=e.hasClass("open");if(!g||g&&b.keyCode==27)return b.which==27&&e.find(c).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",e);if(!h.length)return;var i=h.index(h.filter(":focus"));b.keyCode==38&&i>0&&i--,b.keyCode==40&&i<h.length-1&&i++,~i||(i=0),h.eq(i).focus()};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),e=c.data("bs.dropdown");e||c.data("bs.dropdown",e=new d(this)),typeof b=="string"&&e[b].call(c)})},a.fn.dropdown.Constructor=d,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",e).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",c,d.prototype.toggle).on("keydown.bs.dropdown.data-api",c+", [role=menu]",d.prototype.keydown)}(jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.load(this.options.remote)};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d);if(this.isShown||d.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.$element.on("click.dismiss.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show(),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)})},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b);if(!this.isShown||b.isDefaultPrevented())return;this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal()},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]!==a.target&&!this.$element.has(a.target).length&&this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){a.which==27&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('<div class="modal-backdrop '+d+'" />').appendTo(document.body),this.$element.on("click.dismiss.modal",a.proxy(function(a){if(a.target!==a.currentTarget)return;this.options.backdrop=="static"?this.$element[0].focus.call(this.$element[0]):this.hide.call(this)},this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!b)return;e?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),typeof c=="object"&&c);f||e.data("bs.modal",f=new b(this,g)),typeof c=="string"?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);var e=this.options.trigger.split(" ");for(var f=e.length;f--;){var g=e[f];if(g=="click")this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if(g!="manual"){var h=g=="hover"?"mouseenter":"focus",i=g=="hover"?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&typeof b.delay=="number"&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(c.timeout),c.hoverState="in";if(!c.options.delay||!c.options.delay.show)return c.show();c.timeout=setTimeout(function(){c.hoverState=="in"&&c.show()},c.options.delay.show)},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);clearTimeout(c.timeout),c.hoverState="out";if(!c.options.delay||!c.options.delay.hide)return c.hide();c.timeout=setTimeout(function(){c.hoverState=="out"&&c.hide()},c.options.delay.hide)},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);if(b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d=typeof this.options.placement=="function"?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m=this.options.container=="body"?window.innerWidth:j.outerWidth(),n=this.options.container=="body"?window.innerHeight:j.outerHeight(),o=this.options.container=="body"?0:j.offset().left;d=d=="bottom"&&g.top+g.height+i-l>n?"top":d=="top"&&g.top-l-i<0?"bottom":d=="right"&&g.right+h>m?"left":d=="left"&&g.left-h<o?"right":d,c.removeClass(k).addClass(d)}var p=this.getCalculatedOffset(d,g,h,i);this.applyPlacement(p,d),this.$element.trigger("shown.bs."+this.type)}},b.prototype.applyPlacement=function(a,b){var c,d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),a.top=a.top+g,a.left=a.left+h,d.offset(a).addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;b=="top"&&j!=f&&(c=!0,a.top=a.top+f-j);if(/bottom|top/.test(b)){var k=0;a.left<0&&(k=a.left*-2,a.left=0,d.offset(a),i=d[0].offsetWidth,j=d[0].offsetHeight),this.replaceArrow(k-e+i,i,"left")}else this.replaceArrow(j-f,j,"top");c&&d.offset(a)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function e(){b.hoverState!="in"&&c.detach()}var b=this,c=this.tip(),d=a.Event("hide.bs."+this.type);this.$element.trigger(d);if(d.isDefaultPrevented())return;return c.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?c.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),this.$element.trigger("hidden.bs."+this.type),this},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||typeof a.attr("data-original-title")!="string")&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},typeof b.getBoundingClientRect=="function"?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return a=="bottom"?{top:b.top+b.height,left:b.left+b.width/2-c/2}:a=="top"?{top:b.top-d,left:b.left+b.width/2-c/2}:a=="left"?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||(typeof c.title=="function"?c.title.call(b[0]):c.title),a},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f=typeof c=="object"&&c;e||d.data("bs.tooltip",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||(typeof b.content=="function"?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f=typeof c=="object"&&c;e||d.data("bs.popover",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));if(b.parent("li").hasClass("active"))return;var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});b.trigger(f);if(f.isDefaultPrevented())return;var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})},b.prototype.activate=function(b,c,d){function g(){e.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),f?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var e=c.find("> .active"),f=d&&a.support.transition&&e.hasClass("fade");f?e.one(a.support.transition.end,g).emulateTransitionEnd(150):g(),e.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),typeof c=="string"&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery)
\ No newline at end of file diff --git a/app/assets/javascripts/public/formtastic.qtip2.min.js b/app/assets/javascripts/plugins/formtastic.qtip2.min.js index 52a1ef1f7..52a1ef1f7 100644 --- a/app/assets/javascripts/public/formtastic.qtip2.min.js +++ b/app/assets/javascripts/plugins/formtastic.qtip2.min.js diff --git a/app/assets/javascripts/public/jquery.qtip.min.js b/app/assets/javascripts/plugins/jquery.qtip.min.js index 1ed034ee3..1ed034ee3 100644 --- a/app/assets/javascripts/public/jquery.qtip.min.js +++ b/app/assets/javascripts/plugins/jquery.qtip.min.js diff --git a/app/assets/javascripts/plugins/jquery.tipsy.js b/app/assets/javascripts/plugins/jquery.tipsy.js new file mode 100644 index 000000000..f95c063fd --- /dev/null +++ b/app/assets/javascripts/plugins/jquery.tipsy.js @@ -0,0 +1,258 @@ +// tipsy, facebook style tooltips for jquery +// version 1.0.0a +// (c) 2008-2010 jason frame [jason@onehackoranother.com] +// released under the MIT license + +(function($) { + + function maybeCall(thing, ctx) { + return (typeof thing == 'function') ? (thing.call(ctx)) : thing; + }; + + function isElementInDOM(ele) { + while (ele = ele.parentNode) { + if (ele == document) return true; + } + return false; + }; + + function Tipsy(element, options) { + this.$element = $(element); + this.options = options; + this.enabled = true; + this.fixTitle(); + }; + + Tipsy.prototype = { + show: function() { + var title = this.getTitle(); + if (title && this.enabled) { + var $tip = this.tip(); + + $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title); + $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity + $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body); + + var pos = $.extend({}, this.$element.offset(), { + width: this.$element[0].offsetWidth, + height: this.$element[0].offsetHeight + }); + + var actualWidth = $tip[0].offsetWidth, + actualHeight = $tip[0].offsetHeight, + gravity = maybeCall(this.options.gravity, this.$element[0]); + + var tp; + switch (gravity.charAt(0)) { + case 'n': + tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; + break; + case 's': + tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}; + break; + case 'e': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset}; + break; + case 'w': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset}; + break; + } + + if (gravity.length == 2) { + if (gravity.charAt(1) == 'w') { + tp.left = pos.left + pos.width / 2 - 15; + } else { + tp.left = pos.left + pos.width / 2 - actualWidth + 15; + } + } + + $tip.css(tp).addClass('tipsy-' + gravity); + $tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0); + if (this.options.className) { + $tip.addClass(maybeCall(this.options.className, this.$element[0])); + } + + if (this.options.fade) { + $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity}); + } else { + $tip.css({visibility: 'visible', opacity: this.options.opacity}); + } + } + }, + + hide: function() { + if (this.options.fade) { + this.tip().stop().fadeOut(function() { $(this).remove(); }); + } else { + this.tip().remove(); + } + }, + + fixTitle: function() { + var $e = this.$element; + if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') { + $e.attr('original-title', $e.attr('title') || '').removeAttr('title'); + } + }, + + getTitle: function() { + var title, $e = this.$element, o = this.options; + this.fixTitle(); + var title, o = this.options; + if (typeof o.title == 'string') { + title = $e.attr(o.title == 'title' ? 'original-title' : o.title); + } else if (typeof o.title == 'function') { + title = o.title.call($e[0]); + } + title = ('' + title).replace(/(^\s*|\s*$)/, ""); + return title || o.fallback; + }, + + tip: function() { + if (!this.$tip) { + this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>'); + this.$tip.data('tipsy-pointee', this.$element[0]); + } + return this.$tip; + }, + + validate: function() { + if (!this.$element[0].parentNode) { + this.hide(); + this.$element = null; + this.options = null; + } + }, + + enable: function() { this.enabled = true; }, + disable: function() { this.enabled = false; }, + toggleEnabled: function() { this.enabled = !this.enabled; } + }; + + $.fn.tipsy = function(options) { + + if (options === true) { + return this.data('tipsy'); + } else if (typeof options == 'string') { + var tipsy = this.data('tipsy'); + if (tipsy) tipsy[options](); + return this; + } + + options = $.extend({}, $.fn.tipsy.defaults, options); + + function get(ele) { + var tipsy = $.data(ele, 'tipsy'); + if (!tipsy) { + tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options)); + $.data(ele, 'tipsy', tipsy); + } + return tipsy; + } + + function enter() { + var tipsy = get(this); + tipsy.hoverState = 'in'; + if (options.delayIn == 0) { + tipsy.show(); + } else { + tipsy.fixTitle(); + setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn); + } + }; + + function leave() { + var tipsy = get(this); + tipsy.hoverState = 'out'; + if (options.delayOut == 0) { + tipsy.hide(); + } else { + setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut); + } + }; + + if (!options.live) this.each(function() { get(this); }); + + if (options.trigger != 'manual') { + var binder = options.live ? 'live' : 'bind', + eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus', + eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur'; + this[binder](eventIn, enter)[binder](eventOut, leave); + } + + return this; + + }; + + $.fn.tipsy.defaults = { + className: null, + delayIn: 0, + delayOut: 0, + fade: false, + fallback: '', + gravity: 'n', + html: false, + live: false, + offset: 0, + opacity: 0.8, + title: 'title', + trigger: 'hover' + }; + + $.fn.tipsy.revalidate = function() { + $('.tipsy').each(function() { + var pointee = $.data(this, 'tipsy-pointee'); + if (!pointee || !isElementInDOM(pointee)) { + $(this).remove(); + } + }); + }; + + // Overwrite this method to provide options on a per-element basis. + // For example, you could store the gravity in a 'tipsy-gravity' attribute: + // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' }); + // (remember - do not modify 'options' in place!) + $.fn.tipsy.elementOptions = function(ele, options) { + return $.metadata ? $.extend({}, options, $(ele).metadata()) : options; + }; + + $.fn.tipsy.autoNS = function() { + return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n'; + }; + + $.fn.tipsy.autoWE = function() { + return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w'; + }; + + /** + * yields a closure of the supplied parameters, producing a function that takes + * no arguments and is suitable for use as an autogravity function like so: + * + * @param margin (int) - distance from the viewable region edge that an + * element should be before setting its tooltip's gravity to be away + * from that edge. + * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer + * if there are no viewable region edges effecting the tooltip's + * gravity. It will try to vary from this minimally, for example, + * if 'sw' is preferred and an element is near the right viewable + * region edge, but not the top edge, it will set the gravity for + * that element's tooltip to be 'se', preserving the southern + * component. + */ + $.fn.tipsy.autoBounds = function(margin, prefer) { + return function() { + var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)}, + boundTop = $(document).scrollTop() + margin, + boundLeft = $(document).scrollLeft() + margin, + $this = $(this); + + if ($this.offset().top < boundTop) dir.ns = 'n'; + if ($this.offset().left < boundLeft) dir.ew = 'w'; + if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e'; + if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's'; + + return dir.ns + (dir.ew ? dir.ew : ''); + } + }; + +})(jQuery); diff --git a/app/assets/javascripts/public/jquery.tokeninput.js b/app/assets/javascripts/plugins/jquery.tokeninput.js index 87641a57a..87641a57a 100644 --- a/app/assets/javascripts/public/jquery.tokeninput.js +++ b/app/assets/javascripts/plugins/jquery.tokeninput.js diff --git a/app/assets/javascripts/public/jquery.ui.datepicker-i18n.js b/app/assets/javascripts/plugins/jquery.ui.datepicker-i18n.js index b7748a77a..b7748a77a 100644 --- a/app/assets/javascripts/public/jquery.ui.datepicker-i18n.js +++ b/app/assets/javascripts/plugins/jquery.ui.datepicker-i18n.js diff --git a/app/assets/javascripts/public/proj4js-compressed.js b/app/assets/javascripts/plugins/proj4js-compressed.js index 3da44ad15..3da44ad15 100644 --- a/app/assets/javascripts/public/proj4js-compressed.js +++ b/app/assets/javascripts/plugins/proj4js-compressed.js diff --git a/app/assets/javascripts/public/proj4js-defs.js b/app/assets/javascripts/plugins/proj4js-defs.js index fe77a033c..fe77a033c 100644 --- a/app/assets/javascripts/public/proj4js-defs.js +++ b/app/assets/javascripts/plugins/proj4js-defs.js diff --git a/app/assets/javascripts/rule_parameter_set.js.coffee b/app/assets/javascripts/rule_parameter_set.js.coffee new file mode 100644 index 000000000..bb1e2226b --- /dev/null +++ b/app/assets/javascripts/rule_parameter_set.js.coffee @@ -0,0 +1,10 @@ +jQuery -> + mode_change = (event) -> + $(".mode_specific.selected").toggle() + $(".mode_specific.selected").toggleClass( "selected" ) + mode_selected = $("option:selected").attr("value") + $(".mode_specific."+mode_selected).toggle() + $(".mode_specific."+mode_selected).toggleClass( "selected" ) + + $("#mode").change(mode_change) + diff --git a/app/assets/stylesheets/access_links.css.scss b/app/assets/stylesheets/access_links.css.scss index 63a55e021..c076b30b1 100644 --- a/app/assets/stylesheets/access_links.css.scss +++ b/app/assets/stylesheets/access_links.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.access_links.show diff --git a/app/assets/stylesheets/access_points.css.scss b/app/assets/stylesheets/access_points.css.scss index 22dc3ac3d..6545a32aa 100644 --- a/app/assets/stylesheets/access_points.css.scss +++ b/app/assets/stylesheets/access_points.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.access_points.index { diff --git a/app/assets/stylesheets/api_keys.css.scss b/app/assets/stylesheets/api_keys.css.scss index cca96321e..2c1c45cdb 100644 --- a/app/assets/stylesheets/api_keys.css.scss +++ b/app/assets/stylesheets/api_keys.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the routes controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.referentials.show { diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 7a73fd3fe..b773f970a 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -5,5 +5,7 @@ *= require_self *= require formtastic *= require jquery-ui + *= require morris + *= require font-awesome *= require_tree . */
\ No newline at end of file diff --git a/app/assets/stylesheets/common.css.scss b/app/assets/stylesheets/common.css.scss index 91050771e..950004ec8 100644 --- a/app/assets/stylesheets/common.css.scss +++ b/app/assets/stylesheets/common.css.scss @@ -1,81 +1,4 @@ -@mixin div_for_object { - margin-bottom: 10px; - background-color: #DEFFA8; - padding-top: 10px; - padding-bottom: 10px; - margin-right: 10px; - padding-left: 10px; - - .color { - width: 64px; - height: 64px; - float: left; - margin-right: 10px; - } - - img { - float: left; - margin-right: 10px; - } - - img.preview { - width: 90px; - height: 70px; - } - - a { - display:block; - text-decoration: underline; - margin: 5px 0px 0px 0px; - } - - .info { - font-size: 10px; - color: #777; - font-weight: normal; - line-height: 14px; - margin-top: 5px; - - a { - display:inline; - color: #777; - } - - .actions { - margin-top: 10px; - a { - color: #666; - padding-left: 12px; - } - - a.link { - background: url(image-path('icons/link-small.png')) no-repeat 0% 50%; - } - a.edit { - background: url(image-path('user_interface/ui/edit-small.png')) no-repeat 0% 50%; - } - a.remove { - background: url(image-path('user_interface/ui/remove-small.png')) no-repeat 0% 50%; - } - a.download { - background: url(image-path('download-small.png')) no-repeat 0% 50%; - } - } - - p { - margin:0; - } - } -} - -@mixin content_to_clear { - content: " "; - display: block; - height: 0; - clear: both; - visibility: hidden; -} - -@mixin after_div_for_object { - @include content_to_clear; -} +/* + *= require_tree ./common + *= require_tree ./plugins +*/ diff --git a/app/assets/stylesheets/common/mixins.css.scss b/app/assets/stylesheets/common/mixins.css.scss new file mode 100644 index 000000000..91050771e --- /dev/null +++ b/app/assets/stylesheets/common/mixins.css.scss @@ -0,0 +1,81 @@ +@mixin div_for_object { + margin-bottom: 10px; + background-color: #DEFFA8; + padding-top: 10px; + padding-bottom: 10px; + margin-right: 10px; + padding-left: 10px; + + .color { + width: 64px; + height: 64px; + float: left; + margin-right: 10px; + } + + img { + float: left; + margin-right: 10px; + } + + img.preview { + width: 90px; + height: 70px; + } + + a { + display:block; + text-decoration: underline; + margin: 5px 0px 0px 0px; + } + + .info { + font-size: 10px; + color: #777; + font-weight: normal; + line-height: 14px; + margin-top: 5px; + + a { + display:inline; + color: #777; + } + + .actions { + margin-top: 10px; + a { + color: #666; + padding-left: 12px; + } + + a.link { + background: url(image-path('icons/link-small.png')) no-repeat 0% 50%; + } + a.edit { + background: url(image-path('user_interface/ui/edit-small.png')) no-repeat 0% 50%; + } + a.remove { + background: url(image-path('user_interface/ui/remove-small.png')) no-repeat 0% 50%; + } + a.download { + background: url(image-path('download-small.png')) no-repeat 0% 50%; + } + } + + p { + margin:0; + } + } +} + +@mixin content_to_clear { + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +@mixin after_div_for_object { + @include content_to_clear; +} diff --git a/app/assets/stylesheets/companies.css.scss b/app/assets/stylesheets/companies.css.scss index 7e490841a..c3569c4fd 100644 --- a/app/assets/stylesheets/companies.css.scss +++ b/app/assets/stylesheets/companies.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.companies.index { diff --git a/app/assets/stylesheets/compliance_check_tasks.css.scss b/app/assets/stylesheets/compliance_check_tasks.css.scss new file mode 100644 index 000000000..10ba55893 --- /dev/null +++ b/app/assets/stylesheets/compliance_check_tasks.css.scss @@ -0,0 +1,257 @@ +@import "common/mixins"; + +.status { + margin-left: 10px; +} + +.status_failed { color: #a94442;} +.status_pending { color: #31708f;} +.status_processing { color: #31708f;} +.status_completed { color: #3c763d;} + +#workspace.compliance_check_tasks.index +{ + .compliance_check_task:after { + @include after_div_for_object; + } + + .compliance_check_tasks { + margin-top: 20px; + } + + .compliance_check_tasks:after { + @include content_to_clear; + } + + .compliance_check_task { + width: 300px; + float: left; + padding: 5px; + margin: 0 10px 10px 0px; + background-color: #DEFFA8; + border: 1px solid #61970b; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + + div.icon{ + display: inline-block; + vertical-align: top; + width: 74px; + padding-right: 5px; + + img{ + width: 64px; + height: 64px; + } + } + + div.resume{ + display: inline-block; + + ul.header{ + font-size: 14px; + width: 209px; + + .title{ float: left; } + .remove{ + float: right; + padding-right: 10px; + color: #494949; + } + } + + .links { + font-size: 10px; + height: 38px; + + p { margin: 3px 0px 0px 0px !important; } + + img { margin-right: 10px;} + } + + .history { + margin-top: 10px; + font-size: 10px; + color: #777; + } + } + } +} + +#workspace.compliance_check_tasks.show { + + .links{ + margin: 0px 0 20px 0; + } + + .order{ + margin-bottom: 10px; + padding: 5px; + border-top: 1px solid #e4e4e4; + border-bottom: 1px solid #e4e4e4; + } + + .resume { + &:after{ + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; + } + + .col1 { + float: left; + width: 45%; + } + + .col2 { + margin-left: 10px; + float: left; + width: 45%; + } + + .graph { height: 200px; } + + .caption { + text-align :center; + font-weight: bold; + } + } + + .report{ + .table { margin-top: 20px; } + + } + + .severity__improvment, .severity_warning, .severity_error { + border: 1px solid; + margin: 10px 0px; + padding:10px 10px 10px 10px; + background-repeat: no-repeat; + background-position: 10px center;-moz-border-radius:.5em; + -webkit-border-radius:.5em; + border-radius:.5em; + height: 100%; + + &:after{ + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; + } + + .status_icon { + float: left; + width: 20%; + height: auto; + + img { + vertical-align: middle; + width: 48px; + height: 48px; + } + } + + .status_text{ + float: left; + width: 70%; + + .code{ + font-size: 12px; + font-weight: bold; + } + + .severity { + font-size: 10px; + } + + .explanation{ + display: none; + font-size: 12px; + margin: 5px 0 0 0; + } + + .attributes{ + font-size: 10px; + font-weight: bold; + margin: 5px 0 0px 0; + } + } + + } + + .severity_improvment { + color: black; + background-color: #c5cf4c; + } + + .severity_warning { + color: black; + background-color: #f1dd30; + } + + .severity_error { + color: black; + background-color: #ff9a0c; + } + + .td_error { + width: 30%; + + i { margin-right: 10px; } + + div.details_error{ + margin: 0px 0px 0px 3px !important; + display: none; + + p.detail_error{ + margin: 0px 0px 5px 0px !important; + } + + .file_error{ + margin-left: 26px; + font-size: 10px; + color: #898e7f; + } + } + } +} + +#workspace.compliance_check_tasks.new, #workspace.compliance_check_tasks.create +{ + padding: 0; + margin-top: -0.3em; + margin-bottom: 1em; + + + + .inputs ol { + margin-top: -0.3em; + margin-bottom: 1em; + padding: 0; + width: 100%; + } + .inputs ol li { padding : 0.3em 0; } + + .inputs ol li textarea { + width: 54%; + } + .inputs ol li label { + width: 40%; + margin-top: -0.3em; + } + + .inputs ol li.fl label { width: 40%; margin-top: -0.3em; } + .inputs ol li.fl input { width: 21%; padding: 0; } + + .inputs ol li.fl1 {float: left; width: 70% ;} + .inputs ol li.fl1 label {width: 57%; margin-top: -0.3em; } + .inputs ol li.fl1 input { width: 30%; } + + .inputs ol li.fl2 {float: left; width: 25% ;} + .inputs ol li.fl2 label {width: 10%; margin-top: -0.3em;} + .inputs ol li.fl2 input { width: 85%; } + +} diff --git a/app/assets/stylesheets/connection_links.css.scss b/app/assets/stylesheets/connection_links.css.scss index 00868e49f..b2ad0de75 100644 --- a/app/assets/stylesheets/connection_links.css.scss +++ b/app/assets/stylesheets/connection_links.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.connection_links.index { diff --git a/app/assets/stylesheets/exports.css.scss b/app/assets/stylesheets/exports.css.scss index f9312cc1c..d26ef2c8d 100644 --- a/app/assets/stylesheets/exports.css.scss +++ b/app/assets/stylesheets/exports.css.scss @@ -2,7 +2,7 @@ // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.exports.index { @@ -71,4 +71,4 @@ select { width: 25%; } -}
\ No newline at end of file +} diff --git a/app/assets/stylesheets/file_validations.css.scss b/app/assets/stylesheets/file_validations.css.scss deleted file mode 100644 index 187c74b3c..000000000 --- a/app/assets/stylesheets/file_validations.css.scss +++ /dev/null @@ -1,137 +0,0 @@ -@import "common"; - -#workspace.file_validations.index -{ - .file_validation:after { - @include after_div_for_object; - } - - .file_validations { - margin-top: 20px; - } - - .file_validations:after { - @include content_to_clear; - } - - .file_validation { - @include div_for_object; - - /* to create multi-column index */ - width: 300px; - float: left; - padding-right: 10px; - } -} - -#workspace.file_validations.show { - .file_validation_show { - width: 95% - } - .panelDataSection - { - font-size: 14px; - padding: 3px 0px 3px 20px; - BACKGROUND-COLOR: #FaFaFa; - margin: 10px 0px 0px 0px; - BORDER-LEFT: 1px solid #B0BCD6; - BORDER-RIGHT: 1px solid #B0BCD6; - BORDER-TOP: 1px solid #B0BCD6; - FONT-WEIGHT: bold; - } - .neptune-panel{ - font-family: Arial, Verdana, Helvetica, sans-serif; - font-size: 13px; - background-color: #FFFFFF; - margin: 0px 0px 2px 0px; - padding: 10px 10px 10px 10px; - border: 1px solid #B0BCD6; - table { - border: 0px; - td { - padding: 20px; - } - } - } - .category{ - font-weight: bold; - } - - -.ok{ - background: url(image-path('severity-ok.png')) no-repeat 98% 0%; - } - -.uncheck { - background: url(image-path('severity-uncheck.png')) no-repeat 98% 0%; - } - -.warning{ - background: url(image-path('severity-warning.png')) no-repeat 98% 0%; - } - -.error{ - background: url(image-path('severity-error.png')) no-repeat 98% 0%; - color: red; - } -.fatal{ - background: url(image-path('severity-fatal.png')) no-repeat 98% 0%; - color: red; - } - -.step { - width: 80%; - padding-left:100px; - margin-top:-15px; -} -.detail { - margin: 0 0 0 660px; - padding: 5px 0 0 0; - } -.neptune-panel-inSide -{ - background-color: #FFFFFF; - padding: 5px 5px; - margin:0 0 5px 100px; - width: 80%; - font-size: 12px; - border: 1px solid #B0BCD6; -} -} - -#workspace.file_validations.new, #workspace.file_validations.create -{ - padding: 0; - margin-top: -0.3em; - margin-bottom: 1em; - - - - .inputs ol { - margin-top: -0.3em; - margin-bottom: 1em; - padding: 0; - width: 100%; - } - .inputs ol li { padding : 0.3em 0; } - - .inputs ol li textarea { - width: 54%; - } - .inputs ol li label { - width: 40%; - margin-top: -0.3em; - } - - .inputs ol li.fl label { width: 40%; margin-top: -0.3em; } - .inputs ol li.fl input { width: 21%; padding: 0; } - - .inputs ol li.fl1 {float: left; width: 70% ;} - .inputs ol li.fl1 label {width: 57%; margin-top: -0.3em; } - .inputs ol li.fl1 input { width: 30%; } - - .inputs ol li.fl2 {float: left; width: 25% ;} - .inputs ol li.fl2 label {width: 10%; margin-top: -0.3em;} - .inputs ol li.fl2 input { width: 85%; } - -} diff --git a/app/assets/stylesheets/group_of_lines.css.scss b/app/assets/stylesheets/group_of_lines.css.scss index 24fbdce12..bcfca6f4e 100644 --- a/app/assets/stylesheets/group_of_lines.css.scss +++ b/app/assets/stylesheets/group_of_lines.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.group_of_lines.index { diff --git a/app/assets/stylesheets/import_tasks.css.scss b/app/assets/stylesheets/import_tasks.css.scss new file mode 100644 index 000000000..153f5f097 --- /dev/null +++ b/app/assets/stylesheets/import_tasks.css.scss @@ -0,0 +1,163 @@ +@import "common/mixins"; + +.status { + margin-left: 10px; +} + +.status_failed { color: #a94442;} +.status_pending { color: #31708f;} +.status_processing { color: #31708f;} +.status_completed { color: #3c763d;} + +#workspace.import_tasks.index +{ + .import_task:after { + @include after_div_for_object; + } + + .import_tasks { + margin-top: 20px; + } + + .import_tasks:after { + @include content_to_clear; + } + + .import_task { + width: 300px; + float: left; + padding: 5px; + margin: 0 10px 10px 0px; + background-color: #DEFFA8; + border: 1px solid #61970b; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + + div.icon{ + display: inline-block; + vertical-align: top; + width: 74px; + padding-right: 5px; + + img{ + width: 64px; + height: 64px; + } + } + + div.resume{ + display: inline-block; + + ul.header{ + font-size: 14px; + width: 209px; + + .title{ float: left; } + .remove{ + float: right; + padding-right: 10px; + } + } + + .links { + font-size: 10px; + height: 38px; + + p { margin: 3px 0px 0px 0px !important; } + + img { margin-right: 10px;} + } + + .history { + margin-top: 10px; + font-size: 10px; + color: #777; + } + } + } +} + +#workspace.import_tasks.show { + + .links{ + margin: 0 0 20px 0; + + img { margin-right: 10px; } + } + + .resume { + &:after{ + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; + } + + .col1 { + float: left; + width: 45%; + } + + .col2 { + margin-left: 10px; + float: left; + width: 45%; + } + + #files_statistics { height: 200px; } + #objects_statistics { height: 200px; } + + .caption { + text-align :center; + font-weight: bold; + } + } + + .report { + margin-top: 20px; + + .files { + img { + margin-right: 5px; + } + + .file_name{ + font-weight: bold; + margin-right: 30px; + } + } + + .files_error{ + color: #e22b1b; + display: none; + } + + .files_ignored{ + color: #ffbd2b; + display: none; + } + + .files_ok{ + color: #8fc861; + display: none; + } + + .lines{ display: none; } + } +} + +#workspace.import_tasks.new #workspace.import_tasks.create form.import_task_new { + padding: 0.5em 0; + margin-top: -0.5em; + margin-bottom: 1em; + + label { + display: block; + width: 25%; + float: left; + } + select { + width: 25%; + } +} diff --git a/app/assets/stylesheets/imports.css.scss b/app/assets/stylesheets/imports.css.scss deleted file mode 100644 index 6241a09e8..000000000 --- a/app/assets/stylesheets/imports.css.scss +++ /dev/null @@ -1,70 +0,0 @@ -@import "common"; - -#workspace.imports.index -{ - .import:after { - @include after_div_for_object; - } - - .imports { - margin-top: 20px; - } - - .imports:after { - @include content_to_clear; - } - - .import { - @include div_for_object; - - /* to create multi-column index */ - width: 300px; - float: left; - padding-right: 10px; - } -} - -#workspace.imports.show { - table { - th { - font-style: italic; - } - th.severity { - width: 30px; - } - th.created_at { - text-align: center; - width: 100px; - } - th.position { - padding-right: 5px; - text-align: right; - width: 40px; - } - td.severity { - text-align: center; - } - td.created_at { - padding-right: 3px; - } - td.position { - padding-right: 5px; - text-align: right; - } - } -} - -#workspace.imports.new #workspace.imports.create form.import_new { - padding: 0.5em 0; - margin-top: -0.5em; - margin-bottom: 1em; - - label { - display: block; - width: 25%; - float: left; - } - select { - width: 25%; - } -} diff --git a/app/assets/stylesheets/journey_patterns.css.scss b/app/assets/stylesheets/journey_patterns.css.scss index 0e9113f41..232a9fa66 100644 --- a/app/assets/stylesheets/journey_patterns.css.scss +++ b/app/assets/stylesheets/journey_patterns.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the routes controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.journey_patterns.edit, #workspace.journey_patterns.new, #workspace.journey_patterns.create, #workspace.journey_patterns.update { diff --git a/app/assets/stylesheets/layout.css.scss b/app/assets/stylesheets/layout.css.scss index 4a5237aa7..0505512fe 100644 --- a/app/assets/stylesheets/layout.css.scss +++ b/app/assets/stylesheets/layout.css.scss @@ -7,6 +7,12 @@ $text_color: #222; @import "user_interface/layout"; +// Override user_interface/layout +b { font-weight: bold; } + +// Add margin-top to alert +.alert { margin-top: 10px;} + p.after_map { clear: both; } diff --git a/app/assets/stylesheets/lines.css.scss b/app/assets/stylesheets/lines.css.scss index 8632a72b2..f3ce676e2 100644 --- a/app/assets/stylesheets/lines.css.scss +++ b/app/assets/stylesheets/lines.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.lines.index { diff --git a/app/assets/stylesheets/networks.css.scss b/app/assets/stylesheets/networks.css.scss index da43b41f8..dafe42c98 100644 --- a/app/assets/stylesheets/networks.css.scss +++ b/app/assets/stylesheets/networks.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.networks.index { diff --git a/app/assets/stylesheets/organisations.css.scss b/app/assets/stylesheets/organisations.css.scss index cb794940a..4ce671436 100644 --- a/app/assets/stylesheets/organisations.css.scss +++ b/app/assets/stylesheets/organisations.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.organisations.show { diff --git a/app/assets/stylesheets/plugins/bootstrap.min.css b/app/assets/stylesheets/plugins/bootstrap.min.css new file mode 100644 index 000000000..145037827 --- /dev/null +++ b/app/assets/stylesheets/plugins/bootstrap.min.css @@ -0,0 +1,11 @@ +/*! + * Bootstrap v3.0.3 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden],template{display:none;}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}body{margin:0;}a{background:transparent;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;margin:0.67em 0;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:bold;}dfn{font-style:italic;}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace, serif;font-size:1em;}pre{white-space:pre-wrap;}q{quotes:"\201C" "\201D" "\2018" "\2019";}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{border:0;}svg:not(:root){overflow:hidden;}figure{margin:0;}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}legend{border:0;padding:0;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}button,select{text-transform:none;}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}button[disabled],html input[disabled]{cursor:default;}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;}@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important;} a,a:visited{text-decoration:underline;} a[href]:after{content:" (" attr(href) ")";} abbr[title]:after{content:" (" attr(title) ")";} a[href^="javascript:"]:after,a[href^="#"]:after{content:"";} pre,blockquote{border:1px solid #999;page-break-inside:avoid;} thead{display:table-header-group;} tr,img{page-break-inside:avoid;} img{max-width:100% !important;} @page {margin:2cm .5cm;}p,h2,h3{orphans:3;widows:3;} h2,h3{page-break-after:avoid;} select{background:#fff !important;} .navbar{display:none;} .table td,.table th{background-color:#fff !important;} .btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important;} .label{border:1px solid #000;} .table{border-collapse:collapse !important;} .table-bordered th,.table-bordered td{border:1px solid #ddd !important;}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0, 0, 0, 0);}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333333;background-color:#ffffff;}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;}a{color:#428bca;text-decoration:none;}a:hover,a:focus{color:#2a6496;text-decoration:underline;}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}img{vertical-align:middle;}.img-responsive{display:block;max-width:100%;height:auto;}.img-rounded{border-radius:6px;}.img-thumbnail{padding:4px;line-height:1.428571429;background-color:#ffffff;border:1px solid #dddddd;border-radius:4px;-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;display:inline-block;max-width:100%;height:auto;}.img-circle{border-radius:50%;}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee;}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px;}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;word-break:break-all;word-wrap:break-word;color:#333333;background-color:#f5f5f5;border:1px solid #cccccc;border-radius:4px;}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0;}.pre-scrollable{max-height:340px;overflow-y:scroll;}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px;}.container:before,.container:after{content:" ";display:table;}.container:after{clear:both;}.container:before,.container:after{content:" ";display:table;}.container:after{clear:both;}@media (min-width:768px){.container{width:750px;}}@media (min-width:992px){.container{width:970px;}}@media (min-width:1200px){.container{width:1170px;}}.row{margin-left:-15px;margin-right:-15px;}.row:before,.row:after{content:" ";display:table;}.row:after{clear:both;}.row:before,.row:after{content:" ";display:table;}.row:after{clear:both;}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px;}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left;}.col-xs-12{width:100%;}.col-xs-11{width:91.66666666666666%;}.col-xs-10{width:83.33333333333334%;}.col-xs-9{width:75%;}.col-xs-8{width:66.66666666666666%;}.col-xs-7{width:58.333333333333336%;}.col-xs-6{width:50%;}.col-xs-5{width:41.66666666666667%;}.col-xs-4{width:33.33333333333333%;}.col-xs-3{width:25%;}.col-xs-2{width:16.666666666666664%;}.col-xs-1{width:8.333333333333332%;}.col-xs-pull-12{right:100%;}.col-xs-pull-11{right:91.66666666666666%;}.col-xs-pull-10{right:83.33333333333334%;}.col-xs-pull-9{right:75%;}.col-xs-pull-8{right:66.66666666666666%;}.col-xs-pull-7{right:58.333333333333336%;}.col-xs-pull-6{right:50%;}.col-xs-pull-5{right:41.66666666666667%;}.col-xs-pull-4{right:33.33333333333333%;}.col-xs-pull-3{right:25%;}.col-xs-pull-2{right:16.666666666666664%;}.col-xs-pull-1{right:8.333333333333332%;}.col-xs-pull-0{right:0%;}.col-xs-push-12{left:100%;}.col-xs-push-11{left:91.66666666666666%;}.col-xs-push-10{left:83.33333333333334%;}.col-xs-push-9{left:75%;}.col-xs-push-8{left:66.66666666666666%;}.col-xs-push-7{left:58.333333333333336%;}.col-xs-push-6{left:50%;}.col-xs-push-5{left:41.66666666666667%;}.col-xs-push-4{left:33.33333333333333%;}.col-xs-push-3{left:25%;}.col-xs-push-2{left:16.666666666666664%;}.col-xs-push-1{left:8.333333333333332%;}.col-xs-push-0{left:0%;}.col-xs-offset-12{margin-left:100%;}.col-xs-offset-11{margin-left:91.66666666666666%;}.col-xs-offset-10{margin-left:83.33333333333334%;}.col-xs-offset-9{margin-left:75%;}.col-xs-offset-8{margin-left:66.66666666666666%;}.col-xs-offset-7{margin-left:58.333333333333336%;}.col-xs-offset-6{margin-left:50%;}.col-xs-offset-5{margin-left:41.66666666666667%;}.col-xs-offset-4{margin-left:33.33333333333333%;}.col-xs-offset-3{margin-left:25%;}.col-xs-offset-2{margin-left:16.666666666666664%;}.col-xs-offset-1{margin-left:8.333333333333332%;}.col-xs-offset-0{margin-left:0%;}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left;} .col-sm-12{width:100%;} .col-sm-11{width:91.66666666666666%;} .col-sm-10{width:83.33333333333334%;} .col-sm-9{width:75%;} .col-sm-8{width:66.66666666666666%;} .col-sm-7{width:58.333333333333336%;} .col-sm-6{width:50%;} .col-sm-5{width:41.66666666666667%;} .col-sm-4{width:33.33333333333333%;} .col-sm-3{width:25%;} .col-sm-2{width:16.666666666666664%;} .col-sm-1{width:8.333333333333332%;} .col-sm-pull-12{right:100%;} .col-sm-pull-11{right:91.66666666666666%;} .col-sm-pull-10{right:83.33333333333334%;} .col-sm-pull-9{right:75%;} .col-sm-pull-8{right:66.66666666666666%;} .col-sm-pull-7{right:58.333333333333336%;} .col-sm-pull-6{right:50%;} .col-sm-pull-5{right:41.66666666666667%;} .col-sm-pull-4{right:33.33333333333333%;} .col-sm-pull-3{right:25%;} .col-sm-pull-2{right:16.666666666666664%;} .col-sm-pull-1{right:8.333333333333332%;} .col-sm-pull-0{right:0%;} .col-sm-push-12{left:100%;} .col-sm-push-11{left:91.66666666666666%;} .col-sm-push-10{left:83.33333333333334%;} .col-sm-push-9{left:75%;} .col-sm-push-8{left:66.66666666666666%;} .col-sm-push-7{left:58.333333333333336%;} .col-sm-push-6{left:50%;} .col-sm-push-5{left:41.66666666666667%;} .col-sm-push-4{left:33.33333333333333%;} .col-sm-push-3{left:25%;} .col-sm-push-2{left:16.666666666666664%;} .col-sm-push-1{left:8.333333333333332%;} .col-sm-push-0{left:0%;} .col-sm-offset-12{margin-left:100%;} .col-sm-offset-11{margin-left:91.66666666666666%;} .col-sm-offset-10{margin-left:83.33333333333334%;} .col-sm-offset-9{margin-left:75%;} .col-sm-offset-8{margin-left:66.66666666666666%;} .col-sm-offset-7{margin-left:58.333333333333336%;} .col-sm-offset-6{margin-left:50%;} .col-sm-offset-5{margin-left:41.66666666666667%;} .col-sm-offset-4{margin-left:33.33333333333333%;} .col-sm-offset-3{margin-left:25%;} .col-sm-offset-2{margin-left:16.666666666666664%;} .col-sm-offset-1{margin-left:8.333333333333332%;} .col-sm-offset-0{margin-left:0%;}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left;} .col-md-12{width:100%;} .col-md-11{width:91.66666666666666%;} .col-md-10{width:83.33333333333334%;} .col-md-9{width:75%;} .col-md-8{width:66.66666666666666%;} .col-md-7{width:58.333333333333336%;} .col-md-6{width:50%;} .col-md-5{width:41.66666666666667%;} .col-md-4{width:33.33333333333333%;} .col-md-3{width:25%;} .col-md-2{width:16.666666666666664%;} .col-md-1{width:8.333333333333332%;} .col-md-pull-12{right:100%;} .col-md-pull-11{right:91.66666666666666%;} .col-md-pull-10{right:83.33333333333334%;} .col-md-pull-9{right:75%;} .col-md-pull-8{right:66.66666666666666%;} .col-md-pull-7{right:58.333333333333336%;} .col-md-pull-6{right:50%;} .col-md-pull-5{right:41.66666666666667%;} .col-md-pull-4{right:33.33333333333333%;} .col-md-pull-3{right:25%;} .col-md-pull-2{right:16.666666666666664%;} .col-md-pull-1{right:8.333333333333332%;} .col-md-pull-0{right:0%;} .col-md-push-12{left:100%;} .col-md-push-11{left:91.66666666666666%;} .col-md-push-10{left:83.33333333333334%;} .col-md-push-9{left:75%;} .col-md-push-8{left:66.66666666666666%;} .col-md-push-7{left:58.333333333333336%;} .col-md-push-6{left:50%;} .col-md-push-5{left:41.66666666666667%;} .col-md-push-4{left:33.33333333333333%;} .col-md-push-3{left:25%;} .col-md-push-2{left:16.666666666666664%;} .col-md-push-1{left:8.333333333333332%;} .col-md-push-0{left:0%;} .col-md-offset-12{margin-left:100%;} .col-md-offset-11{margin-left:91.66666666666666%;} .col-md-offset-10{margin-left:83.33333333333334%;} .col-md-offset-9{margin-left:75%;} .col-md-offset-8{margin-left:66.66666666666666%;} .col-md-offset-7{margin-left:58.333333333333336%;} .col-md-offset-6{margin-left:50%;} .col-md-offset-5{margin-left:41.66666666666667%;} .col-md-offset-4{margin-left:33.33333333333333%;} .col-md-offset-3{margin-left:25%;} .col-md-offset-2{margin-left:16.666666666666664%;} .col-md-offset-1{margin-left:8.333333333333332%;} .col-md-offset-0{margin-left:0%;}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left;} .col-lg-12{width:100%;} .col-lg-11{width:91.66666666666666%;} .col-lg-10{width:83.33333333333334%;} .col-lg-9{width:75%;} .col-lg-8{width:66.66666666666666%;} .col-lg-7{width:58.333333333333336%;} .col-lg-6{width:50%;} .col-lg-5{width:41.66666666666667%;} .col-lg-4{width:33.33333333333333%;} .col-lg-3{width:25%;} .col-lg-2{width:16.666666666666664%;} .col-lg-1{width:8.333333333333332%;} .col-lg-pull-12{right:100%;} .col-lg-pull-11{right:91.66666666666666%;} .col-lg-pull-10{right:83.33333333333334%;} .col-lg-pull-9{right:75%;} .col-lg-pull-8{right:66.66666666666666%;} .col-lg-pull-7{right:58.333333333333336%;} .col-lg-pull-6{right:50%;} .col-lg-pull-5{right:41.66666666666667%;} .col-lg-pull-4{right:33.33333333333333%;} .col-lg-pull-3{right:25%;} .col-lg-pull-2{right:16.666666666666664%;} .col-lg-pull-1{right:8.333333333333332%;} .col-lg-pull-0{right:0%;} .col-lg-push-12{left:100%;} .col-lg-push-11{left:91.66666666666666%;} .col-lg-push-10{left:83.33333333333334%;} .col-lg-push-9{left:75%;} .col-lg-push-8{left:66.66666666666666%;} .col-lg-push-7{left:58.333333333333336%;} .col-lg-push-6{left:50%;} .col-lg-push-5{left:41.66666666666667%;} .col-lg-push-4{left:33.33333333333333%;} .col-lg-push-3{left:25%;} .col-lg-push-2{left:16.666666666666664%;} .col-lg-push-1{left:8.333333333333332%;} .col-lg-push-0{left:0%;} .col-lg-offset-12{margin-left:100%;} .col-lg-offset-11{margin-left:91.66666666666666%;} .col-lg-offset-10{margin-left:83.33333333333334%;} .col-lg-offset-9{margin-left:75%;} .col-lg-offset-8{margin-left:66.66666666666666%;} .col-lg-offset-7{margin-left:58.333333333333336%;} .col-lg-offset-6{margin-left:50%;} .col-lg-offset-5{margin-left:41.66666666666667%;} .col-lg-offset-4{margin-left:33.33333333333333%;} .col-lg-offset-3{margin-left:25%;} .col-lg-offset-2{margin-left:16.666666666666664%;} .col-lg-offset-1{margin-left:8.333333333333332%;} .col-lg-offset-0{margin-left:0%;}}table{max-width:100%;background-color:transparent;}th{text-align:left;}.table{width:100%;margin-bottom:20px;}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #dddddd;}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #dddddd;}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0;}.table>tbody+tbody{border-top:2px solid #dddddd;}.table .table{background-color:#ffffff;}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px;}.table-bordered{border:1px solid #dddddd;}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #dddddd;}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px;}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9;}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5;}table col[class*="col-"]{position:static;float:none;display:table-column;}table td[class*="col-"],table th[class*="col-"]{float:none;display:table-cell;}.table>thead>tr>.active,.table>tbody>tr>.active,.table>tfoot>tr>.active,.table>thead>.active>td,.table>tbody>.active>td,.table>tfoot>.active>td,.table>thead>.active>th,.table>tbody>.active>th,.table>tfoot>.active>th{background-color:#f5f5f5;}.table-hover>tbody>tr>.active:hover,.table-hover>tbody>.active:hover>td,.table-hover>tbody>.active:hover>th{background-color:#e8e8e8;}.table>thead>tr>.success,.table>tbody>tr>.success,.table>tfoot>tr>.success,.table>thead>.success>td,.table>tbody>.success>td,.table>tfoot>.success>td,.table>thead>.success>th,.table>tbody>.success>th,.table>tfoot>.success>th{background-color:#dff0d8;}.table-hover>tbody>tr>.success:hover,.table-hover>tbody>.success:hover>td,.table-hover>tbody>.success:hover>th{background-color:#d0e9c6;}.table>thead>tr>.danger,.table>tbody>tr>.danger,.table>tfoot>tr>.danger,.table>thead>.danger>td,.table>tbody>.danger>td,.table>tfoot>.danger>td,.table>thead>.danger>th,.table>tbody>.danger>th,.table>tfoot>.danger>th{background-color:#f2dede;}.table-hover>tbody>tr>.danger:hover,.table-hover>tbody>.danger:hover>td,.table-hover>tbody>.danger:hover>th{background-color:#ebcccc;}.table>thead>tr>.warning,.table>tbody>tr>.warning,.table>tfoot>tr>.warning,.table>thead>.warning>td,.table>tbody>.warning>td,.table>tfoot>.warning>td,.table>thead>.warning>th,.table>tbody>.warning>th,.table>tfoot>.warning>th{background-color:#fcf8e3;}.table-hover>tbody>tr>.warning:hover,.table-hover>tbody>.warning:hover>td,.table-hover>tbody>.warning:hover>th{background-color:#faf2cc;}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #dddddd;-webkit-overflow-scrolling:touch;}.table-responsive>.table{margin-bottom:0;}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap;} .table-responsive>.table-bordered{border:0;}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0;} .table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0;} .table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0;}}fieldset{padding:0;margin:0;border:0;}label{display:inline-block;margin-bottom:5px;font-weight:bold;}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal;}select[multiple],select[size]{height:auto;}select optgroup{font-size:inherit;font-style:inherit;font-family:inherit;}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto;}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555555;vertical-align:middle;}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555555;vertical-align:middle;background-color:#ffffff;background-image:none;border:1px solid #cccccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);}.form-control:-moz-placeholder{color:#999999;}.form-control::-moz-placeholder{color:#999999;opacity:1;}.form-control:-ms-input-placeholder{color:#999999;}.form-control::-webkit-input-placeholder{color:#999999;}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eeeeee;}textarea.form-control{height:auto;}.form-group{margin-bottom:15px;}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px;vertical-align:middle;}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer;}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px;}.radio+.radio,.checkbox+.checkbox{margin-top:-5px;}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer;}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px;}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed;}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px;}select.input-sm{height:30px;line-height:30px;}textarea.input-sm{height:auto;}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px;}select.input-lg{height:46px;line-height:46px;}textarea.input-lg{height:auto;}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b;}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #c0a16b;}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3;}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442;}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ce8483;}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede;}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d;}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #67b168;}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8;}.form-control-static{margin-bottom:0;}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373;}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle;} .form-inline .form-control{display:inline-block;} .form-inline select.form-control{width:auto;} .form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;} .form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0;}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px;}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px;}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px;}.form-horizontal .form-group:before,.form-horizontal .form-group:after{content:" ";display:table;}.form-horizontal .form-group:after{clear:both;}.form-horizontal .form-group:before,.form-horizontal .form-group:after{content:" ";display:table;}.form-horizontal .form-group:after{clear:both;}.form-horizontal .form-control-static{padding-top:7px;}@media (min-width:768px){.form-horizontal .control-label{text-align:right;}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.428571429;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;}.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}.btn:hover,.btn:focus{color:#333333;text-decoration:none;}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;}.btn-default{color:#333333;background-color:#ffffff;border-color:#cccccc;}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333333;background-color:#ebebeb;border-color:#adadad;}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none;}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#ffffff;border-color:#cccccc;}.btn-default .badge{color:#ffffff;background-color:#fff;}.btn-primary{color:#ffffff;background-color:#428bca;border-color:#357ebd;}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#ffffff;background-color:#3276b1;border-color:#285e8e;}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none;}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd;}.btn-primary .badge{color:#428bca;background-color:#fff;}.btn-warning{color:#ffffff;background-color:#f0ad4e;border-color:#eea236;}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#ffffff;background-color:#ed9c28;border-color:#d58512;}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none;}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236;}.btn-warning .badge{color:#f0ad4e;background-color:#fff;}.btn-danger{color:#ffffff;background-color:#d9534f;border-color:#d43f3a;}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#ffffff;background-color:#d2322d;border-color:#ac2925;}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none;}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a;}.btn-danger .badge{color:#d9534f;background-color:#fff;}.btn-success{color:#ffffff;background-color:#5cb85c;border-color:#4cae4c;}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#ffffff;background-color:#47a447;border-color:#398439;}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none;}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c;}.btn-success .badge{color:#5cb85c;background-color:#fff;}.btn-info{color:#ffffff;background-color:#5bc0de;border-color:#46b8da;}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#ffffff;background-color:#39b3d7;border-color:#269abc;}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none;}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da;}.btn-info .badge{color:#5bc0de;background-color:#fff;}.btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0;}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none;}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent;}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent;}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999999;text-decoration:none;}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px;}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px;}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px;}.btn-block{display:block;width:100%;padding-left:0;padding-right:0;}.btn-block+.btn-block{margin-top:5px;}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%;}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}.glyphicon:empty{width:1em;}.glyphicon-asterisk:before{content:"\2a";}.glyphicon-plus:before{content:"\2b";}.glyphicon-euro:before{content:"\20ac";}.glyphicon-minus:before{content:"\2212";}.glyphicon-cloud:before{content:"\2601";}.glyphicon-envelope:before{content:"\2709";}.glyphicon-pencil:before{content:"\270f";}.glyphicon-glass:before{content:"\e001";}.glyphicon-music:before{content:"\e002";}.glyphicon-search:before{content:"\e003";}.glyphicon-heart:before{content:"\e005";}.glyphicon-star:before{content:"\e006";}.glyphicon-star-empty:before{content:"\e007";}.glyphicon-user:before{content:"\e008";}.glyphicon-film:before{content:"\e009";}.glyphicon-th-large:before{content:"\e010";}.glyphicon-th:before{content:"\e011";}.glyphicon-th-list:before{content:"\e012";}.glyphicon-ok:before{content:"\e013";}.glyphicon-remove:before{content:"\e014";}.glyphicon-zoom-in:before{content:"\e015";}.glyphicon-zoom-out:before{content:"\e016";}.glyphicon-off:before{content:"\e017";}.glyphicon-signal:before{content:"\e018";}.glyphicon-cog:before{content:"\e019";}.glyphicon-trash:before{content:"\e020";}.glyphicon-home:before{content:"\e021";}.glyphicon-file:before{content:"\e022";}.glyphicon-time:before{content:"\e023";}.glyphicon-road:before{content:"\e024";}.glyphicon-download-alt:before{content:"\e025";}.glyphicon-download:before{content:"\e026";}.glyphicon-upload:before{content:"\e027";}.glyphicon-inbox:before{content:"\e028";}.glyphicon-play-circle:before{content:"\e029";}.glyphicon-repeat:before{content:"\e030";}.glyphicon-refresh:before{content:"\e031";}.glyphicon-list-alt:before{content:"\e032";}.glyphicon-lock:before{content:"\e033";}.glyphicon-flag:before{content:"\e034";}.glyphicon-headphones:before{content:"\e035";}.glyphicon-volume-off:before{content:"\e036";}.glyphicon-volume-down:before{content:"\e037";}.glyphicon-volume-up:before{content:"\e038";}.glyphicon-qrcode:before{content:"\e039";}.glyphicon-barcode:before{content:"\e040";}.glyphicon-tag:before{content:"\e041";}.glyphicon-tags:before{content:"\e042";}.glyphicon-book:before{content:"\e043";}.glyphicon-bookmark:before{content:"\e044";}.glyphicon-print:before{content:"\e045";}.glyphicon-camera:before{content:"\e046";}.glyphicon-font:before{content:"\e047";}.glyphicon-bold:before{content:"\e048";}.glyphicon-italic:before{content:"\e049";}.glyphicon-text-height:before{content:"\e050";}.glyphicon-text-width:before{content:"\e051";}.glyphicon-align-left:before{content:"\e052";}.glyphicon-align-center:before{content:"\e053";}.glyphicon-align-right:before{content:"\e054";}.glyphicon-align-justify:before{content:"\e055";}.glyphicon-list:before{content:"\e056";}.glyphicon-indent-left:before{content:"\e057";}.glyphicon-indent-right:before{content:"\e058";}.glyphicon-facetime-video:before{content:"\e059";}.glyphicon-picture:before{content:"\e060";}.glyphicon-map-marker:before{content:"\e062";}.glyphicon-adjust:before{content:"\e063";}.glyphicon-tint:before{content:"\e064";}.glyphicon-edit:before{content:"\e065";}.glyphicon-share:before{content:"\e066";}.glyphicon-check:before{content:"\e067";}.glyphicon-move:before{content:"\e068";}.glyphicon-step-backward:before{content:"\e069";}.glyphicon-fast-backward:before{content:"\e070";}.glyphicon-backward:before{content:"\e071";}.glyphicon-play:before{content:"\e072";}.glyphicon-pause:before{content:"\e073";}.glyphicon-stop:before{content:"\e074";}.glyphicon-forward:before{content:"\e075";}.glyphicon-fast-forward:before{content:"\e076";}.glyphicon-step-forward:before{content:"\e077";}.glyphicon-eject:before{content:"\e078";}.glyphicon-chevron-left:before{content:"\e079";}.glyphicon-chevron-right:before{content:"\e080";}.glyphicon-plus-sign:before{content:"\e081";}.glyphicon-minus-sign:before{content:"\e082";}.glyphicon-remove-sign:before{content:"\e083";}.glyphicon-ok-sign:before{content:"\e084";}.glyphicon-question-sign:before{content:"\e085";}.glyphicon-info-sign:before{content:"\e086";}.glyphicon-screenshot:before{content:"\e087";}.glyphicon-remove-circle:before{content:"\e088";}.glyphicon-ok-circle:before{content:"\e089";}.glyphicon-ban-circle:before{content:"\e090";}.glyphicon-arrow-left:before{content:"\e091";}.glyphicon-arrow-right:before{content:"\e092";}.glyphicon-arrow-up:before{content:"\e093";}.glyphicon-arrow-down:before{content:"\e094";}.glyphicon-share-alt:before{content:"\e095";}.glyphicon-resize-full:before{content:"\e096";}.glyphicon-resize-small:before{content:"\e097";}.glyphicon-exclamation-sign:before{content:"\e101";}.glyphicon-gift:before{content:"\e102";}.glyphicon-leaf:before{content:"\e103";}.glyphicon-fire:before{content:"\e104";}.glyphicon-eye-open:before{content:"\e105";}.glyphicon-eye-close:before{content:"\e106";}.glyphicon-warning-sign:before{content:"\e107";}.glyphicon-plane:before{content:"\e108";}.glyphicon-calendar:before{content:"\e109";}.glyphicon-random:before{content:"\e110";}.glyphicon-comment:before{content:"\e111";}.glyphicon-magnet:before{content:"\e112";}.glyphicon-chevron-up:before{content:"\e113";}.glyphicon-chevron-down:before{content:"\e114";}.glyphicon-retweet:before{content:"\e115";}.glyphicon-shopping-cart:before{content:"\e116";}.glyphicon-folder-close:before{content:"\e117";}.glyphicon-folder-open:before{content:"\e118";}.glyphicon-resize-vertical:before{content:"\e119";}.glyphicon-resize-horizontal:before{content:"\e120";}.glyphicon-hdd:before{content:"\e121";}.glyphicon-bullhorn:before{content:"\e122";}.glyphicon-bell:before{content:"\e123";}.glyphicon-certificate:before{content:"\e124";}.glyphicon-thumbs-up:before{content:"\e125";}.glyphicon-thumbs-down:before{content:"\e126";}.glyphicon-hand-right:before{content:"\e127";}.glyphicon-hand-left:before{content:"\e128";}.glyphicon-hand-up:before{content:"\e129";}.glyphicon-hand-down:before{content:"\e130";}.glyphicon-circle-arrow-right:before{content:"\e131";}.glyphicon-circle-arrow-left:before{content:"\e132";}.glyphicon-circle-arrow-up:before{content:"\e133";}.glyphicon-circle-arrow-down:before{content:"\e134";}.glyphicon-globe:before{content:"\e135";}.glyphicon-wrench:before{content:"\e136";}.glyphicon-tasks:before{content:"\e137";}.glyphicon-filter:before{content:"\e138";}.glyphicon-briefcase:before{content:"\e139";}.glyphicon-fullscreen:before{content:"\e140";}.glyphicon-dashboard:before{content:"\e141";}.glyphicon-paperclip:before{content:"\e142";}.glyphicon-heart-empty:before{content:"\e143";}.glyphicon-link:before{content:"\e144";}.glyphicon-phone:before{content:"\e145";}.glyphicon-pushpin:before{content:"\e146";}.glyphicon-usd:before{content:"\e148";}.glyphicon-gbp:before{content:"\e149";}.glyphicon-sort:before{content:"\e150";}.glyphicon-sort-by-alphabet:before{content:"\e151";}.glyphicon-sort-by-alphabet-alt:before{content:"\e152";}.glyphicon-sort-by-order:before{content:"\e153";}.glyphicon-sort-by-order-alt:before{content:"\e154";}.glyphicon-sort-by-attributes:before{content:"\e155";}.glyphicon-sort-by-attributes-alt:before{content:"\e156";}.glyphicon-unchecked:before{content:"\e157";}.glyphicon-expand:before{content:"\e158";}.glyphicon-collapse-down:before{content:"\e159";}.glyphicon-collapse-up:before{content:"\e160";}.glyphicon-log-in:before{content:"\e161";}.glyphicon-flash:before{content:"\e162";}.glyphicon-log-out:before{content:"\e163";}.glyphicon-new-window:before{content:"\e164";}.glyphicon-record:before{content:"\e165";}.glyphicon-save:before{content:"\e166";}.glyphicon-open:before{content:"\e167";}.glyphicon-saved:before{content:"\e168";}.glyphicon-import:before{content:"\e169";}.glyphicon-export:before{content:"\e170";}.glyphicon-send:before{content:"\e171";}.glyphicon-floppy-disk:before{content:"\e172";}.glyphicon-floppy-saved:before{content:"\e173";}.glyphicon-floppy-remove:before{content:"\e174";}.glyphicon-floppy-save:before{content:"\e175";}.glyphicon-floppy-open:before{content:"\e176";}.glyphicon-credit-card:before{content:"\e177";}.glyphicon-transfer:before{content:"\e178";}.glyphicon-cutlery:before{content:"\e179";}.glyphicon-header:before{content:"\e180";}.glyphicon-compressed:before{content:"\e181";}.glyphicon-earphone:before{content:"\e182";}.glyphicon-phone-alt:before{content:"\e183";}.glyphicon-tower:before{content:"\e184";}.glyphicon-stats:before{content:"\e185";}.glyphicon-sd-video:before{content:"\e186";}.glyphicon-hd-video:before{content:"\e187";}.glyphicon-subtitles:before{content:"\e188";}.glyphicon-sound-stereo:before{content:"\e189";}.glyphicon-sound-dolby:before{content:"\e190";}.glyphicon-sound-5-1:before{content:"\e191";}.glyphicon-sound-6-1:before{content:"\e192";}.glyphicon-sound-7-1:before{content:"\e193";}.glyphicon-copyright-mark:before{content:"\e194";}.glyphicon-registration-mark:before{content:"\e195";}.glyphicon-cloud-download:before{content:"\e197";}.glyphicon-cloud-upload:before{content:"\e198";}.glyphicon-tree-conifer:before{content:"\e199";}.glyphicon-tree-deciduous:before{content:"\e200";}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent;}.dropdown{position:relative;}.dropdown-toggle:focus{outline:0;}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#ffffff;border:1px solid #cccccc;border:1px solid rgba(0, 0, 0, 0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0, 0, 0, 0.175);box-shadow:0 6px 12px rgba(0, 0, 0, 0.175);background-clip:padding-box;}.dropdown-menu.pull-right{right:0;left:auto;}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5;}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.428571429;color:#333333;white-space:nowrap;}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5;}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#ffffff;text-decoration:none;outline:0;background-color:#428bca;}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999999;}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed;}.open>.dropdown-menu{display:block;}.open>a{outline:0;}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999999;}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990;}.pull-right>.dropdown-menu{right:0;left:auto;}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:"";}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px;}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto;}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle;}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left;}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2;}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:none;}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px;}.btn-toolbar:before,.btn-toolbar:after{content:" ";display:table;}.btn-toolbar:after{clear:both;}.btn-toolbar:before,.btn-toolbar:after{content:" ";display:table;}.btn-toolbar:after{clear:both;}.btn-toolbar .btn-group{float:left;}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn-group{margin-left:5px;}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0;}.btn-group>.btn:first-child{margin-left:0;}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0;}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;}.btn-group>.btn-group{float:left;}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0;}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0;}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0;}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;}.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px;}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px;}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px;}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px;}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px;}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none;}.btn .caret{margin-left:0;}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0;}.dropup .btn-lg .caret{border-width:0 5px 5px;}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%;}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{content:" ";display:table;}.btn-group-vertical>.btn-group:after{clear:both;}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{content:" ";display:table;}.btn-group-vertical>.btn-group:after{clear:both;}.btn-group-vertical>.btn-group>.btn{float:none;}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0;}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0;}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0;}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0;}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0;}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0;}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0;}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate;}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%;}.btn-group-justified>.btn-group .btn{width:100%;}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none;}.input-group{position:relative;display:table;border-collapse:separate;}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0;}.input-group .form-control{width:100%;margin-bottom:0;}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px;}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px;}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto;}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px;}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px;}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto;}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell;}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0;}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle;}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555555;text-align:center;background-color:#eeeeee;border:1px solid #cccccc;border-radius:4px;}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px;}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px;}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0;}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0;}.input-group-addon:first-child{border-right:0;}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;}.input-group-addon:last-child{border-left:0;}.input-group-btn{position:relative;white-space:nowrap;}.input-group-btn:first-child>.btn{margin-right:-1px;}.input-group-btn:last-child>.btn{margin-left:-1px;}.input-group-btn>.btn{position:relative;}.input-group-btn>.btn+.btn{margin-left:-4px;}.input-group-btn>.btn:hover,.input-group-btn>.btn:active{z-index:2;}.nav{margin-bottom:0;padding-left:0;list-style:none;}.nav:before,.nav:after{content:" ";display:table;}.nav:after{clear:both;}.nav:before,.nav:after{content:" ";display:table;}.nav:after{clear:both;}.nav>li{position:relative;display:block;}.nav>li>a{position:relative;display:block;padding:10px 15px;}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eeeeee;}.nav>li.disabled>a{color:#999999;}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999999;text-decoration:none;background-color:transparent;cursor:not-allowed;}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eeeeee;border-color:#428bca;}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5;}.nav>li>a>img{max-width:none;}.nav-tabs{border-bottom:1px solid #dddddd;}.nav-tabs>li{float:left;margin-bottom:-1px;}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0;}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555555;background-color:#ffffff;border:1px solid #dddddd;border-bottom-color:transparent;cursor:default;}.nav-tabs.nav-justified{width:100%;border-bottom:0;}.nav-tabs.nav-justified>li{float:none;}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px;}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto;}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%;}.nav-tabs.nav-justified>li>a{margin-bottom:0;}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px;}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #dddddd;}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #dddddd;border-radius:4px 4px 0 0;} .nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#ffffff;}}.nav-pills>li{float:left;}.nav-pills>li>a{border-radius:4px;}.nav-pills>li+li{margin-left:2px;}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#ffffff;background-color:#428bca;}.nav-stacked>li{float:none;}.nav-stacked>li+li{margin-top:2px;margin-left:0;}.nav-justified{width:100%;}.nav-justified>li{float:none;}.nav-justified>li>a{text-align:center;margin-bottom:5px;}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto;}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%;}.nav-justified>li>a{margin-bottom:0;}}.nav-tabs-justified{border-bottom:0;}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px;}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #dddddd;}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #dddddd;border-radius:4px 4px 0 0;} .nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#ffffff;}}.tab-content>.tab-pane{display:none;}.tab-content>.active{display:block;}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0;}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent;}.navbar:before,.navbar:after{content:" ";display:table;}.navbar:after{clear:both;}.navbar:before,.navbar:after{content:" ";display:table;}.navbar:after{clear:both;}@media (min-width:768px){.navbar{border-radius:4px;}}.navbar-header:before,.navbar-header:after{content:" ";display:table;}.navbar-header:after{clear:both;}.navbar-header:before,.navbar-header:after{content:" ";display:table;}.navbar-header:after{clear:both;}@media (min-width:768px){.navbar-header{float:left;}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1);-webkit-overflow-scrolling:touch;}.navbar-collapse:before,.navbar-collapse:after{content:" ";display:table;}.navbar-collapse:after{clear:both;}.navbar-collapse:before,.navbar-collapse:after{content:" ";display:table;}.navbar-collapse:after{clear:both;}.navbar-collapse.in{overflow-y:auto;}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none;}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important;} .navbar-collapse.in{overflow-y:visible;} .navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0;}}.container>.navbar-header,.container>.navbar-collapse{margin-right:-15px;margin-left:-15px;}@media (min-width:768px){.container>.navbar-header,.container>.navbar-collapse{margin-right:0;margin-left:0;}}.navbar-static-top{z-index:1000;border-width:0 0 1px;}@media (min-width:768px){.navbar-static-top{border-radius:0;}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0;}}.navbar-fixed-top{top:0;border-width:0 0 1px;}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0;}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none;}@media (min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px;}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px;}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px;}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px;}@media (min-width:768px){.navbar-toggle{display:none;}}.navbar-nav{margin:7.5px -15px;}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px;}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none;}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px;} .navbar-nav .open .dropdown-menu>li>a{line-height:20px;}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none;}}@media (min-width:768px){.navbar-nav{float:left;margin:0;}.navbar-nav>li{float:left;}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px;} .navbar-nav.navbar-right:last-child{margin-right:-15px;}}@media (min-width:768px){.navbar-left{float:left !important;} .navbar-right{float:right !important;}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);margin-top:8px;margin-bottom:8px;}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle;} .navbar-form .form-control{display:inline-block;} .navbar-form select.form-control{width:auto;} .navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;} .navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0;}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px;}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none;}.navbar-form.navbar-right:last-child{margin-right:-15px;}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0;}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0;}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{left:auto;right:0;}.navbar-btn{margin-top:8px;margin-bottom:8px;}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px;}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px;}.navbar-text{margin-top:15px;margin-bottom:15px;}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px;}.navbar-text.navbar-right:last-child{margin-right:0;}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7;}.navbar-default .navbar-brand{color:#777777;}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent;}.navbar-default .navbar-text{color:#777777;}.navbar-default .navbar-nav>li>a{color:#777777;}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333333;background-color:transparent;}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555555;background-color:#e7e7e7;}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#cccccc;background-color:transparent;}.navbar-default .navbar-toggle{border-color:#dddddd;}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#dddddd;}.navbar-default .navbar-toggle .icon-bar{background-color:#cccccc;}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7;}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555555;}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777777;}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333333;background-color:transparent;} .navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555555;background-color:#e7e7e7;} .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#cccccc;background-color:transparent;}}.navbar-default .navbar-link{color:#777777;}.navbar-default .navbar-link:hover{color:#333333;}.navbar-inverse{background-color:#222222;border-color:#080808;}.navbar-inverse .navbar-brand{color:#999999;}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#ffffff;background-color:transparent;}.navbar-inverse .navbar-text{color:#999999;}.navbar-inverse .navbar-nav>li>a{color:#999999;}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#ffffff;background-color:transparent;}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#ffffff;background-color:#080808;}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444444;background-color:transparent;}.navbar-inverse .navbar-toggle{border-color:#333333;}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333333;}.navbar-inverse .navbar-toggle .icon-bar{background-color:#ffffff;}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010;}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#ffffff;}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808;} .navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808;} .navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999999;}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#ffffff;background-color:transparent;} .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#ffffff;background-color:#080808;} .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444444;background-color:transparent;}}.navbar-inverse .navbar-link{color:#999999;}.navbar-inverse .navbar-link:hover{color:#ffffff;}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px;}.breadcrumb>li{display:inline-block;}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#cccccc;}.breadcrumb>.active{color:#999999;}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px;}.pagination>li{display:inline;}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.428571429;text-decoration:none;background-color:#ffffff;border:1px solid #dddddd;margin-left:-1px;}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px;}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px;}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#eeeeee;}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#ffffff;background-color:#428bca;border-color:#428bca;cursor:default;}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999999;background-color:#ffffff;border-color:#dddddd;cursor:not-allowed;}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px;}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px;}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px;}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px;}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center;}.pager:before,.pager:after{content:" ";display:table;}.pager:after{clear:both;}.pager:before,.pager:after{content:" ";display:table;}.pager:after{clear:both;}.pager li{display:inline;}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#ffffff;border:1px solid #dddddd;border-radius:15px;}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eeeeee;}.pager .next>a,.pager .next>span{float:right;}.pager .previous>a,.pager .previous>span{float:left;}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999999;background-color:#ffffff;cursor:not-allowed;}.label[href]:hover,.label[href]:focus{color:#ffffff;text-decoration:none;cursor:pointer;}.label:empty{display:none;}.btn .label{position:relative;top:-1px;}.label-default{background-color:#999999;}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080;}.label-primary{background-color:#428bca;}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9;}.label-success{background-color:#5cb85c;}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44;}.label-info{background-color:#5bc0de;}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5;}.label-warning{background-color:#f0ad4e;}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f;}.label-danger{background-color:#d9534f;}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c;}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#ffffff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999999;border-radius:10px;}.badge:empty{display:none;}.btn .badge{position:relative;top:-1px;}a.badge:hover,a.badge:focus{color:#ffffff;text-decoration:none;cursor:pointer;}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#ffffff;}.nav-pills>li>a>.badge{margin-left:3px;}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eeeeee;}.jumbotron h1,.jumbotron .h1{line-height:1;color:inherit;}.jumbotron p{line-height:1.4;}.container .jumbotron{border-radius:6px;}.jumbotron .container{max-width:100%;}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px;}.container .jumbotron{padding-left:60px;padding-right:60px;} .jumbotron h1,.jumbotron .h1{font-size:63px;}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#ffffff;border:1px solid #dddddd;border-radius:4px;-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;}.thumbnail>img,.thumbnail a>img{display:block;max-width:100%;height:auto;margin-left:auto;margin-right:auto;}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca;}.thumbnail .caption{padding:9px;color:#333333;}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px;}.alert h4{margin-top:0;color:inherit;}.alert .alert-link{font-weight:bold;}.alert>p,.alert>ul{margin-bottom:0;}.alert>p+p{margin-top:5px;}.alert-dismissable{padding-right:35px;}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit;}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d;}.alert-success hr{border-top-color:#c9e2b3;}.alert-success .alert-link{color:#2b542c;}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f;}.alert-info hr{border-top-color:#a6e1ec;}.alert-info .alert-link{color:#245269;}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b;}.alert-warning hr{border-top-color:#f7e1b5;}.alert-warning .alert-link{color:#66512c;}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442;}.alert-danger hr{border-top-color:#e4b9c0;}.alert-danger .alert-link{color:#843534;}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}@keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#ffffff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-transition:width 0.6s ease;transition:width 0.6s ease;}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-size:40px 40px;}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite;}.progress-bar-success{background-color:#5cb85c;}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}.progress-bar-info{background-color:#5bc0de;}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}.progress-bar-warning{background-color:#f0ad4e;}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}.progress-bar-danger{background-color:#d9534f;}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}.media,.media-body{overflow:hidden;zoom:1;}.media,.media .media{margin-top:15px;}.media:first-child{margin-top:0;}.media-object{display:block;}.media-heading{margin:0 0 5px;}.media>.pull-left{margin-right:10px;}.media>.pull-right{margin-left:10px;}.media-list{padding-left:0;list-style:none;}.list-group{margin-bottom:20px;padding-left:0;}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#ffffff;border:1px solid #dddddd;}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px;}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px;}.list-group-item>.badge{float:right;}.list-group-item>.badge+.badge{margin-right:5px;}a.list-group-item{color:#555555;}a.list-group-item .list-group-item-heading{color:#333333;}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5;}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#ffffff;background-color:#428bca;border-color:#428bca;}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit;}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7;}.list-group-item-heading{margin-top:0;margin-bottom:5px;}.list-group-item-text{margin-bottom:0;line-height:1.3;}.panel{margin-bottom:20px;background-color:#ffffff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:0 1px 1px rgba(0, 0, 0, 0.05);}.panel-body{padding:15px;}.panel-body:before,.panel-body:after{content:" ";display:table;}.panel-body:after{clear:both;}.panel-body:before,.panel-body:after{content:" ";display:table;}.panel-body:after{clear:both;}.panel>.list-group{margin-bottom:0;}.panel>.list-group .list-group-item{border-width:1px 0;}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0;}.panel>.list-group .list-group-item:last-child{border-bottom:0;}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0;}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0;}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #dddddd;}.panel>.table>tbody:first-child th,.panel>.table>tbody:first-child td{border-top:0;}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0;}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0;}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0;}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0;}.panel>.table-responsive{border:0;margin-bottom:0;}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px;}.panel-heading>.dropdown .dropdown-toggle{color:inherit;}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit;}.panel-title>a{color:inherit;}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #dddddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px;}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden;}.panel-group .panel+.panel{margin-top:5px;}.panel-group .panel-heading{border-bottom:0;}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #dddddd;}.panel-group .panel-footer{border-top:0;}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #dddddd;}.panel-default{border-color:#dddddd;}.panel-default>.panel-heading{color:#333333;background-color:#f5f5f5;border-color:#dddddd;}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#dddddd;}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#dddddd;}.panel-primary{border-color:#428bca;}.panel-primary>.panel-heading{color:#ffffff;background-color:#428bca;border-color:#428bca;}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca;}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca;}.panel-success{border-color:#d6e9c6;}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6;}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6;}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6;}.panel-warning{border-color:#faebcc;}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc;}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc;}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc;}.panel-danger{border-color:#ebccd1;}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1;}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1;}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1;}.panel-info{border-color:#bce8f1;}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1;}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1;}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1;}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);}.well-lg{padding:24px;border-radius:6px;}.well-sm{padding:9px;border-radius:3px;}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000000;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20);}.close:hover,.close:focus{color:#000000;text-decoration:none;cursor:pointer;opacity:0.5;filter:alpha(opacity=50);}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none;}.modal-open{overflow:hidden;}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out;}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);transform:translate(0, 0);}.modal-dialog{position:relative;width:auto;margin:10px;z-index:1050;}.modal-content{position:relative;background-color:#ffffff;border:1px solid #999999;border:1px solid rgba(0, 0, 0, 0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0, 0, 0, 0.5);box-shadow:0 3px 9px rgba(0, 0, 0, 0.5);background-clip:padding-box;outline:none;}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000000;}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0);}.modal-backdrop.in{opacity:0.5;filter:alpha(opacity=50);}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.428571429px;}.modal-header .close{margin-top:-2px;}.modal-title{margin:0;line-height:1.428571429;}.modal-body{position:relative;padding:20px;}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5;}.modal-footer:before,.modal-footer:after{content:" ";display:table;}.modal-footer:after{clear:both;}.modal-footer:before,.modal-footer:after{content:" ";display:table;}.modal-footer:after{clear:both;}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0;}.modal-footer .btn-group .btn+.btn{margin-left:-1px;}.modal-footer .btn-block+.btn-block{margin-left:0;}@media screen and (min-width:768px){.modal-dialog{width:600px;margin:30px auto;} .modal-content{-webkit-box-shadow:0 5px 15px rgba(0, 0, 0, 0.5);box-shadow:0 5px 15px rgba(0, 0, 0, 0.5);}}.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:0.9;filter:alpha(opacity=90);}.tooltip.top{margin-top:-3px;padding:5px 0;}.tooltip.right{margin-left:3px;padding:0 5px;}.tooltip.bottom{margin-top:3px;padding:5px 0;}.tooltip.left{margin-left:-3px;padding:0 5px;}.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;border-radius:4px;}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid;}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000000;}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000000;}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000000;}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000;}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000;}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000;}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000000;}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000000;}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#ffffff;background-clip:padding-box;border:1px solid #cccccc;border:1px solid rgba(0, 0, 0, 0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);white-space:normal;}.popover.top{margin-top:-10px;}.popover.right{margin-left:10px;}.popover.bottom{margin-top:10px;}.popover.left{margin-left:-10px;}.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0;}.popover-content{padding:9px 14px;}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid;}.popover .arrow{border-width:11px;}.popover .arrow:after{border-width:10px;content:"";}.popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999999;border-top-color:rgba(0, 0, 0, 0.25);bottom:-11px;}.popover.top .arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#ffffff;}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999999;border-right-color:rgba(0, 0, 0, 0.25);}.popover.right .arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#ffffff;}.popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999999;border-bottom-color:rgba(0, 0, 0, 0.25);top:-11px;}.popover.bottom .arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#ffffff;}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999999;border-left-color:rgba(0, 0, 0, 0.25);}.popover.left .arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#ffffff;bottom:-10px;}.clearfix:before,.clearfix:after{content:" ";display:table;}.clearfix:after{clear:both;}.center-block{display:block;margin-left:auto;margin-right:auto;}.pull-right{float:right !important;}.pull-left{float:left !important;}.hide{display:none !important;}.show{display:block !important;}.invisible{visibility:hidden;}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;}.hidden{display:none !important;visibility:hidden !important;}.affix{position:fixed;}
\ No newline at end of file diff --git a/app/assets/stylesheets/plugins/formtastic.css.scss b/app/assets/stylesheets/plugins/formtastic.css.scss new file mode 100644 index 000000000..bded68974 --- /dev/null +++ b/app/assets/stylesheets/plugins/formtastic.css.scss @@ -0,0 +1,34 @@ +fieldset.inputs { + + li.number input { width: 100px; } + li.string input { width: 500px; } + + fieldset.inputs{ + border: 2px groove threedface; + margin-bottom: 20px; + padding: 10px; + + legend span{ + font-weight: bold; + padding: 5px; + } + + li.special { + display: inline-block; + width: 40%; + + label.label { + width: 60%; + margin-right: 10px; + } + + input { + width: 20%; + } + + } + + a.action { float: right; } + + } +}
\ No newline at end of file diff --git a/app/assets/stylesheets/plugins/tipsy.css b/app/assets/stylesheets/plugins/tipsy.css new file mode 100644 index 000000000..f170fb710 --- /dev/null +++ b/app/assets/stylesheets/plugins/tipsy.css @@ -0,0 +1,25 @@ +.tipsy { font-size: 10px; position: absolute; padding: 5px; z-index: 100000; } + .tipsy-inner { background-color: #000; color: #FFF; max-width: 200px; padding: 5px 8px 4px 8px; text-align: center; } + + /* Rounded corners */ + .tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; } + + /* Uncomment for shadow */ + /*.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }*/ + + .tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; } + + /* Rules to colour arrows */ + .tipsy-arrow-n { border-bottom-color: #000; } + .tipsy-arrow-s { border-top-color: #000; } + .tipsy-arrow-e { border-left-color: #000; } + .tipsy-arrow-w { border-right-color: #000; } + + .tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; } + .tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} + .tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} + .tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } + .tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } + .tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } + .tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; } + .tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; } diff --git a/app/assets/stylesheets/referentials.css.scss b/app/assets/stylesheets/referentials.css.scss index 53200bf56..e7874711f 100644 --- a/app/assets/stylesheets/referentials.css.scss +++ b/app/assets/stylesheets/referentials.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the referentials controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.referentials.index { diff --git a/app/assets/stylesheets/routes.css.scss b/app/assets/stylesheets/routes.css.scss index 756ddadfa..918f7c4fb 100644 --- a/app/assets/stylesheets/routes.css.scss +++ b/app/assets/stylesheets/routes.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the routes controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.lines.show { diff --git a/app/assets/stylesheets/rule_parameter_sets.css.scss b/app/assets/stylesheets/rule_parameter_sets.css.scss new file mode 100644 index 000000000..8f9688d85 --- /dev/null +++ b/app/assets/stylesheets/rule_parameter_sets.css.scss @@ -0,0 +1,96 @@ +// Place all the styles related to the rule_parameter_sets controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ +@import "common/mixins"; + +#workspace.rule_parameter_sets.index +{ + .rule_parameter_set:after { + @include after_div_for_object; + } + + .rule_parameter_sets { + margin-top: 20px; + } + + .rule_parameter_sets:after { + @include content_to_clear; + } + + .rule_parameter_set { + @include div_for_object; + + /* to create multi-column index */ + width: 350px; + float: left; + padding-right: 10px; + position: relative; + + .color { + background-color: white; + width: 64px; + height: 64px; + float: left; + margin-right: 10px; + border: 1px solid #999; + + a { + text-decoration: none; + } + } + + .number { + font-size: 16px; + text-align: center; + font-weight: bold; + padding-top: 21px; + } + .name a { + display: inline; + } + } +} + +#workspace.rule_parameter_sets.show, #workspace.compliance_check_tasks.rule_parameter_set +{ + .summary label { + font-weight: bold; + } + + div.attributes_group { + margin: 15px 0 15px 0; + + .title { font-weight: bold; } + + .columns{ + margin-left: 10px; + + div { + display: inline-block; + + &.two_columns { width: 45%; } + &.three_columns { width: 30%; } + &.four_columns { width: 23%; } + + label { + color: #616161; + } + + .value { margin-left: 5px; } + } + } + } + + div.rule_parameter_by_mode { + margin: 20px 0 0 0 !important; + + .mode_specific { + display: none; + margin: 0 0 0 10px; + + p label { color: #616161; } + } + } +} + + diff --git a/app/assets/stylesheets/stop_areas.css.scss b/app/assets/stylesheets/stop_areas.css.scss index 3c0fd0479..8e5dc8fd9 100644 --- a/app/assets/stylesheets/stop_areas.css.scss +++ b/app/assets/stylesheets/stop_areas.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.stop_areas.index { diff --git a/app/assets/stylesheets/stop_points.css.scss b/app/assets/stylesheets/stop_points.css.scss index 939ac1070..6f1ea505a 100644 --- a/app/assets/stylesheets/stop_points.css.scss +++ b/app/assets/stylesheets/stop_points.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.stop_points.index { diff --git a/app/assets/stylesheets/subscriptions.css.scss b/app/assets/stylesheets/subscriptions.css.scss index ca94fd80a..e1877cb69 100644 --- a/app/assets/stylesheets/subscriptions.css.scss +++ b/app/assets/stylesheets/subscriptions.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.subscriptions.create, #workspace.subscriptions.new { diff --git a/app/assets/stylesheets/time_tables.css.scss b/app/assets/stylesheets/time_tables.css.scss index f1ff7b3d2..ddd27b691 100644 --- a/app/assets/stylesheets/time_tables.css.scss +++ b/app/assets/stylesheets/time_tables.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.time_tables.index { diff --git a/app/assets/stylesheets/users.css.scss b/app/assets/stylesheets/users.css.scss index e0fef9e5c..4ae0571ea 100644 --- a/app/assets/stylesheets/users.css.scss +++ b/app/assets/stylesheets/users.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the lines controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.users.edit, #workspace.lines.new { diff --git a/app/assets/stylesheets/vehicle_journeys.css.scss b/app/assets/stylesheets/vehicle_journeys.css.scss index 76d78dd39..f11c6c1db 100644 --- a/app/assets/stylesheets/vehicle_journeys.css.scss +++ b/app/assets/stylesheets/vehicle_journeys.css.scss @@ -1,7 +1,7 @@ // Place all the styles related to the routes controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "common"; +@import "common/mixins"; #workspace.vehicle_journeys.edit, #workspace.vehicle_journeys.update, #workspace.vehicle_journeys.create, #workspace.vehicle_journeys.new { diff --git a/app/controllers/compliance_check_results_controller.rb b/app/controllers/compliance_check_results_controller.rb new file mode 100644 index 000000000..a4ef40509 --- /dev/null +++ b/app/controllers/compliance_check_results_controller.rb @@ -0,0 +1,22 @@ +class ComplianceCheckResultsController < ChouetteController + respond_to :json + respond_to :js, :only => :index + belongs_to :compliance_check_task + + def index + index! do |format| + format.html { render :layout => false } + end + end + + def collection + wheres = [:status, :severity].map{|key| params.has_key?(key) ? {key => params[key]} : {} }\ + .inject({}){|hash, injected| hash.merge!(injected)} + @compliance_check_results ||= end_of_association_chain.where(wheres).order(:rule_code) + end + + def rule_parameter_set + @rule_parameter_set = RuleParameterSet.new.tap { |rps| rps.parameters = resource.parameter_set } + end + +end diff --git a/app/controllers/compliance_check_tasks_controller.rb b/app/controllers/compliance_check_tasks_controller.rb new file mode 100644 index 000000000..45794199a --- /dev/null +++ b/app/controllers/compliance_check_tasks_controller.rb @@ -0,0 +1,41 @@ +class ComplianceCheckTasksController < ChouetteController + respond_to :html, :js + belongs_to :referential + + def references + @references = referential.send(params[:type]).where("name ilike ?", "%#{params[:q]}%") + respond_to do |format| + format.json do + render json: @references.collect { |child| { id: child.id, name: child.name } } + end + end + end + + def rule_parameter_set + @rule_parameter_set = compliance_check_task.rule_parameter_set_archived + render "rule_parameter_sets/show" + end + + protected + + alias_method :compliance_check_task, :resource + + def create_resource( object ) + if object.save + object.delayed_validate + end + end + + def build_resource + super.tap do |export| + compliance_check_task.assign_attributes referential_id: @referential.id, + user_id: current_user.id, + user_name: current_user.name + end + end + + def collection + @compliance_check_tasks ||= end_of_association_chain.order('created_at DESC').paginate(page: params[:page]) + end + +end diff --git a/app/controllers/exports_controller.rb b/app/controllers/exports_controller.rb index 3b8fee566..2f14ab359 100644 --- a/app/controllers/exports_controller.rb +++ b/app/controllers/exports_controller.rb @@ -26,9 +26,9 @@ class ExportsController < ChouetteController def references @references = referential.send(params[:type]).where("name ilike ?", "%#{params[:q]}%") - respond_to do |format| + respond_to do |format| format.json do - render :json => @references.collect { |child| { :id => child.id, :name => child.name } } + render :json => @references.collect { |child| { :id => child.id, :name => child.name } } end end end @@ -53,7 +53,7 @@ class ExportsController < ChouetteController end def collection - @exports ||= end_of_association_chain.paginate(:page => params[:page]) + @exports ||= end_of_association_chain.order('created_at DESC').paginate(:page => params[:page]) end end diff --git a/app/controllers/file_validations_controller.rb b/app/controllers/file_validations_controller.rb deleted file mode 100644 index 274d11f9f..000000000 --- a/app/controllers/file_validations_controller.rb +++ /dev/null @@ -1,45 +0,0 @@ -class FileValidationsController < InheritedResources::Base - respond_to :html, :xml, :json - - def index - no_referential - index! - end - - def show - no_referential - @toc = TestSheetPage.find("toc") - show! - end - - def new - no_referential - @toc = TestSheetPage.find("toc") - new! - end - - def create - no_referential - create! do |success, failure| - success.html { redirect_to file_validations_path } - end - end - - - protected - def no_referential - Apartment::Database.switch("public") - end - - def resource - @file_validation ||= current_organisation.file_validations.find_by_id(params[:id]) - end - def collection - @file_validations ||= current_organisation.file_validations.paginate(:page => params[:page]) - end - def create_resource(file_validation) - file_validation.organisation = current_organisation - super - end - -end diff --git a/app/controllers/import_tasks_controller.rb b/app/controllers/import_tasks_controller.rb new file mode 100644 index 000000000..36710bb69 --- /dev/null +++ b/app/controllers/import_tasks_controller.rb @@ -0,0 +1,67 @@ +class ImportTasksController < ChouetteController + respond_to :html, :xml, :json + respond_to :js, :only => :show + belongs_to :referential + + def new + new! do + available_imports + end + end + + def show + show! do + if import_task.completed? + @files_stats = import_task.result["files"]["stats"] + @files_list = import_task.result["files"]["list"] + @lines_stats = import_task.result["lines"]["stats"] + @lines_list = import_task.result["lines"]["list"] + end + end + end + + def file_to_import + send_file import_task.file_path, :type => "application/#{import_task.file_path_extension}", :disposition => "attachment" + end + + def create + create! do |success, failure| + available_imports + success.html { redirect_to referential_import_tasks_path(@referential) } + end + end + + protected + + def create_resource( import ) + if import_task.save + import_task.delayed_import + end + end + + alias_method :import_task, :resource + + def available_imports + @available_imports ||= ImportTask.formats.collect do |format| + unless @import_task.format == format + @referential.import_tasks.build :format => format + else + @import_task + end + end + end + + # FIXME why #resource_id is nil ?? + def build_resource + super.tap do |import_task| + import_task.referential_id = @referential.id + import_task.user_id = current_user.id + import_task.user_name = current_user.name + end + end + + def collection + @import_tasks ||= end_of_association_chain.order('created_at DESC').paginate(:page => params[:page]) + end + +end diff --git a/app/controllers/imports_controller.rb b/app/controllers/imports_controller.rb deleted file mode 100644 index 31af06c7d..000000000 --- a/app/controllers/imports_controller.rb +++ /dev/null @@ -1,47 +0,0 @@ -class ImportsController < ChouetteController - respond_to :html, :xml, :json - belongs_to :referential - - def new - new! do - available_imports - end - end - - def create - create! do |success, failure| - available_imports - success.html { redirect_to referential_imports_path(@referential) } - end - end - - def create_resource( import ) - if import.save - import.delayed_import - end - end - - protected - - def available_imports - @available_imports ||= Import.types.collect do |type| - unless @import.type == type - @referential.imports.build :type => type - else - @import - end - end - end - - # FIXME why #resource_id is nil ?? - def build_resource - super.tap do |import| - import.referential_id = @referential.id - end - end - - def collection - @imports ||= end_of_association_chain.paginate(:page => params[:page]) - end - -end diff --git a/app/controllers/referentials_controller.rb b/app/controllers/referentials_controller.rb index 447c48bc3..de0b209ca 100644 --- a/app/controllers/referentials_controller.rb +++ b/app/controllers/referentials_controller.rb @@ -2,8 +2,8 @@ class ReferentialsController < InheritedResources::Base respond_to :html respond_to :json, :only => :show respond_to :js, :only => :show - - def show + + def show resource.switch show! do |format| format.json { @@ -15,17 +15,23 @@ class ReferentialsController < InheritedResources::Base } end end - + protected def resource @referential ||= current_organisation.referentials.find_by_id(params[:id]) end - def collection + def collection @referentials ||= current_organisation.referentials end + def build_resource + super.tap do |referential| + referential.user_id = current_user.id + referential.user_name = current_user.name + end + end def create_resource(referential) referential.organisation = current_organisation super end - + end diff --git a/app/controllers/rule_parameter_sets_controller.rb b/app/controllers/rule_parameter_sets_controller.rb new file mode 100644 index 000000000..fbd5281c8 --- /dev/null +++ b/app/controllers/rule_parameter_sets_controller.rb @@ -0,0 +1,25 @@ +class RuleParameterSetsController < ChouetteController + respond_to :html + respond_to :js, :only => [ :mode ] + + belongs_to :referential + + def new + @rule_parameter_set = RuleParameterSet.default( @referential) + new! + end + + def destroy + if @referential.rule_parameter_sets.count == 1 + flash[:alert] = "Suppression impossible, le referentiel doit compter au minimum un jeu de parametre." + redirect_to referential_rule_parameter_sets_path( @referential ) + else + destroy! + end + end + + protected + + alias_method :rule_parameter_set, :resource +end + diff --git a/app/helpers/compliance_check_tasks_helper.rb b/app/helpers/compliance_check_tasks_helper.rb new file mode 100644 index 000000000..3aab59452 --- /dev/null +++ b/app/helpers/compliance_check_tasks_helper.rb @@ -0,0 +1,5 @@ +module ComplianceCheckTasksHelper + + include TypeIdsModelsHelper + +end diff --git a/app/helpers/creation_helper.rb b/app/helpers/creation_helper.rb deleted file mode 100644 index 167f2f01b..000000000 --- a/app/helpers/creation_helper.rb +++ /dev/null @@ -1,15 +0,0 @@ -module CreationHelper - - def creation_tag(object) - field_set_tag t("layouts.creation_tag.title") do - content_tag :ul do - [(content_tag :li do - object.human_attribute_name('creation_time') + ' : ' + l(object.creation_time, :format => :short) - end), - (content_tag :li do - object.human_attribute_name('creator_id') + ' : ' + object.creator_id if object.creator_id - end)].join.html_safe - end - end - end -end diff --git a/app/helpers/exports_helper.rb b/app/helpers/exports_helper.rb index cd177b424..1ae59c190 100644 --- a/app/helpers/exports_helper.rb +++ b/app/helpers/exports_helper.rb @@ -10,76 +10,6 @@ module ExportsHelper end end - @@export_references_type = {} - def export_references_type(type) - @@export_references_type[type] ||= ReferencesTypeHelper.new(type) - end - - class ReferencesTypeHelper - - attr_accessor :type - - def initialize(type) - @type = type.to_s - end - - def relation_name - Export.references_relation(type) - end - - def input_id - "export_reference_#{relation_name}_ids" - end - - def input_class - "export_#{relation_name}_reference_ids" - end - - end - - def export_references_input(form, export, type) - ReferencesInput.new form, export, export_references_type(type) - end - - class ReferencesInput - - attr_accessor :form, :export, :type_helper - def initialize(form, export, type_helper) - @form, @export, @type_helper = form, export, type_helper - end - - delegate :input_id, :type, :input_class, :to => :type_helper - - def current? - export.references_type == type - end - - def references_map - references.collect { |child| { :id => child.id, :name => child.name } } - end - - def wrapper_html_options - { - :class => "export_reference_ids", - :id => "#{input_id}_input", - :"data-type" => type, - :style => ("display: none" unless current?) - } - end - - def input_html_options - { - :id => input_id, - :class => input_class, - :"data-pre" => ( references_map.to_json if current? ), - :disabled => (true unless current?) - } - end - - def input - form.input :reference_ids, :as => :text, :wrapper_html => wrapper_html_options, :input_html => input_html_options - end - - end + include TypeIdsModelsHelper end diff --git a/app/helpers/flash_helper.rb b/app/helpers/flash_helper.rb new file mode 100644 index 000000000..7f19e0566 --- /dev/null +++ b/app/helpers/flash_helper.rb @@ -0,0 +1,33 @@ +module FlashHelper + + def bootstrap_class_for flash_type + case flash_type + when :success + "alert-success" + when :error + "alert-danger" + when :alert + "alert-warning" + when :notice + "alert-info" + else + flash_type.to_s + end + end + + def flash_message_for(flash_type, message) + case flash_type + when :success + "<i class='fa fa-check-circle'></i> #{message}".html_safe + when :error + "<i class='fa fa-minus-circle'></i> #{message}".html_safe + when :alert + "<i class='fa fa-exclamation-circle'></i> #{message}".html_safe + when :notice + "<i class='fa fa-info-circle'></i> #{message}".html_safe + else + message + end + end + +end diff --git a/app/helpers/history_helper.rb b/app/helpers/history_helper.rb new file mode 100644 index 000000000..a4f2df05c --- /dev/null +++ b/app/helpers/history_helper.rb @@ -0,0 +1,43 @@ +module HistoryHelper + + def creation_tag(object) + field_set_tag t("layouts.creation_tag.title") do + content_tag :ul do + [(content_tag :li do + if object.has_attribute?(:creation_time) + object.human_attribute_name('creation_time') + ' : ' + l(object.creation_time, :format => :short) + else + object.class.human_attribute_name('created_at') + ' : ' + l(object.created_at, :format => :short) + end + end), + (content_tag :li do + if object.has_attribute?(:creator_id) + object.human_attribute_name('creator_id') + ' : ' + object.creator_id if object.creator_id + end + end)].join.html_safe + end + end + end + + def history_tag(object) + field_set_tag t("layouts.history_tag.title") do + content_tag :ul do + [(content_tag :li do + if object.has_attribute?(:created_at) + t('layouts.history_tag.created_at') + ' : ' + l(object.created_at, :format => :short) + end + end), + (content_tag :li do + if object.has_attribute?(:updated_at) + t('layouts.history_tag.updated_at') + ' : ' + l(object.updated_at, :format => :short) + end + end), + (content_tag :li do + if object.has_attribute?(:user_name) + t('layouts.history_tag.user_name') + ' : ' + object.user_name if object.user_name + end + end)].join.html_safe + end + end + end +end diff --git a/app/helpers/imports_helper.rb b/app/helpers/imports_helper.rb index 4b829fe98..2b94cfd1a 100644 --- a/app/helpers/imports_helper.rb +++ b/app/helpers/imports_helper.rb @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- module ImportsHelper - def fields_for_import_type(form) - partial_name = "fields_#{form.object.type.underscore}" + def fields_for_import_task_format(form) + partial_name = "fields_#{form.object.format.underscore}_import" begin render :partial => partial_name, :locals => { :form => form } diff --git a/app/helpers/title_helper.rb b/app/helpers/title_helper.rb index 2203151a3..209cbc4a9 100644 --- a/app/helpers/title_helper.rb +++ b/app/helpers/title_helper.rb @@ -9,7 +9,7 @@ module TitleHelper end def title_tag(title, options = nil) - content_tag :h2, title(title), options + content_tag :h2, title(title).html_safe, options end end diff --git a/app/helpers/type_ids_models_helper.rb b/app/helpers/type_ids_models_helper.rb new file mode 100644 index 000000000..3d1c54a5b --- /dev/null +++ b/app/helpers/type_ids_models_helper.rb @@ -0,0 +1,75 @@ +module TypeIdsModelsHelper + + def type_ids_model_references_type( type_ids_model_class, type) + ReferencesTypeHelper.new( type_ids_model_class, type) + end + + class ReferencesTypeHelper + + attr_accessor :type_ids_model_class, :type + + def initialize( type_ids_model_class, type) + @type_ids_model_class, @type = type_ids_model_class, type + end + def model_class + type_ids_model_class.to_s.underscore + end + def input_id + "#{model_class}_reference_#{relation_name}_ids" + end + def input_class + "#{model_class}_#{relation_name}_reference_ids" + end + def relation_name + type_ids_model_class.references_relation(type) + end + end + + def type_ids_model_references_input( form, type_ids_model, model_class, type) + cct_type_helper = type_ids_model_references_type( model_class, type) + ReferencesInput.new form, type_ids_model, type, cct_type_helper + end + + class ReferencesInput + + attr_accessor :form, :type_ids_model, :type, :type_helper + def initialize(form, type_ids_model, type, type_helper) + @form, @type_ids_model, @type, @type_helper = form, type_ids_model, type, type_helper + end + + delegate :input_id, :input_class, :model_class, :to => :type_helper + + def current? + type_ids_model.references_type == type + end + + def references_map + references.collect { |child| { :id => child.id, :name => child.name } } + end + + def wrapper_html_options + { + :class => "#{model_class}_reference_ids", + :id => "#{input_id}_input", + :"data-type" => type, + :style => ("display: none" unless current?) + } + end + + def input_html_options + { + :id => input_id, + :class => input_class, + :"data-pre" => ( references_map.to_json if current? ), + :disabled => (true unless current?) + } + end + + def input + form.input :reference_ids, :as => :text, :wrapper_html => wrapper_html_options, :input_html => input_html_options + end + + end + +end + diff --git a/app/maps/access_link_map.rb b/app/maps/access_link_map.rb index fcca1250f..35873a9b1 100644 --- a/app/maps/access_link_map.rb +++ b/app/maps/access_link_map.rb @@ -9,11 +9,11 @@ class AccessLinkMap < ApplicationMap end def customize_map(map, page) - page.assign "access_points_layer", kml_layer([access_link.referential, access_link.access_point], :styleMap => StyleMap::AccessPointsStyleMap.new(helpers).style_map) + page.assign "access_points_layer", kml_layer([access_link.referential, access_link.access_point], :styleMap => Design::AccessPointsStyleMap.new(helpers).style_map) page << map.add_layer(:access_points_layer) - page.assign "stop_areas_layer", kml_layer([access_link.referential, access_link.stop_area], :styleMap => StyleMap::StopAreasStyleMap.new(helpers).style_map) + page.assign "stop_areas_layer", kml_layer([access_link.referential, access_link.stop_area], :styleMap => Design::StopAreasStyleMap.new(helpers).style_map) page << map.add_layer(:stop_areas_layer) - page << map.add_layer( kml_layer([access_link.referential, access_link.access_point, access_link], :styleMap => StyleMap::AccessLinkStyleMap.new(helpers).style_map)) + page << map.add_layer( kml_layer([access_link.referential, access_link.access_point, access_link], :styleMap => Design::AccessLinkStyleMap.new(helpers).style_map)) page << map.add_control( hover_control_display_name([:access_points_layer,:stop_areas_layer]) ) page << map.zoom_to_extent(bounds.to_google.to_openlayers) if bounds end diff --git a/app/maps/access_point_map.rb b/app/maps/access_point_map.rb index c1fbd2a16..f31dcf5a3 100644 --- a/app/maps/access_point_map.rb +++ b/app/maps/access_point_map.rb @@ -10,9 +10,9 @@ class AccessPointMap < ApplicationMap end def customize_map(map, page) - page.assign "parent_layer", kml_layer(access_point.stop_area, :style_map => StyleMap::StopAreasStyleMap.new(helpers).style_map) + page.assign "parent_layer", kml_layer(access_point.stop_area, :style_map => Design::StopAreasStyleMap.new(helpers).style_map) page << map.add_layer(:parent_layer) - page.assign "edit_access_point_layer", kml_layer(access_point, { :default => editable? }, :style_map => StyleMap::EditAccessPointStyleMap.new(helpers).style_map) + page.assign "edit_access_point_layer", kml_layer(access_point, { :default => editable? }, :style_map => Design::EditAccessPointStyleMap.new(helpers).style_map) page << map.add_layer(:edit_access_point_layer) diff --git a/app/maps/connection_link_map.rb b/app/maps/connection_link_map.rb index 9318ec90f..82050c4da 100644 --- a/app/maps/connection_link_map.rb +++ b/app/maps/connection_link_map.rb @@ -9,9 +9,9 @@ class ConnectionLinkMap < ApplicationMap end def customize_map(map, page) - page.assign "stop_areas_layer", kml_layer([connection_link.referential, connection_link, :stop_areas], :styleMap => StyleMap::StopAreasStyleMap.new(helpers).style_map) + page.assign "stop_areas_layer", kml_layer([connection_link.referential, connection_link, :stop_areas], :styleMap => Design::StopAreasStyleMap.new(helpers).style_map) page << map.add_layer(:stop_areas_layer) - page << map.add_layer( kml_layer([connection_link.referential, connection_link], :styleMap => StyleMap::ConnectionLinkStyleMap.new(helpers).style_map)) + page << map.add_layer( kml_layer([connection_link.referential, connection_link], :styleMap => Design::ConnectionLinkStyleMap.new(helpers).style_map)) page << map.add_control( hover_control_display_name(:stop_areas_layer) ) page << map.zoom_to_extent(bounds.to_google.to_openlayers) if bounds end diff --git a/app/maps/style_map/access_link_style_map.rb b/app/maps/design/access_link_style_map.rb index 07ef5952b..742f7ed0e 100644 --- a/app/maps/style_map/access_link_style_map.rb +++ b/app/maps/design/access_link_style_map.rb @@ -1,4 +1,4 @@ -class StyleMap::AccessLinkStyleMap < StyleMap::GenericStyleMap +class Design::AccessLinkStyleMap < Design::GenericStyleMap attr_accessor :style def initialize(helpers,options = {}) diff --git a/app/maps/style_map/access_points_style_map.rb b/app/maps/design/access_points_style_map.rb index 57cf8dfb3..f7740006d 100644 --- a/app/maps/style_map/access_points_style_map.rb +++ b/app/maps/design/access_points_style_map.rb @@ -1,4 +1,4 @@ -class StyleMap::AccessPointsStyleMap < StyleMap::GenericStyleMap +class Design::AccessPointsStyleMap < Design::GenericStyleMap attr_accessor :style, :context, :temporary def default_style diff --git a/app/maps/style_map/connection_link_style_map.rb b/app/maps/design/connection_link_style_map.rb index 99393fc08..88eeb9457 100644 --- a/app/maps/style_map/connection_link_style_map.rb +++ b/app/maps/design/connection_link_style_map.rb @@ -1,4 +1,4 @@ -class StyleMap::ConnectionLinkStyleMap < StyleMap::GenericStyleMap +class Design::ConnectionLinkStyleMap < Design::GenericStyleMap attr_accessor :style def initialize(helpers,options = {}) diff --git a/app/maps/style_map/edit_access_point_style_map.rb b/app/maps/design/edit_access_point_style_map.rb index 83f9298e8..48c293470 100644 --- a/app/maps/style_map/edit_access_point_style_map.rb +++ b/app/maps/design/edit_access_point_style_map.rb @@ -1,4 +1,4 @@ -class StyleMap::EditAccessPointStyleMap < StyleMap::GenericStyleMap +class Design::EditAccessPointStyleMap < Design::GenericStyleMap attr_accessor :style def default_style diff --git a/app/maps/style_map/edit_stop_area_style_map.rb b/app/maps/design/edit_stop_area_style_map.rb index 38f18f04a..2431f8a0f 100644 --- a/app/maps/style_map/edit_stop_area_style_map.rb +++ b/app/maps/design/edit_stop_area_style_map.rb @@ -1,4 +1,4 @@ -class StyleMap::EditStopAreaStyleMap < StyleMap::GenericStyleMap +class Design::EditStopAreaStyleMap < Design::GenericStyleMap attr_accessor :style def default_style diff --git a/app/maps/style_map/generic_style_map.rb b/app/maps/design/generic_style_map.rb index c905cd00d..0056cc964 100644 --- a/app/maps/style_map/generic_style_map.rb +++ b/app/maps/design/generic_style_map.rb @@ -1,4 +1,4 @@ -class StyleMap::GenericStyleMap +class Design::GenericStyleMap include MapLayers include MapLayers::ViewHelpers diff --git a/app/maps/style_map/journey_pattern_style_map.rb b/app/maps/design/journey_pattern_style_map.rb index 5a06b5c18..1b5766f81 100644 --- a/app/maps/style_map/journey_pattern_style_map.rb +++ b/app/maps/design/journey_pattern_style_map.rb @@ -1,4 +1,4 @@ -class StyleMap::JourneyPatternStyleMap < StyleMap::GenericStyleMap +class Design::JourneyPatternStyleMap < Design::GenericStyleMap attr_accessor :style def initialize(helpers, options = {}) diff --git a/app/maps/style_map/line_style_map.rb b/app/maps/design/line_style_map.rb index acc307df4..e1d76078c 100644 --- a/app/maps/style_map/line_style_map.rb +++ b/app/maps/design/line_style_map.rb @@ -1,4 +1,4 @@ -class StyleMap::LineStyleMap < StyleMap::GenericStyleMap +class Design::LineStyleMap < Design::GenericStyleMap attr_accessor :style, :line_priority, :line_color def initialize(helpers,options = {}) diff --git a/app/maps/style_map/route_style_map.rb b/app/maps/design/route_style_map.rb index 1d9ab12f0..a8042c527 100644 --- a/app/maps/style_map/route_style_map.rb +++ b/app/maps/design/route_style_map.rb @@ -1,4 +1,4 @@ -class StyleMap::RouteStyleMap < StyleMap::GenericStyleMap +class Design::RouteStyleMap < Design::GenericStyleMap attr_accessor :style def initialize(helpers,options = {}) diff --git a/app/maps/style_map/stop_areas_style_map.rb b/app/maps/design/stop_areas_style_map.rb index f23b58136..f45c423e2 100644 --- a/app/maps/style_map/stop_areas_style_map.rb +++ b/app/maps/design/stop_areas_style_map.rb @@ -1,4 +1,4 @@ -class StyleMap::StopAreasStyleMap < StyleMap::GenericStyleMap +class Design::StopAreasStyleMap < Design::GenericStyleMap attr_accessor :style, :context, :temporary def default_style diff --git a/app/maps/group_of_line_map.rb b/app/maps/group_of_line_map.rb index df1708597..b9c174cb9 100644 --- a/app/maps/group_of_line_map.rb +++ b/app/maps/group_of_line_map.rb @@ -8,7 +8,7 @@ class GroupOfLineMap < ApplicationMap end def customize_map(map, page) - page.assign "stop_areas_layer", kml_layer([group_of_line.referential, group_of_line], :styleMap => StyleMap::StopAreasStyleMap.new(helpers).style_map) + page.assign "stop_areas_layer", kml_layer([group_of_line.referential, group_of_line], :styleMap => Design::StopAreasStyleMap.new(helpers).style_map) page << map.add_layer(:stop_areas_layer) page << map.add_control( hover_control_display_name(:stop_areas_layer) ) diff --git a/app/maps/journey_pattern_map.rb b/app/maps/journey_pattern_map.rb index 075019c79..e1cf54a6a 100644 --- a/app/maps/journey_pattern_map.rb +++ b/app/maps/journey_pattern_map.rb @@ -8,7 +8,7 @@ class JourneyPatternMap < ApplicationMap end def customize_map(map, page) - layer = kml_layer([journey_pattern.referential, journey_pattern.route.line, journey_pattern.route, journey_pattern], :styleMap => StyleMap::JourneyPatternStyleMap.new(helpers).style_map) + layer = kml_layer([journey_pattern.referential, journey_pattern.route.line, journey_pattern.route, journey_pattern], :styleMap => Design::JourneyPatternStyleMap.new(helpers).style_map) page.assign "journeyPatternLayer", layer selectFeature = OpenLayers::Control::SelectFeature.new( :journeyPatternLayer) diff --git a/app/maps/line_map.rb b/app/maps/line_map.rb index 3bc229555..8d79bfe0b 100644 --- a/app/maps/line_map.rb +++ b/app/maps/line_map.rb @@ -9,8 +9,8 @@ class LineMap < ApplicationMap end def customize_map(map, page) - page << map.add_layer(kml_layer(line, :styleMap => StyleMap::LineStyleMap.new( :style => line_style).style_map)) - page.assign "stop_areas_layer", kml_layer([line.referential, line], :styleMap => StyleMap::StopAreasStyleMap.new(helpers).style_map) + page << map.add_layer(kml_layer(line, :styleMap => Design::LineStyleMap.new( :style => line_style).style_map)) + page.assign "stop_areas_layer", kml_layer([line.referential, line], :styleMap => Design::StopAreasStyleMap.new(helpers).style_map) page << map.add_layer(:stop_areas_layer) diff --git a/app/maps/network_map.rb b/app/maps/network_map.rb index ec23f62c9..109e390d0 100644 --- a/app/maps/network_map.rb +++ b/app/maps/network_map.rb @@ -8,7 +8,7 @@ class NetworkMap < ApplicationMap end def customize_map(map, page) - page.assign "stop_areas_layer", kml_layer([network.referential, network], :styleMap => StyleMap::StopAreasStyleMap.new(helpers).style_map) + page.assign "stop_areas_layer", kml_layer([network.referential, network], :styleMap => Design::StopAreasStyleMap.new(helpers).style_map) page << map.add_layer(:stop_areas_layer) page << map.add_control( hover_control_display_name(:stop_areas_layer) ) diff --git a/app/maps/route_map.rb b/app/maps/route_map.rb index fc1a7d93e..5acb1ad76 100644 --- a/app/maps/route_map.rb +++ b/app/maps/route_map.rb @@ -8,7 +8,7 @@ class RouteMap < ApplicationMap end def customize_map(map, page) - layer = kml_layer([route.referential, route.line, route], :styleMap => StyleMap::RouteStyleMap.new(helpers).style_map) + layer = kml_layer([route.referential, route.line, route], :styleMap => Design::RouteStyleMap.new(helpers).style_map) page.assign "routeLayer", layer selectFeature = OpenLayers::Control::SelectFeature.new( :routeLayer) diff --git a/app/maps/stop_area_map.rb b/app/maps/stop_area_map.rb index b2e04779a..6c3dd5feb 100644 --- a/app/maps/stop_area_map.rb +++ b/app/maps/stop_area_map.rb @@ -10,21 +10,21 @@ class StopAreaMap < ApplicationMap end def customize_map(map, page) - page.assign "edit_stop_area_layer", kml_layer(stop_area, { :default => editable? }, :style_map => StyleMap::EditStopAreaStyleMap.new(helpers).style_map) + page.assign "edit_stop_area_layer", kml_layer(stop_area, { :default => editable? }, :style_map => Design::EditStopAreaStyleMap.new(helpers).style_map) page << map.add_layer(:edit_stop_area_layer) if stop_area.children.present? - page.assign "children_layer", kml_layer(stop_area, { :children => true }, :style_map => StyleMap::StopAreasStyleMap.new(helpers).style_map) + page.assign "children_layer", kml_layer(stop_area, { :children => true }, :style_map => Design::StopAreasStyleMap.new(helpers).style_map) page << map.add_layer(:children_layer) end if stop_area.routing_stops.present? - page.assign "routing_layer", kml_layer(stop_area, { :routing => true }, :style_map => StyleMap::StopAreasStyleMap.new(helpers).style_map) + page.assign "routing_layer", kml_layer(stop_area, { :routing => true }, :style_map => Design::StopAreasStyleMap.new(helpers).style_map) page << map.add_layer(:routing_layer) page << map.add_control( hover_control_display_name(:routing_layer) ) page << map.zoom_to_extent(bounds.to_google.to_openlayers) if bounds else - page.assign "edit_stop_area_layer", kml_layer(stop_area, { :default => editable? }, :style_map => StyleMap::EditStopAreaStyleMap.new(helpers).style_map) + page.assign "edit_stop_area_layer", kml_layer(stop_area, { :default => editable? }, :style_map => Design::EditStopAreaStyleMap.new(helpers).style_map) page << map.add_layer(:edit_stop_area_layer) if editable? diff --git a/app/models/compliance_check_result.rb b/app/models/compliance_check_result.rb new file mode 100644 index 000000000..6d4509676 --- /dev/null +++ b/app/models/compliance_check_result.rb @@ -0,0 +1,47 @@ +class ComplianceCheckResult < ActiveRecord::Base + scope :warning, -> { where severity: 'warning' } + scope :error, -> { where severity: 'error' } + scope :improvment, -> { where severity: 'improvment' } + + scope :ok, -> { where status: 'ok' } + scope :nok, -> { where status: 'nok' } + scope :na, -> { where status: 'na' } + + attr_accessible :violation_count + belongs_to :compliance_check_task + + validates_presence_of :rule_code + validates_inclusion_of :severity, :in => %w{warning error improvment} + validates_inclusion_of :status, :in => %w{na ok nok} + + serialize :detail, JSON + + def indice + return nil unless rule_code + + rule_code.match( /\d+-\w+-\w+-(\d+)/ )[1].to_i + end + + def data_type + return nil unless rule_code + + rule_code.match( /\d+-\w+-(\w+)-\d+/ )[1] + end + + def format + return nil unless rule_code + + rule_code.match( /\d+-(\w+)-\w+-\d+/ )[1] + end + + def level + return nil unless rule_code + + rule_code.match( /(\d+)-\w+-\w+-\d+/ )[1].to_i + end + + def rule_code_formatted + rule_code.gsub("-", "_").downcase if rule_level + end + +end diff --git a/app/models/compliance_check_task.rb b/app/models/compliance_check_task.rb new file mode 100644 index 000000000..756f4ba13 --- /dev/null +++ b/app/models/compliance_check_task.rb @@ -0,0 +1,95 @@ +class ComplianceCheckTask < ActiveRecord::Base + attr_accessor :rule_parameter_set_id + + belongs_to :referential + belongs_to :import_task + + validates_presence_of :referential + validates_presence_of :user_id + validates_presence_of :user_name + validates_inclusion_of :status, :in => %w{ pending processing completed failed } + + has_many :compliance_check_results, :order => :status + + serialize :parameter_set, JSON + + include ::TypeIdsModelable + + def chouette_command + Chouette::Command.new(:schema => referential.slug) + end + + before_validation :define_default_attributes, :on => :create + def define_default_attributes + self.status ||= "pending" + if self.rule_parameter_set + self.parameter_set = self.rule_parameter_set.parameters + self.parameter_set_name = self.rule_parameter_set.name + end + end + + @@references_types = [ Chouette::Line, Chouette::Network, Chouette::Company, Chouette::GroupOfLine ] + cattr_reader :references_types + + #validates_inclusion_of :references_type, :in => references_types.map(&:to_s), :allow_blank => true, :allow_nil => true + + after_destroy :destroy_import_task + def destroy_import_task + import_task.destroy if import_task + end + + def delayed_validate + delay.validate if import_task.blank? + end + + def name + "#{self.class.model_name.human} #{id}" + end + + def levels + [].tap do |l| + l.concat( [1 , 2]) if self.import_task + l << 3 if self.parameter_set + end + end + + def level1? + levels.include?( 1) + end + + def level2? + levels.include?( 2) + end + + def level3? + levels.include?( 3) + end + + def rule_parameter_set_archived + return nil unless parameter_set + RuleParameterSet.new( :name => parameter_set_name).tap do |rs| + rs.parameters = parameter_set + end + end + + def rule_parameter_set + return nil if self.rule_parameter_set_id.blank? + RuleParameterSet.find( self.rule_parameter_set_id) + end + + def chouette_command_args + {:c => "validate", :id => id} + end + + def validate + begin + chouette_command.run! chouette_command_args + update_attribute :status, "completed" + rescue => e + Rails.logger.error "Validation #{id} failed : #{e}, #{e.backtrace}" + update_attribute :status, "failed" + end + end + + +end diff --git a/app/models/csv_import.rb b/app/models/csv_import.rb index be3c08743..69603b237 100644 --- a/app/models/csv_import.rb +++ b/app/models/csv_import.rb @@ -1,10 +1,6 @@ -class CsvImport < Import +class CsvImport < ImportTask - validates_presence_of :objectid_prefix - option :objectid_prefix - - def import_options - super.merge(:format => :csv, :objectid_prefix => objectid_prefix) - end + validates_presence_of :object_id_prefix + option :object_id_prefix end diff --git a/app/models/export.rb b/app/models/export.rb index 342e55738..f684ddef5 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -9,6 +9,8 @@ class Export < ActiveRecord::Base serialize :options + include ::TypeIdsModelable + def self.option(name) name = name.to_s @@ -74,7 +76,7 @@ class Export < ActiveRecord::Base begin # delayed job may repeat call - ExportLogMessage.where(:export_id => self.id).delete_all + ExportLogMessage.where(:export_id => self.id).delete_all log_messages.create :severity => "ok", :key => :started exporter.export file, export_options @@ -94,54 +96,8 @@ class Export < ActiveRecord::Base validates_inclusion_of :references_type, :in => references_types.map(&:to_s), :allow_blank => true, :allow_nil => true - def references - if references_relation.present? and reference_ids.present? - referential.send(references_relation).find(reference_ids) - else - [] - end - end - - def references=(references) - unless references.blank? - self.references_type = references.first.class.name - self.reference_ids = references.map(&:id) - else - self.references_type = nil - self.reference_ids = [] - end - end - - def references_relation - if references_type.present? - relation = self.class.references_relation(references_type) - relation if referential.respond_to?(relation) - end - end - - def self.references_relation(type) - type.to_s.demodulize.underscore.pluralize - end - - def reference_ids - if raw_reference_ids - raw_reference_ids.split(',').map(&:to_i) - else - [] - end - end - - def reference_ids=(records) - records = Array(records) - write_attribute :reference_ids, (records.present? ? records.join(',') : nil) - end - - def raw_reference_ids - read_attribute :reference_ids - end - def self.format_name(format) - name_by_format = { + name_by_format = { "NeptuneExport" => "Neptune", "CsvExport" => "CSV", "GtfsExport" => "GTFS", diff --git a/app/models/file_validation.rb b/app/models/file_validation.rb deleted file mode 100644 index e09a48113..000000000 --- a/app/models/file_validation.rb +++ /dev/null @@ -1,186 +0,0 @@ -class FileValidation < ActiveRecord::Base - validates_presence_of :resources - - validates_inclusion_of :status, :in => %w{ pending completed failed } - - attr_accessor :resources,:uncheck_count,:ok_count,:warning_count,:error_count,:fatal_count,:log_message_tree - attr_accessor :validator - - belongs_to :organisation - validates_presence_of :organisation - - has_many :log_messages, :class_name => "FileValidationLogMessage", :order => :position, :dependent => :destroy - - serialize :options - - def self.option(name) - name = name.to_s - - define_method(name) do - self.options and self.options[name] - end - - define_method("#{name}=") do |prefix| - (self.options ||= {})[name] = prefix - end - end - - option :test3_1_minimal_distance - option :test3_2_minimal_distance - option :test3_2_polygon_points - option :test3_7_minimal_distance - option :test3_7_maximal_distance - option :test3_8a_minimal_speed - option :test3_8a_maximal_speed - option :test3_8b_minimal_speed - option :test3_8b_maximal_speed - option :test3_8c_minimal_speed - option :test3_8c_maximal_speed - option :test3_8d_minimal_speed - option :test3_8d_maximal_speed - option :test3_9_minimal_speed - option :test3_9_maximal_speed - option :test3_10_minimal_distance - option :test3_15_minimal_time - option :test3_16_1_maximal_time - option :test3_16_3a_maximal_time - option :test3_16_3b_maximal_time - option :test3_21a_minimal_speed - option :test3_21a_maximal_speed - option :test3_21b_minimal_speed - option :test3_21b_maximal_speed - option :test3_21c_minimal_speed - option :test3_21c_maximal_speed - option :test3_21d_minimal_speed - option :test3_21d_maximal_speed - option :projection_reference - - def validator - @validator ||= ::Chouette::FileValidator.new("public") - end - - def with_original_filename - Dir.mktmpdir do |tmp_dir| - tmp_link = File.join(tmp_dir, resources.original_filename) - FileUtils.ln_s resources.path, tmp_link - yield tmp_link - end - end - - before_validation :define_default_attributes, :on => :create - def define_default_attributes - self.status ||= "pending" - end - - after_validation :extract_file_type, :on => :create - def extract_file_type - if ! resources.nil? - if !resources.original_filename.nil? - self.file_type = resources.original_filename.rpartition(".").last - self.file_name = resources.original_filename - end - end - end - - after_create :delayed_validate - def delayed_validate - save_resources - delay.validate - end - - @@root = "#{Rails.root}/tmp/validations" - cattr_accessor :root - - def save_resources - FileUtils.mkdir_p root - FileUtils.cp resources.path, saved_resources - end - - after_destroy :destroy_resources - def destroy_resources - FileUtils.rm saved_resources if File.exists? saved_resources - end - - def saved_resources - "#{root}/#{id}.#{file_type}" - end - - def name - "#{FileValidation.model_name.humanize} #{id}" - end - - def validation_options - hash = { :validation_id => self.id , - :file_format => self.file_type} - options.keys.each do |opt| - hash.merge! opt.to_sym => self.send(opt.to_sym) - end - hash - end - - def validate - begin - # log_messages.create :key => :started - if resources - with_original_filename do |file| - # chouette-command checks the file extension (and requires .zip) :( - validator.validate file, validation_options - end - else - validator.validate saved_resources, validation_options - end - update_attribute :status, "completed" - rescue => e - Rails.logger.error "Validation #{id} failed : #{e}, #{e.backtrace}" - update_attribute :status, "failed" - end - # log_messages.create :key => status - end - - after_find :compute_tests - def compute_tests - if status == 'completed' - self.uncheck_count = 0 - self.ok_count = 0 - self.warning_count = 0 - self.error_count = 0 - self.fatal_count = 0 - self.log_message_tree = Array.new - father1=nil - father2=nil - father3=nil - log_messages.each do |message| - if message.level == 1 - self.log_message_tree << message - father1=message - elsif message.level == 2 - father1.add_child message - father2=message - elsif message.level == 3 - father2.add_child message - father3=message - if message.severity == 'uncheck' - self.uncheck_count += 1 - end - if message.severity == 'ok' - self.ok_count += 1 - end - if message.severity == 'warning' - self.warning_count += 1 - end - if message.severity == 'error' - self.error_count += 1 - end - if message.severity == 'fatal' - self.fatal_count += 1 - end - elsif message.level == 4 - father3.add_child message - end - end - end - - end - - -end diff --git a/app/models/file_validation_log_message.rb b/app/models/file_validation_log_message.rb deleted file mode 100644 index 589327110..000000000 --- a/app/models/file_validation_log_message.rb +++ /dev/null @@ -1,68 +0,0 @@ -class FileValidationLogMessage < ActiveRecord::Base - belongs_to :file_validation - acts_as_list :scope => :file_validation - - attr_accessor :children - - validates_presence_of :key - validates_inclusion_of :severity, :in => %w{info warning error ok uncheck fatal} - - def arguments=(arguments) - write_attribute :arguments, (arguments.to_json if arguments.present?) - end - - def arguments - @decoded_arguments ||= - begin - if (stored_arguments = raw_attributes).present? - ActiveSupport::JSON.decode stored_arguments - else - {} - end - end - end - - def raw_attributes - read_attribute(:arguments) - end - - before_validation :define_default_attributes, :on => :create - def define_default_attributes - self.severity ||= "info" - end - - def level - last_key=key.rpartition("|").last - if last_key == 'TooMuchDetails' - 4 - else - [last_key.count("_") + 1,4].min - end - end - - def full_message - last_key=key.rpartition("|").last - I18n.translate last_key, arguments.symbolize_keys.merge(:scope => "file_validation_log_messages.messages").merge(:default => :undefined).merge(:key => last_key) - end - - def label - last_key=key.rpartition("|").last - label = "" - last_key.split("_").each do |tag| - if (tag.start_with?("Test")) - label = tag.delete("Test") - else - label += "."+tag.delete("Sheet").delete("Step") - end - end - label - end - - def add_child(child) - if self.children.nil? - self.children = Array.new - end - self.children << child - end - -end diff --git a/app/models/gtfs_import.rb b/app/models/gtfs_import.rb index a332fe65e..af83d81a0 100644 --- a/app/models/gtfs_import.rb +++ b/app/models/gtfs_import.rb @@ -1,18 +1,10 @@ -class GtfsImport < Import +class GtfsImport < ImportTask - validates_presence_of :objectid_prefix - option :objectid_prefix + validates_presence_of :object_id_prefix + option :object_id_prefix option :max_distance_for_commercial option :ignore_last_word option :ignore_end_chars option :max_distance_for_connection_link - - def import_options - super.merge(:format => :gtfs, :objectid_prefix => objectid_prefix, - :max_distance_for_commercial => max_distance_for_commercial, - :ignore_last_word => ignore_last_word, - :ignore_end_chars => ignore_end_chars, - :max_distance_for_connection_link => max_distance_for_connection_link) - end end diff --git a/app/models/import.rb b/app/models/import.rb deleted file mode 100644 index 629d54a42..000000000 --- a/app/models/import.rb +++ /dev/null @@ -1,127 +0,0 @@ -class Import < ActiveRecord::Base - belongs_to :referential - - validates_presence_of :referential_id - validates_presence_of :resources - - validates_inclusion_of :status, :in => %w{ pending completed failed } - - attr_accessor :resources - attr_accessor :loader - - has_many :log_messages, :class_name => "ImportLogMessage", :order => :position, :dependent => :delete_all - - serialize :options - - def self.option(name) - name = name.to_s - - define_method(name) do - self.options and self.options[name] - end - - define_method("#{name}=") do |prefix| - (self.options ||= {})[name] = prefix - end - end - - def self.format_name(format) - name_by_format = { "NeptuneImport" => "Neptune", - "CsvImport" => "CSV", - "GtfsImport" => "GTFS", - "NetexImport" => "NeTEx"} - name_by_format[format] - end - - def self.types - # if Rails.env.development? and subclasses.blank? - # Dir[File.expand_path("../*_import.rb", __FILE__)].each do |f| - # require f - # end - # end - - unless Rails.env.development? - subclasses.map(&:to_s) - else - # FIXME - %w{NeptuneImport CsvImport GtfsImport NetexImport} - end - end - - def loader - @loader ||= ::Chouette::Loader.new(referential.slug) - end - - def with_original_filename - Dir.mktmpdir do |tmp_dir| - tmp_link = File.join(tmp_dir, resources.original_filename) - FileUtils.ln_s resources.path, tmp_link - yield tmp_link - end - end - - before_validation :define_default_attributes, :on => :create - def define_default_attributes - self.status ||= "pending" - end - - before_validation :extract_file_type, :on => :create - def extract_file_type - if ! resources.nil? - self.file_type = resources.original_filename.rpartition(".").last - end - end - - def delayed_import - save_resources - delay.import - end - - @@root = "#{Rails.root}/tmp/imports" - cattr_accessor :root - - def save_resources - FileUtils.mkdir_p root - FileUtils.cp resources.path, saved_resources - end - - after_destroy :destroy_resources - def destroy_resources - FileUtils.rm saved_resources if File.exists? saved_resources - end - - def saved_resources - "#{root}/#{id}.#{file_type}" - end - - def name - "#{self.class.model_name.human} #{id}" - end - - def import_options - { :import_id => self.id , :file_format => self.file_type } - end - - def import - begin - log_messages.create :key => :started - - loader.import saved_resources, import_options - - update_attribute :status, "completed" - rescue => e - Rails.logger.error "Import #{id} failed : #{e}, #{e.backtrace}" - update_attribute :status, "failed" - end - log_messages.create :key => status - end - - def self.new(attributes = {}, options = {}, &block) - if self == Import - Object.const_get(attributes.delete(:type) || "NeptuneImport").new(attributes, options) - else - super - end - end - -end diff --git a/app/models/import_log_message.rb b/app/models/import_log_message.rb deleted file mode 100644 index 4b56f03bd..000000000 --- a/app/models/import_log_message.rb +++ /dev/null @@ -1,42 +0,0 @@ -class ImportLogMessage < ActiveRecord::Base - belongs_to :import - acts_as_list :scope => :import - - validates_presence_of :key - validates_inclusion_of :severity, :in => %w{info warning error ok uncheck fatal} - - def arguments=(arguments) - write_attribute :arguments, (arguments.to_json if arguments.present?) - end - - def arguments - @decoded_arguments ||= - begin - if (stored_arguments = raw_attributes).present? - ActiveSupport::JSON.decode stored_arguments - else - {} - end - end - end - - def raw_attributes - read_attribute(:arguments) - end - - before_validation :define_default_attributes, :on => :create - def define_default_attributes - self.severity ||= "info" - end - - def full_message - last_key=key.rpartition("|").last - begin - I18n.translate last_key, arguments.symbolize_keys.merge(:scope => "import_log_messages.messages").merge(:default => :undefined).merge(:key => last_key) - rescue => e - Rails.logger.error "missing arguments for message "+last_key - I18n.translate "WRONG_DATA",{"0"=>last_key}.symbolize_keys.merge(:scope => "import_log_messages.messages").merge(:default => :undefined).merge(:key => "WRONG_DATA") - end - end - -end diff --git a/app/models/import_task.rb b/app/models/import_task.rb new file mode 100644 index 000000000..6aca85821 --- /dev/null +++ b/app/models/import_task.rb @@ -0,0 +1,160 @@ +class ImportTask < ActiveRecord::Base + attr_accessor :resources, :rule_parameter_set_id + + belongs_to :referential + + has_one :user + has_one :compliance_check_task, :dependent => :delete + + serialize :parameter_set, JSON + serialize :result, JSON + + validates_presence_of :referential_id + validates_presence_of :resources + validates_presence_of :user_id + validates_presence_of :user_name + validates_inclusion_of :status, :in => %w{ pending processing completed failed } + + protected + + def self.option(name, type=nil) + name = name.to_s + + define_method(name) do + self.parameter_set and self.parameter_set[name] + end + + if type.to_s == "boolean" + define_method("#{name}=") do |prefix| + (self.parameter_set ||= {})[name] = (prefix=="1" || prefix==true) + end + else + define_method("#{name}=") do |prefix| + (self.parameter_set ||= {})[name] = prefix + end + end + end + + public + + def self.formats + %w{Neptune Csv Gtfs Netex} + end + + def delayed_import + delay.import + end + + protected + + option :no_save, :boolean + option :format + option :file_path + + validates_inclusion_of :no_save, :in => [ true, false] + validates_inclusion_of :format, :in => self.formats + + def chouette_command + Chouette::Command.new(:schema => referential.slug) + end + + before_validation :define_default_attributes, :on => :create + def define_default_attributes + self.status ||= "pending" + end + + @@root = "#{Rails.root}/tmp/imports" + cattr_accessor :root + + def compliance_check_task_attributes + {:referential_id => referential.id, + :user_id => user_id, + :user_name => user_name, + :rule_parameter_set_id => rule_parameter_set_id} + end + + after_create :update_info, :save_resources + def update_info + self.file_path = saved_resources + self.update_attribute :parameter_set, self.parameter_set + + self.create_compliance_check_task( self.compliance_check_task_attributes) + end + + def save_resources + # resources is a required attribute + FileUtils.mkdir_p root + FileUtils.cp resources.path, saved_resources + end + + after_destroy :destroy_resources + def destroy_resources + FileUtils.rm file_path if File.exists? file_path + end + + def saved_resources + raise Exception.new("Illegal call") if self.new_record? + "#{root}/#{id}#{File.extname(resources.original_filename)}" + end + + def chouette_command_args + {:c => "import", :id => id} + end + + public + + def failed? + status == "failed" + end + + def completed? + status == "completed" + end + + def file_path_extension + extension = File.extname( self.file_path ) + if extension == ".xml" + "xml" + elsif extension == ".zip" + "zip" + else + "basic" + end + end + + def name + "#{ImportTask.model_name.human} #{self.format} #{self.id}" + end + + def full_name + return name unless no_save + "#{name} - #{I18n.t('activerecord.attributes.import_task.no_save')}" + end + + # Create ImportTask and ComplianceCheckTask associated and give import id to Chouette Loader + def import + return nil if self.new_record? + + begin + chouette_command.run! chouette_command_args + reload + update_attribute :status, "completed" + compliance_check_task.update_attribute :status, "completed" + rescue => e + Rails.logger.error "Import #{id} failed : #{e}, #{e.backtrace}" + reload + update_attribute :status, "failed" + compliance_check_task.update_attribute :status, "failed" + end + end + + def self.new(attributes = {}, parameter_set = {}, &block) + if self == ImportTask + attributes[:format] = "Neptune" unless attributes[:format] + Object.const_get( attributes[:format] + "Import").new(attributes, parameter_set) + else + super + end + end + +end diff --git a/app/models/import_type.rb b/app/models/import_type.rb new file mode 100644 index 000000000..ecf226562 --- /dev/null +++ b/app/models/import_type.rb @@ -0,0 +1,6 @@ +class ImportType < ActiveEnum::Base + value :id => 'Neptune', :name => 'Neptune' + value :id => 'Csv', :name => 'Csv' + value :id => 'Gtfs', :name => 'GTFS' + value :id => 'Netex', :name => 'NeTEx' +end diff --git a/app/models/neptune_import.rb b/app/models/neptune_import.rb index 11282b306..24e3355d7 100644 --- a/app/models/neptune_import.rb +++ b/app/models/neptune_import.rb @@ -1,7 +1,6 @@ -class NeptuneImport < Import - - def import_options - super.merge(:format => :neptune) - end +class NeptuneImport < ImportTask + # def import_options + # super.merge() + # end end diff --git a/app/models/netex_import.rb b/app/models/netex_import.rb index 74e76e47c..cc09fd496 100644 --- a/app/models/netex_import.rb +++ b/app/models/netex_import.rb @@ -1,7 +1,7 @@ -class NetexImport < Import +class NetexImport < ImportTask - def import_options - super.merge(:format => :netex) - end + # def import_options + # super.merge(:format => :netex) + # end end diff --git a/app/models/referential.rb b/app/models/referential.rb index c759334b8..bc151b001 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- class Referential < ActiveRecord::Base - validates_presence_of :name + validates_presence_of :name validates_presence_of :slug validates_presence_of :prefix validates_presence_of :time_zone @@ -13,21 +13,24 @@ class Referential < ActiveRecord::Base validates_format_of :upper_corner, :with => %r{\A-?[0-9]+\.?[0-9]*\,-?[0-9]+\.?[0-9]*\Z} validates_format_of :lower_corner, :with => %r{\A-?[0-9]+\.?[0-9]*\,-?[0-9]+\.?[0-9]*\Z} validate :slug_excluded_values - + attr_accessor :resources attr_accessor :upper_corner attr_accessor :lower_corner - has_many :imports, :dependent => :destroy + has_one :user + has_many :rule_parameter_sets, :dependent => :destroy + has_many :import_tasks, :dependent => :destroy + has_many :compliance_check_tasks, :dependent => :destroy has_many :exports, :dependent => :destroy has_many :api_keys, :class_name => 'Api::V1::ApiKey', :dependent => :destroy - + belongs_to :organisation validates_presence_of :organisation def slug_excluded_values if ! slug.nil? - if slug.start_with? "pg_" + if slug.start_with? "pg_" errors.add(:slug,I18n.t("referentials.errors.pg_excluded")) end if slug == 'public' @@ -74,7 +77,7 @@ class Referential < ActiveRecord::Base def time_tables Chouette::TimeTable.scoped end - + def connection_links Chouette::ConnectionLink.scoped end @@ -122,7 +125,7 @@ class Referential < ActiveRecord::Base ] end - def projection_type_label + def projection_type_label self.class.available_srids.each do |a| if a.last.to_s == projection_type return a.first.split('(').first.rstrip @@ -141,9 +144,15 @@ class Referential < ActiveRecord::Base Apartment::Database.drop slug end - after_create :import_resources + after_create :import_resources, :add_rule_parameter_set def import_resources - imports.create(:resources => resources) if resources + import_tasks.create(:resources => resources, :no_save => false, + :format => "Neptune", :user_id => user_id, + :user_name => user_name) if resources + end + + def add_rule_parameter_set + RuleParameterSet.default_for_all_modes( self).save end def upper_corner @@ -161,7 +170,7 @@ class Referential < ActiveRecord::Base end end - def lower_corner + def lower_corner envelope.lower_corner end @@ -188,7 +197,7 @@ class Referential < ActiveRecord::Base end Rails.application.config.after_initialize do - + Chouette::TridentActiveRecord class Chouette::TridentActiveRecord @@ -204,19 +213,19 @@ Rails.application.config.after_initialize do end end - + Chouette::StopArea - + class Chouette::StopArea - + attr_accessible :projection_x,:projection_y - + # override default_position method to add referential envelope when no stoparea is positioned - def default_position - # for first StopArea ... the bounds is nil , set to referential center + def default_position + # for first StopArea ... the bounds is nil , set to referential center Chouette::StopArea.bounds ? Chouette::StopArea.bounds.center : self.referential.envelope.center end - + # add projection_type set on pre-insert and pre_update action before_validation :set_projections def set_projections @@ -237,9 +246,9 @@ Rails.application.config.after_initialize do # self.y = nil # end end - + def projection - if self.referential.projection_type.nil? || self.referential.projection_type.empty? + if self.referential.projection_type.nil? || self.referential.projection_type.empty? nil else self.referential.projection_type @@ -252,7 +261,7 @@ Rails.application.config.after_initialize do nil else @point ||= GeoRuby::SimpleFeatures::Point::from_lat_lng(Geokit::LatLng.new(self.latitude,self.longitude)).project_to(self.projection.to_i) - + @point.x end end @@ -270,11 +279,11 @@ Rails.application.config.after_initialize do def projection_y=(dummy) # dummy method end - + end Chouette::AccessPoint - + class Chouette::AccessPoint attr_accessible :projection_x,:projection_y @@ -298,9 +307,9 @@ Rails.application.config.after_initialize do # self.y = nil # end end - + def projection - if self.referential.projection_type.nil? || self.referential.projection_type.empty? + if self.referential.projection_type.nil? || self.referential.projection_type.empty? nil else self.referential.projection_type @@ -313,7 +322,7 @@ Rails.application.config.after_initialize do nil else @point ||= GeoRuby::SimpleFeatures::Point::from_lat_lng(Geokit::LatLng.new(self.latitude,self.longitude)).project_to(self.projection.to_i) - + @point.x end end @@ -332,5 +341,5 @@ Rails.application.config.after_initialize do # dummy method end end - + end diff --git a/app/models/rule_parameter_set.rb b/app/models/rule_parameter_set.rb new file mode 100644 index 000000000..5177d6ecc --- /dev/null +++ b/app/models/rule_parameter_set.rb @@ -0,0 +1,225 @@ +class RuleParameterSet < ActiveRecord::Base + belongs_to :referential + + validates_presence_of :referential + validates_presence_of :name + + serialize :parameters, JSON + + attr_accessible :name, :referential_id + + def self.mode_attribute_prefixes + %w( inter_stop_area_distance_min inter_stop_area_distance_max speed_max speed_min inter_stop_duration_variation_max) + end + def self.general_attributes + %w( inter_stop_area_distance_min parent_stop_area_distance_max stop_areas_area inter_access_point_distance_min + inter_connection_link_distance_max walk_default_speed_max + walk_occasional_traveller_speed_max walk_frequent_traveller_speed_max walk_mobility_restricted_traveller_speed_max + inter_access_link_distance_max inter_stop_duration_max facility_stop_area_distance_max) + end + def self.all_modes + Chouette::TransportMode.all.map { |m| m.to_s} + end + + def self.mode_attribute?( method_name ) + pattern = /(\w+)_mode_(\w+)/ + return false unless method_name.match( pattern) + + mode_attribute_prefixes.include?( $1) && self.class.all_modes.include?( $2) + end + def self.mode_of_mode_attribute( method_name ) + method_name.match( /(\w+)_mode_(\w+)/) + $2 + end + def self.attribute_of_mode_attribute( method_name ) + method_name.match( /(\w+)_mode_(\w+)/) + $1 + end + + def self.mode_parameter(name) + name = name.to_s + attr_accessible name + + define_method(name) do + attribute_name, mode = RuleParameterSet.attribute_of_mode_attribute( name), RuleParameterSet.mode_of_mode_attribute( name) + self.parameters and self.parameters["mode_#{mode}"] and + self.parameters["mode_#{mode}"][attribute_name] + end + + define_method("#{name}=") do |prefix| + attribute_name, mode = RuleParameterSet.attribute_of_mode_attribute( name), RuleParameterSet.mode_of_mode_attribute( name) + ((self.parameters ||= {})["mode_#{mode}"] ||= {})[attribute_name] = prefix + end + end + def self.parameter(name) + name = name.to_s + attr_accessible name + + define_method(name) do + self.parameters and self.parameters[name] + end + + define_method("#{name}=") do |prefix| + (self.parameters ||= {})[name] = prefix + end + end + + def self.default_params(mode=nil) + base = { :inter_stop_area_distance_min => 20, + :parent_stop_area_distance_max => 300, + :inter_access_point_distance_min => 20, + :inter_connection_link_distance_max => 400, + :walk_default_speed_max => 4, + :walk_occasional_traveller_speed_max => 2, + :walk_frequent_traveller_speed_max => 5, + :walk_mobility_restricted_traveller_speed_max => 1, + :inter_access_link_distance_max => 300, + :inter_stop_duration_max => 40, + :facility_stop_area_distance_max => 300 + } + if mode && self.mode_default_params[ mode.to_sym] + base.merge!( self.mode_default_params[ mode.to_sym]) + end + base + end + def self.mode_default_params + { + :coach => { + :inter_stop_area_distance_min_mode_coach => 500, + :inter_stop_area_distance_max_mode_coach => 10000, + :speed_max_mode_coach => 90, + :speed_min_mode_coach => 40, + :inter_stop_duration_variation_max_mode_coach => 20}, + :air => { + :inter_stop_area_distance_min_mode_air => 200, + :inter_stop_area_distance_max_mode_air => 10000, + :speed_max_mode_air => 800, + :speed_min_mode_air => 700, + :inter_stop_duration_variation_max_mode_air => 60}, + :waterborne => { + :inter_stop_area_distance_min_mode_waterborne => 200, + :inter_stop_area_distance_max_mode_waterborne => 10000, + :speed_max_mode_waterborne => 40, + :speed_min_mode_waterborne => 5, + :inter_stop_duration_variation_max_mode_waterborne => 60}, + :bus => { + :inter_stop_area_distance_min_mode_bus => 100, + :inter_stop_area_distance_max_mode_bus => 10000, + :speed_max_mode_bus => 60, + :speed_min_mode_bus => 10, + :inter_stop_duration_variation_max_mode_bus => 15}, + :ferry => { + :inter_stop_area_distance_min_mode_ferry => 200, + :inter_stop_area_distance_max_mode_ferry => 10000, + :speed_max_mode_ferry => 40, + :speed_min_mode_ferry => 5, + :inter_stop_duration_variation_max_mode_ferry => 60}, + :walk => { + :inter_stop_area_distance_min_mode_walk => 1, + :inter_stop_area_distance_max_mode_walk => 10000, + :speed_max_mode_walk => 6, + :speed_min_mode_walk => 1, + :inter_stop_duration_variation_max_mode_walk => 10}, + :metro => { + :inter_stop_area_distance_min_mode_metro => 300, + :inter_stop_area_distance_max_mode_metro => 2000, + :speed_max_mode_metro => 60, + :speed_min_mode_metro => 30, + :inter_stop_duration_variation_max_mode_metro => 30}, + :shuttle => { + :inter_stop_area_distance_min_mode_shuttle => 500, + :inter_stop_area_distance_max_mode_shuttle => 10000, + :speed_max_mode_shuttle => 80, + :speed_min_mode_shuttle => 20, + :inter_stop_duration_variation_max_mode_shuttle => 10}, + :rapid_transit => { + :inter_stop_area_distance_min_mode_rapid_transit => 2000, + :inter_stop_area_distance_max_mode_rapid_transit => 500000, + :speed_max_mode_rapid_transit => 300, + :speed_min_mode_rapid_transit => 20, + :inter_stop_duration_variation_max_mode_rapid_transit => 60}, + :taxi => { + :inter_stop_area_distance_min_mode_taxi => 500, + :inter_stop_area_distance_max_mode_taxi => 300000, + :speed_max_mode_taxi => 130, + :speed_min_mode_taxi => 20, + :inter_stop_duration_variation_max_mode_taxi => 60}, + :local_train => { + :inter_stop_area_distance_min_mode_local_train => 2000, + :inter_stop_area_distance_max_mode_local_train => 500000, + :speed_max_mode_local_train => 300, + :speed_min_mode_local_train => 20, + :inter_stop_duration_variation_max_mode_local_train => 60}, + :train => { + :inter_stop_area_distance_min_mode_train => 2000, + :inter_stop_area_distance_max_mode_train => 500000, + :speed_max_mode_train => 300, + :speed_min_mode_train => 20, + :inter_stop_duration_variation_max_mode_train => 60}, + :long_distance_train => { + :inter_stop_area_distance_min_mode_long_distance_train => 2000, + :inter_stop_area_distance_max_mode_long_distance_train => 500000, + :speed_max_mode_long_distance_train => 300, + :speed_min_mode_long_distance_train => 20, + :inter_stop_duration_variation_max_mode_long_distance_train => 60}, + :tramway => { + :inter_stop_area_distance_min_mode_tramway => 300, + :inter_stop_area_distance_max_mode_tramway => 2000, + :speed_max_mode_tramway => 50, + :speed_min_mode_tramway => 20, + :inter_stop_duration_variation_max_mode_tramway => 30}, + :trolleybus => { + :inter_stop_area_distance_min_mode_trolleybus => 300, + :inter_stop_area_distance_max_mode_trolleybus => 2000, + :speed_max_mode_trolleybus => 50, + :speed_min_mode_trolleybus => 20, + :inter_stop_duration_variation_max_mode_trolleybus => 30}, + :private_vehicle => { + :inter_stop_area_distance_min_mode_private_vehicle => 500, + :inter_stop_area_distance_max_mode_private_vehicle => 300000, + :speed_max_mode_private_vehicle => 130, + :speed_min_mode_private_vehicle => 20, + :inter_stop_duration_variation_max_mode_private_vehicle => 60}, + :bicycle => { + :inter_stop_area_distance_min_mode_bicycle => 300, + :inter_stop_area_distance_max_mode_bicycle => 30000, + :speed_max_mode_bicycle => 40, + :speed_min_mode_bicycle => 10, + :inter_stop_duration_variation_max_mode_bicycle => 10}, + :other => { + :inter_stop_area_distance_min_mode_other => 300, + :inter_stop_area_distance_max_mode_other => 30000, + :speed_max_mode_other => 40, + :speed_min_mode_other => 10, + :inter_stop_duration_variation_max_mode_other => 10}, + } + # :waterborne, :bus, :ferry, :walk, :metro, :shuttle, :rapidtransit, :taxi, :localtrain, :train, :longdistancetrain, :tramway, :trolleybus, :privatevehicle, :bicycle, :other + end + def self.default( referential) + self.default_for_all_modes( referential).tap do |rps| + rps.name = "" + end + end + def self.default_for_all_modes( referential) + mode_attributes = mode_default_params.values.inject(self.default_params){|memo, obj| memo.merge! obj} + self.new( + { :referential_id => referential.id, + :stop_areas_area => referential.envelope.to_polygon.points.map(&:to_coordinates).to_json, + :name => "valeurs par defaut" + }.merge( mode_attributes)) + end + + all_modes.each do |mode| + mode_attribute_prefixes.each do |prefix| + mode_parameter "#{prefix}_mode_#{mode}".to_sym + end + end + + general_attributes.each do |attribute| + parameter attribute.to_sym + unless attribute == "stop_areas_area" + validates attribute.to_sym, :numericality => true, :allow_nil => true, :allow_blank => true + end + end + +end diff --git a/app/models/type_ids_modelable.rb b/app/models/type_ids_modelable.rb new file mode 100644 index 000000000..4d3de7a8f --- /dev/null +++ b/app/models/type_ids_modelable.rb @@ -0,0 +1,61 @@ +# The model table must have two columns : +# - references_type +# - reference_ids +# The model class should also define +# cattr :references_types with expected classes for references_type +module TypeIdsModelable + def self.included(base) + base.extend(Methods) + end + + def references + if references_relation.present? and reference_ids.present? + referential.send(references_relation).find(reference_ids) + else + [] + end + end + + def references=(references) + unless references.blank? + self.references_type = references.first.class.name + self.reference_ids = references.map(&:id) + else + self.references_type = nil + self.reference_ids = [] + end + end + + def references_relation + if references_type.present? + relation = self.class.references_relation(references_type) + relation if referential.respond_to?(relation) + end + end + + def reference_ids + if raw_reference_ids + raw_reference_ids.split(',').map(&:to_i) + else + [] + end + end + + def reference_ids=(records) + records = Array(records) + write_attribute :reference_ids, (records.present? ? records.join(',') : nil) + end + + def raw_reference_ids + read_attribute :reference_ids + end + + module Methods + def type_ids_modelable_class? + return true + end + def references_relation(type) + type.to_s.demodulize.underscore.pluralize + end + end +end diff --git a/app/views/compliance_check_results/_compliance_check_result.erb b/app/views/compliance_check_results/_compliance_check_result.erb new file mode 100644 index 000000000..afd94f62e --- /dev/null +++ b/app/views/compliance_check_results/_compliance_check_result.erb @@ -0,0 +1,21 @@ + <div class="severity_<%= compliance_check_result.severity %> status_<%= compliance_check_result.status %>"> + <div class="status_icon"> + <%= image_tag "icons/status_#{compliance_check_result.status}.png", :class => "status" %> + </div> + <div class="status_text"> + <div class="code"> + <%= compliance_check_result.rule_code %> + </div> + <div class="severity"> + [ <%= ComplianceCheckResult.human_attribute_name(:severity) %> : <%= t compliance_check_result.severity, :scope => "compliance_check_result.severities" %> ] + </div> + <div class="explanation"> + <%= ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code) %> + </div> + <div class="attributes"> + <% if compliance_check_result.violation_count > 0 %> + <%= ComplianceCheckResult.human_attribute_name(:violation_count) %> : + <% end %> + </div> + </div> +</div> diff --git a/app/views/compliance_check_results/index.html.erb b/app/views/compliance_check_results/index.html.erb new file mode 100644 index 000000000..886664857 --- /dev/null +++ b/app/views/compliance_check_results/index.html.erb @@ -0,0 +1,56 @@ +<table class="table table-hover"> + <thead> + <tr> + <th>#</th> + <th><%= ComplianceCheckResult.human_attribute_name(:status) %></th> + <th><%= ComplianceCheckResult.human_attribute_name(:severity) %></th> + <th><%= ComplianceCheckResult.human_attribute_name(:rule_level) %></th> + <th><%= ComplianceCheckResult.human_attribute_name(:rule_code) %></th> + <% if @compliance_check_results && @compliance_check_results.first.status == "nok" %> + <th><%= ComplianceCheckResult.human_attribute_name(:detail) %></th> + <% end %> + </tr> + </thead> + <tbody> + <% @compliance_check_results.each_with_index do |compliance_check_result, index| %> + <tr> + <td><%= index + 1 %></td> + <td><%= image_tag "icons/status_#{compliance_check_result.status}.png" %></td> + <td><%= t compliance_check_result.severity, :scope => "compliance_check_result.severities" %></td> + <td><%= compliance_check_result.rule_level %></td> + <td> + <%= image_tag "icons/notice.png", :"data-content" => ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code), :"data-title" => t("activerecord.attributes.compliance_check_result.detail"), :class =>"notice" %> + <%= link_to compliance_check_result.rule_code, "#", :title => ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code) %></td> + <% if @compliance_check_results && @compliance_check_results.first.status == "nok" %> + <td class="td_error"> + <% if compliance_check_result.detail.present? %> + <span class="title_error"> + <i class="fa fa-plus-square"></i><%= compliance_check_result.violation_count.to_s + " " + ComplianceCheckResult.human_attribute_name(:violation_count) %> + </span> + <div class="details_error"> + <% compliance_check_result.detail["detail"].first(10).each do |error| %> + <p class="detail_error"> + <% if error["messageArgs"] %> + |- <%= image_tag "icons/notice.png", :"data-content" => ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code) + "<br>" + t("compliance_check_result.details." + error["messageKey"], error["messageArgs"].symbolize_keys ), :"data-title" => t("activerecord.attributes.compliance_check_result.detail"), :class =>"notice" %> + <% else %> + |- <%= image_tag "icons/notice.png", :"data-content" => ComplianceCheckResult.human_attribute_name(compliance_check_result.rule_code) + "<br>" + t("compliance_check_result.details." + error["messageKey"]), :"data-title" => t("activerecord.attributes.compliance_check_result.detail"), :class =>"notice" %> + <% end %> + <% if error["location"]["url"].present? %> + <%= link_to error["objectId"], referential_path(@referential) + "/" + error["location"]["url"] %> + <% elsif error["location"]["filename"].present? %> + <%= error["objectId"] %><br> + <span class="file_error"> <%= File.basename(error["location"]["filename"]) %> + <%= t("compliance_check_results.index.column") %>: <%= error["location"]["columnNumber"] %>, <%= t("compliance_check_results.index.line") %>: <%= error["location"]["lineNumber"] %></span> + <% end %> + </p> + <% end %> + </div> + <% end %> + </td> + <% end %> + </tr> + <% end %> + </tbody> +</table> +<%= javascript_include_tag referential_compliance_check_task_compliance_check_results_path(@compliance_check_task.referential, @compliance_check_task, :format => :js) %> + diff --git a/app/views/compliance_check_results/index.js.coffee b/app/views/compliance_check_results/index.js.coffee new file mode 100644 index 000000000..c73676d88 --- /dev/null +++ b/app/views/compliance_check_results/index.js.coffee @@ -0,0 +1,8 @@ +jQuery -> + $("body").popover({ selector: '.notice', container: "body", trigger: "click", html: true, placement: "bottom" }) + + # Hide and show error details + $(".title_error").each -> + $( this ).click -> + $(this).next(".details_error").toggle() + $(this).children("i").toggleClass("fa-plus-square fa-minus-square")
\ No newline at end of file diff --git a/app/views/compliance_check_tasks/_compliance_check_task.erb b/app/views/compliance_check_tasks/_compliance_check_task.erb new file mode 100644 index 000000000..3c5388b00 --- /dev/null +++ b/app/views/compliance_check_tasks/_compliance_check_task.erb @@ -0,0 +1,22 @@ +<%= div_for(compliance_check_task, :class => :compliance_check_task) do %> + <div class="icon"> + <%= link_to image_tag("compliance_check_task-#{compliance_check_task.status}.png"), referential_compliance_check_task_path(@referential, compliance_check_task) %> + </div> + <div class="resume"> + <ul class="header clearfix"> + <li class="title"><%= link_to(compliance_check_task.name, referential_compliance_check_task_path(@referential, compliance_check_task)) %></li> + <li class="remove"><%= link_to "<i class='fa fa-trash-o'></i>".html_safe, referential_compliance_check_task_path(@referential, compliance_check_task), :method => :delete, :class => "delete", :data => {:confirm => t('compliance_check_tasks.actions.destroy_confirm')} %></li> + </ul> + <div class="links"> + <% if compliance_check_task.import_task.present? %> + <p><%= link_to( image_tag('icons/link_page.png') + t("compliance_check_tasks.import_task"), referential_import_task_path(@referential, compliance_check_task.import_task)) %></p> + <% end %> + <% if compliance_check_task.parameter_set %> + <p><%= link_to( image_tag('icons/link_page.png') + t("compliance_check_tasks.actions.rule_parameter_set"), rule_parameter_set_referential_compliance_check_task_path(@referential, compliance_check_task)) %></p> + <% end %> + </div> + <div class="history"> + <%= l compliance_check_task.created_at, :format => "%d/%m/%Y %H:%M" %> | <%= compliance_check_task.user_name %> + </div> + </div> +<% end %> diff --git a/app/views/file_validations/_test_sheet_toc.html.erb b/app/views/compliance_check_tasks/_test_sheet_toc.html.erb index 0605510b4..0605510b4 100644 --- a/app/views/file_validations/_test_sheet_toc.html.erb +++ b/app/views/compliance_check_tasks/_test_sheet_toc.html.erb diff --git a/app/views/compliance_check_tasks/index.html.erb b/app/views/compliance_check_tasks/index.html.erb new file mode 100644 index 000000000..e28d98f1a --- /dev/null +++ b/app/views/compliance_check_tasks/index.html.erb @@ -0,0 +1,18 @@ +<%= title_tag t('.title') %> +<div class="warning"><%= t('.warning') %> </div> +<div class="page_info"> + <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @compliance_check_tasks %> +</div> +<div class="compliance_check_tasks paginated_content"> + <%= render :partial => "compliance_check_task", :collection => @compliance_check_tasks %> +</div> +<div class="pagination"> + <%= will_paginate @compliance_check_tasks, :container => false %> +</div> + +<% content_for :sidebar do %> +<ul class="actions"> + <li><%= link_to t('compliance_check_tasks.actions.new'), new_referential_compliance_check_task_path(), :class => "add" %></li> + <li><%= link_to t('rule_parameter_sets.actions.index'), referential_rule_parameter_sets_path(@referential), :class => "link" %></li> +</ul> +<% end %> diff --git a/app/views/compliance_check_tasks/new.html.erb b/app/views/compliance_check_tasks/new.html.erb new file mode 100644 index 000000000..1d15377e4 --- /dev/null +++ b/app/views/compliance_check_tasks/new.html.erb @@ -0,0 +1,22 @@ +<%= title_tag t(".title") %> + +<%= semantic_form_for [@referential, @compliance_check_task] do |form| %> + <%= form.inputs do %> + <%= form.input :rule_parameter_set_id, :as => :select, + :collection => @referential.rule_parameter_sets.map { |rps| [ rps.name, rps.id ] }, :include_blank => false %> + + <%= form.input :references_type, :as => :select, :collection => ComplianceCheckTask.references_types.map { |c| [ c.model_name.human.capitalize.pluralize, c.name ] }, :include_blank => t(".all") %> + + <% ComplianceCheckTask.references_types.each do |type| %> + <%= type_ids_model_references_input(form, @compliance_check_task, ComplianceCheckTask, type).input %> + <% end %> + <% end %> + + <%= form.actions do %> + <%= form.action :submit, :as => :button , :label => t( 'formtastic.validate' ) %> + <%= form.action :cancel, :as => :link %> + <% end %> +<% end %> + +<%= javascript_include_tag new_referential_compliance_check_task_path(@referential, :format => :js) %> + diff --git a/app/views/compliance_check_tasks/new.js.coffee b/app/views/compliance_check_tasks/new.js.coffee new file mode 100644 index 000000000..f8f60ac79 --- /dev/null +++ b/app/views/compliance_check_tasks/new.js.coffee @@ -0,0 +1,4 @@ +jQuery -> + <% ComplianceCheckTask.references_types.map { |type| type_ids_model_references_type( ComplianceCheckTask, type)}.each do |rt| %> + $("textarea.<%= rt.input_class %>").tokenInput('<%= references_referential_compliance_check_tasks_path(@referential, :type => rt.relation_name, :format => :json) %>', { prePopulate: $('#').data('pre'), minChars: 1 }); + <% end %> diff --git a/app/views/compliance_check_tasks/show.html.erb b/app/views/compliance_check_tasks/show.html.erb new file mode 100644 index 000000000..239cea7dc --- /dev/null +++ b/app/views/compliance_check_tasks/show.html.erb @@ -0,0 +1,38 @@ +<%= title_tag "#{@compliance_check_task.name} <span class='status status_#{@compliance_check_task.status}'>#{ t('compliance_check_tasks.show.'+@compliance_check_task.status) }</span>" %> + +<div class="compliance_check_task_show"> + <div class="links"> + <% if @compliance_check_task.import_task %> + <%= link_to t("compliance_check_tasks.import_task"), referential_import_task_path(@compliance_check_task.referential, @compliance_check_task.import_task), :class => "btn btn-default" %> + <% end %> + <% if @compliance_check_task.rule_parameter_set_archived %> + <%= link_to t("compliance_check_tasks.rule_parameter_set"), rule_parameter_set_referential_compliance_check_task_path(@compliance_check_task.referential, @compliance_check_task), :class => "btn btn-default" %> + <% end %> + </div> + <% if @compliance_check_task.status == 'completed'%> + <div class="resume"> + <div class="col1"> + <div class="caption"><%= t "error", :scope => "compliance_check_result.severities" %></div> + <div class="graph" id="error"></div> + </div> + <div class="col2"> + <div class="caption"><%= t "warning", :scope => "compliance_check_result.severities" %></div> + <div class="graph" id="warning"></div> + </div> + </div> + <div class="order" style="display: none;"> + Filtre : <%= select_tag "order", ("<option value='severity'>" + ComplianceCheckResult.human_attribute_name(:severity) +"</option><option value='status'>" + ComplianceCheckResult.human_attribute_name(:status) + "</option>").html_safe, :include_blank => false %> + </div> + + <div class="report"></div> + <% end %> + <%= javascript_include_tag referential_compliance_check_task_path(@compliance_check_task.referential, @compliance_check_task,:format => :js) %> +</div> +<% content_for :sidebar do %> +<ul class="actions"> + <li><%= link_to t('compliance_check_tasks.actions.destroy'), referential_compliance_check_task_path(@referential, @compliance_check_task), :method => :delete, :data => {:confirm => t('compliance_check_tasks.actions.destroy_confirm')}, :class => "remove" %></li> +</ul> + +<%= history_tag(@compliance_check_task) %> + +<% end %> diff --git a/app/views/compliance_check_tasks/show.js.coffee b/app/views/compliance_check_tasks/show.js.coffee new file mode 100644 index 000000000..ffcc6dc5b --- /dev/null +++ b/app/views/compliance_check_tasks/show.js.coffee @@ -0,0 +1,62 @@ +jQuery -> + + get_compliance_check_results = (html_container, status, severity) -> + h = new Object() + h["status"] = status if status + h["severity"] = severity if severity + $.get( + "<%= @compliance_check_task.id %>/compliance_check_results", + h, + update = (data) -> + html_container.append(data) + ) + + order_change = (event) -> + console.log "order change" + + $('.compliance_check_tasks.show .order').change(order_change) + + Morris.Donut({ + element: 'error', + data: [ + {label: "<%= t 'nok', :scope => 'compliance_check_result.statuses' %>", value: <%= @compliance_check_task.compliance_check_results.nok.error.count %>}, + {label: "<%= t 'na', :scope => 'compliance_check_result.statuses' %>", value: <%= @compliance_check_task.compliance_check_results.na.error.count %>}, + {label: "<%= t 'ok', :scope => 'compliance_check_result.statuses' %>", value: <%= @compliance_check_task.compliance_check_results.ok.error.count %>} + ] + colors: [ "#e22b1b", "#ffbd2b", "#8fc861" ] + }).on('click', update = (i, row) -> + $(".report").empty() + switch i + when 0 then get_compliance_check_results( $(".report"), "nok", "error") + when 1 then get_compliance_check_results( $(".report"), "na", "error") + when 2 then get_compliance_check_results( $(".report"), "ok", "error") + else console.log "Error no other value for donut chart") + + Morris.Donut({ + element: 'warning', + data: [ + {label: "<%= t 'nok', :scope => 'compliance_check_result.statuses' %>", value: <%= @compliance_check_task.compliance_check_results.nok.warning.count %>}, + {label: "<%= t 'na', :scope => 'compliance_check_result.statuses' %>", value: <%= @compliance_check_task.compliance_check_results.na.warning.count %>}, + {label: "<%= t 'ok', :scope => 'compliance_check_result.statuses' %>", value: <%= @compliance_check_task.compliance_check_results.ok.warning.count %>} + ] + colors: [ "#e22b1b", "#ffbd2b", "#8fc861" ] + }).on('click', update = (i, row) -> + $(".report").empty() + switch i + when 0 then get_compliance_check_results( $(".report"), "nok", "warning") + when 1 then get_compliance_check_results( $(".report"), "na", "warning") + when 2 then get_compliance_check_results( $(".report"), "ok", "warning") + else console.log "Error no other value for donut chart") + + $(".resume .col1 .caption").click -> + $(".report").empty() + get_compliance_check_results( $(".report"), null, "error") + + $(".resume .col2 .caption").click -> + $(".report").empty() + get_compliance_check_results( $(".report"), null, "warning") + + $('img[title]').tipsy({gravity: 'w'}) + $('a[title]').tipsy({gravity: 'w'}) + + diff --git a/app/views/connection_links/_connection_link.erb b/app/views/connection_links/_connection_link.erb index 01128051a..0cdcd6f34 100644 --- a/app/views/connection_links/_connection_link.erb +++ b/app/views/connection_links/_connection_link.erb @@ -1,21 +1,21 @@ <%= div_for(connection_link) do %> - <%= link_to truncate(connection_link.name, :length => 30), [@referential, connection_link], :title => "#{Chouette::TimeTable.model_name.human} #{connection_link.name}" %> + <%= link_to truncate(connection_link.name, :length => 35), [@referential, connection_link], :title => "#{Chouette::TimeTable.model_name.human} #{connection_link.name}" %> <div class="info"> <%= t('.from') %> - <% if connection_link.departure.present? %> - <%= link_to_if connection_link.departure, connection_link.departure.name, referential_stop_area_path(@referential, connection_link.departure), :title => "#{connection_link.human_attribute_name('departure')} #{connection_link.departure.name}" %> + <% if connection_link.departure.present? %> + <%= link_to_if connection_link.departure, truncate(connection_link.departure.name, :length => 15) , referential_stop_area_path(@referential, connection_link.departure), :title => "#{connection_link.human_attribute_name('departure')} #{connection_link.departure.name}" %> <% else %> - <%= connection_link.human_attribute_name('undefined') %> + <%= connection_link.human_attribute_name('undefined') %> <% end %> <%= t('.to') %> - <% if connection_link.arrival.present? %> - <%= link_to_if( connection_link.arrival, connection_link.arrival.name, referential_stop_area_path(@referential, connection_link.arrival), :title => "#{connection_link.human_attribute_name('arrival')} #{connection_link.arrival.name}" ) %> + <% if connection_link.arrival.present? %> + <%= link_to_if( connection_link.arrival, truncate(connection_link.arrival.name, :length => 15), referential_stop_area_path(@referential, connection_link.arrival), :title => "#{connection_link.human_attribute_name('arrival')} #{connection_link.arrival.name}" ) %> <% else %> <%= connection_link.human_attribute_name("undefined") %> - <% end %> - - <%= connection_link.human_attribute_name('default_duration').capitalize %>: <%= connection_link.default_duration ? connection_link.default_duration.strftime('%Mm %Ss') : connection_link.human_attribute_name("undefined") %> + <% end %> - + <%= connection_link.human_attribute_name('default_duration').capitalize %>: <%= connection_link.default_duration ? connection_link.default_duration.strftime('%Mm %Ss') : connection_link.human_attribute_name("undefined") %> - <div class="actions"> + <div class="actions"> <%= link_to t("actions.edit"), edit_referential_connection_link_path(@referential, connection_link), :class => "edit" %> | <%= link_to t("actions.destroy"), referential_connection_link_path(@referential, connection_link), :method => :delete, :data => {:confirm => t('connection_links.actions.destroy_confirm')}, :class => "remove" %> </div> diff --git a/app/views/exports/new.html.erb b/app/views/exports/new.html.erb index 60c1cff48..553ebe4a2 100644 --- a/app/views/exports/new.html.erb +++ b/app/views/exports/new.html.erb @@ -8,7 +8,7 @@ <% @available_exports.each do |export| %> <%= semantic_form_for [@referential, export], :as => :export, :url => referential_exports_path(@referential), :html => { :id => "#{export.type}_new", :style => ('display: none' unless @export == export)} do |form| %> - <%= form.inputs do %> + <%= form.inputs do %> <%= fields_for_export_type form %> <% end %> <%= form.inputs do %> @@ -17,7 +17,7 @@ <%= form.input :references_type, :as => :select, :collection => Export.references_types.map { |c| [ c.model_name.human.capitalize.pluralize, c.name ] }, :include_blank => t(".all") %> <% Export.references_types.each do |type| %> - <%= export_references_input(form, @export, type).input %> + <%= type_ids_model_references_input(form, @export, Export, type).input %> <% end %> <% end %> diff --git a/app/views/exports/new.js.coffee b/app/views/exports/new.js.coffee index f3d815d82..01835f404 100644 --- a/app/views/exports/new.js.coffee +++ b/app/views/exports/new.js.coffee @@ -1,4 +1,4 @@ jQuery -> - <% Export.references_types.each do |type| %> - $("textarea.<%= export_references_type(type).input_class %>").tokenInput('<%= references_referential_exports_path(@referential, :type => export_references_type(type).relation_name, :format => :json) %>', { prePopulate: $('#').data('pre'), minChars: 1 }); + <% Export.references_types.map { |type| type_ids_model_references_type( Export, type)}.each do |rt| %> + $("textarea.<%= rt.input_class %>").tokenInput('<%= references_referential_compliance_check_tasks_path(@referential, :type => rt.relation_name, :format => :json) %>', { prePopulate: $('#').data('pre'), minChars: 1 }); <% end %> diff --git a/app/views/file_validations/_file_validation.erb b/app/views/file_validations/_file_validation.erb deleted file mode 100644 index 7ffed1417..000000000 --- a/app/views/file_validations/_file_validation.erb +++ /dev/null @@ -1,13 +0,0 @@ -<%= div_for(file_validation, :class => :file_validation) do %> - <%= link_to(file_validation_path(file_validation), :class => "preview") do %> - <%= image_tag "file-validation-#{file_validation.status}.png" %> - <% end %> - <%= link_to(file_validation.name, file_validation_path(file_validation)) %> - <div class="info"> - <%= l file_validation.created_at %><br/> - <%= file_validation.file_name %> - <div class="actions"> - <%= link_to t("actions.destroy"), file_validation_path(file_validation), :method => :delete, :data => {:confirm => t('file_validations.actions.destroy_confirm')}, :class => "remove" %> - </div> - </div> -<% end %> diff --git a/app/views/file_validations/index.html.erb b/app/views/file_validations/index.html.erb deleted file mode 100644 index 2e0cefbe8..000000000 --- a/app/views/file_validations/index.html.erb +++ /dev/null @@ -1,20 +0,0 @@ -<%= title_tag t('.title') %> -<div class="warning"><%= t('.warning') %> </div> -<div class="pagination"> - <div class="page_info"> - <%= page_entries_info @file_validations %> - </div> - <%= will_paginate @file_validations, :container => false %> -</div> -<div class="file_validations paginated_content"> - <%= render :partial => "file_validation", :collection => @file_validations %> -</div> -<div class="pagination"> - <%= will_paginate @file_validations, :container => false %> -</div> - -<% content_for :sidebar do %> -<ul class="actions"> - <li><%= link_to t('file_validations.actions.new'), new_file_validation_path(), :class => "add" %></li> -</ul> -<% end %> diff --git a/app/views/file_validations/new.html.erb b/app/views/file_validations/new.html.erb deleted file mode 100644 index 3a86cfac9..000000000 --- a/app/views/file_validations/new.html.erb +++ /dev/null @@ -1,51 +0,0 @@ -<%= title_tag t(".title") %> - -<%= semantic_form_for @file_validation do |form| %> - <%= form.inputs do %> - <%= form.input :resources, :as => :file %> - <%= form.input :test3_1_minimal_distance, :as => :number,:input_html => { :value => '10.0' }, :wrapper_html => { :class => 'fl' } %> - <%= form.input :test3_2_minimal_distance, :as => :number,:input_html => { :value => '10.0' }, :wrapper_html => { :class => 'fl' } %> - <%= form.input :test3_2_polygon_points , :as => :text ,:input_html => { :rows => '4', :value => '2.303466,51.399206 8.411865,49.05227 7.950439,43.34116 3.138427,41.869561 -2.376709,43.2932 -5.848389,48.705463' }%> - <%= form.input :test3_7_minimal_distance, :as => :number ,:input_html => { :value => '50.0' }, :wrapper_html => { :class => 'fl1' } %> - <%= form.input :test3_7_maximal_distance, :as => :number ,:input_html => { :value => '15000.0' },:wrapper_html => { :class => 'fl2' } %> - <%= form.input :test3_8a_minimal_speed, :as => :number ,:input_html => { :value => '3.0' }, :wrapper_html => { :class => 'fl1' } %> - <%= form.input :test3_8a_maximal_speed, :as => :number ,:input_html => { :value => '6.0' }, :wrapper_html => { :class => 'fl2' } %> - <%= form.input :test3_8b_minimal_speed, :as => :number ,:input_html => { :value => '4.0' }, :wrapper_html => { :class => 'fl1' } %> - <%= form.input :test3_8b_maximal_speed, :as => :number ,:input_html => { :value => '7.0' }, :wrapper_html => { :class => 'fl2' } %> - <%= form.input :test3_8c_minimal_speed, :as => :number ,:input_html => { :value => '2.0' }, :wrapper_html => { :class => 'fl1' } %> - <%= form.input :test3_8c_maximal_speed, :as => :number ,:input_html => { :value => '5.0' }, :wrapper_html => { :class => 'fl2' } %> - <%= form.input :test3_8d_minimal_speed, :as => :number ,:input_html => { :value => '1.0' }, :wrapper_html => { :class => 'fl1' } %> - <%= form.input :test3_8d_maximal_speed, :as => :number ,:input_html => { :value => '4.0' }, :wrapper_html => { :class => 'fl2' } %> - <%= form.input :test3_9_minimal_speed, :as => :number ,:input_html => { :value => '5.0' }, :wrapper_html => { :class => 'fl1' } %> - <%= form.input :test3_9_maximal_speed, :as => :number ,:input_html => { :value => '45.0' }, :wrapper_html => { :class => 'fl2' } %> - <% end %> - <%= form.inputs do %> - <%= form.input :test3_10_minimal_distance, :as => :number ,:input_html => { :value => '50.0' }, :wrapper_html => { :class => 'fl' } %> - <%= form.input :test3_15_minimal_time, :as => :number,:input_html => { :value => '1' }, :wrapper_html => { :class => 'fl' } %> - <%= form.input :test3_16_1_maximal_time, :as => :number,:input_html => { :value => '120' }, :wrapper_html => { :class => 'fl' } %> - <%= form.input :test3_16_3a_maximal_time, :as => :number ,:input_html => { :value => '600' }, :wrapper_html => { :class => 'fl' } %> - <%= form.input :test3_16_3b_maximal_time, :as => :number ,:input_html => { :value => '300' }, :wrapper_html => { :class => 'fl' } %> - <%= form.input :test3_21a_minimal_speed, :as => :number ,:input_html => { :value => '3.0' }, :wrapper_html => { :class => 'fl1' } %> - <%= form.input :test3_21a_maximal_speed, :as => :number ,:input_html => { :value => '6.0' }, :wrapper_html => { :class => 'fl2' } %> - <%= form.input :test3_21b_minimal_speed, :as => :number ,:input_html => { :value => '4.0' }, :wrapper_html => { :class => 'fl1' } %> - <%= form.input :test3_21b_maximal_speed, :as => :number ,:input_html => { :value => '7.0' }, :wrapper_html => { :class => 'fl2' } %> - <%= form.input :test3_21c_minimal_speed, :as => :number ,:input_html => { :value => '2.0' }, :wrapper_html => { :class => 'fl1' } %> - <%= form.input :test3_21c_maximal_speed, :as => :number ,:input_html => { :value => '2.0' }, :wrapper_html => { :class => 'fl2' } %> - <%= form.input :test3_21d_minimal_speed, :as => :number ,:input_html => { :value => '1.0' }, :wrapper_html => { :class => 'fl1' } %> - <%= form.input :test3_21d_maximal_speed, :as => :number ,:input_html => { :value => '4.0' }, :wrapper_html => { :class => 'fl2' } %> - <% end %> - <%= form.inputs do %> - <%= form.input :projection_reference ,:input_html => { :value => 'WGS84' }, :wrapper_html => { :class => 'fl' } %> - <% end %> - - <%= form.actions do %> - <%= form.action :submit, :as => :button , :label => t( 'formtastic.validate' ) %> - <%= form.action :cancel, :as => :link %> - <% end %> -<% end %> - -<% content_for :sidebar do %> -<%= render :partial => "test_sheet_toc" %> -<% end %> - - diff --git a/app/views/file_validations/show.html.erb b/app/views/file_validations/show.html.erb deleted file mode 100644 index d3d53fde5..000000000 --- a/app/views/file_validations/show.html.erb +++ /dev/null @@ -1,151 +0,0 @@ -<%= title_tag @file_validation.name %> - -<div class="file_validation_show"> - <div class="panelDataSection"><%= t(".summary") %></div> - - <div class="neptune-panel"> - <label><%= FileValidation.human_attribute_name(:created_at) %>: </label> - <%= l @file_validation.created_at %><br/> - <label><%= FileValidation.human_attribute_name(:status) %>: </label> - <%= t @file_validation.status, :scope => "file_validations.statuses" %><br/> - <label><%= FileValidation.human_attribute_name(:file_name) %>: </label> - <%= @file_validation.file_name %><br/> - <br/> - <br/> - <% if @file_validation.status == 'completed' %> - <table> - <tbody> - <tr> - <td><%= image_tag "severity-uncheck.png" , :alt => t("uncheck", :scope => "file_validation_log_messages.severities") %> - <%= t( "file_validations.uncheck_count" , :count => @file_validation.uncheck_count )%> - </td> - <td><%= image_tag "severity-ok.png" , :alt => t("ok", :scope => "file_validation_log_messages.severities") %> - <%= t( "file_validations.ok_count" , :count => @file_validation.ok_count )%> - </td> - <td><%= image_tag "severity-warning.png" , :alt => t("warning", :scope => "file_validation_log_messages.severities") %> - <%= t( "file_validations.warning_count" , :count => @file_validation.warning_count )%> - </td> - <td><%= image_tag "severity-error.png" , :alt => t("error", :scope => "file_validation_log_messages.severities") %> - <%= t( "file_validations.error_count" , :count => @file_validation.error_count )%> - </td> - <td><%= image_tag "severity-fatal.png" , :alt => t("fatal", :scope => "file_validation_log_messages.severities") %> - <%= t( "file_validations.fatal_count" , :count => @file_validation.fatal_count )%> - </td> - </tr> - </tbody> - </table> - <% end %> - </div> -<% if @file_validation.status == 'completed' %> - <h3><%= t(".details") %></h3> - <% @file_validation.log_message_tree.each do |message1| %> - <label class="category"><%= message1.full_message %></label> - <div id="<%= message1.key %>" style="margin-left: 40px;"> - <% message1.children.each do |message2| %> - <div class="panelDataSection"><%= message2.full_message %></div> - <div id="<%= message2.severity %>" class="neptune-panel"> - <% message2.children.each do |message3| %> - <div class="<%= message3.severity %>"> - <div> - <label id=""><%= message3.label %></label> - </div> - <div id="" class="step"> - <%= message3.full_message %> - </div> - </div> - <% if !message3.children.nil? %> - <div id="" class="detail"> </div> - <div id="detail_0_4_0" class="neptune-panel-inSide"> - <ol> - <% message3.children.each do |message4| %> - <li> <%= message4.full_message %> </li> - <br> - <% end %> - </ol> - </div> - <% end %> - <% end %> - </div> - <% end %> - </div> - <% end %> - <div class="panelDataSection"><%= t(".parameters") %></div> - <div class="neptune-panel"> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_1_minimal_distance") %> :</label> - <label><%= @file_validation.test3_1_minimal_distance %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_2_minimal_distance") %> :</label> - <label><%= @file_validation.test3_2_minimal_distance %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_2_polygon_points") %> :</label> - <label><%= @file_validation.test3_2_polygon_points %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_7_minimal_distance") %> :</label> - <label><%= @file_validation.test3_7_minimal_distance %></label> / - <label><%= @file_validation.test3_7_maximal_distance %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_8a_minimal_speed") %> :</label> - <label><%= @file_validation.test3_8a_minimal_speed %></label> / - <label><%= @file_validation.test3_8a_maximal_speed %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_8b_minimal_speed") %> :</label> - <label><%= @file_validation.test3_8b_minimal_speed %></label> / - <label><%= @file_validation.test3_8b_maximal_speed %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_8c_minimal_speed") %> :</label> - <label><%= @file_validation.test3_8c_minimal_speed %></label> / - <label><%= @file_validation.test3_8c_maximal_speed %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_8d_minimal_speed") %> :</label> - <label><%= @file_validation.test3_8d_minimal_speed %></label> / - <label><%= @file_validation.test3_8d_maximal_speed %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_9_minimal_speed") %> :</label> - <label><%= @file_validation.test3_9_minimal_speed %></label> / - <label><%= @file_validation.test3_9_maximal_speed %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_10_minimal_distance") %> :</label> - <label><%= @file_validation.test3_10_minimal_distance %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_15_minimal_time") %> :</label> - <label><%= @file_validation.test3_15_minimal_time %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_16_1_maximal_time") %> :</label> - <label><%= @file_validation.test3_16_1_maximal_time %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_16_3a_maximal_time") %> :</label> - <label><%= @file_validation.test3_16_3a_maximal_time %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_16_3b_maximal_time") %> :</label> - <label><%= @file_validation.test3_16_3b_maximal_time %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_21a_minimal_speed") %> :</label> - <label><%= @file_validation.test3_21a_minimal_speed %></label> / - <label><%= @file_validation.test3_21a_maximal_speed %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_21b_minimal_speed") %> :</label> - <label><%= @file_validation.test3_21b_minimal_speed %></label> / - <label><%= @file_validation.test3_21b_maximal_speed %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_21c_minimal_speed") %> :</label> - <label><%= @file_validation.test3_21c_minimal_speed %></label> / - <label><%= @file_validation.test3_21c_maximal_speed %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.test3_21d_minimal_speed") %> :</label> - <label><%= @file_validation.test3_21d_minimal_speed %></label> / - <label><%= @file_validation.test3_21d_maximal_speed %></label> - <br> - <label class="label"><%= t("activerecord.attributes.file_validation.projection_reference") %> :</label> - <label><%= @file_validation.projection_reference %></label> - - </div> - - <% end %> -</div> -<% content_for :sidebar do %> -<ul class="actions"> - <li><%= link_to t('file_validations.actions.destroy'), file_validation_path(@file_validation), :method => :delete, :data => {:confirm => t('file_validations.actions.destroy_confirm')}, :class => "remove" %></li> -</ul> -<%= render :partial => "test_sheet_toc" %> - -<% end %> diff --git a/app/views/import_tasks/_fields_csv_import.erb b/app/views/import_tasks/_fields_csv_import.erb new file mode 100644 index 000000000..b4ae719a5 --- /dev/null +++ b/app/views/import_tasks/_fields_csv_import.erb @@ -0,0 +1 @@ +<%= form.input :object_id_prefix, :input_html => { :value => @referential.prefix } %> diff --git a/app/views/import_tasks/_fields_gtfs_import.erb b/app/views/import_tasks/_fields_gtfs_import.erb new file mode 100644 index 000000000..842a24ab7 --- /dev/null +++ b/app/views/import_tasks/_fields_gtfs_import.erb @@ -0,0 +1,7 @@ +<%= form.input :object_id_prefix, :input_html => { :value => @referential.prefix } %> +<%= form.input :max_distance_for_commercial , :as => :number , :input_html => { :title => t("tipsy.hints.import_task.max_distance_for_commercial"), :value => 50 } %> +<%= form.input :ignore_last_word , :as => :boolean , :input_html => { :title => t("tipsy.hints.import_task.ignore_last_word"), :value => false }%> +<%= form.input :ignore_end_chars , :as => :number , :input_html => { :title => t("tipsy.hints.import_task.ignore_end_chars"), :value => 0 }%> +<%= form.input :max_distance_for_connection_link , :as => :number , :input_html => { :title => t("tipsy.hints.import_task.max_distance_for_connection_link"), :value => 100 }%> + + diff --git a/app/views/import_tasks/_import_task.erb b/app/views/import_tasks/_import_task.erb new file mode 100644 index 000000000..afa235d4d --- /dev/null +++ b/app/views/import_tasks/_import_task.erb @@ -0,0 +1,20 @@ +<%= div_for import_task do %> + <div class="icon"> + <%= link_to image_tag("import_task-#{import_task.status}.png"), referential_import_task_path(@referential, import_task) %> + </div> + <div class="resume"> + <ul class="header clearfix"> + <li class="title"><%= link_to(import_task.name, referential_import_task_path(@referential, import_task)) %></li> + <li class="remove"><%= link_to "<i class='fa fa-trash-o'></i>".html_safe, referential_import_task_path(@referential, import_task), :method => :delete, :class => "delete", :data => {:confirm => t('import_tasks.actions.destroy_confirm')} %></li> + </ul> + <div class="links"> + <p><%= link_to image_tag("icons/file_#{import_task.file_path_extension}.png") + t("import_tasks.index.imported_file"), file_to_import_referential_import_task_path(@referential, import_task) %></p> + <% if import_task.compliance_check_task.present? %> + <p><%= link_to image_tag('icons/link_page.png') + t("import_tasks.compliance_check_task"), referential_compliance_check_task_path(@referential, import_task.compliance_check_task) %></p> + <% end %> + </div> + <div class="history"> + <%= l import_task.created_at, :format => "%d/%m/%Y %H:%M" %> | <%= import_task.user_name %> + </div> + </div> +<% end %> diff --git a/app/views/import_tasks/_results_dashboard.html.erb b/app/views/import_tasks/_results_dashboard.html.erb new file mode 100644 index 000000000..d1e674964 --- /dev/null +++ b/app/views/import_tasks/_results_dashboard.html.erb @@ -0,0 +1,67 @@ + <div class="resume"> + <div class="col1"> + <% file_title = (@import_task.file_path_extension=="zip") ? t( "import_tasks.show.graph.files.title_zip") : t( "import_tasks.show.graph.files.title_default", :extension => @import_task.file_path_extension)%> + <div class="caption"><%= file_title %></div> + <div id="files_statistics"></div> + </div> + <div class="col2"> + <div class="caption"><%= t "import_tasks.show.graph.lines.title" %></div> + <div id="objects_statistics"></div> + </div> + </div> + <div class="report"> + <div class="files files_error"> + <% @files_list["error"].each_with_index do |error, index| %> + <% index += 1 %> + <%= image_tag "icons/file_xml_md.png" %><span class="file_name"><%= truncate(error["name"], :length => 20) %></span> <% if index%4 == 0 %><br><% end %> + <% end %> + </div> + <div class="files files_ignored"> + <% @files_list["ignored"].each_with_index do |ignored, index| %> + <% index += 1 %> + <%= image_tag "icons/file_xml_md.png" %><span class="file_name"><%= truncate(ignored["name"], :length => 20) %></span> <% if index%4 == 0 %><br><% end %> + <% end %> + </div> + <div class="files files_ok"> + <% @files_list["ok"].each_with_index do |ok, index| %> + <% index += 1 %> + <%= image_tag "icons/file_xml_md.png" %><span class="file_name"><%= truncate(ok["name"], :length => 20) %></span> <% if index%4 == 0 %><br><% end %> + <% end %> + </div> + <div class="lines"> + <table class="table table-hover"> + <thead> + <tr> + <th>#</th> + <th><%= t("import_tasks.show.table.line.name") %></th> + <th><%= t("import_tasks.show.table.line.save") %></th> + <th><%= t("import_tasks.show.table.line.routes") %></th> + <th><%= t("import_tasks.show.table.line.connection_links") %></th> + <th><%= t("import_tasks.show.table.line.time_tables") %></th> + <th><%= t("import_tasks.show.table.line.stop_areas") %></th> + <th><%= t("import_tasks.show.table.line.access_points") %></th> + <th><%= t("import_tasks.show.table.line.vehicle_journeys") %></th> + <th><%= t("import_tasks.show.table.line.journey_patterns") %></th> + </tr> + </thead> + <tbody> + <% @lines_list.each_with_index do |line, index| %> + <tr> + <td><%= index + 1 %></td> + <td><%= line["name"] %></td> + <td><%= t("import_tasks.show.table.line." + line["status"] ) %></td> + <td><%= line["stats"]["route_count"] %></td> + <td><%= line["stats"]["connection_link_count"] %></td> + <td><%= line["stats"]["time_table_count"] %></td> + <td><%= line["stats"]["stop_area_count"] %></td> + <td><%= line["stats"]["acces_point_count"] %></td> + <td><%= line["stats"]["vehicle_journey_count"] %></td> + <td><%= line["stats"]["journey_pattern_count"] %></td> + </tr> + <% end %> + </tbody> + </table> + </div> + </div> + <%= javascript_include_tag referential_import_task_path(@import_task.referential, @import_task,:format => :js) %> + diff --git a/app/views/import_tasks/index.html.erb b/app/views/import_tasks/index.html.erb new file mode 100644 index 000000000..df70120b5 --- /dev/null +++ b/app/views/import_tasks/index.html.erb @@ -0,0 +1,18 @@ +<%= title_tag t('.title') %> +<div class="warning"><%= t('.warning') %> </div> +<div class="page_info"> + <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @import_tasks %> +</div> +<div class="import_tasks paginated_content"> + <%= render :partial => "import_task", :collection => @import_tasks %> +</div> +<div class="pagination"> + <%= will_paginate @import_tasks, :container => false %> +</div> + +<% content_for :sidebar do %> +<ul class="actions"> + <li><%= link_to t('import_tasks.actions.new'), new_referential_import_task_path(@referential), :class => "add" %></li> + <li><%= link_to t('rule_parameter_sets.actions.index'), referential_rule_parameter_sets_path(@referential), :class => "link" %></li> +</ul> +<% end %> diff --git a/app/views/import_tasks/new.html.erb b/app/views/import_tasks/new.html.erb new file mode 100644 index 000000000..13888ad39 --- /dev/null +++ b/app/views/import_tasks/new.html.erb @@ -0,0 +1,31 @@ +<%= title_tag t(".title") %> + +<%= semantic_form_for([@referential, @import_task], :as => :import_task, :url => new_referential_import_task_path(@referential), :method => :get) do |form| %> + <%= form.inputs do %> + <%= form.input :format, :as => :radio, :collection => ImportTask.formats, :required => true, :include_blank => false %> + <% end %> +<% end %> + +<% @available_imports.each do |import_task| %> + <%= semantic_form_for [@referential, import_task], :as => :import_task, :url => referential_import_tasks_path(@referential), :html => { :id => "#{import_task.format}_new", :style => ('display: none' unless @import_task == import_task)} do |form| %> + + <%= form.inputs do %> + <%= fields_for_import_task_format form %> + <% end %> + + <%= form.inputs do %> + <%= form.input :format, :as => :hidden %> + <%= form.input :no_save, :as => :boolean, :collection => [true, false] %> + <%= form.input :rule_parameter_set_id, :as => :select, + :collection => @referential.rule_parameter_sets.map { |rps| [ rps.name, rps.id ] }, :include_blank => true %> + <%= form.input :resources, :as => :file %> + <% end %> + + <%= form.actions do %> + <%= form.action :submit, :as => :button , :label => t( 'formtastic.import' ) %> + <%= form.action :cancel, :as => :link %> + <% end %> + <% end %> +<% end %> + + diff --git a/app/views/import_tasks/show.html.erb b/app/views/import_tasks/show.html.erb new file mode 100644 index 000000000..781b9b07e --- /dev/null +++ b/app/views/import_tasks/show.html.erb @@ -0,0 +1,20 @@ +<%= title_tag "#{@import_task.full_name} <span class='status status_#{@import_task.status}'>#{ t('import_tasks.show.'+@import_task.status) }</span>" %> + +<div class="import_task_show"> + <div class="links"> + <%= link_to t("import_tasks.show.imported_file"), file_to_import_referential_import_task_path(@import_task.referential, @import_task), :class => "btn btn-default" %> + <% if @import_task.compliance_check_task %> + <%= link_to t("import_tasks.compliance_check_task"), referential_compliance_check_task_path(@import_task.referential, @import_task.compliance_check_task), :class => "btn btn-default" %> + <% end %> + </div> + <%= render( :partial => "results_dashboard") if @import_task.completed? %> +</div> + +<% content_for :sidebar do %> +<ul class="actions"> + <li><%= link_to t('import_tasks.actions.destroy'), referential_import_task_path(@referential, @import_task), :method => :delete, :data => {:confirm => t('import_tasks.actions.destroy_confirm')}, :class => "remove" %></li> +</ul> + +<%= history_tag(@import_task) %> + +<% end %> diff --git a/app/views/import_tasks/show.js.coffee b/app/views/import_tasks/show.js.coffee new file mode 100644 index 000000000..accd8e720 --- /dev/null +++ b/app/views/import_tasks/show.js.coffee @@ -0,0 +1,41 @@ +jQuery -> + + get_import_results = (html_container, html_element) -> + html_container.children().each -> + if( $( this ).is(html_element) ) + $( this ).show() + else + $( this ).hide() + + Morris.Donut({ + element: 'files_statistics', + data: [ + {label: "<%= t 'import_tasks.show.graph.files.error' %>", value: <%= @files_stats["error_count"] %> }, + {label: "<%= t 'import_tasks.show.graph.files.ignored' %>", value: <%= @files_stats["ignored_count"] %> }, + {label: "<%= t 'import_tasks.show.graph.files.ok' %>", value: <%= @files_stats["ok_count"] %> } + ] + colors: [ "#e22b1b", "#ffbd2b", "#8fc861" ] + }).on('click', update = (i, row) -> + switch i + when 0 then get_import_results( $(".report"), $(".files_error")) + when 1 then get_import_results( $(".report"), $(".files_ignored")) + when 2 then get_import_results( $(".report"), $(".files_ok")) + else console.log "Error no other value for donut chart") + + Morris.Bar({ + element: 'objects_statistics', + data: [ + { object: "<%= t("import_tasks.show.graph.lines.lines_stats") %>", value: <%= @lines_stats["line_count"] %> }, + { object: "<%= t("import_tasks.show.graph.lines.routes_stats") %>", value: <%= @lines_stats["route_count"] %> }, + { object: "<%= t("import_tasks.show.graph.lines.connection_links_stats") %>", value: <%= @lines_stats["connection_link_count"] %> }, + { object: "<%= t("import_tasks.show.graph.lines.time_tables_stats") %>", value: <%= @lines_stats["time_table_count"] %> }, + { object: "<%= t("import_tasks.show.graph.lines.stop_areas_stats") %>", value: <%= @lines_stats["stop_area_count"] %> }, + { object: "<%= t("import_tasks.show.graph.lines.access_points_stats") %>", value: <%= @lines_stats["access_point_count"] %> }, + { object: "<%= t("import_tasks.show.graph.lines.vehicle_journeys_stats") %>", value: <%= @lines_stats["vehicle_journey_count"] %> }, + { object: "<%= t("import_tasks.show.graph.lines.journey_patterns_stats") %>", value: <%= @lines_stats["journey_pattern_count"] %> }, + ], + xkey: 'object', + ykeys: ['value'], + labels: ['<%= t "import_tasks.show.graph.lines.objects_label" %>'] + }).on('click', update = (i, row) -> + get_import_results( $(".report"), $(".lines")) )
\ No newline at end of file diff --git a/app/views/imports/_fields_csv_import.erb b/app/views/imports/_fields_csv_import.erb deleted file mode 100644 index 2ab96acf7..000000000 --- a/app/views/imports/_fields_csv_import.erb +++ /dev/null @@ -1 +0,0 @@ -<%= form.input :objectid_prefix, :input_html => { :value => @referential.prefix } %> diff --git a/app/views/imports/_fields_gtfs_import.erb b/app/views/imports/_fields_gtfs_import.erb deleted file mode 100644 index dd75a41a5..000000000 --- a/app/views/imports/_fields_gtfs_import.erb +++ /dev/null @@ -1,7 +0,0 @@ -<%= form.input :objectid_prefix, :input_html => { :value => @referential.prefix } %> -<%= form.input :max_distance_for_commercial , :as => :number , :input_html => { :value => 50 } %> -<%= form.input :ignore_last_word , :as => :boolean , :input_html => { :value => false }%> -<%= form.input :ignore_end_chars , :as => :number , :input_html => { :value => 0 }%> -<%= form.input :max_distance_for_connection_link , :as => :number , :input_html => { :value => 100 }%> - - diff --git a/app/views/imports/_import.erb b/app/views/imports/_import.erb deleted file mode 100644 index 87e7c3190..000000000 --- a/app/views/imports/_import.erb +++ /dev/null @@ -1,13 +0,0 @@ -<%= div_for(import, :class => :import) do %> - <%= link_to(referential_import_path(@referential, import), :class => "preview") do %> - <%= image_tag "import-#{import.status}.png" %> - <% end %> - <%= link_to(import.name, referential_import_path(@referential, import)) %> - <div class="info"> - <%= l import.created_at %> - - <div class="actions"> - <%= link_to t("actions.destroy"), referential_import_path(@referential, import), :method => :delete, :data => {:confirm => t('imports.actions.destroy_confirm')}, :class => "remove" %> - </div> - </div> -<% end %> diff --git a/app/views/imports/index.html.erb b/app/views/imports/index.html.erb deleted file mode 100644 index 8469fbd7b..000000000 --- a/app/views/imports/index.html.erb +++ /dev/null @@ -1,17 +0,0 @@ -<%= title_tag t('.title') %> -<div class="warning"><%= t('.warning') %> </div> -<div class="page_info"> - <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @imports %> -</div> -<div class="imports paginated_content"> - <%= render :partial => "import", :collection => @imports %> -</div> -<div class="pagination"> - <%= will_paginate @imports, :container => false %> -</div> - -<% content_for :sidebar do %> -<ul class="actions"> - <li><%= link_to t('imports.actions.new'), new_referential_import_path(@referential), :class => "add" %></li> -</ul> -<% end %> diff --git a/app/views/imports/new.html.erb b/app/views/imports/new.html.erb deleted file mode 100644 index f99ca9062..000000000 --- a/app/views/imports/new.html.erb +++ /dev/null @@ -1,26 +0,0 @@ -<%= title_tag t(".title") %> - -<%= semantic_form_for([@referential, @import], :as => :import, :url => new_referential_import_path(@referential), :method => :get) do |form| %> - <%= form.inputs do %> - <%= form.input :type, :as => :radio, :collection => Import.types.map { |format| [ Import.format_name(format), format]}, :required => true, :include_blank => false %> - <% end %> -<% end %> - -<% @available_imports.each do |import| %> - <%= semantic_form_for [@referential, import], :as => :import, :url => referential_imports_path(@referential), :html => { :id => "#{import.type}_new", :style => ('display: none' unless @import == import)} do |form| %> - - <%= form.inputs do %> - <%= fields_for_import_type form %> - <% end %> - - <%= form.inputs do %> - <%= form.input :type, :as => :hidden %> - <%= form.input :resources, :as => :file %> - <% end %> - - <%= form.actions do %> - <%= form.action :submit, :as => :button , :label => t( 'formtastic.import' ) %> - <%= form.action :cancel, :as => :link %> - <% end %> - <% end %> -<% end %> diff --git a/app/views/imports/show.html.erb b/app/views/imports/show.html.erb deleted file mode 100644 index 15c595e95..000000000 --- a/app/views/imports/show.html.erb +++ /dev/null @@ -1,42 +0,0 @@ -<%= title_tag @import.name %> - -<div class="import_show"> - <div class="summary"> - <p> - <label><%= Import.human_attribute_name(:created_at) %>: </label> - <%= l @import.created_at %> - </p> - <p> - <label><%= Import.human_attribute_name(:status) %>: </label> - <%= t @import.status, :scope => "imports.statuses" %> - </p> - </div> - - <% if @import.log_messages.empty? %> - <p> <%= t(".not_yet_started") %> </p> - <% else %> - <h3><%= t(".report") %></h3> - <table> - <tr> - <th class="severity"></th> - <th class="created_at"><%= ImportLogMessage.human_attribute_name(:created_at) %></th> - <th class="position"><%= ImportLogMessage.human_attribute_name(:position) %></th> - <th class="message"><%= ImportLogMessage.human_attribute_name(:full_message) %></th> - </tr> - <% @import.log_messages.each do |message| %> - <tr> - <td class="severity"><%= image_tag "severity-#{message.severity}.png", :alt => t(message.severity, :scope => "import_log_messages.severities") %></td> - <td class="created_at"><%= l message.created_at, :format => :short %></td> - <td class="position"><%= message.position %></td> - <td class="message"><%= message.full_message %></td> - </tr> - <% end %> - </table> - <% end %> -</div> - -<% content_for :sidebar do %> -<ul class="actions"> - <li><%= link_to t('imports.actions.destroy'), referential_import_path(@referential, @import), :method => :delete, :data => {:confirm => t('imports.actions.destroy_confirm')}, :class => "remove" %></li> -</ul> -<% end %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 81a87f5ae..e13a130e8 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -44,7 +44,6 @@ <% elsif ! selected_referential? %> <% if user_signed_in? %> <li><%= link_to Referential.model_name.human(:count=>2), referentials_path, :class => ("current" if current_page?(referentials_path) || current_page?(root_url)) %></li> - <li><%= tab_link_to FileValidation.model_name.human(:count=>2), file_validations_path %></li> <li class="admin"><%= tab_link_to Organisation.model_name.human, organisation_path %></li> <% end %> <% else %> @@ -56,18 +55,16 @@ <li><%= tab_link_to Chouette::StopArea, referential_stop_areas_path(@referential) %></li> <li><%= tab_link_to Chouette::ConnectionLink, referential_connection_links_path(@referential) %></li> <li><%= tab_link_to Chouette::TimeTable, referential_time_tables_path(@referential) %></li> - - <li><%= tab_link_to Import, referential_imports_path(@referential) %></li> + <li><%= tab_link_to ImportTask, referential_import_tasks_path(@referential) %></li> <li><%= tab_link_to Export, referential_exports_path(@referential) %></li> + <li><%= tab_link_to ComplianceCheckTask, referential_compliance_check_tasks_path(@referential) %></li> <% end %> </ul> </div> </div> <div id="body"> - <div id="flash"> - <%= flash_tag flash %> - </div> <div id="workspace" class="<%= controller_name %> <%= action_name %>"> + <%= render partial: "shared/flash_messages", flash: flash %> <%= yield %> </div> <div id="sidebar"> diff --git a/app/views/lines/_line.erb b/app/views/lines/_line.erb index 88e222686..69baacd75 100644 --- a/app/views/lines/_line.erb +++ b/app/views/lines/_line.erb @@ -1,5 +1,5 @@ <%= div_for(line) do %> - <%= link_to([@referential, line], :class => "preview", :title => "#{Chouette::Line.model_name.human.capitalize} #{line.number}") do %> + <div><%= link_to([@referential, line], :class => "preview", :title => "#{Chouette::Line.model_name.human.capitalize} #{line.number}") do %></div> <div class="color"> <% if line.number and line.number.length <= 3 %> <div class="number"><%= line.number %></div> @@ -14,7 +14,7 @@ <% if line.network.nil? %> <%= line.human_attribute_name('network') %> <%= t('lines.index.unset') %> <% else %> - <%= line.human_attribute_name('network') %> <%= link_to_if line.network, line.network.name, referential_network_path(@referential, line.network), :title => "#{line.human_attribute_name('network')} #{line.network.name}" %> - + <%= line.human_attribute_name('network') %> <%= link_to_if line.network, line.network.name, referential_network_path(@referential, line.network), :title => "#{line.human_attribute_name('network')} #{line.network.name}" %><br> <% end %> <% if line.company.nil? %> <%= line.human_attribute_name('company') %> <%= t('lines.index.unset') %> diff --git a/app/views/lines/index.html.erb b/app/views/lines/index.html.erb index ff14e8749..0eed3e63b 100644 --- a/app/views/lines/index.html.erb +++ b/app/views/lines/index.html.erb @@ -45,10 +45,6 @@ <li><%= link_to t('lines.actions.new'), new_referential_line_path(@referential), :class => "add" %></li> </ul> -<ul class="actions"> - <li><%= link_to t('lines.actions.import'), new_referential_import_path(@referential), :class => "import" %></li> -</ul> - <h3><%= t(".selection") %></h3> <h4><%= Chouette::Company.model_name.human.pluralize %></h4> diff --git a/app/views/rule_parameter_sets/_form.html.erb b/app/views/rule_parameter_sets/_form.html.erb new file mode 100644 index 000000000..1f12d6b14 --- /dev/null +++ b/app/views/rule_parameter_sets/_form.html.erb @@ -0,0 +1,27 @@ +<%= semantic_form_for [@referential, @rule_parameter_set] do |form| %> + <%= form.inputs do %> + <%= form.input :name %> + <%= form.input :inter_stop_area_distance_min, :as => :number %> + <%= form.input :parent_stop_area_distance_max, :as => :number %> + <%= form.input :stop_areas_area %> + <%= form.input :inter_access_point_distance_min, :as => :number %> + <%= form.input :inter_connection_link_distance_max, :as => :number %> + <%= form.input :walk_default_speed_max, :as => :number %> + <%= form.input :walk_occasional_traveller_speed_max, :as => :number %> + <%= form.input :walk_frequent_traveller_speed_max, :as => :number %> + <%= form.input :walk_mobility_restricted_traveller_speed_max, :as => :number %> + + <%= form.input :inter_access_link_distance_max, :as => :number %> + <%= form.input :inter_stop_duration_max, :as => :number %> + <%= form.input :facility_stop_area_distance_max, :as => :number %> + + <% Chouette::Line.transport_modes.map(&:to_s).each do |mode| %> + <%= render :partial => "mode_fields", :locals => { :f => form, :mode => mode} %> + <% end %> + <% end %> + + <%= form.actions do %> + <%= form.action :submit, :as => :button %> + <%= form.action :cancel, :as => :link %> + <% end %> +<% end %> diff --git a/app/views/rule_parameter_sets/_mode_fields.html.erb b/app/views/rule_parameter_sets/_mode_fields.html.erb new file mode 100644 index 000000000..0a17b4d82 --- /dev/null +++ b/app/views/rule_parameter_sets/_mode_fields.html.erb @@ -0,0 +1,5 @@ +<%= f.inputs t("transport_modes.label.#{mode}"), :id => "specific_parameters_#{mode}" do %> + <% RuleParameterSet.mode_attribute_prefixes.each do |prefix| %> + <%= f.input "#{prefix}_mode_#{mode}".to_sym, :as => :number, :label => RuleParameterSet.human_attribute_name(prefix), :wrapper_html => { :class => "special"} %> + <% end %> +<% end %> diff --git a/app/views/rule_parameter_sets/_mode_selection.html.erb b/app/views/rule_parameter_sets/_mode_selection.html.erb new file mode 100644 index 000000000..56d1c05bb --- /dev/null +++ b/app/views/rule_parameter_sets/_mode_selection.html.erb @@ -0,0 +1,6 @@ +<select class="undescribed_modes"> + <% Chouette::TransportMode.all.map { |m| m.name.downcase}.each do |mode| %> + <option value='<%= mode %>'><%= t("transport_modes.label.#{mode}") %></option> + <% end %> +</select> + diff --git a/app/views/rule_parameter_sets/_transport_mode_parameter_set_fields.html.erb b/app/views/rule_parameter_sets/_transport_mode_parameter_set_fields.html.erb new file mode 100644 index 000000000..3d2bcd3d2 --- /dev/null +++ b/app/views/rule_parameter_sets/_transport_mode_parameter_set_fields.html.erb @@ -0,0 +1,10 @@ +<%= 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 :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 %> +<% end %> + diff --git a/app/views/rule_parameter_sets/edit.html.erb b/app/views/rule_parameter_sets/edit.html.erb new file mode 100644 index 000000000..eb2ca466f --- /dev/null +++ b/app/views/rule_parameter_sets/edit.html.erb @@ -0,0 +1,4 @@ +<%= title_tag t('rule_parameter_sets.edit.title', :rule_parameter_set => @rule_parameter_set.name ) %> + +<%= render "form" %> + diff --git a/app/views/rule_parameter_sets/index.html.erb b/app/views/rule_parameter_sets/index.html.erb new file mode 100644 index 000000000..c03ff0d15 --- /dev/null +++ b/app/views/rule_parameter_sets/index.html.erb @@ -0,0 +1,21 @@ +<%= title_tag t('rule_parameter_sets.index.title') %> + +<% @rule_parameter_sets.each do |rule_parameter_set| %> + <%= div_for(rule_parameter_set) do %> + <%= link_to( rule_parameter_set.name, [@referential, rule_parameter_set]) %> + <div class="info"> + <div class="actions"> + <%= link_to t("actions.edit"), edit_referential_rule_parameter_set_path(@referential, rule_parameter_set), :class => "edit" %> + <% if @referential.rule_parameter_sets.size > 1 %> + | <%= link_to t("actions.destroy"), referential_rule_parameter_set_path(@referential, rule_parameter_set), :method => :delete, :data => {:confirm => t('rule_parameter_sets.actions.destroy_confirm')}, :class => "remove" %> + <% end %> + </div> + </div> + <% end %> +<% end %> + +<% content_for :sidebar do %> +<ul class="actions"> + <li><%= link_to t('rule_parameter_sets.actions.new'), new_referential_rule_parameter_set_path(@referential), :class => "add" %></li> +</ul> +<% end %> diff --git a/app/views/rule_parameter_sets/mode.js.erb b/app/views/rule_parameter_sets/mode.js.erb new file mode 100644 index 000000000..22b70830e --- /dev/null +++ b/app/views/rule_parameter_sets/mode.js.erb @@ -0,0 +1,13 @@ +if ( $('#specific_parameters_<%= @mode %>').length == 0) { + <% form_content = "" %> + <% semantic_form_for [@referential, @rule_parameter_set] do |form| %> + <% form_content += render(:partial => 'mode_fields', :locals => { :mode => @mode, :f => form }) %> + <% end %> + $('#added_mode_parameter_set').before('<%= escape_javascript( form_content).html_safe %>'); +} +else { + $('#_destroy_mode_<%= @mode %>').attr( "value", false); + $('#specific_parameters_<%= @mode %>').toggle(); +} + + diff --git a/app/views/rule_parameter_sets/new.html.erb b/app/views/rule_parameter_sets/new.html.erb new file mode 100644 index 000000000..228a2da7a --- /dev/null +++ b/app/views/rule_parameter_sets/new.html.erb @@ -0,0 +1,4 @@ +<%= title_tag t('rule_parameter_sets.new.title') %> + +<%= render "form" %> + diff --git a/app/views/rule_parameter_sets/show.html.erb b/app/views/rule_parameter_sets/show.html.erb new file mode 100644 index 000000000..f2427e36e --- /dev/null +++ b/app/views/rule_parameter_sets/show.html.erb @@ -0,0 +1,109 @@ +<%= title_tag t('rule_parameter_sets.show.title', :rule_parameter_set => @rule_parameter_set.name ) %> + +<div class="rule_parameter_set_show"> + + <div class="summary"> + <p> + <label><%= RuleParameterSet.human_attribute_name("name") %>: </label> + <%= @rule_parameter_set.name %> + </p> + <p> + <label><%= RuleParameterSet.human_attribute_name("stop_areas_area") %>: </label> + <%= @rule_parameter_set.stop_areas_area %> + </p> + <div class="attributes_group" > + <span class="title"><%= t(".min_distance") %></span> + <div class="columns"> + <div class="two_columns"> + <label><%= t(".inter_stop_area_distance_min") %> : </label> + <span class="value"><%= @rule_parameter_set.inter_stop_area_distance_min %></span> + </div> + <div class="two_columns"> + <label><%= t(".inter_access_point_distance_min") %> : </label> + <span class="value"><%= @rule_parameter_set.inter_access_point_distance_min %></span> + </div> + </div> + </div> + <div class="attributes_group" > + <span class="title"><%= t(".max_distance") %></span> + <div class="columns"> + <div class="two_columns"> + <label><%= t(".parent_stop_area_distance_max") %>: </label> + <span class="value"><%= @rule_parameter_set.parent_stop_area_distance_max %></span> + </div> + <div class="two_columns"> + <label><%= t(".inter_connection_link_distance_max") %>: </label> + <span class="value"><%= @rule_parameter_set.inter_connection_link_distance_max %></span> + </div> + </div> + <div class="columns"> + <div class="two_columns"> + <label><%= t(".inter_access_link_distance_max") %>: </label> + <span class="value"><%= @rule_parameter_set.inter_access_link_distance_max %></span> + </div> + <div class="two_columns"> + <label><%= t(".facility_stop_area_distance_max") %>: </label> + <span class="value"><%= @rule_parameter_set.facility_stop_area_distance_max %></span> + </div> + </div> + </div> + <div class="attributes_group" > + <span class="title"><%= t(".walk_speed") %></span> + <div class="columns"> + <div class="four_columns"> + <label><%= t(".walk_default_speed_max") %>: </label> + <span class="value"><%= @rule_parameter_set.walk_default_speed_max %></span> + </div> + <div class="four_columns"> + <label><%= t(".walk_occasional_traveller_speed_max") %>: </label> + <span class="value"><%= @rule_parameter_set.walk_occasional_traveller_speed_max %></span> + </div> + <div class="four_columns"> + <label><%= t(".walk_frequent_traveller_speed_max") %>: </label> + <span class="value"><%= @rule_parameter_set.walk_frequent_traveller_speed_max %></span> + </div> + <div class="four_columns"> + <label><%= t(".walk_mobility_restricted_traveller_speed_max") %>: </label> + <span class="value"><%= @rule_parameter_set.walk_mobility_restricted_traveller_speed_max %></span> + </div> + </div> + </div> + <p> + <label><%= t(".inter_stop_duration_max") %>: </label> + <%= @rule_parameter_set.inter_stop_duration_max %> + </p> + <div class="rule_parameter_by_mode"> + <label><%= t(".rule_parameter_by_mode") %>: </label> + <select id="mode" > + <%= options_for_select( Chouette::Line.transport_modes.map(&:to_s).map { |s| [ I18n.t("transport_modes.label.#{s}"), s]}, 1) %> + </select> + <% Chouette::Line.transport_modes.map(&:to_s).each_with_index do |mode, index| %> + <% selected_class = (index==0) ? 'selected' : '' %> + <% style = (index==0) ? "style='display: block;'" : '' %> + <div class='<%= "#{mode} mode_specific #{selected_class}" %>' <%= style %> > + <% RuleParameterSet.mode_attribute_prefixes.each do |prefix| %> + <% unless @rule_parameter_set.send("#{prefix}_mode_#{mode}" ).blank? %> + <p> + <label><%= RuleParameterSet.human_attribute_name( prefix) %>: </label> + <%= @rule_parameter_set.send "#{prefix}_mode_#{mode}" %> + </p> + <% end %> + <% end %> + </div> + <% end %> + </div> + </div> +</div> + +<% content_for :sidebar do %> +<ul class="actions"> + <% if @rule_parameter_set.persisted? %> + <li><%= link_to t('rule_parameter_sets.actions.index'), referential_rule_parameter_sets_path(@referential), :class => "link" %></li> + <li><%= link_to t('rule_parameter_sets.actions.edit'), edit_referential_rule_parameter_set_path(@referential, @rule_parameter_set), :class => "edit" %></li> + <% if @referential.rule_parameter_sets.size > 1 %> + <li><%= link_to t('rule_parameter_sets.actions.destroy'), referential_rule_parameter_set_path(@referential, @rule_parameter_set), :method => :delete, :data => {:confirm => t('rule_parameter_sets.actions.destroy_confirm')}, :class => "remove" %></li> + <% end %> + <li><%= link_to t('rule_parameter_sets.actions.new'), new_referential_rule_parameter_set_path(@referential), :class => "add" %></li> + <% end %> +</ul> +<% end %> diff --git a/app/views/shared/_flash_messages.erb b/app/views/shared/_flash_messages.erb new file mode 100644 index 000000000..bad859aa9 --- /dev/null +++ b/app/views/shared/_flash_messages.erb @@ -0,0 +1,6 @@ +<% flash.each do |type, message| %> + <div class="alert <%= bootstrap_class_for(type) %> fade in"> + <button class="close" data-dismiss="alert">×</button> + <%= flash_message_for type, message %> + </div> +<% end %> diff --git a/config/environment.rb b/config/environment.rb index 7d362d262..296970388 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -6,4 +6,4 @@ require File.expand_path('../application', __FILE__) ChouetteIhm::Application.initialize! # Fix version -APP_VERSION = '2.1.1' +APP_VERSION = '2.2.0' diff --git a/config/initializers/active_enum.rb b/config/initializers/active_enum.rb new file mode 100644 index 000000000..cabf0bf7b --- /dev/null +++ b/config/initializers/active_enum.rb @@ -0,0 +1,24 @@ +# Form helper integration +# require 'active_enum/form_helpers/formtastic' # for Formtastic <2 +require 'active_enum/form_helpers/formtastic2' # for Formtastic 2.x + +ActiveEnum.setup do |config| + + # Extend classes to add enumerate method + # config.extend_classes = [ ActiveRecord::Base ] + + # Return name string as value for attribute method + # config.use_name_as_value = false + + # Storage of values (:memory, :i18n) + # config.storage = :memory + +end + +# ActiveEnum.define do +# +# enum(:enum_name) do +# value 1 => 'Name' +# end +# +# end diff --git a/config/initializers/apartment.rb b/config/initializers/apartment.rb index b9873db1b..095ee9aff 100644 --- a/config/initializers/apartment.rb +++ b/config/initializers/apartment.rb @@ -1,6 +1,6 @@ Apartment.configure do |config| # set your options (described below) here - config.excluded_models = ["Referential", "Organisation", "User", "Import", "ImportLogMessage", "Export", "ExportLogMessage","FileValidation", "FileValidationLogMessage", "Delayed::Backend::ActiveRecord::Job", "Api::V1::ApiKey"] # these models will not be multi-tenanted, but remain in the global (public) namespace + config.excluded_models = ["Referential", "Organisation", "User", "ImportTask", "Export", "ExportLogMessage","ComplianceCheckTask", "ComplianceCheckResult", "Delayed::Backend::ActiveRecord::Job", "Api::V1::ApiKey", "RuleParameterSet"] # these models will not be multi-tenanted, but remain in the global (public) namespace # Dynamically get database names to migrate config.database_names = lambda{ Referential.pluck(:slug) } diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index d77e42f46..bf423a2f5 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -92,18 +92,18 @@ Devise.setup do |config| # this period, the invited resource won't be able to accept the invitation. # When invite_for is 0 (the default), the invitation won't expire. # config.invite_for = 2.weeks - + # Number of invitations users can send. # If invitation_limit is nil, users can send unlimited invitations. # If invitation_limit is 0, users can't send invitations. # If invitation_limit n > 0, users can send n invitations. # Default: nil # config.invitation_limit = 5 - + # The key to be used to check existing users when sending an invitation # config.invite_key = :email - - # Flag that force a record to be valid before being actually invited + + # Flag that force a record to be valid before being actually invited # Default: false # config.validate_on_invite = true @@ -242,3 +242,25 @@ Devise.setup do |config| # manager.default_strategies(:scope => :user).unshift :some_external_strategy # end end + +class Devise::FailureApp + def return_to_root_path? + root_path == session["#{scope}_return_to"] + end + def redirect + store_location! + if flash[:timedout] && flash[:alert] + flash.keep(:timedout) + flash.keep(:alert) + else + Rails.logger.debug "A" * 30 + Rails.logger.debug i18n_message + Rails.logger.debug redirect_url + Rails.logger.debug scope + Rails.logger.debug root_path + Rails.logger.debug session["#{scope}_return_to"] + flash[:alert] = i18n_message unless return_to_root_path? + end + redirect_to redirect_url + end +end diff --git a/config/initializers/formtastic.rb b/config/initializers/formtastic.rb index 7aee33df5..c1f7f972f 100644 --- a/config/initializers/formtastic.rb +++ b/config/initializers/formtastic.rb @@ -1,6 +1,5 @@ Formtastic::FormBuilder.i18n_lookups_by_default = true - module Formtastic module Inputs class CheckBoxesInput diff --git a/config/locales/compliance_check_results.yml b/config/locales/compliance_check_results.yml new file mode 100644 index 000000000..b523275c2 --- /dev/null +++ b/config/locales/compliance_check_results.yml @@ -0,0 +1,265 @@ +en: + compliance_check_result: + severities: + error: "Obligatory Tests" + warning: "Optionnal Tests" + statuses: + nok: "Error" + na: "Unavailable" + ok: "Success" + activerecord: + models: + compliance_check_result: + zero: "Validation" + one: "Validation" + other: "Validation" + attributes: + compliance_check_result: + violation_count: "Violation count" + +fr: + compliance_check_results: + index: + line: "Li" + column: "Col" + compliance_check_result: + severities: + error: "Tests Obligatoires" + warning: "Tests Optionnels" + statuses: + nok: "Erreur" + na: "Absent" + ok: "Succès" + details: + #### level 1 + ## NEPTUNE + detail_1_neptune_xml_1: "%{xmlKey} : %{message}" + detail_1_neptune_xml_2: "%{xmlKey} : %{message}" + #### level 2 + ## NEPTUNE + detail_2_neptune_common_1: "" + detail_2_neptune_common_2: "RegistrationNumber = %{RegistrationNumber}" + detail_2_neptune_network_1: "La ligne %{lineId} est absente de la liste des lignes du réseau %{objectId}" + detail_2_neptune_groupofline_1: "lineId = %{lineId}" + detail_2_neptune_stoparea_1: "contains = %{contains}" + detail_2_neptune_stoparea_2: "contains = %{contains}" + detail_2_neptune_stoparea_3: "contains = %{contains}" + detail_2_neptune_stoparea_4: "contains = %{contains}" + detail_2_neptune_stoparea_5: "centroidOfArea = %{centroidOfArea}" + detail_2_neptune_stoparea_6: "centroidOfArea = %{centroidOfArea}" + detail_2_neptune_itl_1: "contains = %{contains}" + detail_2_neptune_itl_2: "" + detail_2_neptune_itl_3: "areaId = %{areaId}" + detail_2_neptune_itl_4: "areaId = %{areaId}" + detail_2_neptune_itl_5: "lineIdShortCut = %{lineIdShortCut}" + detail_2_neptune_areacentroid_1: "containedIn = %{containedIn}" + detail_2_neptune_areacentroid_2: "longLatType = %{longLatType}" + detail_2_neptune_connectionlink_1: "" + detail_2_neptune_accesspoint_1: "containedIn = %{containedIn}" + detail_2_neptune_accesspoint_2: "containedIn = %{containedIn}" + detail_2_neptune_accesspoint_3: "" + detail_2_neptune_accesspoint_4: "" + detail_2_neptune_accesspoint_5: "" + detail_2_neptune_accesspoint_6: "" + detail_2_neptune_accesspoint_7: "longLatType = %{longLatType}" + detail_2_neptune_accesslink_1: "%{link} = %{target}" + detail_2_neptune_accesslink_2: "startOfLink = %{startOfLink} et endOfLink = %{endOfLink} ; type = %{type}" + detail_2_neptune_line_1: "ptNetworkIdShortcut = %{ptNetworkIdShortcut}" + detail_2_neptune_line_2: "lineEnd = %{lineEnd}" + detail_2_neptune_line_3: "lineEnd = %{lineEnd}" + detail_2_neptune_line_4: "routeId = %{routeId}" + detail_2_neptune_line_5: "routeId = %{routeId}" + detail_2_neptune_route_1: "journeyPatternId = %{journeyPatternId}" + detail_2_neptune_route_2: "ptLinkId = %{ptLinkId}" + detail_2_neptune_route_3: "waybackRouteId = %{waybackRouteId}" + detail_2_neptune_route_4: "ptLinkId = %{ptLinkId}" + detail_2_neptune_route_5: "%{link} = %{target}" + detail_2_neptune_route_6: "ptLinkId = %{ptLinkId}" + detail_2_neptune_route_7: "journeyPatternId = %{journeyPatternId}" + detail_2_neptune_route_8: "journeyPatternId = %{journeyPatternId}" + detail_2_neptune_route_9: "L'arrêt (stopPointId = %{stopPointId}) de la séquence d'arrêts %{objectId} n'est utilisé dans aucune mission" + detail_2_neptune_route_10: "waybackRouteId = %{waybackRouteId}" + detail_2_neptune_route_11: "Le sens (%{waybackValue}) de la séquence d'arrêt %{objectId} n'est pas compatible avec celui (%{oppositeWaybackValue}) de la séquence opposée %{waybackRouteId}" + detail_2_neptune_route_12: "Le départ (stopPointId = %{stopPointId}) de la séquence d'arrêts %{objectId} n'est pas dans la même zone que l'arrivée (stopPointId = %{waybackStopPointId} de la séquence retour %{waybackRouteId}" + detail_2_neptune_ptlink_1: "%{link} = %{target}" + detail_2_neptune_journeypattern_1: "routeId = %{routeId}" + detail_2_neptune_journeypattern_2: "stopPointId = %{stopPointId}" + detail_2_neptune_journeypattern_3: "lineIdShortcut = %{lineIdShortcut}" + detail_2_neptune_stoppoint_1: "lineIdShortcut = %{lineIdShortcut}" + detail_2_neptune_stoppoint_2: "ptNetworkIdShortcut = %{ptNetworkIdShortcut}" + detail_2_neptune_stoppoint_3: "containedIn = %{containedIn}" + detail_2_neptune_stoppoint_4: "longLatType = %{longLatType}" + detail_2_neptune_timetable_1: "" + detail_2_neptune_timetable_2: "La course %{objectId} n'est référencée dans aucun objet <Timetable>" + detail_2_neptune_vehiclejourney_1: "routeId = %{routeId}" + detail_2_neptune_vehiclejourney_2: "journeyPatternId = %{journeyPatternId}" + detail_2_neptune_vehiclejourney_3: "lineIdShortcut = %{lineIdShortcut}" + detail_2_neptune_vehiclejourney_4: "L'opérateur (operatorId = %{operatorId}) de la course %{objectId} n'existe pas" + detail_2_neptune_vehiclejourney_5: "timeSlotId = %{timeSlotId}" + detail_2_neptune_vehiclejourney_6: "journeyPatternId = %{journeyPatternId}" + detail_2_neptune_vehiclejourney_7: "" + detail_2_neptune_vehiclejourneyatstop_1: "stopPointId = %{stopPointId}" + detail_2_neptune_vehiclejourneyatstop_2: "vehicleJourneyId = %{vehicleJourneyId}" + detail_2_neptune_vehiclejourneyatstop_3: "routeId = %{routeId}" + detail_2_neptune_vehiclejourneyatstop_4: "journeyPatternId = %{journeyPatternId}" + detail_2_neptune_facility_1: "containedId = %{containedId}" + detail_2_neptune_facility_2: "stopAreaId = %{stopAreaId}" + detail_2_neptune_facility_3: "lineId = %{lineId}" + detail_2_neptune_facility_4: "connectionLinkId = %{connectionLinkId}" + detail_2_neptune_facility_5: "stopPointId = %{stopPointId}" + detail_2_neptune_facility_6: "longLatType = %{longLatType}" + #### level 3 + detail_3_stoparea_1: "" + detail_3_stoparea_2: "" + detail_3_stoparea_3: "" + detail_3_stoparea_4: "" + detail_3_stoparea_5: "" + detail_3_accesspoint_1: "" + detail_3_accesspoint_2: "" + detail_3_accesspoint_3: "" + detail_3_connectionlink_1: "" + detail_3_connectionlink_2: "" + detail_3_connectionlink_3: "" + detail_3_accesslink_1: "" + detail_3_accesslink_2: "" + detail_3_accesslink_3: "" + detail_3_line_1: "" + detail_3_line_2: "" + detail_3_route_1: "" + detail_3_route_2: "" + detail_3_route_3: "Entre les arrêts de rang %{firstStopRank} (%{firstStop} et %{nextStopRank} (%{nextStop}, distance %{distance} %{orientation} %{distanceLimit} " + detail_3_route_4: "" + detail_3_route_5: "" + detail_3_route_6: "" + detail_3_route_7: "" + detail_3_route_8: "%{count} arrêts non utilisés par des missions : %{names}" + detail_3_route_9: "" + detail_3_journeypattern_1: "Nombre d'arrêts = %{count}" + detail_3_vehiclejourney_1: "Arrêt n° %{stopRank} (%{stopName}) : durée d'arrêt mesurée %{diffTime} > %{maxDiffTime}" + detail_3_vehiclejourney_2: "" + detail_3_vehiclejourney_3: "" + detail_3_vehiclejourney_4: "" + detail_3_vehiclejourney_5: "" + detail_3_facility_1: "" + detail_3_facility_2: "" + + activerecord: + models: + compliance_check_result: + zero: "Validation" + one: "Validation" + other: "Validations" + attributes: + compliance_check_result: + 1-NEPTUNE-XML-1: "Conformité à la syntaxe XML suivant les recommandations du W3C." + 1-NEPTUNE-XML-2: "Conformité au schéma défini par la XSD du profil TRIDENT/NEPTUNE." + 2-NEPTUNE-Common-1: "Unicité des éléments objectId des différents objets d'un lot de fichiers Neptune." + 2-NEPTUNE-Common-2: "Unicité des éléments regitrationNumber des différents objets d'un lot de fichiers Neptune." + 2-NEPTUNE-Network-1: "Correcte référence à des lignes <Line> dans version du réseau <PTNetwork>." + 2-NEPTUNE-GroupOfLine-1: "Correcte référence à des lignes <Line> dans groupe de lignes <GroupOfLine>." + 2-NEPTUNE-StopArea-1: "Correcte référence à des arrêts <StopArea> et/ou à des points d'arrêt sur parcours <StopPoint> dans les arrêts <StopArea>." + 2-NEPTUNE-StopArea-2: "Correcte référence à des arrêts <StopArea> dans les arrêts <StopArea> de type StopPlace." + 2-NEPTUNE-StopArea-3: "Correcte référence à des arrêts <StopArea> dans les arrêts <StopArea> de type CommercialStopPoint." + 2-NEPTUNE-StopArea-4: "Correcte référence à des points d'arrêt sur parcours <StopPoint> dans les arrêts <StopArea> de type BoardingPosition ou Quay." + 2-NEPTUNE-StopArea-5: "Correcte référence à une position géographique <AreaCentroid> dans les arrêts <StopArea> de tout type StopPlace, CommercialStopPoint, BoardingPosition et Quay." + 2-NEPTUNE-StopArea-6: "référenceréciproque d'une position géographique <AreaCentroid> dans les arrêts <StopArea> de tout type StopPlace, CommercialStopPoint, BoardingPosition et Quay." + 2-NEPTUNE-ITL-1: "Correcte référence à des arrêts <StopArea> dans les arrêts <StopArea> de type ITL." + 2-NEPTUNE-ITL-2: "Correcte référence à des arrêts <StopArea> de type ITL dans la classe d’objets <ITL>." + 2-NEPTUNE-ITL-3: "Correcte référence à des arrêts <StopArea> dans la classe d’objets <ITL>." + 2-NEPTUNE-ITL-4: "Vérification du type de référence à des arrêts <StopArea> type ITL dans la classe d’objets <ITL>." + 2-NEPTUNE-ITL-5: "Bonne référence à la ligne <Line> dans la classe d’objets <ITL>." + 2-NEPTUNE-AreaCentroid-1: "Correcte référence à des arrêts <StopArea> dans la classe d’objets <AreaCentroid>." + 2-NEPTUNE-AreaCentroid-2: "Vérification du modèle de projection de référence utilisé." + 2-NEPTUNE-ConnectionLink-1: "Correcte référence aux arrêts <StopArea> définissant des tronçons de correspondance <ConnectionLink>." + 2-NEPTUNE-AccessPoint-1: "Correcte référence à un arrêt <StopArea> dans les accès <AccessPoint>." + 2-NEPTUNE-AccessPoint-2: "Correcte référence à un arrêt <StopArea> dans les accès <AccessPoint>." + 2-NEPTUNE-AccessPoint-3: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint>." + 2-NEPTUNE-AccessPoint-4: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint> de type 'in'." + 2-NEPTUNE-AccessPoint-5: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint> sur les accès de type 'out'." + 2-NEPTUNE-AccessPoint-6: "Existence de liens d'accès <AccessLink> sur les accès <AccessPoint> sur les accès de type 'inout'." + 2-NEPTUNE-AccessPoint-7: "Vérification du modèle de projection de référence utilisé." + 2-NEPTUNE-AccessLink-1: "Correcte référence aux arrêts <StopArea> et accès «AccessPoint> définissant des liens d'accès <AccessLink>." + 2-NEPTUNE-AccessLink-2: "Correcte référence aux arrêts <StopArea> et accès «AccessPoint> définissant des liens d'accès <AccessLink>." + 2-NEPTUNE-Line-1: "Correcte référence au réseau dans l'objet ligne <Line>." + 2-NEPTUNE-Line-2: "Correcte référence à un point d'arrêt sur parcours <StopPoint> comme terminus de ligne <Line>." + 2-NEPTUNE-Line-3: "Correcte référence à un point d'arrêt sur parcours <StopPoint> comme terminus de ligne <Line>." + 2-NEPTUNE-Line-4: "Correcte référence aux séquences d'arrêts <ChouetteRoute> dans l'objet ligne <Line>." + 2-NEPTUNE-Line-5: "Correcte référence aux séquences d'arrêts <ChouetteRoute> dans l'objet ligne <Line>." + 2-NEPTUNE-Route-1: "Existence des missions <JourneyPattern> référencées par la séquence d'arrêt <ChouetteRoute>." + 2-NEPTUNE-Route-2: "Existence des tronçons commerciaux <PtLink> référencés par la séquence d'arrêt <ChouetteRoute>." + 2-NEPTUNE-Route-3: "Existence de la séquence opposée <ChouetteRoute> référencée par la séquence d'arrêt <ChouetteRoute>." + 2-NEPTUNE-Route-4: "Correcte référence à un tronçon commercial <PtLink> dans une séquence d'arrêts <ChouetteRoute>." + 2-NEPTUNE-Route-5: "Vérification que tous les points d'arrêts sur parcours sont rattachés à une séquence d'arrêts <ChouetteRoute> au départ d'un tronçon commercial <PtLink> et/ou à l'arrivée d'un autre tronçon commercial <PtLink> de la même séquence d'arrêts." + 2-NEPTUNE-Route-6: "Vérification du correct ordonnancement des points d'arrêts sur parcours <StopPoint> dans le chainage des tronçons <PtLink> d'une séquence d'arrêts <ChouetteRoute>." + 2-NEPTUNE-Route-7: "référence mutuelle des missions <JourneyPattern> et des séquences d'arrêts <ChouetteRoute>." + 2-NEPTUNE-Route-8: "Cohérence des références aux points d'arrêt des missions <JourneyPattern> et des séquences d'arrêts <ChouetteRoute>." + 2-NEPTUNE-Route-9: "Utilité des points d'arrêts sur parcours des séquences d'arrêts <ChouetteRoute>." + 2-NEPTUNE-Route-10: "référence d'une séquence d'arrêts <ChouetteRoute> à une séquence d'arrêts opposée." + 2-NEPTUNE-Route-11: "Cohérence des sens de la référence d'une séquence d'arrêts <ChouetteRoute> à une séquence d'arrêts opposée." + 2-NEPTUNE-Route-12: "Cohérence des terminus de la référence d'une séquence d'arrêts <ChouetteRoute> à une séquence d'arrêts opposée." + 2-NEPTUNE-PtLink-1: "Existence des arrêts <StopPoint> référencés par les tronçons commerciaux <PTLink>." + 2-NEPTUNE-JourneyPattern-1: "Existence de la séquence d'arrêt <ChouetteRoute> référencée par la mission <JourneyPattern>." + 2-NEPTUNE-JourneyPattern-2: "Existence des arrêts <StopPoint> référencés par la mission <JourneyPattern>." + 2-NEPTUNE-JourneyPattern-3: "Existence de la ligne <Line> référencée par la mission <JourneyPattern>." + 2-NEPTUNE-StopPoint-1: "Existence de la ligne <Line> référencée par l'arrêt <StopPoint>." + 2-NEPTUNE-StopPoint-2: "Existence du réseau <PTNetwork> référence par l'arrêt <StopPoint>." + 2-NEPTUNE-StopPoint-3: "Existence de l'arrêt <StopArea> référencé par l'arrêt <StopPoint>." + 2-NEPTUNE-StopPoint-4: "Vérification du modèle de projection de référence utilisé." + 2-NEPTUNE-Timetable-1: "Utilité des calendriers." + 2-NEPTUNE-Timetable-2: "Utilité des calendriers." + 2-NEPTUNE-VehicleJourney-1: "Existence de la séquence d'arrêt <ChouetteRoute> référencée par la course <VehicleJourney>." + 2-NEPTUNE-VehicleJourney-2: "Existence de la mission <JourneyPattern> référencée par la course <VehicleJourney>." + 2-NEPTUNE-VehicleJourney-3: "Existence de la ligne <Line> référencée par la course <VehicleJourney>." + 2-NEPTUNE-VehicleJourney-4: "Existence de l'opérateur <Company> référencé par la course <VehicleJourney>." + 2-NEPTUNE-VehicleJourney-5: "Existence de la tranche horaire <TimeSlot> référencée par la course <VehicleJourney>." + 2-NEPTUNE-VehicleJourney-6: "Cohérence entre la course, la mission et la séquence d'arrêts." + 2-NEPTUNE-VehicleJourney-7: "Utilité des missions" + 2-NEPTUNE-VehicleJourneyAtStop-1: "Existence de l'arrêt <StopPoint> référencé par l'horaire <VehicleJourneyAtStop>." + 2-NEPTUNE-VehicleJourneyAtStop-2: "Existence de la course <VehicleJourney> référenceé par l'horaire <VehicleJourneyAtStop>." + 2-NEPTUNE-VehicleJourneyAtStop-3: "adéquation des horaires de la course à la séquence d'arrêts." + 2-NEPTUNE-VehicleJourneyAtStop-4: "adéquation des horaires de la course à la mission." + 2-NEPTUNE-Facility-1: "Existence de l'arrêt <StopArea> référencé par l'équipement <Facility>." + 2-NEPTUNE-Facility-2: "Existence de l'arrêt <StopArea> référencé par l'équipement <Facility>." + 2-NEPTUNE-Facility-3: "Existence de la ligne <Line> référencée par l'équipement <Facility>." + 2-NEPTUNE-Facility-4: "Existence de la correspondance <ConnectionLink> référencée par l'équipement <Facility>." + 2-NEPTUNE-Facility-5: "Existence de l'arrêt <StopPoint> référencé par l'équipement <Facility>." + 2-NEPTUNE-Facility-6: "Vérification du modèle de projection de référence utilisé." + 3-StopArea-1: "Vérification de la géolocalisation de tous les arrêts hors ITL" + 3-StopArea-2: "Vérification que 2 arrêts de noms différents en dehors d'un même regroupement d'arrêts ne sont pas trop proches" + 3-StopArea-3: "Vérification de l'unicité des arrêts" + 3-StopArea-4: "Vérification de la géolocalisation des arrêts" + 3-StopArea-5: "Vérification de la position relative des arrêts et de leur parent" + 3-AccessPoint-1: "Vérification de la géolocalisation de tous les accès" + 3-AccessPoint-2: "Vérification que deux accès de nom différents ne sont pas trop proches" + 3-AccessPoint-3: "Vérification de la proximité entre les accès et leur arrêt de rattachement" + 3-ConnectionLink-1: "Vérification de la proximité entre les deux arrêts d'une correspondance" + 3-ConnectionLink-2: "Vérification de la cohérence entre la distance fournie sur la correspondance et la distance géographique entre les deux arrêts de la correspondance" + 3-ConnectionLink-3: "Vérification de la vitesse de parcours entre les deux arrêts d'une correspondance" + 3-AccessLink-1: "Vérification de la proximité entre les deux extrémités d'un lien d'accès" + 3-AccessLink-2: "Vérification de la cohérence entre la distance fournie sur le lien d'accès et la distance géographique entre les deux extrémités du lien d'accès" + 3-AccessLink-3: "Vérification de la vitesse de parcours entre les deux extrémités d'un lien d'accès" + 3-Line-1: "Vérification de la non homonymie des lignes" + 3-Route-1: "Vérification de la succession des arrêts de la séquence" + 3-Route-2: "Vérification de la séquence inverse" + 3-Route-3: "Vérification de la distance entre deux arrêts successifs de la séquence" + 3-Route-4: "Vérification de double définition de séquences" + 3-Route-5: "Vérification de séquences sans séquence opposée" + 3-JourneyPattern-1: "Vérification de l'utilisation des arrêts par les missions" + 3-JourneyPattern-2: "Vérification de l’existence d’une mission passant par tous les arrêts de la séquence" + 3-JourneyPattern-3: "Vérification de double définition de missions" + 3-VehicleJourney-1: "Vérification de la chronologie des horaires de passage à un arrêt" + 3-VehicleJourney-2: "Vérification de la chronologie des horaires de passage entre deux arrêts" + 3-VehicleJourney-3: "Vérification de la vitesse de transfert entre deux arrêts" + 3-VehicleJourney-4: "Vérification de la cohérence des courses successives desservant deux mêmes arrêts" + 3-VehicleJourney-5: "Vérification de l'affectation des courses à un calendrier" + 3-Facility-1: "Vérification de la géolocalisation de tous les accès" + 3-Facility-2: "Vérification de la proximité entre les équipements et leur arrêt de rattachement" + severity: "Sévérité" + status: "Statut" + rule_level: "Niveau" + rule_target: "Objet" + rule_number: "Etape" + rule_code: "Code" + violation_count: "Violations" + detail: "Détail" + diff --git a/config/locales/compliance_check_tasks.yml b/config/locales/compliance_check_tasks.yml new file mode 100644 index 000000000..c9472136a --- /dev/null +++ b/config/locales/compliance_check_tasks.yml @@ -0,0 +1,143 @@ +en: + compliance_check_tasks: + index: + title: "Validation" + warning: "" + edit: + title: "Edit the Validation" + show: + title: "Neptune Validation" + summary: "Rapport de conformité à la norme NEPTUNE" + completed: "[ Completed ]" + failed: "[ Failed ]" + pending: "[ In the treatment queue ]" + processing: "[ In progress... ]" + new: + title: "Create a new validation" + submit: "Create a validation" + all: "All" + actions: + new: "Add a validation" + destroy_confirm: "Do you confirm to destroy this validation ?" + destroy: "Destroy this validation" + edit: "Edit this validation" + rule_parameter_set: "Rule parameter set" + statuses: + pending: "Pending" + completed: "Completed" + failed: "Failed" + file_validation_log_messages: + messages: + undefined: "%{key} undefined" + TooMuchDetails: ( %{0} erreurs / warnings supplémentaires ) + ONE: "Catégorie 1 : Syntaxe" + severities: + uncheck: "Unchecked" + ok: "Ok" + warning: "Warning" + error: "Error" + fatal: "Fatal" + import_task: "Import Report" + rule_parameter_set: "Rule Parameter Set" + activerecord: + models: + file_validation: + zero: "Validation" + one: "Validation" + other: "Validation" + attributes: + file_validation: + created_at: "Executed at" + references_type: "Associated Data Type" + reference_ids: "Associated Data" + rule_parameter_set_id: "Rule parameters set" + resources: "File to validate" + status: "Status" + file_name: "Tested data" + projection_reference: "Système de projection de référence" + file_validation_log_message: + created_at: "Date" + position: "N." + full_message: "Message" + +fr: + compliance_check_tasks: + index: + title: "Validation" + warning: "" + edit: + title: "Editer la validation" + show: + title: "Validation Neptune" + summary: "Rapport de conformité à la norme NEPTUNE" + details: "Détails" + parameters: "Paramètres des tests" + completed: "[ Terminé ]" + failed: "[ Echoué ]" + pending: "[ En file d'attente ]" + processing: "[ En progression... ]" + new: + title: "Démarrer une nouvelle validation" + submit: "Lancer la validation" + all: "Toutes" + actions: + new: "Ajouter une validation" + destroy_confirm: "Voulez-vous supprimer ce résultat de validation ?" + destroy: "Supprimer cette validation" + edit: "Editer cette validation" + rule_parameter_set: "Jeu de paramètres" + statuses: + pending: "En cours" + completed: "Achevé" + failed: "Echoué" + uncheck_count: + zero: "aucun inapplicable" + one: "un inapplicable" + other: "%{count} inapplicables" + ok_count: + zero: "aucun test réussi" + one: "un test réussi" + other: "%{count} tests réussis" + warning_count: + zero: "aucun warning" + one: "un warning" + other: "%{count} warnings" + error_count: + zero: "aucune erreur" + one: "une erreur" + other: "%{count} erreurs" + fatal_count: + zero: "aucune erreur fatale" + one: "une erreur fatale" + other: "%{count} erreurs fatales" + import_task: "Import" + rule_parameter_set: "Jeu de paramètres" + file_validation_log_messages: + messages: + undefined: "%{key} non défini" + TooMuchDetails: "( %{0} erreurs / warnings supplémentaires )" + severities: + uncheck: "Non testé" + ok: "Ok" + warning: "Alerte" + error: "Erreur" + fatal: "Fatal" + activerecord: + models: + compliance_check_task: + zero: "Validation" + one: "Validation" + other: "Validations" + attributes: + compliance_check_task: + created_at: "Exécuté le" + references_type: "Type de données incluses" + reference_ids: "Données incluses" + rule_parameter_set_id: "Jeu de paramètres" + resources: "Fichier à valider" + status: "Status" + file_name: "Jeu de données" + compliance_check_task_log_message: + created_at: "Date" + position: "N." + full_message: "Message" diff --git a/config/locales/file_validations.yml b/config/locales/file_validations.yml deleted file mode 100644 index c252796a6..000000000 --- a/config/locales/file_validations.yml +++ /dev/null @@ -1,595 +0,0 @@ -en: - file_validations: - index: - title: "Neptune Validation" - warning: "" - edit: - title: "Edit the Validation" - show: - title: "Neptune Validation" - summary: "Rapport de conformité à la norme NEPTUNE" - new: - title: "Create a new validation" - submit: "Create a validation" - actions: - new: "Add a validation" - destroy_confirm: "Do you confirm to destroy this validation ?" - destroy: "Destroy this validation" - edit: "Edit this validation" - statuses: - pending: "Pending" - completed: "Completed" - failed: "Failed" - file_validation_log_messages: - messages: - undefined: "%{key} undefined" - TooMuchDetails: ( %{0} erreurs / warnings supplémentaires ) - ONE: "Catégorie 1 : Syntaxe" - Test1_Sheet1: 'Fiche n° 1.1 : Conformité à la syntaxe XML suivant les recommandations du W3C' - Test1_Sheet1_Step1: "Conformité à la syntaxe XML" - Test1_Sheet1_Step2: "Conformité au schéma XML du profil NEPTUNE" - Test1_Sheet1_Step0_fatal: "Erreur fatale : Impossible d'ouvrir le fichier %{0}" - Test1_Sheet1_Step0_error: "Impossible d'importer cette entrée %{0} du zip" - Test1_Sheet1_Step0_warning: "Cette entrée %{0} du zip n'est pas un fichier xml et a été ignoré" - Test1_Sheet1_Step1_error: "le fichier %{0} n'est pas correctement formé selon les recommandations du W3C" - Test1_Sheet1_Step2_error: "le fichier %{0} ne respecte pas le modèle NEPTUNE" - Test1_Sheet1_Step2_encoding: "le fichier %{0} ne respecte pas le codage de caractères du modèle NEPTUNE (ISO-8859-1)" - Test1_Sheet1_Step2_fatal: "Erreur fatale : Aucune entrée valide trouvée dans le fichier" - Test1_Sheet2: 'Fiche n° 1.2 : Conformité au schéma XML du profil NEPTUNE' - Test1_Sheet2_Step1: Conformité au schéma XML du profil NEPTUNE - Test1_Sheet2_Step1_error: "le fichier %{0} ne respecte pas le modèle NEPTUNE" - Test1_Sheet2_Step1_encoding: "le fichier %{0} ne respecte pas le codage de caractères du modèle NEPTUNE (ISO-8859-1)" - Test1_Sheet2_Step1_fatal: "Erreur fatale : Aucune entrée valide trouvée dans le fichier" - TWO: "Catégorie 2 : Complétude, cohérence et intégrité des données" - Test2_Sheet1: "Fiche n° 2.1 : Cohérence entre le réseau et ses composants" - Test2_Sheet1_fatal: "La ligne %{0} n'a pas de réseau" - Test2_Sheet1_Step1: "Correcte réference à des LIGNEs/Chouette(<Line>)" - Test2_Sheet1_Step1_error: "La ligne %{1} n'est pas dans la liste des identifiants de ligne de %{0}" - Test2_Sheet1_Step2: "Correcte référence à la VERSION DU RÉSEAU(< PTNetwork >) dans LIGNEs/Chouette (< Line >)" - Test2_Sheet1_Step2a_error: "Le réseau %{0} n'est pas celui lié à la ligne %{1} dont le raccourci est %{2}." - Test2_Sheet1_Step2b_error: "Le raccourci du réseau %{0} dans la ligne %{1} ne correspond à aucun réseau de la ligne" - Test2_Sheet2: "Fiche n° 2.2 : Cohérence entre le regroupement de lignes et ses composants" - Test2_Sheet2_Step1: "Correcte référence à des LIGNEs/Chouette ( < Line >) dans GROUPE DE LIGNES ( < GroupOfLine >)" - Test2_Sheet2_Step1_error: "la valeur de l'élément < lineId > : %{0} de la classe d'objets < GroupOfLine > n'a pas été repérée dans l'élément < objectId > de la classe d'objets < Line >" - Test2_Sheet3: "Fiche n° 2.3 : Cohérence entre les arrêts et leurs composants" - Test2_Sheet3_Step1: "Correcte référence à des ARRÊTs/Chouette ( < StopArea >) et/ou à des POINTs D''ARRÊT SUR PARCOURS ( < StopPoint >) dans les ARRÊTs/Chouette ( < StopArea >) " - Test2_Sheet3_Step1_unchecked: "non implémenté" - Test2_Sheet3_Step1_error: "une ou plusieurs valeurs de l'élément < contains > de l'objet < StopArea > %{0} n'est pas repérée dans la classe d'objets correspondant < StopPoint > ou < StopArea >. >" - Test2_Sheet4: "Fiche n° 2.4 : Définition des correspondances" - Test2_Sheet4_Step1: "Correcte référence aux ARRÊTs/Chouette ( < StopArea >) définissant des TronçonsDeCorrespondance/Chouette ( < ConnectionLink >)" - Test2_Sheet4_Step1_unchecked: "non implémenté" - Test2_Sheet4_Step1_error: "L'objet < ConnectionLink > %{0} a des < StartOfLink > %{1} et < EndOfLink > %{2} qui pointent vers le même < StopArea >" - Test2_Sheet4_Step1_error_a: "a : il manque au moins un identifiant d'arrêt < StartOfLink > et < EndOfLink > dans l'objet < ConnectionLink > %{0}" - Test2_Sheet4_Step1_error_b: "b : un identifiant d'arrêt < StartOfLink > ou < EndOfLink > de l'objet < ConnectionLink> %{0} n'est pas repéré dans un objet < StopArea >" - Test2_Sheet5: "Fiche n° 2.5 : Cohérence entre les courses et les horaires" - Test2_Sheet5_Step1: "Correcte référence aux COURSES COMMERCIALES ( < VehicleJourney > ) dans les VERSIONs DES HORAIRES/Chouette ( < Timetable >)" - Test2_Sheet5_Step1_error: "un identifiant de course, situé dans l'objet < Timetable >, n'est pas référencé dans un objet < VehicleJourney >" - Test2_Sheet5_Step2: "Chaque COURSE COMMERCIALE ( < VehicleJourney > ) est référencée dans une VERSION DES HORAIRES/Chouette ( < Timetable >)" - Test2_Sheet5_Step2_error: "une course n'est pas référencée dans aucun < TimeTable >" - Test2_Sheet6: "Fiche n° 2.6 : Définition des terminus" - Test2_Sheet6_Step1: "Correcte définition du terminus de LIGNE/Chouette < Line >" - Test2_Sheet6_Step1_unchecked: "non implémenté" - Test2_Sheet6_Step1_error: "un identifiant de point d'arrêt de fin de trajet n'est pas repéré dans un objet < StopPoint>" - Test2_Sheet6_Step2: "Caractère terminus des points de fin de trajet des LIGNEs/Chouette < Line >" - Test2_Sheet6_Step2_error: "un identifiant de point d'arrêt de fin de trajet n'est pas repéré comme début ou comme fin d'un trajet" - Test2_Sheet7: "Fiche n° 2.7 : Cohérence entre les Itinéraires/Chouette et les LIGNEs/Chouette" - Test2_Sheet7_Step1: "Correcte référence aux Itinéraires/Chouette ( < ChouetteRoute >) pour chaque LIGNE/Chouette ( < Line >)" - Test2_Sheet7_Step1_unchecked: "non implémenté" - Test2_Sheet7_Step1_error: "un identifiant d'Itinéraire < RouteId > situé dans l'objet < Line > n'est pas identifié dans l'objet < ChouetteRoute >" - Test2_Sheet8: "Fiche n° 2.8 : Cohérence entre les missions commerciales et les itinéraires" - Test2_Sheet8_Step1: "Correcte référence des MISSIONs COMMERCIALEs ( < JourneyPattern >) par les Itinéraires/Chouette ( < ChouetteRoute >)" - Test2_Sheet8_Step1_error: "un élément < journeyPatternId > dans un objet d'Itinéraire < ChouetteRoute > n'a pas d'identifiant < ObjectId > dans un objet < JourneyPattern>" - Test2_Sheet8_Step2: "Correcte référence des Itinéraires/Chouette ( < ChouetteRoute >) que référencent les MISSIONs COMMERCIALEs ( < JourneyPattern >)" - Test2_Sheet8_Step2_error: "l'élément d'Itinéraire < routeId >, référencé dans un objet < JourneyPattern >, n'a pas d'identifiant < objectId > dans l'objet d'Itinéraire < ChouetteRoute >" - Test2_Sheet8_Step3: "Cohérence de la séquence des POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) d'une mission commerciale et celle de l'Itinéraire/Chouette ( < ChouetteRoute >) correspondant" - Test2_Sheet8_Step3_a_error: "a : l'identifiant du < %{0} > détecté dans l'objet < StopPoint > ne figure pas dans la liste des points d'arrêt de l'objet < JourneyPattern >" - Test2_Sheet8_Step3_b_error: "b : l'identifiant du %{0} < StopPoint > ne figure pas dans l'un des éléments < startOfLink > ou < endOfLink > du tronçon < PtLink >" - Test2_Sheet8_Step3_c_error: "c : l'identifiant du tronçon < PtLink > : %{0} , détecté dans le test b, n'est pas intégré dans un Itinéraire < ChouetteRoute >" - Test2_Sheet8_Step3_d_error: "d : les <PTLinks> de l'Itinéraire < ChouetteRoute > : %{0} ne sont pas cohérents avec les <StopPoints> du < JourneyPattern > %{1}" - Test2_Sheet9: "Fiche n° 2.9 : Définition de l'itinéraire retour" - Test2_Sheet9_Step1: "Correcte référence à un Itinéraire/Chouette ( < ChouetteRoute >) dans le cas d'un Itinéraire de retour" - Test2_Sheet9_Step1_error: "un élément d'Itinéraire de retour < wayBackRouteId > dans un objet d'Itinéraire < ChouetteRoute > n'a pas d'identifiant < ObjectId > dans un autre objet d'Itinéraire < ChouetteRoute >" - Test2_Sheet10: "Fiche n° 2.10 : Référence à une ligne pour un point d'arrêt" - Test2_Sheet10_Step1: "Correcte référence à une LIGNE/Chouette ( < Line >) pour les POINTs D'ARRÊT SUR PARCOURS ( < StopPoint > )" - Test2_Sheet10_Step1_error: "Le point d'arrêt (< StopPoint >) fait référence à une ligne inexistante>" - Test2_Sheet11: "Fiche n° 2.11 : Référence à un réseau au point d'arrêt" - Test2_Sheet11_Step1: "Correcte référence à la VERSION DU RÉSEAU ( < PTNetwork >) pour chaque POINT D'ARRÊT SUR PARCOURS \n( < StopPoint >)" - Test2_Sheet11_Step1_error: "Le point d'arrêt (< StopPoint >) fait référence à un réseau inexistant>" - Test2_Sheet12: "Fiche n° 2.12 : Définition de l''Interdiction de Trafic Local" - Test2_Sheet12_Step1: "Cohérence entre les objets < ITL > et les ARRÊTs/Chouette ( < StopArea >)" - Test2_Sheet12_Step1_error: "Un objet d'interdiction de trafic local < ITL > %{0} fait référence à un arrêt du réseau < StopArea > %{1} inexistant" - Test2_Sheet13: "Fiche n° 2.13 : Référence à une ligne des arrêts ITL" - Test2_Sheet13_Step1: "Correcte référence à la LIGNE/Chouette ( < Line >) pour chaque < ITL >" - Test2_Sheet13_Step1_error: "Un objet d'interdiction de trafic local < ITL > fait référence à une ligne inexistante" - Test2_Sheet14: "Fiche n° 2.14 : Association points d'arrêt, tronçons, itinéraire" - Test2_Sheet14_Step1: "Tout POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) est associé à un Itinéraire/Chouette (ChouetteRoute >)" - Test2_Sheet14_Step1a_error: "a : le point d'arrêt (< StopPoint >) %{0} n'appartient à aucune extrémité de tronçon" - Test2_Sheet14_Step1b_error: "b : le tronçon %{0} fait référence à un itinéraire inexistant" - Test2_Sheet14_Step2: "Continuité des tronçons COMMERCIAUX/Chouette ( < PtLink >) au sein d'un Itinéraire/Chouette ( < ChouetteRoute >)" - Test2_Sheet14_Step2_error: "l'analyse des tronçons d'un itinéraire fait apparaître que la valeur de l'attribut de l'élément < endOfLink > d'un premier tronçon < PtLink > n'est pas identique à la valeur de l'attribut de l'élément < startOfLink > du deuxième tronçon < PtLink >" - Test2_Sheet15: "Fiche n° 2.15 : Cohérence entre points d'arrêt et missions commerciales" - Test2_Sheet15_Step1: "Existence de définition des POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) d'une mission commerciale ( < JourneyPattern >)" - Test2_Sheet15_Step1_error: "La liste de l'objet < JourneyPattern > %{0} fait référence à des points d'arrêt inexistants" - Test2_Sheet15_Step2: "Tout POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) appartient à une mission commerciale ( < JourneyPattern >)" - Test2_Sheet15_Step2_error: "un point d'arrêt (< StopPoint >) n'est pas rattaché à une mission commerciale" - Test2_Sheet16: "Fiche n° 2.16 : Référence à une ligne des missions commerciales" - Test2_Sheet16_Step1: "Correcte référence à une une LIGNE/Chouette ( < Ligne >) pour une MISSION COMMERCIALE ( < JourneyPattern >)" - Test2_Sheet16_Step1_error: "Un objet < JourneyPattern > fait référence à une ligne inexistante" - Test2_Sheet17: "Fiche n° 2.17 : Cohérence entre itinéraires et courses" - Test2_Sheet17_Step1: "Correcte référence à l'Itinéraire/Chouette ( < ChouetteRoute) pour chaque COURSE COMMERCIALE ( < VehicleJourney > )" - Test2_Sheet17_Step1_error: "la course %{0} fait référence à un itinéraire inexistant %{1}" - Test2_Sheet18: "Fiche n° 2.18 : Cohérence entre les missions commerciales et les courses" - Test2_Sheet18_Step1: "Existence d'une MISSION COMMERCIALE ( < JourneyPattern < ) pour chaque COURSE COMMERCIALE ( < VehicleJourney >)" - Test2_Sheet18_Step1_error: "la course %{0} fait référence à une mission commerciale inexistante" - Test2_Sheet18_Step2: "Cohérence de points entre MISSION COMMERCIALE ( < JourneyPattern < ) et COURSE COMMERCIALE ( < VehicleJourney >)" - Test2_Sheet18_Step2_error_a: "a : l'identifiant (< StopPoint >) détecté dans un objet < StopPoint > ne figure pas dans la liste des points d'arrêts < stopPointList > de < JourneyPattern >" - Test2_Sheet18_Step2_error_b: "b : l'identifiant (< StopPoint >) ne figure pas dans l'élément < stopPointId > d'un objet < vehicleJourneyAtStop >" - Test2_Sheet19: "Fiche n° 2.19 : Référence à une ligne pour chaque course" - Test2_Sheet19_Step1: "Référence à une LIGNE/Chouette ( < Line >) pour une COURSE COMMERCIALE ( < VehicleJourney >)" - Test2_Sheet19_Step1_error: "le raccourci de ligne d'une course %{0} fait référence à une ligne inexistante" - Test2_Sheet20: "Fiche n° 2.20 : Vérification des identifiants d''exploitants que référencent les courses" - Test2_Sheet20_Step1: "Correcte référence à l'EXPLOITANT/Chouette ( < Company >) dans une COURSE COMMERCIALE ( < VehicleJourney > )" - Test2_Sheet20_Step1_error: "la course %{0} fait référence à un exploitant inexistant" - Test2_Sheet21: "Fiche n° 2.21 : Référence à une tranche horaire pour les courses" - Test2_Sheet21_Step1: "Correcte référence des COURSEs COMMERCIALEs ( < VehicleJourney > ) à des TRANCHEs HORAIREs ( < TimeSlot >)" - Test2_Sheet21_Step1_error: "la course %{0} fait référence à une tranche horaire inexistante" - Test2_Sheet22: "Fiche n° 2.22 : Cohérence entre les points d'arrêts et les heures de passage" - Test2_Sheet22_Step1: "Correcte référence à un POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) pour les HEUREs DE PASSAGE GRAPHIQUées/Chouette ( < VehicleJourneyAtStop >)" - Test2_Sheet22_Step1_error: "une heure de passage %{0} fait référence à un point d'arrêt (< StopPoint >) inexistant" - Test2_Sheet23: "Fiche n° 2.23 : Cohérence entre les courses et des heures de passage" - Test2_Sheet23_Step1: "Correcte référence à une COURSE COMMERCIALE \n( < VehicleJourney >) dans HEURE DE PASSAGE GRAPHIQUEE/Chouette ( < VehicleJourneyAtStop >)" - Test2_Sheet23_Step1_error: "une heure de passage %{0} fait référence à une course inexistante" - Test2_Sheet24: "Fiche n° 2.24 : Cohérence entre la mission commerciale de la course et l''itinéraire de la course" - Test2_Sheet24_Step1: "Cohérence de la référence un Itinéraire/Chouette pour une COURSE COMMERCIALE ( < VehicleJourney >) et la MISSION COMMERCIALE ( < JourneyPattern >) correspondante" - Test2_Sheet24_Step1_error: "un objet < vehicleJourney > possède une valeur de l'attribut de l'élément < RouteId >. Cette valeur ne se retrouve dans un élément < RouteId > d'un objet < JourneyPattern > " - Test2_Sheet25: "Fiche n° 2.25 : Définition des liens d'accès" - Test2_Sheet25_Step1: "Correcte référence aux ARRÊTs/Chouette ( < StopArea >) et ACCES/NEPTUNE ( <AccessPoint >) définissant des LiensAccèsZoneArrêt/NEPTUNE ( < AccessLink >)" - Test2_Sheet25_Step1_error_a: "a : les objets < StartOfLink > et < EndOfLink > de l'objet < AccessLink > sont identiques" - Test2_Sheet25_Step1_error_b: "b : un identifiant d'arrêt ou d'accès < StartOfLink > ou < EndOfLink > de l'objet < AccessLink> n'est pas repéré dans un objet < StopArea > ou < AccessPoint >" - Test2_Sheet26: "Fiche n° 2.26 : Cohérence entre les accès et leurs composants" - Test2_Sheet26_Step1: "Correcte référence à des ARRÊTs/Chouette ( < StopArea >) et/ou à des LiensAccèsZoneArrêt/NEPTUNE ( < AccessLink >) dans les ACCES/NEPTUNE ( < AccessPoint >) " - Test2_Sheet26_Step1_error: "une ou plusieurs valeurs de l'élément < containedIn> de la classe d'objets < AccessPoint> n'est pas repérée dans la classe d'objets correspondante < StopArea > ou < AccessLink >" - Test2_Sheet27: "Fiche n° 2.27 : Référence aux arrêts dans les équipements" - Test2_Sheet27_Step1: "Correcte référence à des ARRÊTs/Chouette ( < StopArea >) dans les EQUIPEMENTs /NEPTUNE ( <Facility>)" - Test2_Sheet27_Step1_error: "une valeur de l'élément < containedIn> de la classe d'objets < Facility> n'est pas repérée dans la classe d'objets correspondante < StopArea >" - Test2_Sheet28: "Fiche n° 2.28 : Référencement correct des composants dans les équipements" - Test2_Sheet28_Step1: "Correcte référence à un ARRÊT/Chouette ( < StopArea >) ou à une LIGNE/Chouette ( < Line >) ou à un POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) ou à un TronçonsDeCorrespondance/Chouette ( < ConnectionLink >) dans les FACILITYs /NEPTUNE ( <Facility>)" - Test2_Sheet28_Step1_error: "une valeur de l'élément < stopAreaId> de la classe d'objets < Facility> n'est pas repérée dans la classe d'objets correspondant < StopArea >" - Test2_Sheet28_Step2_error: "une valeur de l'élément < lineId> de la classe d'objets < Facility> n'est pas repérée dans la classe d'objets correspondant < Line>" - Test2_Sheet28_Step3_error: "une valeur de l'élément < connectionLinkId> de la classe d'objets < Facility> n'est pas repérée dans la classe d'objets correspondant < ConnectionLink >" - Test2_Sheet28_Step4_error: "une valeur de l'élément < stopPointId> de la classe d'objets < Facility> n'est pas repérée dans la classe d'objets correspondant < StopPoint >" - THREE: "Catégorie 3 : Contenu" - Test3_Sheet1: "Fiche n° 3.1 : Points d'arrêt de dénomination différente et très proches" - Test3_Sheet1_Step1: "2 POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) très proches porte le même nom/même adresse" - Test3_Sheet1_Step1_warning: "deux points d'arrêt séparés par une distance %{3} inférieure à une valeur paramétrable %{0} ne portent pas le même nom , premier : %{1} , deuxième : %{2} " - Test3_Sheet2: "Fiche n° 3.2 : Points d'arrêt très proches regroupés au sein d'une zone d'arrêt" - Test3_Sheet2_Step1: "2 POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) très proches appartiennent à un même ARRÊT1/Chouette ( < StopArea >)" - Test3_Sheet2_Step1_warning: "la distance calculée %{0} entre un point d'arrêt et les autres points d'arrêt est inférieure à une valeur paramétrable %{1} mais la valeur de l'attribut de l'élément < containedIn > de ces deux points d'arrêt < StopPoint > n'est pas identique, premier : %{2} , deuxième : %{3}" - Test3_Sheet3: "Fiche n° 3.3 : Unicité des noms de points d'arrêt " - Test3_Sheet3_Step1: "Différentiation de nom pour les POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >)" - Test3_Sheet3_Step1_warning: "deux points d'arrêt < StopPoint > : %{0} et %{1} de même nom ne sont pas suffisamment renseignés pour avoir des propriétés uniques" - Test3_Sheet4: "Fiche n° 3.4 : Unicité des noms de ligne" - Test3_Sheet4_Step1: "Chaque LINE/Chouette ( < Line >) possède des valeurs d'attributs uniques" - Test3_Sheet4_Step1_error: "les éléments < name > et < number > d'une ligne ne constituent pas un identifiant unique pour la ligne < Line > référencée par l'élément < %{0} >" - Test3_Sheet5: "Fiche n° 3.5 : Modèle de représentation des coordonnées des points d'arrêt" - Test3_Sheet5_Step1: "Coordonnées géographiques de chaque POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) par rapport à un modèle de projection de référence" - Test3_Sheet5_Step1_warning: "le point d'arrêt d'identifiant < %{0} > n'est pas dans le bon système de projection ou ses coordonnées géographiques sont nulle ou il est situé hors d'une zone dont le périmètre ou le contour est à définir" - Test3_Sheet6: "Fiche n° 3.6 : Localisation des points d'arrêt à l'intérieur d'un périmètre défini" - Test3_Sheet6_Step1: "Les coordonnées de chaque POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) sont inscrites dans une zone déterminée et qu'elles sont dans le bon système de projection" - Test3_Sheet6_Step1_warning_a: "a : le point d'arrêt d'identifiant < %{0} > n'est pas dans le bon système de projection " - Test3_Sheet6_Step1_error_b: "b : le point d'arrêt d'identifiant < %{0} > a des coordonnées qui sont hors du polygone de la zone couverte" - Test3_Sheet7: "Fiche n° 3.7 : Caractérisation des distances entre les points d'arrêt" - Test3_Sheet7_Step1: "La distance entre 2 POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) consécutifs" - Test3_Sheet7_Step1_warning: "la distance spatiale entre deux points d'arrêt consécutifs ne se situe pas dans une fourchette autorisée (entre %{0} pour sa valeur minimale et %{1} pour sa valeur supérieure" - Test3_Sheet8: "Fiche n° 3.8 : Cohérence entre le temps et la distance pour chaque correspondance" - Test3_Sheet8_Step1: " Les vitesses calculées à partir des attributs du TronçonDeCorrespondance/Chouette ( < ConnectionLink >) suivant les paramètres fixés" - Test3_Sheet8_Step1_error_a: "a : la vitesse fixée par l'élément < DefaultDuration > n'est pas conforme à la valeur paramétrable : Vitesse minimale %{0} et Vitesse maximale %{1} fixée pour la correspondance dont l'identifiant est < %{2} >" - Test3_Sheet8_Step1_error_b: "b : la vitesse fixée par l'élément < FrequentTravellerDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} (+/- delta) et Vitesse maximale %{1} fixée pour la correspondance dont l'identifiant est < %{2} >" - Test3_Sheet8_Step1_error_c: "c : la vitesse fixée par l'élément < OccasionalTravellerDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} (+/- delta) et Vitesse maximale %{1} fixée pour la correspondance dont l'identifiant est < %{2} >" - Test3_Sheet8_Step1_error_d: "d : la vitesse fixée par l'élément < MobilityRestrictedTravellerDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} (+/- delta) et Vitesse maximale %{1} fixée pour la correspondance dont l'identifiant est < %{2} >" - Test3_Sheet9: "Fiche n° 3.9 : Cohérence entre le temps et la distance pour chaque tronçon" - Test3_Sheet9_Step1: "La vitesse entre 2 POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) consécutifs se situe dans une fourchette autorisée" - Test3_Sheet9_Step1_warning: "la vitesse déterminée par la distance et le temps entre 2 points d'arrêt consécutifs (entre deux objets < %{0} > et < %{1} > ) ne se situe pas une fourchette autorisée entre %{2} et %{3}" - Test3_Sheet10: "Fiche n° 3.10 : Détection des boucles" - Test3_Sheet10_Step1: "Utilisation unique dans un Itinéraire/Chouette ( < ChouetteRoute >) d'un POINT D'ARRÊT SUR PARCOURS ( < StopPoint >)" - Test3_Sheet10_Step1_error_a: "a : le point d'arrêt d'identifiant < %{0} > est défini de manière unique et ne retrouve pas dans au moins deux tronçons" - Test3_Sheet10_Step1_error_b: "b : les identifiants de tronçon identifiés dans le 3.10.1 a ne sont pas présents dans un même itinéraire" - Test3_Sheet10_Step2: "Boucle dans un itinéraire/Chouette" - Test3_Sheet10_Step2_warning: "des tronçons < PtLink > utilisent des points d'arrêt < StopPoint > ayant la même valeur d'attribut que l'élément < containedIn > pour la route %{0} " - Test3_Sheet10_Step3: "La distance entre points d'arrêt d'un même itinéraire/Chouette" - Test3_Sheet10_Step3_warning: "des points d'arrêt < StopPoint > utilisés par des tronçons d'itinéraire, sont proches les uns des autres d'une distance %{0} inférieure à une valeur paramétrable %{1} " - Test3_Sheet11: "Fiche n° 3.11 : Détection des retours en arrière" - Test3_Sheet11_Step1: "Utilisation répétitive de POINTs D'ARRÊT SUR PARCOURS d'un Itinéraire/Chouette ( < ChouetteRoute >)" - Test3_Sheet11_Step1_warning: "les tronçons < PtLink > d'un itinéraire utilisent des points d'arrêt < StopPoint > identiques plus de deux fois" - Test3_Sheet12: "Fiche n° 3.12 : Connexité du graphe des lignes et des points d'arrêt" - Test3_Sheet12_Step1: "Construction d'un graphe à partir de chaque POINTs D'ARRÊT SUR PARCOURS" - Test3_Sheet15: "Fiche n° 3.15 : Cohérence des horaires" - Test3_Sheet15_Step1: "Cohérence des HEUREs DE PASSAGE GRAPHIQUEEs/Chouette ( < VehicleJourneyAtStop >) d'une COURSE ( < VehicleJourney >) pour chaque POINT D'ARRÊT SUR PARCOURS ( < StopPoint >)" - Test3_Sheet15_Step1_error: "la différence absolue entre la valeur de l'attribut de l'élément < arrivalTime > et la valeur de l'attribut de l'élément < departureTime > est supérieure à une valeur paramétrable %{0}" - Test3_Sheet16: "Fiche n° 3.16 : Cohérence des courses" - Test3_Sheet16_Step1: "Cohérence horaire pour 2 COURSEs ( < VehicleJourney >) utilisant le même couple de POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >)" - Test3_Sheet16_Step1_error: "pour deux courses qui utilisent le même couple de points A -> B, les temps de parcours : %{2} entre le point A : %{0} et le point B : %{1} ne sont pas cohérents" - Test3_Sheet16_Step2: "La VERSION DES HORAIREs/Chouette ( < Timetable >) contient des COURSEs ( < VehicleJourney >)" - Test3_Sheet16_Step2_warning: "La course < vehicleJourney > dont l'identifiant est < %{0} > n'est pas référencée dans l'objet < TimeTable >" - Test3_Sheet16_Step3: "Cohérence des HEUREs DE PASSAGE GRAPHIQUEEs/Chouette ( < VehicleJourneyAtStop >) entre 2 POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) consécutifs dans une COURSE ( < VehicleJourney >)" - Test3_Sheet16_Step3_error_a: "a : entre deux éléments < vehicleJourneyAtStop > successifs, la différence absolue entre la valeur de l'attribut de l'élément < departureTime > du premier point d'arrêt et la valeur de l'attribut de l'élément < arrivalTime > du second point d'arrêt : %{0} est supérieure à une valeur paramétrable %{1} " - Test3_Sheet16_Step3_error_b: "b : entre deux éléments < vehicleJourneyAtStop > successifs, la valeur de l'attribut de l'élément < departureTime > du premier point d'arrêt est inférieure à la valeur de l'attribut de l'élément < arrivalTime > du second point d'arrêt ou la valeur de l'attribut de l'élément < arrivalTime > du second point d'arrêt : %{0} est supérieure à une valeur paramétrable %{1}" - Test3_Sheet17: "Fiche n° 3.17 : Modèle de représentation des coordonnées des points d'accès" - Test3_Sheet17_Step1: " Les coordonnées géographiques de chaque POINT D'ACCES ( < AccessPoint >) par rapport à un modèle de projection de référence" - Test3_Sheet17_Step1_warning: "le point d'accès d'identifiant < %{0} > n'est pas dans le bon système de projection ou ses coordonnées géographiques sont nulles ou il est situé hors d'une zone dont le périmètre ou le contour est à définir" - Test3_Sheet18: "Fiche n° 3.18 : Localisation des points d'accès à l'intérieur d'un périmètre défini" - Test3_Sheet18_Step1: " Les coordonnées de chaque POINT D'ACCES ( < AccessPoint >) sont inscrites dans une zone déterminée et qu'elles sont dans le bon système de projection" - Test3_Sheet18_Step1_warning_a: "a : le point d'accès d'identifiant < %{0} > n'est pas dans le bon système de projection" - Test3_Sheet18_Step1_error_b: "b : le point d'accès d'identifiant < %{0} > a des coordonnées qui sont hors du polygone de la zone couverte" - Test3_Sheet19: "Fiche n° 3.19 : Modèle de représentation des coordonnées des équipements" - Test3_Sheet19_Step1: " Test des coordonnées géographiques de chaque EQUIPEMENT ( < Facility >) par rapport à un modèle de projection de référence" - Test3_Sheet19_Step1_warning: "l'equipement < %{0} > n'est pas dans le bon système de projection ou ses coordonnées géographiques sont nulle ou il est situé hors d'une zone dont le périmètre ou le contour est à définir" - Test3_Sheet20: "Fiche n° 3.20 : Localisation des équipements à l'intérieur d'un périmètre défini" - Test3_Sheet20_Step1: " Les coordonnées de chaque EQUIPEMENT ( < Facility>) sont inscrites dans une zone déterminée et qu'elles sont dans le bon système de projection" - Test3_Sheet20_Step1_warning_a: "a : l'equipement d'identifiant < %{0} > n'est pas dans le bon système de projection " - Test3_Sheet20_Step1_error_b: "b : l'equipement d'identifiant < %{0} > a des coordonnées qui sont hors du polygone de la zone couverte " - Test3_Sheet21: "Fiche n° 3.21 : Cohérence entre le temps et la distance pour chaque lien accès-zone d'arrêt" - Test3_Sheet21_Step1: " Les vitesses calculées à partir des attributs du LiensAccèsZoneArrêt /NEPTUNE ( < AccessLink >) suivant les paramètres fixés" - Test3_Sheet21_Step1_error_a: "a : la vitesse fixée par l'élément < DefaultDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} et Vitesse maximale %{1} fixée pour le lien d'accès dont l'identifiant est < %{2} >" - Test3_Sheet21_Step1_error_b: "b : la vitesse fixée par l'élément < FrequentTravellerDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} et Vitesse maximale %{1} fixée pour le lien d'accès dont l'identifiant est < %{2} >" - Test3_Sheet21_Step1_error_c: "c : la vitesse fixée par l'élément < OccasionalTravellerDuration > n'est pas conforme à la valeur paramétrable %{Vitesse minimale %{0} et Vitesse maximale %{1} fixée pour le lien d'accès dont l'identifiant est < %{2} >" - Test3_Sheet21_Step1_error_d: "d : la vitesse fixée par l'élément < MobilityRestrictedTravellerDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} et Vitesse maximale %{1} fixée pour le lien d'accès dont l'identifiant est < %{2} >" - severities: - uncheck: "Unchecked" - ok: "Ok" - warning: "Warning" - error: "Error" - fatal: "Fatal" - activerecord: - models: - file_validation: - zero: "Neptune Validation" - one: "Neptune Validation" - other: "Neptune Validation" - attributes: - file_validation: - resources: "File to validate" - status: "Status" - file_name: "Tested data" - test3_1_minimal_distance: "Distance minimale (test 3.1)" - test3_2_minimal_distance: "Distance minimale (test 3.2)" - test3_2_polygon_points: "Polygone (long lat) (test 3.6)" - test3_7_minimal_distance: "Distance minimale / maximale (test 3.7)" - test3_7_maximal_distance: " / " - test3_8a_minimal_speed: "Vitesse minimale / maximale (test 3.8a)" - test3_8a_maximal_speed: " / " - test3_8b_minimal_speed: "Vitesse minimale / maximale (test 3.8b)" - test3_8b_maximal_speed: " / " - test3_8c_minimal_speed: "Vitesse minimale / maximale (test 3.8c)" - test3_8c_maximal_speed: " / " - test3_8d_minimal_speed: "Vitesse minimale / maximale (test 3.8d)" - test3_8d_maximal_speed: " / " - test3_9_minimal_speed: "Vitesse minimale / maximale (test 3.9)" - test3_9_maximal_speed: " / " - test3_10_minimal_distance: "Distance minimale (test 3.10)" - test3_15_minimal_time: "Temps minimal (test 3.15)" - test3_16_1_maximal_time: "Ecart maximal de durée entre deux desserte d'un même tronçon (test 3.16.1)" - test3_16_3a_maximal_time: "Durée maximale du parcours entre 2 arrêts successifs (test 3.16.3a)" - test3_16_3b_maximal_time: "Heure maximale de départ au premier arrêt après minuit sur une course franchissant minuit (test 3.16.3b)" - test3_21a_minimal_speed: "Vitesse minimale / maximale (test 3.21a)" - test3_21a_maximal_speed: " / " - test3_21b_minimal_speed: "Vitesse minimale / maximale (test 3.21b)" - test3_21b_maximal_speed: " / " - test3_21c_minimal_speed: "Vitesse minimale / maximale (test 3.21c)" - test3_21c_maximal_speed: " / " - test3_21d_minimal_speed: "Vitesse minimale / maximale (test 3.21d)" - test3_21d_maximal_speed: " / " - projection_reference: "Système de projection de référence" - file_validation_log_message: - created_at: "Date" - position: "N." - full_message: "Message" - -fr: - file_validations: - index: - title: "Validation Neptune" - warning: "" - edit: - title: "Editer la validation" - show: - title: "Validation Neptune" - summary: "Rapport de conformité à la norme NEPTUNE" - details: "Détails" - parameters: "Paramètres des tests" - new: - title: "Démarrer une nouvelle validation" - submit: "Lancer la validation" - actions: - new: "Ajouter une validation" - destroy_confirm: "Voulez-vous supprimer ce résultat de validation ?" - destroy: "Supprimer cette validation" - edit: "Editer cette validation" - statuses: - pending: "En cours" - completed: "Achevé" - failed: "Echoué" - uncheck_count: - zero: "aucun inapplicable" - one: "un inapplicable" - other: "%{count} inapplicables" - ok_count: - zero: "aucun test réussi" - one: "un test réussi" - other: "%{count} tests réussis" - warning_count: - zero: "aucun warning" - one: "un warning" - other: "%{count} warnings" - error_count: - zero: "aucune erreur" - one: "une erreur" - other: "%{count} erreurs" - fatal_count: - zero: "aucune erreur fatale" - one: "une erreur fatale" - other: "%{count} erreurs fatales" - file_validation_log_messages: - messages: - undefined: "%{key} non défini" - TooMuchDetails: "( %{0} erreurs / warnings supplémentaires )" - ONE: "Catégorie 1 : Syntaxe" - Test1_Sheet1: 'Fiche n° 1.1 : Conformité à la syntaxe XML suivant les recommandations du W3C' - Test1_Sheet1_Step1: "Conformité à la syntaxe XML" - Test1_Sheet1_Step2: "Conformité au schéma XML du profil NEPTUNE" - Test1_Sheet1_Step0_fatal: "Erreur fatale : Impossible d'ouvrir le fichier %{0}" - Test1_Sheet1_Step0_error: "Impossible d'importer cette entrée %{0} du zip" - Test1_Sheet1_Step0_warning: "Cette entrée %{0} du zip n'est pas un fichier xml et a été ignoré" - Test1_Sheet1_Step1_error: "le fichier %{0} n'est pas correctement formé selon les recommandations du W3C" - Test1_Sheet1_Step2_error: "le fichier %{0} ne respecte pas le modèle NEPTUNE" - Test1_Sheet1_Step2_encoding: "le fichier %{0} ne respecte pas le codage de caractères du modèle NEPTUNE (ISO-8859-1)" - Test1_Sheet1_Step2_fatal: "Erreur fatale : Aucune entrée valide trouvée dans le fichier" - Test1_Sheet2: 'Fiche n° 1.2 : Conformité au schéma XML du profil NEPTUNE' - Test1_Sheet2_Step1: Conformité au schéma XML du profil NEPTUNE - Test1_Sheet2_Step1_error: "le fichier %{0} ne respecte pas le modèle NEPTUNE" - Test1_Sheet2_Step1_encoding: "le fichier %{0} ne respecte pas le codage de caractères du modèle NEPTUNE (ISO-8859-1)" - Test1_Sheet2_Step1_fatal: "Erreur fatale : Aucune entrée valide trouvée dans le fichier" - TWO: "Catégorie 2 : Complétude, cohérence et intégrité des données" - Test2_Sheet1: "Fiche n° 2.1 : Cohérence entre le réseau et ses composants" - Test2_Sheet1_fatal: "La ligne %{0} n'a pas de réseau" - Test2_Sheet1_Step1: "Correcte réference à des LIGNEs/Chouette(<Line>)" - Test2_Sheet1_Step1_error: "La ligne %{1} n'est pas dans la liste des identifiants de ligne de %{0}" - Test2_Sheet1_Step2: "Correcte référence à la VERSION DU RÉSEAU(< PTNetwork >) dans LIGNEs/Chouette (< Line >)" - Test2_Sheet1_Step2a_error: "Le réseau %{0} n'est pas celui lié à la ligne %{1} dont le raccourci est %{2}." - Test2_Sheet1_Step2b_error: "Le raccourci du réseau %{0} dans la ligne %{1} ne correspond à aucun réseau de la ligne" - Test2_Sheet2: "Fiche n° 2.2 : Cohérence entre le regroupement de lignes et ses composants" - Test2_Sheet2_Step1: "Correcte référence à des LIGNEs/Chouette ( < Line >) dans GROUPE DE LIGNES ( < GroupOfLine >)" - Test2_Sheet2_Step1_error: "la valeur de l'élément < lineId > : %{0} de la classe d'objets < GroupOfLine > n'a pas été repérée dans l'élément < objectId > de la classe d'objets < Line >" - Test2_Sheet3: "Fiche n° 2.3 : Cohérence entre les arrêts et leurs composants" - Test2_Sheet3_Step1: Conformité au schéma XML du profil NEPTUNE"Correcte référence à des ARRÊTs/Chouette ( < StopArea >) et/ou à des POINTs D''ARRÊT SUR PARCOURS ( < StopPoint >) dans les ARRÊTs/Chouette ( < StopArea >) " - Test2_Sheet3_Step1_unchecked: "non implémenté" - Test2_Sheet3_Step1_error: "une ou plusieurs valeurs de l'élément < contains > de l'objet < StopArea > %{0} n'est pas repérée dans la classe d'objets correspondant < StopPoint > ou < StopArea >. >" - Test2_Sheet4: "Fiche n° 2.4 : Définition des correspondances" - Test2_Sheet4_Step1: "Correcte référence aux ARRÊTs/Chouette ( < StopArea >) définissant des TronçonsDeCorrespondance/Chouette ( < ConnectionLink >)" - Test2_Sheet4_Step1_unchecked: "non implémenté" - Test2_Sheet4_Step1_error: "L'objet < ConnectionLink > %{0} a des < StartOfLink > %{1} et < EndOfLink > %{2} qui pointent vers le même < StopArea >" - Test2_Sheet4_Step1_error_a: "a : il manque au moins un identifiant d'arrêt < StartOfLink > et < EndOfLink > dans l'objet < ConnectionLink > %{0}" - Test2_Sheet4_Step1_error_b: "b : un identifiant d'arrêt < StartOfLink > ou < EndOfLink > de l'objet < ConnectionLink> %{0} n'est pas repéré dans un objet < StopArea >" - Test2_Sheet5: "Fiche n° 2.5 : Cohérence entre les courses et les horaires" - Test2_Sheet5_Step1: "Correcte référence aux COURSES COMMERCIALES ( < VehicleJourney > ) dans les VERSIONs DES HORAIRES/Chouette ( < Timetable >)" - Test2_Sheet5_Step1_error: "un identifiant de course, situé dans l'objet < Timetable >, n'est pas référencé dans un objet < VehicleJourney >" - Test2_Sheet5_Step2: "Chaque COURSE COMMERCIALE ( < VehicleJourney > ) est référencée dans une VERSION DES HORAIRES/Chouette ( < Timetable >)" - Test2_Sheet5_Step2_error: "une course n'est pas référencée dans aucun < TimeTable >" - Test2_Sheet6: "Fiche n° 2.6 : Définition des terminus" - Test2_Sheet6_Step1: "Correcte définition du terminus de LIGNE/Chouette < Line >" - Test2_Sheet6_Step1_unchecked: "non implémenté" - Test2_Sheet6_Step1_error: "un identifiant de point d'arrêt de fin de trajet n'est pas repéré dans un objet < StopPoint>" - Test2_Sheet6_Step2: "Caractère terminus des points de fin de trajet des LIGNEs/Chouette < Line >" - Test2_Sheet6_Step2_error: "un identifiant de point d'arrêt de fin de trajet n'est pas repéré comme début ou comme fin d'un trajet" - Test2_Sheet7: "Fiche n° 2.7 : Cohérence entre les Itinéraires/Chouette et les LIGNEs/Chouette" - Test2_Sheet7_Step1: "Correcte référence aux Itinéraires/Chouette ( < ChouetteRoute >) pour chaque LIGNE/Chouette ( < Line >)" - Test2_Sheet7_Step1_unchecked: "non implémenté" - Test2_Sheet7_Step1_error: "un identifiant d'Itinéraire < RouteId > situé dans l'objet < Line > n'est pas identifié dans l'objet < ChouetteRoute >" - Test2_Sheet8: "Fiche n° 2.8 : Cohérence entre les missions commerciales et les itinéraires" - Test2_Sheet8_Step1: "Correcte référence des MISSIONs COMMERCIALEs ( < JourneyPattern >) par les Itinéraires/Chouette ( < ChouetteRoute >)" - Test2_Sheet8_Step1_error: "un élément < journeyPatternId > dans un objet d'Itinéraire < ChouetteRoute > n'a pas d'identifiant < ObjectId > dans un objet < JourneyPattern>" - Test2_Sheet8_Step2: "Correcte référence des Itinéraires/Chouette ( < ChouetteRoute >) que référencent les MISSIONs COMMERCIALEs ( < JourneyPattern >)" - Test2_Sheet8_Step2_error: "l'élément d'Itinéraire < routeId >, référencé dans un objet < JourneyPattern >, n'a pas d'identifiant < objectId > dans l'objet d'Itinéraire < ChouetteRoute >" - Test2_Sheet8_Step3: "Cohérence de la séquence des POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) d'une mission commerciale et celle de l'Itinéraire/Chouette ( < ChouetteRoute >) correspondant" - Test2_Sheet8_Step3_a_error: "a : l'identifiant du < %{0} > détecté dans l'objet < StopPoint > ne figure pas dans la liste des points d'arrêt de l'objet < JourneyPattern >" - Test2_Sheet8_Step3_b_error: "b : l'identifiant du %{0} < StopPoint > ne figure pas dans l'un des éléments < startOfLink > ou < endOfLink > du tronçon < PtLink >" - Test2_Sheet8_Step3_c_error: "c : l'identifiant du tronçon < PtLink > : %{0} , détecté dans le test b, n'est pas intégré dans un Itinéraire < ChouetteRoute >" - Test2_Sheet8_Step3_d_error: "d : les <PTLinks> de l'Itinéraire < ChouetteRoute > : %{0} ne sont pas cohérents avec les <StopPoints> du < JourneyPattern > %{1}" - Test2_Sheet9: "Fiche n° 2.9 : Définition de l'itinéraire retour" - Test2_Sheet9_Step1: "Correcte référence à un Itinéraire/Chouette ( < ChouetteRoute >) dans le cas d'un Itinéraire de retour" - Test2_Sheet9_Step1_error: "un élément d'Itinéraire de retour < wayBackRouteId > dans un objet d'Itinéraire < ChouetteRoute > n'a pas d'identifiant < ObjectId > dans un autre objet d'Itinéraire < ChouetteRoute >" - Test2_Sheet10: "Fiche n° 2.10 : Référence à une ligne pour un point d'arrêt" - Test2_Sheet10_Step1: "Correcte référence à une LIGNE/Chouette ( < Line >) pour les POINTs D'ARRÊT SUR PARCOURS ( < StopPoint > )" - Test2_Sheet10_Step1_error: "Le point d'arrêt (< StopPoint >) fait référence à une ligne inexistante>" - Test2_Sheet11: "Fiche n° 2.11 : Référence à un réseau au point d'arrêt" - Test2_Sheet11_Step1: "Correcte référence à la VERSION DU RÉSEAU ( < PTNetwork >) pour chaque POINT D'ARRÊT SUR PARCOURS \n( < StopPoint >)" - Test2_Sheet11_Step1_error: "Le point d'arrêt (< StopPoint >) fait référence à un réseau inexistant>" - Test2_Sheet12: "Fiche n° 2.12 : Définition de l''Interdiction de Trafic Local" - Test2_Sheet12_Step1: "Cohérence entre les objets < ITL > et les ARRÊTs/Chouette ( < StopArea >)" - Test2_Sheet12_Step1_error: "Un objet d'interdiction de trafic local < ITL > %{0} fait référence à un arrêt du réseau < StopArea > %{1} inexistant" - Test2_Sheet13: "Fiche n° 2.13 : Référence à une ligne des arrêts ITL" - Test2_Sheet13_Step1: "Correcte référence à la LIGNE/Chouette ( < Line >) pour chaque < ITL >" - Test2_Sheet13_Step1_error: "Un objet d'interdiction de trafic local < ITL > fait référence à une ligne inexistante" - Test2_Sheet14: "Fiche n° 2.14 : Association points d'arrêt, tronçons, itinéraire" - Test2_Sheet14_Step1: "Tout POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) est associé à un Itinéraire/Chouette (ChouetteRoute >)" - Test2_Sheet14_Step1a_error: "a : le point d'arrêt (< StopPoint >) %{0} n'appartient à aucune extrémité de tronçon" - Test2_Sheet14_Step1b_error: "b : le tronçon %{0} fait référence à un itinéraire inexistant" - Test2_Sheet14_Step2: "Continuité des tronçons COMMERCIAUX/Chouette ( < PtLink >) au sein d'un Itinéraire/Chouette ( < ChouetteRoute >)" - Test2_Sheet14_Step2_error: "l'analyse des tronçons d'un itinéraire fait apparaître que la valeur de l'attribut de l'élément < endOfLink > d'un premier tronçon < PtLink > n'est pas identique à la valeur de l'attribut de l'élément < startOfLink > du deuxième tronçon < PtLink >" - Test2_Sheet15: "Fiche n° 2.15 : Cohérence entre points d'arrêt et missions commerciales" - Test2_Sheet15_Step1: "Existence de définition des POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) d'une mission commerciale ( < JourneyPattern >)" - Test2_Sheet15_Step1_error: "La liste de l'objet < JourneyPattern > %{0} fait référence à des points d'arrêt inexistants" - Test2_Sheet15_Step2: "Tout POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) appartient à une mission commerciale ( < JourneyPattern >)" - Test2_Sheet15_Step2_error: "un point d'arrêt (< StopPoint >) n'est pas rattaché à une mission commerciale" - Test2_Sheet16: "Fiche n° 2.16 : Référence à une ligne des missions commerciales" - Test2_Sheet16_Step1: "Correcte référence à une une LIGNE/Chouette ( < Ligne >) pour une MISSION COMMERCIALE ( < JourneyPattern >)" - Test2_Sheet16_Step1_error: "Un objet < JourneyPattern > fait référence à une ligne inexistante" - Test2_Sheet17: "Fiche n° 2.17 : Cohérence entre itinéraires et courses" - Test2_Sheet17_Step1: "Correcte référence à l'Itinéraire/Chouette ( < ChouetteRoute) pour chaque COURSE COMMERCIALE ( < VehicleJourney > )" - Test2_Sheet17_Step1_error: "la course %{0} fait référence à un itinéraire inexistant %{1}" - Test2_Sheet18: "Fiche n° 2.18 : Cohérence entre les missions commerciales et les courses" - Test2_Sheet18_Step1: "Existence d'une MISSION COMMERCIALE ( < JourneyPattern < ) pour chaque COURSE COMMERCIALE ( < VehicleJourney >)" - Test2_Sheet18_Step1_error: "la course %{0} fait référence à une mission commerciale inexistante" - Test2_Sheet18_Step2: "Cohérence de points entre MISSION COMMERCIALE ( < JourneyPattern < ) et COURSE COMMERCIALE ( < VehicleJourney >)" - Test2_Sheet18_Step2_error_a: "a : l'identifiant (< StopPoint >) détecté dans un objet < StopPoint > ne figure pas dans la liste des points d'arrêts < stopPointList > de < JourneyPattern >" - Test2_Sheet18_Step2_error_b: "b : l'identifiant (< StopPoint >) ne figure pas dans l'élément < stopPointId > d'un objet < vehicleJourneyAtStop >" - Test2_Sheet19: "Fiche n° 2.19 : Référence à une ligne pour chaque course" - Test2_Sheet19_Step1: "Référence à une LIGNE/Chouette ( < Line >) pour une COURSE COMMERCIALE ( < VehicleJourney >)" - Test2_Sheet19_Step1_error: "le raccourci de ligne d'une course %{0} fait référence à une ligne inexistante" - Test2_Sheet20: "Fiche n° 2.20 : Vérification des identifiants d''exploitants que référencent les courses" - Test2_Sheet20_Step1: "Correcte référence à l'EXPLOITANT/Chouette ( < Company >) dans une COURSE COMMERCIALE ( < VehicleJourney > )" - Test2_Sheet20_Step1_error: "la course %{0} fait référence à un exploitant inexistant" - Test2_Sheet21: "Fiche n° 2.21 : Référence à une tranche horaire pour les courses" - Test2_Sheet21_Step1: "Correcte référence des COURSEs COMMERCIALEs ( < VehicleJourney > ) à des TRANCHEs HORAIREs ( < TimeSlot >)" - Test2_Sheet21_Step1_error: "la course %{0} fait référence à une tranche horaire inexistante" - Test2_Sheet22: "Fiche n° 2.22 : Cohérence entre les points d'arrêts et les heures de passage" - Test2_Sheet22_Step1: "Correcte référence à un POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) pour les HEUREs DE PASSAGE GRAPHIQUées/Chouette ( < VehicleJourneyAtStop >)" - Test2_Sheet22_Step1_error: "une heure de passage %{0} fait référence à un point d'arrêt (< StopPoint >) inexistant" - Test2_Sheet23: "Fiche n° 2.23 : Cohérence entre les courses et des heures de passage" - Test2_Sheet23_Step1: "Correcte référence à une COURSE COMMERCIALE \n( < VehicleJourney >) dans HEURE DE PASSAGE GRAPHIQUEE/Chouette ( < VehicleJourneyAtStop >)" - Test2_Sheet23_Step1_error: "une heure de passage %{0} fait référence à une course inexistante" - Test2_Sheet24: "Fiche n° 2.24 : Cohérence entre la mission commerciale de la course et l''itinéraire de la course" - Test2_Sheet24_Step1: "Cohérence de la référence un Itinéraire/Chouette pour une COURSE COMMERCIALE ( < VehicleJourney >) et la MISSION COMMERCIALE ( < JourneyPattern >) correspondante" - Test2_Sheet24_Step1_error: "un objet < vehicleJourney > possède une valeur de l'attribut de l'élément < RouteId >. Cette valeur ne se retrouve dans un élément < RouteId > d'un objet < JourneyPattern > " - Test2_Sheet25: "Fiche n° 2.25 : Définition des liens d'accès" - Test2_Sheet25_Step1: "Correcte référence aux ARRÊTs/Chouette ( < StopArea >) et ACCES/NEPTUNE ( <AccessPoint >) définissant des LiensAccèsZoneArrêt/NEPTUNE ( < AccessLink >)" - Test2_Sheet25_Step1_error_a: "a : les objets < StartOfLink > et < EndOfLink > de l'objet < AccessLink > sont identiques" - Test2_Sheet25_Step1_error_b: "b : un identifiant d'arrêt ou d'accès < StartOfLink > ou < EndOfLink > de l'objet < AccessLink> n'est pas repéré dans un objet < StopArea > ou < AccessPoint >" - Test2_Sheet26: "Fiche n° 2.26 : Cohérence entre les accès et leurs composants" - Test2_Sheet26_Step1: "Correcte référence à des ARRÊTs/Chouette ( < StopArea >) et/ou à des LiensAccèsZoneArrêt/NEPTUNE ( < AccessLink >) dans les ACCES/NEPTUNE ( < AccessPoint >) " - Test2_Sheet26_Step1_error: "une ou plusieurs valeurs de l'élément < containedIn> de la classe d'objets < AccessPoint> n'est pas repérée dans la classe d'objets correspondante < StopArea > ou < AccessLink >" - Test2_Sheet27: "Fiche n° 2.27 : Référence aux arrêts dans les équipements" - Test2_Sheet27_Step1: "Correcte référence à des ARRÊTs/Chouette ( < StopArea >) dans les EQUIPEMENTs /NEPTUNE ( <Facility>)" - Test2_Sheet27_Step1_error: "une valeur de l'élément < containedIn> de la classe d'objets < Facility> n'est pas repérée dans la classe d'objets correspondante < StopArea >" - Test2_Sheet28: "Fiche n° 2.28 : Référencement correct des composants dans les équipements" - Test2_Sheet28_Step1: "Correcte référence à un ARRÊT/Chouette ( < StopArea >) ou à une LIGNE/Chouette ( < Line >) ou à un POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) ou à un TronçonsDeCorrespondance/Chouette ( < ConnectionLink >) dans les FACILITYs /NEPTUNE ( <Facility>)" - Test2_Sheet28_Step1_error: "une valeur de l'élément < stopAreaId> de la classe d'objets < Facility> n'est pas repérée dans la classe d'objets correspondant < StopArea >" - Test2_Sheet28_Step2_error: "une valeur de l'élément < lineId> de la classe d'objets < Facility> n'est pas repérée dans la classe d'objets correspondant < Line>" - Test2_Sheet28_Step3_error: "une valeur de l'élément < connectionLinkId> de la classe d'objets < Facility> n'est pas repérée dans la classe d'objets correspondant < ConnectionLink >" - Test2_Sheet28_Step4_error: "une valeur de l'élément < stopPointId> de la classe d'objets < Facility> n'est pas repérée dans la classe d'objets correspondant < StopPoint >" - THREE: "Catégorie 3 : Contenu" - Test3_Sheet1: "Fiche n° 3.1 : Points d'arrêt de dénomination différente et très proches" - Test3_Sheet1_Step1: "2 POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) très proches porte le même nom/même adresse" - Test3_Sheet1_Step1_warning: "deux points d'arrêt séparés par une distance %{3} inférieure à une valeur paramétrable %{0} ne portent pas le même nom , premier : %{1} , deuxième : %{2} " - Test3_Sheet2: "Fiche n° 3.2 : Points d'arrêt très proches regroupés au sein d'une zone d'arrêt" - Test3_Sheet2_Step1: "2 POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) très proches appartiennent à un même ARRÊT1/Chouette ( < StopArea >)" - Test3_Sheet2_Step1_warning: "la distance calculée %{0} entre un point d'arrêt et les autres points d'arrêt est inférieure à une valeur paramétrable %{1} mais la valeur de l'attribut de l'élément < containedIn > de ces deux points d'arrêt < StopPoint > n'est pas identique, premier : %{2} , deuxième : %{3}" - Test3_Sheet3: "Fiche n° 3.3 : Unicité des noms de points d'arrêt " - Test3_Sheet3_Step1: "Différentiation de nom pour les POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >)" - Test3_Sheet3_Step1_warning: "deux points d'arrêt < StopPoint > : %{0} et %{1} de même nom ne sont pas suffisamment renseignés pour avoir des propriétés uniques" - Test3_Sheet4: "Fiche n° 3.4 : Unicité des noms de ligne" - Test3_Sheet4_Step1: "Chaque LINE/Chouette ( < Line >) possède des valeurs d'attributs uniques" - Test3_Sheet4_Step1_error: "les éléments < name > et < number > d'une ligne ne constituent pas un identifiant unique pour la ligne < Line > référencée par l'élément < %{0} >" - Test3_Sheet5: "Fiche n° 3.5 : Modèle de représentation des coordonnées des points d'arrêt" - Test3_Sheet5_Step1: "Coordonnées géographiques de chaque POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) par rapport à un modèle de projection de référence" - Test3_Sheet5_Step1_warning: "le point d'arrêt d'identifiant < %{0} > n'est pas dans le bon système de projection ou ses coordonnées géographiques sont nulle ou il est situé hors d'une zone dont le périmètre ou le contour est à définir" - Test3_Sheet6: "Fiche n° 3.6 : Localisation des points d'arrêt à l'intérieur d'un périmètre défini" - Test3_Sheet6_Step1: "Les coordonnées de chaque POINT D'ARRÊT SUR PARCOURS ( < StopPoint >) sont inscrites dans une zone déterminée et qu'elles sont dans le bon système de projection" - Test3_Sheet6_Step1_warning_a: "a : le point d'arrêt d'identifiant < %{0} > n'est pas dans le bon système de projection " - Test3_Sheet6_Step1_error_b: "b : le point d'arrêt d'identifiant < %{0} > a des coordonnées qui sont hors du polygone de la zone couverte" - Test3_Sheet7: "Fiche n° 3.7 : Caractérisation des distances entre les points d'arrêt" - Test3_Sheet7_Step1: "La distance entre 2 POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) consécutifs" - Test3_Sheet7_Step1_warning: "la distance spatiale entre deux points d'arrêt consécutifs ne se situe pas dans une fourchette autorisée (entre %{0} pour sa valeur minimale et %{1} pour sa valeur supérieure" - Test3_Sheet8: "Fiche n° 3.8 : Cohérence entre le temps et la distance pour chaque correspondance" - Test3_Sheet8_Step1: " Les vitesses calculées à partir des attributs du TronçonDeCorrespondance/Chouette ( < ConnectionLink >) suivant les paramètres fixés" - Test3_Sheet8_Step1_error_a: "a : la vitesse fixée par l'élément < DefaultDuration > n'est pas conforme à la valeur paramétrable : Vitesse minimale %{0} et Vitesse maximale %{1} fixée pour la correspondance dont l'identifiant est < %{2} >" - Test3_Sheet8_Step1_error_b: "b : la vitesse fixée par l'élément < FrequentTravellerDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} (+/- delta) et Vitesse maximale %{1} fixée pour la correspondance dont l'identifiant est < %{2} >" - Test3_Sheet8_Step1_error_c: "c : la vitesse fixée par l'élément < OccasionalTravellerDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} (+/- delta) et Vitesse maximale %{1} fixée pour la correspondance dont l'identifiant est < %{2} >" - Test3_Sheet8_Step1_error_d: "d : la vitesse fixée par l'élément < MobilityRestrictedTravellerDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} (+/- delta) et Vitesse maximale %{1} fixée pour la correspondance dont l'identifiant est < %{2} >" - Test3_Sheet9: "Fiche n° 3.9 : Cohérence entre le temps et la distance pour chaque tronçon" - Test3_Sheet9_Step1: "La vitesse entre 2 POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) consécutifs se situe dans une fourchette autorisée" - Test3_Sheet9_Step1_warning: "la vitesse déterminée par la distance et le temps entre 2 points d'arrêt consécutifs (entre deux objets < %{0} > et < %{1} > ) ne se situe pas une fourchette autorisée entre %{2} et %{3}" - Test3_Sheet10: "Fiche n° 3.10 : Détection des boucles" - Test3_Sheet10_Step1: "Utilisation unique dans un Itinéraire/Chouette ( < ChouetteRoute >) d'un POINT D'ARRÊT SUR PARCOURS ( < StopPoint >)" - Test3_Sheet10_Step1_error_a: "a : le point d'arrêt d'identifiant < %{0} > est défini de manière unique et ne retrouve pas dans au moins deux tronçons" - Test3_Sheet10_Step1_error_b: "b : les identifiants de tronçon identifiés dans le 3.10.1 a ne sont pas présents dans un même itinéraire" - Test3_Sheet10_Step2: "Boucle dans un itinéraire/Chouette" - Test3_Sheet10_Step2_warning: "des tronçons < PtLink > utilisent des points d'arrêt < StopPoint > ayant la même valeur d'attribut que l'élément < containedIn > pour la route %{0} " - Test3_Sheet10_Step3: "La distance entre points d'arrêt d'un même itinéraire/Chouette" - Test3_Sheet10_Step3_warning: "des points d'arrêt < StopPoint > utilisés par des tronçons d'itinéraire, sont proches les uns des autres d'une distance %{0} inférieure à une valeur paramétrable %{1} " - Test3_Sheet11: "Fiche n° 3.11 : Détection des retours en arrière" - Test3_Sheet11_Step1: "Utilisation répétitive de POINTs D'ARRÊT SUR PARCOURS d'un Itinéraire/Chouette ( < ChouetteRoute >)" - Test3_Sheet11_Step1_warning: "les tronçons < PtLink > d'un itinéraire utilisent des points d'arrêt < StopPoint > identiques plus de deux fois" - Test3_Sheet12: "Fiche n° 3.12 : Connexité du graphe des lignes et des points d'arrêt" - Test3_Sheet12_Step1: "Construction d'un graphe à partir de chaque POINTs D'ARRÊT SUR PARCOURS" - Test3_Sheet15: "Fiche n° 3.15 : Cohérence des horaires" - Test3_Sheet15_Step1: "Cohérence des HEUREs DE PASSAGE GRAPHIQUEEs/Chouette ( < VehicleJourneyAtStop >) d'une COURSE ( < VehicleJourney >) pour chaque POINT D'ARRÊT SUR PARCOURS ( < StopPoint >)" - Test3_Sheet15_Step1_error: "la différence absolue entre la valeur de l'attribut de l'élément < arrivalTime > et la valeur de l'attribut de l'élément < departureTime > est supérieure à une valeur paramétrable %{0}" - Test3_Sheet16: "Fiche n° 3.16 : Cohérence des courses" - Test3_Sheet16_Step1: "Cohérence horaire pour 2 COURSEs ( < VehicleJourney >) utilisant le même couple de POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >)" - Test3_Sheet16_Step1_error: "pour deux courses qui utilisent le même couple de points A -> B, les temps de parcours : %{2} entre le point A : %{0} et le point B : %{1} ne sont pas cohérents" - Test3_Sheet16_Step2: "La VERSION DES HORAIREs/Chouette ( < Timetable >) contient des COURSEs ( < VehicleJourney >)" - Test3_Sheet16_Step2_warning: "La course < vehicleJourney > dont l'identifiant est < %{0} > n'est pas référencée dans l'objet < TimeTable >" - Test3_Sheet16_Step3: "Cohérence des HEUREs DE PASSAGE GRAPHIQUEEs/Chouette ( < VehicleJourneyAtStop >) entre 2 POINTs D'ARRÊT SUR PARCOURS ( < StopPoint >) consécutifs dans une COURSE ( < VehicleJourney >)" - Test3_Sheet16_Step3_error_a: "a : entre deux éléments < vehicleJourneyAtStop > successifs, la différence absolue entre la valeur de l'attribut de l'élément < departureTime > du premier point d'arrêt et la valeur de l'attribut de l'élément < arrivalTime > du second point d'arrêt : %{0} est supérieure à une valeur paramétrable %{1} " - Test3_Sheet16_Step3_error_b: "b : entre deux éléments < vehicleJourneyAtStop > successifs, la valeur de l'attribut de l'élément < departureTime > du premier point d'arrêt est inférieure à la valeur de l'attribut de l'élément < arrivalTime > du second point d'arrêt ou la valeur de l'attribut de l'élément < arrivalTime > du second point d'arrêt : %{0} est supérieure à une valeur paramétrable %{1}" - Test3_Sheet17: "Fiche n° 3.17 : Modèle de représentation des coordonnées des points d'accès" - Test3_Sheet17_Step1: " Les coordonnées géographiques de chaque POINT D'ACCES ( < AccessPoint >) par rapport à un modèle de projection de référence" - Test3_Sheet17_Step1_warning: "le point d'accès d'identifiant < %{0} > n'est pas dans le bon système de projection ou ses coordonnées géographiques sont nulles ou il est situé hors d'une zone dont le périmètre ou le contour est à définir" - Test3_Sheet18: "Fiche n° 3.18 : Localisation des points d'accès à l'intérieur d'un périmètre défini" - Test3_Sheet18_Step1: " Les coordonnées de chaque POINT D'ACCES ( < AccessPoint >) sont inscrites dans une zone déterminée et qu'elles sont dans le bon système de projection" - Test3_Sheet18_Step1_warning_a: "a : le point d'accès d'identifiant < %{0} > n'est pas dans le bon système de projection" - Test3_Sheet18_Step1_error_b: "b : le point d'accès d'identifiant < %{0} > a des coordonnées qui sont hors du polygone de la zone couverte" - Test3_Sheet19: "Fiche n° 3.19 : Modèle de représentation des coordonnées des équipements" - Test3_Sheet19_Step1: " Test des coordonnées géographiques de chaque EQUIPEMENT ( < Facility >) par rapport à un modèle de projection de référence" - Test3_Sheet19_Step1_warning: "l'equipement < %{0} > n'est pas dans le bon système de projection ou ses coordonnées géographiques sont nulle ou il est situé hors d'une zone dont le périmètre ou le contour est à définir" - Test3_Sheet20: "Fiche n° 3.20 : Localisation des équipements à l'intérieur d'un périmètre défini" - Test3_Sheet20_Step1: " Les coordonnées de chaque EQUIPEMENT ( < Facility>) sont inscrites dans une zone déterminée et qu'elles sont dans le bon système de projection" - Test3_Sheet20_Step1_warning_a: "a : l'equipement d'identifiant < %{0} > n'est pas dans le bon système de projection " - Test3_Sheet20_Step1_error_b: "b : l'equipement d'identifiant < %{0} > a des coordonnées qui sont hors du polygone de la zone couverte " - Test3_Sheet21: "Fiche n° 3.21 : Cohérence entre le temps et la distance pour chaque lien accès-zone d'arrêt" - Test3_Sheet21_Step1: " Les vitesses calculées à partir des attributs du LiensAccèsZoneArrêt /NEPTUNE ( < AccessLink >) suivant les paramètres fixés" - Test3_Sheet21_Step1_error_a: "a : la vitesse fixée par l'élément < DefaultDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} et Vitesse maximale %{1} fixée pour le lien d'accès dont l'identifiant est < %{2} >" - Test3_Sheet21_Step1_error_b: "b : la vitesse fixée par l'élément < FrequentTravellerDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} et Vitesse maximale %{1} fixée pour le lien d'accès dont l'identifiant est < %{2} >" - Test3_Sheet21_Step1_error_c: "c : la vitesse fixée par l'élément < OccasionalTravellerDuration > n'est pas conforme à la valeur paramétrable %{Vitesse minimale %{0} et Vitesse maximale %{1} fixée pour le lien d'accès dont l'identifiant est < %{2} >" - Test3_Sheet21_Step1_error_d: "d : la vitesse fixée par l'élément < MobilityRestrictedTravellerDuration > n'est pas conforme à la valeur paramétrable Vitesse minimale %{0} et Vitesse maximale %{1} fixée pour le lien d'accès dont l'identifiant est < %{2} >" - severities: - uncheck: "Non testé" - ok: "Ok" - warning: "Alerte" - error: "Erreur" - fatal: "Fatal" - activerecord: - models: - file_validation: - zero: "Validation Neptune" - one: "Validation Neptune" - other: "Validations Neptune" - attributes: - file_validation: - resources: "Fichier à valider" - status: "Status" - file_name: "Jeu de données" - test3_1_minimal_distance: "Distance minimale (test 3.1)" - test3_2_minimal_distance: "Distance minimale (test 3.2)" - test3_2_polygon_points: "Polygone (long lat) (test 3.6)" - test3_7_minimal_distance: "Distance minimale / maximale (test 3.7)" - test3_7_maximal_distance: " / " - test3_8a_minimal_speed: "Vitesse minimale / maximale (test 3.8a)" - test3_8a_maximal_speed: " / " - test3_8b_minimal_speed: "Vitesse minimale / maximale (test 3.8b)" - test3_8b_maximal_speed: " / " - test3_8c_minimal_speed: "Vitesse minimale / maximale (test 3.8c)" - test3_8c_maximal_speed: " / " - test3_8d_minimal_speed: "Vitesse minimale / maximale (test 3.8d)" - test3_8d_maximal_speed: " / " - test3_9_minimal_speed: "Vitesse minimale / maximale (test 3.9)" - test3_9_maximal_speed: " / " - test3_10_minimal_distance: "Distance minimale (test 3.10)" - test3_15_minimal_time: "Temps minimal (test 3.15)" - test3_16_1_maximal_time: "Ecart maximal de durée entre deux desserte d'un même tronçon (test 3.16.1)" - test3_16_3a_maximal_time: "Durée maximale du parcours entre 2 arrêts successifs (test 3.16.3a)" - test3_16_3b_maximal_time: "Heure maximale de départ au premier arrêt après minuit sur une course franchissant minuit (test 3.16.3b)" - test3_21a_minimal_speed: "Vitesse minimale / maximale (test 3.21a)" - test3_21a_maximal_speed: " / " - test3_21b_minimal_speed: "Vitesse minimale / maximale (test 3.21b)" - test3_21b_maximal_speed: " / " - test3_21c_minimal_speed: "Vitesse minimale / maximale (test 3.21c)" - test3_21c_maximal_speed: " / " - test3_21d_minimal_speed: "Vitesse minimale / maximale (test 3.21d)" - test3_21d_maximal_speed: " / " - projection_reference: "Système de projection de référence" - file_validation_log_message: - created_at: "Date" - position: "N." - full_message: "Message" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 31075abe5..e2632152c 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -225,16 +225,4 @@ fr: <<: *errors # FIN: https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/fr.yml - "true": "oui" - "false": "non" - or: "ou" - back: "Revenir" - today: "Aujourd'hui" - yesterday: "Hier" - edit_periods: "Editer Périodes" - delete_periods: "Supprimer Périodes" - attributes: - author: "Modifié par" - created_at: "Créé le" - updated_at: "Modifié le" diff --git a/config/locales/import_tasks.yml b/config/locales/import_tasks.yml new file mode 100644 index 000000000..94134188f --- /dev/null +++ b/config/locales/import_tasks.yml @@ -0,0 +1,195 @@ +en: + import_tasks: + actions: + new: "New import" + destroy: "Destroy" + destroy_confirm: "Are you sure you want destroy this import?" + new: + title: "New import" + index: + title: "Imports" + warning: "" + show: + report: "Report" + not_yet_started: "On queue" + imported_file: "Imported file" + completed: "[ Completed ]" + failed: "[ Failed ]" + pending: "[ In the treatment queue ]" + processing: "[ In progress... ]" + graph: + files: + title_zip: "Import results for files in zip" + title_default: "Import result for %{extension} file" + error: "Errors" + ignored: "Ignored" + ok: "Success" + lines: + title: "Imported objects" + objects_label: "Objects count" + lines_stats: "Lines" + routes_stats: "Routes" + connection_links_stats: "Connection Links" + time_tables_stats: "Timetables" + stop_areas_stats: "Stop Areas" + access_points_stats: "Access Points" + vehicle_journeys_stats: "Vehicle Journeys" + journey_patterns_stats: "Journey Patterns" + statuses: + pending: "Pending" + completed: "Completed" + failed: "Failed" + compliance_check_task: "Validate Report" + severities: + info: "Information" + uncheck: "Unchecked" + ok: "Ok" + warning: "Warning" + error: "Error" + fatal: "Fatal" + activerecord: + models: + import_task: + zero: "import" + one: "import" + other: "imports" + neptune_import: + zero: "import" + one: "Neptune import" + other: "imports" + csv_import: + zero: "import" + one: "CSV import" + other: "imports" + gtfs_import: + zero: "import" + one: "GTFS import" + other: "imports" + netex_import: + zero: "import" + one: "NeTEx import" + other: "imports" + attributes: + import_task: + resources: "File to import" + created_at: "Created on" + status: "Status" + no_save: "No save" + rule_parameter_set_id: "Rule parameter set for compliance check" + object_id_prefix: "Neptune Id prefix" + max_distance_for_commercial: "Max distance for commercial stop" + max_distance_for_connection_link: "Max distance for connection link" + ignore_last_word: "ignore last word" + ignore_end_chars: "ignore last chars" + tipsy: + hints: + import_task: + max_distance_for_commercial: "Maximal distance to merge homonymous stops in commercial stop in meter" + max_distance_for_connection_link: "Maximal distance to link stops by connection link stop in meter" + ignore_last_word: "ignore last word on stop name in homonymous detection (inappliable when just one word occurs)" + ignore_end_chars: "ignore some chars at the end of stop names in homonymous detection" +fr: + import_tasks: + actions: + new: "Nouvel import" + destroy: "Supprimer cet import" + destroy_confirm: "Etes vous sûr de détruire cet import ?" + new: + title: "Nouvel import" + index: + title: "Imports" + warning: "" + imported_file: "Fichier importé" + show: + report: "Rapport" + not_yet_started: "En file d'attente" + imported_file: "Fichier importé" + completed: "[ Terminé ]" + failed: "[ Echoué ]" + pending: "[ En file d'attente ]" + processing: "[ En progression... ]" + graph: + files: + title_zip: "Résultat d'import des fichiers du zip" + title_default: "Résultat d'import du fichier %{extension}" + error: "Erreurs" + ignored: "Ignorés" + ok: "Succès" + lines: + title: "Volume de données lues par type de donnée" + objects_label: "Quantité lue" + lines_stats: "Lignes" + routes_stats: "Séquences d'arrêts" + connection_links_stats: "Correspondances" + time_tables_stats: "Calendriers" + stop_areas_stats: "Zones d'arrèt" + access_points_stats: "Accès" + vehicle_journeys_stats: "Courses" + journey_patterns_stats: "Missions" + table: + line: + name: "Nom" + save: "Sauvegarde" + routes: "Séquences d'arrêts" + connection_links: "Correspondances" + time_tables: "Calendriers" + stop_areas: "Zones d'arrèt" + access_points: "Accès" + vehicle_journeys: "Courses" + journey_patterns: "Missions" + not_saved: "Non Sauvé" + saved: "Sauvé" + save_error: "Sauvegarde en erreur" + statuses: + pending: "En cours" + completed: "Achevé" + failed: "Echoué" + compliance_check_task: "Validation" + severities: + info: "Information" + uncheck: "Non testé" + ok: "Ok" + warning: "Alerte" + error: "Erreur" + fatal: "Fatal" + activerecord: + models: + import_task: + zero: "import" + one: "import" + other: "imports" + neptune_import: + zero: "import" + one: "import Neptune" + other: "imports" + csv_import: + zero: "import" + one: "import CSV" + other: "imports" + gtfs_import: + zero: "import" + one: "import GTFS" + other: "imports" + netex_import: + zero: "import" + one: "import NeTEx" + other: "imports" + attributes: + import_task: + resources: "Fichier à importer" + created_at: "Créé le" + status: "Status" + no_save: "Pas de sauvegarde" + rule_parameter_set_id: "Jeu de paramètres pour validation" + object_id_prefix: "Préfixe d'identifiants" + max_distance_for_commercial: "Distance max pour créer les zones" + max_distance_for_connection_link: "Distance max pour créer les correspondances" + ignore_last_word: "ignorer le dernier mot" + ignore_end_chars: "ignorer les n derniers caractères" + tipsy: + hints: + import_task: + max_distance_for_commercial: "Distance maximale entre deux arrêts homonymes pour créer les zones d'arrêt (en mètre)" + max_distance_for_connection_link: "Distance maximale entre deux arrêts pour créer les correspondances (en mètre)" + ignore_last_word: "Ignorer le dernier mot pour détecter l'homonymie des noms d'arrêt (inapplicable quand le nom ne comporte qu'un mot)" + ignore_end_chars: "Ignorer les n derniers caractères du nom de l'arrêt pour détecter l'homonymie" diff --git a/config/locales/imports.yml b/config/locales/imports.yml deleted file mode 100644 index d9e51fac4..000000000 --- a/config/locales/imports.yml +++ /dev/null @@ -1,292 +0,0 @@ -en: - imports: - actions: - new: "New import" - destroy: "Destroy" - destroy_confirm: "Are you sure you want destroy this import?" - new: - title: "New import" - index: - title: "Imports" - warning: "" - show: - report: "Report" - not_yet_started: "On queue" - statuses: - pending: "Pending" - completed: "Completed" - failed: "Failed" - import_log_messages: - messages: - started: "Started import" - completed: "Completed import" - failed: "Failed import" - undefined: "%{key} undefined" - IMPORT: "Import on %{0} format" - ZIP_FILE: "ZIP File %{0}" - ZIP_ERROR: "Error %{0}" - ZIP_ENTRY: "ZIP Entry %{0}" - ZIP_MISSING_ENTRY: "Missing ZIP entry %{0}" - FILE: "File %{0}" - FILE_ERROR: "Error %{0}" - FILE_IGNORED: "Unknown file %{0} ignored" - VALIDATION_ERROR: "Wrong grammar : %{0}" - VALIDATION_CAUSE: "%{0}" - IMPORTED_LINE: "Imported Line : %{0}" - LINE_COUNT: "Line count : %{0}" - TIME_TABLE_COUNT: "Timetable count : %{0}" - ROUTE_COUNT: "Route count : %{0}" - JOURNEY_PATTERN_COUNT: "Journey pattern count : %{0}" - VEHICLE_JOURNEY_COUNT: "Vehicle journey count : %{0}" - STOP_AREA_COUNT: "Stop area count : %{0}" - CONNECTION_LINK_COUNT: "Connection link count : %{0}" - ACCES_POINT_COUNT: "Access Point count : %{0}" - MANDATORY_TAG: "Mandatory tag : %{0} " - MANDATORY_DATA: "Mandatory data on line %{0} : %{1}" - IGNORED_DATA: "%{0} line %{1} : invalid field %{2} (%{3}) ignored" - DUPLICATE_ID: "%{0} line %{1} : duplicate id %{2}" - UNKNOWN_ENUM: "Unknown enum vaule for %{0} : %{1} " - EMPTY_TAG: "Empty value : %{0}" - BAD_REFERENCE: "%{0} %{1} missing reference %{2}, id = %{3}" - BAD_REFERENCE_IN_FILE: "%{0} line %{1} missing reference %{2}, id = %{3}" - NETWORK_ANALYSE: "Analysing networks" - COMPANY_ANALYSE: "Analysing networks" - GROUP_OF_LINES_ANALYSE: "Analysing networks" - LINE_ANALYSE: "Analysing lines" - ROUTE_ANALYSE: "Analysing routes" - STOP_ANALYSE: "Analysing stops" - VEHICLE_JOURNEY_ANALYSE: "Analysing vehicle journeys" - TIME_TABLE_ANALYSE: "Analysing timetables" - CONNECTION_LINK_ANALYSE: "Analysing connection links" - EMPTY_LINE: "Empty Line %{0} " - EMPTY_ROUTE: "Empty Route {0} " - EMPTY_JOURNEY_PATTERN: "Empty Journey pattern %{0}" - EMPTY_VEHICLE_JOURNEY: "Empty Vehicle journey %{0} " - EMPTY_TIMETABLE: "Empty Timetable %{0} " - SAVE_OK: "%{0} saved" - SAVE_ERROR: "%{0} save failed : %{1}" - IMPORT_ERROR: "Import Error" - EXCEPTION: "Problem : %{0}" - WRONG_DATA: "Missing arguments to produce log message %{0}" - COUNT_MORE_ITEMS: "%{0} similar problems" - # old Import reports (before 2.0.3) - SAVE: "Save" - CSV_IMPORT: "Import CVS file" - CSV_OK_LINE: "line %{0} imported" - CSV_OK_TIMETABLE: "timetables %{0} (%{1}) imported" - CSV_OK_PTNETWORK: "network %{0} : %{1} imported" - CSV_OK_COMPANY: "company %{0} imported" - CSV_FILE_NOT_FOUND: "file %{0} : error %{1}" - CSV_FILE_IGNORED: "file %{0} ignored (not XML) " - CSV_VALIDATION_ERROR: "XML file don't agree with Neptune XSD : %{0}" - CSV_VALIDATION_CAUSE: "%{0}" - CSV_PARSE_OBJECT: "Analyse %{0}" - CSV_MANDATORY_TAG: "missing or empty mandatory tag : %{0}" - CSV_UNKNOWN_ENUM: "Unknown %{0} enumaration value : %{1}" - CSV_EMPTY_TAG: "empty tag : %{0}" - CSV_TIMETABLE_COUNT: "timetable count : %{0}" - CSV_LINE_COUNT: "line count : %{0}" - CSV_END_OF_FILE: "Unexpected end of file" - CSV_BAD_TIMETABLE_PERIODS: "Bad timetable periods" - CSV_INVALID_LINE: "invalid line : %{0}" - CSV_STOP_WITHOUT_COORDS: "Stop without coords : %{0}" - CSV_VJ_MISSING_TIMETABLE: "Unable to find timetable of vehicle journey : %{0}" - CSV_FILE_FORMAT: "Invalid or deprecated CSV format" - CSV_BAD_ID: "Invalid built Neptune Object ID : %{1} for %{0} " - CSV_UNUSED_TIMETABLE: "Unused timetable %{0} (%{1})" - severities: - info: "Information" - uncheck: "Unchecked" - ok: "Ok" - warning: "Warning" - error: "Error" - fatal: "Fatal" - activerecord: - models: - import: - zero: "import" - one: "import" - other: "imports" - neptune_import: - zero: "import" - one: "Neptune import" - other: "imports" - csv_import: - zero: "import" - one: "CSV import" - other: "imports" - gtfs_import: - zero: "import" - one: "GTFS import" - other: "imports" - netex_import: - zero: "import" - one: "NeTEx import" - other: "imports" - attributes: - import: - resources: "File to import" - created_at: "Created on" - status: "Status" - objectid_prefix: "Neptune Id prefix" - max_distance_for_commercial: "Max distance for commercial stop" - max_distance_for_connection_link: "Max distance for connection link" - ignore_last_word: "ignore last word" - ignore_end_chars: "ignore last chars" - import_log_message: - created_at: "Date" - position: "N." - full_message: "Message" - formtastic: - hints: - import: - max_distance_for_commercial: "Maximal distance to merge homonymous stops in commercial stop in meter" - max_distance_for_connection_link: "Maximal distance to link stops by connection link stop in meter" - ignore_last_word: "ignore last word on stop name in homonymous detection (inappliable when just one word occurs)" - ignore_end_chars: "ignore some chars at the end of stop names in homonymous detection" -fr: - imports: - actions: - new: "Nouvel import" - destroy: "Supprimer cet import" - destroy_confirm: "Etes vous sûr de détruire cet import ?" - new: - title: "Nouvel import" - index: - title: "Imports" - warning: "" - show: - report: "Rapport" - not_yet_started: "En file d'attente" - statuses: - pending: "En cours" - completed: "Achevé" - failed: "Echoué" - import_log_messages: - messages: - started: "Import démarré" - completed: "Import achevé avec succès" - failed: "Import interrompu" - undefined: "%{key} non défini" - IMPORT: "Import au format %{0}" - ZIP_FILE: "Fichier ZIP %{0}" - ZIP_ERROR: "Erreur %{0}" - ZIP_ENTRY: "Entrée de ZIP %{0}" - ZIP_MISSING_ENTRY: "Entrée de ZIP %{0} absente" - FILE: "Fichier %{0}" - FILE_ERROR: "Erreur %{0}" - FILE_IGNORED: "Format non traité %{0}" - VALIDATION_ERROR: "Le fichier ne respecte pas la grammaire : %{0}" - VALIDATION_CAUSE: "%{0}" - IMPORTED_LINE: "Ligne importée %{0}" - LINE_COUNT: "Nombre de lignes extraites : %{0}" - TIME_TABLE_COUNT: "Nombre de calendriers extraits : %{0}" - ROUTE_COUNT: "Nombre de séquences d'arrêts extraites : %{0}" - JOURNEY_PATTERN_COUNT: "Nombre de missions extraites : %{0}" - VEHICLE_JOURNEY_COUNT: "Nombre de courses extraites : %{0}" - STOP_AREA_COUNT: "Nombre d'arrêts extraits : %{0}" - CONNECTION_LINK_COUNT: "Nombre de correspondances extraites : %{0}" - ACCES_POINT_COUNT: "Nombre de points d'accès extraits : %{0}" - MANDATORY_TAG: "Valeur obligatoire absente ou vide : %{0} " - MANDATORY_DATA: "Ligne %{0} : il manque les données %{1}" - IGNORED_DATA: "%{0} ligne %{1} : champ %{2} invalide (%{3}) ignoré" - DUPLICATE_ID: "%{0} ligne %{1} : identifiant en double %{2}" - UNKNOWN_ENUM: "Valeur de l'enum %{0} inconnue : %{1} " - EMPTY_TAG: "Valeur vide : %{0}" - BAD_REFERENCE: "%{0} %{1} Référence %{2} d'identifiant %{3} manquant" - BAD_REFERENCE_IN_FILE: "%{0} ligne %{1} Référence %{2} d'identifiant %{3} manquant" - NETWORK_ANALYSE: "Analyse des réseaux" - COMPANY_ANALYSE: "Analyse des networks" - GROUP_OF_LINES_ANALYSE: "Analyse des networks" - LINE_ANALYSE: "Analyse des lignes" - ROUTE_ANALYSE: "Analyse des séquences d'arrêts" - STOP_ANALYSE: "Analyse des arrêts" - VEHICLE_JOURNEY_ANALYSE: "Analyse des courses" - TIME_TABLE_ANALYSE: "Analyse des calendriers" - CONNECTION_LINK_ANALYSE: "Analyse des correspondances" - EMPTY_LINE: "Ligne %{0} sans séquence d'arrêt" - EMPTY_ROUTE: "Séquence d'arrêts %{0} sans mission ou arrêt" - EMPTY_JOURNEY_PATTERN: "Mission %{0} sans arrêt ou course" - EMPTY_VEHICLE_JOURNEY: "Course %{0} sans horaire" - EMPTY_TIMETABLE: "Calendrier %{0} sans jours ni période" - SAVE_OK: "%{0} enregistré" - SAVE_ERROR: "Echec de l'enregistrement de %{0} : %{1}" - IMPORT_ERROR: "Erreur d'import" - EXCEPTION: "Problème : %{0}" - WRONG_DATA: "Il manque des données pour afficher le message de log %{0}" - COUNT_MORE_ITEMS: "%{0} problèmes similaires" - # old Import reports (before 2.0.3) - SAVE: "Sauvegarde" - CSV_IMPORT: "Import de fichier au format CSV" - CSV_OK_LINE: "Ligne %{0} importée" - CSV_OK_TIMETABLE: "Tableau de marche %{0} (%{1}) importé" - CSV_OK_PTNETWORK: "Réseau %{0} : %{1} importé" - CSV_OK_COMPANY: "Transporteur %{0} importé" - CSV_FILE_ERROR: "Fichier %{0} : erreur %{1}" - CSV_FILE_IGNORED: "Fichier %{0} ignoré (non CSV) " - CSV_VALIDATION_ERROR: "Fichier CSV ne respecte pas le format Chouette : %{0}" - CSV_VALIDATION_CAUSE: "%{0}" - CSV_PARSE_OBJECT: "Analyse %{0}" - CSV_MANDATORY_TAG: "Tag obligatoire absent ou vide : %{0}" - CSV_UNKNOWN_ENUM: "Valeur de l'enum %{0} inconnue : %{1}" - CSV_EMPTY_TAG: "Tag vide : %{0}" - CSV_TIMETABLE_COUNT: "Nombre de tableaux de marche : %{0}" - CSV_LINE_COUNT: "Nombre de lignes : %{0}" - CSV_END_OF_FILE: "Fichier tronqué" - CSV_BAD_TIMETABLE_PERIODS: "Mauvaises périodes dans le tableau de marche" - CSV_INVALID_LINE: "ligne invalide : %{0}" - CSV_STOP_WITHOUT_COORDS: "Arret sans coordonnées : %{0}" - CSV_VJ_MISSING_TIMETABLE: "Impossible de trouver le tableau de marche de la course : %{0}" - CSV_FILE_FORMAT: "Format CSV invalide ou obsolète" - CSV_BAD_ID: "Identifiant Neptune produit invalide : %{1} pour %{0} " - CSV_UNUSED_TIMETABLE: "Tableau de marche %{0} (%{1}) inutilisé" - severities: - info: "Information" - uncheck: "Non testé" - ok: "Ok" - warning: "Alerte" - error: "Erreur" - fatal: "Fatal" - activerecord: - models: - import: - zero: "import" - one: "import" - other: "imports" - neptune_import: - zero: "import" - one: "import Neptune" - other: "imports" - csv_import: - zero: "import" - one: "import CSV" - other: "imports" - gtfs_import: - zero: "import" - one: "import GTFS" - other: "imports" - netex_import: - zero: "import" - one: "import NeTEx" - other: "imports" - attributes: - import: - resources: "Fichier à importer" - created_at: "Créé le" - status: "Status" - objectid_prefix: "Préfixe d'identifiants" - max_distance_for_commercial: "Distance max pour créer les zones" - max_distance_for_connection_link: "Distance max pour créer les correspondances" - ignore_last_word: "ignorer le dernier mot" - ignore_end_chars: "ignorer les n derniers caractères" - import_log_message: - created_at: "Date" - position: "No" - full_message: "Message" - formtastic: - hints: - import: - max_distance_for_commercial: "Distance maximale entre deux arrêts homonymes pour créer les zones d'arrêt (en mètre)" - max_distance_for_connection_link: "Distance maximale entre deux arrêts pour créer les correspondances (en mètre)" - ignore_last_word: "ignorer le dernier mot pour détecter l'homonymie des noms d'arrêt (inapplicable quand le nom ne comporte qu'un mot)" - ignore_end_chars: "ignorer les n derniers caractères du nom de l'arrêt pour détecter l'homonymie" diff --git a/config/locales/layouts.yml b/config/locales/layouts.yml index 6c9165bf2..6efd519c7 100644 --- a/config/locales/layouts.yml +++ b/config/locales/layouts.yml @@ -10,6 +10,17 @@ en: dashboard: "dashboard" creation_tag: title: "Create" + history_tag: + title: "History" + created_at: "Created at" + updated_at: "Updated at" + user_name: "User" + flash_messages: + success: "Success" + error: "Error" + alert: "Alert" + notice: "Info" + fr: layouts: back_to_dashboard: "Retour au Tableau de Bord" @@ -22,3 +33,27 @@ fr: dashboard: "Tableau de bord" creation_tag: title: "Création" + history_tag: + title: "Historique" + created_at: "Créé le" + updated_at: "Mise à jour le" + user_name: "Auteur" + flash_messages: + success: "Succès" + error: "Erreur" + alert: "Alerte" + notice: "Info" + + true: "oui" + false: "non" + or: "ou" + back: "Revenir" + today: "Aujourd'hui" + yesterday: "Hier" + edit_periods: "Editer Périodes" + delete_periods: "Supprimer Périodes" + attributes: + author: "Modifié par" + created_at: "Créé le" + updated_at: "Modifié le" + diff --git a/config/locales/rule_parameter_sets.yml b/config/locales/rule_parameter_sets.yml new file mode 100644 index 000000000..421322f07 --- /dev/null +++ b/config/locales/rule_parameter_sets.yml @@ -0,0 +1,113 @@ +en: + rule_parameter_sets: + actions: + new: "Add a new parameter set" + edit: "Edit this parameter set" + index: "Rule parameter sets" + destroy: "Remove this rule parameter set" + destroy_confirm: "Are you sure you want destroy this rule parameter set ?" + new: + title: "Add a new parameter set" + edit: + title: "Update parameter set %{rule_parameter_set}" + form: + add_mode_parameter_set: "Add mode specific parameter set" + show: + title: "Parameter Set %{rule_parameter_set}" + max_distance: "Maximum distance" + min_distance: "Minimum distance" + walk_speed: "Maximum walk speed for" + inter_stop_area_distance_min: "between 2 stop areas having different parent" + parent_stop_area_distance_max: "between a stop area and its own parent" + inter_access_point_distance_min: "between 2 access having different name for a commun stop area" + inter_connection_link_distance_max: "between stop area departure and stop area arrival in a connection link" + walk_default_speed_max: "a regular traveller" + walk_occasional_traveller_speed_max: "an occasional traveller" + walk_frequent_traveller_speed_max: "a frequent traveller" + walk_mobility_restricted_traveller_speed_max: "for a mobility restricted traveller" + inter_access_link_distance_max: "Access link maximum distance" + inter_stop_duration_max: "Maximum duration between the moment when a vehicle is arriving at a stop and the moment when the vehicle is leaving" + facility_stop_area_distance_max: "between a stop area and a facility" + index: + title: "Parameter sets" + activerecord: + models: + rule_parameter_set: "Parameter Set for Conformity Rules" + attributes: + rule_parameter_set: + name: "Name" + inter_stop_area_distance_min: "Minimum distance between 2 stop areas having different parent" + parent_stop_area_distance_max: "Maximum distance between a stop area and its own parent" + stop_areas_area: "Geographic stop area envelop" + inter_access_point_distance_min: "Minimum distance between 2 access having different name for a commun stop area" + inter_connection_link_distance_max: "Maximum distance between stop area departure and stop area arrival in a connection link" + walk_default_speed_max: "Maximum walk speed for a regular traveller" + walk_occasional_traveller_speed_max: "Maximum walk speed for an occasional traveller" + walk_frequent_traveller_speed_max: "Maximum walk speed for a frequent traveller" + walk_mobility_restricted_traveller_speed_max: "Maximum walk speed for a mobility restricted traveller" + inter_access_link_distance_max: "Access link maximum distance" + inter_stop_duration_max: "Maximum duration for a stopping time" + facility_stop_area_distance_max: "Maximum distance between a stop area and a facility" + inter_stop_area_distance_min: "Maximum distance between a stop areas" + inter_stop_area_distance_max: "Maximum distance between a stop areas" + speed_min: "Minimum speed" + speed_max: "Maximum speed" + inter_stop_duration_variation_max: "Maximum duration gap between 2 vehicle journeys and between 2 folowing stops" + +fr: + rule_parameter_sets: + actions: + new: "Ajouter un jeu de paramètres" + edit: "Modifier ce jeu de paramètres" + index: "Jeux de paramètres" + destroy: "Supprimer ce jeu de paramètres" + destroy_confirm: "Etes vous sûr de détruire ce jeu de paramètres ?" + new: + title: "Ajouter un jeu de paramètres" + form: + add_mode_parameter_set: "Ajouter les paramètres spécifiques à un mode" + edit: + title: "Modifier le jeu de paramètres %{rule_parameter_set}" + show: + title: "Jeu de paramètres %{rule_parameter_set}" + max_distance: "Distance maximum entre : " + min_distance: "Distance minimum entre : " + walk_speed: "Vitesse de marche maximum d'un voyageur : " + inter_stop_area_distance_min: "2 arrêts n'ayant pas le même parent" + parent_stop_area_distance_max: "un arrêt et son parent" + inter_access_point_distance_min: "2 accès de noms différents pour un même arrêt" + inter_connection_link_distance_max: "les arrêts en correspondance" + walk_default_speed_max: "ordinaire" + walk_occasional_traveller_speed_max: "occasionnel" + walk_frequent_traveller_speed_max: "habituel" + walk_mobility_restricted_traveller_speed_max: "à mobilité réduite" + inter_access_link_distance_max: "liaison accès - arrêt" + facility_stop_area_distance_max: "un arrêt et un équipement" + inter_stop_duration_max: "Durée maximum de stationnement à un arrêt" + rule_parameter_by_mode: "Jeu de paramètres pour un mode de transport" + index: + title: "Jeux de paramètres" + activerecord: + models: + rule_parameter_set: "Jeu de paramètres pour le contrôle de qualité des données" + attributes: + rule_parameter_set: + name: "Nom" + inter_stop_area_distance_min: Distance minimum entre 2 arrêts n'ayant pas le même parent + parent_stop_area_distance_max: Distance maximum entre un arrêt et son parent + stop_areas_area: Délimitation géographique des arrêts + inter_access_point_distance_min: Distance minimum entre 2 accès de noms différents pour un même arrêt + inter_connection_link_distance_max: Distance maximum entre les arrêts en correspondance + walk_default_speed_max: Vitesse de marche maximum pour un voyageur ordinaire + walk_occasional_traveller_speed_max: Vitesse de marche maximum pour un voyageur occasionnel + walk_frequent_traveller_speed_max: Vitesse de marche maximum pour un voyageur habituel + walk_mobility_restricted_traveller_speed_max: Vitesse de marche maximum pour un voyageur à mobilité réduite + inter_access_link_distance_max: Distance maximum d'un liaison accès - arrêt + inter_stop_duration_max: Durée maximum entre les horaires d'arrivée et de départ à un arrêt + facility_stop_area_distance_max: Distance maximum entre un arrêt et un équipement + inter_stop_area_distance_min: Distance minimum entre 2 arrêts + inter_stop_area_distance_max: Distance maximum entre 2 arrêts + speed_min: Vitesse minimum + speed_max: Vitesse maximum + inter_stop_duration_variation_max: Ecart maximum de durée de trajet entre 2 arrêts successifs pour les différentes courses + diff --git a/config/locales/transport_modes.yml b/config/locales/transport_modes.yml index 3c89e4524..9ed0745f7 100644 --- a/config/locales/transport_modes.yml +++ b/config/locales/transport_modes.yml @@ -15,13 +15,13 @@ en: waterborne: "Waterborne" private_vehicle: "Private vehicle" walk: "Walk" - trolley_bus: "Trolleybus" + trolleybus: "Trolleybus" bicycle: "Bicycle" shuttle: "Shuttle" taxi: "Taxi" val: "VAL" other: "Other" - + fr: transport_modes: label: @@ -29,8 +29,8 @@ fr: air: "Air" train: "Train" long_distance_train: "Train Grande Ligne" - local_train: "TER" - rapid_transit: "RER" + local_train: "TER" + rapid_transit: "RER" metro: "Métro" tramway: "Tramway" coach: "Autocar" @@ -39,7 +39,7 @@ fr: waterborne: "Bac" private_vehicle: "Voiture particulière" walk: "Marche à pied" - trolley_bus: "Trolleybus" + trolleybus: "Trolleybus" bicycle: "Vélo" shuttle: "Navette" taxi: "Taxi" diff --git a/config/routes.rb b/config/routes.rb index 238217099..a0e91cf7f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -28,7 +28,7 @@ ChouetteIhm::Application.routes.draw do resources :vehicle_journeys, :only => :show end end - + resource :subscription @@ -36,10 +36,9 @@ ChouetteIhm::Application.routes.draw do resources :users end - resources :file_validations - resources :referentials do resources :api_keys + resources :rule_parameter_sets resources :stop_point_areas match 'lines' => 'lines#destroy_all', :via => :delete resources :group_of_lines do @@ -55,7 +54,7 @@ ChouetteIhm::Application.routes.draw do get 'add_routing_lines' get 'add_routing_stops' end - end + end resources :lines collection do get :name_filter @@ -81,7 +80,7 @@ ChouetteIhm::Application.routes.draw do get 'add_routing_lines' get 'add_routing_stops' end - end + end resources :routes do resources :journey_patterns do member do @@ -101,15 +100,30 @@ ChouetteIhm::Application.routes.draw do end end - resources :imports + resources :import_tasks do + member do + get 'file_to_import' + end + end + resources :exports do collection do get 'references' end end + resources :compliance_check_tasks do + member do + get 'rule_parameter_set' + end + collection do + get 'references' + end + + resources :compliance_check_results + end resources :companies - + resources :time_tables do collection do get :comment_filter @@ -123,7 +137,7 @@ ChouetteIhm::Application.routes.draw do end resources :stop_areas do - resources :access_points + resources :access_points resources :stop_area_parents resources :stop_area_children resources :stop_area_routing_lines @@ -135,13 +149,13 @@ ChouetteIhm::Application.routes.draw do get 'add_routing_stops' get 'access_links' end - collection do + collection do put 'default_geometry' end end resources :connection_links do - resources :connection_link_areas + resources :connection_link_areas member do get 'select_areas' end @@ -157,12 +171,12 @@ ChouetteIhm::Application.routes.draw do get 'add_routing_lines' get 'add_routing_stops' end - end + end end resources :clean_ups - - end + + end match '/help/(*slug)' => 'help#show' match '/test_sheet/(*slug)' => 'test_sheet#show' diff --git a/db/migrate/20120531070108_add_type_and_options_to_import.rb b/db/migrate/20120531070108_add_type_and_options_to_import.rb index 490427c8a..0488fb6d4 100644 --- a/db/migrate/20120531070108_add_type_and_options_to_import.rb +++ b/db/migrate/20120531070108_add_type_and_options_to_import.rb @@ -3,6 +3,6 @@ class AddTypeAndOptionsToImport < ActiveRecord::Migration change_table :imports do |t| t.string :type, :options end - Import.update_all :type => "NeptuneImport" + # Import.update_all :type => "NeptuneImport" end end diff --git a/db/migrate/20120612071936_add_file_type_to_import.rb b/db/migrate/20120612071936_add_file_type_to_import.rb index fccd91cce..8eacab40d 100644 --- a/db/migrate/20120612071936_add_file_type_to_import.rb +++ b/db/migrate/20120612071936_add_file_type_to_import.rb @@ -3,6 +3,6 @@ class AddFileTypeToImport < ActiveRecord::Migration change_table :imports do |t| t.string :file_type end - Import.update_all :file_type => "zip" + #Import.update_all :file_type => "zip" end end diff --git a/db/migrate/20120905125251_add_organisation_id_to_file_validation.rb b/db/migrate/20120905125251_add_organisation_id_to_file_validation.rb index 996bf8dba..79929414f 100644 --- a/db/migrate/20120905125251_add_organisation_id_to_file_validation.rb +++ b/db/migrate/20120905125251_add_organisation_id_to_file_validation.rb @@ -4,9 +4,9 @@ class AddOrganisationIdToFileValidation < ActiveRecord::Migration f.belongs_to :organisation end - FileValidation.reset_column_information - organisation = Organisation.find_or_create_by_name!("Chouette") - FileValidation.update_all :organisation_id => organisation.id + #FileValidation.reset_column_information + #organisation = Organisation.find_or_create_by_name!("Chouette") + #FileValidation.update_all :organisation_id => organisation.id end end diff --git a/db/migrate/20131028153043_add_bounds_to_referentials.rb b/db/migrate/20131028153043_add_bounds_to_referentials.rb new file mode 100644 index 000000000..013852e3f --- /dev/null +++ b/db/migrate/20131028153043_add_bounds_to_referentials.rb @@ -0,0 +1,7 @@ +class AddBoundsToReferentials < ActiveRecord::Migration + def change + change_table :referentials do |t| + t.text :geographical_bounds + end + end +end diff --git a/db/migrate/20131029092608_drop_import_log_messages.rb b/db/migrate/20131029092608_drop_import_log_messages.rb new file mode 100644 index 000000000..98b17a42e --- /dev/null +++ b/db/migrate/20131029092608_drop_import_log_messages.rb @@ -0,0 +1,24 @@ +class DropImportLogMessages < ActiveRecord::Migration + def up + if table_exists? :import_log_messages + execute "DROP TABLE import_log_messages" # fix Foreigner bug < 1.5.0 + # drop_table :import_log_messages + end + end + + def down + unless table_exists? :import_log_messages + create_table :import_log_messages do |t| + t.belongs_to :import + t.string :key + t.string :arguments,:limit => 1000 + t.integer :position + t.string :severity + t.timestamps + end + add_index :import_log_messages, :import_id + end + end + + +end diff --git a/db/migrate/20131029105107_drop_imports.rb b/db/migrate/20131029105107_drop_imports.rb new file mode 100644 index 000000000..12677fa1f --- /dev/null +++ b/db/migrate/20131029105107_drop_imports.rb @@ -0,0 +1,23 @@ +class DropImports < ActiveRecord::Migration + def up + if table_exists? :imports + execute "DROP TABLE imports" # fix Foreigner bug < 1.5.0 + # drop_table :imports + end + end + + def down + unless table_exists? :imports + create_table :imports do |t| + t.belongs_to :referential + t.string :status + t.string :type + t.string :options + t.string :file_type + t.timestamps + end + add_index :imports, :referential_id + end + end + +end diff --git a/db/migrate/20131029110239_create_import_tasks.rb b/db/migrate/20131029110239_create_import_tasks.rb new file mode 100644 index 000000000..fa2faec37 --- /dev/null +++ b/db/migrate/20131029110239_create_import_tasks.rb @@ -0,0 +1,27 @@ +class CreateImportTasks < ActiveRecord::Migration + def up + unless table_exists? :import_tasks + create_table :import_tasks do |t| + t.belongs_to :referential ,:limit => 8 + t.string :status # pending processing completed failed + t.string :format # NEPTUNE, CSV, NETEX, GTFS + t.boolean :no_save # processing no save on database (exclude level 3 conformity testing) + t.text :parameter_set # all parameters needed to execute the import operation + t.integer :user_id ,:limit => 8 # id to the user who has requested this task (may be nil) + t.string :user_name # name of the user who has requested this task + t.string :file_path # saved file + 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 + end + end + + def down + if table_exists? :import_tasks + execute "drop table import_tasks" + # drop_table :import_tasks + end + end +end diff --git a/db/migrate/20131029115751_create_compliance_check_tasks.rb b/db/migrate/20131029115751_create_compliance_check_tasks.rb new file mode 100644 index 000000000..9195556b2 --- /dev/null +++ b/db/migrate/20131029115751_create_compliance_check_tasks.rb @@ -0,0 +1,26 @@ +class CreateComplianceCheckTasks < ActiveRecord::Migration + def up + unless table_exists? :compliance_check_tasks + create_table :compliance_check_tasks do |t| + t.belongs_to :referential, :null => :no ,:limit => 8 + t.belongs_to :import_task ,:limit => 8 # optional + t.string :status # global status of conformity checking + t.string :parameter_set_name # name of parameter set used for testing + t.text :parameter_set # all parameters needed to execute the import operation + t.integer :user_id ,:limit => 8 # id to the user who has requested this task (may be nil) + 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 + end + end + + def down + if table_exists? :compliance_check_tasks + execute "drop table compliance_check_tasks" + # drop_table :compliance_check_tasks + end + end +end diff --git a/db/migrate/20131029115820_create_compliance_check_results.rb b/db/migrate/20131029115820_create_compliance_check_results.rb new file mode 100644 index 000000000..8b72aa4c0 --- /dev/null +++ b/db/migrate/20131029115820_create_compliance_check_results.rb @@ -0,0 +1,23 @@ +class CreateComplianceCheckResults < ActiveRecord::Migration + def up + unless table_exists? :compliance_check_results + create_table :compliance_check_results do |t| + t.belongs_to :compliance_check_task , :null => :no ,:limit => 8 + t.string :rule_code # rule code value + t.string :severity # warning, error, improvement + t.string :status # NA, OK, NOK + 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 + end + end + + def down + if table_exists? :compliance_check_results + execute "drop table compliance_check_results" + # drop_table :compliance_check_results + end + end +end diff --git a/db/migrate/20131104110509_create_rule_parameter_sets.rb b/db/migrate/20131104110509_create_rule_parameter_sets.rb new file mode 100644 index 000000000..b2ceb0dbb --- /dev/null +++ b/db/migrate/20131104110509_create_rule_parameter_sets.rb @@ -0,0 +1,19 @@ +class CreateRuleParameterSets < ActiveRecord::Migration + def up + unless table_exists? :rule_parameter_sets + create_table :rule_parameter_sets do |a| + a.belongs_to :referential ,:limit => 8 + a.text :parameters + a.string :name + a.timestamps + end + end + end + + def down + if table_exists? :rule_parameter_sets + execute "drop table rule_parameter_sets" + # drop_table :rule_parameter_sets + end + end +end diff --git a/db/migrate/20131105063323_create_transport_mode_parameter_sets.rb b/db/migrate/20131105063323_create_transport_mode_parameter_sets.rb new file mode 100644 index 000000000..307a7f4db --- /dev/null +++ b/db/migrate/20131105063323_create_transport_mode_parameter_sets.rb @@ -0,0 +1,20 @@ +class CreateTransportModeParameterSets < ActiveRecord::Migration + def up + unless table_exists? :transport_mode_parameter_sets + create_table :transport_mode_parameter_sets do |a| + a.belongs_to :rule_parameter_set ,:limit => 8 + a.string :transport_mode + a.text :parameters + a.timestamps + end + end + end + + def down + if table_exists? :transport_mode_parameter_sets + execute "drop table transport_mode_parameter_sets" + # drop_table :transport_mode_parameter_sets + end + + end +end diff --git a/db/migrate/20131220083200_drop_file_validation.rb b/db/migrate/20131220083200_drop_file_validation.rb new file mode 100644 index 000000000..ff774310c --- /dev/null +++ b/db/migrate/20131220083200_drop_file_validation.rb @@ -0,0 +1,14 @@ +class DropFileValidation < ActiveRecord::Migration + def change + if table_exists? :file_validation_log_messages + execute "drop table file_validation_log_messages" + # drop_table :file_validation_log_messages + end + + if table_exists? :file_validations + execute "drop table file_validations" + # drop_table :file_validations + end + + end +end diff --git a/db/migrate/20131220215103_add_reference_to_compliance_check_task.rb b/db/migrate/20131220215103_add_reference_to_compliance_check_task.rb new file mode 100644 index 000000000..225c1a974 --- /dev/null +++ b/db/migrate/20131220215103_add_reference_to_compliance_check_task.rb @@ -0,0 +1,7 @@ +class AddReferenceToComplianceCheckTask < ActiveRecord::Migration + def change + change_table :compliance_check_tasks do |t| + t.string :references_type, :reference_ids + end + end +end diff --git a/db/migrate/20140106084920_add_rule_code_parts_to_compilance_check_results.rb b/db/migrate/20140106084920_add_rule_code_parts_to_compilance_check_results.rb new file mode 100644 index 000000000..f494a0428 --- /dev/null +++ b/db/migrate/20140106084920_add_rule_code_parts_to_compilance_check_results.rb @@ -0,0 +1,8 @@ +class AddRuleCodePartsToCompilanceCheckResults < ActiveRecord::Migration + def change + change_table :compliance_check_results do |t| + t.string :rule_target, :rule_format + t.integer :rule_level, :rule_number + end + end +end diff --git a/db/migrate/20140107084816_insert_rule_parameter_sets.rb b/db/migrate/20140107084816_insert_rule_parameter_sets.rb new file mode 100644 index 000000000..fd951c765 --- /dev/null +++ b/db/migrate/20140107084816_insert_rule_parameter_sets.rb @@ -0,0 +1,10 @@ +class InsertRuleParameterSets < ActiveRecord::Migration + def up + Referential.all.each do |referential| + RuleParameterSet.default_for_all_modes( referential).save if referential.rule_parameter_sets.empty? + end + end + + def down + end +end diff --git a/db/migrate/20140110090743_add_user_id_name_to_referential.rb b/db/migrate/20140110090743_add_user_id_name_to_referential.rb new file mode 100644 index 000000000..127ba5937 --- /dev/null +++ b/db/migrate/20140110090743_add_user_id_name_to_referential.rb @@ -0,0 +1,6 @@ +class AddUserIdNameToReferential < ActiveRecord::Migration + def change + add_column :referentials, :user_id, :integer, :limit => 8 + add_column :referentials, :user_name, :string + end +end diff --git a/db/migrate/20140113094406_move_options_to_parameter_set_import_task.rb b/db/migrate/20140113094406_move_options_to_parameter_set_import_task.rb new file mode 100644 index 000000000..cb12aa3c4 --- /dev/null +++ b/db/migrate/20140113094406_move_options_to_parameter_set_import_task.rb @@ -0,0 +1,19 @@ +class MoveOptionsToParameterSetImportTask < ActiveRecord::Migration + def up + ImportTask.all.each do |import| + import.parameter_set.tap do |parameter_set| + parameter_set = {} if parameter_set.nil? + import.resources = "dummy" + import.update_attribute :format, "Neptune" + import.update_attribute :no_save, false + result = import.update_attribute( :parameter_set, { :no_save => import.attributes[ "no_save"], + :file_path => import.attributes[ "file_path"], + :format => import.attributes[ "format"]}.merge( parameter_set)) + raise Exception.new("Echec id=#{import.id}, import.valid? #{import.valid?}, import.erros #{import.errors.inspect}") unless result + end + end + end + + def down + end +end diff --git a/db/migrate/20140113103544_remove_format_no_save_file_path_from_import_task.rb b/db/migrate/20140113103544_remove_format_no_save_file_path_from_import_task.rb new file mode 100644 index 000000000..f1548e5b4 --- /dev/null +++ b/db/migrate/20140113103544_remove_format_no_save_file_path_from_import_task.rb @@ -0,0 +1,13 @@ +class RemoveFormatNoSaveFilePathFromImportTask < ActiveRecord::Migration + def up + remove_column :import_tasks, :no_save + remove_column :import_tasks, :file_path + remove_column :import_tasks, :format + end + + def down + add_column :import_tasks, :no_save, :boolean + add_column :import_tasks, :file_path, :datatype + add_column :import_tasks, :format, :datatype + end +end diff --git a/db/schema.rb b/db/schema.rb index f6e27009d..f6203e6d7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,3 +1,4 @@ +# encoding: UTF-8 # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. @@ -10,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130710123351) do +ActiveRecord::Schema.define(:version => 20140113103544) do create_table "access_links", :force => true do |t| t.integer "access_point_id", :limit => 8 @@ -87,6 +88,36 @@ ActiveRecord::Schema.define(:version => 20130710123351) do add_index "companies", ["objectid"], :name => "companies_objectid_key", :unique => true add_index "companies", ["registration_number"], :name => "companies_registration_number_key", :unique => true + create_table "compliance_check_results", :force => true do |t| + t.integer "compliance_check_task_id", :limit => 8 + t.string "rule_code" + t.string "severity" + t.string "status" + t.integer "violation_count" + t.text "detail" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "rule_target" + t.string "rule_format" + t.integer "rule_level" + t.integer "rule_number" + end + + create_table "compliance_check_tasks", :force => true do |t| + t.integer "referential_id", :limit => 8 + t.integer "import_task_id", :limit => 8 + t.string "status" + t.string "parameter_set_name" + t.text "parameter_set" + t.integer "user_id", :limit => 8 + t.string "user_name" + t.text "progress_info" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "references_type" + t.string "reference_ids" + end + create_table "connection_links", :force => true do |t| t.integer "departure_id", :limit => 8 t.integer "arrival_id", :limit => 8 @@ -182,28 +213,6 @@ ActiveRecord::Schema.define(:version => 20130710123351) do t.integer "choice_code" end - create_table "file_validation_log_messages", :force => true do |t| - t.integer "file_validation_id", :limit => 8 - t.string "key" - t.string "arguments", :limit => 1000 - t.integer "position" - t.string "severity" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "file_validation_log_messages", ["file_validation_id"], :name => "index_file_validation_log_messages_on_file_validation_id" - - create_table "file_validations", :force => true do |t| - t.string "status" - t.string "options", :limit => 2000 - t.string "file_name" - t.string "file_type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "organisation_id", :limit => 8 - end - create_table "group_of_lines", :force => true do |t| t.string "objectid", :null => false t.integer "object_version" @@ -220,30 +229,18 @@ ActiveRecord::Schema.define(:version => 20130710123351) do t.integer "line_id", :limit => 8 end - create_table "import_log_messages", :force => true do |t| - t.integer "import_id", :limit => 8 - t.string "key" - t.string "arguments", :limit => 1000 - t.integer "position" - t.string "severity" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "import_log_messages", ["import_id"], :name => "index_import_log_messages_on_import_id" - - create_table "imports", :force => true do |t| + create_table "import_tasks", :force => true do |t| t.integer "referential_id", :limit => 8 t.string "status" + t.text "parameter_set" + t.integer "user_id", :limit => 8 + t.string "user_name" + t.text "result" + t.text "progress_info" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false - t.string "type" - t.string "options" - t.string "file_type" end - add_index "imports", ["referential_id"], :name => "index_imports_on_referential_id" - create_table "journey_patterns", :force => true do |t| t.integer "route_id", :limit => 8 t.string "objectid", :null => false @@ -329,13 +326,16 @@ ActiveRecord::Schema.define(:version => 20130710123351) do create_table "referentials", :force => true do |t| t.string "name" t.string "slug" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.string "prefix" t.string "projection_type" t.string "time_zone" t.string "bounds" - t.integer "organisation_id", :limit => 8 + t.integer "organisation_id", :limit => 8 + t.text "geographical_bounds" + t.integer "user_id", :limit => 8 + t.string "user_name" end create_table "routes", :force => true do |t| @@ -360,6 +360,14 @@ ActiveRecord::Schema.define(:version => 20130710123351) do t.integer "line_id", :limit => 8 end + create_table "rule_parameter_sets", :force => true do |t| + t.integer "referential_id", :limit => 8 + t.text "parameters" + t.string "name" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "stop_areas", :force => true do |t| t.integer "parent_id", :limit => 8 t.string "objectid", :null => false @@ -456,6 +464,14 @@ ActiveRecord::Schema.define(:version => 20130710123351) do 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" + create_table "transport_mode_parameter_sets", :force => true do |t| + t.integer "rule_parameter_set_id", :limit => 8 + t.string "transport_mode" + t.text "parameters" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "users", :force => true do |t| t.string "email", :default => "", :null => false t.string "encrypted_password", :default => "" @@ -532,12 +548,19 @@ ActiveRecord::Schema.define(:version => 20130710123351) do add_foreign_key "access_points", "stop_areas", :name => "access_area_fkey", :dependent => :delete + add_foreign_key "compliance_check_results", "compliance_check_tasks", :name => "compliance_check_results_compliance_check_task_id_fk", :dependent => :delete + + add_foreign_key "compliance_check_tasks", "import_tasks", :name => "compliance_check_tasks_import_task_id_fk", :dependent => :delete + add_foreign_key "compliance_check_tasks", "referentials", :name => "compliance_check_tasks_referential_id_fk", :dependent => :delete + add_foreign_key "connection_links", "stop_areas", :name => "colk_endarea_fkey", :column => "arrival_id", :dependent => :delete add_foreign_key "connection_links", "stop_areas", :name => "colk_startarea_fkey", :column => "departure_id", :dependent => :delete add_foreign_key "group_of_lines_lines", "group_of_lines", :name => "groupofline_group_fkey", :dependent => :delete add_foreign_key "group_of_lines_lines", "lines", :name => "groupofline_line_fkey", :dependent => :delete + add_foreign_key "import_tasks", "referentials", :name => "import_tasks_referential_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 diff --git a/lib/tasks/demo.rake b/lib/tasks/demo.rake index 7d964b894..da9f6c024 100644 --- a/lib/tasks/demo.rake +++ b/lib/tasks/demo.rake @@ -14,7 +14,7 @@ namespace :demo do referential = organisation.referentials.create( :name => "Tatrobus", :slug => "tatrobus", :prefix => "TAT") resource = Rack::Test::UploadedFile.new( Rails.application.config.demo_data, 'application/zip', false) - import_instance = referential.imports.create( :resources => resource, :referential_id => referential.id) + import_instance = referential.import_tasks.create( :resources => resource, :referential_id => referential.id) import_instance.save_resources import_instance.import puts "Restore demo environment complete" diff --git a/spec/controllers/exports_controller_spec.rb b/spec/controllers/exports_controller_spec.rb index e7a49a8e8..fd7b182d7 100644 --- a/spec/controllers/exports_controller_spec.rb +++ b/spec/controllers/exports_controller_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe ImportsController do +describe ExportsController do login_user describe "GET 'new'" do diff --git a/spec/controllers/import_tasks_controller_spec.rb b/spec/controllers/import_tasks_controller_spec.rb new file mode 100644 index 000000000..d9b8b7660 --- /dev/null +++ b/spec/controllers/import_tasks_controller_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe ImportTasksController do + login_user + shared_examples_for "referential dependant" do + it "assigns referential as @referential" do + assigns[:referential].should == referential + end + end + + describe "GET /new" do + before(:each) do + get :new, + :referential_id => referential.id + end + it_behaves_like "referential dependant" + it "should assign import_task with NeptuneImport instance" do + assigns[:import_task].class.should == NeptuneImport + end + it "should assign import_task with Neptune format" do + assigns[:import_task].format.should == ImportTask.new.format + end + it "should assign import_task with refrential.id" do + assigns[:import_task].referential_id.should == referential.id + end + it "should assign import_task with logged in user id" do + assigns[:import_task].user_id.should == referential.organisation.users.first.id + end + it "should assign import_task with logged in user name" do + assigns[:import_task].user_name.should == referential.organisation.users.first.name + end + end + +end diff --git a/spec/controllers/imports_controller_spec.rb b/spec/controllers/imports_controller_spec.rb deleted file mode 100644 index 8e2582a99..000000000 --- a/spec/controllers/imports_controller_spec.rb +++ /dev/null @@ -1,41 +0,0 @@ -require 'spec_helper' - -describe ImportsController do - login_user - - describe "GET 'new'" do - it "returns http success" do - pending - get 'new' - response.should be_success - end - end - - describe "POST 'create'" do - before(:each) do - post :create, - :referential_id => referential.id, - :import => { :resources => Rack::Test::UploadedFile.new( "spec/fixtures/neptune.zip", 'application/zip', false)} - end - - it "assigns import.referential as @referential" do - assigns[:import].referential.should == referential - end - - it "assigns referential as @referential" do - assigns[:referential].should == referential - end - it "shoud redirect to imports" do - response.should redirect_to referential_imports_path(referential) - end - end - - describe "GET 'index'" do - it "returns http success" do - pending - get 'index' - response.should be_success - end - end - -end diff --git a/spec/controllers/rule_parameter_sets_controller_spec.rb b/spec/controllers/rule_parameter_sets_controller_spec.rb new file mode 100644 index 000000000..99a522581 --- /dev/null +++ b/spec/controllers/rule_parameter_sets_controller_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe RuleParameterSetsController do + login_user + let(:mode){"air"} + + shared_examples_for "referential dependant" do + it "assigns referential as @referential" do + assigns[:referential].should == referential + end + end + + describe "GET /index" do + before(:each) do + get :index, + :referential_id => referential.id + end + it_behaves_like "referential dependant" + end + + describe "GET /new" do + before(:each) do + get :new, + :referential_id => referential.id + end + it_behaves_like "referential dependant" + it "should assign rule_parameter_set with default params" do + RuleParameterSet.default_params.each do |k,v| + assigns[:rule_parameter_set].send( k ).should == v + end + assigns[:rule_parameter_set].referential_id.should == referential.id + end + end +end diff --git a/spec/factories.rb b/spec/factories.rb index 681400443..205f020bb 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -13,6 +13,14 @@ FactoryGirl.define do f.time_zone "Europe/Paris" end + factory :rule_parameter_set do |f| + f.sequence(:name) { |n| "Test #{n}" } + f.association :referential + f.after_create do |rsp| + rsp.parameters = RuleParameterSet.default_for_all_modes( rsp.referential).parameters + end + end + factory :user do |f| f.association :organisation f.sequence(:name) { |n| "chouette#{n}" } @@ -21,16 +29,15 @@ FactoryGirl.define do f.password_confirmation "secret" end - factory :import do |f| + factory :import_task do |f| + f.user_name "dummy" + f.user_id 123 + f.no_save false + f.format "Neptune" f.resources { Rack::Test::UploadedFile.new 'spec/fixtures/neptune.zip', 'application/zip', false } f.referential { Referential.find_by_slug("first") } end - factory :import_log_message do |f| - f.association :import - f.sequence(:key) { "key_#{n}" } - end - factory :kml_export do |f| f.referential { Referential.find_by_slug("first") } end @@ -49,9 +56,18 @@ FactoryGirl.define do f.duration 1 end - factory :file_validation do |f| - f.resources { Rack::Test::UploadedFile.new 'spec/fixtures/neptune.zip', 'application/zip', false } - f.association :organisation + factory :compliance_check_result do |f| + f.association :compliance_check_task + f.rule_code "2-NEPTUNE-StopArea-6" + f.severity "warning" + f.status "nok" + end + + factory :compliance_check_task do |f| + f.user_id 1 + f.user_name "Dummy" + f.status "pending" + f.referential { Referential.find_by_slug("first") } end factory :file_validation_log_message do |f| diff --git a/spec/models/compliance_check_result_spec.rb b/spec/models/compliance_check_result_spec.rb new file mode 100644 index 000000000..4d73d8ad3 --- /dev/null +++ b/spec/models/compliance_check_result_spec.rb @@ -0,0 +1,68 @@ +require 'spec_helper' + +describe ComplianceCheckResult do + + subject { Factory( :compliance_check_result)} + + describe "#indice" do + context "when 1-NEPTUNE-XML-1 result" do + before(:each) do + subject.rule_code = "1-NEPTUNE-XML-1" + end + its(:indice) { should == 1 } + end + context "when 2-NETEX-AccessLink-2 result" do + before(:each) do + subject.rule_code = "2-NETEX-AccessLink-2" + end + its(:indice) { should == 2 } + end + end + + describe "#data_type" do + context "when 1-NEPTUNE-XML-1 result" do + before(:each) do + subject.rule_code = "1-NEPTUNE-XML-1" + end + its(:data_type) { should == "XML" } + end + context "when 2-NETEX-AccessLink-2 result" do + before(:each) do + subject.rule_code = "2-NETEX-AccessLink-2" + end + its(:data_type) { should == "AccessLink" } + end + end + + describe "#format" do + context "when 1-NEPTUNE-XML-1 result" do + before(:each) do + subject.rule_code = "1-NEPTUNE-XML-1" + end + its(:format) { should == "NEPTUNE" } + end + context "when 2-NETEX-AccessLink-2 result" do + before(:each) do + subject.rule_code = "2-NETEX-AccessLink-2" + end + its(:format) { should == "NETEX" } + end + end + + describe "#level" do + context "when 1-NEPTUNE-XML-1 result" do + before(:each) do + subject.rule_code = "1-NEPTUNE-XML-1" + end + its(:level) { should == 1 } + end + context "when 2-NEPTUNE-AccessLink-2 result" do + before(:each) do + subject.rule_code = "2-NEPTUNE-AccessLink-2" + end + its(:level) { should == 2 } + end + end + +end + diff --git a/spec/models/compliance_check_task_spec.rb b/spec/models/compliance_check_task_spec.rb new file mode 100644 index 000000000..e06554fe4 --- /dev/null +++ b/spec/models/compliance_check_task_spec.rb @@ -0,0 +1,283 @@ +require 'spec_helper' + +describe ComplianceCheckTask do + + subject { Factory( :compliance_check_task ) } + + RSpec::Matchers.define :be_log_message do |expected| + match do |actual| + actual and expected.all? { |k,v| actual[k.to_s] == v } + end + end + + describe "#destroy" do + let(:import_task){ Factory( :import_task )} + context "with an import_task" do + before(:each) do + subject.import_task = import_task + end + it "should destroy import_task" do + subject.destroy + ImportTask.exists?( import_task.id).should be_false + end + end + context "without any import_task" do + before(:each) do + subject.import_task = nil + end + it "should not raise exception" do + subject.destroy + subject.should be_destroyed + end + end + end + + describe "#levels" do + let(:import_task){ Factory( :import_task )} + context "when validation is without import" do + it "should not return levels 1 and 2" do + subject.levels.include?(1).should be_false + subject.levels.include?(2).should be_false + end + context "when parameter_set is defined" do + before(:each) do + subject.parameter_set = "dummy" + end + it "should return level 3" do + subject.levels.include?(3).should be_true + end + end + context "when parameter_set is not defined" do + before(:each) do + subject.parameter_set = nil + end + it "should not return level 3" do + subject.levels.include?(3).should_not be_true + end + end + end + context "when validation is done with an import" do + before(:each) do + subject.import_task = import_task + end + it "should return levels 1 and 2" do + subject.levels.include?(1).should be_true + subject.levels.include?(2).should be_true + end + context "when parameter_set is defined" do + before(:each) do + subject.parameter_set = "dummy" + end + it "should return level 3" do + subject.levels.include?(3).should be_true + end + end + context "when parameter_set is not defined" do + before(:each) do + subject.parameter_set = nil + end + it "should not return level 3" do + subject.levels.include?(3).should_not be_true + end + end + end + + end + + describe "#chouette_command" do + it "should be a Chouette::Command instance" do + subject.send( :chouette_command).class.should == Chouette::Command + end + it "should have schema same as referential.slug" do + subject.send( :chouette_command).schema.should == subject.referential.slug + end + end + + describe "#validate" do + let(:compliance_check_task){ Factory(:compliance_check_task) } + let(:chouette_command) { "dummy" } + context "for failing validation" do + before(:each) do + chouette_command.stub!( :run!).and_raise( "dummy") + compliance_check_task.stub!( :chouette_command => chouette_command) + end + it "should have status 'failed'" do + compliance_check_task.validate + compliance_check_task.status.should == "failed" + end + end + context "for successful validation" do + before(:each) do + compliance_check_task.stub!( :chouette_command => mock( :run! => true )) + end + it "should have status 'completed'" do + compliance_check_task.validate + compliance_check_task.status.should == "completed" + end + end + end + + describe "#validate" do + let(:compliance_check_task){ Factory(:compliance_check_task) } + let(:command_args){ "dummy" } + before(:each) do + compliance_check_task.stub!( :chouette_command => mock( :run! => true )) + compliance_check_task.stub!( :chouette_command_args => command_args) + end + it "should call chouette_command.run! with :c => 'import', :id => id" do + compliance_check_task.send( :chouette_command).should_receive( :run! ).with( command_args) + compliance_check_task.validate + end + end + + describe "#delayed_validate" do + let( :import_task){ Factory.build(:import_task) } + before(:each) do + subject.stub!( :delay => mock( :validate => true)) + end + it "should not call delay#validate if import_task defined" do + subject.import_task = import_task + subject.delay.should_not_receive( :validate) + subject.delayed_validate + end + it "should call delay#validate if import_task blank" do + subject.import_task = nil + subject.delay.should_receive( :validate) + subject.delayed_validate + end + + end + + describe "#define_default_attributes" do + it "should keep status if defined" do + subject.status = "dummy" + subject.define_default_attributes + subject.status.should == "dummy" + end + it "should set status to pending if not defined" do + subject.status = nil + subject.define_default_attributes + subject.status.should == "pending" + end + context "when rule_parameter_set is nil" do + before(:each) do + subject.stub!( :rule_parameter_set => nil) + subject.parameter_set = "dummy" + subject.parameter_set_name = "dummy" + end + it "should keep parameter_set_name" do + subject.define_default_attributes + subject.parameter_set_name.should == "dummy" + end + it "should keep parameter_set" do + subject.define_default_attributes + subject.parameter_set.should == "dummy" + end + end + context "when rule_parameter_set is defined" do + let( :rule_parameter_set ){ Factory( :rule_parameter_set ) } + before(:each) do + subject.stub!( :rule_parameter_set => rule_parameter_set) + subject.parameter_set = "dummy" + subject.parameter_set_name = "dummy" + end + it "should set parameter_set_name to rule_parameter_set.name" do + subject.define_default_attributes + subject.parameter_set_name.should == rule_parameter_set.name + end + it "should keep set parameter_set to rule_parameter_set.parameters" do + subject.define_default_attributes + subject.parameter_set.should == rule_parameter_set.parameters + end + end + end + + describe "#rule_parameter_set" do + context "when rule_parameter_set_id is blank" do + before(:each) do + subject.rule_parameter_set_id = "" + end + it "should return nil" do + subject.rule_parameter_set.should be_nil + end + end + context "when rule_parameter_set_id is not blank" do + let( :rule_parameter_set ){ Factory( :rule_parameter_set ) } + before(:each) do + subject.rule_parameter_set_id = rule_parameter_set.id + end + it "should return rule_parameter_set instance" do + subject.rule_parameter_set.should == rule_parameter_set + end + end + end + + describe "#rule_parameter_set_archived" do + context "when parameter_set is blank" do + before(:each) do + subject.parameter_set = nil + end + it "should return nil" do + subject.rule_parameter_set_archived.should be_nil + end + end + context "when parameter_set is blank" do + before(:each) do + subject.parameter_set = { :speed => 30, :distance => 5 } + end + it "should return RuleParameterSet#parameters same as parameter_set" do + subject.rule_parameter_set_archived.parameters.should == subject.parameter_set + end + it "should return RuleParameterSet#name same as parameter_set_name" do + subject.rule_parameter_set_archived.name.should == subject.parameter_set_name + end + end + + end + +# describe "#validate" do +# +# before(:each) do +# subject.stub :validator => mock(:validate => true) +# end +# +# it "should create a ComplianceCheckResult :started when started" do +# subject.validate +# subject.compliance_check_results.first.should 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") +# 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") +# end +# +# end + + describe ".create" do + let( :new_compliance_check_task){ Factory.build( :compliance_check_task) } + + it "should call #define_default_attributes" do + new_compliance_check_task.should_receive( :define_default_attributes) + new_compliance_check_task.save + end + + it "should call #delayed_validate" do + new_compliance_check_task.should_not_receive( :delayed_validate) + new_compliance_check_task.save + end + + end + + it_behaves_like TypeIdsModelable do + let(:type_ids_model) { subject} + end + +end + diff --git a/spec/models/csv_import_spec.rb b/spec/models/csv_import_spec.rb index e169afb5f..3dad39aeb 100644 --- a/spec/models/csv_import_spec.rb +++ b/spec/models/csv_import_spec.rb @@ -2,18 +2,13 @@ require 'spec_helper' describe CsvImport do - describe "#objectid_prefix" do + describe "#object_id_prefix" do - it "should be included in options" do - subject.objectid_prefix = "dummy" - subject.options.should include "objectid_prefix" => "dummy" - end + it "should be included in import_options" do + subject.object_id_prefix = "dummy" + subject.parameter_set["object_id_prefix"].should == "dummy" + end - it "should be included in import_options" do - subject.objectid_prefix = "dummy" - subject.import_options.should include :objectid_prefix => "dummy" - end - - end + end end diff --git a/spec/models/export_spec.rb b/spec/models/export_spec.rb index fb83236b0..cc8c045f1 100644 --- a/spec/models/export_spec.rb +++ b/spec/models/export_spec.rb @@ -9,7 +9,7 @@ describe Export do actual and expected.all? { |k,v| actual[k.to_s] == v } end end - + describe "#export" do before(:each) do @@ -36,7 +36,7 @@ describe Export do end describe "#options" do - + it "should be empty by default" do subject.options.should be_empty end @@ -44,7 +44,7 @@ describe Export do end describe ".types" do - + it "should return available Export implementations" do Export.types.should =~ %w{NeptuneExport CsvExport GtfsExport NetexExport KmlExport} end @@ -52,99 +52,15 @@ describe Export do end describe ".new" do - + it "should use type attribute to create a subclass" do Export.new(:type => "NeptuneExport").should be_an_instance_of(NeptuneExport) end end - describe "#references" do - - it "should be empty if references_type is nil" do - subject.references_type = nil - subject.references.should be_empty - end - - it "should be empty if reference_ids is blank" do - subject.reference_ids = "" - subject.references.should be_empty - end - - end - - describe "#references=" do - - context "with Lines" do - - let(:lines) { create_list :line, 3 } - - before(:each) do - subject.references = lines - end - - it "should use 'Chouette::Line' as references_type" do - subject.references_type.should == 'Chouette::Line' - end - - it "should use line identifiers as raw reference_ids" do - subject.raw_reference_ids.should == lines.map(&:id).join(',') - end - - end - - end - - describe "#references_relation" do - - it "should be 'lines' when relation_type is 'Chouette::Line'" do - subject.references_type = "Chouette::Line" - subject.references_relation.should == "lines" - end - - it "should be 'networks' when relation_type is 'Chouette::Network'" do - subject.references_type = "Chouette::Network" - subject.references_relation.should == "networks" - end - - it "should be nil when relation_type is blank" do - subject.references_type = "" - subject.references_relation.should be_nil - end - - it "should be nil when relation_type is 'dummy'" do - subject.references_type = "dummy" - subject.references_relation.should be_nil - end - - end - - describe "#reference_ids" do - - it "should parse raw_reference_ids and returns ids" do - subject.stub :raw_reference_ids => "1,2,3" - subject.reference_ids.should == [1,2,3] - end - - it "should be empty if raw_reference_ids is blank" do - subject.stub :raw_reference_ids => "" - subject.reference_ids.should be_empty - end - - end - - describe "#reference_ids=" do - - it "should join ids with comma" do - subject.reference_ids = [1,2,3] - subject.raw_reference_ids.should == "1,2,3" - end - - it "should be nil if records is blank" do - subject.reference_ids = [] - subject.raw_reference_ids.should be_nil - end - + it_behaves_like TypeIdsModelable do + let(:type_ids_model) { subject} end end diff --git a/spec/models/gtfs_import_spec.rb b/spec/models/gtfs_import_spec.rb index f22a2d20d..e1a1ac48e 100644 --- a/spec/models/gtfs_import_spec.rb +++ b/spec/models/gtfs_import_spec.rb @@ -2,74 +2,49 @@ require 'spec_helper' describe GtfsImport do - describe "#objectid_prefix" do - - it "should be included in options" do - subject.objectid_prefix = "dummy" - subject.options.should include "objectid_prefix" => "dummy" - end - - it "should be included in import_options" do - subject.objectid_prefix = "dummy" - subject.import_options.should include :objectid_prefix => "dummy" - end - - end - - describe "#max_distance_for_commercial" do - - it "should be included in options" do - subject.max_distance_for_commercial = 300 - subject.options.should include "max_distance_for_commercial" => 300 - end - - it "should be included in import_options" do - subject.max_distance_for_commercial = 300 - subject.import_options.should include :max_distance_for_commercial => 300 - end - - end - - describe "#max_distance_for_connection_link" do - - it "should be included in options" do - subject.max_distance_for_connection_link = 300 - subject.options.should include "max_distance_for_connection_link" => 300 - end - - it "should be included in import_options" do - subject.max_distance_for_connection_link = 300 - subject.import_options.should include :max_distance_for_connection_link => 300 - end - - end - - describe "#ignore_last_word" do - - it "should be included in options" do - subject.ignore_last_word = true - subject.options.should include "ignore_last_word" => true - end - - it "should be included in import_options" do - subject.ignore_last_word = true - subject.import_options.should include :ignore_last_word => true - end - - end - - describe "#ignore_end_chars" do - - it "should be included in options" do - subject.ignore_end_chars = 2 - subject.options.should include "ignore_end_chars" => 2 - end - - it "should be included in import_options" do - subject.ignore_end_chars = 2 - subject.import_options.should include :ignore_end_chars => 2 - end - - end + describe "#object_id_prefix" do + + it "should be included in import_options" do + subject.object_id_prefix = "dummy" + subject.parameter_set["object_id_prefix"].should == "dummy" + end + + end + + describe "#max_distance_for_commercial" do + + it "should be included in import_options" do + subject.max_distance_for_commercial = 300 + subject.parameter_set["max_distance_for_commercial"].should == 300 + end + + end + + describe "#max_distance_for_connection_link" do + + it "should be included in import_options" do + subject.max_distance_for_connection_link = 300 + subject.parameter_set["max_distance_for_connection_link"].should == 300 + end + + end + + describe "#ignore_last_word" do + + it "should be included in import_options" do + subject.ignore_last_word = true + subject.parameter_set["ignore_last_word"].should == true + end + + end + + describe "#ignore_end_chars" do + + it "should be included in import_options" do + subject.ignore_end_chars = 2 + subject.parameter_set["ignore_end_chars"].should == 2 + end + + end end diff --git a/spec/models/import_log_message_spec.rb b/spec/models/import_log_message_spec.rb deleted file mode 100644 index dab951255..000000000 --- a/spec/models/import_log_message_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -require 'spec_helper' - -describe ImportLogMessage do - - describe "#attributes" do - - subject { create :import_log_message } - - it "should read json stored in database" do - subject.update_attribute :arguments, { "key" => "value"} - subject.raw_attributes.should == { "key" => "value"}.to_json - end - - end - -end diff --git a/spec/models/import_spec.rb b/spec/models/import_spec.rb deleted file mode 100644 index bbf6725d7..000000000 --- a/spec/models/import_spec.rb +++ /dev/null @@ -1,61 +0,0 @@ -require 'spec_helper' - -describe Import do - - subject { create :import } - - RSpec::Matchers.define :be_log_message do |expected| - match do |actual| - actual and expected.all? { |k,v| actual[k.to_s] == v } - end - end - - describe "#import" do - - before(:each) do - subject.stub :loader => mock(:import => true) - end - - it "should create a ImportLogmessage :started when started" do - subject.import - subject.log_messages.first.should be_log_message(:key => "started") - end - - it "should create a ImportLogmessage :completed when completed" do - subject.import - subject.log_messages.last.should be_log_message(:key => "completed") - end - - it "should create a ImportLogmessage :failed when failed" do - subject.loader.stub(:import).and_raise("import failed") - subject.import - subject.log_messages.last.should be_log_message(:key => "failed") - end - - end - - describe "#options" do - - it "should be nil by default" do - subject.options.should be_nil - end - - end - - describe ".types" do - - it "should return available Import implementations" do - Import.types.should =~ %w{NeptuneImport CsvImport GtfsImport NetexImport} - end - - end - - describe ".new" do - - it "should use type attribute to create a subclass" do - Import.new(:type => "NeptuneImport").should be_an_instance_of(NeptuneImport) - end - - end - -end diff --git a/spec/models/import_task_spec.rb b/spec/models/import_task_spec.rb new file mode 100644 index 000000000..542ccd739 --- /dev/null +++ b/spec/models/import_task_spec.rb @@ -0,0 +1,196 @@ +require 'spec_helper' + +describe ImportTask do + + subject { build :import_task } + + describe ".new" do + + it "should use type attribute to create a subclass" do + ImportTask.new(:format => "Neptune").should be_an_instance_of(NeptuneImport) + ImportTask.new(:format => "Gtfs").should be_an_instance_of(GtfsImport) + ImportTask.new(:format => "Netex").should be_an_instance_of(NetexImport) + ImportTask.new(:format => "Csv").should be_an_instance_of(CsvImport) + + NeptuneImport.new.should be_an_instance_of(NeptuneImport) + GtfsImport.new.should be_an_instance_of(GtfsImport) + NetexImport.new.should be_an_instance_of(NetexImport) + CsvImport.new.should be_an_instance_of(CsvImport) + end + + end + + describe "#delayed_import" do + before(:each) do + subject.stub!( :delay => mock( :import => true)) + end + it "should call delay#import" do + subject.delay.should_receive( :import) + subject.send :delayed_import + end + end + + describe ".create" do + before(:each) do + subject.stub!( :save_resources => true ) + end + it "should call save_resource" do + subject.should_receive( :save_resources) + subject.send :save + end + it "should update file_path with #saved_resources" do + subject.send :save + ImportTask.find( subject.id).file_path.should == subject.send( :saved_resources) + end + it "should have a compliance_check_task" do + subject.send :save + ImportTask.find( subject.id).compliance_check_task.should_not be_nil + end + end + + describe "#compliance_check_task" do + let(:rule_parameter_set){ Factory( :rule_parameter_set) } + let(:import_task){ Factory(:import_task, :rule_parameter_set_id => rule_parameter_set.id) } + let(:compliance_check_task){ import_task.compliance_check_task } + + it "should have same #referential as import_task" do + compliance_check_task.referential.should == import_task.referential + end + + it "should have same #rule_parameter_set_id as import_task" do + compliance_check_task.rule_parameter_set_id.should == import_task.rule_parameter_set_id + end + + it "should have same #user_id as import_task" do + compliance_check_task.user_id.should == import_task.user_id + end + + it "should have same #user_name as import_task" do + compliance_check_task.user_name.should == import_task.user_name + end + end + + describe "#file_path_extension" do + let(:import_task){ Factory(:import_task) } + context "zip file to import" do + before(:each) do + import_task.file_path = "aaa/bbb.zip" + end + it "should return zip" do + import_task.file_path_extension.should == "zip" + end + end + context "xml file to import" do + before(:each) do + import_task.file_path = "aaa/bbb.xml" + end + it "should return xml" do + import_task.file_path_extension.should == "xml" + end + end + context "csv file to import" do + before(:each) do + import_task.file_path = "aaa/bbb.csv" + end + it "should return csv" do + import_task.file_path_extension.should == "basic" + end + end + + end + + context "options attributes" do + let(:import_task){ Factory(:import_task) } + describe "#no_save" do + it "should read parameter_set['no_save']" do + import_task.parameter_set[ "no_save"] = "dummy" + import_task.no_save.should == "dummy" + end + end + describe "#format" do + it "should read parameter_set['format']" do + import_task.parameter_set[ "format"] = "dummy" + import_task.format.should == "dummy" + end + end + describe "#file_path" do + it "should read parameter_set['file_path']" do + import_task.parameter_set[ "file_path"] = "dummy" + import_task.file_path.should == "dummy" + end + end + describe "#no_save=" do + it "should read parameter_set['no_save']" do + import_task.no_save = "dummy" + import_task.parameter_set[ "no_save"].should == false + end + end + describe "#format=" do + it "should read parameter_set['format']" do + import_task.format = "dummy" + import_task.parameter_set[ "format"].should == "dummy" + end + end + describe "#file_path=" do + it "should read parameter_set['file_path']" do + import_task.file_path = "dummy" + import_task.parameter_set[ "file_path"].should == "dummy" + end + end + end + + describe "#chouette_command" do + it "should be a Chouette::Command instance" do + subject.send( :chouette_command).class.should == Chouette::Command + end + it "should have schema same as referential.slug" do + subject.send( :chouette_command).schema.should == subject.referential.slug + end + end + + describe "#import" do + let(:import_task){ Factory(:import_task) } + let(:chouette_command) { "dummy" } + context "for failing import" do + before(:each) do + chouette_command.stub!( :run!).and_raise( "dummy") + import_task.stub!( :chouette_command => chouette_command) + end + it "should have status 'failed'" do + import_task.import + import_task.status.should == "failed" + end + it "should have status 'failed' for compliance_check_task" do + import_task.import + import_task.compliance_check_task.status.should == "failed" + end + end + context "for successful import" do + before(:each) do + import_task.stub!( :chouette_command => mock( :run! => true )) + end + it "should have status 'completed'" do + import_task.import + import_task.status.should == "completed" + end + it "should have status 'completed' for compliance_check_task" do + import_task.import + import_task.status.should == "completed" + end + end + end + + describe "#import" do + let(:import_task){ Factory(:import_task) } + let(:command_args){ "dummy" } + before(:each) do + import_task.stub!( :chouette_command => mock( :run! => true )) + import_task.stub!( :chouette_command_args => command_args) + end + it "should call chouette_command.run! with :c => 'import', :id => id" do + import_task.send( :chouette_command).should_receive( :run! ).with( command_args) + import_task.import + end + end + +end diff --git a/spec/models/rule_parameter_set_spec.rb b/spec/models/rule_parameter_set_spec.rb new file mode 100644 index 000000000..bf785d6f7 --- /dev/null +++ b/spec/models/rule_parameter_set_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe RuleParameterSet do + + describe ".mode_of_mode_attribute" do + it "should retreive attribute name" do + subject.class.attribute_of_mode_attribute("dummy1_mode_dummy2").should == "dummy1" + end + it "should retreive mode" do + subject.class.mode_of_mode_attribute("dummy1_mode_dummy2").should == "dummy2" + end + end + + RuleParameterSet.mode_attribute_prefixes.each do |prefix| + RuleParameterSet.all_modes.map do |mode| + "#{prefix}_mode_#{mode}".tap do |attribute| + describe "##{attribute}=" do + it "should store value on parameters hash" do + subject.send( "#{attribute}=".to_sym, 1234) + subject.send( attribute.to_sym).should == 1234 + subject.parameters["mode_#{mode}"][ prefix].should == 1234 + end + end + it { should allow_mass_assignment_of attribute.to_sym} + end + end + end + + RuleParameterSet.general_attributes.each do |attribute| + describe "##{attribute}=" do + it "should store value on parameters hash" do + subject.send( "#{attribute}=".to_sym, 1234) + subject.send( attribute.to_sym).should == 1234 + subject.parameters[ attribute].should == 1234 + end + end + it { should allow_mass_assignment_of attribute.to_sym} + end + + describe "#referential" do + it { should validate_presence_of(:referential) } + it { should allow_mass_assignment_of :referential_id } + end + + describe "#name" do + it { should validate_presence_of(:name) } + it { should allow_mass_assignment_of :name } + end +end diff --git a/spec/requests/companies_spec.rb b/spec/requests/companies_spec.rb index dbacd4a71..fdcff4cab 100644 --- a/spec/requests/companies_spec.rb +++ b/spec/requests/companies_spec.rb @@ -4,12 +4,11 @@ require 'spec_helper' describe "Companies" do login_user - let(:companies) { Array.new(2) { create :company } } + let!(:companies) { Array.new(2) { create :company } } subject { companies.first } describe "list" do it "display companies" do - pending visit referential_companies_path(referential) page.should have_content(companies.first.name) page.should have_content(companies.last.name) @@ -19,7 +18,6 @@ describe "Companies" do describe "show" do it "display company" do - pending visit referential_companies_path(referential) click_link "#{companies.first.name}" page.should have_content(companies.first.name) @@ -29,7 +27,6 @@ describe "Companies" do describe "new" do it "creates company and return to show" do - pending visit referential_companies_path(referential) click_link "Ajouter un transporteur" fill_in "Nom", :with => "Company 1" @@ -42,7 +39,6 @@ describe "Companies" do describe "edit and return to show" do it "edit company" do - pending visit referential_company_path(referential, subject) click_link "Modifier ce transporteur" fill_in "Nom", :with => "Company Modified" diff --git a/spec/requests/connection_links_spec.rb b/spec/requests/connection_links_spec.rb index 48b5aa41d..74fe17c2e 100644 --- a/spec/requests/connection_links_spec.rb +++ b/spec/requests/connection_links_spec.rb @@ -4,12 +4,11 @@ require 'spec_helper' describe "ConnectionLinks" do login_user - let(:connection_links) { Array.new(2) { create(:connection_link) } } + let!(:connection_links) { Array.new(2) { create(:connection_link) } } subject { connection_links.first } describe "list" do it "display connection_links" do - pending visit referential_connection_links_path(referential) page.should have_content(connection_links.first.name) page.should have_content(connection_links.last.name) @@ -19,14 +18,12 @@ describe "ConnectionLinks" do describe "show" do it "display connection_link" do - pending visit referential_connection_links_path(referential) click_link "#{connection_links.first.name}" page.should have_content(connection_links.first.name) end it "display map" do - pending ": map not yet implemented" subject.stub(:stop_areas).and_return(Array.new(2) { Factory(:stop_area) }) visit referential_connection_links_path(referential) click_link "#{connection_links.first.name}" @@ -37,7 +34,6 @@ describe "ConnectionLinks" do describe "new" do it "creates connection_link and return to show" do - pending visit referential_connection_links_path(referential) click_link "Ajouter une correspondance" fill_in "Nom", :with => "ConnectionLink 1" @@ -49,7 +45,6 @@ describe "ConnectionLinks" do describe "edit and return to show" do it "edit connection_link" do - pending visit referential_connection_link_path(referential, subject) click_link "Modifier cette correspondance" fill_in "Nom", :with => "ConnectionLink Modified" diff --git a/spec/requests/lines_spec.rb b/spec/requests/lines_spec.rb index 10d653f30..b851f522a 100644 --- a/spec/requests/lines_spec.rb +++ b/spec/requests/lines_spec.rb @@ -4,14 +4,13 @@ require 'spec_helper' describe "Lines" do login_user - let(:network) { Factory(:network) } - let(:company) { Factory(:company) } - let(:lines) { referential; Array.new(2) { Factory(:line, :network => network, :company => company) } } + let!(:network) { Factory(:network) } + let!(:company) { Factory(:company) } + let!(:lines) { Array.new(2) { Factory(:line_with_stop_areas, :network => network, :company => company) } } subject { lines.first } describe "list" do it "display lines" do - pending visit referential_lines_path(referential) page.should have_content(lines.first.name) page.should have_content(lines.last.name) @@ -22,16 +21,12 @@ describe "Lines" do describe "show" do it "display line" do - pending - subject.stub(:stop_areas).and_return(Array.new(2) { Factory(:stop_area) }) visit referential_lines_path(referential) click_link "#{lines.first.name}" page.should have_content(lines.first.name) end it "display map" do - pending - subject.stub(:stop_areas).and_return(Array.new(2) { Factory(:stop_area) }) visit referential_lines_path(referential) click_link "#{lines.first.name}" page.should have_selector("#map", :class => 'line') @@ -41,13 +36,11 @@ describe "Lines" do describe "new" do it "creates line and return to show" do - pending - subject.stub(:stop_areas).and_return(Array.new(2) { Factory(:stop_area) }) visit referential_lines_path(referential) click_link "Ajouter une ligne" fill_in "Nom", :with => "Line 1" - fill_in "Numéro d'enregistrement", :with => "test-1" - fill_in "Identifiant Neptune", :with => "test:Line:1" + fill_in "Numéro d'enregistrement", :with => "1" + fill_in "Identifiant Neptune", :with => "test:Line:999" click_button("Créer ligne") page.should have_content("Line 1") end @@ -55,8 +48,6 @@ describe "Lines" do describe "edit and return to show" do it "edit line" do - pending - subject.stub(:stop_areas).and_return(Array.new(2) { Factory(:stop_area) }) visit referential_line_path(referential, subject) click_link "Modifier cette ligne" fill_in "Nom", :with => "Line Modified" diff --git a/spec/requests/networks_spec.rb b/spec/requests/networks_spec.rb index ff020dca6..662e5e830 100644 --- a/spec/requests/networks_spec.rb +++ b/spec/requests/networks_spec.rb @@ -4,13 +4,11 @@ require 'spec_helper' describe "Networks" do login_user - let(:networks) { Array.new(2) { Factory(:network) } } + let!(:networks) { Array.new(2) { Factory(:network) } } subject { networks.first } describe "list" do it "display networks" do - pending - visit referential_networks_path(referential) page.should have_content(networks.first.name) page.should have_content(networks.last.name) @@ -20,8 +18,6 @@ describe "Networks" do describe "show" do it "display network" do - pending - subject.stub(:stop_areas).and_return(Array.new(2) { Factory(:stop_area) }) visit referential_networks_path(referential) click_link "#{networks.first.name}" @@ -29,8 +25,6 @@ describe "Networks" do end it "display map" do - pending - subject.stub(:stop_areas).and_return(Array.new(2) { Factory(:stop_area) }) visit referential_networks_path(referential) click_link "#{networks.first.name}" @@ -41,8 +35,6 @@ describe "Networks" do describe "new" do it "creates network and return to show" do - pending - subject.stub(:stop_areas).and_return(Array.new(2) { Factory(:stop_area) }) visit referential_networks_path(referential) click_link "Ajouter un réseau" @@ -56,8 +48,6 @@ describe "Networks" do describe "edit and return to show" do it "edit network" do - pending - subject.stub(:stop_areas).and_return(Array.new(2) { Factory(:stop_area) }) visit referential_network_path(referential, subject) click_link "Modifier ce réseau" @@ -68,23 +58,15 @@ describe "Networks" do end end - describe "delete", :js => true do - it "delete network and return to the list" do - # subject.stub(:stop_areas).and_return(Array.new(2) { Factory(:stop_area) }) - - # visit referential_networks_path(referential) - # click_link "#{networks.first.name}" - # click_link "Modifier ce réseau" - # fill_in "Nom", :with => "Network 1" - # fill_in "Numéro d'enregistrement", :with => "test-1" - # click_button("Modifier Réseau") - # page.should have_content("Network 1") - # visit referential_network_path(referential, subject) - # click_link "Supprimer ce réseau" - # page.evaluate_script('window.confirm = function() { return true; }') - # click_button "Valider" - # page.should have_no_content("Network 1") - end + # describe "delete", :js => true do + # it "delete network and return to the list" do + # subject.stub(:stop_areas).and_return(Array.new(2) { Factory(:stop_area) }) + # visit referential_network_path(referential, subject) + # click_link "Supprimer ce réseau" + # page.evaluate_script('window.confirm = function() { return true; }') + # click_button "Valider" + # page.should have_no_content(subject.name) + # end - end + # end end diff --git a/spec/requests/referentials_spec.rb b/spec/requests/referentials_spec.rb index 9203de16d..c57192d9b 100644 --- a/spec/requests/referentials_spec.rb +++ b/spec/requests/referentials_spec.rb @@ -22,8 +22,6 @@ describe "Referentials" do retrieve_referential_by_slug("bb")] } it "should show n referentials" do - pending - visit referentials_path page.should have_content(referentials.first.name) page.should have_content(referentials.last.name) diff --git a/spec/requests/routes_spec.rb b/spec/requests/routes_spec.rb index 3ba1985eb..5e24b8492 100644 --- a/spec/requests/routes_spec.rb +++ b/spec/requests/routes_spec.rb @@ -4,9 +4,9 @@ require 'spec_helper' describe "Routes" do login_user - let(:line) { Factory(:line) } - let(:route) { Factory(:route, :line => line) } - let(:route2) { Factory(:route, :line => line) } + let!(:line) { Factory(:line) } + let!(:route) { Factory(:route, :line => line) } + let!(:route2) { Factory(:route, :line => line) } describe "from lines page to a line page" do it "display line's routes" do diff --git a/spec/requests/stop_areas_spec.rb b/spec/requests/stop_areas_spec.rb index 5d4e3afb3..ef3ca9275 100644 --- a/spec/requests/stop_areas_spec.rb +++ b/spec/requests/stop_areas_spec.rb @@ -4,30 +4,25 @@ require 'spec_helper' describe "StopAreas" do login_user - let(:stop_areas) { Array.new(2) { Factory(:stop_area) } } + let!(:stop_areas) { Array.new(2) { Factory(:stop_area) } } subject { stop_areas.first } describe "list" do it "display stop_areas" do - pending visit referential_stop_areas_path(referential) page.should have_content(stop_areas.first.name) page.should have_content(stop_areas.last.name) - end - + end end - describe "show" do it "display stop_area" do - pending visit referential_stop_areas_path(referential) click_link "#{stop_areas.first.name}" page.should have_content(stop_areas.first.name) end it "display map" do - pending visit referential_stop_areas_path(referential) click_link "#{stop_areas.first.name}" page.should have_selector("#map", :class => 'stop_area') @@ -37,12 +32,11 @@ describe "StopAreas" do describe "new" do it "creates stop_area and return to show" do - pending visit referential_stop_areas_path(referential) click_link "Ajouter un arrêt" fill_in "Nom", :with => "StopArea 1" fill_in "Numéro d'enregistrement", :with => "test-1" - #fill_in "Identifiant Neptune", :with => "test:StopArea:1" + fill_in "Identifiant Neptune", :with => "test:StopArea:1" click_button("Créer arrêt") page.should have_content("StopArea 1") end @@ -50,7 +44,6 @@ describe "StopAreas" do describe "edit and return to show" do it "edit stop_area" do - pending visit referential_stop_area_path(referential, subject) click_link "Modifier cet arrêt" fill_in "Nom", :with => "StopArea Modified" diff --git a/spec/requests/time_tables_spec.rb b/spec/requests/time_tables_spec.rb index c935587b3..412dcece6 100644 --- a/spec/requests/time_tables_spec.rb +++ b/spec/requests/time_tables_spec.rb @@ -4,12 +4,11 @@ require 'spec_helper' describe "TimeTables" do login_user - let(:time_tables) { Array.new(2) { create(:time_table) } } + let!(:time_tables) { Array.new(2) { create(:time_table) } } subject { time_tables.first } describe "list" do it "display time_tables" do - pending visit referential_time_tables_path(referential) page.should have_content(time_tables.first.comment) page.should have_content(time_tables.last.comment) @@ -19,7 +18,6 @@ describe "TimeTables" do describe "show" do it "display time_table" do - pending visit referential_time_tables_path(referential) click_link "#{time_tables.first.comment}" page.should have_content(time_tables.first.comment) @@ -29,7 +27,6 @@ describe "TimeTables" do describe "new" do it "creates time_table and return to show" do - pending visit referential_time_tables_path(referential) click_link "Ajouter un calendrier" fill_in "Description", :with => "TimeTable 1" @@ -41,7 +38,6 @@ describe "TimeTables" do describe "edit and return to show" do it "edit time_table" do - pending visit referential_time_table_path(referential, subject) click_link "Modifier ce calendrier" fill_in "Description", :with => "TimeTable Modified" diff --git a/spec/support/devise.rb b/spec/support/devise.rb index b50f3a71a..8713e96fa 100644 --- a/spec/support/devise.rb +++ b/spec/support/devise.rb @@ -3,7 +3,7 @@ module DeviseRequestHelper def login_user organisation = Organisation.find_by_name("first") || create(:organisation, :name => "first") - @user ||= create(:user, :organisation => organisation) + @user ||= create(:user, :organisation => organisation) @user.confirm! login_as @user, :scope => :user # post_via_redirect user_session_path, 'user[email]' => @user.email, 'user[password]' => @user.password @@ -22,7 +22,7 @@ module DeviseRequestHelper login_user end after(:each) do - Warden.test_reset! + Warden.test_reset! end end diff --git a/spec/support/type_ids_modelable_spec.rb b/spec/support/type_ids_modelable_spec.rb new file mode 100644 index 000000000..d5a3f7042 --- /dev/null +++ b/spec/support/type_ids_modelable_spec.rb @@ -0,0 +1,100 @@ +require 'spec_helper' + +shared_examples_for TypeIdsModelable do + context 'class methods' do + it 'should be a TypeIdsModelable class' do + described_class.type_ids_modelable_class?.should be_true + end + describe ".references_relation" do + it "shoud demodulize, underscore and puralize" do + described_class.references_relation( Chouette::StopArea).should == "stop_areas" + end + end + end + + context 'with an instance' do + describe "#references" do + it "should be empty if references_type is nil" do + type_ids_model.references_type = nil + type_ids_model.references.should be_empty + end + it "should be empty if reference_ids is blank" do + type_ids_model.reference_ids = "" + type_ids_model.references.should be_empty + end + end + describe "#references=" do + let(:lines) { create_list :line, 3 } + + context "when references defined" do + before(:each) do + type_ids_model.references = lines + end + it "should set reference_ids to [data_a.id]" do + type_ids_model.reference_ids.should == lines.map(&:id) + end + it "should set references_type to EffectiveDataTypeA" do + type_ids_model.references_type.should == 'Chouette::Line' + end + end + context "when references blank" do + before(:each) do + type_ids_model.references = "" + end + it "should set reference_ids to []" do + type_ids_model.reference_ids.should == [] + end + it "should set references_type to nil" do + type_ids_model.references_type.should be_nil + end + end + end + + describe "#references_relation" do + it "should be 'lines' when relation_type is 'Chouette::Line'" do + type_ids_model.references_type = "Chouette::Line" + type_ids_model.references_relation.should == "lines" + end + + it "should be 'networks' when relation_type is 'Chouette::Network'" do + type_ids_model.references_type = "Chouette::Network" + type_ids_model.references_relation.should == "networks" + end + + it "should be nil when relation_type is blank" do + type_ids_model.references_type = "" + type_ids_model.references_relation.should be_nil + end + + it "should be nil when relation_type is 'dummy'" do + type_ids_model.references_type = "dummy" + type_ids_model.references_relation.should be_nil + end + end + + describe "#reference_ids" do + it "should parse raw_reference_ids and returns ids" do + type_ids_model.stub :raw_reference_ids => "1,2,3" + type_ids_model.reference_ids.should == [1,2,3] + end + + it "should be empty if raw_reference_ids is blank" do + type_ids_model.stub :raw_reference_ids => "" + type_ids_model.reference_ids.should be_empty + end + end + + describe "#reference_ids=" do + it "should join ids with comma" do + type_ids_model.reference_ids = [1,2,3] + type_ids_model.raw_reference_ids.should == "1,2,3" + end + it "should be nil if records is blank" do + type_ids_model.reference_ids = [] + type_ids_model.raw_reference_ids.should be_nil + end + end + end + + +end diff --git a/spec/views/imports/index.html.erb_spec.rb b/spec/views/import_tasks/index.html.erb_spec.rb index c0f2d3462..c0f2d3462 100644 --- a/spec/views/imports/index.html.erb_spec.rb +++ b/spec/views/import_tasks/index.html.erb_spec.rb diff --git a/spec/views/import_tasks/new.html.erb_spec.rb b/spec/views/import_tasks/new.html.erb_spec.rb new file mode 100644 index 000000000..002832dc9 --- /dev/null +++ b/spec/views/import_tasks/new.html.erb_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe "import_tasks/new.html.erb" do + + assign_referential + let!(:import_task) { assign(:import_task, ImportTask.new) } + + let!(:available_imports) { assign(:available_imports, []) } + + it "should display a radio button to choose import type" do + render + rendered.should have_selector("input", :type => "select", :name => "import_task[format]") + end + +end diff --git a/spec/views/imports/new.html.erb_spec.rb b/spec/views/imports/new.html.erb_spec.rb deleted file mode 100644 index 081999c60..000000000 --- a/spec/views/imports/new.html.erb_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' - -describe "imports/new.html.erb" do - - assign_referential - let!(:import) { assign(:import, NeptuneImport.new) } - - let!(:available_imports) { assign(:available_imports, []) } - - it "should display a radio button to choose import type" do - render - rendered.should have_selector("input", :type => "radio", :name => "import[type]") - end - -end diff --git a/spec/views/rule_parameter_sets/index.html.erb_spec.rb b/spec/views/rule_parameter_sets/index.html.erb_spec.rb new file mode 100644 index 000000000..0f50ea387 --- /dev/null +++ b/spec/views/rule_parameter_sets/index.html.erb_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe "/rule_parameter_sets/index" do + + assign_referential + let!(:rule_parameter_sets) { assign :rule_parameter_sets, [ Factory(:rule_parameter_set), + Factory(:rule_parameter_set)] } + + it "should render a show link for each rule_parameter_set" do + render + rule_parameter_sets.each do |rule_parameter_set| + rendered.should have_selector(".rule_parameter_set a[href='#{view.referential_rule_parameter_set_path(referential, rule_parameter_set)}']", :text => rule_parameter_set.name) + end + end + + it "should render a link to create a new rule_parameter_set" do + render + view.content_for(:sidebar).should have_selector(".actions a[href='#{new_referential_rule_parameter_set_path(referential)}']") + end + +end + diff --git a/spec/views/rule_parameter_sets/new.html.erb_spec.rb b/spec/views/rule_parameter_sets/new.html.erb_spec.rb new file mode 100644 index 000000000..4670ecceb --- /dev/null +++ b/spec/views/rule_parameter_sets/new.html.erb_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe "/rule_parameter_sets/new" do + + assign_referential + let!(:rule_parameter_set) { assign :rule_parameter_set, build( :rule_parameter_set, :referential => referential) } + + describe "form" do + + it "should render input for name" do + render + rendered.should have_selector("form") do + with_selector "input[type=text][name=?]", rule_parameter_set.name + end + end + it "should render input div for added_mode_parameter_set" do + render + rendered.should have_selector("form") do + with_selector "#added_mode_parameter_set" + end + end + + end + +end + |
