aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/cleanup.coffee11
-rw-r--r--app/assets/javascripts/es6_browserified/itineraries/index.js15
-rw-r--r--app/assets/javascripts/es6_browserified/itineraries/reducers/stopPoints.js19
-rw-r--r--app/assets/javascripts/routing_constraint_zones.coffee33
-rw-r--r--app/controllers/referentials_controller.rb4
-rw-r--r--app/controllers/routing_constraint_zones_controller.rb31
-rw-r--r--app/controllers/time_tables_controller.rb5
-rw-r--r--app/controllers/workbenches_controller.rb1
-rw-r--r--app/helpers/breadcrumb_helper.rb8
-rw-r--r--app/mailers/calendar_mailer.rb10
-rw-r--r--app/models/calendar_observer.rb4
-rw-r--r--app/models/chouette/journey_pattern.rb3
-rw-r--r--app/models/chouette/line.rb2
-rw-r--r--app/models/chouette/routing_constraint_zone.rb11
-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/time_table.rb90
-rw-r--r--app/models/chouette/vehicle_journey.rb11
-rw-r--r--app/models/chouette/vehicle_journey_at_stop.rb37
-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.rb4
-rw-r--r--app/models/user.rb27
-rw-r--r--app/policies/login_policy.rb2
-rw-r--r--app/views/calendar_mailer/created.html.slim24
-rw-r--r--app/views/calendar_mailer/updated.html.slim23
-rw-r--r--app/views/layouts/application.html.slim2
-rw-r--r--app/views/layouts/mailer.html.slim21
-rw-r--r--app/views/layouts/navigation/_main_nav_left.html.slim2
-rw-r--r--app/views/layouts/navigation/_main_nav_top.html.slim2
-rw-r--r--app/views/referentials/_filters.html.slim4
-rw-r--r--app/views/referentials/_form.html.slim4
-rw-r--r--app/views/referentials/_period_fields.html.slim2
-rw-r--r--app/views/referentials/index.html.slim6
-rw-r--r--app/views/referentials/show.html.slim16
-rw-r--r--app/views/routing_constraint_zones/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/_filters.html.slim16
-rw-r--r--app/views/workbenches/index.html.slim6
-rw-r--r--app/views/workbenches/show.html.slim6
-rw-r--r--config/locales/actions.en.yml2
-rw-r--r--config/locales/actions.fr.yml2
-rw-r--r--config/locales/clean_ups.en.yml4
-rw-r--r--config/locales/clean_ups.fr.yml4
-rw-r--r--config/locales/en.yml3
-rw-r--r--config/locales/fr.yml3
-rw-r--r--config/locales/mailers.en.yml5
-rw-r--r--config/locales/mailers.fr.yml7
-rw-r--r--config/locales/organisations.en.yml5
-rw-r--r--config/locales/organisations.fr.yml5
-rw-r--r--config/locales/referentials.en.yml11
-rw-r--r--config/locales/referentials.fr.yml9
-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.yml4
-rw-r--r--config/locales/workbenches.fr.yml4
-rw-r--r--lib/stif/permission_translator.rb40
-rw-r--r--spec/controllers/devise/cas_sessions_controller_spec.rb26
-rw-r--r--spec/features/workbenches_spec.rb24
-rw-r--r--spec/javascripts/itineraries/reducers/stop_points_spec.js63
-rw-r--r--spec/lib/stif/permission_translator_spec.rb39
-rw-r--r--spec/mailers/calendar_mailer_spec.rb2
-rw-r--r--spec/models/calendar_observer_spec.rb8
-rw-r--r--spec/models/chouette/journey_pattern_spec.rb48
-rw-r--r--spec/models/chouette/line_spec.rb11
-rw-r--r--spec/models/chouette/routing_constraint_zone_spec.rb2
-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.rb19
-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/support/permissions.rb1
76 files changed, 816 insertions, 302 deletions
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/itineraries/index.js b/app/assets/javascripts/es6_browserified/itineraries/index.js
index a8f3048fa..ad32b9519 100644
--- a/app/assets/javascripts/es6_browserified/itineraries/index.js
+++ b/app/assets/javascripts/es6_browserified/itineraries/index.js
@@ -69,28 +69,15 @@ document.querySelector('input[name=commit]').addEventListener('click', (event)=>
if(state.stopPoints.length >= 2) {
state.stopPoints.map((stopPoint, i) => {
- addInput('id', (datas[i]) ? datas[i].stoppoint_id : '', i)
+ addInput('id', stopPoint.stoppoint_id ? stopPoint.stoppoint_id : '', i)
addInput('stop_area_id',stopPoint.stoparea_id, i)
addInput('position',i, i)
addInput('for_boarding',stopPoint.for_boarding, i)
addInput('for_alighting',stopPoint.for_alighting, i)
})
- if(state.stopPoints.length < datas.length){
- for(var j= state.stopPoints.length; j < datas.length; j++){
- updateFormForDeletion(datas[j])
- }
- }
} else {
event.preventDefault()
let msg = "L'itinéraire doit comporter au moins deux arrêts"
$('#stop_points').find('.subform').after("<div class='alert alert-danger'><span class='fa fa-lg fa-exclamation-circle'></span><span>" + msg + "</span></div>")
}
})
-
-const updateFormForDeletion = (stop) =>{
- if (stop.stoppoint_id !== undefined){
- let now = Date.now()
- addInput('id', stop.stoppoint_id, now)
- addInput('_destroy', 'true', now)
- }
-}
diff --git a/app/assets/javascripts/es6_browserified/itineraries/reducers/stopPoints.js b/app/assets/javascripts/es6_browserified/itineraries/reducers/stopPoints.js
index 24c3e5d87..a3b8accb3 100644
--- a/app/assets/javascripts/es6_browserified/itineraries/reducers/stopPoints.js
+++ b/app/assets/javascripts/es6_browserified/itineraries/reducers/stopPoints.js
@@ -20,6 +20,14 @@ const stopPoint = (state = {}, action, length) => {
}
}
+const updateFormForDeletion = (stop) =>{
+ if (stop.stoppoint_id !== undefined){
+ let now = Date.now()
+ addInput('id', stop.stoppoint_id, now)
+ addInput('_destroy', 'true', now)
+ }
+}
+
const stopPoints = (state = [], action) => {
switch (action.type) {
case 'ADD_STOP':
@@ -30,18 +38,19 @@ const stopPoints = (state = [], action) => {
case 'MOVE_STOP_UP':
return [
...state.slice(0, action.index - 1),
- state[action.index],
- state[action.index - 1],
+ _.assign({}, state[action.index], { stoppoint_id: state[action.index - 1].stoppoint_id }),
+ _.assign({}, state[action.index - 1], { stoppoint_id: state[action.index].stoppoint_id }),
...state.slice(action.index + 1)
]
case 'MOVE_STOP_DOWN':
return [
...state.slice(0, action.index),
- state[action.index + 1],
- state[action.index],
+ _.assign({}, state[action.index + 1], { stoppoint_id: state[action.index].stoppoint_id }),
+ _.assign({}, state[action.index], { stoppoint_id: state[action.index + 1].stoppoint_id }),
...state.slice(action.index + 2)
]
case 'DELETE_STOP':
+ updateFormForDeletion(state[action.index])
return [
...state.slice(0, action.index),
...state.slice(action.index + 1).map((stopPoint)=>{
@@ -56,7 +65,7 @@ const stopPoints = (state = [], action) => {
{},
t,
{
- stoppoint_id: "",
+ stoppoint_id: t.stoppoint_id,
text: action.text.text,
stoparea_id: action.text.stoparea_id,
user_objectid: action.text.user_objectid,
diff --git a/app/assets/javascripts/routing_constraint_zones.coffee b/app/assets/javascripts/routing_constraint_zones.coffee
index c01c9ca2f..8fdcb3b50 100644
--- a/app/assets/javascripts/routing_constraint_zones.coffee
+++ b/app/assets/javascripts/routing_constraint_zones.coffee
@@ -1,18 +1,17 @@
-$ ->
-
- update_stop_points = () ->
- url = $('#routing_constraint_zone_route_id').attr("data-url")
- routing_constraint_zone_json = $('#routing_constraint_zone_route_id').attr("data-object")
- route_id = $('#routing_constraint_zone_route_id').val()
- $.ajax
- url: url
- dataType: 'script'
- data: { route_id: route_id, routing_constraint_zone_json: routing_constraint_zone_json }
- error: (jqXHR, textStatus, errorThrown) ->
- console.log("ERROR")
- success: (data, textStatus, jqXHR) ->
- console.log("SUCCESS")
+update_stop_points = () ->
+ url = $('#routing_constraint_zone_route_id').attr("data-url")
+ routing_constraint_zone_json = $('#routing_constraint_zone_route_id').attr("data-object")
+ route_id = $('#routing_constraint_zone_route_id').val()
+ $.ajax
+ url: url
+ dataType: 'script'
+ data: { route_id: route_id, routing_constraint_zone_json: routing_constraint_zone_json }
+ error: (jqXHR, textStatus, errorThrown) ->
+ console.log("ERROR")
+ success: (data, textStatus, jqXHR) ->
+ console.log("SUCCESS")
- $("#itl_form #routing_constraint_zone_route_id").on 'change', -> update_stop_points()
-
- update_stop_points()
+$ ->
+ if $('#routing_constraint_zone_route_id').hasClass('new_routing_constraint_zone_route')
+ $("#routing_constraint_zone_route_id").on 'change', -> update_stop_points()
+ update_stop_points()
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/routing_constraint_zones_controller.rb b/app/controllers/routing_constraint_zones_controller.rb
index 6c3cb8a29..6541eb492 100644
--- a/app/controllers/routing_constraint_zones_controller.rb
+++ b/app/controllers/routing_constraint_zones_controller.rb
@@ -58,23 +58,40 @@ class RoutingConstraintZonesController < ChouetteController
@q = current_referential.routing_constraint_zones.search(params[:q])
@routing_constraint_zones ||= begin
- if sort_column && sort_direction
- routing_constraint_zones = @q.result(distinct: true).order(sort_column + ' ' + sort_direction)
- else
- routing_constraint_zones = @q.result(distinct: true).order(:name)
- end
- routing_constraint_zones = routing_constraint_zones.paginate(page: params[:page], per_page: 10)
+ routing_constraint_zones = sort_collection
+ routing_constraint_zones = routing_constraint_zones.paginate(
+ page: params[:page],
+ per_page: 10
+ )
end
end
private
def sort_column
- (Chouette::RoutingConstraintZone.column_names).include?(params[:sort]) ? params[:sort] : 'name'
+ (
+ Chouette::RoutingConstraintZone.column_names +
+ [
+ 'stop_points_count',
+ 'route'
+ ]
+ ).include?(params[:sort]) ? params[:sort] : 'name'
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
end
+ def sort_collection
+ sort_by = sort_column
+
+ if sort_by == 'stop_points_count'
+ @q.result.order_by_stop_points_count(sort_direction)
+ elsif sort_by == 'route'
+ @q.result.order_by_route_name(sort_direction)
+ else
+ @q.result.order(sort_column + ' ' + sort_direction)
+ end
+ end
+
def routing_constraint_zone_params
params.require(:routing_constraint_zone).permit(
:name,
diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb
index edeb5a32f..0054963c9 100644
--- a/app/controllers/time_tables_controller.rb
+++ b/app/controllers/time_tables_controller.rb
@@ -35,7 +35,7 @@ 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 = Calendar.find(tt_params[:calendar_id])
tt_params[:calendar_id] = nil if tt_params.has_key?(:dates_attributes) || tt_params.has_key?(:periods_attributes)
@@ -115,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
diff --git a/app/controllers/workbenches_controller.rb b/app/controllers/workbenches_controller.rb
index 171db6a07..19af28a98 100644
--- a/app/controllers/workbenches_controller.rb
+++ b/app/controllers/workbenches_controller.rb
@@ -7,6 +7,7 @@ class WorkbenchesController < BreadcrumbController
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
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/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/journey_pattern.rb b/app/models/chouette/journey_pattern.rb
index 868d8121e..f238d7339 100644
--- a/app/models/chouette/journey_pattern.rb
+++ b/app/models/chouette/journey_pattern.rb
@@ -14,7 +14,7 @@ class Chouette::JourneyPattern < Chouette::TridentActiveRecord
validates_presence_of :route
validates_presence_of :name
- validates :stop_points, length: { minimum: 2, too_short: :minimum }, on: :update
+ #validates :stop_points, length: { minimum: 2, too_short: :minimum }, on: :update
enum section_status: { todo: 0, completed: 1, control: 2 }
attr_accessor :control_checked
@@ -170,4 +170,3 @@ class Chouette::JourneyPattern < Chouette::TridentActiveRecord
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/routing_constraint_zone.rb b/app/models/chouette/routing_constraint_zone.rb
index 77f51c466..a649b0b8e 100644
--- a/app/models/chouette/routing_constraint_zone.rb
+++ b/app/models/chouette/routing_constraint_zone.rb
@@ -3,9 +3,18 @@ class Chouette::RoutingConstraintZone < Chouette::TridentActiveRecord
has_array_of :stop_points, class_name: 'Chouette::StopPoint'
validates_presence_of :name, :stop_points, :route
- validates :stop_point_ids, length: { minimum: 2, too_short: I18n.t('activerecord.errors.models.routing_constraint_zone.attributes.stop_points.not_enough_stop_points') }
+ # validates :stop_point_ids, length: { minimum: 2, too_short: I18n.t('activerecord.errors.models.routing_constraint_zone.attributes.stop_points.not_enough_stop_points') }
validate :stop_points_belong_to_route, :not_all_stop_points_selected
+ scope :order_by_stop_points_count, ->(direction) do
+ order("array_length(stop_point_ids, 1) #{direction}")
+ end
+
+ scope :order_by_route_name, ->(direction) do
+ joins(:route)
+ .order("routes.name #{direction}")
+ end
+
def stop_points_belong_to_route
errors.add(:stop_point_ids, I18n.t('activerecord.errors.models.routing_constraint_zone.attributes.stop_points.stop_points_not_from_route')) unless stop_points.all? { |sp| route.stop_points.include? sp }
end
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/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 19299d098..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|
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/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 e65d6a33b..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,
@@ -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/views/calendar_mailer/created.html.slim b/app/views/calendar_mailer/created.html.slim
index da15b7189..37b2a86ea 100644
--- a/app/views/calendar_mailer/created.html.slim
+++ b/app/views/calendar_mailer/created.html.slim
@@ -1 +1,25 @@
div = t('mailers.calendar_mailer.created.body', cal_name: @calendar.name, cal_index_url: calendars_url)
+
+table style="border-collapse:collapse;font-family:'Open Sans', Arial, sans serif;width:550px;margin:0px auto;color:#333333;"
+
+ thead
+ tr
+ th
+ .jumbotron style="background-color:#007fbb;color:#fff;padding:20px 25px;margin-bottom:0px;text-align:left;"
+ h1.brandname style="display:inline-block;font-size:20px;font-weight:700;text-transform:uppercase;margin:0;"
+ = t('brandname')
+
+ tbody
+ tr
+ td style="padding:40px 0px 60px 0px;"
+ p style="font-size:14px;font-weight:700;margin:0px 0px 10px 0px;"
+ = t('mailers.calendar_mailer.updated.subject')
+
+ p style="font-size:14px;margin:0px 0px 10px 0px;"
+ = t('mailers.calendar_mailer.created.body', cal_name: @calendar.name, cal_index_url: calendars_url).html_safe
+
+ tr
+ td style="text-align:center;padding:20px 0 0 0;border-top:1px solid #007fbb;"
+ p style="font-size:12px;font-weight:700;margin:0px 0px 10px 0px;opacity:0.85;"
+ em = t('mailers.calendar_mailer.sent_by') + " "
+ = link_to t('brandname'), unauthenticated_root_url, style: "color:#333333;text-decoration:underline;"
diff --git a/app/views/calendar_mailer/updated.html.slim b/app/views/calendar_mailer/updated.html.slim
index f70480107..bf128439a 100644
--- a/app/views/calendar_mailer/updated.html.slim
+++ b/app/views/calendar_mailer/updated.html.slim
@@ -1,2 +1,23 @@
-div = t('mailers.calendar_mailer.updated.body', cal_name: @calendar.name, cal_index_url: calendars_url)
+table style="border-collapse:collapse;font-family:'Open Sans', Arial, sans serif;width:550px;margin:0px auto;color:#333333;"
+ thead
+ tr
+ th
+ .jumbotron style="background-color:#007fbb;color:#fff;padding:20px 25px;margin-bottom:0px;text-align:left;"
+ h1.brandname style="display:inline-block;font-size:20px;font-weight:700;text-transform:uppercase;margin:0;"
+ = t('brandname')
+
+ tbody
+ tr
+ td style="padding:40px 0px 60px 0px;"
+ p style="font-size:14px;font-weight:700;margin:0px 0px 10px 0px;"
+ = t('mailers.calendar_mailer.updated.subject')
+
+ p style="font-size:14px;margin:0px 0px 10px 0px;"
+ = t('mailers.calendar_mailer.updated.body', cal_name: @calendar.name, cal_index_url: calendars_url).html_safe
+
+ tr
+ td style="text-align:center;padding:20px 0 0 0;border-top:1px solid #007fbb;"
+ p style="font-size:12px;font-weight:700;margin:0px 0px 10px 0px;opacity:0.85;"
+ em = t('mailers.calendar_mailer.sent_by') + " "
+ = link_to t('brandname'), unauthenticated_root_url, style: "color:#333333;text-decoration:underline;"
diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim
index 6eab2a761..d6a22c4f8 100644
--- a/app/views/layouts/application.html.slim
+++ b/app/views/layouts/application.html.slim
@@ -6,7 +6,7 @@ html lang=I18n.locale
= csrf_meta_tag
- title STIF BOIV
+ title = t('brandname')
= stylesheet_link_tag 'base'
= stylesheet_link_tag 'application'
diff --git a/app/views/layouts/mailer.html.slim b/app/views/layouts/mailer.html.slim
index 1485e8188..5db6917b3 100644
--- a/app/views/layouts/mailer.html.slim
+++ b/app/views/layouts/mailer.html.slim
@@ -2,21 +2,6 @@ doctype html
html
head
meta charset="utf-8"
- title= message.subject
-
- body style="font-family: Verdana, Helvetica, Arial, MS Trebuchet, sans-serif; font-size: 14px; width: 600px; background: #E5E5E5; padding: 15px"
-
- <style>
- h2 { font-size: 18px; }
- h3 { font-size: 14px; }
- a { color: black; }
- </style>
-
- h1 style="background: #61970B; height: 75px; font-size: 24px; font-weight: normal; color: white; padding: 20px 0 0 30px;"
- |Chouette
-
- div style="background: white; margin-bottom: 10px; padding: 15px; -moz-box-shadow: 3px 3px 4px #bbbbbb; -webkit-box-shadow: 3px 3px 4px #BBB; box-shadow: 3px 3px 4px #BBB; border-right: 1px solid #BBB; border-bottom: 1px solid #BBB;"
- = yield
-
- div style="color: #333333; text-align:center; font-size: 10px;"
- = "Envoyé par #{link_to 'Chouette', unauthenticated_root_url}"
+ /!* Email styles need to be inline */
+ body
+ = yield
diff --git a/app/views/layouts/navigation/_main_nav_left.html.slim b/app/views/layouts/navigation/_main_nav_left.html.slim
index 9dfc828c0..8e82ac528 100644
--- a/app/views/layouts/navigation/_main_nav_left.html.slim
+++ b/app/views/layouts/navigation/_main_nav_left.html.slim
@@ -5,7 +5,7 @@
.menu-content
.closeMenu title='Fermer le menu'
- .brandname = "IBOO"
+ .brandname = t('brandname')
#menu-items.panel-group
.menu-item.panel
diff --git a/app/views/layouts/navigation/_main_nav_top.html.slim b/app/views/layouts/navigation/_main_nav_top.html.slim
index 4cdd5f053..d6c849d3f 100644
--- a/app/views/layouts/navigation/_main_nav_top.html.slim
+++ b/app/views/layouts/navigation/_main_nav_top.html.slim
@@ -1,5 +1,5 @@
.nav-menu#menu_top
- .brandname IBOO
+ .brandname = t('brandname')
.menu-content
.menu-item
diff --git a/app/views/referentials/_filters.html.slim b/app/views/referentials/_filters.html.slim
index 9302ccaa8..1cc6bb410 100644
--- a/app/views/referentials/_filters.html.slim
+++ b/app/views/referentials/_filters.html.slim
@@ -20,5 +20,5 @@
= f.input :company_id_eq_any, collection: LineReferential.first.companies.order('name').pluck(:id), as: :check_boxes, label: false, label_method: lambda{|l| ("<span>#{LineReferential.first.companies.find(l).name}</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }
.actions
- = link_to 'Effacer', @workbench, class: 'btn btn-link'
- = f.submit 'Filtrer', class: 'btn btn-default'
+ = link_to t('actions.erase'), @workbench, class: 'btn btn-link'
+ = f.submit t('actions.filter'), class: 'btn btn-default'
diff --git a/app/views/referentials/_form.html.slim b/app/views/referentials/_form.html.slim
index 31d71bcdc..a9e308699 100644
--- a/app/views/referentials/_form.html.slim
+++ b/app/views/referentials/_form.html.slim
@@ -42,11 +42,11 @@
= render 'period_fields', f: period_form
.links.nested-linker
- = link_to_add_association 'Ajouter une période', subform, :periods, class: 'btn btn-outline-primary'
+ = link_to_add_association t('simple_form.labels.referential.actions.add_period'), subform, :periods, class: 'btn btn-outline-primary'
.separator
- = subform.input :lines, as: :select, collection: @referential.workbench.lines.includes(:company).order(:name), selected: subform.object.line_ids, label_method: :display_name, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Sélection de lignes', 'multiple': 'multiple', style: 'width: 100%' }
+ = subform.input :lines, as: :select, collection: @referential.workbench.lines.includes(:company).order(:name), selected: subform.object.line_ids, label_method: :display_name, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': t('simple_form.labels.referential.placeholders.select_lines'), 'multiple': 'multiple', style: 'width: 100%' }
.hidden = form.input :workbench_id, as: :hidden
diff --git a/app/views/referentials/_period_fields.html.slim b/app/views/referentials/_period_fields.html.slim
index 95e204554..4d2372f7b 100644
--- a/app/views/referentials/_period_fields.html.slim
+++ b/app/views/referentials/_period_fields.html.slim
@@ -12,4 +12,4 @@
div
= f.input :end, as: :date, label: false, wrapper_html: { class: 'date smart_date' }
div
- = link_to_remove_association '', f, class: 'fa fa-trash', data: { confirm: 'Etes-vous sûr(e) ?' }, title: t('actions.delete')
+ = link_to_remove_association '', f, class: 'fa fa-trash', data: { confirm: t('are_you_sure')}, title: t('actions.delete')
diff --git a/app/views/referentials/index.html.slim b/app/views/referentials/index.html.slim
index 8943d419c..8bb66da21 100644
--- a/app/views/referentials/index.html.slim
+++ b/app/views/referentials/index.html.slim
@@ -1,7 +1,7 @@
/ FIXME #827
- current_organisation.workbenches.each do |workbench|
h2 = link_to workbench.name, workbench
- p = "#{workbench.referentials.count} jeu(x) de données à l'heure actuelle"
+ p = t('workbenches.referential_count', count: workbench.referentials.count)
/ FIXME #823
- if false
@@ -11,8 +11,8 @@
- content_for :sidebar do
ul.actions
- li = link_to 'Données Reflex', stop_area_referential_path(1)
- li = link_to 'Données CodifLigne', line_referential_path(1)
+ li = link_to t('reflex_data'), stop_area_referential_path(1)
+ li = link_to t('codif_data'), line_referential_path(1)
li = link_to t('calendars.standard_calendars'), calendars_path
- if false
li = link_to t('referentials.actions.new'), new_referential_path, class: 'add'
diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim
index d3687c3a7..49c152789 100644
--- a/app/views/referentials/show.html.slim
+++ b/app/views/referentials/show.html.slim
@@ -24,7 +24,7 @@
.row
.col-lg-6.col-md-6.col-sm-12.col-xs-12
= definition_list t('metadatas'),
- { 'Statut' => @referential.archived? ? "<div class='td-block'><span class='fa fa-archive'></span><span>Conservé</span></div>".html_safe : "<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>En préparation</span></div>".html_safe,
+ { t('activerecord.attributes.referential.status') => @referential.archived? ? "<div class='td-block'><span class='fa fa-archive'></span><span>#{t('activerecord.attributes.referential.archived_at')}</span></div>".html_safe : "<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>#{t('activerecord.attributes.referential.archived_at_null')}</span></div>".html_safe,
@referential.human_attribute_name(:validity_period) => (@referential.validity_period.present? ? t('validity_range', debut: l(@referential.try(:validity_period).try(:begin), format: :short), end: l(@referential.try(:validity_period).try(:end), format: :short)) : '-'),
@referential.human_attribute_name(:organisation) => @referential.organisation.name,
@referential.human_attribute_name(:published_at) => '-' }
@@ -41,7 +41,7 @@
= table_builder_2 @reflines,
[ \
TableBuilderHelper::Column.new( \
- name: 'ID Codifligne', \
+ name: t('id_codif'), \
attribute: Proc.new { |n| n.objectid.local_id }, \
sortable: false \
), \
@@ -85,17 +85,21 @@
= modalbox 'purgeModal' do
= simple_form_for [@referential, CleanUp.new] do |f|
.modal-header
- h4.modal-title Purger le JDD
+ h4.modal-title #{t('simple_form.labels.clean_up.title')}
.modal-body
.container-fluid
.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
+ button.btn.btn-link type='button' data-dismiss='modal' #{t('cancel')}
- unless policy(@referential).archived?
= f.button :submit, t('actions.clean_up') , class: 'btn btn-primary'
diff --git a/app/views/routing_constraint_zones/new.html.slim b/app/views/routing_constraint_zones/new.html.slim
index 4e792f8af..600663b18 100644
--- a/app/views/routing_constraint_zones/new.html.slim
+++ b/app/views/routing_constraint_zones/new.html.slim
@@ -12,7 +12,7 @@
.row
.col-lg-12
= form.input :name
- = form.input :route_id, collection: @line.routes, include_blank: false, input_html: {data: {url: new_referential_line_routing_constraint_zone_path(@referential, @line), object: @routing_constraint_zone.to_json }}
+ = form.input :route_id, collection: @line.routes, include_blank: false, input_html: { class: 'new_routing_constraint_zone_route', data: {url: new_referential_line_routing_constraint_zone_path(@referential, @line), object: @routing_constraint_zone.to_json }}
.separator
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/_filters.html.slim b/app/views/workbenches/_filters.html.slim
index d7ac79577..8da7ecf51 100644
--- a/app/views/workbenches/_filters.html.slim
+++ b/app/views/workbenches/_filters.html.slim
@@ -1,24 +1,24 @@
= search_form_for @q_for_form, url: workbench_path(@workbench.id), builder: SimpleForm::FormBuilder, class: 'form form-filter' do |f|
.ffg-row
.input-group.search_bar
- = f.search_field :name_cont, class: 'form-control', placeholder: 'Indiquez un nom de référentiel...'
+ = f.search_field :name_cont, class: 'form-control', placeholder: t('referentials.filters.name')
span.input-group-btn
button.btn.btn-default type='submit'
span.fa.fa-search
.ffg-row
.form-group
- = f.label 'Ligne', required: false, class: 'control-label'
- = f.input :associated_lines_id_eq, as: :select, collection: @workbench.lines.includes(:company).order(:name), input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Indiquez une ligne...' }, label: false, label_method: :display_name, wrapper_html: { class: 'select2ed'}
+ = f.label t('activerecord.models.line.one').upcase, required: false, class: 'control-label'
+ = f.input :associated_lines_id_eq, as: :select, collection: @workbench.lines.includes(:company).order(:name), input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': t('referentials.filters.line') }, label: false, label_method: :display_name, wrapper_html: { class: 'select2ed'}
.form-group.togglable
= f.label Referential.human_attribute_name(:status), required: false, class: 'control-label'
.form-group.checkbox_list
- = f.input :archived_at_not_null, label: ("<span>Conservé<span class='fa fa-archive'></span></span>").html_safe, as: :boolean, wrapper_html: { class: 'checkbox-wrapper' }
- = f.input :archived_at_null, label: ("<span>En préparation<span class='sb sb-lg sb-preparing'></span></span>").html_safe, as: :boolean, wrapper_html: { class: 'checkbox-wrapper' }
+ = f.input :archived_at_not_null, label: ("<span>#{t('activerecord.attributes.referential.archived_at')}<span class='fa fa-archive'></span></span>").html_safe, as: :boolean, wrapper_html: { class: 'checkbox-wrapper' }
+ = f.input :archived_at_null, label: ("<span>#{t('activerecord.attributes.referential.archived_at_null')}<span class='sb sb-lg sb-preparing'></span></span>").html_safe, as: :boolean, wrapper_html: { class: 'checkbox-wrapper' }
.form-group.togglable
- = f.label 'Organisation(s)', required: false, class: 'control-label'
+ = f.label t('activerecord.models.organisation.one'), required: false, class: 'control-label'
= f.input :organisation_name_eq_any, collection: Organisation.order('name').pluck(:name), as: :check_boxes, label: false, label_method: lambda{|w| ("<span>#{w}</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }
.form-group.togglable
@@ -29,5 +29,5 @@
= p.input :end_lteq, as: :date, label: t('simple_form.to'), wrapper_html: { class: 'date smart_date filter_menu-item' }, default: @end_range, include_blank: @end_range ? false : true
.actions
- = link_to 'Effacer', @workbench, class: 'btn btn-link'
- = f.submit 'Filtrer', class: 'btn btn-default'
+ = link_to t('actions.erase'), @workbench, class: 'btn btn-link'
+ = f.submit t('actions.filter'), class: 'btn btn-default'
diff --git a/app/views/workbenches/index.html.slim b/app/views/workbenches/index.html.slim
index 1bd116a85..ca61d439d 100644
--- a/app/views/workbenches/index.html.slim
+++ b/app/views/workbenches/index.html.slim
@@ -33,14 +33,14 @@
h3.panel-title.with_actions
div
= t('.offers.referentials')
- span.badge.ml-xs = @workbench.referentials.count if @workbench.all_referentials.any?
+ 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 @workbench.all_referentials.any?
+ - if @referentials.any?
.list-group
- - @workbench.all_referentials.each_with_index do |referential, i|
+ - @referentials.each_with_index do |referential, i|
= link_to referential.name, referential_path(referential), class: 'list-group-item' if i < 6
- else
diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim
index bb8b71ab2..6a41ca569 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
@@ -31,7 +31,7 @@
), \
TableBuilderHelper::Column.new( \
key: :status, \
- attribute: Proc.new {|w| w.archived? ? ("<div class='td-block'><span class='fa fa-archive'></span><span>Conservé</span></div>").html_safe : ("<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>En préparation</span></div>").html_safe} \
+ attribute: Proc.new {|w| w.archived? ? ("<div class='td-block'><span class='fa fa-archive'></span><span>#{t('activerecord.attributes.referential.archived_at')}</span></div>").html_safe : ("<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>#{t('activerecord.attributes.referential.archived_at_null')}</span></div>").html_safe} \
), \
TableBuilderHelper::Column.new( \
key: :organisation, \
@@ -43,7 +43,7 @@
), \
TableBuilderHelper::Column.new( \
key: :lines, \
- name: 'Nb lignes', \
+ name: t('activerecord.attributes.referential.number_of_lines'), \
attribute: Proc.new {|w| w.lines.count} \
), \
TableBuilderHelper::Column.new( \
diff --git a/config/locales/actions.en.yml b/config/locales/actions.en.yml
index f6979136a..36b76d01c 100644
--- a/config/locales/actions.en.yml
+++ b/config/locales/actions.en.yml
@@ -17,6 +17,8 @@ en:
combine: 'Combine'
actualize: 'Actualize'
import: 'Import'
+ filter: 'Filter'
+ erase: 'Erase'
or: "or"
cancel: "Cancel"
search_hint: "Type in a search term"
diff --git a/config/locales/actions.fr.yml b/config/locales/actions.fr.yml
index 86e72088a..f581142c7 100644
--- a/config/locales/actions.fr.yml
+++ b/config/locales/actions.fr.yml
@@ -17,6 +17,8 @@ fr:
combine: 'Combiner'
actualize: 'Actualiser'
import: 'Importer'
+ filter: 'Filtrer'
+ erase: 'Effacer'
or: "ou"
cancel: "Annuler"
search_hint: "Entrez un texte à rechercher"
diff --git a/config/locales/clean_ups.en.yml b/config/locales/clean_ups.en.yml
index fcfcfec7b..876694592 100644
--- a/config/locales/clean_ups.en.yml
+++ b/config/locales/clean_ups.en.yml
@@ -34,3 +34,7 @@ en:
presence: "A clean up must have a begin date"
end_date:
presence: "A clean up must have a end date"
+ simple_form:
+ labels:
+ clean_up:
+ title: "Clean Up the referential"
diff --git a/config/locales/clean_ups.fr.yml b/config/locales/clean_ups.fr.yml
index e2db82998..59d7c5dbc 100644
--- a/config/locales/clean_ups.fr.yml
+++ b/config/locales/clean_ups.fr.yml
@@ -33,3 +33,7 @@ fr:
presence: "Une purge doit avoir une date de début"
end_date:
presence: "Une purge doit avoir une date de fin"
+ simple_form:
+ labels:
+ clean_up:
+ title: "Purger le JDD"
diff --git a/config/locales/en.yml b/config/locales/en.yml
index b25f5fd7f..b65484bc2 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -55,4 +55,7 @@ en:
id_codif: 'Codifligne ID'
id_reflex: 'Reflex ID'
+ codif_data: 'Codifligne datas'
+ reflex_data: 'Reflex datas'
objectid: 'ID'
+ brandname: IBOO
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 8ef183d91..49e41a570 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -55,4 +55,7 @@ fr:
id_codif: 'ID Codifligne'
id_reflex: 'ID Reflex'
+ codif_data: 'Données Codifligne'
+ reflex_data: 'Données Reflex'
objectid: 'ID'
+ brandname: IBOO
diff --git a/config/locales/mailers.en.yml b/config/locales/mailers.en.yml
index 9f89c9d46..857033401 100644
--- a/config/locales/mailers.en.yml
+++ b/config/locales/mailers.en.yml
@@ -1,9 +1,10 @@
en:
mailers:
calendar_mailer:
+ sent_by: "Sent by"
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}
+ body: "A new shared calendar %{cal_name} has been added by STIF. You can now view it in the <a href='%{cal_index_url}' target='_blank' style='color:#333333;'>list of shared calendars</a>."
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}
+ body: "A new shared calendar %{cal_name} has been updated by STIF. You can now view it in the <a href='%{cal_index_url}' target='_blank' style='color:#333333;'>list of shared calendars</a>."
diff --git a/config/locales/mailers.fr.yml b/config/locales/mailers.fr.yml
index a448f13d9..74af036de 100644
--- a/config/locales/mailers.fr.yml
+++ b/config/locales/mailers.fr.yml
@@ -1,9 +1,10 @@
fr:
mailers:
calendar_mailer:
+ sent_by: "Envoyé par"
created:
subject: Un nouveau calendrier partagé à été ajouté
- body: 'Un calendrier partagé %{cal_name} a été ajouté par le STIF. Vous pouvez maintenant le consulter dans la liste des calendriers partagés : %{cal_index_url}'
+ body: "Un calendrier partagé %{cal_name} a été ajouté par le STIF. Vous pouvez maintenant le consulter dans la <a href='%{cal_index_url}' target='_blank' style='color:#333333;'>liste des calendriers partagés</a>."
updated:
- subject: Un nouveau calendrier partagé à été mise à jour
- body: 'Un calendrier partagé %{cal_name} a été mis à jour par le STIF. Vous pouvez maintenant le consulter dans la liste des calendriers partagés : %{cal_index_url}'
+ subject: Un nouveau calendrier partagé à été mis à jour
+ body: "Un calendrier partagé %{cal_name} a été mis à jour par le STIF. Vous pouvez maintenant le consulter dans la <a href='%{cal_index_url}' target='_blank' style='color:#333333;'>liste des calendriers partagés</a>."
diff --git a/config/locales/organisations.en.yml b/config/locales/organisations.en.yml
index 617e61ca2..a64920daf 100644
--- a/config/locales/organisations.en.yml
+++ b/config/locales/organisations.en.yml
@@ -10,6 +10,11 @@ en:
users: "Users"
rule_parameter_sets: "Rule parameter sets"
activerecord:
+ models:
+ organisation:
+ zero: "organization"
+ one: "organization"
+ other: "organizations"
attributes:
organisation:
name: "Name"
diff --git a/config/locales/organisations.fr.yml b/config/locales/organisations.fr.yml
index db7482fbc..50cb9f3be 100644
--- a/config/locales/organisations.fr.yml
+++ b/config/locales/organisations.fr.yml
@@ -10,6 +10,11 @@ fr:
users: "Utilisateurs"
rule_parameter_sets: "Jeux de paramètres"
activerecord:
+ models:
+ organisation:
+ zero: "organisation"
+ one: "organisation"
+ other: "organisations"
attributes:
organisation:
name: "Nom"
diff --git a/config/locales/referentials.en.yml b/config/locales/referentials.en.yml
index 5f39f03f4..e29df7cf4 100644
--- a/config/locales/referentials.en.yml
+++ b/config/locales/referentials.en.yml
@@ -2,6 +2,8 @@ en:
referentials:
filters:
name_or_number_or_objectid: 'Search by name, number or objectid'
+ name: 'Search by name'
+ line: 'Seach by associated lines'
search_no_results: 'No data space matching your query'
index:
title: 'Data spaces'
@@ -59,7 +61,6 @@ en:
upper_corner: "Top,Right corner for default bounding box"
lower_corner: "Bottom,Left corner for default bounding box"
resources: "Neptune Import File"
- validity_period: "Validity period"
no_validity_period: "undefined"
start_validity_period: "from"
end_validity_period: "to"
@@ -86,14 +87,16 @@ en:
data_format: "Favorite format for export"
timebands: "Time bands"
routing_constraint_zone: Routing constraint zone
- validity_period: "Validity period"
+ validity_period: "Inclusive validity period"
updated_at: "Updated"
published_at: "Integrated"
archived_at: "Archived"
+ archived_at_null: "Unarchived"
created_from: 'Created from'
updated_at: "Updated"
created_at: "Created"
organisation: 'Organisation'
+ number_of_lines: 'No. of lines'
formtastic:
titles:
referential:
@@ -112,6 +115,10 @@ en:
periods:
begin: 'Period beginning'
end: 'Period end'
+ actions:
+ add_period: 'Add a period'
+ placeholders:
+ select_lines: 'Selection of lignes'
notice:
referentials:
diff --git a/config/locales/referentials.fr.yml b/config/locales/referentials.fr.yml
index f69c26276..643295c0e 100644
--- a/config/locales/referentials.fr.yml
+++ b/config/locales/referentials.fr.yml
@@ -2,6 +2,8 @@ fr:
referentials:
filters:
name_or_number_or_objectid: 'Indiquez un nom de ligne, nom court ou objectid'
+ name: 'Indiquez un nom de référentiel...'
+ line: 'Indiquez une ligne...'
search_no_results: 'Aucun jeu de données ne correspond à votre recherche'
index:
title: 'Jeux de données'
@@ -59,7 +61,6 @@ fr:
upper_corner: "Point haut/droite de l'emprise par défaut"
lower_corner: "Point bas/gauche de l'emprise par défaut"
resources: "Import Neptune"
- validity_period: "Période de validité"
no_validity_period: "non définie"
start_validity_period: "du"
end_validity_period: "au"
@@ -91,8 +92,10 @@ fr:
created_at: "Créé le"
published_at: "Intégré le"
archived_at: "Conservé"
+ archived_at_null: "En préparation"
created_from: 'Créé à partir de'
organisation: 'Organisation'
+ number_of_lines: 'Nb lignes'
formtastic:
titles:
referential:
@@ -111,6 +114,10 @@ fr:
periods:
begin: 'Début de période'
end: 'Fin de période'
+ actions:
+ add_period: 'Ajouter une période'
+ placeholders:
+ select_lines: 'Sélection de lignes'
notice:
referentials:
deleted: "Les jeux de données on été supprimés"
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
index 8525a4b9f..8a458e118 100644
--- a/config/locales/workbenches.en.yml
+++ b/config/locales/workbenches.en.yml
@@ -10,3 +10,7 @@ en:
calendars: "Calendars"
see: "See the list"
no_content: "No content yet."
+ referential_count:
+ zero: "Currently, there is no referential in your workbench"
+ one: "Currently, there is one referential in your workbench"
+ other: "Currently, there are #{count} referentials in your workbench"
diff --git a/config/locales/workbenches.fr.yml b/config/locales/workbenches.fr.yml
index 1cdc19a13..85c5259b8 100644
--- a/config/locales/workbenches.fr.yml
+++ b/config/locales/workbenches.fr.yml
@@ -10,3 +10,7 @@ fr:
calendars: "Calendriers"
see: "Voir la liste"
no_content: "Aucun contenu pour le moment"
+ referential_count:
+ zero: "Aucun jeu de données à l'heure actuelle"
+ one: "1 jeu de données à l'heure actuelle"
+ other: "#{count} jeux de données à l'heure actuelle"
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/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/features/workbenches_spec.rb b/spec/features/workbenches_spec.rb
index 9141b5673..536469a46 100644
--- a/spec/features/workbenches_spec.rb
+++ b/spec/features/workbenches_spec.rb
@@ -36,7 +36,7 @@ describe 'Workbenches', type: :feature do
context 'without any filter' do
it 'should have results' do
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
expect(page).to have_content(referential.name)
expect(page).to have_content(other_referential.name)
end
@@ -45,7 +45,7 @@ describe 'Workbenches', type: :feature do
context 'filter by organisation' do
it 'should be possible to filter by organisation' do
find("#q_organisation_name_eq_any_#{@user.organisation.name.parameterize.underscore}").set(true)
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
expect(page).to have_content(referential.name)
expect(page).not_to have_content(other_referential.name)
@@ -54,7 +54,7 @@ describe 'Workbenches', type: :feature do
it 'should be possible to filter by multiple organisation' do
find("#q_organisation_name_eq_any_#{@user.organisation.name.parameterize.underscore}").set(true)
find("#q_organisation_name_eq_any_#{another_organisation.name.parameterize.underscore}").set(true)
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
expect(page).to have_content(referential.name)
expect(page).to have_content(other_referential.name)
@@ -63,7 +63,7 @@ describe 'Workbenches', type: :feature do
it 'should keep filter value on submit' do
box = "#q_organisation_name_eq_any_#{another_organisation.name.parameterize.underscore}"
find(box).set(true)
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
expect(find(box)).to be_checked
end
end
@@ -73,7 +73,7 @@ describe 'Workbenches', type: :feature do
other_referential.update_attribute(:archived_at, Date.today)
find("#q_archived_at_not_null").set(true)
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
expect(page).to have_content(other_referential.name)
expect(page).to_not have_content(referential.name)
end
@@ -83,7 +83,7 @@ describe 'Workbenches', type: :feature do
find("#q_archived_at_not_null").set(true)
find("#q_archived_at_null").set(true)
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
expect(page).to have_content(referential.name)
expect(page).to have_content(other_referential.name)
end
@@ -92,14 +92,14 @@ describe 'Workbenches', type: :feature do
other_referential.update_attribute(:archived_at, Date.today)
find("#q_archived_at_null").set(true)
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
expect(page).to have_content(referential.name)
expect(page).to_not have_content(other_referential.name)
end
it 'should keep filter value on submit' do
find("#q_archived_at_null").set(true)
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
expect(find("#q_archived_at_null")).to be_checked
end
end
@@ -115,7 +115,7 @@ describe 'Workbenches', type: :feature do
dates = referential.validity_period.to_a
fill_validity_field dates[0], 'begin_gteq'
fill_validity_field dates[1], 'end_lteq'
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
expect(page).to have_content(referential.name)
expect(page).to_not have_content(other_referential.name)
@@ -125,7 +125,7 @@ describe 'Workbenches', type: :feature do
dates = referential.validity_period.to_a
fill_validity_field dates[0], 'begin_gteq'
fill_validity_field dates[1], 'end_lteq'
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
find('a[href*="&sort=validity_period"]').click
@@ -136,7 +136,7 @@ describe 'Workbenches', type: :feature do
it 'should not show results for out off range' do
fill_validity_field(Date.today - 2.year, 'begin_gteq')
fill_validity_field(Date.today - 1.year, 'end_lteq')
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
expect(page).to_not have_content(referential.name)
expect(page).to_not have_content(other_referential.name)
@@ -147,7 +147,7 @@ describe 'Workbenches', type: :feature do
['begin_gteq', 'end_lteq'].each_with_index do |field, index|
fill_validity_field dates[index], field
end
- click_button 'Filtrer'
+ click_button I18n.t('actions.filter')
['begin_gteq', 'end_lteq'].each_with_index do |field, index|
expect(find("#q_validity_period_#{field}_3i").value).to eq dates[index].day.to_s
diff --git a/spec/javascripts/itineraries/reducers/stop_points_spec.js b/spec/javascripts/itineraries/reducers/stop_points_spec.js
index 93fe85d36..0331a424c 100644
--- a/spec/javascripts/itineraries/reducers/stop_points_spec.js
+++ b/spec/javascripts/itineraries/reducers/stop_points_spec.js
@@ -16,6 +16,7 @@ describe('stops reducer', () => {
{
text: 'first',
index: 0,
+ stoppoint_id: 72,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -27,6 +28,7 @@ describe('stops reducer', () => {
{
text: 'second',
index: 1,
+ stoppoint_id: 73,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -54,6 +56,7 @@ describe('stops reducer', () => {
{
text: 'first',
index: 0,
+ stoppoint_id: 72,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -65,6 +68,7 @@ describe('stops reducer', () => {
{
text: 'second',
index: 1,
+ stoppoint_id: 73,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -99,6 +103,7 @@ describe('stops reducer', () => {
{
text: 'second',
index: 1,
+ stoppoint_id: 72,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -110,6 +115,7 @@ describe('stops reducer', () => {
{
text: 'first',
index: 0,
+ stoppoint_id: 73,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -133,6 +139,7 @@ describe('stops reducer', () => {
{
text: 'second',
index: 1,
+ stoppoint_id: 72,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -144,6 +151,7 @@ describe('stops reducer', () => {
{
text: 'first',
index: 0,
+ stoppoint_id: 73,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -156,28 +164,29 @@ describe('stops reducer', () => {
)
})
- it('should handle DELETE_STOP', () => {
- expect(
- stopPointsReducer(state, {
- type: 'DELETE_STOP',
- index: 1
- })
- ).toEqual(
- [
- {
- text: 'first',
- index: 0,
- edit: false,
- for_boarding: 'normal',
- for_alighting: 'normal',
- olMap: {
- isOpened: false,
- json: {}
- }
- }
- ]
- )
- })
+ // it('should handle DELETE_STOP', () => {
+ // expect(
+ // stopPointsReducer(state, {
+ // type: 'DELETE_STOP',
+ // index: 1
+ // })
+ // ).toEqual(
+ // [
+ // {
+ // text: 'first',
+ // index: 0,
+ // stoppoint_id: 72,
+ // edit: false,
+ // for_boarding: 'normal',
+ // for_alighting: 'normal',
+ // olMap: {
+ // isOpened: false,
+ // json: {}
+ // }
+ // }
+ // ]
+ // )
+ // })
it('should handle UPDATE_INPUT_VALUE', () => {
expect(
@@ -205,8 +214,8 @@ describe('stops reducer', () => {
text: 'new value',
name: 'new',
index: 0,
+ stoppoint_id: 72,
edit: false,
- stoppoint_id: '',
stoparea_id: 1,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -226,6 +235,7 @@ describe('stops reducer', () => {
{
text: 'second',
index: 1,
+ stoppoint_id: 73,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -251,6 +261,7 @@ describe('stops reducer', () => {
{
text: 'first',
index: 0,
+ stoppoint_id: 72,
edit: false,
for_boarding: 'prohibited',
for_alighting: 'normal',
@@ -262,6 +273,7 @@ describe('stops reducer', () => {
{
text: 'second',
index: 1,
+ stoppoint_id: 73,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -285,6 +297,7 @@ describe('stops reducer', () => {
{
text: 'first',
index: 0,
+ stoppoint_id: 72,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -293,6 +306,7 @@ describe('stops reducer', () => {
json: {
text: 'first',
index: 0,
+ stoppoint_id: 72,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -303,6 +317,7 @@ describe('stops reducer', () => {
{
text: 'second',
index: 1,
+ stoppoint_id: 73,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -326,6 +341,7 @@ describe('stops reducer', () => {
{
text: 'first',
index: 0,
+ stoppoint_id: 72,
edit: true,
for_boarding: 'normal',
for_alighting: 'normal',
@@ -337,6 +353,7 @@ describe('stops reducer', () => {
{
text: 'second',
index: 1,
+ stoppoint_id: 73,
edit: false,
for_boarding: 'normal',
for_alighting: 'normal',
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/mailers/calendar_mailer_spec.rb b/spec/mailers/calendar_mailer_spec.rb
index 49cc3cce8..9a2076f64 100644
--- a/spec/mailers/calendar_mailer_spec.rb
+++ b/spec/mailers/calendar_mailer_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe CalendarMailer, type: :mailer do
shared_examples 'notify all user' do |type|
let!(:user) { create(:user) }
let(:calendar) { create(:calendar, shared: true) }
- let(:email) { CalendarMailer.send(type, calendar, user) }
+ let(:email) { CalendarMailer.send(type, calendar.id, user.id) }
it 'should deliver email to user' do
expect(email).to deliver_to user.email
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/journey_pattern_spec.rb b/spec/models/chouette/journey_pattern_spec.rb
index 6601ed5f4..26d220056 100644
--- a/spec/models/chouette/journey_pattern_spec.rb
+++ b/spec/models/chouette/journey_pattern_spec.rb
@@ -2,30 +2,30 @@ require 'spec_helper'
describe Chouette::JourneyPattern, :type => :model do
- context 'validate minimum stop_points size' do
- let(:journey_pattern) { create :journey_pattern }
- let(:stop_points) { journey_pattern.stop_points }
-
- it 'should be valid if it has at least two sp' do
- journey_pattern.stop_points.first(stop_points.size - 2).each do |sp|
- journey_pattern.stop_points.delete(sp)
- end
- expect(journey_pattern).to be_valid
- end
-
- it 'should not be valid if it has less then two sp' do
- journey_pattern.stop_points.first(stop_points.size - 1).each do |sp|
- journey_pattern.stop_points.delete(sp)
- end
- expect(journey_pattern).to_not be_valid
- expect(journey_pattern.errors).to have_key(:stop_points)
- end
-
- it 'should only validate on update' do
- jp = build(:journey_pattern_common)
- expect(jp).to be_valid
- end
- end
+ # context 'validate minimum stop_points size' do
+ # let(:journey_pattern) { create :journey_pattern }
+ # let(:stop_points) { journey_pattern.stop_points }
+ #
+ # it 'should be valid if it has at least two sp' do
+ # journey_pattern.stop_points.first(stop_points.size - 2).each do |sp|
+ # journey_pattern.stop_points.delete(sp)
+ # end
+ # expect(journey_pattern).to be_valid
+ # end
+ #
+ # it 'should not be valid if it has less then two sp' do
+ # journey_pattern.stop_points.first(stop_points.size - 1).each do |sp|
+ # journey_pattern.stop_points.delete(sp)
+ # end
+ # expect(journey_pattern).to_not be_valid
+ # expect(journey_pattern.errors).to have_key(:stop_points)
+ # end
+ #
+ # it 'should only validate on update' do
+ # jp = build(:journey_pattern_common)
+ # expect(jp).to be_valid
+ # end
+ # end
describe "state_update" do
def journey_pattern_to_state jp
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/routing_constraint_zone_spec.rb b/spec/models/chouette/routing_constraint_zone_spec.rb
index 87ee9e9ac..0165c369d 100644
--- a/spec/models/chouette/routing_constraint_zone_spec.rb
+++ b/spec/models/chouette/routing_constraint_zone_spec.rb
@@ -29,7 +29,7 @@ describe Chouette::RoutingConstraintZone, type: :model do
}.to raise_error(ActiveRecord::RecordInvalid)
end
- it 'validates that not all stop points from the route are selected' do
+ xit 'validates that not all stop points from the route are selected' do
routing_constraint_zone.stop_points = routing_constraint_zone.route.stop_points
expect {
routing_constraint_zone.save!
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 c495becac..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 }
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/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