aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--INSTALL.md6
-rw-r--r--app/assets/javascripts/select2.coffee6
-rw-r--r--app/assets/stylesheets/components/_main_nav.sass32
-rw-r--r--app/assets/stylesheets/modules/_jp_collection.sass7
-rw-r--r--app/controllers/application_controller.rb5
-rw-r--r--app/controllers/compliance_check_messages_controller.rb34
-rw-r--r--app/controllers/compliance_check_sets_controller.rb4
-rw-r--r--app/controllers/import_messages_controller.rb2
-rw-r--r--app/controllers/journey_patterns_collections_controller.rb1
-rw-r--r--app/controllers/merges_controller.rb2
-rw-r--r--app/controllers/vehicle_journeys_controller.rb9
-rw-r--r--app/decorators/network_decorator.rb2
-rw-r--r--app/helpers/compliance_check_resources_helper.rb12
-rw-r--r--app/javascript/helpers/save_button.js47
-rw-r--r--app/javascript/helpers/stop_area_header_manager.js9
-rw-r--r--app/javascript/journey_patterns/components/JourneyPattern.js65
-rw-r--r--app/javascript/journey_patterns/components/SaveJourneyPattern.js38
-rw-r--r--app/javascript/packs/vehicle_journeys/index.js3
-rw-r--r--app/javascript/vehicle_journeys/components/SaveVehicleJourneys.js38
-rw-r--r--app/javascript/vehicle_journeys/components/tools/CreateModal.js9
-rw-r--r--app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js50
-rw-r--r--app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js17
-rw-r--r--app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js1
-rw-r--r--app/javascript/vehicle_journeys/reducers/custom_fields.js6
-rw-r--r--app/javascript/vehicle_journeys/reducers/index.js4
-rw-r--r--app/javascript/vehicle_journeys/reducers/modal.js9
-rw-r--r--app/javascript/vehicle_journeys/reducers/vehicleJourneys.js31
-rw-r--r--app/models/chouette/company.rb2
-rw-r--r--app/models/chouette/journey_pattern.rb2
-rw-r--r--app/models/chouette/line.rb2
-rw-r--r--app/models/chouette/network.rb2
-rw-r--r--app/models/chouette/stop_area.rb12
-rw-r--r--app/models/chouette/vehicle_journey.rb20
-rw-r--r--app/models/chouette/vehicle_journey_at_stop.rb32
-rw-r--r--app/models/compliance_check_message_export.rb46
-rw-r--r--app/models/compliance_check_set.rb8
-rw-r--r--app/models/custom_field.rb3
-rw-r--r--app/models/import_message_export.rb4
-rw-r--r--app/models/merge.rb3
-rw-r--r--app/models/referential.rb12
-rw-r--r--app/models/workbench.rb7
-rw-r--r--app/models/workgroup.rb5
-rw-r--r--app/policies/network_policy.rb11
-rw-r--r--app/policies/referential_policy.rb4
-rw-r--r--app/views/api/v1/journey_patterns/show.rabl1
-rw-r--r--app/views/autocomplete_stop_areas/around.rabl2
-rw-r--r--app/views/autocomplete_stop_areas/index.rabl2
-rw-r--r--app/views/compliance_check_sets/executed.html.slim2
-rw-r--r--app/views/compliance_check_sets/index.html.slim10
-rw-r--r--app/views/compliance_check_sets/show.html.slim43
-rw-r--r--app/views/import_resources/index.html.slim2
-rw-r--r--app/views/networks/_form.html.slim10
-rw-r--r--app/views/networks/show.html.slim6
-rw-r--r--app/views/referential_vehicle_journeys/index.html.slim2
-rw-r--r--app/views/referentials/show.html.slim2
-rw-r--r--app/views/vehicle_journeys/index.html.slim3
-rw-r--r--app/views/vehicle_journeys/show.rabl10
-rw-r--r--app/views/workbenches/_filters.html.slim8
-rw-r--r--app/views/workbenches/show.html.slim4
-rw-r--r--config/breadcrumbs.rb5
-rw-r--r--config/locales/area_types.en.yml1
-rw-r--r--config/locales/compliance_check_messages.en.yml31
-rw-r--r--config/locales/compliance_check_messages.fr.yml31
-rw-r--r--config/locales/compliance_check_results.en.yml2
-rw-r--r--config/locales/compliance_check_results.fr.yml2
-rw-r--r--config/locales/compliance_check_sets.en.yml15
-rw-r--r--config/locales/compliance_check_sets.fr.yml21
-rw-r--r--config/locales/import_messages.en.yml103
-rw-r--r--config/locales/import_messages.fr.yml103
-rw-r--r--config/locales/lines.en.yml4
-rw-r--r--config/locales/lines.fr.yml4
-rw-r--r--config/locales/referentials.en.yml2
-rw-r--r--config/locales/referentials.fr.yml2
-rw-r--r--config/locales/stop_areas.en.yml2
-rw-r--r--config/locales/stop_areas.fr.yml2
-rw-r--r--config/routes.rb1
-rw-r--r--db/migrate/20180111200406_add_merged_at_to_referentials.rb5
-rw-r--r--db/schema.rb3
-rw-r--r--package.json2
-rw-r--r--spec/decorators/referential_decorator_spec.rb1
-rw-r--r--spec/factories/chouette_vehicle_journey_at_stop.rb2
-rw-r--r--spec/features/compliance_check_sets_spec.rb2
-rw-r--r--spec/features/workbenches/workbenches_show_spec.rb72
-rw-r--r--spec/helpers/table_builder_helper_spec.rb4
-rw-r--r--spec/javascript/time_table/reducers/timetable_spec.js3
-rw-r--r--spec/javascript/vehicle_journeys/components/CustomFieldsInputs_spec.js41
-rw-r--r--spec/javascript/vehicle_journeys/components/__snapshots__/CustomFieldsInputs_spec.js.snap3
-rw-r--r--spec/javascript/vehicle_journeys/reducers/vehicleJourneys_spec.js137
-rw-r--r--spec/models/chouette/vehicle_journey_at_stop_spec.rb24
-rw-r--r--spec/models/chouette/vehicle_journey_spec.rb43
-rw-r--r--spec/models/custom_field_spec.rb12
-rw-r--r--spec/policies/network_policy_spec.rb10
-rw-r--r--spec/policies/referential_policy_spec.rb7
-rw-r--r--spec/views/offer_workbenches/show.html.erb_spec.rb8
-rw-r--r--yarn.lock4
95 files changed, 1107 insertions, 338 deletions
diff --git a/INSTALL.md b/INSTALL.md
index 5ed8ca9f1..9e04730f7 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -169,6 +169,8 @@ bundle exec rake referential:create
#### Run tests
+#### Rspec
+
```sh
bundle exec rake spec
bundle exec rake teaspoon
@@ -180,7 +182,11 @@ If Postgres complains about illegal type `hstore` or `unaccent` in your tests th
Thanks to `lib/tasks/extensions.rake`.
+#### Jest (React integration specs)
+
+`grunt jest` to run the whole specs.
+`grunt` to watch for changes and automatically run corresponding tests.
#### Start local server
diff --git a/app/assets/javascripts/select2.coffee b/app/assets/javascripts/select2.coffee
index 4cf5f42d0..05b73dc6b 100644
--- a/app/assets/javascripts/select2.coffee
+++ b/app/assets/javascripts/select2.coffee
@@ -27,9 +27,9 @@ bind_select2_ajax = (el, cfg = {}) ->
item.text
escapeMarkup: (markup) ->
markup
- initSelection : (item, callback) ->
- if _this.data('initvalue')
- callback(_this.data('initvalue'))
+
+ if _this.data('initvalue')
+ cfg["initSelection"] = (item, callback) -> callback(_this.data('initvalue'))
bind_select2(el, cfg)
diff --git a/app/assets/stylesheets/components/_main_nav.sass b/app/assets/stylesheets/components/_main_nav.sass
index f102c4617..2af070389 100644
--- a/app/assets/stylesheets/components/_main_nav.sass
+++ b/app/assets/stylesheets/components/_main_nav.sass
@@ -245,7 +245,7 @@ $menuW: 300px
& > .menu-item
max-width: 75%
-
+
.menu-item
padding: 0 10px
@@ -337,47 +337,35 @@ $menuW: 300px
height: $menuH
padding: 0 50px 0 75px
margin-top: -4px
+ display: flex
> *
display: inline-block
&.sticky-ptitle
- width: 60%
+ flex: 1 1
height: $menuH
+ position: relative
h1
- position: relative
+ position: absolute
+ left: 0
+ right: 10px
+ top: 0
line-height: 1.1
white-space: nowrap
max-height: 1.1em
margin: 0 -1.4em 0 0
padding: 0 1.4em 5px 0
overflow: hidden
-
- &:before
- content: '[...]'
- font-size: 0.65em
- position: absolute
- z-index: 6
- right: 0
- bottom: 9px
-
- &:after
- content: ''
- position: absolute
- z-index: 5
- right: 0
- width: 1.4em
- height: 1em
- margin-top: 0.2em
- background-color: $blue
+ text-overflow: ellipsis
.small.fa
color: #fff
margin-left: 0.5em
&.sticky-paction
- width: 40%
+ flex: 0 0 auto
text-align: right
vertical-align: top
diff --git a/app/assets/stylesheets/modules/_jp_collection.sass b/app/assets/stylesheets/modules/_jp_collection.sass
index 9d68a217f..b4370a5ac 100644
--- a/app/assets/stylesheets/modules/_jp_collection.sass
+++ b/app/assets/stylesheets/modules/_jp_collection.sass
@@ -5,7 +5,6 @@
#journey_patterns
.table-2entries
.t2e-head
-
> .td
position: relative
padding-left: 25px
@@ -119,6 +118,12 @@
.td
padding: 15px 8px
+ .totals
+ color: $blue
+ padding-top: 4px
+ i
+ padding-right: 3px
+
$link-size: 10px
.link
position: absolute
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 474277da1..80d194096 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -41,6 +41,11 @@ class ApplicationController < ActionController::Base
end
helper_method :current_offer_workbench
+ def current_workgroup
+ current_offer_workbench.workgroup
+ end
+ helper_method :current_workgroup
+
def current_functional_scope
functional_scope = current_organisation.sso_attributes.try(:[], "functional_scope") if current_organisation
JSON.parse(functional_scope) if functional_scope
diff --git a/app/controllers/compliance_check_messages_controller.rb b/app/controllers/compliance_check_messages_controller.rb
new file mode 100644
index 000000000..7c416584e
--- /dev/null
+++ b/app/controllers/compliance_check_messages_controller.rb
@@ -0,0 +1,34 @@
+class ComplianceCheckMessagesController < ChouetteController
+ defaults resource_class: ComplianceCheckMessage, collection_name: 'compliance_check_messages', instance_name: 'compliance_check_message'
+ respond_to :csv
+ belongs_to :compliance_check_set, :parent_class => ComplianceCheckSet
+
+
+ def index
+ index! do |format|
+ format.csv {
+ send_data ComplianceCheckMessageExport.new(compliance_check_messages: collection).to_csv(:col_sep => "\;", :quote_char=>'"', force_quotes: true, server_url: request.base_url) , :filename => "compliance_check_set_errors_#{line_code}_#{Time.now.to_i}.csv"
+ }
+ end
+ end
+
+ protected
+ def collection
+ parent.compliance_check_messages.where(compliance_check_resource_id: params[:compliance_check_resource_id])
+ end
+
+ def parent
+ @compliance_check_set ||= ComplianceCheckSet.find(params[:compliance_check_set_id])
+ end
+
+ def compliance_check_resource
+ ComplianceCheckResource.find(params[:compliance_check_resource_id])
+ end
+
+ private
+
+ def line_code
+ Chouette::Line.find_by_objectid("#{compliance_check_resource.reference}").get_objectid.local_id
+ end
+
+end
diff --git a/app/controllers/compliance_check_sets_controller.rb b/app/controllers/compliance_check_sets_controller.rb
index 600c69126..4ec86f0d6 100644
--- a/app/controllers/compliance_check_sets_controller.rb
+++ b/app/controllers/compliance_check_sets_controller.rb
@@ -21,9 +21,7 @@ class ComplianceCheckSetsController < ChouetteController
def show
show! do
- @compliance_check_set = @compliance_check_set.decorate(context: {
- compliance_check_set: @compliance_check_set
- })
+ @compliance_check_set = @compliance_check_set.decorate
end
end
diff --git a/app/controllers/import_messages_controller.rb b/app/controllers/import_messages_controller.rb
index 6546b25f8..286bb0ce8 100644
--- a/app/controllers/import_messages_controller.rb
+++ b/app/controllers/import_messages_controller.rb
@@ -9,7 +9,7 @@ class ImportMessagesController < ChouetteController
def index
index! do |format|
format.csv {
- send_data ImportMessageExport.new(:import_messages => @import_messages).to_csv(:col_sep => ";") , :filename => "#{File.basename(@import_resource.name)}_#{Time.now.to_i}.csv"
+ send_data ImportMessageExport.new(:import_messages => @import_messages).to_csv(:col_sep => "\;", :quote_char=>'"', force_quotes: true) , :filename => "import_errors_#{@import_resource.name.gsub('.xml', '')}_#{Time.now.to_i}.csv"
}
end
end
diff --git a/app/controllers/journey_patterns_collections_controller.rb b/app/controllers/journey_patterns_collections_controller.rb
index b37ac6cd0..da567779e 100644
--- a/app/controllers/journey_patterns_collections_controller.rb
+++ b/app/controllers/journey_patterns_collections_controller.rb
@@ -44,6 +44,7 @@ class JourneyPatternsCollectionsController < ChouetteController
:zip_code => sp.stop_area.try(:zip_code),
:city_name => sp.stop_area.try(:city_name),
:country_name => sp.stop_area.try(:country_name),
+ :time_zone_formatted_offset => sp.stop_area.try(:time_zone_formatted_offset),
:comment => sp.stop_area.try(:comment),
:area_type => sp.stop_area.try(:area_type),
:registration_number => sp.stop_area.try(:registration_number),
diff --git a/app/controllers/merges_controller.rb b/app/controllers/merges_controller.rb
index a95768139..1ce64ed58 100644
--- a/app/controllers/merges_controller.rb
+++ b/app/controllers/merges_controller.rb
@@ -11,7 +11,7 @@ class MergesController < ChouetteController
private
def set_mergeable_controllers
- @mergeable_referentials ||= parent.referentials.ready.not_in_referential_suite
+ @mergeable_referentials ||= parent.referentials.mergeable
Rails.logger.debug "Mergeables: #{@mergeable_referentials.inspect}"
end
diff --git a/app/controllers/vehicle_journeys_controller.rb b/app/controllers/vehicle_journeys_controller.rb
index 565cccec8..d59696ad7 100644
--- a/app/controllers/vehicle_journeys_controller.rb
+++ b/app/controllers/vehicle_journeys_controller.rb
@@ -49,6 +49,7 @@ class VehicleJourneysController < ChouetteController
end
format.html do
load_missions
+ load_custom_fields
@stop_points_list = []
@stop_points_list = route.stop_points.includes(:stop_area).map do |sp|
{
@@ -59,8 +60,10 @@ class VehicleJourneysController < ChouetteController
:for_boarding => sp.try(:for_boarding),
:for_alighting => sp.try(:for_alighting),
:name => sp.stop_area.try(:name),
+ :time_zone_formatted_offset => sp.stop_area.try(:time_zone_formatted_offset),
:zip_code => sp.stop_area.try(:zip_code),
:city_name => sp.stop_area.try(:city_name),
+ :time_zone_offset => sp.stop_area.try(:time_zone_offset),
:comment => sp.stop_area.try(:comment),
:area_type => sp.stop_area.try(:area_type),
:stop_area_id => sp.stop_area_id,
@@ -176,6 +179,10 @@ class VehicleJourneysController < ChouetteController
end
private
+ def load_custom_fields
+ @custom_fields = current_workgroup.custom_fields_definitions
+ end
+
def load_missions
@all_missions = route.journey_patterns.count > 10 ? [] : route.journey_patterns.map do |item|
{
@@ -186,6 +193,8 @@ class VehicleJourneysController < ChouetteController
published_name: item.published_name,
object_id: item.objectid,
short_id: item.get_objectid.short_id,
+ full_schedule: item.full_schedule?,
+ costs: item.costs,
stop_area_short_descriptions: item.stop_areas.map do |stop|
{
stop_area_short_description: {
diff --git a/app/decorators/network_decorator.rb b/app/decorators/network_decorator.rb
index 1f62fe512..b0a19cf60 100644
--- a/app/decorators/network_decorator.rb
+++ b/app/decorators/network_decorator.rb
@@ -35,7 +35,7 @@ class NetworkDecorator < Draper::Decorator
object
),
method: :delete,
- data: { confirm: t('networks.actions.destroy_confirm') }
+ data: { confirm: h.t('networks.actions.destroy_confirm') }
)
end
diff --git a/app/helpers/compliance_check_resources_helper.rb b/app/helpers/compliance_check_resources_helper.rb
new file mode 100644
index 000000000..95cabed88
--- /dev/null
+++ b/app/helpers/compliance_check_resources_helper.rb
@@ -0,0 +1,12 @@
+module ComplianceCheckResourcesHelper
+
+ # Comlpiance Check Resources statuses helper
+ def compliance_check_resource_status(status)
+ cls = ''
+ cls = 'success' if status == 'OK'
+ cls = 'warning' if status == 'WARNING'
+ cls = 'danger' if %w[ERROR IGNORED].include? status
+
+ content_tag :span, '', class: "fa fa-circle text-#{cls}"
+ end
+end
diff --git a/app/javascript/helpers/save_button.js b/app/javascript/helpers/save_button.js
new file mode 100644
index 000000000..7e0bd5bbe
--- /dev/null
+++ b/app/javascript/helpers/save_button.js
@@ -0,0 +1,47 @@
+import React, { PropTypes, Component } from 'react'
+
+export default class SaveButton extends Component{
+ constructor(props){
+ super(props)
+ }
+
+ btnDisabled(){
+ return !this.props.status.fetchSuccess || this.props.status.isFetching
+ }
+
+ btnClass(){
+ let className = ['btn btn-default']
+ if(this.btnDisabled()){
+ className.push('disabled')
+ }
+ return className.join(' ')
+ }
+
+ render() {
+ if (!this.hasPolicy()) {
+ return false
+ }else{
+ return (
+ <div className='row mt-md'>
+ <div className='col-lg-12 text-right'>
+ <form className={this.formClassName() + ' formSubmitr ml-xs'} onSubmit={e => {e.preventDefault()}}>
+ <div className="btn-group sticky-actions">
+ <button
+ className={this.btnClass()}
+ type='button'
+ disabled={this.btnDisabled()}
+ onClick={e => {
+ e.preventDefault()
+ this.props.editMode ? this.submitForm() : this.props.onEnterEditMode()
+ }}
+ >
+ {this.props.editMode ? "Valider" : "Editer"}
+ </button>
+ </div>
+ </form>
+ </div>
+ </div>
+ )
+ }
+ }
+}
diff --git a/app/javascript/helpers/stop_area_header_manager.js b/app/javascript/helpers/stop_area_header_manager.js
index 54d957be9..c9f397dee 100644
--- a/app/javascript/helpers/stop_area_header_manager.js
+++ b/app/javascript/helpers/stop_area_header_manager.js
@@ -21,7 +21,14 @@ export default class StopAreaHeaderManager {
data-headline={showHeadline}
title={sp.city_name + ' (' + sp.zip_code +')'}
>
- <span><span>{sp.name}</span></span>
+ <span>
+ <span>
+ {sp.name}
+ {sp.time_zone_formatted_offset && <span className="small">
+ &nbsp;({sp.time_zone_formatted_offset})
+ </span>}
+ </span>
+ </span>
</div>
)
}
diff --git a/app/javascript/journey_patterns/components/JourneyPattern.js b/app/javascript/journey_patterns/components/JourneyPattern.js
index 8dc542bc8..ecbebe2cc 100644
--- a/app/javascript/journey_patterns/components/JourneyPattern.js
+++ b/app/javascript/journey_patterns/components/JourneyPattern.js
@@ -74,18 +74,60 @@ export default class JourneyPattern extends Component{
return !this.props.status.policy[`journey_patterns.${action}`]
}
+ totals(){
+ let totalTime = 0
+ let totalDistance = 0
+ let from = null
+ this.props.value.stop_points.map((stopPoint, i) =>{
+ if(from && stopPoint.checked){
+ let [costsKey, costs, time, distance] = this.getTimeAndDistanceBetweenStops(from, stopPoint.id)
+ totalTime += time
+ totalDistance += distance
+ }
+ if(stopPoint.checked){
+ from = stopPoint.id
+ }
+ })
+ return [this.formatTime(totalTime), this.formatDistance(totalDistance)]
+ }
+
+ getTimeAndDistanceBetweenStops(from, to){
+ let costsKey = from + "-" + to
+ let costs = this.props.value.costs[costsKey] || {distance: 0, time: 0}
+ let time = costs['time'] || 0
+ let distance = costs['distance'] || 0
+ return [costsKey, costs, time, distance]
+ }
+
+ formatDistance(distance){
+ return parseFloat(Math.round(distance * 100) / 100).toFixed(2) + " km"
+ }
+
+ formatTime(time){
+ if(time < 60){
+ return time + " min"
+ }
+ else{
+ let hours = parseInt(time/60)
+ return hours + " h " + (time - 60*hours) + " min"
+ }
+ }
+
render() {
this.previousSpId = undefined
+ let [totalTime, totalDistance] = this.totals()
return (
<div className={'t2e-item' + (this.props.value.deletable ? ' disabled' : '') + (this.props.value.object_id ? '' : ' to_record') + (this.props.value.errors ? ' has-error': '') + (this.hasFeature('costs_in_journey_patterns') ? ' with-costs' : '')}>
- {/* Errors */}
- {/* this.props.value.errors ? this.getErrors(this.props.value.errors) : '' */}
-
<div className='th'>
<div className='strong mb-xs'>{this.props.value.object_id ? this.props.value.short_id : '-'}</div>
<div>{this.props.value.registration_number}</div>
<div>{actions.getChecked(this.props.value.stop_points).length} arrêt(s)</div>
-
+ {this.hasFeature('costs_in_journey_patterns') &&
+ <div className="small row totals">
+ <span className="col-md-6"><i className="fa fa-arrows-h"></i>{totalDistance}</span>
+ <span className="col-md-6"><i className="fa fa-clock-o"></i>{totalTime}</span>
+ </div>
+ }
<div className={this.props.value.deletable ? 'btn-group disabled' : 'btn-group'}>
<div
className={this.props.value.deletable ? 'btn dropdown-toggle disabled' : 'btn dropdown-toggle'}
@@ -132,17 +174,8 @@ export default class JourneyPattern extends Component{
let distance = null
let time_in_words = null
if(this.previousSpId && stopPoint.checked){
- costsKey = this.previousSpId + "-" + stopPoint.id
- costs = this.props.value.costs[costsKey] || {distance: 0, time: 0}
- time = costs['time'] || 0
- distance = costs['distance'] || 0
- if(time < 60){
- time_in_words = time + " min"
- }
- else{
- let hours = parseInt(time/60)
- time_in_words = hours + " h " + (time - 60*hours) + " min"
- }
+ [costsKey, costs, time, distance] = this.getTimeAndDistanceBetweenStops(this.previousSpId, stopPoint.id)
+ time_in_words = this.formatTime(time)
}
if(stopPoint.checked){
this.previousSpId = stopPoint.id
@@ -165,7 +198,7 @@ export default class JourneyPattern extends Component{
</p>
</div>}
{!this.props.editMode && <div>
- <p><i className="fa fa-arrows-h"></i>{(costs['distance'] || 0) + " km"}</p>
+ <p><i className="fa fa-arrows-h"></i>{this.formatDistance(costs['distance'] || 0)}</p>
<p><i className="fa fa-clock-o"></i>{time_in_words}</p>
</div>}
</div>}
diff --git a/app/javascript/journey_patterns/components/SaveJourneyPattern.js b/app/javascript/journey_patterns/components/SaveJourneyPattern.js
index 7e4492e0e..4bb6a73a0 100644
--- a/app/javascript/journey_patterns/components/SaveJourneyPattern.js
+++ b/app/javascript/journey_patterns/components/SaveJourneyPattern.js
@@ -1,35 +1,19 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
+import SaveButton from '../../helpers/save_button'
import actions from '../actions'
-export default class SaveJourneyPattern extends Component {
- constructor(props){
- super(props)
+export default class SaveJourneyPattern extends SaveButton {
+ hasPolicy(){
+ return this.props.status.policy['journey_patterns.update'] == true
}
- render() {
- if(this.props.status.policy['journey_patterns.update'] == false) {
- return false
- }else{
- return (
- <div className='row mt-md'>
- <div className='col-lg-12 text-right'>
- <form className='jp_collection formSubmitr ml-xs' onSubmit={e => {e.preventDefault()}}>
- <button
- className='btn btn-default'
- type='button'
- onClick={e => {
- e.preventDefault()
- this.props.editMode ? this.props.onSubmitJourneyPattern(this.props.dispatch, this.props.journeyPatterns) : this.props.onEnterEditMode()
- }}
- >
- {this.props.editMode ? "Valider" : "Editer"}
- </button>
- </form>
- </div>
- </div>
- )
- }
+ formClassName(){
+ return 'jp_collection'
+ }
+
+ submitForm(){
+ this.props.onSubmitJourneyPattern(this.props.dispatch, this.props.journeyPatterns)
}
}
@@ -37,4 +21,4 @@ SaveJourneyPattern.propTypes = {
journeyPatterns: PropTypes.array.isRequired,
status: PropTypes.object.isRequired,
page: PropTypes.number.isRequired
-} \ No newline at end of file
+}
diff --git a/app/javascript/packs/vehicle_journeys/index.js b/app/javascript/packs/vehicle_journeys/index.js
index ab28371fe..aa5738d59 100644
--- a/app/javascript/packs/vehicle_journeys/index.js
+++ b/app/javascript/packs/vehicle_journeys/index.js
@@ -71,7 +71,8 @@ var initialState = {
modalProps: {},
confirmModal: {}
},
- missions: window.all_missions
+ missions: window.all_missions,
+ custom_fields: window.custom_fields
}
if (window.jpOrigin){
diff --git a/app/javascript/vehicle_journeys/components/SaveVehicleJourneys.js b/app/javascript/vehicle_journeys/components/SaveVehicleJourneys.js
index c5161b917..6e94b04a3 100644
--- a/app/javascript/vehicle_journeys/components/SaveVehicleJourneys.js
+++ b/app/javascript/vehicle_journeys/components/SaveVehicleJourneys.js
@@ -1,37 +1,19 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
+import SaveButton from '../../helpers/save_button'
import actions from '../actions'
-export default class SaveVehicleJourneys extends Component{
- constructor(props){
- super(props)
+export default class SaveVehicleJourneys extends SaveButton{
+ hasPolicy(){
+ return this.props.filters.policy['vehicle_journeys.update'] == true
}
- render() {
- if (this.props.filters.policy['vehicle_journeys.update'] == false) {
- return false
- }else{
- return (
- <div className='row mt-md'>
- <div className='col-lg-12 text-right'>
- <form className='vehicle_journeys formSubmitr ml-xs' onSubmit={e => {e.preventDefault()}}>
- <div className="btn-group sticky-actions">
- <button
- className={'btn btn-default' + (this.props.status.fetchSuccess ? '' : ' disabled')}
- type='button'
- onClick={e => {
- e.preventDefault()
- this.props.editMode ? this.props.onSubmitVehicleJourneys(this.props.dispatch, this.props.vehicleJourneys) : this.props.onEnterEditMode()
- }}
- >
- {this.props.editMode ? "Valider" : "Editer"}
- </button>
- </div>
- </form>
- </div>
- </div>
- )
- }
+ formClassName(){
+ return 'vehicle_journeys'
+ }
+
+ submitForm(){
+ this.props.onSubmitVehicleJourneys(this.props.dispatch, this.props.vehicleJourneys)
}
}
diff --git a/app/javascript/vehicle_journeys/components/tools/CreateModal.js b/app/javascript/vehicle_journeys/components/tools/CreateModal.js
index 07c684760..90328458b 100644
--- a/app/javascript/vehicle_journeys/components/tools/CreateModal.js
+++ b/app/javascript/vehicle_journeys/components/tools/CreateModal.js
@@ -3,15 +3,17 @@ import PropTypes from 'prop-types'
import actions from '../../actions'
import MissionSelect2 from './select2s/MissionSelect2'
import CompanySelect2 from './select2s/CompanySelect2'
+import CustomFieldsInputs from './CustomFieldsInputs'
export default class CreateModal extends Component {
constructor(props) {
super(props)
+ this.custom_fields = _.assign({}, this.props.custom_fields)
}
handleSubmit() {
if (actions.validateFields(...this.refs, $('.vjCreateSelectJP')[0]) && this.props.modal.modalProps.selectedJPModal) {
- this.props.onAddVehicleJourney(this.refs, this.props.modal.modalProps.selectedJPModal, this.props.stopPointsList, this.props.modal.modalProps.vehicleJourney && this.props.modal.modalProps.vehicleJourney.company)
+ this.props.onAddVehicleJourney(_.assign({}, this.refs, {custom_fields: this.custom_fields}), this.props.modal.modalProps.selectedJPModal, this.props.stopPointsList, this.props.modal.modalProps.vehicleJourney && this.props.modal.modalProps.vehicleJourney.company)
this.props.onModalClose()
$('#NewVehicleJourneyModal').modal('hide')
}
@@ -89,6 +91,11 @@ export default class CreateModal extends Component {
/>
</div>
</div>
+ <CustomFieldsInputs
+ values={this.props.custom_fields}
+ onUpdate={(code, value) => this.custom_fields[code]["value"] = value}
+ disabled={false}
+ />
{ this.props.modal.modalProps.selectedJPModal && this.props.modal.modalProps.selectedJPModal.full_schedule && <div className='col-lg-6 col-md-6 col-sm-6 col-xs-12'>
<div className='form-group'>
<label className='control-label'>Heure de départ</label>
diff --git a/app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js b/app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js
new file mode 100644
index 000000000..90d72a801
--- /dev/null
+++ b/app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js
@@ -0,0 +1,50 @@
+import _ from 'lodash'
+import Select2 from 'react-select2-wrapper'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+
+export default class CustomFieldsInputs extends Component {
+ constructor(props) {
+ super(props)
+ }
+
+ listInput(cf){
+ return(
+ <Select2
+ data={_.map(cf.options.list_values, (v, k) => {
+ return {id: k, text: (v.length > 0 ? v : '\u00A0')}
+ })}
+ ref={'custom_fields.' + cf.code}
+ className='form-control'
+ defaultValue={cf.value}
+ disabled={this.props.disabled}
+ options={{
+ theme: 'bootstrap',
+ width: '100%'
+ }}
+ onSelect={(e) => this.props.onUpdate(cf.code, e.params.data.id) }
+ />
+ )
+ }
+
+ render() {
+ return (
+ <div>
+ {_.map(this.props.values, (cf, code) =>
+ <div className='col-lg-6 col-md-6 col-sm-6 col-xs-12' key={code}>
+ <div className='form-group'>
+ <label className='control-label'>{cf.name}</label>
+ {this[cf.field_type + "Input"](cf)}
+ </div>
+ </div>
+ )}
+ </div>
+ )
+ }
+}
+
+CustomFieldsInputs.propTypes = {
+ onUpdate: PropTypes.func.isRequired,
+ values: PropTypes.object.isRequired,
+ disabled: PropTypes.bool.isRequired
+}
diff --git a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js
index 08d74baba..2893422f8 100644
--- a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js
+++ b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js
@@ -2,6 +2,7 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types'
import actions from '../../actions'
import CompanySelect2 from './select2s/CompanySelect2'
+import CustomFieldsInputs from './CustomFieldsInputs'
export default class EditVehicleJourney extends Component {
constructor(props) {
@@ -15,8 +16,8 @@ export default class EditVehicleJourney extends Component {
company = this.props.modal.modalProps.selectedCompany
} else if (typeof this.props.modal.modalProps.vehicleJourney.company === "object") {
company = this.props.modal.modalProps.vehicleJourney.company
- }
- this.props.onEditVehicleJourney(this.refs, company)
+ }
+ this.props.onEditVehicleJourney(_.assign({}, this.refs, {custom_fields: this.custom_fields}), company)
this.props.onModalClose()
$('#EditVehicleJourneyModal').modal('hide')
}
@@ -27,6 +28,9 @@ export default class EditVehicleJourney extends Component {
return false
}
if(this.props.status.fetchSuccess == true) {
+ if(this.props.modal.modalProps.vehicleJourney){
+ this.custom_fields = _.assign({}, this.props.modal.modalProps.vehicleJourney.custom_fields)
+ }
return (
<li className='st_action'>
<button
@@ -140,8 +144,15 @@ export default class EditVehicleJourney extends Component {
defaultValue={this.props.modal.modalProps.vehicleJourney.checksum}
/>
</div>
-
+ <div className='row'>
+ <CustomFieldsInputs
+ values={this.props.modal.modalProps.vehicleJourney.custom_fields}
+ onUpdate={(code, value) => this.custom_fields[code]["value"] = value}
+ disabled={!this.props.editMode}
+ />
+ </div>
</div>
+
{
this.props.editMode &&
<div className='modal-footer'>
diff --git a/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js b/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js
index 0f4a0ea7d..0db7628be 100644
--- a/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js
+++ b/app/javascript/vehicle_journeys/containers/tools/AddVehicleJourney.js
@@ -10,6 +10,7 @@ const mapStateToProps = (state, ownProps) => {
status: state.status,
stopPointsList: state.stopPointsList,
missions: state.missions,
+ custom_fields: state.custom_fields,
}
}
diff --git a/app/javascript/vehicle_journeys/reducers/custom_fields.js b/app/javascript/vehicle_journeys/reducers/custom_fields.js
new file mode 100644
index 000000000..482fd91cb
--- /dev/null
+++ b/app/javascript/vehicle_journeys/reducers/custom_fields.js
@@ -0,0 +1,6 @@
+export default function custom_fields(state = [], action) {
+ switch (action.type) {
+ default:
+ return state
+ }
+}
diff --git a/app/javascript/vehicle_journeys/reducers/index.js b/app/javascript/vehicle_journeys/reducers/index.js
index 862c864ae..1963f7c6d 100644
--- a/app/javascript/vehicle_journeys/reducers/index.js
+++ b/app/javascript/vehicle_journeys/reducers/index.js
@@ -7,6 +7,7 @@ import filters from './filters'
import editMode from './editMode'
import stopPointsList from './stopPointsList'
import missions from './missions'
+import custom_fields from './custom_fields'
const vehicleJourneysApp = combineReducers({
vehicleJourneys,
@@ -16,7 +17,8 @@ const vehicleJourneysApp = combineReducers({
filters,
editMode,
stopPointsList,
- missions
+ missions,
+ custom_fields
})
export default vehicleJourneysApp
diff --git a/app/javascript/vehicle_journeys/reducers/modal.js b/app/javascript/vehicle_journeys/reducers/modal.js
index c2556303d..fb7e16547 100644
--- a/app/javascript/vehicle_journeys/reducers/modal.js
+++ b/app/javascript/vehicle_journeys/reducers/modal.js
@@ -147,14 +147,7 @@ export default function modal(state = {}, action) {
let stopAreas = _.map(window.jpOriginStopPoints, (sa, i) =>{
return _.assign({}, {stop_area_short_description : {id : sa.stop_area_id}})
})
- selectedJP = {
- id: window.jpOrigin.id,
- name: window.jpOrigin.name,
- published_name: window.jpOrigin.published_name,
- objectid: window.jpOrigin.objectid,
- stop_areas: stopAreas,
- missions: state.missions
- }
+ selectedJP = _.assign({}, window.jpOrigin, {stop_areas: stopAreas})
}
return {
type: 'create',
diff --git a/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js b/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js
index 0549c7adc..ae45993a8 100644
--- a/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js
+++ b/app/javascript/vehicle_journeys/reducers/vehicleJourneys.js
@@ -16,7 +16,7 @@ const vehicleJourney= (state = {}, action, keep) => {
}
if(action.data["start_time.hour"] && action.data["start_time.minute"] && action.selectedJourneyPattern.full_schedule){
current_time.hour = parseInt(action.data["start_time.hour"].value)
- current_time.minute = parseInt(action.data["start_time.minute"].value)
+ current_time.minute = parseInt(action.data["start_time.minute"].value) || 0
}
_.each(action.stopPointsList, (sp) =>{
if(action.selectedJourneyPattern.full_schedule && action.selectedJourneyPattern.costs && action.selectedJourneyPattern.costs[prevSp.stop_area_id + "-" + sp.stop_area_id]){
@@ -31,29 +31,46 @@ const vehicleJourney= (state = {}, action, keep) => {
current_time.hour = current_time.hour % 24
prevSp = sp
}
+ let offsetHours = sp.time_zone_offset / 3600
+ let offsetminutes = sp.time_zone_offset/60 - 60*offsetHours
let newVjas = {
delta: 0,
departure_time:{
- hour: current_time.hour,
- minute: current_time.minute
+ hour: (24 + current_time.hour + offsetHours) % 24,
+ minute: current_time.minute + offsetminutes
},
arrival_time:{
- hour: current_time.hour,
- minute: current_time.minute
+ hour: (24 + current_time.hour + offsetHours) % 24,
+ minute: current_time.minute + offsetminutes
},
stop_point_objectid: sp.object_id,
stop_area_cityname: sp.city_name,
dummy: true
}
+ if(current_time.hour + offsetHours > 24){
+ newVjas.departure_day_offset = 1
+ newVjas.arrival_day_offset = 1
+ }
+ if(current_time.hour + offsetHours < 0){
+ newVjas.departure_day_offset = -1
+ newVjas.arrival_day_offset = -1
+ }
+
_.each(action.selectedJourneyPattern.stop_areas, (jp) =>{
if (jp.stop_area_short_description.id == sp.id){
newVjas.dummy = false
return
}
})
+
+ if(newVjas.dummy){
+ newVjas.departure_time = {hour: "00", minute: "00"}
+ newVjas.arrival_time = {hour: "00", minute: "00"}
+ }
pristineVjasList.push(newVjas)
})
+
return {
company: action.selectedCompany,
journey_pattern: action.selectedJourneyPattern,
@@ -68,7 +85,8 @@ const vehicleJourney= (state = {}, action, keep) => {
selected: false,
deletable: false,
transport_mode: window.transportMode ? window.transportMode : 'undefined',
- transport_submode: window.transportSubmode ? window.transportSubmode : 'undefined'
+ transport_submode: window.transportSubmode ? window.transportSubmode : 'undefined',
+ custom_fields: action.data.custom_fields
}
case 'DUPLICATE_VEHICLEJOURNEY':
case 'SHIFT_VEHICLEJOURNEY':
@@ -148,6 +166,7 @@ export default function vehicleJourneys(state = [], action) {
company: action.selectedCompany,
published_journey_name: action.data.published_journey_name.value,
published_journey_identifier: action.data.published_journey_identifier.value,
+ custom_fields: action.data.custom_fields,
})
}else{
return vj
diff --git a/app/models/chouette/company.rb b/app/models/chouette/company.rb
index 12b21e347..b3d40ab96 100644
--- a/app/models/chouette/company.rb
+++ b/app/models/chouette/company.rb
@@ -3,7 +3,7 @@ module Chouette
include CompanyRestrictions
include LineReferentialSupport
include ObjectidSupport
- has_paper_trail
+ has_paper_trail class_name: 'PublicVersion'
has_many :lines
diff --git a/app/models/chouette/journey_pattern.rb b/app/models/chouette/journey_pattern.rb
index d03eb6ad7..55faaf997 100644
--- a/app/models/chouette/journey_pattern.rb
+++ b/app/models/chouette/journey_pattern.rb
@@ -72,7 +72,9 @@ module Chouette
# In this case, we mark jp to be valid if persisted? return true
jp.errors.clear if jp.persisted?
+ jp.after_commit_objectid
item['object_id'] = jp.objectid
+ item['short_id'] = jp.get_objectid.short_id
item['new_record'] = true
jp
end
diff --git a/app/models/chouette/line.rb b/app/models/chouette/line.rb
index 389240ec7..ba2e2755d 100644
--- a/app/models/chouette/line.rb
+++ b/app/models/chouette/line.rb
@@ -1,6 +1,6 @@
module Chouette
class Line < Chouette::ActiveRecord
- has_paper_trail
+ has_paper_trail class_name: 'PublicVersion'
include LineRestrictions
include LineReferentialSupport
include ObjectidSupport
diff --git a/app/models/chouette/network.rb b/app/models/chouette/network.rb
index 9b3f2fe29..6843c69ad 100644
--- a/app/models/chouette/network.rb
+++ b/app/models/chouette/network.rb
@@ -1,6 +1,6 @@
module Chouette
class Network < Chouette::ActiveRecord
- has_paper_trail
+ has_paper_trail class_name: 'PublicVersion'
include NetworkRestrictions
include LineReferentialSupport
include ObjectidSupport
diff --git a/app/models/chouette/stop_area.rb b/app/models/chouette/stop_area.rb
index 52602be9f..ea1855ea8 100644
--- a/app/models/chouette/stop_area.rb
+++ b/app/models/chouette/stop_area.rb
@@ -2,7 +2,7 @@ require 'geokit'
require 'geo_ruby'
module Chouette
class StopArea < Chouette::ActiveRecord
- has_paper_trail
+ has_paper_trail class_name: 'PublicVersion'
include ProjectionFields
include StopAreaRestrictions
include StopAreaReferentialSupport
@@ -358,11 +358,21 @@ module Chouette
update_attribute :deleted_at, Time.now
end
+ def time_zone_offset
+ return 0 unless time_zone.present?
+ ActiveSupport::TimeZone[time_zone]&.utc_offset
+ end
+
def country_name
return unless country_code
country = ISO3166::Country[country_code]
country.translations[I18n.locale.to_s] || country.name
end
+
+ def time_zone_formatted_offset
+ return nil unless time_zone.present?
+ ActiveSupport::TimeZone[time_zone]&.formatted_offset
+ end
end
end
diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb
index a8c9c1824..8a704d8c0 100644
--- a/app/models/chouette/vehicle_journey.rb
+++ b/app/models/chouette/vehicle_journey.rb
@@ -132,10 +132,14 @@ module Chouette
def update_vjas_from_state state
state.each do |vjas|
next if vjas["dummy"]
+ stop_point = Chouette::StopPoint.find_by(objectid: vjas['stop_point_objectid'])
+ stop_area = stop_point&.stop_area
+ tz = stop_area&.time_zone
+ tz = tz && ActiveSupport::TimeZone[tz]
params = {}.tap do |el|
['arrival_time', 'departure_time'].each do |field|
time = "#{vjas[field]['hour']}:#{vjas[field]['minute']}"
- el[field.to_sym] = Time.parse("2000-01-01 #{time}:00 UTC")
+ el[field.to_sym] = Time.parse("2000-01-01 #{time}:00 #{tz&.formatted_offset || "UTC"}")
end
end
stop = create_or_find_vjas_from_state(vjas)
@@ -208,7 +212,9 @@ module Chouette
def self.state_create_instance route, item
# Flag new record, so we can unset object_id if transaction rollback
vj = route.vehicle_journeys.create(state_permited_attributes(item))
- item['objectid'] = vj.objectid
+ vj.after_commit_objectid
+ item['objectid'] = vj.objectid
+ item['short_id'] = vj.get_objectid.short_id
item['new_record'] = true
vj
end
@@ -218,6 +224,7 @@ module Chouette
['company', 'journey_pattern'].map do |association|
attrs["#{association}_id"] = item[association]['id'] if item[association]
end
+ attrs["custom_field_values"] = Hash[*(item["custom_fields"] || {}).map{|k, v| [k, v["value"]]}.flatten]
attrs
end
@@ -256,8 +263,15 @@ module Chouette
end
end
+ def self.custom_fields
+ CustomField.where(resource_type: self.name.split("::").last)
+ end
+
+
def custom_fields
- CustomField.where(resource_type: self.class.name.split("::").last)
+ Hash[*self.class.custom_fields.map do |v|
+ [v.code, v.slice(:code, :name, :field_type, :options).update(value: custom_field_value(v.code))]
+ end.flatten]
end
def custom_field_value key
diff --git a/app/models/chouette/vehicle_journey_at_stop.rb b/app/models/chouette/vehicle_journey_at_stop.rb
index 6b3c1e7de..eda711ade 100644
--- a/app/models/chouette/vehicle_journey_at_stop.rb
+++ b/app/models/chouette/vehicle_journey_at_stop.rb
@@ -77,11 +77,39 @@ module Chouette
end
def departure
- departure_time.utc.strftime "%H:%M" if departure_time
+ format_time departure_time.utc
end
def arrival
- arrival_time.utc.strftime "%H:%M" if arrival_time
+ format_time arrival_time.utc
+ end
+
+ def departure_local_time
+ local_time departure_time
+ end
+
+ def arrival_local_time
+ local_time arrival_time
+ end
+
+ def departure_local
+ format_time departure_local_time
+ end
+
+ def arrival_local
+ format_time arrival_local_time
+ end
+
+ private
+ def local_time time
+ return unless time
+ return time unless stop_point&.stop_area&.time_zone.present?
+ return time unless ActiveSupport::TimeZone[stop_point.stop_area.time_zone].present?
+ time + ActiveSupport::TimeZone[stop_point.stop_area.time_zone].utc_offset
+ end
+
+ def format_time time
+ time.strftime "%H:%M" if time
end
end
diff --git a/app/models/compliance_check_message_export.rb b/app/models/compliance_check_message_export.rb
new file mode 100644
index 000000000..04e1a9caa
--- /dev/null
+++ b/app/models/compliance_check_message_export.rb
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+require "csv"
+require "zip"
+
+class ComplianceCheckMessageExport
+ include ActiveModel::Validations
+ include ActiveModel::Conversion
+ extend ActiveModel::Naming
+
+ attr_accessor :compliance_check_messages
+
+ def initialize(attributes = {})
+ attributes.each { |name, value| send("#{name}=", value) }
+ end
+
+ def persisted?
+ false
+ end
+
+ def label(name)
+ I18n.t "vehicle_journey_exports.label.#{name}"
+ end
+
+ def column_names
+ ["criticity", "message key", "resource objectid", "link", "message"]
+ end
+
+ def to_csv(options = {})
+ CSV.generate(options.slice(:col_sep, :quote_char, :force_quotes)) do |csv|
+ csv << column_names
+ compliance_check_messages.each do |compliance_check_message|
+ csv << [compliance_check_message.compliance_check.criticity, *compliance_check_message.message_attributes.values_at('test_id', 'source_objectid'), options[:server_url] + compliance_check_message.message_attributes['source_object_path'], I18n.t("compliance_check_messages.#{compliance_check_message.message_key}", compliance_check_message.message_attributes.deep_symbolize_keys)]
+ end
+ end
+ end
+
+ def to_zip(temp_file,options = {})
+ ::Zip::OutputStream.open(temp_file) { |zos| }
+ ::Zip::File.open(temp_file.path, ::Zip::File::CREATE) do |zipfile|
+ zipfile.get_output_stream(label("vj_filename")+route.id.to_s+".csv") { |f| f.puts to_csv(options) }
+ zipfile.get_output_stream(label("tt_filename")+".csv") { |f| f.puts time_tables_to_csv(options) }
+ zipfile.get_output_stream(label("ftn_filename")+".csv") { |f| f.puts footnotes_to_csv(options) }
+ end
+ end
+
+end
diff --git a/app/models/compliance_check_set.rb b/app/models/compliance_check_set.rb
index 63f380d99..f4c44d26d 100644
--- a/app/models/compliance_check_set.rb
+++ b/app/models/compliance_check_set.rb
@@ -26,6 +26,14 @@ class ComplianceCheckSet < ActiveRecord::Base
end
end
+ def organisation
+ workbench.organisation
+ end
+
+ def human_attribute_name(*args)
+ self.class.human_attribute_name(*args)
+ end
+
def update_status
statuses = compliance_check_resources.map do |resource|
case resource.status
diff --git a/app/models/custom_field.rb b/app/models/custom_field.rb
index e8e76c6b5..3f79ec62c 100644
--- a/app/models/custom_field.rb
+++ b/app/models/custom_field.rb
@@ -1,7 +1,8 @@
class CustomField < ActiveRecord::Base
extend Enumerize
- enumerize :field_type, in: %i{list}
+ enumerize :field_type, in: %i{list}
validates :name, uniqueness: {scope: :resource_type}
+ validates :code, uniqueness: {scope: :resource_type, case_sensitive: false}
end
diff --git a/app/models/import_message_export.rb b/app/models/import_message_export.rb
index 88d0f27e2..05f8a2cc7 100644
--- a/app/models/import_message_export.rb
+++ b/app/models/import_message_export.rb
@@ -22,14 +22,14 @@ class ImportMessageExport
end
def column_names
- ["criticity", "message key", "message"]
+ ["criticity", "message key", "message", "file name", "line", "column"]
end
def to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
import_messages.each do |import_message|
- csv << [import_message.criticity, import_message.message_key, I18n.t("import_messages.compliance_check_messages.#{import_message.message_key}", import_message.message_attributes.deep_symbolize_keys) ]
+ csv << [import_message.criticity, import_message.message_key, I18n.t("import_messages.#{import_message.message_key}", import_message.message_attributes.deep_symbolize_keys), *import_message.resource_attributes.values_at("filename", "line_number", "column_number") ]
end
end
end
diff --git a/app/models/merge.rb b/app/models/merge.rb
index 26bd5398b..91be27f2c 100644
--- a/app/models/merge.rb
+++ b/app/models/merge.rb
@@ -60,6 +60,7 @@ class Merge < ActiveRecord::Base
end
new.referential_suite = output
+ new.workbench = workbench
new.organisation = workbench.organisation
new.slug = "output_#{workbench.id}_#{created_at.to_i}"
new.name = I18n.t("merges.referential_name", date: I18n.l(created_at))
@@ -360,6 +361,8 @@ class Merge < ActiveRecord::Base
def save_current
output.update current: new, new: nil
output.current.update referential_suite: output
+
+ referentials.update_all merged_at: created_at, archived_at: created_at
end
def fixme_functional_scope
diff --git a/app/models/referential.rb b/app/models/referential.rb
index 718f60ffd..92931564d 100644
--- a/app/models/referential.rb
+++ b/app/models/referential.rb
@@ -463,6 +463,18 @@ class Referential < ActiveRecord::Base
not metadatas_overlap?
end
+ def merged?
+ merged_at.present?
+ end
+
+ def self.not_merged
+ where merged_at: nil
+ end
+
+ def self.mergeable
+ ready.not_merged.not_in_referential_suite
+ end
+
private
def lock_table
diff --git a/app/models/workbench.rb b/app/models/workbench.rb
index f49f4e7cf..b80fa64ac 100644
--- a/app/models/workbench.rb
+++ b/app/models/workbench.rb
@@ -31,7 +31,12 @@ class Workbench < ActiveRecord::Base
if line_ids.empty?
Referential.none
else
- Referential.joins(:metadatas).where(['referential_metadata.line_ids && ARRAY[?]::bigint[]', line_ids]).ready.not_in_referential_suite
+ workgroup
+ .referentials
+ .joins(:metadatas)
+ .where(['referential_metadata.line_ids && ARRAY[?]::bigint[]', line_ids])
+ .ready
+ .not_in_referential_suite
end
end
diff --git a/app/models/workgroup.rb b/app/models/workgroup.rb
index 995917fac..3d761e81f 100644
--- a/app/models/workgroup.rb
+++ b/app/models/workgroup.rb
@@ -4,6 +4,7 @@ class Workgroup < ActiveRecord::Base
has_many :workbenches
has_many :organisations, through: :workbenches
+ has_many :referentials, through: :workbenches
validates_uniqueness_of :name
@@ -11,4 +12,8 @@ class Workgroup < ActiveRecord::Base
validates_presence_of :stop_area_referential_id
has_many :custom_fields
+
+ def custom_fields_definitions
+ Hash[*custom_fields.map{|cf| [cf.code, cf]}.flatten]
+ end
end
diff --git a/app/policies/network_policy.rb b/app/policies/network_policy.rb
index 9f86451a5..9b871d2b5 100644
--- a/app/policies/network_policy.rb
+++ b/app/policies/network_policy.rb
@@ -4,4 +4,15 @@ class NetworkPolicy < ApplicationPolicy
scope
end
end
+ def create?
+ user.has_permission?('networks.create')
+ end
+
+ def destroy?
+ user.has_permission?('networks.destroy')
+ end
+
+ def update?
+ user.has_permission?('networks.update')
+ end
end
diff --git a/app/policies/referential_policy.rb b/app/policies/referential_policy.rb
index af5c14880..f5c2d7c08 100644
--- a/app/policies/referential_policy.rb
+++ b/app/policies/referential_policy.rb
@@ -18,7 +18,7 @@ class ReferentialPolicy < ApplicationPolicy
end
def clone?
- !referential_read_only? && create?
+ !record.in_referential_suite? && create?
end
def validate?
@@ -30,7 +30,7 @@ class ReferentialPolicy < ApplicationPolicy
end
def unarchive?
- !record.archived_at.nil? && organisation_match? && user.has_permission?('referentials.update')
+ record.archived? && !record.merged? && organisation_match? && user.has_permission?('referentials.update')
end
def common_lines?
diff --git a/app/views/api/v1/journey_patterns/show.rabl b/app/views/api/v1/journey_patterns/show.rabl
index cdda2d1cd..aac66b6f3 100644
--- a/app/views/api/v1/journey_patterns/show.rabl
+++ b/app/views/api/v1/journey_patterns/show.rabl
@@ -12,6 +12,7 @@ end
if has_feature? :costs_in_journey_patterns
attribute :costs
end
+
node(:route_short_description) do |journey_pattern|
partial("api/v1/routes/short_description", :object => journey_pattern.route)
end
diff --git a/app/views/autocomplete_stop_areas/around.rabl b/app/views/autocomplete_stop_areas/around.rabl
index bc8f06054..d067dc4d0 100644
--- a/app/views/autocomplete_stop_areas/around.rabl
+++ b/app/views/autocomplete_stop_areas/around.rabl
@@ -12,7 +12,7 @@ child @stop_areas, root: :features, object_root: false do
name: s.name,
short_name: truncate(s.name, :length => 30) || "",
city_name: s.city_name,
- area_type: s.area_type,
+ area_type: Chouette::AreaType.find(s.area_type).label,
registration_number: s.registration_number,
stoparea_id: s.id,
text: "#{s.name}, #{s.zip_code} #{s.city_name}",
diff --git a/app/views/autocomplete_stop_areas/index.rabl b/app/views/autocomplete_stop_areas/index.rabl
index d20051ad5..c92b708f4 100644
--- a/app/views/autocomplete_stop_areas/index.rabl
+++ b/app/views/autocomplete_stop_areas/index.rabl
@@ -13,7 +13,7 @@ node do |stop_area|
:user_objectid => stop_area.user_objectid,
:longitude => stop_area.longitude,
:latitude => stop_area.latitude,
- :area_type => stop_area.area_type,
+ :area_type => Chouette::AreaType.find(stop_area.area_type).label,
:comment => stop_area.comment,
:text => stop_area.full_name
}
diff --git a/app/views/compliance_check_sets/executed.html.slim b/app/views/compliance_check_sets/executed.html.slim
index da8a2a3de..b33b516b4 100644
--- a/app/views/compliance_check_sets/executed.html.slim
+++ b/app/views/compliance_check_sets/executed.html.slim
@@ -1,4 +1,4 @@
-- breadcrumb :compliance_check_set, @workbench, @compliance_check_set
+- breadcrumb :compliance_check_set_executed, @workbench, @compliance_check_set
- page_header_content_for @compliance_check_set
.page_content
diff --git a/app/views/compliance_check_sets/index.html.slim b/app/views/compliance_check_sets/index.html.slim
index f109845b4..f15e85bdd 100644
--- a/app/views/compliance_check_sets/index.html.slim
+++ b/app/views/compliance_check_sets/index.html.slim
@@ -12,7 +12,10 @@
[ \
TableBuilderHelper::Column.new( \
key: :ref, \
- attribute: 'id' \
+ attribute: 'id', \
+ link_to: lambda do |compliance_check_set| \
+ workbench_compliance_check_set_path(compliance_check_set.workbench_id, compliance_check_set.id) \
+ end \
), \
TableBuilderHelper::Column.new( \
key: :creation_date, \
@@ -31,7 +34,10 @@
), \
TableBuilderHelper::Column.new(\
key: :compliance_control_set, \
- attribute: Proc.new{ |n| (n.compliance_control_set.name) if n.compliance_control_set} \
+ attribute: 'name', \
+ link_to: lambda do |compliance_check_set| \
+ executed_workbench_compliance_check_set_path(compliance_check_set.workbench_id, compliance_check_set.id) \
+ end \
), \
],
sortable: true,
diff --git a/app/views/compliance_check_sets/show.html.slim b/app/views/compliance_check_sets/show.html.slim
index 5d8e3fa15..4db2e805f 100644
--- a/app/views/compliance_check_sets/show.html.slim
+++ b/app/views/compliance_check_sets/show.html.slim
@@ -1,4 +1,4 @@
-- breadcrumb :compliance_check_sets, @workbench, @compliance_check_set
+- breadcrumb :compliance_check_set, @workbench, @compliance_check_set
/ PageHeader
- content_for :page_header_content do
.row
@@ -11,31 +11,28 @@
= link.content
- page_header_content_for @compliance_check_set
-/ = pageheader 'jeux-de-donnees',
-/ @compliance_check_set.name,
-/ '',
-/ t('last_update', time: l(@compliance_check_set.updated_at, format: :short)) do
-
- / Below is secundary actions & optional contents (filters, ...)
- / .row
- / .col-lg-12.text-right.mb-sm
- / - @compliance_check_set.action_links.each do |link|
- / = link_to link.href,
- / method: link.method,
- / data: link.data,
- / class: 'btn btn-primary' do
- / = link.content
/ PageContent
.page_content.import_messages
.container-fluid
.row
+ .col-lg-6.col-md-6.col-sm-12.col-xs-12
+ = definition_list( t('metadatas'),
+ { I18n.t("compliance_check_sets.show.metadatas.referential") => (@compliance_check_set.referential.nil? ? '' : link_to(@compliance_check_set.referential.name, referential_path(@compliance_check_set.referential)) ),
+ I18n.t("compliance_check_sets.show.metadatas.referential_type") => 'Jeu de données',
+ I18n.t("compliance_check_sets.show.metadatas.compliance_check_set_executed") => link_to(@compliance_check_set.name, executed_workbench_compliance_check_set_path(@compliance_check_set.workbench_id, @compliance_check_set)),
+ I18n.t("compliance_check_sets.show.metadatas.compliance_control_owner") => @compliance_check_set.organisation.name,
+ I18n.t("compliance_check_sets.show.metadatas.import") => '' })
+ .row
.col-lg-12
h1
span.status_icon = compliance_check_set_status(@compliance_check_set.status)
- span = t('compliance_check_sets.show.table_state', lines_status: @compliance_check_set.lines_status , lines_in_compliance_check_set: @compliance_check_set.lines_in_compliance_check_set )
+ span = t('.table_state', lines_status: @compliance_check_set.lines_status , lines_in_compliance_check_set: @compliance_check_set.lines_in_compliance_check_set )
+ .col-lg-12
+ h2 = t('.table_title')
.col-lg-12
- = t('compliance_check_sets.show.table_explanation')
+ = t('.table_explanation')
+
.row
.col-lg-12
= table_builder_2 @compliance_check_set.compliance_check_resources,
@@ -46,13 +43,21 @@
), \
TableBuilderHelper::Column.new( \
key: :status, \
- attribute: Proc.new { |n| compliance_check_set_status(n.status) } \
+ attribute: Proc.new { |n| compliance_check_resource_status(n.status) } \
), \
TableBuilderHelper::Column.new( \
key: :metrics, \
attribute: Proc.new { |n| I18n.t('compliance_check_sets.show.metrics', n.metrics.deep_symbolize_keys) } \
+ ), \
+ TableBuilderHelper::Column.new( \
+ name: 'Téléchargement' , \
+ attribute: Proc.new { |n| '<i class="fa fa-download" aria-hidden="true"></i>'.html_safe }, \
+ sortable: false, \
+ link_to: lambda do |compliance_check_resource| \
+ workbench_compliance_check_set_compliance_check_messages_path(@compliance_check_set.workbench, @compliance_check_set, format: 'csv', compliance_check_resource_id: compliance_check_resource.id ) \
+ end \
) \
],
sortable: false, \
links: [],
- cls: 'table'
+ cls: 'table has-search'
diff --git a/app/views/import_resources/index.html.slim b/app/views/import_resources/index.html.slim
index 728d9f4a8..0c21a9e09 100644
--- a/app/views/import_resources/index.html.slim
+++ b/app/views/import_resources/index.html.slim
@@ -48,4 +48,4 @@
- else
.col-lg-12
- @import.messages.each do |message|
- = I18n.t("import_messages.compliance_check_messages.#{message.message_key}")
+ = I18n.t("import_messages.#{message.message_key}")
diff --git a/app/views/networks/_form.html.slim b/app/views/networks/_form.html.slim
index 362584f97..f91a112e8 100644
--- a/app/views/networks/_form.html.slim
+++ b/app/views/networks/_form.html.slim
@@ -4,11 +4,11 @@
= f.input :name, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@line_referential)}.network.name")}
= f.input :registration_number, :input_html => { :title => t("formtastic.titles#{format_restriction_for_locales(@line_referential)}.network.registration_number")}
= f.input :comment
- = f.input :version_date, :label_html => { :class => 'string optional col-sm-4 col-xs-5 control-label' }, :wrapper => :multi_select_inline
- = f.input :description
- = f.input :source_name
- = f.input :source_type_name, as: :select, :collection => Chouette::Network.source_type_name.options, :include_blank => true
- = f.input :source_identifier
+ / = f.input :version_date, :label_html => { :class => 'string optional col-sm-4 col-xs-5 control-label' }, :wrapper => :multi_select_inline
+ / = f.input :description
+ / = f.input :source_name
+ / = f.input :source_type_name, as: :select, :collection => Chouette::Network.source_type_name.options, :include_blank => true
+ / = f.input :source_identifier
.separator
= f.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'network_form'
diff --git a/app/views/networks/show.html.slim b/app/views/networks/show.html.slim
index f7d40a049..8e40a13b2 100644
--- a/app/views/networks/show.html.slim
+++ b/app/views/networks/show.html.slim
@@ -14,4 +14,8 @@
.row
.col-lg-6.col-md-6.col-sm-12.col-xs-12
= definition_list t('metadatas'),
- { 'ID Codif' => @network.try(:get_objectid).try(:short_id) }
+ { @network.human_attribute_name(:id) => @network.get_objectid.try(:short_id), \
+ @network.human_attribute_name(:name) => @network.name, \
+ @network.human_attribute_name(:registration_number) => @network.registration_number, \
+ @network.human_attribute_name(:comment) => (@network.comment.presence || '-'), \
+ }
diff --git a/app/views/referential_vehicle_journeys/index.html.slim b/app/views/referential_vehicle_journeys/index.html.slim
index 394f4a3f7..d29a78a6c 100644
--- a/app/views/referential_vehicle_journeys/index.html.slim
+++ b/app/views/referential_vehicle_journeys/index.html.slim
@@ -23,7 +23,7 @@
key: :published_journey_name, \
attribute: 'published_journey_name', \
link_to: lambda do |vehicle_journey| \
- referential_line_route_vehicle_journeys_path(@referential, vehicle_journey.route.line, vehicle_journey.route) \
+ vehicle_journey.published_journey_name ? referential_line_route_vehicle_journeys_path(@referential, vehicle_journey.route.line, vehicle_journey.route) : '' \
end, \
sortable: false \
), \
diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim
index 305d04f6b..cbb622c44 100644
--- a/app/views/referentials/show.html.slim
+++ b/app/views/referentials/show.html.slim
@@ -25,7 +25,7 @@
- attributes[@referential.human_attribute_name(:status)] = @referential.referential_read_only? ? "<div class='td-block'><span class='fa fa-archive'></span><span>#{t('activerecord.attributes.referential.archived_at')}</span></div>".html_safe : "<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>#{t('activerecord.attributes.referential.archived_at_null')}</span></div>".html_safe unless @referential.in_referential_suite?
- attributes[@referential.human_attribute_name(:validity_period)] = (@referential.validity_period.present? ? t('validity_range', debut: l(@referential.try(:validity_period).try(:begin), format: :short), end: l(@referential.try(:validity_period).try(:end), format: :short)) : '-')
- attributes[@referential.human_attribute_name(:organisation)] = @referential.organisation.name
- - attributes[@referential.human_attribute_name(:published_at)] = '-' unless @referential.in_referential_suite?
+ - attributes[@referential.human_attribute_name(:merged_at)] = @referential.merged_at ? l(@referential.merged_at, format: :short) : '-' unless @referential.in_referential_suite?
= definition_list t('metadatas'), attributes
- if params[:q].present? or @reflines.any?
diff --git a/app/views/vehicle_journeys/index.html.slim b/app/views/vehicle_journeys/index.html.slim
index 66e90d839..2c7a3b97d 100644
--- a/app/views/vehicle_journeys/index.html.slim
+++ b/app/views/vehicle_journeys/index.html.slim
@@ -17,7 +17,7 @@
= javascript_tag do
| window.route_id = #{params[:route_id]};
| window.stopPoints = #{(@stop_points_list.to_json).html_safe};
- | window.jpOrigin = #{(@jp_origin.to_json).html_safe};
+ | window.jpOrigin = #{(@jp_origin.attributes.update({full_schedule: @jp_origin.full_schedule?}).to_json).html_safe};
| window.jpOriginStopPoints = #{(@jp_origin_stop_points.to_json).html_safe};
| window.transportMode = #{(@transport_mode.to_json).html_safe};
| window.transportSubmode = #{(@transport_submode.to_json).html_safe};
@@ -27,6 +27,7 @@
| window.perms = #{raw @perms};
| window.features = #{raw @features};
| window.all_missions = #{(@all_missions.to_json).html_safe};
+ | window.custom_fields = #{(@custom_fields.to_json).html_safe};
| window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe};
= javascript_pack_tag 'vehicle_journeys/index.js'
diff --git a/app/views/vehicle_journeys/show.rabl b/app/views/vehicle_journeys/show.rabl
index eeed79b34..fc65e6cb6 100644
--- a/app/views/vehicle_journeys/show.rabl
+++ b/app/views/vehicle_journeys/show.rabl
@@ -1,6 +1,6 @@
object @vehicle_journey
-[:objectid, :published_journey_name, :published_journey_identifier, :company_id, :comment, :checksum].each do |attr|
+[:objectid, :published_journey_name, :published_journey_identifier, :company_id, :comment, :checksum, :custom_fields].each do |attr|
attributes attr, :unless => lambda { |m| m.send( attr).nil?}
end
@@ -59,11 +59,11 @@ child(:vehicle_journey_at_stops_matrix, :object_root => false) do |vehicle_stops
vehicle_stop.stop_point.stop_area.city_name
end
- [:arrival_time, :departure_time].each do |att|
- node(att) do |vs|
+ [:arrival, :departure].each do |att|
+ node("#{att}_time") do |vs|
{
- hour: vs.send(att).try(:strftime, '%H'),
- minute: vs.send(att).try(:strftime, '%M')
+ hour: vs.send("#{att}_local_time").try(:strftime, '%H'),
+ minute: vs.send("#{att}_local_time").try(:strftime, '%M')
}
end
end
diff --git a/app/views/workbenches/_filters.html.slim b/app/views/workbenches/_filters.html.slim
index 4d9e0066c..491749515 100644
--- a/app/views/workbenches/_filters.html.slim
+++ b/app/views/workbenches/_filters.html.slim
@@ -19,7 +19,13 @@
.form-group.togglable
= f.label t('activerecord.models.organisation.one'), required: false, class: 'control-label'
- = f.input :organisation_name_eq_any, collection: Organisation.order('name').pluck(:name), as: :check_boxes, label: false, label_method: lambda{|w| ("<span>#{w}</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }
+ = f.input :organisation_name_eq_any,
+ collection: @workbench.workgroup.organisations.order('name').pluck(:name),
+ as: :check_boxes,
+ label: false,
+ label_method: lambda { |w| ("<span>#{w}</span>").html_safe },
+ required: false,
+ wrapper_html: { class: 'checkbox_list' }
.form-group.togglable
= f.label Referential.human_attribute_name(:validity_period), required: false, class: 'control-label'
diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim
index 17ad75051..8907f3f08 100644
--- a/app/views/workbenches/show.html.slim
+++ b/app/views/workbenches/show.html.slim
@@ -54,8 +54,8 @@
attribute: Proc.new {|w| l(w.updated_at, format: :short)} \
), \
TableBuilderHelper::Column.new( \
- key: :published_at, \
- attribute: '' \
+ key: :merged_at, \
+ attribute: Proc.new {|w| w.merged_at ? l(w.merged_at, format: :short) : '-'} \
) \
],
selectable: ->(ref){ @workbench.referentials.include?(ref) },
diff --git a/config/breadcrumbs.rb b/config/breadcrumbs.rb
index ce5cf5b0f..6da96d73a 100644
--- a/config/breadcrumbs.rb
+++ b/config/breadcrumbs.rb
@@ -96,6 +96,11 @@ crumb :compliance_check_set do |workbench, compliance_check_set|
parent :compliance_check_sets, workbench
end
+crumb :compliance_check_set_executed do |workbench, compliance_check_set|
+ link I18n.t('compliance_check_sets.executed.title', name: compliance_check_set.name), executed_workbench_compliance_check_set_path(workbench, compliance_check_set)
+ parent :compliance_check_sets, workbench
+end
+
crumb :imports do |workbench|
link I18n.t('imports.index.title'), workbench_imports_path(workbench)
parent :workbench, workbench
diff --git a/config/locales/area_types.en.yml b/config/locales/area_types.en.yml
index 9f505c5e6..34ec3243d 100644
--- a/config/locales/area_types.en.yml
+++ b/config/locales/area_types.en.yml
@@ -6,4 +6,3 @@ en:
zdlp: ZDLp
zdlr: ZDLr
lda: LDA
-
diff --git a/config/locales/compliance_check_messages.en.yml b/config/locales/compliance_check_messages.en.yml
new file mode 100644
index 000000000..216a363a3
--- /dev/null
+++ b/config/locales/compliance_check_messages.en.yml
@@ -0,0 +1,31 @@
+en:
+ compliance_check_messages:
+ 3_route_1: "The route with %{source_objectid} objectid connect the stop points %{target_0_label} (%{target_0_objectid}) and %{target_1_label} (%{target_1_objectid}) which belong to the same ZDL"
+ 3_route_2: "The route with %{source_objectid} objectid references an incoherent oppposite route %{target_0_objectid}"
+ 3_route_3: "The route with %{source_objectid} objectid doesn't have any journey pattern"
+ 3_route_4: "The route with %{source_objectid} objectid is identical with another route %{target_0_objectid}"
+ 3_route_5: "The route with %{source_objectid} objectid has a first stop from the %{target_0_label} ZDL whereas its oppoite route's last stop is from the ZDL %{target_1_label}"
+ 3_route_6: "The route with %{source_objectid} objectid does not connect enough stop points (required 2 stop points)"
+ 3_route_8: "The stop point %{target_0_label} (%{target_0_objectid}) of the route %{source_objectid} is not used by any journey pattern"
+ 3_route_9: "The route with %{source_objectid} objectid does not have a journey pattern that connect all of its stop points"
+ 3_route_10: "L'itinéraire %{source_objectid} référence un arrêt (ZDEp) désactivé %{target_0_label} (%{target_0_objectid})"
+ 3_journeypattern_1: "The journey pattern with objectid %{source_objectid} is identical with another one %{target_0_objectid}"
+ 3_journeypattern_2: "The journey pattern with %{source_objectid} objectid doesn't have any vehicle journey"
+ 3_vehiclejourney_1: "On the following vehicle journey %{source_objectid}, the waiting time %{error_value} a this stop point %{target_0_label} (%{target_0_objectid}) is greater than the threshold (%{reference_value})"
+ 3_vehiclejourney_2_1: "On the following vehicle journey %{source_objectid}, the computed speed %{error_value} between the stop points %{target_0_label} (%{target_0_objectid}) and %{target_1_label} (%{target_1_objectid}) is greater than the threshold (%{reference_value})"
+ 3_vehiclejourney_2_2: "On the following vehicle journey %{source_objectid}, the computed speed %{error_value} between the stop points %{target_0_label} (%{target_0_objectid}) and %{target_1_label} (%{target_1_objectid}) is smaller than the threshold (%{reference_value})"
+ 3_vehiclejourney_3: "The travel time on the vehicle journey with %{source_objectid} objectid between the stop points %{target_0_label} (%{target_0_objectid}) and %{target_1_label} (%{target_1_objectid}) is too far off %{error_value} the average waiting on the journey pattern"
+ 3_vehiclejourney_4: "The vehicle journey with %{source_objectid} objectid does not have a timetable"
+ 3_vehiclejourney_5_1: "The vehicle journey with %{source_objectid} objectid has an arrival time %{error_value} greater than the departure time %{reference_value} at the stop point %{target_0_label} (%{target_0_objectid})"
+ 3_vehiclejourney_5_2: "The vehicle journey with %{source_objectid} objectid has an departure time %{error_value} at stop point %{target_0_label} (%{target_0_objectid}) greater than the arrival %{reference_value} at the next stop point"
+ 3_routingconstraint_1: "The Routing Constraint Zone %{source_objectid} references an unactivated stop point (ZDEp) %{target_0_label} (%{target_0_objectid})"
+ 3_routingconstraint_2: "The Routing Constraint Zone %{source_objectid} covers all the stop points of its related route : %{target_0_objectid}."
+ 3_routingconstraint_3: "The Routing Constraint Zone %{source_objectid} has less than 2 stop points"
+ 3_line_1: "On line :%{source_label} (%{source_objectid}), no route has an opposite route"
+ 3_generic_1: "%{source_objectid} : the %{source_attribute} attribute value (%{error_value}) does not respect the following pattern : %{reference_value}"
+ 3_generic_2_1: "%{source_objectid} : the %{source_attribute} attributes's value (%{error_value}) is greater than the authorized maximum value : %{reference_value}"
+ 3_generic_2_2: "%{source_objectid} : the %{source_attribute} attributes's value (%{error_value}) is smaller than the authorized minimum value %{reference_value}"
+ 3_generic_3: "%{source_objectid} : the %{source_attribute} attribute (%{error_value}) has a value shared with : %{target_0_objectid}"
+ 3_shape_1: "Tracé %{source_objectid} : le tracé passe trop loin de l'arrêt %{target_0_label} (%{target_0_objectid}) : %{error_value} > %{reference_value}"
+ 3_shape_2: "Tracé %{source_objectid} : le tracé n'est pas défini entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid})"
+ 3_shape_3: "Le tracé de l'itinéraire %{source_objectid} est en écart avec la voirie sur %{error_value} sections" \ No newline at end of file
diff --git a/config/locales/compliance_check_messages.fr.yml b/config/locales/compliance_check_messages.fr.yml
new file mode 100644
index 000000000..db127d236
--- /dev/null
+++ b/config/locales/compliance_check_messages.fr.yml
@@ -0,0 +1,31 @@
+fr:
+ compliance_check_messages:
+ 3_route_1: "L'itinéraire %{source_objectid} dessert successivement les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) de la même zone de lieu"
+ 3_route_2: "L'itinéraire %{source_objectid} référence un itinéraire retour %{target_0_objectid} incohérent"
+ 3_route_3: "L'itinéraire %{source_objectid} n'a pas de mission"
+ 3_route_4: "L'itinéraire %{source_objectid} est identique à l'itinéraire %{target_0_objectid}"
+ 3_route_5: "L'itinéraire %{source_objectid} dessert au départ un arrêt de la ZDL %{target_0_label} alors que l'itinéraire inverse dessert à l'arrivée un arrêt de la ZDL %{target_1_label}"
+ 3_route_6: "L'itinéraire %{source_objectid} ne dessert pas assez d'arrêts (minimum 2 requis)"
+ 3_route_8: "l'arrêt %{target_0_label} (%{target_0_objectid}) de l'itinéraire %{source_objectid} n'est desservi par aucune mission"
+ 3_route_9: "L'itinéraire %{source_objectid} n'a aucune mission desservant l'ensemble de ses arrêts"
+ 3_route_10: "L'itinéraire %{source_objectid} référence un arrêt (ZDEp) désactivé %{target_0_label} (%{target_0_objectid})"
+ 3_journeypattern_1: "La mission %{source_objectid} est identique à la mission %{target_0_objectid}"
+ 3_journeypattern_2: "La mission %{source_objectid} n'a pas de course"
+ 3_vehiclejourney_1: "Sur la course %{source_objectid}, le temps d'attente %{error_value} à l'arrêt %{target_0_label} (%{target_0_objectid}) est supérieur au seuil toléré (%{reference_value})"
+ 3_vehiclejourney_2_1: "Sur la course %{source_objectid}, la vitesse calculée %{error_value} entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) est supérieure au seuil toléré (%{reference_value})"
+ 3_vehiclejourney_2_2: "Sur la course %{source_objectid}, la vitesse calculée %{error_value} entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) est inférieure au seuil toléré (%{reference_value})"
+ 3_vehiclejourney_3: "Le temps de parcours sur la course %{source_objectid} entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid}) s'écarte de %{error_value} du temps moyen constaté sur la mission"
+ 3_vehiclejourney_4: "La course %{source_objectid} n'a pas de calendrier d'application"
+ 3_vehiclejourney_5_1: "La course %{source_objectid} a un horaire d'arrivé %{error_value} supérieur à l'horaire de départ %{reference_value} à l'arrêt %{target_0_label} (%{target_0_objectid})"
+ 3_vehiclejourney_5_2: "La course %{source_objectid} a un horaire de départ %{error_value} à l'arrêt %{target_0_label} (%{target_0_objectid}) supérieur à l'horaire d'arrivé %{reference_value} à l'arrêt suivant"
+ 3_routingconstraint_1: "L'ITL %{source_objectid} référence un arrêt (ZDEp) désactivé %{target_0_label} (%{target_0_objectid})"
+ 3_routingconstraint_2: "L'ITL %{source_objectid} couvre tous les arrêts de l'itinéraire %{target_0_objectid}."
+ 3_routingconstraint_3: "L'ITL %{source_objectid} n'a pas suffisament d'arrêts (minimum 2 arrêts requis)"
+ 3_line_1: "Sur la ligne %{source_label} (%{source_objectid}), aucun itinéraire n'a d'itinéraire inverse"
+ 3_generic_1: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} qui ne respecte pas le motif %{reference_value}"
+ 3_generic_2_1: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} supérieure à la valeur maximale autorisée %{reference_value}"
+ 3_generic_2_2: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} inférieure à la valeur minimale autorisée %{reference_value}"
+ 3_generic_3: "%{source_objectid} : l'attribut %{source_attribute} a une valeur %{error_value} partagée avec %{target_0_objectid}"
+ 3_shape_1: "Tracé %{source_objectid} : le tracé passe trop loin de l'arrêt %{target_0_label} (%{target_0_objectid}) : %{error_value} > %{reference_value}"
+ 3_shape_2: "Tracé %{source_objectid} : le tracé n'est pas défini entre les arrêts %{target_0_label} (%{target_0_objectid}) et %{target_1_label} (%{target_1_objectid})"
+ 3_shape_3: "Le tracé de l'itinéraire %{source_objectid} est en écart avec la voirie sur %{error_value} sections" \ No newline at end of file
diff --git a/config/locales/compliance_check_results.en.yml b/config/locales/compliance_check_results.en.yml
deleted file mode 100644
index cd22aefb1..000000000
--- a/config/locales/compliance_check_results.en.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-en:
- compliance_check_messages:
diff --git a/config/locales/compliance_check_results.fr.yml b/config/locales/compliance_check_results.fr.yml
deleted file mode 100644
index d3fbf0900..000000000
--- a/config/locales/compliance_check_results.fr.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-fr:
- compliance_check_messages:
diff --git a/config/locales/compliance_check_sets.en.yml b/config/locales/compliance_check_sets.en.yml
index 1081b1d66..5e8c3b24f 100644
--- a/config/locales/compliance_check_sets.en.yml
+++ b/config/locales/compliance_check_sets.en.yml
@@ -22,7 +22,14 @@ en:
title: Compliance check set report
table_state: "%{lines_status} lines imported on %{lines_in_compliance_check_set} in the archive"
table_explanation: "These controls apply to all imported data and condition the construction of your organization's offer."
+ table_title: Analysed lines state
metrics: "%{ok_count} ok, %{error_count} errors, %{warning_count} warnings, %{uncheck_count} n/a"
+ metadatas:
+ referential: "Object analysed"
+ referential_type: "Apply to"
+ compliance_check_set_executed: "Compliance check set executed"
+ compliance_control_owner: "Compliance control owner"
+ import: "Import"
errors:
no_parent: "The compliance check set doesn't have any parent"
activerecord:
@@ -40,6 +47,14 @@ en:
metrics: Test results
download: Download
models:
+ compliance_check_set:
+ zero: "Compliance check set"
+ one: "Compliance check set"
+ other: "Compliance check sets"
+ compliance_check:
+ zero: "Compliance check"
+ one: "Compliance check"
+ other: "Compliance checks"
compliance_check_block:
one: compliance_control_set
other: compliance_control_sets
diff --git a/config/locales/compliance_check_sets.fr.yml b/config/locales/compliance_check_sets.fr.yml
index 8c4561ae9..20bf11d85 100644
--- a/config/locales/compliance_check_sets.fr.yml
+++ b/config/locales/compliance_check_sets.fr.yml
@@ -13,12 +13,19 @@ fr:
title: "Liste des rapports de contrôles"
search_no_results: Aucun rapport de contrôle ne correspond à votre recherche
executed:
- title: Jeu de contrôles exécutés %{name}
+ title: Jeu de contrôles exécuté %{name}
show:
title: Rapport de contrôle
- table_state: "%{lines_status} lignes importées sur %{lines_in_compliance_check_set} présentes dans l'archive"
+ table_state: "%{lines_status} lignes valides sur %{lines_in_compliance_check_set} présentes dans l'offre de transport"
table_explanation: Ces contrôles s’appliquent pour toutes les données importées et conditionnent la construction de l’offre de votre organisation
+ table_title: État des lignes analysées
metrics: "%{ok_count} ok, %{error_count} errors, %{warning_count} warnings, %{uncheck_count} n/a"
+ metadatas:
+ referential: "Objet analysé"
+ referential_type: "Appliqué à"
+ compliance_check_set_executed: "Jeu de contrôles exécuté"
+ compliance_control_owner: "Propriétaire du jeu de contrôles"
+ import: "Rapport d'import"
errors:
no_parent: "Le jeux de contrôle n'a pas de parent"
activerecord:
@@ -28,7 +35,7 @@ fr:
creation_date: Date et heure de création
associated_object: Objet associé
assigned_to: Affectation
- compliance_control_set: jeu de contrôle
+ compliance_control_set: Jeu de contrôle exécuté
name: Nom
compliance_check_resource:
name: Nom de la ligne
@@ -36,6 +43,14 @@ fr:
metrics: Résultat des tests
download: Télécharger
models:
+ compliance_check_set:
+ zero: "Rapport de contrôles"
+ one: "Rapport de contrôles"
+ other: "Rapport de contrôles"
+ compliance_check:
+ zero: "Contrôle"
+ one: "Contrôle"
+ other: "Contrôles"
compliance_check_block:
zero: "Groupe de contrôle"
one: "Groupe de contrôle"
diff --git a/config/locales/import_messages.en.yml b/config/locales/import_messages.en.yml
index 42d180abd..aad4fb772 100644
--- a/config/locales/import_messages.en.yml
+++ b/config/locales/import_messages.en.yml
@@ -1,54 +1,53 @@
en:
import_messages:
- compliance_check_messages:
- corrupt_zip_file: "The zip file %{source_filename} is corrupted and cannot be read"
- inconsistent_zip_file: "The zip file %{source_filename} contains unexpected directories: %{spurious_dirs}, which are ignored"
- referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les mêmes périodes et lignes"
- 1_netexstif_2: "Le fichier %{source_filename} ne respecte pas la syntaxe XML ou la XSD NeTEx : erreur '%{error_value}' rencontré"
- 1_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
- 2_netexstif_1_1: "Le fichier commun.xml ne contient pas de frame nommée NETEX_COMMUN"
- 2_netexstif_1_2: "Le fichier commun.xml contient une frame nommée %{error_value} non acceptée"
- 2_netexstif_2_1: "Le fichier calendriers.xml ne contient pas de frame nommée NETEX_CALENDRIER"
- 2_netexstif_2_2: "Le fichier calendriers.xml contient une frame nommée %{error_value} non acceptée"
- 2_netexstif_3_1: "Le fichier %{source_filename} ne contient pas de frame nommée NETEX_OFFRE_LIGNE"
- 2_netexstif_3_2: "Le fichier %{source_filename} contient une frame nommée %{error_value} non acceptée"
- 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{error_value} obligatoire"
- 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{error_value} non acceptée"
- 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{error_value} ne respecte pas la syntaxe %{reference_value}"
- 2_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{error_value} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
- 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'"
- 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{error_value}"
- 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe : référence interne attendue"
- 2_netexstif_8_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type interne mais disposant d'un contenu (version externe possible)"
- 2_netexstif_9_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type interne : référence externe attendue"
- 2_netexstif_9_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe sans information de version"
- 2_netexstif_10: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe inconnue"
- 2_netexstif_daytype_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} ne définit aucun calendrier, il est ignoré"
- 2_netexstif_daytype_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} est reliée à des périodes mais ne définit pas de types de jours"
- 2_netexstif_daytypeassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingDay"
- 2_netexstif_daytypeassignment_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingPeriod sur la condition IsAvailable à faux."
- 2_netexstif_direction_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut Name"
- 2_netexstif_direction_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} définit un attribut %{error_value} non autorisé"
- 2_netexstif_notice_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} doit définir un texte"
- 2_netexstif_notice_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} de type %{error_value} est ignoré"
- 2_netexstif_operatingperiod_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet OperatingPeriod d'identifiant %{source_objectid} a une date de fin %{error_value} inférieure ou égale à la date de début %{reference_value}"
- 2_netexstif_passengerstopassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'attribut %{source_label} de l'objet PassengerStopAssignment %{source_objectid} doit être renseigné"
- 2_netexstif_passengerstopassignment_2: "L'arrêt %{source_objectid} ne fait pas partie des arrêts disponibles pour votre organisation."
- 2_netexstif_passingtime_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} ne dispose pas de DepartureTime"
- 2_netexstif_passingtime_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} fournit un ArrivalTime supérieur à son DepartureTime"
- 2_netexstif_route_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} a une valeur de l'attribut DirectionType interdite : %{error_value}"
- 2_netexstif_route_2_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{error_value} qui ne le référence pas"
- 2_netexstif_route_2_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{error_value} de même DirectionType"
- 2_netexstif_route_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Les ServiceJourneyPattern de l'objet Route d'identifiant %{source_objectid} ne permettent pas de reconstituer la séquence des arrêts de celui-ci"
- 2_netexstif_route_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, Les informations de montée/Descente à l'arrêt %{error_value} de la Route %{source_objectid} diffèrent sur plusieurs ServiceJourneyPattern, ces informations ne sont pas importées"
- 2_netexstif_routingconstraintzone_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} doit référencer au moins deux ScheduledStopPoint"
- 2_netexstif_routingconstraintzone_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} a une valeur interdite pour l'attribut ZoneUse : %{error_value}"
- 2_netexstif_servicejourney_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} ne référence pas de ServiceJourneyPattern"
- 2_netexstif_servicejourney_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} fournit plus d'un trainNumber"
- 2_netexstif_servicejourney_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Le nombre d'horaires (passing_times) de l'objet ServiceJourney d'identifiant %{source_objectid} n'est pas cohérent avec le ServiceJourneyPattern associé."
- 2_netexstif_servicejourney_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} fournit des horaires antérieurs au passingTime précédent."
- 2_netexstif_servicejourneypattern_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} ne référence pas de Route"
- 2_netexstif_servicejourneypattern_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} doit contenir au moins 2 StopPointInJourneyPattern"
- 2_netexstif_servicejourneypattern_3_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut ServiceJourneyPatternType"
- 2_netexstif_servicejourneypattern_3_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} a une valeur interdite %{error_value} pour l'attribut ServiceJourneyPatternType différente de 'passenger'"
- 2_netexstif_servicejourneypattern_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, objet ServiceJourneyPattern d'identifiant %{source_objectid} : les attributs 'order' des StopPointInJourneyPattern ne sont pas croissants."
+ corrupt_zip_file: "The zip file %{source_filename} is corrupted and cannot be read"
+ inconsistent_zip_file: "The zip file %{source_filename} contains unexpected directories: %{spurious_dirs}, which are ignored"
+ referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les mêmes périodes et lignes"
+ 1_netexstif_2: "Le fichier %{source_filename} ne respecte pas la syntaxe XML ou la XSD NeTEx : erreur '%{error_value}' rencontré"
+ 1_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
+ 2_netexstif_1_1: "Le fichier commun.xml ne contient pas de frame nommée NETEX_COMMUN"
+ 2_netexstif_1_2: "Le fichier commun.xml contient une frame nommée %{error_value} non acceptée"
+ 2_netexstif_2_1: "Le fichier calendriers.xml ne contient pas de frame nommée NETEX_CALENDRIER"
+ 2_netexstif_2_2: "Le fichier calendriers.xml contient une frame nommée %{error_value} non acceptée"
+ 2_netexstif_3_1: "Le fichier %{source_filename} ne contient pas de frame nommée NETEX_OFFRE_LIGNE"
+ 2_netexstif_3_2: "Le fichier %{source_filename} contient une frame nommée %{error_value} non acceptée"
+ 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{error_value} obligatoire"
+ 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{error_value} non acceptée"
+ 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{error_value} ne respecte pas la syntaxe %{reference_value}"
+ 2_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{error_value} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
+ 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'"
+ 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{error_value}"
+ 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe : référence interne attendue"
+ 2_netexstif_8_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type interne mais disposant d'un contenu (version externe possible)"
+ 2_netexstif_9_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type interne : référence externe attendue"
+ 2_netexstif_9_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe sans information de version"
+ 2_netexstif_10: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe inconnue"
+ 2_netexstif_daytype_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} ne définit aucun calendrier, il est ignoré"
+ 2_netexstif_daytype_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} est reliée à des périodes mais ne définit pas de types de jours"
+ 2_netexstif_daytypeassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingDay"
+ 2_netexstif_daytypeassignment_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingPeriod sur la condition IsAvailable à faux."
+ 2_netexstif_direction_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut Name"
+ 2_netexstif_direction_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} définit un attribut %{error_value} non autorisé"
+ 2_netexstif_notice_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} doit définir un texte"
+ 2_netexstif_notice_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} de type %{error_value} est ignoré"
+ 2_netexstif_operatingperiod_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet OperatingPeriod d'identifiant %{source_objectid} a une date de fin %{error_value} inférieure ou égale à la date de début %{reference_value}"
+ 2_netexstif_passengerstopassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'attribut %{source_label} de l'objet PassengerStopAssignment %{source_objectid} doit être renseigné"
+ 2_netexstif_passengerstopassignment_2: "L'arrêt %{source_objectid} ne fait pas partie des arrêts disponibles pour votre organisation."
+ 2_netexstif_passingtime_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} ne dispose pas de DepartureTime"
+ 2_netexstif_passingtime_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} fournit un ArrivalTime supérieur à son DepartureTime"
+ 2_netexstif_route_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} a une valeur de l'attribut DirectionType interdite : %{error_value}"
+ 2_netexstif_route_2_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{error_value} qui ne le référence pas"
+ 2_netexstif_route_2_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{error_value} de même DirectionType"
+ 2_netexstif_route_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Les ServiceJourneyPattern de l'objet Route d'identifiant %{source_objectid} ne permettent pas de reconstituer la séquence des arrêts de celui-ci"
+ 2_netexstif_route_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, Les informations de montée/Descente à l'arrêt %{error_value} de la Route %{source_objectid} diffèrent sur plusieurs ServiceJourneyPattern, ces informations ne sont pas importées"
+ 2_netexstif_routingconstraintzone_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} doit référencer au moins deux ScheduledStopPoint"
+ 2_netexstif_routingconstraintzone_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} a une valeur interdite pour l'attribut ZoneUse : %{error_value}"
+ 2_netexstif_servicejourney_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} ne référence pas de ServiceJourneyPattern"
+ 2_netexstif_servicejourney_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} fournit plus d'un trainNumber"
+ 2_netexstif_servicejourney_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Le nombre d'horaires (passing_times) de l'objet ServiceJourney d'identifiant %{source_objectid} n'est pas cohérent avec le ServiceJourneyPattern associé."
+ 2_netexstif_servicejourney_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} fournit des horaires antérieurs au passingTime précédent."
+ 2_netexstif_servicejourneypattern_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} ne référence pas de Route"
+ 2_netexstif_servicejourneypattern_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} doit contenir au moins 2 StopPointInJourneyPattern"
+ 2_netexstif_servicejourneypattern_3_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut ServiceJourneyPatternType"
+ 2_netexstif_servicejourneypattern_3_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} a une valeur interdite %{error_value} pour l'attribut ServiceJourneyPatternType différente de 'passenger'"
+ 2_netexstif_servicejourneypattern_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, objet ServiceJourneyPattern d'identifiant %{source_objectid} : les attributs 'order' des StopPointInJourneyPattern ne sont pas croissants." \ No newline at end of file
diff --git a/config/locales/import_messages.fr.yml b/config/locales/import_messages.fr.yml
index bdb0d6c50..1e5054648 100644
--- a/config/locales/import_messages.fr.yml
+++ b/config/locales/import_messages.fr.yml
@@ -1,54 +1,53 @@
fr:
import_messages:
- compliance_check_messages:
- corrupt_zip_file: "Le fichier zip est corrompu, et ne peut être lu"
- inconsistent_zip_file: "Le fichier zip contient des repertoires non prévus : %{spurious_dirs} qui seront ignorés"
- referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les mêmes périodes et lignes"
- 1_netexstif_2: "Le fichier %{source_filename} ne respecte pas la syntaxe XML ou la XSD NeTEx : erreur '%{error_value}' rencontré"
- 1_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
- 2_netexstif_1_1: "Le fichier commun.xml ne contient pas de frame nommée NETEX_COMMUN"
- 2_netexstif_1_2: "Le fichier commun.xml contient une frame nommée %{error_value} non acceptée"
- 2_netexstif_2_1: "Le fichier calendriers.xml ne contient pas de frame nommée NETEX_CALENDRIER"
- 2_netexstif_2_2: "Le fichier calendriers.xml contient une frame nommée %{error_value} non acceptée"
- 2_netexstif_3_1: "Le fichier %{source_filename} ne contient pas de frame nommée NETEX_OFFRE_LIGNE"
- 2_netexstif_3_2: "Le fichier %{source_filename} contient une frame nommée %{error_value} non acceptée"
- 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{error_value} obligatoire"
- 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{error_value} non acceptée"
- 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{error_value} ne respecte pas la syntaxe %{reference_value}"
- 2_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{error_value} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
- 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'"
- 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{error_value}"
- 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe : référence interne attendue"
- 2_netexstif_8_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type interne mais disposant d'un contenu (version externe possible)"
- 2_netexstif_9_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type interne : référence externe attendue"
- 2_netexstif_9_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe sans information de version"
- 2_netexstif_10: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe inconnue"
- 2_netexstif_daytype_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} ne définit aucun calendrier, il est ignoré"
- 2_netexstif_daytype_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} est reliée à des périodes mais ne définit pas de types de jours"
- 2_netexstif_daytypeassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingDay"
- 2_netexstif_daytypeassignment_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingPeriod sur la condition IsAvailable à faux."
- 2_netexstif_direction_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut Name"
- 2_netexstif_direction_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} définit un attribut %{error_value} non autorisé"
- 2_netexstif_notice_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} doit définir un texte"
- 2_netexstif_notice_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} de type %{error_value} est ignoré"
- 2_netexstif_operatingperiod_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet OperatingPeriod d'identifiant %{source_objectid} a une date de fin %{error_value} inférieure ou égale à la date de début %{reference_value}"
- 2_netexstif_passengerstopassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'attribut %{source_label} de l'objet PassengerStopAssignment %{source_objectid} doit être renseigné"
- 2_netexstif_passengerstopassignment_2: "L'arrêt %{source_objectid} ne fait pas partie des arrêts disponibles pour votre organisation."
- 2_netexstif_passingtime_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} ne dispose pas de DepartureTime"
- 2_netexstif_passingtime_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} fournit un ArrivalTime supérieur à son DepartureTime"
- 2_netexstif_route_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} a une valeur de l'attribut DirectionType interdite : %{error_value}"
- 2_netexstif_route_2_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{error_value} qui ne le référence pas"
- 2_netexstif_route_2_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{error_value} de même DirectionType"
- 2_netexstif_route_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Les ServiceJourneyPattern de l'objet Route d'identifiant %{source_objectid} ne permettent pas de reconstituer la séquence des arrêts de celui-ci"
- 2_netexstif_route_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, Les informations de montée/Descente à l'arrêt %{error_value} de la Route %{source_objectid} diffèrent sur plusieurs ServiceJourneyPattern, ces informations ne sont pas importées"
- 2_netexstif_routingconstraintzone_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} doit référencer au moins deux ScheduledStopPoint"
- 2_netexstif_routingconstraintzone_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} a une valeur interdite pour l'attribut ZoneUse : %{error_value}"
- 2_netexstif_servicejourney_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} ne référence pas de ServiceJourneyPattern"
- 2_netexstif_servicejourney_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} fournit plus d'un trainNumber"
- 2_netexstif_servicejourney_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Le nombre d'horaires (passing_times) de l'objet ServiceJourney d'identifiant %{source_objectid} n'est pas cohérent avec le ServiceJourneyPattern associé."
- 2_netexstif_servicejourney_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} fournit des horaires antérieurs au passingTime précédent."
- 2_netexstif_servicejourneypattern_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} ne référence pas de Route"
- 2_netexstif_servicejourneypattern_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} doit contenir au moins 2 StopPointInJourneyPattern"
- 2_netexstif_servicejourneypattern_3_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut ServiceJourneyPatternType"
- 2_netexstif_servicejourneypattern_3_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} a une valeur interdite %{error_value} pour l'attribut ServiceJourneyPatternType différente de 'passenger'"
- 2_netexstif_servicejourneypattern_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, objet ServiceJourneyPattern d'identifiant %{source_objectid} : les attributs 'order' des StopPointInJourneyPattern ne sont pas croissants."
+ corrupt_zip_file: "Le fichier zip est corrompu, et ne peut être lu"
+ inconsistent_zip_file: "Le fichier zip contient des repertoires non prévus : %{spurious_dirs} qui seront ignorés"
+ referential_creation: "Le référentiel n'a pas pu être créé car un référentiel existe déjà sur les mêmes périodes et lignes"
+ 1_netexstif_2: "Le fichier %{source_filename} ne respecte pas la syntaxe XML ou la XSD NeTEx : erreur '%{error_value}' rencontré"
+ 1_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
+ 2_netexstif_1_1: "Le fichier commun.xml ne contient pas de frame nommée NETEX_COMMUN"
+ 2_netexstif_1_2: "Le fichier commun.xml contient une frame nommée %{error_value} non acceptée"
+ 2_netexstif_2_1: "Le fichier calendriers.xml ne contient pas de frame nommée NETEX_CALENDRIER"
+ 2_netexstif_2_2: "Le fichier calendriers.xml contient une frame nommée %{error_value} non acceptée"
+ 2_netexstif_3_1: "Le fichier %{source_filename} ne contient pas de frame nommée NETEX_OFFRE_LIGNE"
+ 2_netexstif_3_2: "Le fichier %{source_filename} contient une frame nommée %{error_value} non acceptée"
+ 2_netexstif_3_3: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} ne contient pas la frame %{error_value} obligatoire"
+ 2_netexstif_3_4: "la frame NETEX_OFFRE_LIGNE du fichier %{source_filename} contient une frame %{error_value} non acceptée"
+ 2_netexstif_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'identifiant %{source_objectid} de l'objet %{error_value} ne respecte pas la syntaxe %{reference_value}"
+ 2_netexstif_5: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{error_value} d'identifiant %{source_objectid} a une date de mise à jour dans le futur"
+ 2_netexstif_6: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} a un état de modification interdit : 'delete'"
+ 2_netexstif_7: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{reference_value} de syntaxe invalide : %{error_value}"
+ 2_netexstif_8_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe : référence interne attendue"
+ 2_netexstif_8_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type interne mais disposant d'un contenu (version externe possible)"
+ 2_netexstif_9_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type interne : référence externe attendue"
+ 2_netexstif_9_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe sans information de version"
+ 2_netexstif_10: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet %{source_label} d'identifiant %{source_objectid} définit une référence %{error_value} de type externe inconnue"
+ 2_netexstif_daytype_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} ne définit aucun calendrier, il est ignoré"
+ 2_netexstif_daytype_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayType d'identifiant %{source_objectid} est reliée à des périodes mais ne définit pas de types de jours"
+ 2_netexstif_daytypeassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingDay"
+ 2_netexstif_daytypeassignment_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet DayTypeAssignment d'identifiant %{source_objectid} ne peut référencer un OperatingPeriod sur la condition IsAvailable à faux."
+ 2_netexstif_direction_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut Name"
+ 2_netexstif_direction_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Direction d'identifiant %{source_objectid} définit un attribut %{error_value} non autorisé"
+ 2_netexstif_notice_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} doit définir un texte"
+ 2_netexstif_notice_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Notice d'identifiant %{source_objectid} de type %{error_value} est ignoré"
+ 2_netexstif_operatingperiod_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet OperatingPeriod d'identifiant %{source_objectid} a une date de fin %{error_value} inférieure ou égale à la date de début %{reference_value}"
+ 2_netexstif_passengerstopassignment_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'attribut %{source_label} de l'objet PassengerStopAssignment %{source_objectid} doit être renseigné"
+ 2_netexstif_passengerstopassignment_2: "L'arrêt %{source_objectid} ne fait pas partie des arrêts disponibles pour votre organisation."
+ 2_netexstif_passingtime_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} ne dispose pas de DepartureTime"
+ 2_netexstif_passingtime_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} fournit un ArrivalTime supérieur à son DepartureTime"
+ 2_netexstif_route_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} a une valeur de l'attribut DirectionType interdite : %{error_value}"
+ 2_netexstif_route_2_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{error_value} qui ne le référence pas"
+ 2_netexstif_route_2_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet Route d'identifiant %{source_objectid} référence un objet Route inverse %{error_value} de même DirectionType"
+ 2_netexstif_route_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Les ServiceJourneyPattern de l'objet Route d'identifiant %{source_objectid} ne permettent pas de reconstituer la séquence des arrêts de celui-ci"
+ 2_netexstif_route_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, Les informations de montée/Descente à l'arrêt %{error_value} de la Route %{source_objectid} diffèrent sur plusieurs ServiceJourneyPattern, ces informations ne sont pas importées"
+ 2_netexstif_routingconstraintzone_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} doit référencer au moins deux ScheduledStopPoint"
+ 2_netexstif_routingconstraintzone_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, l'objet RoutingConstraintZone %{source_objectid} a une valeur interdite pour l'attribut ZoneUse : %{error_value}"
+ 2_netexstif_servicejourney_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} ne référence pas de ServiceJourneyPattern"
+ 2_netexstif_servicejourney_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourney d'identifiant %{source_objectid} fournit plus d'un trainNumber"
+ 2_netexstif_servicejourney_3: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : Le nombre d'horaires (passing_times) de l'objet ServiceJourney d'identifiant %{source_objectid} n'est pas cohérent avec le ServiceJourneyPattern associé."
+ 2_netexstif_servicejourney_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} , objet ServiceJourney d'identifiant %{source_objectid} : le passingTime de rang %{error_value} fournit des horaires antérieurs au passingTime précédent."
+ 2_netexstif_servicejourneypattern_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} ne référence pas de Route"
+ 2_netexstif_servicejourneypattern_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} doit contenir au moins 2 StopPointInJourneyPattern"
+ 2_netexstif_servicejourneypattern_3_1: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} n'a pas de valeur pour l'attribut ServiceJourneyPatternType"
+ 2_netexstif_servicejourneypattern_3_2: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number} : l'objet ServiceJourneyPattern d'identifiant %{source_objectid} a une valeur interdite %{error_value} pour l'attribut ServiceJourneyPatternType différente de 'passenger'"
+ 2_netexstif_servicejourneypattern_4: "%{source_filename}-Ligne %{source_line_number}-Colonne %{source_column_number}, objet ServiceJourneyPattern d'identifiant %{source_objectid} : les attributs 'order' des StopPointInJourneyPattern ne sont pas croissants."
diff --git a/config/locales/lines.en.yml b/config/locales/lines.en.yml
index 49a629557..4b2bdfdb8 100644
--- a/config/locales/lines.en.yml
+++ b/config/locales/lines.en.yml
@@ -21,8 +21,12 @@ en:
show_company: 'Show company'
new:
title: "Add a new line"
+ create:
+ title: "Add a new line"
edit:
title: "Update line %{name}"
+ update:
+ title: "Update line %{name}"
show:
title: "Line %{name}"
routes:
diff --git a/config/locales/lines.fr.yml b/config/locales/lines.fr.yml
index 8fd409f1e..6317e2930 100644
--- a/config/locales/lines.fr.yml
+++ b/config/locales/lines.fr.yml
@@ -21,8 +21,12 @@ fr:
show_company: 'Voir le transporteur principal'
new:
title: "Ajouter une ligne"
+ create:
+ title: "Ajouter une ligne"
edit:
title: "Editer la ligne %{name}"
+ update:
+ title: "Editer la ligne %{name}"
show:
title: "Ligne %{name}"
routes:
diff --git a/config/locales/referentials.en.yml b/config/locales/referentials.en.yml
index f41e35446..eb8eae98d 100644
--- a/config/locales/referentials.en.yml
+++ b/config/locales/referentials.en.yml
@@ -91,7 +91,7 @@ en:
routing_constraint_zone: Routing constraint zone
validity_period: "Inclusive validity period"
updated_at: "Updated"
- published_at: "Integrated"
+ merged_at: "Finalized"
archived_at: "Archived"
archived_at_null: "Unarchived"
created_from: 'Created from'
diff --git a/config/locales/referentials.fr.yml b/config/locales/referentials.fr.yml
index 0f6e71520..37af8a4eb 100644
--- a/config/locales/referentials.fr.yml
+++ b/config/locales/referentials.fr.yml
@@ -92,7 +92,7 @@ fr:
validity_period: "Période de validité englobante"
updated_at: "Edité le"
created_at: "Créé le"
- published_at: "Intégré le"
+ merged_at: "Finalisé le"
archived_at: "Conservé"
archived_at_null: "En préparation"
created_from: 'Créé à partir de'
diff --git a/config/locales/stop_areas.en.yml b/config/locales/stop_areas.en.yml
index f3ab4e557..09e8d1a82 100644
--- a/config/locales/stop_areas.en.yml
+++ b/config/locales/stop_areas.en.yml
@@ -16,7 +16,9 @@ en:
accessibility: "Accessibility"
actions:
new: "Add a new stop"
+ create: "Add a new stop"
edit: "Edit this stop"
+ update: "Edit this stop"
destroy: "Remove"
activate: "Activate this stop"
deactivate: "Deactivate this stop"
diff --git a/config/locales/stop_areas.fr.yml b/config/locales/stop_areas.fr.yml
index 6131efdfc..0095bbe6d 100644
--- a/config/locales/stop_areas.fr.yml
+++ b/config/locales/stop_areas.fr.yml
@@ -16,7 +16,9 @@ fr:
accessibility: "Accessibilité"
actions:
new: "Ajouter un arrêt"
+ create: "Ajouter un arrêt"
edit: "Editer cet arrêt"
+ update: "Editer cet arrêt"
destroy: "Supprimer"
activate: "Activer cet arrêt"
deactivate: "Désactiver cet arrêt"
diff --git a/config/routes.rb b/config/routes.rb
index 8b5faff03..0f60733af 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -14,6 +14,7 @@ ChouetteIhm::Application.routes.draw do
resources :compliance_check_sets, only: [:index, :show] do
get :executed, on: :member
resources :compliance_checks, only: [:show]
+ resources :compliance_check_messages, only: [:index]
end
resource :output, controller: :workbench_outputs
diff --git a/db/migrate/20180111200406_add_merged_at_to_referentials.rb b/db/migrate/20180111200406_add_merged_at_to_referentials.rb
new file mode 100644
index 000000000..27b11fa29
--- /dev/null
+++ b/db/migrate/20180111200406_add_merged_at_to_referentials.rb
@@ -0,0 +1,5 @@
+class AddMergedAtToReferentials < ActiveRecord::Migration
+ def change
+ add_column :referentials, :merged_at, :datetime
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index f55800c8b..2c5520110 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20180109180350) do
+ActiveRecord::Schema.define(version: 20180111200406) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -676,6 +676,7 @@ ActiveRecord::Schema.define(version: 20180109180350) do
t.boolean "ready", default: false
t.integer "referential_suite_id", limit: 8
t.string "objectid_format"
+ t.datetime "merged_at"
end
add_index "referentials", ["created_from_id"], name: "index_referentials_on_created_from_id", using: :btree
diff --git a/package.json b/package.json
index 01625839c..80ca22f83 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
"grunt-watch-change": "^0.1.1",
"jest": "22.0.4",
"jest-context": "^2.1.0",
+ "jest-environment-jsdom-global": "^1.0.2",
"jest-set": "^2.0.0",
"react-addons-test-utils": "15.6.2",
"react-test-renderer": "^16.2.0",
@@ -47,6 +48,7 @@
"roots": [
"<rootDir>/spec/javascript"
],
+ "testEnvironment": "jest-environment-jsdom-global",
"setupFiles": [
"<rootDir>/spec/javascript/spec_helper.js",
"jest-context/setup",
diff --git a/spec/decorators/referential_decorator_spec.rb b/spec/decorators/referential_decorator_spec.rb
index 879ab7d4b..9e34a0109 100644
--- a/spec/decorators/referential_decorator_spec.rb
+++ b/spec/decorators/referential_decorator_spec.rb
@@ -69,6 +69,7 @@ RSpec.describe ReferentialDecorator, type: [:helper, :decorator] do
expect_action_link_elements.to be_empty
expect_action_link_hrefs.to eq([
referential_time_tables_path(object),
+ new_referential_path(from: object)
])
end
end
diff --git a/spec/factories/chouette_vehicle_journey_at_stop.rb b/spec/factories/chouette_vehicle_journey_at_stop.rb
index 831e347d4..07a4ec557 100644
--- a/spec/factories/chouette_vehicle_journey_at_stop.rb
+++ b/spec/factories/chouette_vehicle_journey_at_stop.rb
@@ -1,9 +1,9 @@
FactoryGirl.define do
factory :vehicle_journey_at_stop, :class => Chouette::VehicleJourneyAtStop do
association :vehicle_journey, :factory => :vehicle_journey
+ association :stop_point, :factory => :stop_point
departure_day_offset { 0 }
departure_time { Time.now }
arrival_time { Time.now - 1.hour }
end
end
-
diff --git a/spec/features/compliance_check_sets_spec.rb b/spec/features/compliance_check_sets_spec.rb
index 6b7d7a4f8..5cace04d4 100644
--- a/spec/features/compliance_check_sets_spec.rb
+++ b/spec/features/compliance_check_sets_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe "ComplianceCheckSets", type: :feature do
expect_breadcrumb_links "Accueil", "Gestion de l'offre", "Liste des rapports de contrôles"
# Headline
- expect( page ).to have_content("Jeu de contrôles exécutés #{compliance_check_set.name}")
+ expect( page ).to have_content(I18n.t("compliance_check_sets.executed.title", name: compliance_check_set.name))
# Information Definition List
expect( page.first('.dl-term') ).to have_content("Nom")
diff --git a/spec/features/workbenches/workbenches_show_spec.rb b/spec/features/workbenches/workbenches_show_spec.rb
index f1151a67b..7be813b94 100644
--- a/spec/features/workbenches/workbenches_show_spec.rb
+++ b/spec/features/workbenches/workbenches_show_spec.rb
@@ -22,11 +22,69 @@ RSpec.describe 'Workbenches', type: :feature do
end
end
+ it 'lists referentials in the current workgroup' do
+ other_workbench = create(
+ :workbench,
+ line_referential: line_ref,
+ workgroup: workbench.workgroup
+ )
+ other_referential = create(
+ :workbench_referential,
+ workbench: other_workbench,
+ organisation: other_workbench.organisation,
+ metadatas: [
+ create(
+ :referential_metadata,
+ lines: [create(:line, line_referential: line_ref)]
+ )
+ ]
+ )
+
+ hidden_referential = create(
+ :workbench_referential,
+ workbench: create(
+ :workbench,
+ line_referential: line_ref
+ ),
+ metadatas: [
+ create(
+ :referential_metadata,
+ lines: [create(:line, line_referential: line_ref)]
+ )
+ ]
+ )
+
+ visit workbench_path(workbench)
+
+ expect(page).to have_content(referential.name),
+ "Couldn't find `referential`: `#{referential.inspect}`"
+ expect(page).to have_content(other_referential.name),
+ "Couldn't find `other_referential`: `#{other_referential.inspect}`"
+ expect(page).to_not have_content(hidden_referential.name),
+ "Couldn't find `hidden_referential`: `#{hidden_referential.inspect}`"
+ end
+
context 'filtering' do
let!(:another_organisation) { create :organisation }
let(:another_line) { create :line, line_referential: line_ref }
let(:another_ref_metadata) { create(:referential_metadata, lines: [another_line]) }
- let!(:other_referential) { create :workbench_referential, workbench: workbench, metadatas: [another_ref_metadata] }
+ let(:other_workbench) do
+ create(
+ :workbench,
+ line_referential: line_ref,
+ organisation: another_organisation,
+ workgroup: workbench.workgroup
+ )
+ end
+ let!(:other_referential) do
+ create(
+ :workbench_referential,
+ workbench: other_workbench,
+ metadatas: [another_ref_metadata],
+ organisation: other_workbench.organisation
+ )
+ end
+
before(:each) do
visit workbench_path(workbench)
@@ -64,6 +122,18 @@ RSpec.describe 'Workbenches', type: :feature do
click_button I18n.t('actions.filter')
expect(find(box)).to be_checked
end
+
+ it 'only lists organisations in the current workgroup' do
+ unaffiliated_workbench = workbench.dup
+ unaffiliated_workbench.update(organisation: create(:organisation))
+
+ expect(page).to have_selector(
+ "#q_organisation_name_eq_any_#{@user.organisation.name.parameterize.underscore}"
+ )
+ expect(page).to_not have_selector(
+ "#q_organisation_name_eq_any_#{unaffiliated_workbench.name.parameterize.underscore}"
+ )
+ end
end
context 'filter by status' do
diff --git a/spec/helpers/table_builder_helper_spec.rb b/spec/helpers/table_builder_helper_spec.rb
index e82697b0a..8b383d88d 100644
--- a/spec/helpers/table_builder_helper_spec.rb
+++ b/spec/helpers/table_builder_helper_spec.rb
@@ -55,7 +55,7 @@ describe TableBuilderHelper, type: :helper do
<th><a href="/workbenches/#{workbench.id}?direction=desc&amp;sort=lines">Lignes<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th>
<th><a href="/workbenches/#{workbench.id}?direction=desc&amp;sort=created_at">Créé le<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th>
<th><a href="/workbenches/#{workbench.id}?direction=desc&amp;sort=updated_at">Edité le<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th>
- <th><a href="/workbenches/#{workbench.id}?direction=desc&amp;sort=published_at">Intégré le<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th>
+ <th><a href="/workbenches/#{workbench.id}?direction=desc&amp;sort=merged_at">Finalisé le<span class="orderers"><span class="fa fa-sort-asc active"></span><span class="fa fa-sort-desc "></span></span></a></th>
<th></th>
</tr>
</thead>
@@ -144,7 +144,7 @@ describe TableBuilderHelper, type: :helper do
attribute: Proc.new {|w| l(w.updated_at, format: :short)}
),
TableBuilderHelper::Column.new(
- key: :published_at,
+ key: :merged_at,
attribute: ''
)
],
diff --git a/spec/javascript/time_table/reducers/timetable_spec.js b/spec/javascript/time_table/reducers/timetable_spec.js
index f0f9eaa8c..926fb2687 100644
--- a/spec/javascript/time_table/reducers/timetable_spec.js
+++ b/spec/javascript/time_table/reducers/timetable_spec.js
@@ -22,8 +22,6 @@ let json = {
time_table_dates: time_table_dates
}
-
-
describe('timetable reducer with empty state', () => {
beforeEach(() => {
state = {
@@ -87,6 +85,7 @@ describe('timetable reducer with filled state', () => {
periode_range: periode_range,
currentPage: current_periode_range
}
+ jsdom.reconfigure({url: "http://example.com/foo/bar"})
expect(
timetableReducer(state, {
type: 'GO_TO_PREVIOUS_PAGE',
diff --git a/spec/javascript/vehicle_journeys/components/CustomFieldsInputs_spec.js b/spec/javascript/vehicle_journeys/components/CustomFieldsInputs_spec.js
new file mode 100644
index 000000000..4f8d42d2d
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/components/CustomFieldsInputs_spec.js
@@ -0,0 +1,41 @@
+import React, { Component } from 'react'
+import CustomFieldsInputs from '../../../../app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs'
+import renderer from 'react-test-renderer'
+require('select2')
+
+describe('CustomFieldsInputs', () => {
+ set('values', () => {
+ return {}
+ })
+
+ set('component', () => {
+ let inputs = renderer.create(
+ <CustomFieldsInputs
+ values={values}
+ disabled={false}
+ onUpdate={()=>{}}
+ />
+ ).toJSON()
+
+ return inputs
+ })
+
+ it('should match the snapshot', () => {
+ expect(component).toMatchSnapshot()
+ })
+
+ // context('with fields', () => {
+ // set('values', () => {
+ // return {
+ // foo: {
+ // options: { list_values: ["", "1", "2"] },
+ // field_type: "list",
+ // name: "test"
+ // }
+ // }
+ // })
+ // it('should match the snapshot', () => {
+ // expect(component).toMatchSnapshot()
+ // })
+ // })
+})
diff --git a/spec/javascript/vehicle_journeys/components/__snapshots__/CustomFieldsInputs_spec.js.snap b/spec/javascript/vehicle_journeys/components/__snapshots__/CustomFieldsInputs_spec.js.snap
new file mode 100644
index 000000000..c93ec0097
--- /dev/null
+++ b/spec/javascript/vehicle_journeys/components/__snapshots__/CustomFieldsInputs_spec.js.snap
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`CustomFieldsInputs should match the snapshot 1`] = `<div />`;
diff --git a/spec/javascript/vehicle_journeys/reducers/vehicleJourneys_spec.js b/spec/javascript/vehicle_journeys/reducers/vehicleJourneys_spec.js
index 44e11aadf..0d7612a80 100644
--- a/spec/javascript/vehicle_journeys/reducers/vehicleJourneys_spec.js
+++ b/spec/javascript/vehicle_journeys/reducers/vehicleJourneys_spec.js
@@ -76,12 +76,12 @@ describe('vehicleJourneys reducer', () => {
let pristineVjasList = [{
delta : 0,
arrival_time : {
- hour: 0,
- minute: 0
+ hour: "00",
+ minute: "00"
},
departure_time : {
- hour: 0,
- minute: 0
+ hour: "00",
+ minute: "00"
},
stop_point_objectid: 'test',
stop_area_cityname: 'city',
@@ -89,7 +89,12 @@ describe('vehicleJourneys reducer', () => {
}]
let fakeData = {
published_journey_name: {value: 'test'},
- published_journey_identifier: {value : ''}
+ published_journey_identifier: {value : ''},
+ custom_fields: {
+ foo: {
+ value: 12
+ }
+ }
}
let fakeSelectedJourneyPattern = {id: "1"}
let fakeSelectedCompany = {name: "ALBATRANS"}
@@ -115,7 +120,12 @@ describe('vehicleJourneys reducer', () => {
selected: false,
deletable: false,
transport_mode: 'undefined',
- transport_submode: 'undefined'
+ transport_submode: 'undefined',
+ custom_fields: {
+ foo: {
+ value: 12
+ }
+ }
}, ...state])
})
@@ -132,31 +142,33 @@ describe('vehicleJourneys reducer', () => {
},
stop_point_objectid: 'test-1',
stop_area_cityname: 'city',
- dummy: true
+ dummy: false
},
{
delta : 0,
arrival_time : {
- hour: 0,
+ hour: 23,
minute: 2
},
departure_time : {
- hour: 0,
+ hour: 23,
minute: 2
},
+ departure_day_offset: -1,
+ arrival_day_offset: -1,
stop_point_objectid: 'test-2',
stop_area_cityname: 'city',
- dummy: true
+ dummy: false
},
{
delta : 0,
arrival_time : {
- hour: 0,
- minute: 2
+ hour: "00",
+ minute: "00"
},
departure_time : {
- hour: 0,
- minute: 2
+ hour: "00",
+ minute: "00"
},
stop_point_objectid: 'test-3',
stop_area_cityname: 'city',
@@ -174,7 +186,7 @@ describe('vehicleJourneys reducer', () => {
},
stop_point_objectid: 'test-4',
stop_area_cityname: 'city',
- dummy: true
+ dummy: false
}]
let fakeData = {
published_journey_name: {value: 'test'},
@@ -185,6 +197,11 @@ describe('vehicleJourneys reducer', () => {
let fakeSelectedJourneyPattern = {
id: "1",
full_schedule: true,
+ stop_areas: [
+ {stop_area_short_description: {id: 1}},
+ {stop_area_short_description: {id: 2}},
+ {stop_area_short_description: {id: 4}},
+ ],
costs: {
"1-2": {
distance: 10,
@@ -202,7 +219,84 @@ describe('vehicleJourneys reducer', () => {
type: 'ADD_VEHICLEJOURNEY',
data: fakeData,
selectedJourneyPattern: fakeSelectedJourneyPattern,
- stopPointsList: [{object_id: 'test-1', city_name: 'city', stop_area_id: 1}, {object_id: 'test-2', city_name: 'city', stop_area_id: 2}, {object_id: 'test-3', city_name: 'city', stop_area_id: 3}, {object_id: 'test-4', city_name: 'city', stop_area_id: 4}],
+ stopPointsList: [{object_id: 'test-1', city_name: 'city', stop_area_id: 1, id: 1, time_zone_offset: 0}, {object_id: 'test-2', city_name: 'city', stop_area_id: 2, id: 2, time_zone_offset: -3600}, {object_id: 'test-3', city_name: 'city', stop_area_id: 3, id: 3, time_zone_offset: 0}, {object_id: 'test-4', city_name: 'city', stop_area_id: 4, id: 4, time_zone_offset: 0}],
+ selectedCompany: fakeSelectedCompany
+ })
+ ).toEqual([{
+ journey_pattern: fakeSelectedJourneyPattern,
+ company: fakeSelectedCompany,
+ published_journey_name: 'test',
+ published_journey_identifier: '',
+ short_id: '',
+ objectid: '',
+ footnotes: [],
+ time_tables: [],
+ purchase_windows: [],
+ vehicle_journey_at_stops: pristineVjasList,
+ selected: false,
+ custom_fields: undefined,
+ deletable: false,
+ transport_mode: 'undefined',
+ transport_submode: 'undefined'
+ }, ...state])
+ })
+
+ it('should handle ADD_VEHICLEJOURNEY with a start time and a fully timed JP but the minutes are not set', () => {
+ let pristineVjasList = [{
+ delta : 0,
+ arrival_time : {
+ hour: 22,
+ minute: 0
+ },
+ departure_time : {
+ hour: 22,
+ minute: 0
+ },
+ stop_point_objectid: 'test-1',
+ stop_area_cityname: 'city',
+ dummy: false
+ },
+ {
+ delta : 0,
+ arrival_time : {
+ hour: 22,
+ minute: 3
+ },
+ departure_time : {
+ hour: 22,
+ minute: 3
+ },
+ stop_point_objectid: 'test-2',
+ stop_area_cityname: 'city',
+ dummy: false
+ }]
+ let fakeData = {
+ published_journey_name: {value: 'test'},
+ published_journey_identifier: {value : ''},
+ "start_time.hour": {value : '22'},
+ "start_time.minute": {value : ''}
+ }
+ let fakeSelectedJourneyPattern = {
+ id: "1",
+ full_schedule: true,
+ stop_areas: [
+ {stop_area_short_description: {id: 1}},
+ {stop_area_short_description: {id: 2}},
+ ],
+ costs: {
+ "1-2": {
+ distance: 10,
+ time: 63
+ },
+ }
+ }
+ let fakeSelectedCompany = {name: "ALBATRANS"}
+ expect(
+ vjReducer(state, {
+ type: 'ADD_VEHICLEJOURNEY',
+ data: fakeData,
+ selectedJourneyPattern: fakeSelectedJourneyPattern,
+ stopPointsList: [{object_id: 'test-1', city_name: 'city', stop_area_id: 1, id: 1, time_zone_offset: 0}, {object_id: 'test-2', city_name: 'city', stop_area_id: 2, id: 2, time_zone_offset: -3600}],
selectedCompany: fakeSelectedCompany
})
).toEqual([{
@@ -217,6 +311,7 @@ describe('vehicleJourneys reducer', () => {
purchase_windows: [],
vehicle_journey_at_stops: pristineVjasList,
selected: false,
+ custom_fields: undefined,
deletable: false,
transport_mode: 'undefined',
transport_submode: 'undefined'
@@ -345,12 +440,18 @@ describe('vehicleJourneys reducer', () => {
})
it('should handle EDIT_VEHICLEJOURNEY', () => {
+ let custom_fields = {
+ foo: {
+ value: 12
+ }
+ }
let fakeData = {
published_journey_name: {value : 'test'},
- published_journey_identifier: {value: 'test'}
+ published_journey_identifier: {value: 'test'},
+ custom_fields: {foo: {value: 12}}
}
let fakeSelectedCompany : {name : 'ALBATRANS'}
- let newVJ = Object.assign({}, state[0], {company: fakeSelectedCompany, published_journey_name: fakeData.published_journey_name.value, published_journey_identifier: fakeData.published_journey_identifier.value})
+ let newVJ = Object.assign({}, state[0], {company: fakeSelectedCompany, published_journey_name: fakeData.published_journey_name.value, published_journey_identifier: fakeData.published_journey_identifier.value, custom_fields})
expect(
vjReducer(state, {
type: 'EDIT_VEHICLEJOURNEY',
diff --git a/spec/models/chouette/vehicle_journey_at_stop_spec.rb b/spec/models/chouette/vehicle_journey_at_stop_spec.rb
index df8a630fe..4d4a1794e 100644
--- a/spec/models/chouette/vehicle_journey_at_stop_spec.rb
+++ b/spec/models/chouette/vehicle_journey_at_stop_spec.rb
@@ -40,6 +40,30 @@ RSpec.describe Chouette::VehicleJourneyAtStop, type: :model do
end
end
+ context "the different times" do
+ let (:at_stop) { build_stubbed(:vehicle_journey_at_stop) }
+
+ describe "without a TimeZone" do
+ it "should not offset times" do
+ expect(at_stop.departure).to eq at_stop.departure_local
+ expect(at_stop.arrival).to eq at_stop.arrival_local
+ end
+ end
+
+
+ describe "with a TimeZone" do
+ before(:each) do
+ stop = at_stop.stop_point.stop_area
+ stop.time_zone = "Mexico City"
+ end
+
+ it "should offset times" do
+ expect(at_stop.departure_local).to eq at_stop.send(:format_time, at_stop.departure_time - 6.hours)
+ expect(at_stop.arrival_local).to eq at_stop.send(:format_time, at_stop.arrival_time - 6.hours)
+ end
+ end
+ end
+
describe "#validate" do
it "displays the proper error message when day offset exceeds the max" do
bad_offset = Chouette::VehicleJourneyAtStop::DAY_OFFSET_MAX + 1
diff --git a/spec/models/chouette/vehicle_journey_spec.rb b/spec/models/chouette/vehicle_journey_spec.rb
index 3ec2387e5..2a88ac3ce 100644
--- a/spec/models/chouette/vehicle_journey_spec.rb
+++ b/spec/models/chouette/vehicle_journey_spec.rb
@@ -64,10 +64,12 @@ describe Chouette::VehicleJourney, :type => :model do
at_stop[att.to_s] = vjas.send(att) unless vjas.send(att).nil?
end
- [:arrival_time, :departure_time].map do |att|
- at_stop[att.to_s] = {
- 'hour' => vjas.send(att).strftime('%H'),
- 'minute' => vjas.send(att).strftime('%M'),
+ at_stop["stop_point_objectid"] = vjas&.stop_point&.objectid
+
+ [:arrival, :departure].map do |att|
+ at_stop["#{att}_time"] = {
+ 'hour' => vjas.send("#{att}_local_time").strftime('%H'),
+ 'minute' => vjas.send("#{att}_local_time").strftime('%M'),
}
end
at_stop
@@ -80,6 +82,7 @@ describe Chouette::VehicleJourney, :type => :model do
item['purchase_windows'] = []
item['footnotes'] = []
item['purchase_windows'] = []
+ item['custom_fields'] = vj.custom_fields
vj.vehicle_journey_at_stops.each do |vjas|
item['vehicle_journey_at_stops'] << vehicle_journey_at_stop_to_state(vjas)
@@ -94,18 +97,44 @@ describe Chouette::VehicleJourney, :type => :model do
let(:collection) { [state] }
it 'should create new vj from state' do
- new_vj = build(:vehicle_journey, objectid: nil, published_journey_name: 'dummy', route: route, journey_pattern: journey_pattern)
+ create(:custom_field, code: :energy)
+ new_vj = build(:vehicle_journey, objectid: nil, published_journey_name: 'dummy', route: route, journey_pattern: journey_pattern, custom_field_values: {energy: 99})
collection << vehicle_journey_to_state(new_vj)
expect {
Chouette::VehicleJourney.state_update(route, collection)
}.to change {Chouette::VehicleJourney.count}.by(1)
- expect(collection.last['objectid']).not_to be_nil
obj = Chouette::VehicleJourney.last
+ expect(obj).to receive(:after_commit_objectid).and_call_original
+
+ # For some reason we have to force it
+ obj.after_commit_objectid
obj.run_callbacks(:commit)
+ expect(collection.last['objectid']).to eq obj.objectid
expect(obj.published_journey_name).to eq 'dummy'
+ expect(obj.custom_fields["energy"]["value"]).to eq 99
+ end
+
+ it 'should expect local times' do
+ new_vj = build(:vehicle_journey, objectid: nil, published_journey_name: 'dummy', route: route, journey_pattern: journey_pattern)
+ stop_area = create(:stop_area, time_zone: "Mexico City")
+ stop_point = create(:stop_point, stop_area: stop_area)
+ new_vj.vehicle_journey_at_stops << build(:vehicle_journey_at_stop, vehicle_journey: vehicle_journey, stop_point: stop_point)
+ data = vehicle_journey_to_state(new_vj)
+ data['vehicle_journey_at_stops'][0]["departure_time"]["hour"] = "15"
+ data['vehicle_journey_at_stops'][0]["arrival_time"]["hour"] = "12"
+ collection << data
+ expect {
+ Chouette::VehicleJourney.state_update(route, collection)
+ }.to change {Chouette::VehicleJourney.count}.by(1)
+ created = Chouette::VehicleJourney.last.vehicle_journey_at_stops.last
+ expect(created.stop_point).to eq stop_point
+ expect(created.departure_local_time.hour).to_not eq created.departure_time.hour
+ expect(created.arrival_local_time.hour).to_not eq created.arrival_time.hour
+ expect(created.departure_local_time.hour).to eq 15
+ expect(created.arrival_local_time.hour).to eq 12
end
it 'should save vehicle_journey_at_stops of newly created vj' do
@@ -205,11 +234,13 @@ describe Chouette::VehicleJourney, :type => :model do
it 'should update vj attributes from state' do
state['published_journey_name'] = 'edited_name'
state['published_journey_identifier'] = 'edited_identifier'
+ state['custom_fields'] = {energy: {value: 99}}
Chouette::VehicleJourney.state_update(route, collection)
expect(state['errors']).to be_nil
expect(vehicle_journey.reload.published_journey_name).to eq state['published_journey_name']
expect(vehicle_journey.reload.published_journey_identifier).to eq state['published_journey_identifier']
+ expect(vehicle_journey.reload.custom_field_value("energy")).to eq 99
end
it 'should return errors when validation failed' do
diff --git a/spec/models/custom_field_spec.rb b/spec/models/custom_field_spec.rb
index 80873683c..8a6d0cb41 100644
--- a/spec/models/custom_field_spec.rb
+++ b/spec/models/custom_field_spec.rb
@@ -5,6 +5,7 @@ RSpec.describe CustomField, type: :model do
context "validates" do
it { should validate_uniqueness_of(:name).scoped_to(:resource_type) }
+ it { should validate_uniqueness_of(:code).scoped_to(:resource_type).case_insensitive }
end
context "field access" do
@@ -17,8 +18,15 @@ RSpec.describe CustomField, type: :model do
context "custom fields for a resource" do
- let!( :fields ){ (1..2).map{ create :custom_field } }
- it { expect(vj.custom_fields).to eq(fields) }
+ let!( :fields ){ [create(:custom_field), create(:custom_field, code: :energy)] }
+ let!( :instance_fields ){
+ {
+ fields[0].code => fields[0].slice(:code, :name, :field_type, :options).update(value: nil),
+ "energy" => fields[1].slice(:code, :name, :field_type, :options).update(value: 99)
+ }
+ }
+ it { expect(Chouette::VehicleJourney.custom_fields).to eq(fields) }
+ it { expect(vj.custom_fields).to eq(instance_fields) }
end
context "custom field_values for a resource" do
diff --git a/spec/policies/network_policy_spec.rb b/spec/policies/network_policy_spec.rb
index 6dc3f0d46..2b7bbcdca 100644
--- a/spec/policies/network_policy_spec.rb
+++ b/spec/policies/network_policy_spec.rb
@@ -24,19 +24,19 @@ RSpec.describe Chouette::NetworkPolicy, type: :policy do
context 'Destructive actions →' do
permissions :create? do
- it_behaves_like 'always forbidden', 'networks.create', archived_and_finalised: true
+ it_behaves_like 'permitted policy', 'networks.create'
end
permissions :destroy? do
- it_behaves_like 'always forbidden', 'networks.destroy', archived_and_finalised: true
+ it_behaves_like 'permitted policy', 'networks.destroy'
end
permissions :edit? do
- it_behaves_like 'always forbidden', 'networks.update', archived_and_finalised: true
+ it_behaves_like 'permitted policy', 'networks.update'
end
permissions :new? do
- it_behaves_like 'always forbidden', 'networks.create', archived_and_finalised: true
+ it_behaves_like 'permitted policy', 'networks.create'
end
permissions :update? do
- it_behaves_like 'always forbidden', 'networks.update', archived_and_finalised: true
+ it_behaves_like 'permitted policy', 'networks.update'
end
end
end
diff --git a/spec/policies/referential_policy_spec.rb b/spec/policies/referential_policy_spec.rb
index 8540d3ce9..778e14901 100644
--- a/spec/policies/referential_policy_spec.rb
+++ b/spec/policies/referential_policy_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
RSpec.describe ReferentialPolicy, type: :policy do
let( :record ){ build_stubbed :referential }
@@ -45,9 +46,9 @@ RSpec.describe ReferentialPolicy, type: :policy do
# Custom Permissions
# ------------------
- permissions :clone? do
- it_behaves_like 'permitted policy', 'referentials.create', archived_and_finalised: true
- end
+ # permissions :clone? do
+ # it_behaves_like 'permitted policy', 'referentials.create', archived_and_finalised: true
+ # end
permissions :archive? do
diff --git a/spec/views/offer_workbenches/show.html.erb_spec.rb b/spec/views/offer_workbenches/show.html.erb_spec.rb
index 138a1560d..2a2642911 100644
--- a/spec/views/offer_workbenches/show.html.erb_spec.rb
+++ b/spec/views/offer_workbenches/show.html.erb_spec.rb
@@ -22,7 +22,13 @@ describe "workbenches/show", :type => :view do
}
let!(:workbench){ assign :workbench, create(:workbench) }
let!(:same_organisation_referential){ create :workbench_referential, workbench: workbench, metadatas: [create(:referential_metadata, lines: lines)] }
- let!(:different_organisation_referential){ create :workbench_referential, metadatas: [create(:referential_metadata, lines: lines)] }
+ let!(:different_organisation_referential) do
+ create(
+ :workbench_referential,
+ workbench: create(:workbench, workgroup: workbench.workgroup),
+ metadatas: [create(:referential_metadata, lines: lines)]
+ )
+ end
let!(:referentials){
same_organisation_referential && different_organisation_referential
assign :wbench_refs, paginate_collection(Referential, ReferentialDecorator)
diff --git a/yarn.lock b/yarn.lock
index 3e19cecbc..e95ee9a63 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3462,6 +3462,10 @@ jest-docblock@^22.0.3:
dependencies:
detect-newline "^2.1.0"
+jest-environment-jsdom-global@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom-global/-/jest-environment-jsdom-global-1.0.2.tgz#b3449e016e0b13cb0779704e29a1377f927b38a3"
+
jest-environment-jsdom@^22.0.5:
version "22.0.5"
resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-22.0.5.tgz#7b479452e387aef5b4bf8b9fe03e8be77493f5ea"