aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--INSTALL.md14
-rw-r--r--app/assets/javascripts/es6_browserified/itineraries/form_helper.js62
-rw-r--r--app/assets/javascripts/es6_browserified/itineraries/index.js19
-rw-r--r--app/assets/javascripts/es6_browserified/itineraries/reducers/stopPoints.js2
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/actions/index.js36
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/ConfirmModal.js17
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/ErrorModal.js15
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/Metas.js24
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js18
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js11
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/TagsSelect2.js10
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/TimeTableDay.js3
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js19
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/containers/App.js11
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js6
-rw-r--r--app/models/referential.rb2
-rw-r--r--app/models/referential_suite.rb6
-rw-r--r--app/views/time_tables/edit.html.slim2
-rw-r--r--config/locales/actions.en.yml1
-rw-r--r--config/locales/actions.fr.yml1
-rw-r--r--config/locales/compliance_control_sets.en.yml24
-rw-r--r--config/locales/compliance_control_sets.fr.yml4
-rw-r--r--config/locales/time_tables.en.yml31
-rw-r--r--config/locales/time_tables.fr.yml31
-rw-r--r--db/migrate/20170922161352_create_referential_suites.rb10
-rw-r--r--db/migrate/20170922165315_add_referential_suite_to_referentials.rb8
-rw-r--r--db/schema.rb15
-rw-r--r--lib/model_attribute.rb5
-rw-r--r--spec/lib/model_attribute_spec.rb46
-rw-r--r--spec/models/referential_spec.rb1
-rw-r--r--spec/models/referential_suite_spec.rb5
31 files changed, 334 insertions, 125 deletions
diff --git a/INSTALL.md b/INSTALL.md
index 330230a40..82f9f5779 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -139,8 +139,22 @@ To create `Referential` objects with some data (`Route`, `JourneyPattern`, `Vehi
# Troubleshooting
+## Postgres
+
If Postgres complains about illegal type `hstore` in your tests that is probably because the shared extension is not installed, here is what to do:
bundle exec rake db:test:purge
Thanks to `lib/tasks/extensions.rake`.
+
+## macOS
+
+### Nokogiri
+
+http://www.nokogiri.org/tutorials/installing_nokogiri.html tells us that `xz` can cause troubles, here is what to do
+
+```
+brew unlink xz
+gem install nokogiri # or bundle install
+brew link xz
+```
diff --git a/app/assets/javascripts/es6_browserified/itineraries/form_helper.js b/app/assets/javascripts/es6_browserified/itineraries/form_helper.js
index 0baba27ef..f682e39c0 100644
--- a/app/assets/javascripts/es6_browserified/itineraries/form_helper.js
+++ b/app/assets/javascripts/es6_browserified/itineraries/form_helper.js
@@ -1,11 +1,55 @@
-const addInput = (name, value, index) => {
- let form = document.querySelector('form')
- let input = document.createElement('input')
- let formatedName = 'route[stop_points_attributes]['+ index.toString()+']['+name+']'
- input.setAttribute('type', 'hidden')
- input.setAttribute('name', formatedName)
- input.setAttribute('value', value)
- form.appendChild(input)
+const formHelper = {
+ addInput: (name, value, index) => {
+ let form = document.querySelector('form')
+ let input = document.createElement('input')
+ let formatedName = `route[stop_points_attributes][${index.toString()}][${name}]`
+ input.setAttribute('type', 'hidden')
+ input.setAttribute('name', formatedName)
+ input.setAttribute('value', value)
+ form.appendChild(input)
+ },
+ addError: (ids) => {
+ ids.forEach((id) => {
+ if (!$(id).parents('.form-group').hasClass('has-error')) {
+ $(id).parents('.form-group').addClass('has-error')
+ $(id).parent().append(`<span class='help-block small'>${'doit être rempli(e)'}</span>`)
+ }
+ })
+ },
+ cleanInputs: (ids) => {
+ ids.forEach((id) =>{
+ $(id).parents('.form-group').removeClass('has-error')
+ $(id).siblings('span').remove()
+ })
+ },
+ handleForm: (...ids) => {
+ let filledInputs = []
+ let blankInputs = []
+ ids.forEach(id => {
+ $(id).val() == "" ? blankInputs.push(id) : filledInputs.push(id)
+ })
+
+ if (filledInputs.length > 0) formHelper.cleanInputs(filledInputs)
+ if (blankInputs.length > 0) formHelper.addError(blankInputs)
+ },
+ handleStopPoints: (event, state) => {
+ if (state.stopPoints.length >= 2) {
+ state.stopPoints.map((stopPoint, i) => {
+ formHelper.addInput('id', stopPoint.stoppoint_id ? stopPoint.stoppoint_id : '', i)
+ formHelper.addInput('stop_area_id', stopPoint.stoparea_id, i)
+ formHelper.addInput('position', i, i)
+ formHelper.addInput('for_boarding', stopPoint.for_boarding, i)
+ formHelper.addInput('for_alighting', stopPoint.for_alighting, i)
+ })
+ if ($('.alert.alert-danger').length > 0) $('.alert.alert-danger').remove()
+ } else {
+ event.preventDefault()
+ let msg = "L'itinéraire doit comporter au moins deux arrêts"
+ if ($('.alert.alert-danger').length == 0) {
+ $('#stop_points').find('.subform').after(`<div class='alert alert-danger'><span class='fa fa-lg fa-exclamation-circle'></span><span>" ${msg} "</span></div>`)
+ }
+ }
+ }
}
-module.exports = addInput
+module.exports = formHelper \ No newline at end of file
diff --git a/app/assets/javascripts/es6_browserified/itineraries/index.js b/app/assets/javascripts/es6_browserified/itineraries/index.js
index ad32b9519..bb06126f7 100644
--- a/app/assets/javascripts/es6_browserified/itineraries/index.js
+++ b/app/assets/javascripts/es6_browserified/itineraries/index.js
@@ -4,7 +4,7 @@ var Provider = require('react-redux').Provider
var createStore = require('redux').createStore
var reducers = require('./reducers')
var App = require('./components/App')
-var addInput = require('./form_helper')
+var { handleForm, handleStopPoints } = require('./form_helper')
let datas = JSON.parse(decodeURIComponent(window.itinerary_stop))
// logger, DO NOT REMOVE
@@ -67,17 +67,12 @@ render(
document.querySelector('input[name=commit]').addEventListener('click', (event)=>{
let state = store.getState()
- if(state.stopPoints.length >= 2) {
- state.stopPoints.map((stopPoint, i) => {
- addInput('id', stopPoint.stoppoint_id ? stopPoint.stoppoint_id : '', i)
- addInput('stop_area_id',stopPoint.stoparea_id, i)
- addInput('position',i, i)
- addInput('for_boarding',stopPoint.for_boarding, i)
- addInput('for_alighting',stopPoint.for_alighting, i)
- })
- } else {
+ let name = $("#route_name").val()
+ let publicName = $("#route_published_name").val()
+ if (name == "" || publicName == "") {
event.preventDefault()
- let msg = "L'itinéraire doit comporter au moins deux arrêts"
- $('#stop_points').find('.subform').after("<div class='alert alert-danger'><span class='fa fa-lg fa-exclamation-circle'></span><span>" + msg + "</span></div>")
+ handleForm("#route_name", "#route_published_name")
}
+
+ handleStopPoints(event, state)
})
diff --git a/app/assets/javascripts/es6_browserified/itineraries/reducers/stopPoints.js b/app/assets/javascripts/es6_browserified/itineraries/reducers/stopPoints.js
index a3b8accb3..f3a26b8d7 100644
--- a/app/assets/javascripts/es6_browserified/itineraries/reducers/stopPoints.js
+++ b/app/assets/javascripts/es6_browserified/itineraries/reducers/stopPoints.js
@@ -1,5 +1,5 @@
var _ = require('lodash')
-var addInput = require('../form_helper')
+var { addInput } = require('../form_helper')
const stopPoint = (state = {}, action, length) => {
switch (action.type) {
diff --git a/app/assets/javascripts/es6_browserified/time_tables/actions/index.js b/app/assets/javascripts/es6_browserified/time_tables/actions/index.js
index ba5d91568..361e89c36 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/actions/index.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/actions/index.js
@@ -1,19 +1,20 @@
const _ = require('lodash')
+const { I18n } = window
const actions = {
+ weekDays: (index) => {
+ return _.range(1, 8).map(n => I18n.time_tables.edit.metas.days[n])
+ },
strToArrayDayTypes: (str) =>{
- let weekDays = ['Di', 'Lu', 'Ma', 'Me', 'Je', 'Ve', 'Sa']
- return weekDays.map((day, i) => str.indexOf(day) !== -1)
+ return actions.weekDays().map(day => str.indexOf(day) !== -1)
},
- arrayToStrDayTypes: (arr) => {
- let weekDays = ['Di', 'Lu', 'Ma', 'Me', 'Je', 'Ve', 'Sa']
- let str = []
- arr.map((dayActive, i) => {
- if(dayActive){
- str.push(weekDays[i])
- }
- })
- return str.join(',')
+ arrayToStrDayTypes: (dayTypes) => {
+ let newDayTypes = dayTypes.reduce((arr, dayActive, i) => {
+ if (dayActive) arr.push(actions.weekDays()[i])
+ return arr
+ }, [])
+
+ return newDayTypes.join(',')
},
fetchingApi: () =>({
type: 'FETCH_API'
@@ -149,8 +150,8 @@ const actions = {
type : 'CLOSE_MODAL'
}),
monthName(strDate) {
- let monthList = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"]
- var date = new Date(strDate)
+ let monthList = _.range(1,13).map(n => I18n.calendars.months[n])
+ let date = new Date(strDate)
return monthList[date.getMonth()]
},
getHumanDate(strDate, mLimit) {
@@ -219,7 +220,7 @@ const actions = {
let period = periods[i]
if (index !== i && !period.deleted) {
if (new Date(period.period_start) <= end && new Date(period.period_end) >= start) {
- error = 'Les périodes ne peuvent pas se chevaucher'
+ error = I18n.time_tables.edit.error_submit.periods_overlaps
break
}
}
@@ -233,7 +234,7 @@ const actions = {
for (let day of in_days) {
if (start <= new Date(day.date) && end >= new Date(day.date)) {
- error = 'Une période ne peut chevaucher une date dans un calendrier'
+ error = I18n.time_tables.edit.error_submit.dates_overlaps
break
}
}
@@ -241,7 +242,6 @@ const actions = {
},
fetchTimeTables: (dispatch, nextPage) => {
let urlJSON = window.location.pathname.split('/', 5).join('/')
- // console.log(nextPage)
if(nextPage) {
urlJSON += "/month.json?date=" + nextPage
}else{
@@ -310,9 +310,9 @@ const actions = {
errorModalMessage: (errorKey) => {
switch (errorKey) {
case "withoutPeriodsWithDaysTypes":
- return window.I18n.fr.time_tables.edit.error_modal.withoutPeriodsWithDaysTypes
+ return I18n.time_tables.edit.error_modal.withoutPeriodsWithDaysTypes
case "withPeriodsWithoutDayTypes":
- return window.I18n.fr.time_tables.edit.error_modal.withPeriodsWithoutDayTypes
+ return I18n.time_tables.edit.error_modal.withPeriodsWithoutDayTypes
default:
return errorKey
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/ConfirmModal.js b/app/assets/javascripts/es6_browserified/time_tables/components/ConfirmModal.js
index 40ae0eccf..674a03296 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/ConfirmModal.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/ConfirmModal.js
@@ -1,18 +1,17 @@
var React = require('react')
-var Component = require('react').Component
-var PropTypes = require('react').PropTypes
+var { PropTypes } = require('react')
-const ConfirmModal = ({dispatch, modal, onModalAccept, onModalCancel, timetable, metas}) => (
+const ConfirmModal = ({dispatch, modal, onModalAccept, onModalCancel, timetable, metas}, {I18n}) => (
<div className={ 'modal fade ' + ((modal.type == 'confirm') ? 'in' : '') } id='ConfirmModal'>
<div className='modal-container'>
<div className='modal-dialog'>
<div className='modal-content'>
<div className='modal-header'>
- <h4 className='modal-title'>Confirmation</h4>
+ <h4 className='modal-title'>{I18n.time_tables.edit.confirm_modal.title}</h4>
</div>
<div className='modal-body'>
<div className='mt-md mb-md'>
- <p>Vous vous apprêtez à changer de page. Voulez-vous valider vos modifications avant cela ?</p>
+ <p>{I18n.time_tables.edit.confirm_modal.message}</p>
</div>
</div>
<div className='modal-footer'>
@@ -22,7 +21,7 @@ const ConfirmModal = ({dispatch, modal, onModalAccept, onModalCancel, timetable,
type='button'
onClick= {() => {onModalCancel(modal.confirmModal.callback)}}
>
- Ne pas valider
+ {I18n.cancel}
</button>
<button
className='btn btn-primary'
@@ -30,7 +29,7 @@ const ConfirmModal = ({dispatch, modal, onModalAccept, onModalCancel, timetable,
type='button'
onClick = {() => {onModalAccept(modal.confirmModal.callback, timetable, metas)}}
>
- Valider
+ {I18n.actions.submit}
</button>
</div>
</div>
@@ -45,4 +44,8 @@ ConfirmModal.propTypes = {
onModalCancel: PropTypes.func.isRequired
}
+ConfirmModal.contextTypes = {
+ I18n: PropTypes.object
+}
+
module.exports = ConfirmModal
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/ErrorModal.js b/app/assets/javascripts/es6_browserified/time_tables/components/ErrorModal.js
index 4e8f7e363..2597a4870 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/ErrorModal.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/ErrorModal.js
@@ -1,15 +1,14 @@
var React = require('react')
-var Component = require('react').Component
-var PropTypes = require('react').PropTypes
-var errorModalMessage = require('../actions').errorModalMessage
+var { PropTypes } = require('react')
+var { errorModalMessage } = require('../actions')
-const ErrorModal = ({dispatch, modal, I18n, onModalClose}) => (
+const ErrorModal = ({dispatch, modal, onModalClose}, {I18n}) => (
<div className={ 'modal fade ' + ((modal.type == 'error') ? 'in' : '') } id='ErrorModal'>
<div className='modal-container'>
<div className='modal-dialog'>
<div className='modal-content'>
<div className='modal-header'>
- <h4 className='modal-title'>{window.I18n.fr.time_tables.edit.error_modal.title}</h4>
+ <h4 className='modal-title'>{I18n.time_tables.edit.error_modal.title}</h4>
</div>
<div className='modal-body'>
<div className='mt-md mb-md'>
@@ -23,7 +22,7 @@ const ErrorModal = ({dispatch, modal, I18n, onModalClose}) => (
type='button'
onClick= {() => {onModalClose()}}
>
- Retour
+ {I18n.back}
</button>
</div>
</div>
@@ -37,4 +36,8 @@ ErrorModal.propTypes = {
onModalClose: PropTypes.func.isRequired
}
+ErrorModal.contextTypes = {
+ I18n: PropTypes.object
+}
+
module.exports = ErrorModal
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/Metas.js b/app/assets/javascripts/es6_browserified/time_tables/components/Metas.js
index a0fac84f3..26a96e4a6 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/Metas.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/Metas.js
@@ -1,9 +1,9 @@
var React = require('react')
-var PropTypes = require('react').PropTypes
-let weekDays = ['D', 'L', 'Ma', 'Me', 'J', 'V', 'S']
+var { PropTypes } = require('react')
+const { weekDays } = require('../actions')
var TagsSelect2 = require('./TagsSelect2')
-const Metas = ({metas, onUpdateDayTypes, onUpdateComment, onUpdateColor, onSelect2Tags, onUnselect2Tags}) => {
+const Metas = ({metas, onUpdateDayTypes, onUpdateComment, onUpdateColor, onSelect2Tags, onUnselect2Tags}, {I18n}) => {
let colorList = ["", "#9B9B9B", "#FFA070", "#C67300", "#7F551B", "#41CCE3", "#09B09C", "#3655D7", "#6321A0", "#E796C6", "#DD2DAA"]
return (
<div className='form-horizontal'>
@@ -12,7 +12,7 @@ const Metas = ({metas, onUpdateDayTypes, onUpdateComment, onUpdateColor, onSelec
{/* comment (name) */}
<div className="form-group">
<label htmlFor="" className="control-label col-sm-4 required">
- Nom <abbr title="Champ requis">*</abbr>
+ {I18n.time_tables.edit.metas.name} <abbr title="">*</abbr>
</label>
<div className="col-sm-8">
<input
@@ -27,7 +27,7 @@ const Metas = ({metas, onUpdateDayTypes, onUpdateComment, onUpdateColor, onSelec
{/* color */}
<div className="form-group">
- <label htmlFor="" className="control-label col-sm-4">Couleur associée</label>
+ <label htmlFor="" className="control-label col-sm-4">{I18n.activerecord.attributes.time_table.color}</label>
<div className="col-sm-8">
<div className="dropdown color_selector">
<button
@@ -72,7 +72,7 @@ const Metas = ({metas, onUpdateDayTypes, onUpdateComment, onUpdateColor, onSelec
{/* tags */}
<div className="form-group">
- <label htmlFor="" className="control-label col-sm-4">Etiquettes</label>
+ <label htmlFor="" className="control-label col-sm-4">{I18n.activerecord.attributes.time_table.tag_list}</label>
<div className="col-sm-8">
<TagsSelect2
initialTags={metas.initial_tags}
@@ -85,16 +85,16 @@ const Metas = ({metas, onUpdateDayTypes, onUpdateComment, onUpdateColor, onSelec
{/* calendar */}
<div className="form-group">
- <label htmlFor="" className="control-label col-sm-4">Modèle de calendrier associé</label>
+ <label htmlFor="" className="control-label col-sm-4">{I18n.activerecord.attributes.time_table.calendar}</label>
<div className="col-sm-8">
- <span>{metas.calendar ? metas.calendar.name : 'Aucun'}</span>
+ <span>{metas.calendar ? metas.calendar.name : I18n.time_tables.edit.metas.no_calendar}</span>
</div>
</div>
{/* day_types */}
<div className="form-group">
<label htmlFor="" className="control-label col-sm-4">
- Journées d'applications pour les périodes ci-dessous
+ {I18n.time_tables.edit.metas.day_types}
</label>
<div className="col-sm-8">
<div className="form-group labelled-checkbox-group">
@@ -112,7 +112,7 @@ const Metas = ({metas, onUpdateDayTypes, onUpdateComment, onUpdateColor, onSelec
type="checkbox"
checked={day ? 'checked' : ''}
/>
- <span className='lcbx-group-item-label'>{weekDays[i]}</span>
+ <span className='lcbx-group-item-label'>{weekDays()[i]}</span>
</label>
</div>
</div>
@@ -135,4 +135,8 @@ Metas.propTypes = {
onUnselect2Tags: PropTypes.func.isRequired
}
+Metas.contextTypes = {
+ I18n: PropTypes.object
+}
+
module.exports = Metas
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js
index 3234a3fd7..d494109cc 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js
@@ -1,5 +1,5 @@
var React = require('react')
-var PropTypes = require('react').PropTypes
+var { PropTypes } = require('react')
var _ = require('lodash')
let monthsArray = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']
@@ -32,7 +32,7 @@ const makeYearsOptions = (yearSelected) => {
return arr
}
-const PeriodForm = ({modal, timetable, metas, onOpenAddPeriodForm, onClosePeriodForm, onUpdatePeriodForm, onValidatePeriodForm}) => (
+const PeriodForm = ({modal, timetable, metas, onOpenAddPeriodForm, onClosePeriodForm, onUpdatePeriodForm, onValidatePeriodForm}, {I18n}) => (
<div className="container-fluid">
<div className="row">
<div className="col lg-6 col-lg-offset-3">
@@ -44,7 +44,7 @@ const PeriodForm = ({modal, timetable, metas, onOpenAddPeriodForm, onClosePeriod
<div>
<div className="form-group">
<label htmlFor="" className="control-label required">
- Début de période
+ {I18n.time_tables.edit.period_form.begin}
<abbr title="requis">*</abbr>
</label>
</div>
@@ -52,7 +52,7 @@ const PeriodForm = ({modal, timetable, metas, onOpenAddPeriodForm, onClosePeriod
<div>
<div className="form-group">
<label htmlFor="" className="control-label required">
- Fin de période
+ {I18n.time_tables.edit.period_form.end}
<abbr title="requis">*</abbr>
</label>
</div>
@@ -103,14 +103,14 @@ const PeriodForm = ({modal, timetable, metas, onOpenAddPeriodForm, onClosePeriod
className='btn btn-link'
onClick={onClosePeriodForm}
>
- Annuler
+ {I18n.cancel}
</button>
<button
type='button'
className='btn btn-outline-primary mr-sm'
onClick={() => onValidatePeriodForm(modal.modalProps, timetable.time_table_periods, metas, _.filter(timetable.time_table_dates, ['in_out', true]))}
>
- Valider
+ {I18n.actions.submit}
</button>
</div>
</div>
@@ -122,7 +122,7 @@ const PeriodForm = ({modal, timetable, metas, onOpenAddPeriodForm, onClosePeriod
className='btn btn-outline-primary'
onClick={onOpenAddPeriodForm}
>
- Ajouter une période
+ {I18n.time_tables.actions.add_period}
</button>
</div>
}
@@ -142,4 +142,8 @@ PeriodForm.propTypes = {
timetable: PropTypes.object.isRequired
}
+PeriodForm.contextTypes = {
+ I18n: PropTypes.object
+}
+
module.exports = PeriodForm
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js
index cf4cbfb32..704e21331 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js
@@ -1,11 +1,10 @@
var React = require('react')
-var Component = require('react').Component
-var PropTypes = require('react').PropTypes
+var { Component, PropTypes } = require('react')
var actions = require('../actions')
class PeriodManager extends Component {
- constructor(props) {
- super(props)
+ constructor(props, context) {
+ super(props, context)
}
toEndPeriod(curr, end) {
@@ -82,4 +81,8 @@ PeriodManager.propTypes = {
onOpenEditPeriodForm: PropTypes.func.isRequired
}
+PeriodManager.contextTypes = {
+ I18n: PropTypes.object
+}
+
module.exports = PeriodManager
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/TagsSelect2.js b/app/assets/javascripts/es6_browserified/time_tables/components/TagsSelect2.js
index a1f41a693..46188cdd1 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/TagsSelect2.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/TagsSelect2.js
@@ -9,8 +9,8 @@ var path = window.location.pathname.split('/', 4).join('/')
var _ = require('lodash')
class TagsSelect2 extends React.Component{
- constructor(props) {
- super(props)
+ constructor(props, context) {
+ super(props, context)
}
mapKeys(array){
@@ -38,7 +38,7 @@ class TagsSelect2 extends React.Component{
allowClear: true,
theme: 'bootstrap',
width: '100%',
- placeholder: 'Ajoutez ou cherchez une étiquette...',
+ placeholder: this.context.I18n.time_tables.edit.select2.tag.placeholder,
ajax: {
url: origin + path + '/tags.json',
dataType: 'json',
@@ -74,4 +74,8 @@ const formatRepo = (props) => {
if(props.name) return props.name
}
+TagsSelect2.contextTypes = {
+ I18n: PropTypes.object
+}
+
module.exports = TagsSelect2
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/TimeTableDay.js b/app/assets/javascripts/es6_browserified/time_tables/components/TimeTableDay.js
index 71621c874..93a0a90fe 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/TimeTableDay.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/TimeTableDay.js
@@ -1,6 +1,5 @@
var React = require('react')
-var Component = require('react').Component
-var PropTypes = require('react').PropTypes
+var { Component, PropTypes } = require('react')
class TimeTableDay extends Component {
constructor(props) {
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js b/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js
index a613549c3..22e971c6b 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js
@@ -1,14 +1,13 @@
var React = require('react')
-var Component = require('react').Component
-var PropTypes = require('react').PropTypes
+var { Component, PropTypes} = require('react')
var TimeTableDay = require('./TimeTableDay')
var PeriodsInDay = require('./PeriodsInDay')
var ExceptionsInDay = require('./ExceptionsInDay')
var actions = require('../actions')
class Timetable extends Component{
- constructor(props){
- super(props)
+ constructor(props, context){
+ super(props, context)
}
currentDate(mFirstday, day) {
@@ -31,11 +30,11 @@ class Timetable extends Component{
<div className="table table-2entries mb-sm">
<div className="t2e-head w20">
<div className="th">
- <div className="strong">Synthèse</div>
+ <div className="strong">{this.context.I18n.time_tables.synthesis}</div>
</div>
- <div className="td"><span>Journées d'application</span></div>
- <div className="td"><span>Périodes</span></div>
- <div className="td"><span>Exceptions</span></div>
+ <div className="td"><span>{this.context.I18n.time_tables.edit.day_types}</span></div>
+ <div className="td"><span>{this.context.I18n.time_tables.edit.periods}</span></div>
+ <div className="td"><span>{this.context.I18n.time_tables.edit.exceptions}</span></div>
</div>
<div className="t2e-item-list w80">
<div>
@@ -111,4 +110,8 @@ Timetable.propTypes = {
onIncludeDateInPeriod: PropTypes.func.isRequired
}
+Timetable.contextTypes = {
+ I18n: PropTypes.object
+}
+
module.exports = Timetable
diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/App.js b/app/assets/javascripts/es6_browserified/time_tables/containers/App.js
index 02f0ddbd8..772747104 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/containers/App.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/containers/App.js
@@ -1,6 +1,6 @@
var React = require('react')
var connect = require('react-redux').connect
-var Component = require('react').Component
+var { Component, PropTypes} = require('react')
var actions = require('../actions')
var Metas = require('./Metas')
var Timetable = require('./Timetable')
@@ -9,12 +9,17 @@ var PeriodForm = require('./PeriodForm')
var SaveTimetable = require('./SaveTimetable')
var ConfirmModal = require('./ConfirmModal')
var ErrorModal = require('./ErrorModal')
+const { I18n } = window
class App extends Component {
componentDidMount(){
this.props.onLoadFirstPage()
}
+ getChildContext() {
+ return { I18n }
+ }
+
render(){
return(
<div className='row'>
@@ -41,6 +46,10 @@ const mapDispatchToProps = (dispatch) => {
}
}
+App.childContextTypes = {
+ I18n: PropTypes.object
+}
+
const timeTableApp = connect(null, mapDispatchToProps)(App)
module.exports = timeTableApp
diff --git a/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js b/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js
index edb965065..712808abd 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js
@@ -96,9 +96,9 @@ const timetable = (state = {}, action) => {
let newPeriods = JSON.parse(JSON.stringify(action.timeTablePeriods))
if (action.modalProps.index !== false){
- updatePeriod = newPeriods[action.modalProps.index]
- updatePeriod.period_start = period_start
- updatePeriod.period_end = period_end
+ let updatedPeriod = newPeriods[action.modalProps.index]
+ updatedPeriod.period_start = period_start
+ updatedPeriod.period_end = period_end
newDates = _.reject(state.time_table_dates, d => actions.isInPeriod(newPeriods, d.date) && !d.in_out)
}else{
let newPeriod = {
diff --git a/app/models/referential.rb b/app/models/referential.rb
index af08aa868..c7b52ddf8 100644
--- a/app/models/referential.rb
+++ b/app/models/referential.rb
@@ -45,6 +45,8 @@ class Referential < ActiveRecord::Base
has_many :stop_areas, through: :stop_area_referential
belongs_to :workbench
+ belongs_to :referential_suite
+
scope :ready, -> { where(ready: true) }
scope :in_periode, ->(periode) { where(id: referential_ids_in_periode(periode)) }
scope :include_metadatas_lines, ->(line_ids) { where('referential_metadata.line_ids && ARRAY[?]::bigint[]', line_ids) }
diff --git a/app/models/referential_suite.rb b/app/models/referential_suite.rb
new file mode 100644
index 000000000..9fd25ef3f
--- /dev/null
+++ b/app/models/referential_suite.rb
@@ -0,0 +1,6 @@
+class ReferentialSuite < ActiveRecord::Base
+ belongs_to :new, class_name: 'Referential'
+ belongs_to :current, class_name: 'Referential'
+
+ has_many :referentials
+end
diff --git a/app/views/time_tables/edit.html.slim b/app/views/time_tables/edit.html.slim
index ed55dc4e3..cc6f31489 100644
--- a/app/views/time_tables/edit.html.slim
+++ b/app/views/time_tables/edit.html.slim
@@ -11,6 +11,6 @@
= javascript_tag do
| window.actionType = "#{raw params[:action]}";
- | window.I18n = #{(I18n.backend.send(:translations).to_json).html_safe};
+ | window.I18n = #{(I18n.backend.send(:translations)[I18n.locale].to_json).html_safe};
= javascript_include_tag 'es6_browserified/time_tables/index.js'
diff --git a/config/locales/actions.en.yml b/config/locales/actions.en.yml
index 8dea51ca3..44e55067d 100644
--- a/config/locales/actions.en.yml
+++ b/config/locales/actions.en.yml
@@ -22,6 +22,7 @@ en:
create_api_key: "Create an API key"
or: "or"
cancel: "Cancel"
+ back: "Go Back"
search_hint: "Type in a search term"
no_result_text: "No Results"
searching_term: "Searching..."
diff --git a/config/locales/actions.fr.yml b/config/locales/actions.fr.yml
index 01fc06326..ee35fbb31 100644
--- a/config/locales/actions.fr.yml
+++ b/config/locales/actions.fr.yml
@@ -22,6 +22,7 @@ fr:
create_api_key: "Créer une clé d'API"
or: "ou"
cancel: "Annuler"
+ back: "Retour"
search_hint: "Entrez un texte à rechercher"
no_result_text: "Aucun résultat"
searching_term: "Recherche en cours..."
diff --git a/config/locales/compliance_control_sets.en.yml b/config/locales/compliance_control_sets.en.yml
new file mode 100644
index 000000000..497ca50c3
--- /dev/null
+++ b/config/locales/compliance_control_sets.en.yml
@@ -0,0 +1,24 @@
+fr:
+ compliance_control_sets:
+ index:
+ title: Control games
+ new: Creating a control set
+ edit: Editing a Control Game
+ actions:
+ new: Add
+ edit: Edit
+ destroy: Delete
+ destroy_confirm: Are you sure to remove the control games ?
+ filters:
+ name: Specify a control game name...
+ search_no_results: No control game matches your search
+ activerecord:
+ models:
+ compliance_control_set: Calendar
+ attributes:
+ compliance_control_set:
+ name: Name
+ assignment: Affectation
+ owner_jdc: Owner of the control game
+ control_numbers: Nb contrôle
+ updated_at: Update \ No newline at end of file
diff --git a/config/locales/compliance_control_sets.fr.yml b/config/locales/compliance_control_sets.fr.yml
index fedfeede7..f5bb7c67b 100644
--- a/config/locales/compliance_control_sets.fr.yml
+++ b/config/locales/compliance_control_sets.fr.yml
@@ -10,8 +10,8 @@ fr:
destroy: Supprimer
destroy_confirm: Etes vous sûr de supprimer ce jeux de contrôle ?
filters:
- name: 'Indiquez un nom de jeux de contrôle...'
- search_no_results: 'Aucun jeu de contrôle ne correspond à votre recherche'
+ name: Indiquez un nom de jeux de contrôle...
+ search_no_results: Aucun jeu de contrôle ne correspond à votre recherche
activerecord:
models:
compliance_control_set: Calendrier
diff --git a/config/locales/time_tables.en.yml b/config/locales/time_tables.en.yml
index d67e30edb..e68836f99 100644
--- a/config/locales/time_tables.en.yml
+++ b/config/locales/time_tables.en.yml
@@ -29,10 +29,39 @@ en:
title: "Duplicate timetable"
edit:
title: "Update timetable %{time_table}"
+ day_types: Day types
+ periods: Periods
+ exceptions: Exceptions
+ synthesis: Synthesis
error_modal:
title: "Error"
withoutPeriodsWithDaysTypes: "A timetable can't have day type(s) without period(s)."
- withPeriodsWithoutDayTypes: "A tiemetable can't have period(s) swithout day type(s)."
+ withPeriodsWithoutDayTypes: "A tiemetable can't have period(s) swithout day type(s)."
+ error_submit:
+ periods_overlaps: "Periods cannot overlap in a timetable"
+ dates_overlaps: "A period cannot overlap a date in a timetable"
+ confirm_modal:
+ title: "Confirm"
+ message: "You are about to change pages. Do you want to validate your changes before this?"
+ metas:
+ name: Name
+ calendar: Associated calendar
+ no_calendar: None
+ day_types: Periods day tpes
+ days:
+ 1: Su
+ 2: Mo
+ 3: Tu
+ 4: We
+ 5: Th
+ 6: Fr
+ 7: Sa
+ select2:
+ tag:
+ placeholder: Add or search a tag...
+ period_form:
+ begin: Period start
+ end: Period end
show:
title: "Timetable %{time_table}"
dates: "Application dates"
diff --git a/config/locales/time_tables.fr.yml b/config/locales/time_tables.fr.yml
index 06d1d59e8..b85f7ca33 100644
--- a/config/locales/time_tables.fr.yml
+++ b/config/locales/time_tables.fr.yml
@@ -29,10 +29,39 @@ fr:
title: "Dupliquer un calendrier"
edit:
title: "Editer le calendrier %{time_table}"
+ day_types: Journées d'application
+ periods: Périodes
+ exceptions: Exceptions
+ synthesis: Synthèse
error_modal:
title: "Erreur"
withoutPeriodsWithDaysTypes: "Un calendrier d'application ne peut pas avoir de journée(s) d'application sans période(s)."
- withPeriodsWithoutDayTypes: "Un calendrier d'application ne peut pas avoir de période(s) sans journée(s) d'application."
+ withPeriodsWithoutDayTypes: "Un calendrier d'application ne peut pas avoir de période(s) sans journée(s) d'application."
+ error_submit:
+ periods_overlaps: "Les périodes ne peuvent pas se chevaucher"
+ dates_overlaps: "Une période ne peut chevaucher une date dans un calendrier"
+ confirm_modal:
+ title: "Confirmation"
+ message: "Vous vous apprêtez à changer de page. Voulez-vous valider vos modifications avant cela ?"
+ metas:
+ name: Nom
+ calendar: Modèle de calendrier associée
+ no_calendar: Aucun
+ day_types: Journées d'applications pour les périodes ci-dessous
+ days:
+ 1: Di
+ 2: Lu
+ 3: Ma
+ 4: Me
+ 5: Je
+ 6: Ve
+ 7: Sa
+ select2:
+ tag:
+ placeholder: Ajoutez ou cherchez une étiquette...
+ period_form:
+ begin: Début de période
+ end: Fin de période
show:
title: Calendrier %{time_table}
dates: "Dates d'application"
diff --git a/db/migrate/20170922161352_create_referential_suites.rb b/db/migrate/20170922161352_create_referential_suites.rb
new file mode 100644
index 000000000..5a8693d01
--- /dev/null
+++ b/db/migrate/20170922161352_create_referential_suites.rb
@@ -0,0 +1,10 @@
+class CreateReferentialSuites < ActiveRecord::Migration
+ def change
+ create_table :referential_suites do |t|
+ t.bigint :new_id, index: true
+ t.bigint :current_id, index: true
+
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/migrate/20170922165315_add_referential_suite_to_referentials.rb b/db/migrate/20170922165315_add_referential_suite_to_referentials.rb
new file mode 100644
index 000000000..a01ba4d40
--- /dev/null
+++ b/db/migrate/20170922165315_add_referential_suite_to_referentials.rb
@@ -0,0 +1,8 @@
+class AddReferentialSuiteToReferentials < ActiveRecord::Migration
+ def change
+ add_reference :referentials, :referential_suite,
+ index: true,
+ foreign_key: true,
+ type: :bigint
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 2b62fa7f1..89f002aee 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: 20170918103913) do
+ActiveRecord::Schema.define(version: 20170922165315) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -602,6 +602,16 @@ ActiveRecord::Schema.define(version: 20170918103913) do
add_index "referential_metadata", ["referential_id"], name: "index_referential_metadata_on_referential_id", using: :btree
add_index "referential_metadata", ["referential_source_id"], name: "index_referential_metadata_on_referential_source_id", using: :btree
+ create_table "referential_suites", id: :bigserial, force: :cascade do |t|
+ t.integer "new_id", limit: 8
+ t.integer "current_id", limit: 8
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+ add_index "referential_suites", ["current_id"], name: "index_referential_suites_on_current_id", using: :btree
+ add_index "referential_suites", ["new_id"], name: "index_referential_suites_on_new_id", using: :btree
+
create_table "referentials", id: :bigserial, force: :cascade do |t|
t.string "name"
t.string "slug"
@@ -622,9 +632,11 @@ ActiveRecord::Schema.define(version: 20170918103913) do
t.datetime "archived_at"
t.integer "created_from_id", limit: 8
t.boolean "ready", default: false
+ t.integer "referential_suite_id", limit: 8
end
add_index "referentials", ["created_from_id"], name: "index_referentials_on_created_from_id", using: :btree
+ add_index "referentials", ["referential_suite_id"], name: "index_referentials_on_referential_suite_id", using: :btree
create_table "route_sections", id: :bigserial, force: :cascade do |t|
t.integer "departure_id", limit: 8
@@ -987,6 +999,7 @@ ActiveRecord::Schema.define(version: 20170918103913) do
add_foreign_key "journey_patterns", "stop_points", column: "departure_stop_point_id", name: "departure_point_fkey", on_delete: :nullify
add_foreign_key "journey_patterns_stop_points", "journey_patterns", name: "jpsp_jp_fkey", on_delete: :cascade
add_foreign_key "journey_patterns_stop_points", "stop_points", name: "jpsp_stoppoint_fkey", on_delete: :cascade
+ add_foreign_key "referentials", "referential_suites"
add_foreign_key "route_sections", "stop_areas", column: "arrival_id"
add_foreign_key "route_sections", "stop_areas", column: "departure_id"
add_foreign_key "routes", "routes", column: "opposite_route_id", name: "route_opposite_route_fkey"
diff --git a/lib/model_attribute.rb b/lib/model_attribute.rb
index 60580e306..4d246853a 100644
--- a/lib/model_attribute.rb
+++ b/lib/model_attribute.rb
@@ -12,9 +12,9 @@ class ModelAttribute
def self.classes
all
.map(&:klass)
+ .uniq
.map(&:to_s)
.map(&:camelize)
- .uniq
end
def self.group_by_class
@@ -93,7 +93,8 @@ class ModelAttribute
end
def ==(other)
- klass == other.klass &&
+ self.class === other &&
+ klass == other.klass &&
name == other.name &&
data_type == other.data_type
end
diff --git a/spec/lib/model_attribute_spec.rb b/spec/lib/model_attribute_spec.rb
index 427e01490..cdba87a90 100644
--- a/spec/lib/model_attribute_spec.rb
+++ b/spec/lib/model_attribute_spec.rb
@@ -1,4 +1,8 @@
RSpec.describe ModelAttribute do
+ before(:each) do
+ ModelAttribute.instance_variable_set(:@__all__, [])
+ end
+
describe ".define" do
it "adds a new instance of ModelAttribute to .all" do
expect do
@@ -16,11 +20,9 @@ RSpec.describe ModelAttribute do
describe ".classes" do
it "returns the list of classes of ModelAttributes in .all" do
- ModelAttribute.instance_variable_set(:@__all__, [
- ModelAttribute.new(:route, :name, :string),
- ModelAttribute.new(:journey_pattern, :name, :string),
- ModelAttribute.new(:time_table, :start_date, :date)
- ])
+ ModelAttribute.define(:route, :name, :string)
+ ModelAttribute.define(:journey_pattern, :name, :string)
+ ModelAttribute.define(:time_table, :start_date, :date)
expect(ModelAttribute.classes).to match_array([
'Route',
@@ -32,9 +34,7 @@ RSpec.describe ModelAttribute do
describe ".from_code" do
it "returns a ModelAttribute from a given code" do
- ModelAttribute.instance_variable_set(:@__all__, [
- ModelAttribute.new(:journey_pattern, :name, :string)
- ])
+ ModelAttribute.define(:journey_pattern, :name, :string)
expect(ModelAttribute.from_code('journey_pattern#name')).to eq(
ModelAttribute.new(:journey_pattern, :name, :string)
@@ -44,12 +44,10 @@ RSpec.describe ModelAttribute do
describe ".group_by_class" do
it "returns all ModelAttributes grouped by klass" do
- ModelAttribute.instance_variable_set(:@__all__, [
- ModelAttribute.new(:route, :name, :string),
- ModelAttribute.new(:route, :published_name, :string),
- ModelAttribute.new(:journey_pattern, :name, :string),
- ModelAttribute.new(:vehicle_journey, :number, :integer)
- ])
+ ModelAttribute.define(:route, :name, :string)
+ ModelAttribute.define(:route, :published_name, :string)
+ ModelAttribute.define(:journey_pattern, :name, :string)
+ ModelAttribute.define(:vehicle_journey, :number, :integer)
expect(ModelAttribute.group_by_class).to eq({
route: [
@@ -68,12 +66,10 @@ RSpec.describe ModelAttribute do
describe ".methods_by_class" do
it "returns all ModelAttributes for a given class" do
- ModelAttribute.instance_variable_set(:@__all__, [
- ModelAttribute.new(:route, :name, :string),
- ModelAttribute.new(:route, :published_name, :string),
- ModelAttribute.new(:route, :direction, :string),
- ModelAttribute.new(:journey_pattern, :name, :string)
- ])
+ ModelAttribute.define(:route, :name, :string)
+ ModelAttribute.define(:route, :published_name, :string)
+ ModelAttribute.define(:route, :direction, :string)
+ ModelAttribute.define(:journey_pattern, :name, :string)
expect(ModelAttribute.methods_by_class(:route)).to match_array([
ModelAttribute.new(:route, :name, :string),
@@ -85,12 +81,10 @@ RSpec.describe ModelAttribute do
describe ".methods_by_class_and_type" do
it "returns ModelAttributes of a certain class and type" do
- ModelAttribute.instance_variable_set(:@__all__, [
- ModelAttribute.new(:route, :name, :string),
- ModelAttribute.new(:route, :checked_at, :date),
- ModelAttribute.new(:journey_pattern, :name, :string),
- ModelAttribute.new(:journey_pattern, :section_status, :integer)
- ])
+ ModelAttribute.define(:route, :name, :string)
+ ModelAttribute.define(:route, :checked_at, :date)
+ ModelAttribute.define(:journey_pattern, :name, :string)
+ ModelAttribute.define(:journey_pattern, :section_status, :integer)
expect(ModelAttribute.methods_by_class_and_type(:route, :string)).to match_array([
ModelAttribute.new(:route, :name, :string)
diff --git a/spec/models/referential_spec.rb b/spec/models/referential_spec.rb
index f9ace08cc..bb8fabb2e 100644
--- a/spec/models/referential_spec.rb
+++ b/spec/models/referential_spec.rb
@@ -10,6 +10,7 @@ describe Referential, :type => :model do
it { should have_many(:metadatas) }
it { should belong_to(:workbench) }
+ it { should belong_to(:referential_suite) }
context ".referential_ids_in_periode" do
it 'should retrieve referential id in periode range' do
diff --git a/spec/models/referential_suite_spec.rb b/spec/models/referential_suite_spec.rb
new file mode 100644
index 000000000..771187b55
--- /dev/null
+++ b/spec/models/referential_suite_spec.rb
@@ -0,0 +1,5 @@
+RSpec.describe ReferentialSuite, type: :model do
+ it { should belong_to(:new).class_name('Referential') }
+ it { should belong_to(:current).class_name('Referential') }
+ it { should have_many(:referentials) }
+end