aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuc Donnet2017-07-25 22:15:35 +0200
committerLuc Donnet2017-07-25 22:15:35 +0200
commitcbfe9501f2d2cfc38cbe6ac12180e372dd78eca7 (patch)
treedbe70647c87af0d779dbba06e20d0f0c2b4a294a
parentea3ad8d1f9db76e3d2dfc5f96c930af8db074690 (diff)
parentcada0f02d732dce25492d7f7eb6d6232d56188dd (diff)
downloadchouette-core-cbfe9501f2d2cfc38cbe6ac12180e372dd78eca7.tar.bz2
Merge branch 'master' into staging
-rw-r--r--.erdconfig23
-rw-r--r--Gemfile.lock15
-rw-r--r--app/assets/javascripts/cleanup.coffee11
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js2
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js4
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js7
-rw-r--r--app/assets/stylesheets/_layout.sass10
-rw-r--r--app/assets/stylesheets/components/_panels.sass22
-rw-r--r--app/assets/stylesheets/components/_select2.sass4
-rw-r--r--app/assets/stylesheets/old_application.sass.erb62
-rw-r--r--app/controllers/companies_controller.rb23
-rw-r--r--app/controllers/networks_controller.rb23
-rw-r--r--app/controllers/referential_companies_controller.rb23
-rw-r--r--app/controllers/referential_networks_controller.rb23
-rw-r--r--app/controllers/referentials_controller.rb4
-rw-r--r--app/controllers/time_tables_controller.rb29
-rw-r--r--app/controllers/workbenches_controller.rb9
-rw-r--r--app/helpers/breadcrumb_helper.rb8
-rw-r--r--app/jobs/mailer_job.rb2
-rw-r--r--app/mailers/calendar_mailer.rb10
-rw-r--r--app/models/calendar_observer.rb4
-rw-r--r--app/models/chouette/line.rb2
-rw-r--r--app/models/chouette/stif_codifligne_objectid.rb18
-rw-r--r--app/models/chouette/stif_reflex_objectid.rb18
-rw-r--r--app/models/chouette/stop_area.rb17
-rw-r--r--app/models/chouette/stop_point.rb4
-rw-r--r--app/models/chouette/time_table.rb90
-rw-r--r--app/models/chouette/vehicle_journey.rb13
-rw-r--r--app/models/chouette/vehicle_journey_at_stop.rb37
-rw-r--r--app/models/clean_up.rb2
-rw-r--r--app/models/concerns/default_attributes_support.rb3
-rw-r--r--app/models/concerns/stif_codifligne_attributes_support.rb21
-rw-r--r--app/models/concerns/stif_reflex_attributes_support.rb21
-rw-r--r--app/models/referential.rb6
-rw-r--r--app/models/user.rb27
-rw-r--r--app/policies/login_policy.rb2
-rw-r--r--app/policies/referential_policy.rb6
-rw-r--r--app/views/compliance_checks/detailed_errors_index.csv.slim2
-rw-r--r--app/views/compliance_checks/summary_errors_index.csv.slim2
-rw-r--r--app/views/layouts/navigation/_main_nav_left.html.slim2
-rw-r--r--app/views/referential_stop_areas/index.html.slim2
-rw-r--r--app/views/referentials/show.html.slim8
-rw-r--r--app/views/stop_area_copies/new.html.slim2
-rw-r--r--app/views/time_tables/_filter.html.slim4
-rw-r--r--app/views/time_tables/time_tables.json.rabl2
-rw-r--r--app/views/workbenches/index.html.slim67
-rw-r--r--app/views/workbenches/show.html.slim2
-rw-r--r--config/i18n-tasks.yml34
-rw-r--r--config/locales/actions.en.yml1
-rw-r--r--config/locales/calendars.en.yml13
-rw-r--r--config/locales/clean_ups.en.yml2
-rw-r--r--config/locales/clean_ups.fr.yml2
-rw-r--r--config/locales/en.yml32
-rw-r--r--config/locales/enumerize.en.yml1
-rw-r--r--config/locales/fr.yml31
-rw-r--r--config/locales/imports.en.yml2
-rw-r--r--config/locales/imports.fr.yml2
-rw-r--r--config/locales/mailers.en.yml2
-rw-r--r--config/locales/referentials.en.yml3
-rw-r--r--config/locales/routes.en.yml6
-rw-r--r--config/locales/routing_constraint_zones.en.yml3
-rw-r--r--config/locales/simple_form.en.yml22
-rw-r--r--config/locales/simple_form.fr.yml13
-rw-r--r--config/locales/stop_areas.en.yml4
-rw-r--r--config/locales/stop_areas.fr.yml3
-rw-r--r--config/locales/time_tables.en.yml2
-rw-r--r--config/locales/vehicle_journey_at_stops.en.yml4
-rw-r--r--config/locales/vehicle_journey_at_stops.fr.yml4
-rw-r--r--config/locales/workbenches.en.yml12
-rw-r--r--config/locales/workbenches.fr.yml12
-rw-r--r--config/routes.rb9
-rw-r--r--config/sidekiq.yml5
-rw-r--r--lib/stif/permission_translator.rb40
-rw-r--r--lib/tasks/generate.rake11
-rw-r--r--spec/controllers/devise/cas_sessions_controller_spec.rb26
-rw-r--r--spec/decorators/referential_decorator_spec.rb5
-rw-r--r--spec/lib/stif/permission_translator_spec.rb39
-rw-r--r--spec/models/calendar_observer_spec.rb8
-rw-r--r--spec/models/chouette/line_spec.rb11
-rw-r--r--spec/models/chouette/stop_area_spec.rb19
-rw-r--r--spec/models/chouette/time_table_spec.rb39
-rw-r--r--spec/models/chouette/vehicle_journey_at_stop_spec.rb49
-rw-r--r--spec/models/chouette/vehicle_journey_spec.rb23
-rw-r--r--spec/models/referential_spec.rb3
-rw-r--r--spec/models/time_table_combination_spec.rb76
-rw-r--r--spec/models/user_spec.rb8
-rw-r--r--spec/policies/referential_policy_spec.rb2
-rw-r--r--spec/support/permissions.rb1
88 files changed, 947 insertions, 335 deletions
diff --git a/.erdconfig b/.erdconfig
new file mode 100644
index 000000000..9d1618ffd
--- /dev/null
+++ b/.erdconfig
@@ -0,0 +1,23 @@
+attributes:
+ - content
+ - foreign_key
+ - primary_key
+ - inheritance
+ - timestamps
+disconnected: true
+filename: erd
+filetype: png
+indirect: true
+inheritance: false
+markup: true
+notation: uml
+orientation: vertical
+polymorphism: false
+sort: true
+warn: true
+title: sample title
+exclude: null
+only: null
+only_recursion_depth: null
+prepend_primary: true
+cluster: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 41ae70f56..2239cf853 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -267,8 +267,8 @@ GEM
htmlbeautifier (1.3.1)
httparty (0.14.0)
multi_xml (>= 0.5.2)
- i18n (0.8.1)
- i18n-tasks (0.9.13)
+ i18n (0.8.6)
+ i18n-tasks (0.9.15)
activesupport (>= 4.0.2)
ast (>= 2.1.0)
easy_translate (>= 0.5.0)
@@ -313,7 +313,7 @@ GEM
mime-types-data (3.2016.0521)
mimemagic (0.3.2)
mini_portile2 (2.2.0)
- minitest (5.10.1)
+ minitest (5.10.2)
multi_json (1.12.1)
multi_test (0.1.2)
multi_xml (0.6.0)
@@ -406,7 +406,8 @@ GEM
activesupport (= 4.2.8)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
- rainbow (2.2.1)
+ rainbow (2.2.2)
+ rake
rake (12.0.0)
ransack (1.6.5)
actionpack (>= 3.0)
@@ -515,8 +516,8 @@ GEM
teaspoon-jasmine (2.3.4)
teaspoon (>= 1.0.0)
temple (0.7.7)
- terminal-table (1.7.3)
- unicode-display_width (~> 1.1.1)
+ terminal-table (1.8.0)
+ unicode-display_width (~> 1.1, >= 1.1.1)
therubyracer (0.12.3)
libv8 (~> 3.16.14.15)
ref
@@ -536,7 +537,7 @@ GEM
uglifier (2.7.2)
execjs (>= 0.3.0)
json (>= 1.8.0)
- unicode-display_width (1.1.3)
+ unicode-display_width (1.3.0)
warden (1.2.7)
rack (>= 1.0)
webmock (3.0.1)
diff --git a/app/assets/javascripts/cleanup.coffee b/app/assets/javascripts/cleanup.coffee
index 7e291aa9e..41aa1ff15 100644
--- a/app/assets/javascripts/cleanup.coffee
+++ b/app/assets/javascripts/cleanup.coffee
@@ -4,11 +4,16 @@ $(document).on("change", 'input[name="clean_up[date_type]"]', (e) ->
if type == 'before'
end_date.hide()
- $("label[for='clean_up_begin_date_3i']").html("Date de fin de la purge");
+ $('label.begin_date').addClass 'hidden'
+ $('label.end_date').removeClass 'hidden'
+
else if type == 'after'
end_date.hide()
- $("label[for='clean_up_begin_date_3i']").html("Date de début de la purge");
+ $('label.begin_date').removeClass 'hidden'
+ $('label.end_date').addClass 'hidden'
+
else
- $("label[for='clean_up_begin_date_3i']").html("Date de début de la purge");
+ $('label.begin_date').removeClass 'hidden'
+ $('label.end_date').addClass 'hidden'
end_date.show()
)
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js
index a6b8dcfa1..d277be003 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js
@@ -51,7 +51,7 @@ class BSelect4 extends React.Component{
},
cache: true
},
- minimumInputLength: 3,
+ minimumInputLength: 1,
templateResult: formatRepo
}}
/>
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js
index b3df767ab..c04a1d642 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js
@@ -43,14 +43,14 @@ class BSelect4 extends React.Component{
item => _.assign(
{},
item,
- { text: '<small><em>Nom: </em></small>' + item.published_name + '<br/><small><em>Code: </em></small>' + item.registration_number + '<br/><small><em>ID: </em></small>' + _.last(_.split(item.object_id, ':')) }
+ { text: "<strong>" + item.published_name + _.last(_.split(item.object_id, ':')) + "</strong><br/><small>" + item.registration_number + "</small>" }
)
)
};
},
cache: true
},
- minimumInputLength: 0,
+ minimumInputLength: 1,
escapeMarkup: function (markup) { return markup; },
templateResult: formatRepo
}}
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
index b236e7d94..3e81290f5 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
@@ -2,6 +2,7 @@ var _ = require('lodash')
var React = require('react')
var PropTypes = require('react').PropTypes
var Select2 = require('react-select2')
+var actions = require('../../../actions')
// get JSON full path
var origin = window.location.origin
@@ -37,20 +38,20 @@ class BSelect4 extends React.Component{
};
},
processResults: function(data, params) {
-
return {
results: data.map(
item => _.assign(
{},
item,
- {text: item.comment}
+ {text: '<strong>' + (item.color ? "<span class='fa fa-circle' style='color:" + item.color + "'></span> " : '') + item.comment + ' - ' + item.short_id + '</strong><br/><small>' + item.day_types.match(/[A-Z]?[a-z]+/g).join(', ') + '</small>'}
)
)
};
},
cache: true
},
- minimumInputLength: 3,
+ minimumInputLength: 1,
+ escapeMarkup: function (markup) { return markup; },
templateResult: formatRepo
}}
/>
diff --git a/app/assets/stylesheets/_layout.sass b/app/assets/stylesheets/_layout.sass
index c19d9b054..b6b91b2a5 100644
--- a/app/assets/stylesheets/_layout.sass
+++ b/app/assets/stylesheets/_layout.sass
@@ -28,3 +28,13 @@ body
// width: 75%
border-bottom: 1px solid rgba($blue, 0.5)
margin: 30px auto 45px auto
+
+.content_header
+ font-size: 2.2rem
+ font-weight: normal
+ margin: 40px 0
+ padding: 0px 15px 9px 15px
+ border-bottom: 1px solid #eee
+
+ &:first-child
+ margin-top: 0
diff --git a/app/assets/stylesheets/components/_panels.sass b/app/assets/stylesheets/components/_panels.sass
index ff384faf9..e9f615081 100644
--- a/app/assets/stylesheets/components/_panels.sass
+++ b/app/assets/stylesheets/components/_panels.sass
@@ -17,9 +17,31 @@
border-bottom: 2px solid $darkgrey
padding: 5px 15px
+ .badge
+ color: #fff
+ background-color: $grey
+
> h3, > h4
margin: 0
+ > .panel-title.with_actions
+ display: table
+ width: 100%
+
+ .badge
+ vertical-align: top
+
+ a
+ text-decoration: none
+ color: $blue
+
+ &:hover, &:focus
+ color: $darkblue
+
+ > div
+ display: table-cell
+ vertical-align: middle
+
.panel-footer
padding: 5px 15px
background-color: transparent
diff --git a/app/assets/stylesheets/components/_select2.sass b/app/assets/stylesheets/components/_select2.sass
index 960e8b10b..332af16cd 100644
--- a/app/assets/stylesheets/components/_select2.sass
+++ b/app/assets/stylesheets/components/_select2.sass
@@ -7,6 +7,10 @@
// .select2-results__message, .loading-results
// display: none
+.select2-container, .select2-container--bootstrap
+ .select2-selection--single .select2-selection__rendered
+ height: 100%
+
.select2-selection__placeholder
color: rgba($grey, 0.65)
font-style: italic
diff --git a/app/assets/stylesheets/old_application.sass.erb b/app/assets/stylesheets/old_application.sass.erb
deleted file mode 100644
index 3443a035d..000000000
--- a/app/assets/stylesheets/old_application.sass.erb
+++ /dev/null
@@ -1,62 +0,0 @@
-// First import journal variables
-$brand-primary: <%= ChouetteIhm::Application.config.company_theme %>
-$navbar-default-bg: $brand-primary
-$navbar-default-link-color: white
-$body-bg: #eee
-
-// Then bootstrap itself
-@import 'bootstrap-sass-official/_bootstrap-sprockets.scss'
-@import 'bootstrap-sass-official'
-
-// Whatever application styles you have go last
-// Modules and Variables
-@import 'modules/search'
-@import 'modules/index_item'
-@import 'modules/icons'
-@import 'modules/devise'
-@import 'modules/progress_bars'
-
-// Partials
-@import 'partials/base'
-@import 'partials/header'
-@import 'partials/footer'
-
-// Third-party
-@import 'tagmanager/tagmanager'
-@import 'font-awesome-sprockets'
-@import 'font-awesome'
-@import 'jquery-ui'
-@import 'formtastic'
-@import 'eonasdan-bootstrap-datetimepicker'
-@import 'footable'
-@import 'OpenLayers/ol'
-@import 'OpenLayers/custom'
-
-// Select2, themed w. Bootstrap
-@import 'select2'
-@import 'select2-bootstrap'
-
-@import 'vendor/openlayers_style'
-@import 'vendor/openlayers_ie6-style'
-@import 'vendor/openlayers_google'
-@import 'vendor/openlayers_framedCloud'
-@import 'vendor/formtastic_changes'
-@import 'vendor/pagination'
-@import 'vendor/map_layers'
-@import 'vendor/token-input'
-@import 'vendor/typeahead'
-@import 'vendor/bootstrap_changes'
-@import 'vendor/simple_form'
-// Select2
-@import 'vendor/select2'
-@import 'vendor/select2-bootstrap'
-
-// Main css
-@import 'main/*'
-
-// Components
-@import 'components/*'
-
-// Hack to make li simple
-li
- list-style: none
diff --git a/app/controllers/companies_controller.rb b/app/controllers/companies_controller.rb
index 07a732fc9..cf27c39cf 100644
--- a/app/controllers/companies_controller.rb
+++ b/app/controllers/companies_controller.rb
@@ -16,14 +16,13 @@ class CompaniesController < BreadcrumbController
redirect_to params.merge(:page => 1)
end
- @companies = ModelDecorator.decorate(
- @companies,
- with: CompanyDecorator,
- context: {
- referential: line_referential
- }
- )
+ @companies = decorate_companies(@companies)
}
+
+ format.json {
+ @companies = decorate_companies(@companies)
+ }
+
build_breadcrumb :index
end
end
@@ -77,4 +76,14 @@ class CompaniesController < BreadcrumbController
%w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
end
+ def decorate_companies(companies)
+ ModelDecorator.decorate(
+ companies,
+ with: CompanyDecorator,
+ context: {
+ referential: line_referential
+ }
+ )
+ end
+
end
diff --git a/app/controllers/networks_controller.rb b/app/controllers/networks_controller.rb
index d1f83340e..5dae1ba3f 100644
--- a/app/controllers/networks_controller.rb
+++ b/app/controllers/networks_controller.rb
@@ -37,14 +37,13 @@ class NetworksController < BreadcrumbController
redirect_to params.merge(:page => 1)
end
- @networks = ModelDecorator.decorate(
- @networks,
- with: NetworkDecorator,
- context: {
- line_referential: line_referential
- }
- )
+ @networks = decorate_networks(@networks)
}
+
+ format.js {
+ @networks = decorate_networks(@networks)
+ }
+
build_breadcrumb :index
end
end
@@ -87,4 +86,14 @@ class NetworksController < BreadcrumbController
%w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
end
+ def decorate_networks(networks)
+ ModelDecorator.decorate(
+ networks,
+ with: NetworkDecorator,
+ context: {
+ line_referential: line_referential
+ }
+ )
+ end
+
end
diff --git a/app/controllers/referential_companies_controller.rb b/app/controllers/referential_companies_controller.rb
index 53dde93bb..482f74ea0 100644
--- a/app/controllers/referential_companies_controller.rb
+++ b/app/controllers/referential_companies_controller.rb
@@ -14,14 +14,13 @@ class ReferentialCompaniesController < ChouetteController
redirect_to params.merge(:page => 1)
end
- @companies = ModelDecorator.decorate(
- @companies,
- with: CompanyDecorator,
- context: {
- referential: referential
- }
- )
+ @companies = decorate_companies(@companies)
}
+
+ format.js {
+ @companies = decorate_companies(@companies)
+ }
+
build_breadcrumb :index
end
end
@@ -70,4 +69,14 @@ class ReferentialCompaniesController < ChouetteController
%w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
end
+ def decorate_companies(companies)
+ ModelDecorator.decorate(
+ companies,
+ with: CompanyDecorator,
+ context: {
+ referential: referential
+ }
+ )
+ end
+
end
diff --git a/app/controllers/referential_networks_controller.rb b/app/controllers/referential_networks_controller.rb
index e0ce71ce4..ee2db8008 100644
--- a/app/controllers/referential_networks_controller.rb
+++ b/app/controllers/referential_networks_controller.rb
@@ -30,14 +30,13 @@ class ReferentialNetworksController < ChouetteController
redirect_to params.merge(:page => 1)
end
- @networks = ModelDecorator.decorate(
- @networks,
- with: ReferentialNetworkDecorator,
- context: {
- referential: referential
- }
- )
+ @networks = decorate_networks(@networks)
}
+
+ format.js {
+ @networks = decorate_networks(@networks)
+ }
+
build_breadcrumb :index
end
end
@@ -81,4 +80,14 @@ class ReferentialNetworksController < ChouetteController
%w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
end
+ def decorate_networks(networks)
+ ModelDecorator.decorate(
+ networks,
+ with: ReferentialNetworkDecorator,
+ context: {
+ referential: referential
+ }
+ )
+ end
+
end
diff --git a/app/controllers/referentials_controller.rb b/app/controllers/referentials_controller.rb
index 838c46168..afd376092 100644
--- a/app/controllers/referentials_controller.rb
+++ b/app/controllers/referentials_controller.rb
@@ -9,7 +9,7 @@ class ReferentialsController < BreadcrumbController
def new
if params[:from]
source_referential = Referential.find(params[:from])
- @referential = Referential.new_from(source_referential, organisation: current_organisation)
+ @referential = Referential.new_from(source_referential)
end
new! do
@@ -118,7 +118,7 @@ class ReferentialsController < BreadcrumbController
end
def create_resource(referential)
- referential.organisation = current_organisation unless referential.created_from
+ referential.organisation = current_organisation
referential.ready = true
super
end
diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb
index 20d500ea9..0054963c9 100644
--- a/app/controllers/time_tables_controller.rb
+++ b/app/controllers/time_tables_controller.rb
@@ -35,9 +35,9 @@ class TimeTablesController < ChouetteController
def create
tt_params = time_table_params
- if tt_params[:calendar_id]
+ if tt_params[:calendar_id] && tt_params[:calendar_id] != ""
%i(monday tuesday wednesday thursday friday saturday sunday).map { |d| tt_params[d] = true }
- calendar = current_organisation.calendars.find_by_id(tt_params[:calendar_id])
+ calendar = Calendar.find(tt_params[:calendar_id])
tt_params[:calendar_id] = nil if tt_params.has_key?(:dates_attributes) || tt_params.has_key?(:periods_attributes)
end
@@ -86,16 +86,14 @@ class TimeTablesController < ChouetteController
redirect_to params.merge(:page => 1)
end
- @time_tables = ModelDecorator.decorate(
- @time_tables,
- with: TimeTableDecorator,
- context: {
- referential: @referential
- }
- )
+ @time_tables = decorate_time_tables(@time_tables)
build_breadcrumb :index
}
+
+ format.js {
+ @time_tables = decorate_time_tables(@time_tables)
+ }
end
end
@@ -117,7 +115,8 @@ class TimeTablesController < ChouetteController
end
def tags
- @tags = ActsAsTaggableOn::Tag.where("tags.name = ?", "%#{params[:tag]}%")
+ # @tags = ActsAsTaggableOn::Tag.where("tags.name = ?", "%#{params[:tag]}%")
+ @tags = Chouette::TimeTable.tags_on(:tags)
respond_to do |format|
format.json { render :json => @tags.map{|t| {:id => t.id, :name => t.name }} }
end
@@ -195,6 +194,16 @@ class TimeTablesController < ChouetteController
Chouette::TimeTable.find(from_id) if from_id
end
+ def decorate_time_tables(time_tables)
+ ModelDecorator.decorate(
+ time_tables,
+ with: TimeTableDecorator,
+ context: {
+ referential: @referential
+ }
+ )
+ end
+
def time_table_params
params.require(:time_table).permit(
:objectid,
diff --git a/app/controllers/workbenches_controller.rb b/app/controllers/workbenches_controller.rb
index 22a71863a..19af28a98 100644
--- a/app/controllers/workbenches_controller.rb
+++ b/app/controllers/workbenches_controller.rb
@@ -2,7 +2,14 @@ class WorkbenchesController < BreadcrumbController
before_action :query_params, only: [:show]
defaults resource_class: Workbench
- respond_to :html, only: [:show]
+ respond_to :html, only: [:show, :index]
+
+ def index
+ # Only display Wb with selected name, according to #4108
+ @workbench = current_organisation.workbenches.find_by(name: "Gestion de l'offre")
+ @referentials = @workbench.all_referentials
+ @calendars = Calendar.where('organisation_id = ? OR shared = ?', current_organisation.id, true)
+ end
def show
scope = resource.all_referentials
diff --git a/app/helpers/breadcrumb_helper.rb b/app/helpers/breadcrumb_helper.rb
index 1f8690f38..55031d4f3 100644
--- a/app/helpers/breadcrumb_helper.rb
+++ b/app/helpers/breadcrumb_helper.rb
@@ -73,13 +73,13 @@ module BreadcrumbHelper
end
def calendar_breadcrumb(action)
- add_breadcrumb I18n.t('breadcrumbs.referentials'), referentials_path
+ add_breadcrumb I18n.t('breadcrumbs.referentials'), workbenches_path
add_breadcrumb I18n.t('calendars.index.title'), calendars_path
add_breadcrumb @calendar.name if %i(show edit).include? action
end
def workbench_breadcrumb(action)
- add_breadcrumb I18n.t("breadcrumbs.referentials"), referentials_path
+ add_breadcrumb I18n.t("breadcrumbs.referentials"), workbenches_path
add_breadcrumb breadcrumb_label(@workbench), workbench_path(@workbench), :title => breadcrumb_tooltip(@workbench)
end
@@ -215,7 +215,7 @@ module BreadcrumbHelper
end
def import_breadcrumb (action)
- add_breadcrumb I18n.t("breadcrumbs.referentials"), referentials_path
+ add_breadcrumb I18n.t("breadcrumbs.referentials"), workbenches_path
add_breadcrumb breadcrumb_label(@workbench), workbench_path(@workbench), :title => breadcrumb_tooltip(@workbench)
add_breadcrumb I18n.t("breadcrumbs.imports"), workbench_imports_path(@workbench)
@@ -257,7 +257,7 @@ module BreadcrumbHelper
end
def organisation_breadcrumb (action = :index)
- add_breadcrumb I18n.t("breadcrumbs.referentials"), referentials_path
+ add_breadcrumb I18n.t("breadcrumbs.referentials"), workbenches_path
add_breadcrumb breadcrumb_label(@organisation), organisation_path,:title => breadcrumb_tooltip(@organisation) unless action == :index
end
diff --git a/app/jobs/mailer_job.rb b/app/jobs/mailer_job.rb
index 761a29cd6..3918745b8 100644
--- a/app/jobs/mailer_job.rb
+++ b/app/jobs/mailer_job.rb
@@ -1,5 +1,5 @@
class MailerJob < ActiveJob::Base
- queue_as :mail
+ # No need to specify queue it's already used mailers queue
def perform klass, action, params
klass.constantize.public_send(action, *params).deliver_later
diff --git a/app/mailers/calendar_mailer.rb b/app/mailers/calendar_mailer.rb
index cc8175a07..e2a368c6c 100644
--- a/app/mailers/calendar_mailer.rb
+++ b/app/mailers/calendar_mailer.rb
@@ -1,11 +1,13 @@
class CalendarMailer < ApplicationMailer
- def updated calendar, user
- @calendar = calendar
+ def updated calendar_id, user_id
+ @calendar = Calendar.find(calendar_id)
+ user = User.find(user_id)
mail to: user.email, subject: t('mailers.calendar_mailer.updated.subject')
end
- def created calendar, user
- @calendar = calendar
+ def created calendar_id, user_id
+ @calendar = Calendar.find(calendar_id)
+ user = User.find(user_id)
mail to: user.email, subject: t('mailers.calendar_mailer.created.subject')
end
end
diff --git a/app/models/calendar_observer.rb b/app/models/calendar_observer.rb
index 789805356..c81addff4 100644
--- a/app/models/calendar_observer.rb
+++ b/app/models/calendar_observer.rb
@@ -4,7 +4,7 @@ class CalendarObserver < ActiveRecord::Observer
return unless calendar.shared
User.with_organisation.each do |user|
- MailerJob.perform_later('CalendarMailer', 'updated', [calendar, user])
+ MailerJob.perform_later('CalendarMailer', 'updated', [calendar.id, user.id])
end
end
@@ -12,7 +12,7 @@ class CalendarObserver < ActiveRecord::Observer
return unless calendar.shared
User.with_organisation.each do |user|
- MailerJob.perform_later('CalendarMailer', 'created', [calendar, user])
+ MailerJob.perform_later('CalendarMailer', 'created', [calendar.id, user.id])
end
end
end
diff --git a/app/models/chouette/line.rb b/app/models/chouette/line.rb
index 33a2fbb00..63d2d1606 100644
--- a/app/models/chouette/line.rb
+++ b/app/models/chouette/line.rb
@@ -1,5 +1,5 @@
class Chouette::Line < Chouette::ActiveRecord
- include DefaultNetexAttributesSupport
+ include StifCodifligneAttributesSupport
include LineRestrictions
include LineReferentialSupport
include StifTransportModeEnumerations
diff --git a/app/models/chouette/stif_codifligne_objectid.rb b/app/models/chouette/stif_codifligne_objectid.rb
new file mode 100644
index 000000000..46109e24f
--- /dev/null
+++ b/app/models/chouette/stif_codifligne_objectid.rb
@@ -0,0 +1,18 @@
+class Chouette::StifCodifligneObjectid < String
+
+ @@format = /^([A-Za-z_]+):([A-Za-z]+):([A-Za-z]+):([0-9A-Za-z_-]+)$/
+ cattr_reader :format
+
+ def parts
+ match(format).try(:captures)
+ end
+
+ def object_type
+ parts.try(:third)
+ end
+
+ def local_id
+ parts.try(:fourth)
+ end
+
+end
diff --git a/app/models/chouette/stif_reflex_objectid.rb b/app/models/chouette/stif_reflex_objectid.rb
new file mode 100644
index 000000000..c41a9325a
--- /dev/null
+++ b/app/models/chouette/stif_reflex_objectid.rb
@@ -0,0 +1,18 @@
+class Chouette::StifReflexObjectid < String
+
+ @@format = /^([A-Za-z_]+):([0-9A-Za-z_-]+):([A-Za-z]+):([0-9A-Za-z_-]+):([A-Za-z]+)$/
+ cattr_reader :format
+
+ def parts
+ match(format).try(:captures)
+ end
+
+ def object_type
+ parts.try(:third)
+ end
+
+ def local_id
+ parts.try(:fourth)
+ end
+
+end
diff --git a/app/models/chouette/stop_area.rb b/app/models/chouette/stop_area.rb
index 4d98027d6..43bc82f7f 100644
--- a/app/models/chouette/stop_area.rb
+++ b/app/models/chouette/stop_area.rb
@@ -4,20 +4,16 @@ require 'geo_ruby'
class Chouette::StopArea < Chouette::ActiveRecord
# FIXME http://jira.codehaus.org/browse/JRUBY-6358
self.primary_key = "id"
+
include Geokit::Mappable
+ include StifReflexAttributesSupport
include ProjectionFields
include StopAreaRestrictions
+ include StopAreaReferentialSupport
extend Enumerize
enumerize :area_type, in: %i(zdep zder zdlp zdlr lda)
- def self.model_name
- ActiveModel::Name.new self, Chouette, self.name.demodulize
- end
- # Refs #1627
- # include DefaultAttributesSupport
- include StopAreaReferentialSupport
-
with_options dependent: :destroy do |assoc|
assoc.has_many :stop_points
assoc.has_many :access_points
@@ -57,13 +53,6 @@ class Chouette::StopArea < Chouette::ActiveRecord
after_update :clean_invalid_access_links
before_save :coordinates_to_lat_lng
- # Refs #1627
- before_validation :prepare_auto_columns
- def prepare_auto_columns
- self.object_version = 1
- self.creator_id = 'chouette'
- end
-
def combine_lat_lng
if self.latitude.nil? || self.longitude.nil?
""
diff --git a/app/models/chouette/stop_point.rb b/app/models/chouette/stop_point.rb
index 3dbf6be0d..8fe79dc0c 100644
--- a/app/models/chouette/stop_point.rb
+++ b/app/models/chouette/stop_point.rb
@@ -36,12 +36,12 @@ module Chouette
def stop_area_id_validation
if stop_area_id.nil?
- errors.add(:stop_area_id, I18n.t("errors.messages.empty"))
+ errors.add(:stop_area_id, I18n.t("stop_areas.errors.empty"))
end
end
def self.area_candidates
- Chouette::StopArea.where( :area_type => ['Quay', 'BoardingPosition'])
+ Chouette::StopArea.where(:area_type => ['Quay', 'BoardingPosition'])
end
end
diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb
index d907d797e..713ce0b21 100644
--- a/app/models/chouette/time_table.rb
+++ b/app/models/chouette/time_table.rb
@@ -38,26 +38,26 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
validates_associated :periods
def continuous_dates
+ in_days = self.dates.where(in_out: true).sort_by(&:date)
chunk = {}
group = nil
- self.dates.where(in_out: true).each_with_index do |date, index|
+ in_days.each_with_index do |date, index|
group ||= index
- group = (date.date == dates[index - 1].date + 1.day) ? group : group + 1
+ group = (date.date == in_days[index - 1].date + 1.day) ? group : group + 1
chunk[group] ||= []
chunk[group] << date
end
- chunk.values
+ # Remove less than 2 continuous day chunk
+ chunk.values.delete_if {|dates| dates.count < 2}
end
def convert_continuous_dates_to_periods
chunks = self.continuous_dates
- # Remove less than 3 continuous day chunk
- chunks.delete_if {|chunk| chunk.count < 3}
transaction do
chunks.each do |chunk|
self.periods.create!(period_start: chunk.first.date, period_end: chunk.last.date)
- chunk.map(&:destroy)
+ self.dates.delete(chunk)
end
end
end
@@ -415,7 +415,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
def clone_periods
periods = []
self.periods.each { |p| periods << p.copy}
- periods
+ periods.sort_by(&:period_start)
end
def included_days
@@ -436,7 +436,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
# produce a copy of periods without anyone overlapping or including another
- def optimize_periods
+ def optimize_overlapping_periods
periods = self.clone_periods
optimized = []
i=0
@@ -461,6 +461,59 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
optimized.sort { |a,b| a.period_start <=> b.period_start}
end
+ def continuous_periods
+ periods = self.periods.sort_by(&:period_start)
+ chunk = {}
+ group = nil
+ periods.each_with_index do |period, index|
+ group ||= index
+ group = (period.period_start - 1.day == periods[index - 1].period_end) ? group : group + 1
+ chunk[group] ||= []
+ chunk[group] << period
+ end
+ chunk.values.delete_if {|periods| periods.count < 2}
+ end
+
+ def convert_continuous_periods_into_one
+ chunks = self.continuous_periods
+
+ transaction do
+ chunks.each do |chunk|
+ self.periods.create!(period_start: chunk.first.period_start, period_end: chunk.last.period_end)
+ self.periods.delete chunk
+ end
+ end
+ end
+
+ #update a period if a in_day is just before or after
+ def optimize_continuous_dates_and_periods
+ return self.periods if self.included_days.empty? || periods.empty?
+
+ periods = self.clone_periods
+ optimized = []
+
+ i = 0
+ while i < periods.length
+ period = periods[i]
+ j = 0
+ in_days = self.reload.dates.where(in_out: true).sort_by(&:date)
+ while j < in_days.length
+ day = in_days[j]
+ if period.period_start - 1.day === day.date
+ period.period_start = day.date
+ self.dates.delete day
+ elsif period.period_end + 1.day === day.date
+ period.period_end = day.date
+ self.dates.delete day
+ end
+ j += 1
+ end
+ i += 1
+ optimized << period
+ end
+ optimized
+ end
+
# add a peculiar day or switch it from excluded to included
def add_included_day(d)
if self.excluded_date?(d)
@@ -478,22 +531,27 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
def merge!(another_tt)
transaction do
self.periods = another_tt.clone_periods + self.periods
- self.periods = self.optimize_periods
# For included dates
another_tt.included_days.map{ |d| add_included_day(d) }
# For excluded dates
- existing_out_date = self.dates.where(in_out: false).map(&:date)
- another_tt.dates.where(in_out: false).each do |d|
- unless existing_out_date.include?(d.date)
- self.dates << Chouette::TimeTableDate.new(:date => d.date, :in_out => false)
+ self.dates.where(in_out: false).each do |d|
+ self.dates.delete d if another_tt.include_in_periods?(d.date) && !another_tt.excluded_date?(d.date)
+ end
+
+ another_tt.excluded_days.each do |d|
+ unless self.reload.excluded_date?(d)
+ self.dates << Chouette::TimeTableDate.new(date: d, in_out: false)
end
+ self.save!
end
- self.save!
- end
- self.convert_continuous_dates_to_periods
+ self.convert_continuous_dates_to_periods
+ self.periods = self.optimize_continuous_dates_and_periods
+ self.convert_continuous_periods_into_one
+ self.periods = self.optimize_overlapping_periods
+ end
end
def included_days_in_dates_and_periods
diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb
index 71c339780..bc2713973 100644
--- a/app/models/chouette/vehicle_journey.rb
+++ b/app/models/chouette/vehicle_journey.rb
@@ -23,7 +23,10 @@ module Chouette
validates_presence_of :route
validates_presence_of :journey_pattern
- validates :vehicle_journey_at_stops, :vjas_departure_time_must_be_before_next_stop_arrival_time,
+ validates :vehicle_journey_at_stops,
+ # Validation temporarily removed for day offsets
+ # :vjas_departure_time_must_be_before_next_stop_arrival_time,
+
vehicle_journey_at_stops_are_in_increasing_time_order: true
validates_presence_of :number
@@ -34,6 +37,12 @@ module Chouette
before_validation :set_default_values,
:calculate_vehicle_journey_at_stop_day_offset
+ # TODO: Remove this validator
+ # We've eliminated this validation because it prevented vehicle journeys
+ # from being saved with at-stops having a day offset greater than 0,
+ # because these would have times that were "earlier" than the previous
+ # at-stop. TBD by Luc whether we're deleting this validation altogether or
+ # instead rejiggering it to work with day offsets.
def vjas_departure_time_must_be_before_next_stop_arrival_time
notice = 'departure time must be before next stop arrival time'
vehicle_journey_at_stops.each_with_index do |current_stop, index|
@@ -142,7 +151,7 @@ module Chouette
vj.update_attributes(state_permited_attributes(item))
vj.update_has_and_belongs_to_many_from_state(item)
- item['errors'] = vj.errors if vj.errors.any?
+ item['errors'] = vj.errors.full_messages.uniq if vj.errors.any?
end
# Delete ids of new object from state if we had to rollback
diff --git a/app/models/chouette/vehicle_journey_at_stop.rb b/app/models/chouette/vehicle_journey_at_stop.rb
index 5dfec8352..35d94aa75 100644
--- a/app/models/chouette/vehicle_journey_at_stop.rb
+++ b/app/models/chouette/vehicle_journey_at_stop.rb
@@ -3,6 +3,8 @@ module Chouette
include ForBoardingEnumerations
include ForAlightingEnumerations
+ DAY_OFFSET_MAX = 1
+
# FIXME http://jira.codehaus.org/browse/JRUBY-6358
self.primary_key = "id"
@@ -24,11 +26,46 @@ module Chouette
end
end
+ validate :day_offset_must_be_within_range
+
after_initialize :set_virtual_attributes
def set_virtual_attributes
@_destroy = false
@dummy = false
end
+ def day_offset_must_be_within_range
+ if day_offset_outside_range?(arrival_day_offset)
+ errors.add(
+ :arrival_day_offset,
+ I18n.t(
+ 'vehicle_journey_at_stops.errors.day_offset_must_not_exceed_max',
+ local_id: vehicle_journey.objectid.local_id,
+ max: DAY_OFFSET_MAX + 1
+ )
+ )
+ end
+
+ if day_offset_outside_range?(departure_day_offset)
+ errors.add(
+ :departure_day_offset,
+ I18n.t(
+ 'vehicle_journey_at_stops.errors.day_offset_must_not_exceed_max',
+ local_id: vehicle_journey.objectid.local_id,
+ max: DAY_OFFSET_MAX + 1
+ )
+ )
+ end
+ end
+
+ def day_offset_outside_range?(offset)
+ # At-stops that were created before the database-default of 0 will have
+ # nil offsets. Handle these gracefully by forcing them to a 0 offset.
+ offset ||= 0
+
+ offset < 0 || offset > DAY_OFFSET_MAX
+ end
+
+
end
end
diff --git a/app/models/clean_up.rb b/app/models/clean_up.rb
index cdbf6c00a..b1135a155 100644
--- a/app/models/clean_up.rb
+++ b/app/models/clean_up.rb
@@ -14,7 +14,7 @@ class CleanUp < ActiveRecord::Base
def end_date_must_be_greater_that_begin_date
if self.end_date && self.date_type == 'between' && self.begin_date >= self.end_date
- errors.add(:base, I18n.t('clean_ups.activerecord.errors.invalid_period'))
+ errors.add(:base, I18n.t('activerecord.errors.models.clean_up.invalid_period'))
end
end
diff --git a/app/models/concerns/default_attributes_support.rb b/app/models/concerns/default_attributes_support.rb
index 7928093e6..e85a59160 100644
--- a/app/models/concerns/default_attributes_support.rb
+++ b/app/models/concerns/default_attributes_support.rb
@@ -77,7 +77,8 @@ module DefaultAttributesSupport
def build_objectid
if objectid.include? ':__pending_id__'
fix_uniq_objectid
- update_attributes( :objectid => objectid, :object_version => (object_version - 1) )
+ self.object_version = object_version - 1
+ self.save(validate: false)
end
end
diff --git a/app/models/concerns/stif_codifligne_attributes_support.rb b/app/models/concerns/stif_codifligne_attributes_support.rb
new file mode 100644
index 000000000..d4370e505
--- /dev/null
+++ b/app/models/concerns/stif_codifligne_attributes_support.rb
@@ -0,0 +1,21 @@
+module StifCodifligneAttributesSupport
+ extend ActiveSupport::Concern
+
+ included do
+ validates_presence_of :objectid
+ end
+
+ module ClassMethods
+ def object_id_key
+ model_name
+ end
+
+ def model_name
+ ActiveModel::Name.new self, Chouette, self.name.demodulize
+ end
+ end
+
+ def objectid
+ Chouette::StifCodifligneObjectid.new read_attribute(:objectid).to_s
+ end
+end
diff --git a/app/models/concerns/stif_reflex_attributes_support.rb b/app/models/concerns/stif_reflex_attributes_support.rb
new file mode 100644
index 000000000..e6236a146
--- /dev/null
+++ b/app/models/concerns/stif_reflex_attributes_support.rb
@@ -0,0 +1,21 @@
+module StifReflexAttributesSupport
+ extend ActiveSupport::Concern
+
+ included do
+ validates_presence_of :objectid
+ end
+
+ module ClassMethods
+ def object_id_key
+ model_name
+ end
+
+ def model_name
+ ActiveModel::Name.new self, Chouette, self.name.demodulize
+ end
+ end
+
+ def objectid
+ Chouette::StifReflexObjectid.new read_attribute(:objectid).to_s
+ end
+end
diff --git a/app/models/referential.rb b/app/models/referential.rb
index ed23e2e51..cb2c7b23b 100644
--- a/app/models/referential.rb
+++ b/app/models/referential.rb
@@ -130,14 +130,13 @@ class Referential < ActiveRecord::Base
self
end
- def self.new_from(from, organisation:)
+ def self.new_from(from)
Referential.new(
name: I18n.t("activerecord.copy", :name => from.name),
slug: "#{from.slug}_clone",
prefix: from.prefix,
time_zone: from.time_zone,
bounds: from.bounds,
- organisation: organisation,
line_referential: from.line_referential,
stop_area_referential: from.stop_area_referential,
workbench: from.workbench,
@@ -186,7 +185,7 @@ class Referential < ActiveRecord::Base
before_validation :clone_associations, :on => :create, if: :created_from
before_validation :assign_slug, :on => :create
before_validation :assign_prefix, :on => :create
- before_create :create_schema, unless: :created_from
+ before_create :create_schema
after_create :clone_schema, if: :created_from
@@ -206,7 +205,6 @@ class Referential < ActiveRecord::Base
end
def clone_associations
- self.organisation = created_from.organisation
self.line_referential = created_from.line_referential
self.stop_area_referential = created_from.stop_area_referential
self.workbench = created_from.workbench
diff --git a/app/models/user.rb b/app/models/user.rb
index 64d66883f..c2aa14bda 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -29,29 +29,6 @@ class User < ActiveRecord::Base
scope :with_organisation, -> { where.not(organisation_id: nil) }
- def self.destructive_permissions_for(models)
- models.product( %w{create destroy update} ).map{ |model_action| model_action.join('.') }
- end
-
- @@edit_offer_permissions =
- destructive_permissions_for( %w[
- access_points
- connection_links
- calendars
- footnotes
- journey_patterns
- referentials
- routes
- routing_constraint_zones
- time_tables
- vehicle_journeys
- ]) << 'boiv:edit-offer'
-
- mattr_reader :edit_offer_permissions
-
- def self.all_permissions
- edit_offer_permissions
- end
# Callback invoked by DeviseCasAuthenticable::Model#authernticate_with_cas_ticket
def cas_extra_attributes=(extra_attributes)
@@ -59,7 +36,7 @@ class User < ActiveRecord::Base
self.name = extra[:full_name]
self.email = extra[:email]
self.organisation = Organisation.sync_update extra[:organisation_code], extra[:organisation_name], extra[:functional_scope]
- self.permissions = extra[:permissions].include?('boiv:edit-offer') ? @@edit_offer_permissions : []
+ self.permissions = Stif::PermissionTranslator.translate(extra[:permissions])
end
def self.portail_api_request
@@ -87,7 +64,7 @@ class User < ActiveRecord::Base
user.locked_at = el['locked_at']
user.organisation = Organisation.sync_update el['organization_code'], el['organization_name'], el['functional_scope']
user.synced_at = Time.now
- user.permissions = el['permissions'].include?('boiv:edit-offer') ? @@edit_offer_permissions : []
+ user.permissions = Stif::PermissionTranslator.translate(el['permissions'])
user.save
end
end
diff --git a/app/policies/login_policy.rb b/app/policies/login_policy.rb
index 3364c37ac..5b07b97f3 100644
--- a/app/policies/login_policy.rb
+++ b/app/policies/login_policy.rb
@@ -7,7 +7,7 @@ class LoginPolicy
end
def boiv?
- !(user.permissions || []).grep(%r{\Aboiv:.}).empty?
+ (user.permissions || []).include?('sessions:create')
end
end
diff --git a/app/policies/referential_policy.rb b/app/policies/referential_policy.rb
index 9d0a92093..fdc80516c 100644
--- a/app/policies/referential_policy.rb
+++ b/app/policies/referential_policy.rb
@@ -20,7 +20,7 @@ class ReferentialPolicy < ApplicationPolicy
def clone?
- !archived? && organisation_match? && create?
+ !archived? && create?
end
def archive?
@@ -37,7 +37,3 @@ class ReferentialPolicy < ApplicationPolicy
end
end
-
-
-
-
diff --git a/app/views/compliance_checks/detailed_errors_index.csv.slim b/app/views/compliance_checks/detailed_errors_index.csv.slim
index 0b2c3f24f..7fe20e282 100644
--- a/app/views/compliance_checks/detailed_errors_index.csv.slim
+++ b/app/views/compliance_checks/detailed_errors_index.csv.slim
@@ -29,7 +29,7 @@
= error["source"]["file"]["line_number"]
- else
- = I18n.t("activemodel.attributes.compliance_check_result."+r.test_id);
+ = I18n.t("activemodel.attributes.compliance_check_result.#{r.test_id}");
= I18n.t("compliance_check_result.details.detail_#{error['error_id']}", object_labels_hash(error) )
= "\n"
diff --git a/app/views/compliance_checks/summary_errors_index.csv.slim b/app/views/compliance_checks/summary_errors_index.csv.slim
index bbb2c8c88..8c88d5cf6 100644
--- a/app/views/compliance_checks/summary_errors_index.csv.slim
+++ b/app/views/compliance_checks/summary_errors_index.csv.slim
@@ -16,7 +16,7 @@
= r.result;
= r.test_id;
- = I18n.t("activemodel.attributes.compliance_check_result." + r.test_id);
+ = I18n.t("activemodel.attributes.compliance_check_result.#{r.test_id}");
= Rails.application.config.validation_spec + I18n.locale.to_s + "/" + r.test_id + ".html";
= r.error_count
diff --git a/app/views/layouts/navigation/_main_nav_left.html.slim b/app/views/layouts/navigation/_main_nav_left.html.slim
index 3cf6428af..9dfc828c0 100644
--- a/app/views/layouts/navigation/_main_nav_left.html.slim
+++ b/app/views/layouts/navigation/_main_nav_left.html.slim
@@ -16,7 +16,7 @@
#miOne.panel-collapse.collapse
.list-group
- = link_to root_path, class: "list-group-item #{(@localizationUrl == 'referentials#index') ? 'active' : ''}" do
+ = link_to root_path, class: "list-group-item #{(@localizationUrl == 'workbenches#index') ? 'active' : ''}" do
span Tableau de bord
= link_to '#', class: 'list-group-item' do
span Offre de mon organisation
diff --git a/app/views/referential_stop_areas/index.html.slim b/app/views/referential_stop_areas/index.html.slim
index 1cbe1945f..7bf39eabd 100644
--- a/app/views/referential_stop_areas/index.html.slim
+++ b/app/views/referential_stop_areas/index.html.slim
@@ -4,7 +4,7 @@
.panel.panel-default
.panel-heading
.input-group.col-md-9.col-sm-9
- = f.text_field :name_or_objectid_cont, placeholder: t('.name_or_objectid'), class: 'form-control'
+ = f.text_field :name_or_objectid_cont, placeholder: t('stop_areas.filters.name_or_objectid'), class: 'form-control'
.input-group-btn
button.btn.btn-primary#search-btn type="submit"
span.fa.fa-search
diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim
index d3687c3a7..425f8014a 100644
--- a/app/views/referentials/show.html.slim
+++ b/app/views/referentials/show.html.slim
@@ -91,9 +91,13 @@
.row
.col-lg-8.col-ld-offset-2.col-md-8.col-md-offset-2.col-sm-8.col-sm-offset-2.col-xs-12
= f.input :date_type, as: :radio_buttons, label: false
- = f.input :begin_date, as: :date, label: t('titles.clean_up.begin_date'),:wrapper_html => { class: 'date smart_date', title: t('titles.clean_up.begin_date') }
- = f.input :end_date, as: :date, label: t('titles.clean_up.end_date'), :wrapper_html => { class: 'date cleanup_end_date_wrapper smart_date', title: t('titles.clean_up.end_date'), id: "end_date" }
+ .col-lg-8.col-ld-offset-2.col-md-8.col-md-offset-2.col-sm-8.col-sm-offset-2.col-xs-12
+ label.control-label.begin_date = t('titles.clean_up.begin_date')
+ label.control-label.end_date.hidden = t('titles.clean_up.end_date')
+ = f.input :begin_date, as: :date, label: false, wrapper_html: { class: 'date smart_date' }
+
+ = f.input :end_date, as: :date, label: t('titles.clean_up.end_date'), wrapper_html: { class: 'date cleanup_end_date_wrapper smart_date', id: "end_date" }
.modal-footer
button.btn.btn-link type='button' data-dismiss='modal' Annuler
diff --git a/app/views/stop_area_copies/new.html.slim b/app/views/stop_area_copies/new.html.slim
index 1a8764cbc..b506d35f4 100644
--- a/app/views/stop_area_copies/new.html.slim
+++ b/app/views/stop_area_copies/new.html.slim
@@ -1,4 +1,4 @@
-= title_tag t("stop_area_copies.new.title."+@stop_area_copy.hierarchy)
+= title_tag t("stop_area_copies.new.title.#{@stop_area_copy.hierarchy}")
= semantic_form_for [@referential, @stop_area, @stop_area_copy] do |form|
br
diff --git a/app/views/time_tables/_filter.html.slim b/app/views/time_tables/_filter.html.slim
index 1015eca31..392dc4f50 100644
--- a/app/views/time_tables/_filter.html.slim
+++ b/app/views/time_tables/_filter.html.slim
@@ -7,10 +7,6 @@
span.fa.fa-search
.ffg-row
- / .form-group.togglable
- / = f.label Chouette::TimeTable.human_attribute_name(:color), required: false, class: 'control-label'
- / = f.input :color_cont_any, collection: ["#9B9B9B", "#FFA070", "#C67300", "#7F551B", "#41CCE3", "#09B09C", "#3655D7", "#6321A0", "#E796C6", "#DD2DAA"], as: :check_boxes, label: false, label_method: lambda{|tt| ("<span style='height:19px;'><span class='fa fa-circle' style='position:relative;top:0;margin-top:0;color:" + tt + "'></span></span>").html_safe }, required: false, wrapper_html: { class: 'checkbox_list' }
-
.form-group
= f.label Chouette::TimeTable.human_attribute_name(:tag_search), required: false, class: 'control-label'
= f.input :tag_search, as: :tags, collection: Chouette::TimeTable.tags_on(:tags).pluck(:name), label: false, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Indiquez une étiquette...' }, wrapper_html: { class: 'select2ed'}, include_blank: false
diff --git a/app/views/time_tables/time_tables.json.rabl b/app/views/time_tables/time_tables.json.rabl
index dec29cb69..b91ca9ae9 100644
--- a/app/views/time_tables/time_tables.json.rabl
+++ b/app/views/time_tables/time_tables.json.rabl
@@ -2,4 +2,4 @@ collection @time_tables, :object_root => false
node do |time_table|
{ :id => time_table.id, :comment => time_table.comment, :time_table_bounding => time_table_bounding( time_table), :composition_info => composition_info(time_table) }
-end
+end
diff --git a/app/views/workbenches/index.html.slim b/app/views/workbenches/index.html.slim
new file mode 100644
index 000000000..ca61d439d
--- /dev/null
+++ b/app/views/workbenches/index.html.slim
@@ -0,0 +1,67 @@
+/ PageHeader
+= pageheader 'map-marker',
+ t('.title', organisation: current_organisation.name)
+
+/ PageContent
+.page_content
+ .container-fluid
+ .row
+ .col-lg-12
+ h2.content_header = t('.offers.title')
+
+ .row
+ .col-lg-6.col-md-6.col-sm-6.col-xs-12
+ .panel.panel-default
+ .panel-heading
+ h3.panel-title
+ = t('.offers.organisation')
+
+ .panel-body
+ em.small.text-muted = t('.offers.no_content')
+
+ .panel.panel-default
+ .panel-heading
+ h3.panel-title
+ = t('.offers.idf')
+
+ .panel-body
+ em.small.text-muted = t('.offers.no_content')
+
+ .col-lg-6.col-md-6.col-sm-6.col-xs-12
+ .panel.panel-default
+ .panel-heading
+ h3.panel-title.with_actions
+ div
+ = t('.offers.referentials')
+ span.badge.ml-xs = @referentials.count if @referentials.any?
+
+ div
+ = link_to '', workbench_path(@workbench), class: ' fa fa-chevron-right pull-right', title: t('.offers.see')
+
+ - if @referentials.any?
+ .list-group
+ - @referentials.each_with_index do |referential, i|
+ = link_to referential.name, referential_path(referential), class: 'list-group-item' if i < 6
+
+ - else
+ .panel-body
+ em.small.text-muted = t('.offers.no_content')
+
+ .panel.panel-default
+ .panel-heading
+ h3.panel-title.with_actions
+ div
+ = t('.offers.calendars')
+ span.badge.ml-xs = @calendars.count if @calendars.any?
+
+ div
+ = link_to '', calendars_path, class: ' fa fa-chevron-right pull-right', title: t('.offers.see')
+
+ - if @calendars.any?
+ .list-group
+ - @calendars.each_with_index do |calendar, i|
+ = link_to calendar.name, calendar_path(calendar), class: 'list-group-item' if i < 6
+
+ - else
+ .panel-body
+ em.small.text-muted = t('.offers.no_content')
diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim
index bb8b71ab2..a9ce2f704 100644
--- a/app/views/workbenches/show.html.slim
+++ b/app/views/workbenches/show.html.slim
@@ -7,8 +7,8 @@
/ Below is secundary actions & optional contents (filters, ...)
.row.mb-sm
.col-lg-12.text-right
- = link_to t('actions.import'), workbench_imports_path(@workbench), class: 'btn btn-primary'
- if policy(Referential).create?
+ = link_to t('actions.import'), workbench_imports_path(@workbench), class: 'btn btn-primary'
= link_to t('actions.add'), new_referential_path(workbench_id: @workbench), class: 'btn btn-primary'
/ PageContent
diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml
index 88c02341b..19a919cc2 100644
--- a/config/i18n-tasks.yml
+++ b/config/i18n-tasks.yml
@@ -1,9 +1,9 @@
# i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks
# The "main" locale.
-base_locale: en
+base_locale: fr
## All available locales are inferred from the data by default. Alternatively, specify them explicitly:
-# locales: [es, fr]
+locales: [en, fr]
## Reporting locale, default: en. Available: en, ru.
# internal_locale: en
@@ -18,7 +18,6 @@ data:
## Default:
- config/locales/%{locale}.yml
## More files:
- - config/locales/*.%{locale}.yml
- config/locales/**/*.%{locale}.yml
## Another gem (replace %#= with %=):
# - "<%#= %x[bundle show vagrant].chomp %>/templates/locales/%{locale}.yml"
@@ -27,13 +26,12 @@ data:
# `i18n-tasks normalize -p` will force move the keys according to these rules
write:
## For example, write devise and simple form keys to their respective files:
- - ['{devise}.*', 'config/locales/devise.%{locale}.yml']
- - ['{simple_form}.*', 'config/locales/simple_form.%{locale}.yml']
+ - ['{devise, simple_form}.*', 'config/locales/\1.%{locale}.yml']
## Catch-all default:
- config/locales/%{locale}.yml
## Specify the router (see Readme for details). Valid values: conservative_router, pattern_router, or a custom class.
- # router: convervative_router
+ # router: conservative_router
yaml:
write:
@@ -68,13 +66,18 @@ search:
- app/assets/images
- app/assets/fonts
- app/assets/javascripts
+ - app/assets/videos
## Alternatively, the only files or `File.fnmatch patterns` to search in `paths`:
## If specified, this settings takes priority over `exclude`, but `exclude` still applies.
- # include: ["*.rb", "*.html.slim"]
+ # only: ["*.rb", "*.html.slim"]
- ## Default scanner finds t() and I18n.t() calls.
- # scanner: I18n::Tasks::Scanners::PatternWithScopeScanner
+ ## If `strict` is `false`, guess usages such as t("categories.#{category}.title"). The default is `true`.
+ # strict: true
+
+ ## Multiple scanners can be used. Their results are merged.
+ ## The options specified above are passed down to each scanner. Per-scanner options can be specified as well.
+ ## See this example of a custom scanner: https://github.com/glebm/i18n-tasks/wiki/A-custom-scanner-example
## Google Translate
# translation:
@@ -104,3 +107,16 @@ search:
## Ignore these keys completely:
# ignore:
# - kaminari.*
+
+## Sometimes, it isn't possible for i18n-tasks to match the key correctly,
+## e.g. in case of a relative key defined in a helper method.
+## In these cases you can use the built-in PatternMapper to map patterns to keys, e.g.:
+#
+# <%# I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
+# only: %w(*.html.haml *.html.slim),
+# patterns: [['= title\b', '.page_title']] %>
+#
+# The PatternMapper can also match key literals via a special %{key} interpolation, e.g.:
+#
+# <%# I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
+# patterns: [['\bSpree\.t[( ]\s*%{key}', 'spree.%{key}']] %>
diff --git a/config/locales/actions.en.yml b/config/locales/actions.en.yml
index cffd04fcf..f6979136a 100644
--- a/config/locales/actions.en.yml
+++ b/config/locales/actions.en.yml
@@ -4,6 +4,7 @@ en:
destroy: "Destroy"
delete: "Delete"
search: "Search"
+ submit: "Submit"
add: "Add new"
new: "Add new"
show: "See"
diff --git a/config/locales/calendars.en.yml b/config/locales/calendars.en.yml
index f6c5ba852..cb1ede4c7 100644
--- a/config/locales/calendars.en.yml
+++ b/config/locales/calendars.en.yml
@@ -9,6 +9,19 @@ en:
friday: F
saturday: Sa
sunday: Su
+ months:
+ 1: January
+ 2: February
+ 3: March
+ 4: April
+ 5: May
+ 6: June
+ 7: July
+ 8: August
+ 9: September
+ 10: October
+ 11: November
+ 12: December
standard_calendars: Standard calendars
standard_calendar: Standard calendar
actions:
diff --git a/config/locales/clean_ups.en.yml b/config/locales/clean_ups.en.yml
index a05750f6d..fcfcfec7b 100644
--- a/config/locales/clean_ups.en.yml
+++ b/config/locales/clean_ups.en.yml
@@ -24,9 +24,9 @@ en:
end_date: "End date of clean up"
activerecord:
errors:
- invalid_period: "Invalid period : the end date must be strictly greater than the begin date"
models:
clean_up:
+ invalid_period: "Invalid period : the end date must be strictly greater than the begin date"
attributes:
date_type:
presence: "A clean up must have a date type"
diff --git a/config/locales/clean_ups.fr.yml b/config/locales/clean_ups.fr.yml
index 77e07591b..e2db82998 100644
--- a/config/locales/clean_ups.fr.yml
+++ b/config/locales/clean_ups.fr.yml
@@ -23,9 +23,9 @@ fr:
end_date: "Date de fin de la purge"
activerecord:
errors:
- invalid_period: "Période invalide : tLa date de fin doit être strictement supérieure à la date de début"
models:
clean_up:
+ invalid_period: "Période invalide : La date de fin doit être strictement supérieure à la date de début"
attributes:
date_type:
presence: "Une purge doit avoir un type de renseigné"
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 0a6002175..b25f5fd7f 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -14,6 +14,38 @@ en:
formats:
short: "%Y/%m/%d"
short_with_time: "%Y/%m/%d at %Hh%M"
+ abbr_day_names:
+ - Sun
+ - Mon
+ - Tue
+ - Wed
+ - Thu
+ - Fri
+ - Sat
+ day_names:
+ - Sunday
+ - Monday
+ - Tuesday
+ - Wednesday
+ - Thursday
+ - Friday
+ - Saturday
+ month_names:
+ -
+ - January
+ - February
+ - March
+ - April
+ - May
+ - June
+ - July
+ - August
+ - September
+ - October
+ - November
+ - December
+ errors:
+ format: "%{message}"
last_update: 'Last update on<br>%{time}'
last_sync: 'Last sync on %{time}'
diff --git a/config/locales/enumerize.en.yml b/config/locales/enumerize.en.yml
index f76237288..0bc3e5edc 100644
--- a/config/locales/enumerize.en.yml
+++ b/config/locales/enumerize.en.yml
@@ -114,6 +114,7 @@ en:
transport_mode:
interchange: Interchange
unknown: "unknown"
+ undefined: "undefined"
air: "Air"
train: "Train"
long_distance_train: "Long distance train"
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 3d5dc4c2c..8ef183d91 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -14,6 +14,36 @@ fr:
formats:
short: "%d/%m/%Y"
short_with_time: "%d/%m/%Y à %Hh%M"
+ abbr_day_names:
+ - dim
+ - lun
+ - mar
+ - mer
+ - jeu
+ - ven
+ - sam
+ day_names:
+ - dimanche
+ - lundi
+ - mardi
+ - mercredi
+ - jeudi
+ - vendredi
+ - samedi
+ month_names:
+ -
+ - janvier
+ - février
+ - mars
+ - avril
+ - mai
+ - juin
+ - juillet
+ - août
+ - septembre
+ - octobre
+ - novembre
+ - décembre
errors:
format: "%{message}"
@@ -25,3 +55,4 @@ fr:
id_codif: 'ID Codifligne'
id_reflex: 'ID Reflex'
+ objectid: 'ID'
diff --git a/config/locales/imports.en.yml b/config/locales/imports.en.yml
index a5eb0f969..b20f0f1da 100644
--- a/config/locales/imports.en.yml
+++ b/config/locales/imports.en.yml
@@ -7,6 +7,8 @@ en:
index:
title: "Imports"
warning: ""
+ new:
+ title: "Imports"
show:
report: "Report"
imported_file: "Original file"
diff --git a/config/locales/imports.fr.yml b/config/locales/imports.fr.yml
index 8fe8817f5..933025c82 100644
--- a/config/locales/imports.fr.yml
+++ b/config/locales/imports.fr.yml
@@ -7,6 +7,8 @@ fr:
index:
title: "Imports"
warning: ""
+ new:
+ title: "Imports"
show:
report: "Rapport"
imported_file: "Fichier source"
diff --git a/config/locales/mailers.en.yml b/config/locales/mailers.en.yml
index d4bd45129..9f89c9d46 100644
--- a/config/locales/mailers.en.yml
+++ b/config/locales/mailers.en.yml
@@ -4,6 +4,6 @@ en:
created:
subject: A new shared calendar has been created
body: A new shared calendar% {cal_name} has been added by STIF. You can now view it in the list of shared calendars %{cal_index_url}
- created:
+ updated:
subject: A shared calendar has been updated
body: A new shared calendar% {cal_name} has been updated by STIF. You can now view it in the list of shared calendars %{cal_index_url}
diff --git a/config/locales/referentials.en.yml b/config/locales/referentials.en.yml
index 7a4c60869..5f39f03f4 100644
--- a/config/locales/referentials.en.yml
+++ b/config/locales/referentials.en.yml
@@ -1,6 +1,6 @@
en:
referentials:
- filter:
+ filters:
name_or_number_or_objectid: 'Search by name, number or objectid'
search_no_results: 'No data space matching your query'
index:
@@ -41,6 +41,7 @@ en:
user_excluded: "%{user} is a reserved value"
overlapped_referential: "%{referential} cover the same perimeter"
overlapped_period: "Another period is on the same period"
+ short_period: Min period length is two days
activerecord:
models:
referential:
diff --git a/config/locales/routes.en.yml b/config/locales/routes.en.yml
index d8160772f..3099d4ab1 100644
--- a/config/locales/routes.en.yml
+++ b/config/locales/routes.en.yml
@@ -84,9 +84,3 @@ en:
hub:
route:
objectid: "[prefix]:Route:[unique_key] : prefix contains only alphanumerical or underscore characters, unique_key accepts also minus character. Maximum length of the unique key = 8."
-
- # simpleform
- helpers:
- submit:
- route:
- create: 'Create route'
diff --git a/config/locales/routing_constraint_zones.en.yml b/config/locales/routing_constraint_zones.en.yml
index 59d4484a8..836705a6a 100644
--- a/config/locales/routing_constraint_zones.en.yml
+++ b/config/locales/routing_constraint_zones.en.yml
@@ -24,9 +24,6 @@ en:
routing_constraint_zones:
search_no_results: "No ITL matches your query"
actions:
- new: New routing constraint zone
- edit: Edit this routing constraint zone
- destroy: Delete this routing constraint zone
destroy_confirm: Are you sure you want to delete this routing constraint zone?
new:
title: Add a new routings constraint zone
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index f6c0079ee..ad722312e 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -7,21 +7,11 @@ en:
required:
text: 'Required field'
mark: '*'
- # You can uncomment the line below if you need to overwrite the whole required html.
- # When using html, text and mark won't be used.
- # html: '<abbr title="required">*</abbr>'
error_notification:
default_message: "Please review the problems below:"
- # Labels and hints examples
- # labels:
- # defaults:
- # password: 'Password'
- # user:
- # new:
- # email: 'E-mail to sign in.'
- # edit:
- # email: 'E-mail.'
- # hints:
- # defaults:
- # username: 'User name to sign in.'
- # password: 'No special characters, please.'
+
+ helpers:
+ submit:
+ create: Submit
+ edit: Edit
+ update: Edit
diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml
index 2a6893595..cd5dd1fbe 100644
--- a/config/locales/simple_form.fr.yml
+++ b/config/locales/simple_form.fr.yml
@@ -15,16 +15,3 @@ fr:
create: Valider
edit: Editer
update: Editer
- # Labels and hints examples
- # labels:
- # defaults:
- # password: 'Password'
- # user:
- # new:
- # email: 'E-mail to sign in.'
- # edit:
- # email: 'E-mail.'
- # hints:
- # defaults:
- # username: 'User name to sign in.'
- # password: 'No special characters, please.'
diff --git a/config/locales/stop_areas.en.yml b/config/locales/stop_areas.en.yml
index 3d6b65350..324294892 100644
--- a/config/locales/stop_areas.en.yml
+++ b/config/locales/stop_areas.en.yml
@@ -1,6 +1,8 @@
en:
stop_areas: &en_stop_areas
search_no_results: "No stop area matching your query"
+ errors:
+ empty: Aucun stop_area_id
default_geometry_success: "%{count} modified stop areas"
stop_area:
no_position: "No Position"
@@ -90,6 +92,7 @@ en:
registration_number: "Registration number"
published_name: "Published name"
deleted: "Deleted"
+ deleted_at: "Deleted at"
comment: "Description"
stop_area_type: "Area type"
area_type: "Area type"
@@ -179,5 +182,6 @@ en:
comment: "Maximum length = 255."
coordinates: "Coordinates are mandatory."
projection_xy: "x,y in secondary referential, dot for decimal separator"
+
referential_stop_areas:
<<: *en_stop_areas
diff --git a/config/locales/stop_areas.fr.yml b/config/locales/stop_areas.fr.yml
index 3e49cdf7c..216516e5b 100644
--- a/config/locales/stop_areas.fr.yml
+++ b/config/locales/stop_areas.fr.yml
@@ -1,6 +1,8 @@
fr:
stop_areas: &fr_stop_areas
search_no_results: "Aucun arrêt ne correspond à votre recherche"
+ errors:
+ empty: Aucun stop_area_id
default_geometry_success: "%{count} arrêts édités"
stop_area:
no_position: "Pas de position"
@@ -14,6 +16,7 @@ fr:
new: "Ajouter un arrêt"
edit: "Editer cet arrêt"
destroy: "Supprimer cet arrêt"
+ deleted_at: "Activé"
destroy_confirm: "Etes vous sûr de supprimer cet arrêt ainsi que tous ses fils?"
select_parent: "Créer ou éditer la relation enfant -> parent"
add_children: "Créer ou éditer la relation parent -> enfants"
diff --git a/config/locales/time_tables.en.yml b/config/locales/time_tables.en.yml
index dc6c6d9f4..24750f0af 100644
--- a/config/locales/time_tables.en.yml
+++ b/config/locales/time_tables.en.yml
@@ -24,6 +24,8 @@ en:
success: "Actualize succeded"
new:
title: "Add a new timetable"
+ duplicate:
+ title: "Duplicate timetable"
edit:
title: "Update timetable %{time_table}"
show:
diff --git a/config/locales/vehicle_journey_at_stops.en.yml b/config/locales/vehicle_journey_at_stops.en.yml
new file mode 100644
index 000000000..a96effa2b
--- /dev/null
+++ b/config/locales/vehicle_journey_at_stops.en.yml
@@ -0,0 +1,4 @@
+en:
+ vehicle_journey_at_stops:
+ errors:
+ day_offset_must_not_exceed_max: "The vehicle journey with ID %{local_id} cannot have times exceeding %{max} days"
diff --git a/config/locales/vehicle_journey_at_stops.fr.yml b/config/locales/vehicle_journey_at_stops.fr.yml
new file mode 100644
index 000000000..3eff79cf4
--- /dev/null
+++ b/config/locales/vehicle_journey_at_stops.fr.yml
@@ -0,0 +1,4 @@
+fr:
+ vehicle_journey_at_stops:
+ errors:
+ day_offset_must_not_exceed_max: "La course avec l'identifiant %{local_id} ne peut pas avoir des horaires sur plus de %{max} jours"
diff --git a/config/locales/workbenches.en.yml b/config/locales/workbenches.en.yml
new file mode 100644
index 000000000..8525a4b9f
--- /dev/null
+++ b/config/locales/workbenches.en.yml
@@ -0,0 +1,12 @@
+en:
+ workbenches:
+ index:
+ title: "%{organisation} dashboard"
+ offers:
+ title: "Transport offers"
+ organisation: "Organisation offers"
+ idf: "IDF offers"
+ referentials: "Referentials"
+ calendars: "Calendars"
+ see: "See the list"
+ no_content: "No content yet."
diff --git a/config/locales/workbenches.fr.yml b/config/locales/workbenches.fr.yml
new file mode 100644
index 000000000..1cdc19a13
--- /dev/null
+++ b/config/locales/workbenches.fr.yml
@@ -0,0 +1,12 @@
+fr:
+ workbenches:
+ index:
+ title: "Tableau de bord %{organisation}"
+ offers:
+ title: "Offres de transport"
+ organisation: "Offres de mon organisation"
+ idf: "Offres IDF"
+ referentials: "Jeux de données"
+ calendars: "Calendriers"
+ see: "Voir la liste"
+ no_content: "Aucun contenu pour le moment"
diff --git a/config/routes.rb b/config/routes.rb
index aa6713857..28c092e6a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,7 +1,7 @@
require 'sidekiq/web'
ChouetteIhm::Application.routes.draw do
- resources :workbenches, :only => [:show] do
+ resources :workbenches, only: [:show, :index] do
delete :referentials, on: :member, action: :delete_referentials
resources :imports do
get :download, on: :member
@@ -14,7 +14,7 @@ ChouetteIhm::Application.routes.draw do
devise_scope :user do
authenticated :user do
- root :to => 'referentials#index', as: :authenticated_root
+ root :to => 'workbenches#index', as: :authenticated_root
end
unauthenticated :user do
@@ -76,7 +76,7 @@ ChouetteIhm::Application.routes.draw do
get :autocomplete, on: :collection, controller: 'autocomplete_calendars'
end
- resources :referentials do
+ resources :referentials, except: :index do
resources :api_keys
resources :autocomplete_stop_areas, only: [:show, :index] do
get 'around', on: :member
@@ -213,7 +213,8 @@ ChouetteIhm::Application.routes.draw do
end
end
end
- root :to => "referentials#index"
+
+ root :to => "workbenches#index"
get '/help/(*slug)' => 'help#show'
diff --git a/config/sidekiq.yml b/config/sidekiq.yml
new file mode 100644
index 000000000..be0fceb30
--- /dev/null
+++ b/config/sidekiq.yml
@@ -0,0 +1,5 @@
+:concurrency: 5
+:pidfile: tmp/pids/sidekiq.pid
+:queues:
+ - default
+ - mailers
diff --git a/lib/stif/permission_translator.rb b/lib/stif/permission_translator.rb
index 7032f910a..afe69756e 100644
--- a/lib/stif/permission_translator.rb
+++ b/lib/stif/permission_translator.rb
@@ -1,7 +1,45 @@
module Stif
module PermissionTranslator extend self
+
def translate(sso_extra_permissions)
- %w{sessions:create}
+ sso_extra_permissions
+ .sort
+ .flat_map(&method(:extra_permission_translation))
+ .uniq
+ end
+
+ private
+
+ def all_destructive_permissions
+ destructive_permissions_for( all_resources )
+ end
+
+ def all_resources
+ %w[
+ access_points
+ connection_links calendars
+ footnotes
+ journey_patterns
+ referentials routes routing_constraint_zones
+ time_tables
+ vehicle_journeys
+ ]
+ end
+
+ def destructive_permissions_for(models)
+ @__destructive_permissions_for__ ||=
+ models.product( %w{create destroy update} ).map{ |model_action| model_action.join('.') }
+ end
+
+ def extra_permission_translation extra_permission
+ translation_table.fetch(extra_permission, [])
+ end
+
+ def translation_table
+ {
+ "boiv:read-offer" => %w{sessions:create},
+ "boiv:edit-offer" => all_destructive_permissions + %w{sessions:create},
+ }
end
end
end
diff --git a/lib/tasks/generate.rake b/lib/tasks/generate.rake
index 4b1e98ca4..f02a75cc2 100644
--- a/lib/tasks/generate.rake
+++ b/lib/tasks/generate.rake
@@ -1,12 +1,9 @@
namespace :generate do
-
+
desc "Create model diagrams for Chouette"
task :model_diagram => :environment do
- sh "bundle exec rake erd orientation=horizontal title='Chouette v2.5.2 model diagram (part 1)' only='Organisation,Referential,Export,Api::V1::ApiKey,ExportLogMessage,Import,RuleParameterSet,Validation,User' filename='model-diagram-part-1'"
-
- sh "bundle exec rake erd:generate orientation=horizontal title='Chouette v2.5.2 model diagram (part 2)' exclude='Organisation,Referential,Export,Api::V1::ApiKey,ExportLogMessage,Import,RuleParameterSet, Validation,User,NetexImport,NeptuneImport,GtfsImport,CsvImport,Delayed::Backend::ActiveRecord::Job' filename='model-diagram-part-2'"
-
- sh "bundle exec rake erd:generate orientation=horizontal title='Chouette v2.5.2 model diagram (part 3)' only='NetexImport,NeptuneImport,GtfsImport,CsvImport,Delayed::Backend::ActiveRecord::Job' filename='model-diagram-part-3'"
+ sh "bundle exec rake erd only='Calendar,Referential,Chouette::Line,Chouette::Route,Chouette::JourneyPattern,Chouette::VehicleJourney,Chouette::VehicleJourneyAtStop,Chouette::TimeTable,Chouette::TimeTableDate,Chouette::TimeTablePeriod,Chouette::Footnote,Chouette::Network,Chouette::Company,Chouette::StopPoint,Chouette::StopArea' filename='offer_datas' title='Offer Datas'"
+ sh "bundle exec rake erd only='Organisation,Referential,User,Workbench' filename='organisation' title='Organisation'"
end
-
+
end
diff --git a/spec/controllers/devise/cas_sessions_controller_spec.rb b/spec/controllers/devise/cas_sessions_controller_spec.rb
index 950d141fd..c82fd2cdb 100644
--- a/spec/controllers/devise/cas_sessions_controller_spec.rb
+++ b/spec/controllers/devise/cas_sessions_controller_spec.rb
@@ -1,25 +1,37 @@
RSpec.describe Devise::CasSessionsController, type: :controller do
- login_user
+ before do
+ @user = signed_in_user
+ allow_any_instance_of(Warden::Proxy).to receive(:authenticate).and_return @user
+ allow_any_instance_of(Warden::Proxy).to receive(:authenticate!).and_return @user
+ @request.env["devise.mapping"] = Devise.mappings[:user]
+ end
+
context 'login is correctly redirected' do
+ let( :signed_in_user ){ build_stubbed :user }
it 'to #service' do
get :new
- expect(response).to redirect_to(unauthenticated_root_path)
+ expect( response ).to be_redirect
+ expect( response.redirect_url ).to eq("http://stif-portail-dev.af83.priv/sessions/login?service=http%3A%2F%2Ftest.host%2Fusers%2Fservice")
end
end
- context 'user does not have any boiv:.+ permission' do
- xit 'cannot login and will be redirected to the login page, with a corresponding message' do
+ context 'user does not have permission sessions:create' do
+ let( :signed_in_user ){ build_stubbed :user }
+
+ it 'cannot login and will be redirected to the login page, with a corresponding message' do
get :service
expect(controller).to set_flash[:alert].to(%r{IBOO})
- expect(response).to redirect_to("http://stif-portail-dev.af83.priv/sessions/login?service=http%3A%2F%2Ftest.host%2Fusers%2Fservice")
+ expect(response).to redirect_to "http://stif-portail-dev.af83.priv/sessions/logout?service=http%3A%2F%2Ftest.host%2Fusers%2Fservice"
end
end
- context 'user does have a boiv:.+ permission' do
+ context 'user does have permission sessions:create' do
+ let( :signed_in_user ){ build_stubbed :allmighty_user }
+
it 'can login and will be redirected to the referentials page' do
- @user.update_attribute :permissions, (@user.permissions << 'boiv:UnameIt')
+ @user.permissions << 'sessions:create'
get :service
expect(response).to redirect_to(authenticated_root_path)
end
diff --git a/spec/decorators/referential_decorator_spec.rb b/spec/decorators/referential_decorator_spec.rb
index 5de6b7e95..16da8d30b 100644
--- a/spec/decorators/referential_decorator_spec.rb
+++ b/spec/decorators/referential_decorator_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe ReferentialDecorator, type: [:helper, :decorator] do
end
end
- context 'all rights and different organisation' do
+ context 'all rights and different organisation' do
let( :user ){ build_stubbed :allmighty_user }
@@ -33,10 +33,11 @@ RSpec.describe ReferentialDecorator, type: [:helper, :decorator] do
expect_action_link_elements.to be_empty
expect_action_link_hrefs.to eq([
referential_time_tables_path(object),
+ new_referential_path(from: object),
])
end
end
- context 'all rights and same organisation' do
+ context 'all rights and same organisation' do
let( :user ){ build_stubbed :allmighty_user, organisation: referential.organisation }
diff --git a/spec/lib/stif/permission_translator_spec.rb b/spec/lib/stif/permission_translator_spec.rb
index 3672c7937..1af21364c 100644
--- a/spec/lib/stif/permission_translator_spec.rb
+++ b/spec/lib/stif/permission_translator_spec.rb
@@ -1,10 +1,45 @@
RSpec.describe Stif::PermissionTranslator do
- context "SSO Permission boiv:read:offer →" do
+ context "No SSO Permissions" do
+ it { expect(described_class.translate([])).to be_empty }
+ end
+
+ context "SSO Permission boiv:read-offer →" do
it "sessions:create only" do
- expect( described_class.translate(%w{boiv:read:offer}) ).to eq(%w{sessions:create})
+ expect( described_class.translate(%w{boiv:read-offer}) ).to eq(%w{sessions:create})
+ end
+
+ end
+
+ context "SSO Permission boiv:edit-offer →" do
+
+ it "all permissions" do
+ expect( described_class.translate(%w{boiv:edit-offer}) ).to eq(Support::Permissions.all_permissions)
+ end
+
+ it "all permissions, no doubletons" do
+ expect( described_class.translate(%w{boiv:edit-offer boiv:read-offer}) ).to eq(Support::Permissions.all_permissions)
end
+ it "all permissions, input order agnostic" do
+ expect( described_class.translate(%w{boiv:read-offer boiv:edit-offer}) ).to eq(Support::Permissions.all_permissions)
+ end
+ end
+
+ context "SSO Permission ignores garbage (no injection) →" do
+ it "remains empty" do
+ expect( described_class.translate(%w{referentials.create}) ).to be_empty
+ end
+
+ it "remains at boiv:read-offer level" do
+ expect( described_class.translate(%w{referentials.create boiv:read-offer calendars.delete}) ).to eq(%w{sessions:create})
+ end
+
+ it "does not add garbage or doubletons for boiv:edit-offer level" do
+ expect(
+ described_class.translate(%w{xxx boiv:read-offer lines.delete boiv:edit-offer footnotes.update})
+ ).to eq(Support::Permissions.all_permissions)
+ end
end
end
diff --git a/spec/models/calendar_observer_spec.rb b/spec/models/calendar_observer_spec.rb
index abb462d25..4fba02bef 100644
--- a/spec/models/calendar_observer_spec.rb
+++ b/spec/models/calendar_observer_spec.rb
@@ -12,14 +12,14 @@ RSpec.describe CalendarObserver, type: :observer do
it 'should schedule mailer on calendar update' do
calendar.name = 'edited_name'
- expect(MailerJob).to receive(:perform_later).with 'CalendarMailer', 'updated', [calendar, user]
+ expect(MailerJob).to receive(:perform_later).with 'CalendarMailer', 'updated', [calendar.id, user.id]
calendar.save
end
it 'should not schedule mailer for none shared calendar on update' do
calendar = create(:calendar, shared: false)
calendar.name = 'edited_name'
- expect(MailerJob).to_not receive(:perform_later).with 'CalendarMailer', 'updated', [calendar, user]
+ expect(MailerJob).to_not receive(:perform_later).with 'CalendarMailer', 'updated', [calendar.id, user.id]
calendar.save
end
end
@@ -31,12 +31,12 @@ RSpec.describe CalendarObserver, type: :observer do
end
it 'should schedule mailer on calendar create' do
- expect(MailerJob).to receive(:perform_later).with 'CalendarMailer', 'created', [anything, user]
+ expect(MailerJob).to receive(:perform_later).with 'CalendarMailer', 'created', [anything, user.id]
build(:calendar, shared: true).save
end
it 'should not schedule mailer for none shared calendar on create' do
- expect(MailerJob).to_not receive(:perform_later).with 'CalendarMailer', 'created', [anything, user]
+ expect(MailerJob).to_not receive(:perform_later).with 'CalendarMailer', 'created', [anything, user.id]
build(:calendar, shared: false).save
end
end
diff --git a/spec/models/chouette/line_spec.rb b/spec/models/chouette/line_spec.rb
index 5a339e7ed..2e5882012 100644
--- a/spec/models/chouette/line_spec.rb
+++ b/spec/models/chouette/line_spec.rb
@@ -1,17 +1,12 @@
require 'spec_helper'
describe Chouette::Line, :type => :model do
-
subject { create(:line) }
- it { is_expected.to belong_to(:line_referential) }
+ it { should belong_to(:line_referential) }
# it { is_expected.to validate_presence_of :network }
# it { is_expected.to validate_presence_of :company }
-
- it { is_expected.to validate_presence_of :name }
-
- # it { should validate_presence_of :objectid }
- it { is_expected.to validate_uniqueness_of :objectid }
+ it { should validate_presence_of :name }
describe '#display_name' do
it 'should display local_id, number, name and company name' do
@@ -22,7 +17,7 @@ describe Chouette::Line, :type => :model do
describe '#objectid' do
subject { super().objectid }
- it { is_expected.to be_kind_of(Chouette::NetexObjectId) }
+ it { is_expected.to be_kind_of(Chouette::StifCodifligneObjectid) }
end
# it { should validate_numericality_of :objectversion }
diff --git a/spec/models/chouette/stop_area_spec.rb b/spec/models/chouette/stop_area_spec.rb
index 1a2ff8ede..293ae5202 100644
--- a/spec/models/chouette/stop_area_spec.rb
+++ b/spec/models/chouette/stop_area_spec.rb
@@ -7,16 +7,15 @@ describe Chouette::StopArea, :type => :model do
let!(:commercial_stop_point) { create :stop_area, :area_type => "lda" }
let!(:stop_place) { create :stop_area, :area_type => "zdlp" }
- # Refs #1627
- # describe '#objectid' do
- # subject { super().objectid }
- # it { is_expected.to be_kind_of(Chouette::ObjectId) }
- # end
-
- it { is_expected.to belong_to(:stop_area_referential) }
- it { is_expected.to validate_presence_of :name }
- it { is_expected.to validate_numericality_of :latitude }
- it { is_expected.to validate_numericality_of :longitude }
+ describe '#objectid' do
+ subject { super().objectid }
+ it { should be_kind_of(Chouette::StifReflexObjectid) }
+ end
+
+ it { should belong_to(:stop_area_referential) }
+ it { should validate_presence_of :name }
+ it { should validate_numericality_of :latitude }
+ it { should validate_numericality_of :longitude }
# describe ".latitude" do
# it "should accept -90 value" do
diff --git a/spec/models/chouette/time_table_spec.rb b/spec/models/chouette/time_table_spec.rb
index bd74a2d4c..304cb0184 100644
--- a/spec/models/chouette/time_table_spec.rb
+++ b/spec/models/chouette/time_table_spec.rb
@@ -14,6 +14,8 @@ describe Chouette::TimeTable, :type => :model do
describe "#merge! with time_table" do
let(:another_tt) { create(:time_table) }
let(:another_tt_periods_to_range) { another_tt.periods.map{|p| p.period_start..p.period_end } }
+ let(:dates) { another_tt.dates.map(&:date) }
+ let(:continuous_dates) { another_tt.continuous_dates.flatten.map(&:date) }
# Make sur we don't have overlapping periods or dates
before do
@@ -22,12 +24,19 @@ describe Chouette::TimeTable, :type => :model do
p.period_end = p.period_end + 1.year
end
another_tt.dates.each{| d| d.date = d.date + 1.year }
+ another_tt.save
end
it 'should merge dates' do
subject.dates.clear
subject.merge!(another_tt)
- expect(subject.dates.map(&:date)).to include(*another_tt.dates.map(&:date))
+ expect(subject.dates.map(&:date)).to match_array(dates - continuous_dates)
+ end
+
+ it 'should not merge continuous dates' do
+ subject.dates.clear
+ subject.merge!(another_tt)
+ expect(subject.dates.map(&:date)).not_to include(*continuous_dates)
end
it 'should merge periods' do
@@ -50,28 +59,42 @@ describe Chouette::TimeTable, :type => :model do
subject.merge!(another_tt)
expect(subject.dates.map(&:date)).to include(another_tt.dates.last.date)
end
+
+ it 'should remove date in_out false if other tt doesnt have them' do
+ subject.dates.create(in_out: false, date: Date.today + 5.day + 1.year)
+
+ expect {
+ subject.merge!(another_tt)
+ }.to change {subject.reload.excluded_days.count}.by(-1)
+ end
end
context "#merge! with calendar" do
let(:calendar) { create(:calendar, date_ranges: [Date.today + 1.year..Date.tomorrow + 1.year]) }
+ let(:another_tt) { calendar.convert_to_time_table }
+ let(:dates) { subject.dates.map(&:date) }
+ let(:continuous_dates) { subject.continuous_dates.flatten.map(&:date) }
it 'should merge calendar dates' do
subject.dates.clear
- subject.merge!(calendar.convert_to_time_table)
- expect(subject.dates.map(&:date)).to include(*calendar.dates)
+ subject.merge!(another_tt)
+ expect(subject.dates.map(&:date)).to match_array(dates - continuous_dates)
+ end
+
+ it 'should not merge calendar continuous dates' do
+ subject.dates.clear
+ subject.merge!(another_tt)
+ expect(subject.dates.map(&:date)).not_to include(*continuous_dates)
end
it 'should merge calendar periods with no periods in source' do
subject.periods.clear
- another_tt = calendar.convert_to_time_table
subject.merge!(another_tt)
expect(subject_periods_to_range).to include(*calendar.date_ranges)
end
it 'should add calendar periods with existing periods in source' do
- another_tt = calendar.convert_to_time_table
subject.merge!(another_tt)
-
expect(subject_periods_to_range).to include(*calendar.date_ranges)
end
end
@@ -1109,7 +1132,7 @@ end
- describe "#optimize_periods" do
+ describe "#optimize_overlapping_periods" do
before do
subject.periods.clear
subject.periods << Chouette::TimeTablePeriod.new(
@@ -1127,7 +1150,7 @@ end
subject.int_day_types = 4|8|16
end
it "should return 2 ordered periods" do
- periods = subject.optimize_periods
+ periods = subject.optimize_overlapping_periods
expect(periods.size).to eq(2)
expect(periods[0].period_start).to eq(Date.new(2014, 6, 1))
expect(periods[0].period_end).to eq(Date.new(2014, 6, 14))
diff --git a/spec/models/chouette/vehicle_journey_at_stop_spec.rb b/spec/models/chouette/vehicle_journey_at_stop_spec.rb
new file mode 100644
index 000000000..d999ed1a8
--- /dev/null
+++ b/spec/models/chouette/vehicle_journey_at_stop_spec.rb
@@ -0,0 +1,49 @@
+require 'spec_helper'
+
+RSpec.describe Chouette::VehicleJourneyAtStop, type: :model do
+ describe "#day_offset_outside_range?" do
+ let (:at_stop) { build_stubbed(:vehicle_journey_at_stop) }
+
+ it "disallows negative offsets" do
+ expect(at_stop.day_offset_outside_range?(-1)).to be true
+ end
+
+ it "disallows offsets greater than DAY_OFFSET_MAX" do
+ expect(at_stop.day_offset_outside_range?(
+ Chouette::VehicleJourneyAtStop::DAY_OFFSET_MAX + 1
+ )).to be true
+ end
+
+ it "allows offsets between 0 and DAY_OFFSET_MAX inclusive" do
+ expect(at_stop.day_offset_outside_range?(
+ Chouette::VehicleJourneyAtStop::DAY_OFFSET_MAX
+ )).to be false
+ end
+
+ it "forces a nil offset to 0" do
+ expect(at_stop.day_offset_outside_range?(nil)).to be false
+ end
+ end
+
+ describe "#validate" do
+ it "displays the proper error message when day offset exceeds the max" do
+ bad_offset = Chouette::VehicleJourneyAtStop::DAY_OFFSET_MAX + 1
+
+ at_stop = build_stubbed(
+ :vehicle_journey_at_stop,
+ arrival_day_offset: bad_offset,
+ departure_day_offset: bad_offset
+ )
+ error_message = I18n.t(
+ 'vehicle_journey_at_stops.errors.day_offset_must_not_exceed_max',
+ local_id: at_stop.vehicle_journey.objectid.local_id,
+ max: bad_offset
+ )
+
+ at_stop.validate
+
+ expect(at_stop.errors[:arrival_day_offset]).to include(error_message)
+ expect(at_stop.errors[:departure_day_offset]).to include(error_message)
+ end
+ end
+end
diff --git a/spec/models/chouette/vehicle_journey_spec.rb b/spec/models/chouette/vehicle_journey_spec.rb
index c78ef5b33..645513735 100644
--- a/spec/models/chouette/vehicle_journey_spec.rb
+++ b/spec/models/chouette/vehicle_journey_spec.rb
@@ -1,7 +1,24 @@
require 'spec_helper'
describe Chouette::VehicleJourney, :type => :model do
- describe "vjas_departure_time_must_be_before_next_stop_arrival_time" do
+ it "must be valid with an at-stop day offset of 1" do
+ vehicle_journey = create(
+ :vehicle_journey,
+ stop_arrival_time: '23:00:00',
+ stop_departure_time: '23:00:00'
+ )
+ vehicle_journey.vehicle_journey_at_stops.last.update(
+ arrival_time: '00:30:00',
+ departure_time: '00:30:00',
+ arrival_day_offset: 1,
+ departure_day_offset: 1
+ )
+
+ expect(vehicle_journey).to be_valid
+ end
+
+ describe "vjas_departure_time_must_be_before_next_stop_arrival_time",
+ skip: "Validation currently commented out because it interferes with day offsets" do
let(:vehicle_journey) { create :vehicle_journey }
let(:vjas) { vehicle_journey.vehicle_journey_at_stops }
@@ -10,7 +27,7 @@ describe Chouette::VehicleJourney, :type => :model do
vehicle_journey.validate
expect(vjas[0].errors[:departure_time]).not_to be_blank
- expect(vehicle_journey.errors[:vehicle_journey_at_stops].count).to eq(1)
+ expect(vehicle_journey.errors.count).to eq(1)
expect(vehicle_journey).not_to be_valid
end
@@ -19,7 +36,7 @@ describe Chouette::VehicleJourney, :type => :model do
vehicle_journey.validate
expect(vjas[0].errors[:departure_time]).to be_blank
- expect(vehicle_journey.errors[:vehicle_journey_at_stops]).to be_empty
+ expect(vehicle_journey.errors).to be_empty
expect(vehicle_journey).to be_valid
end
diff --git a/spec/models/referential_spec.rb b/spec/models/referential_spec.rb
index 2390cc470..53eaa60a3 100644
--- a/spec/models/referential_spec.rb
+++ b/spec/models/referential_spec.rb
@@ -27,11 +27,12 @@ describe Referential, :type => :model do
context "Cloning referential" do
let(:clone) do
- Referential.new_from(ref, organisation: ref.organisation)
+ Referential.new_from(ref)
end
let(:saved_clone) do
clone.tap do |clone|
+ clone.organisation = ref.organisation
clone.metadatas.each do |metadata|
metadata.periodes = metadata.periodes.map { |period| Range.new(period.end+1, period.end+10) }
end
diff --git a/spec/models/time_table_combination_spec.rb b/spec/models/time_table_combination_spec.rb
index 3e60fa444..ee934f50d 100644
--- a/spec/models/time_table_combination_spec.rb
+++ b/spec/models/time_table_combination_spec.rb
@@ -8,30 +8,93 @@ describe TimeTableCombination, :type => :model do
describe '#continuous_dates' do
it 'should group continuous dates' do
dates = source.dates.where(in_out: true)
- expect(source.continuous_dates[0].count).to eq(dates.count)
+ expect(source.continuous_dates.flatten.count).to eq(dates.count)
- # 6 more continuous date, 1 isolated date
+ # 6 more continuous dates, 2 isolated dates
(10..15).each do |n|
source.dates.create(date: Date.today + n.day, in_out: true)
end
- source.dates.create(date: Date.today + 1.year, in_out: true)
+
+ (1..2).each do |n|
+ source.dates.create(date: Date.today + n.day + 1.year, in_out: true)
+ end
+
expect(source.reload.continuous_dates[1].count).to eq(6)
- expect(source.reload.continuous_dates[2].count).to eq(1)
+ expect(source.reload.continuous_dates[2].count).to eq(2)
end
end
describe '#convert_continuous_dates_to_periods' do
it 'should convert continuous dates to periods' do
+ source.dates.clear
+
(10..12).each do |n|
source.dates.create(date: Date.today + n.day, in_out: true)
end
- source.dates.create(date: Date.today + 1.year, in_out: true)
+
+ (1..3).each do |n|
+ source.dates.create(date: Date.today + n.day + 1.year, in_out: true)
+ end
expect {
source.reload.convert_continuous_dates_to_periods
}.to change {source.periods.count}.by(2)
- expect(source.reload.dates.where(in_out: true).count).to eq(1)
+ expect(source.reload.dates.where(in_out: true).count).to eq(0)
+ end
+ end
+
+ describe '#continuous_periods' do
+ it 'should group continuous periods' do
+ source.periods.clear
+
+ start_date = Date.today + 1.year
+ end_date = start_date + 10
+
+ # 6 more continuous dates, 2 isolated dates
+ 0.upto(4) do |i|
+ source.periods.create(period_start: start_date, period_end: end_date)
+ start_date = end_date + 1
+ end_date = start_date + 10
+ end
+
+ expect(source.reload.continuous_periods.flatten.count).to eq(5)
+ end
+ end
+
+ describe '#convert_continuous_periods_into_one' do
+ it 'should convert continuous periods into one' do
+ source.periods.clear
+
+ start_date = Date.today + 1.year
+ end_date = start_date + 10
+
+ # 6 more continuous dates, 2 isolated dates
+ 0.upto(4) do |i|
+ source.periods.create(period_start: start_date, period_end: end_date)
+ start_date = end_date + 1
+ end_date = start_date + 10
+ end
+
+ expect {
+ source.reload.convert_continuous_periods_into_one
+ }.to change {source.periods.count}.by(-4)
+ end
+ end
+
+ describe '#optimize_continuous_dates_and_periods' do
+ it 'should update period if timetable has in_date just before or after ' do
+ source.dates.clear
+ source.periods.clear
+
+ source.periods.create(period_start: Date.today, period_end: Date.today + 10.day)
+ source.dates.create(date: Date.today - 1.day, in_out: true)
+
+ expect {
+ source.periods = source.optimize_continuous_dates_and_periods
+ }.to change {source.dates.count}.by(-1)
+
+ expect(source.reload.periods.first.period_start).to eq(Date.today - 1.day)
end
end
@@ -129,4 +192,3 @@ describe TimeTableCombination, :type => :model do
end
end
end
-
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 6f98e5ce7..3a9ae37e9 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1,6 +1,4 @@
-require 'spec_helper'
-
-describe User, :type => :model do
+RSpec.describe User, :type => :model do
# it { should validate_uniqueness_of :email }
# it { should validate_presence_of :name }
@@ -116,9 +114,11 @@ describe User, :type => :model do
end
context 'permissions' do
+ let( :all_permissions ){ Stif::PermissionTranslator.translate(%w{boiv:edit-offer}) }
+
it 'should give edit permissions to user if user has "edit offer" permission in portail' do
User.portail_sync
- expect(User.find_by(username: 'vlatka.pavisic').permissions).to include_all(User.edit_offer_permissions)
+ expect(User.find_by(username: 'vlatka.pavisic').permissions).to eq(all_permissions)
expect(User.find_by(username: 'pierre.vabre').permissions).to be_empty
end
end
diff --git a/spec/policies/referential_policy_spec.rb b/spec/policies/referential_policy_spec.rb
index 33d8e13e8..69d0eb17b 100644
--- a/spec/policies/referential_policy_spec.rb
+++ b/spec/policies/referential_policy_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe ReferentialPolicy, type: :policy do
# ------------------
permissions :clone? do
- it_behaves_like 'permitted policy and same organisation', 'referentials.create', archived: true
+ it_behaves_like 'permitted policy', 'referentials.create', archived: true
end
permissions :archive? do
diff --git a/spec/support/permissions.rb b/spec/support/permissions.rb
index a13010f65..fcf9ae9c4 100644
--- a/spec/support/permissions.rb
+++ b/spec/support/permissions.rb
@@ -15,6 +15,7 @@ module Support
%w[
access_points
connection_links
+ calendars
footnotes
journey_patterns
referentials