aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXinhui2017-05-23 10:03:52 +0200
committerXinhui2017-05-23 10:03:52 +0200
commit4f5cc7d35777f3b4bfa1c63c1223c679f713424e (patch)
tree8c3fa28f8f1f4b238248037dce4a6c5974a82e02
parentaf2c4b003ca0bf856a1f1d532865963b40f159ee (diff)
parent5e3c2d8daba5617a72d0bfd06e0b6b3f03628f56 (diff)
downloadchouette-core-4f5cc7d35777f3b4bfa1c63c1223c679f713424e.tar.bz2
Merge branch 'master' into staging
-rw-r--r--app/assets/javascripts/es6_browserified/itineraries/show.js99
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/actions/index.js22
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js18
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/Metas.js2
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js2
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/TimeTableDay.js2
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js4
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/containers/Metas.js7
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/reducers/metas.js4
-rw-r--r--app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js2
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js16
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/Filters.js44
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/Tools.js4
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js11
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js1
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js (renamed from app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CalendarsEditVehicleJourney.js)10
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js1
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js15
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js1
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/VJSelect2.js68
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/fr.js9
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Filters.js6
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/TimetablesEditVehicleJourney.js (renamed from app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/CalendarsEditVehicleJourney.js)10
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/index.js21
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/filters.js17
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js11
-rw-r--r--app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js19
-rw-r--r--app/assets/javascripts/select2.coffee47
-rw-r--r--app/assets/javascripts/time_table_combinations.coffee6
-rw-r--r--app/assets/stylesheets/OpenLayers/custom.sass63
-rw-r--r--app/assets/stylesheets/OpenLayers/ol.css227
-rw-r--r--app/assets/stylesheets/application.sass2
-rw-r--r--app/assets/stylesheets/base.sass3
-rw-r--r--app/assets/stylesheets/components/_buttons.sass7
-rw-r--r--app/assets/stylesheets/components/_forms.sass2
-rw-r--r--app/assets/stylesheets/components/_olMap.sass27
-rw-r--r--app/assets/stylesheets/components/_select2.sass13
-rw-r--r--app/assets/stylesheets/components/_tables.sass14
-rw-r--r--app/assets/stylesheets/modules/_routes_stopoints.sass4
-rw-r--r--app/assets/stylesheets/modules/_vj_collection.sass7
-rw-r--r--app/controllers/autocomplete_calendars_controller.rb7
-rw-r--r--app/controllers/time_table_combinations_controller.rb50
-rw-r--r--app/controllers/time_tables_controller.rb26
-rw-r--r--app/controllers/vehicle_journeys_controller.rb80
-rw-r--r--app/helpers/newapplication_helper.rb2
-rw-r--r--app/models/calendar.rb11
-rw-r--r--app/models/chouette/time_table.rb17
-rw-r--r--app/models/chouette/vehicle_journey.rb50
-rw-r--r--app/models/time_table_combination.rb43
-rw-r--r--app/policies/time_table_policy.rb4
-rw-r--r--app/views/access_link_pairs/_access_link_pair.html.slim1
-rw-r--r--app/views/autocomplete_calendars/autocomplete.rabl5
-rw-r--r--app/views/autocomplete_time_tables/index.rabl9
-rw-r--r--app/views/group_of_lines/_group_of_line.html.slim10
-rw-r--r--app/views/referential_lines/_filters.html.slim16
-rw-r--r--app/views/referential_lines/show.html.slim8
-rw-r--r--app/views/routes/show.html.slim13
-rw-r--r--app/views/time_table_combinations/_combine.html.slim12
-rw-r--r--app/views/time_table_combinations/_combine_form.html.slim11
-rw-r--r--app/views/time_table_combinations/_form.html.slim22
-rw-r--r--app/views/time_table_combinations/create_failure.js.slim3
-rw-r--r--app/views/time_table_combinations/create_success.js.slim6
-rw-r--r--app/views/time_table_combinations/new.html.slim12
-rw-r--r--app/views/time_table_combinations/new.js.slim2
-rw-r--r--app/views/time_tables/_filter.html.slim11
-rw-r--r--app/views/time_tables/show.html.slim13
-rw-r--r--app/views/time_tables/show.rabl3
-rw-r--r--app/views/vehicle_journeys/show.rabl2
-rw-r--r--config/locales/actions.en.yml1
-rw-r--r--config/locales/actions.fr.yml1
-rw-r--r--config/locales/time_table_combinations.en.yml5
-rw-r--r--config/locales/time_table_combinations.fr.yml13
-rw-r--r--config/locales/time_tables.en.yml2
-rw-r--r--config/locales/time_tables.fr.yml4
-rw-r--r--config/routes.rb6
-rw-r--r--spec/controllers/autocomplete_calendars_controller_spec.rb5
-rw-r--r--spec/factories/chouette_vehicle_journey.rb11
-rw-r--r--spec/features/calendars_permissions_spec.rb55
-rw-r--r--spec/features/group_of_lines_permissions_spec.rb43
-rw-r--r--spec/features/group_of_lines_spec.rb2
-rw-r--r--spec/features/line_footnotes_permissions_spec.rb40
-rw-r--r--spec/features/line_footnotes_spec.rb14
-rw-r--r--spec/features/lines_permissions_spec.rb66
-rw-r--r--spec/features/referential_lines_permissions_spec.rb44
-rw-r--r--spec/features/routes_permissions_spec.rb42
-rw-r--r--spec/features/routes_spec.rb13
-rw-r--r--spec/features/time_tables_permissions_spec.rb38
-rw-r--r--spec/features/workbenches_permissions_spec.rb42
-rw-r--r--spec/features/workbenches_spec.rb1
-rw-r--r--spec/javascripts/time_table/actions_spec.js5
-rw-r--r--spec/javascripts/time_table/reducers/metas_spec.js4
-rw-r--r--spec/javascripts/vehicle_journeys/actions_spec.js8
-rw-r--r--spec/javascripts/vehicle_journeys/reducers/filters_spec.js13
-rw-r--r--spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js11
-rw-r--r--spec/models/calendar_spec.rb16
-rw-r--r--spec/models/chouette/time_table_spec.rb67
-rw-r--r--spec/models/chouette/vehicle_journey_spec.rb80
-rw-r--r--spec/models/time_table_combination_spec.rb49
-rw-r--r--spec/policies/application_policy_spec.rb19
-rw-r--r--spec/policies/company_policy_spec.rb4
-rw-r--r--spec/policies/group_of_line_policy_spec.rb4
-rw-r--r--spec/policies/line_policy_spec.rb4
-rw-r--r--spec/policies/network_policy_spec.rb4
-rw-r--r--spec/policies/referential_policy_spec.rb4
-rw-r--r--spec/policies/stop_area_policy_spec.rb4
-rw-r--r--spec/policies/time_table_policy_spec.rb26
-rw-r--r--spec/spec_helper.rb20
-rw-r--r--spec/support/helpers.rb4
-rw-r--r--spec/support/helpers/session_helpers.rb3
-rw-r--r--spec/support/pundit.rb31
-rw-r--r--spec/support/subject.rb11
111 files changed, 1705 insertions, 431 deletions
diff --git a/app/assets/javascripts/es6_browserified/itineraries/show.js b/app/assets/javascripts/es6_browserified/itineraries/show.js
new file mode 100644
index 000000000..79a11701f
--- /dev/null
+++ b/app/assets/javascripts/es6_browserified/itineraries/show.js
@@ -0,0 +1,99 @@
+route = JSON.parse(decodeURIComponent(route))
+const geoColPts = []
+const geoColLns= []
+const geoColEdges = [
+ new ol.Feature({
+ geometry: new ol.geom.Point(ol.proj.fromLonLat([parseFloat(route[0].longitude), parseFloat(route[0].latitude)]))
+ }),
+ new ol.Feature({
+ geometry: new ol.geom.Point(ol.proj.fromLonLat([parseFloat(route[route.length - 1].longitude), parseFloat(route[route.length - 1].latitude)]))
+ })
+]
+route.forEach(function(stop, i){
+ if (i < route.length - 1){
+ geoColLns.push(new ol.Feature({
+ geometry: new ol.geom.LineString([
+ ol.proj.fromLonLat([parseFloat(route[i].longitude), parseFloat(route[i].latitude)]),
+ ol.proj.fromLonLat([parseFloat(route[i+1].longitude), parseFloat(route[i+1].latitude)])
+ ])
+ }))
+ }
+ geoColPts.push(new ol.Feature({
+ geometry: new ol.geom.Point(ol.proj.fromLonLat([parseFloat(stop.longitude), parseFloat(stop.latitude)]))
+ })
+ )
+})
+var edgeStyles = new ol.style.Style({
+ image: new ol.style.Circle(({
+ radius: 5,
+ stroke: new ol.style.Stroke({
+ color: '#007fbb',
+ width: 2
+ }),
+ fill: new ol.style.Fill({
+ color: '#007fbb',
+ width: 2
+ })
+ }))
+})
+var defaultStyles = new ol.style.Style({
+ image: new ol.style.Circle(({
+ radius: 4,
+ stroke: new ol.style.Stroke({
+ color: '#007fbb',
+ width: 2
+ }),
+ fill: new ol.style.Fill({
+ color: '#ffffff',
+ width: 2
+ })
+ }))
+})
+var lineStyle = new ol.style.Style({
+ stroke: new ol.style.Stroke({
+ color: '#007fbb',
+ width: 3
+ })
+})
+
+var vectorPtsLayer = new ol.layer.Vector({
+ source: new ol.source.Vector({
+ features: geoColPts
+ }),
+ style: defaultStyles,
+ zIndex: 2
+})
+var vectorEdgesLayer = new ol.layer.Vector({
+ source: new ol.source.Vector({
+ features: geoColEdges
+ }),
+ style: edgeStyles,
+ zIndex: 3
+})
+var vectorLnsLayer = new ol.layer.Vector({
+ source: new ol.source.Vector({
+ features: geoColLns
+ }),
+ style: [lineStyle],
+ zIndex: 1
+})
+
+var map = new ol.Map({
+ target: 'route_map',
+ layers: [
+ new ol.layer.Tile({
+ source: new ol.source.OSM()
+ }),
+ vectorPtsLayer,
+ vectorEdgesLayer,
+ vectorLnsLayer
+ ],
+ controls: [ new ol.control.ScaleLine(), new ol.control.Zoom(), new ol.control.ZoomSlider() ],
+ interactions: ol.interaction.defaults({
+ zoom: true
+ }),
+ view: new ol.View({
+ center: ol.proj.fromLonLat([parseFloat(route[0].longitude), parseFloat(route[0].latitude)]),
+ zoom: 13
+ })
+});
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 3f15b7f01..41d247b21 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/actions/index.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/actions/index.js
@@ -50,9 +50,13 @@ const actions = {
dispatch,
page: val
}),
- updateDayTypes: (index) => ({
+ updateDayTypes: (dayTypes) => ({
type: 'UPDATE_DAY_TYPES',
- index
+ dayTypes
+ }),
+ updateCurrentMonthFromDaytypes: (dayTypes) => ({
+ type: 'UPDATE_CURRENT_MONTH_FROM_DAYTYPES',
+ dayTypes
}),
updateComment: (comment) => ({
type: 'UPDATE_COMMENT',
@@ -162,11 +166,8 @@ const actions = {
if(testDate === false){
if(currentDate >= begin && currentDate <= end) {
- if(daytypes[d.wday] === false) {
- testDate = false
- } else {
- testDate = true
- }
+ testDate = true
+ p.include_date = false
}
}
})
@@ -174,8 +175,11 @@ const actions = {
}
let improvedCM = state.current_month.map((d, i) => {
+ let bool = isInPeriod(state.current_month[i])
return _.assign({}, state.current_month[i], {
- in_periods: isInPeriod(state.current_month[i])
+ in_periods: bool,
+ include_date: bool ? false : state.current_month[i].include_date,
+ excluded_date: !bool ? false : state.current_month[i].excluded_date
})
})
return improvedCM
@@ -197,7 +201,7 @@ const actions = {
start = new Date(start)
end = new Date(end)
_.each(periods, (period, i) => {
- if(index != i){
+ if(index != i && !period.deleted){
if((new Date(period.period_start) <= start && new Date(period.period_end) >= start) || (new Date(period.period_start) <= end && new Date(period.period_end) >= end))
error = 'Les périodes ne peuvent pas se chevaucher'
}
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js b/app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js
index cc7980b22..10b558373 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/ExceptionsInDay.js
@@ -10,9 +10,8 @@ class ExceptionsInDay extends Component {
render() {
{/* display add or remove link, only if true in daytypes */}
- if(this.props.outFromDaytypes == true) {
{/* display add or remove link, according to context (presence in period, or not) */}
- if(this.props.value.current_month[this.props.index].in_periods == true) {
+ if(this.props.value.current_month[this.props.index].in_periods == true && this.props.blueDaytype == true) {
return (
<div className='td'>
<button
@@ -28,7 +27,7 @@ class ExceptionsInDay extends Component {
</button>
</div>
)
- } else {
+ } else if(this.props.value.current_month[this.props.index].in_periods == false) {
return (
<div className='td'>
<button
@@ -44,19 +43,20 @@ class ExceptionsInDay extends Component {
</button>
</div>
)
+ } else if(this.props.value.current_month[this.props.index].in_periods == true && this.props.blueDaytype == false){
+ return (
+ <div className='td'></div>
+ )
+ } else{
+ return false
}
- } else {
- return (
- <div className='td'></div>
- )
- }
}
}
ExceptionsInDay.propTypes = {
value: PropTypes.object.isRequired,
metas: PropTypes.object.isRequired,
- outFromDaytypes: PropTypes.bool.isRequired,
+ blueDaytype: PropTypes.bool.isRequired,
onExcludeDateFromPeriod: PropTypes.func.isRequired,
onIncludeDateInPeriod: PropTypes.func.isRequired,
index: PropTypes.number.isRequired
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 792d75520..502320c27 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/Metas.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/Metas.js
@@ -107,7 +107,7 @@ const Metas = ({metas, onUpdateDayTypes, onUpdateComment, onUpdateColor, onSelec
<div className="checkbox">
<label>
<input
- onChange={(e) => {onUpdateDayTypes(i)}}
+ onChange={(e) => {onUpdateDayTypes(i, metas.day_types)}}
id={i}
type="checkbox"
checked={day ? 'checked' : ''}
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 5beb80573..1a6c67b6b 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js
@@ -118,7 +118,7 @@ const PeriodForm = ({modal, timetable, metas, onOpenAddPeriodForm, onClosePeriod
<div className="text-right">
<button
type='button'
- className='btn btn-outline-primary add_fields'
+ className='btn btn-outline-primary'
onClick={onOpenAddPeriodForm}
>
Ajouter une période
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 29c894565..71621c874 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/TimeTableDay.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/TimeTableDay.js
@@ -17,7 +17,7 @@ class TimeTableDay extends Component {
{((this.props.value.day).charAt(0) == 'm') ? (this.props.value.day).substr(0, 2) : (this.props.value.day).charAt(0)}
</span>
<span
- className={'daynumber' + (((this.props.value.in_periods && this.props.dayTypeActive && !this.props.value.excluded_date) || (this.props.value.include_date && this.props.dayTypeActive)) ? ' included' : '')}
+ className={'daynumber' + (((this.props.value.in_periods && this.props.dayTypeActive && !this.props.value.excluded_date) || (this.props.value.include_date)) ? ' included' : '')}
>
{this.props.value.mday}
</span>
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 1830bfcde..d562655b9 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js
@@ -60,7 +60,7 @@ class Timetable extends Component{
{this.props.timetable.current_month.map((d, i) =>
<div
key={i}
- className={'td-group' + (this.props.metas.day_types[d.wday] ? '' : ' out_from_daytypes') + (d.wday == 0 ? ' last_wday' : '')}
+ className={'td-group' + (this.props.metas.day_types[d.wday] || !d.in_periods ? '' : ' out_from_daytypes') + (d.wday == 0 ? ' last_wday' : '')}
>
{/* day_types */}
<div className="td"></div>
@@ -80,7 +80,7 @@ class Timetable extends Component{
index={i}
value={this.props.timetable}
metas={this.props.metas}
- outFromDaytypes={this.props.metas.day_types[d.wday]}
+ blueDaytype={this.props.metas.day_types[d.wday]}
onExcludeDateFromPeriod={this.props.onExcludeDateFromPeriod}
onIncludeDateInPeriod={this.props.onIncludeDateInPeriod}
/>
diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/Metas.js b/app/assets/javascripts/es6_browserified/time_tables/containers/Metas.js
index a8639d89f..c4ab2d5b3 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/containers/Metas.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/containers/Metas.js
@@ -10,8 +10,11 @@ const mapStateToProps = (state) => {
const mapDispatchToProps = (dispatch) => {
return {
- onUpdateDayTypes: (index) => {
- dispatch(actions.updateDayTypes(index))
+ onUpdateDayTypes: (index, dayTypes) => {
+ let newDayTypes = dayTypes.slice(0)
+ newDayTypes[index] = !newDayTypes[index]
+ dispatch(actions.updateDayTypes(newDayTypes))
+ dispatch(actions.updateCurrentMonthFromDaytypes(newDayTypes))
},
onUpdateComment: (comment) => {
dispatch(actions.updateComment(comment))
diff --git a/app/assets/javascripts/es6_browserified/time_tables/reducers/metas.js b/app/assets/javascripts/es6_browserified/time_tables/reducers/metas.js
index dd6b484f3..97de90225 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/reducers/metas.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/metas.js
@@ -18,9 +18,7 @@ const metas = (state = {}, action) => {
case 'VALIDATE_PERIOD_FORM':
return _.assign({}, state, {calendar: {name: 'Aucun'}})
case 'UPDATE_DAY_TYPES':
- let dayTypes = state.day_types.slice(0)
- dayTypes[action.index] = !dayTypes[action.index]
- return _.assign({}, state, {day_types: dayTypes, calendar : {name: 'Aucun'}})
+ return _.assign({}, state, {day_types: action.dayTypes, calendar : {name: 'Aucun'}})
case 'UPDATE_COMMENT':
return _.assign({}, state, {comment: action.comment})
case 'UPDATE_COLOR':
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 f84223b23..65cd9231a 100644
--- a/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js
+++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js
@@ -55,6 +55,8 @@ const timetable = (state = {}, action) => {
})
newState = _.assign({}, state, {current_month: newCMe})
return _.assign({}, newState, {current_month: actions.updateSynthesis(newState, action.dayTypes)})
+ case 'UPDATE_CURRENT_MONTH_FROM_DAYTYPES':
+ return _.assign({}, state, {current_month: actions.updateSynthesis(state, action.dayTypes)})
case 'VALIDATE_PERIOD_FORM':
let period_start = actions.formatDate(action.modalProps.begin)
let period_end = actions.formatDate(action.modalProps.end)
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js
index 0e6f5ed12..0af1bb53d 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js
@@ -88,9 +88,10 @@ const actions = {
type : 'DELETE_CALENDAR_MODAL',
timetable
}),
- editVehicleJourneyCalendars : (vehicleJourneys) => ({
- type: 'EDIT_VEHICLEJOURNEYS_CALENDARS',
- vehicleJourneys
+ editVehicleJourneyTimetables : (vehicleJourneys, timetables) => ({
+ type: 'EDIT_VEHICLEJOURNEYS_TIMETABLES',
+ vehicleJourneys,
+ timetables
}),
openShiftModal : () => ({
type : 'SHIFT_VEHICLEJOURNEY_MODAL'
@@ -189,6 +190,9 @@ const actions = {
toggleWithoutSchedule: () => ({
type: 'TOGGLE_WITHOUT_SCHEDULE'
}),
+ toggleWithoutTimeTable: () => ({
+ type: 'TOGGLE_WITHOUT_TIMETABLE'
+ }),
updateStartTimeFilter: (val, unit) => ({
type: 'UPDATE_START_TIME_FILTER',
val,
@@ -216,6 +220,12 @@ const actions = {
published_name: selectedJP.published_name
}
}),
+ filterSelect2VehicleJourney: (selectedVJ) => ({
+ type : 'SELECT_VJ_FILTER',
+ selectedItem: {
+ objectid: selectedVJ.objectid
+ }
+ }),
createQueryString: () => ({
type: 'CREATE_QUERY_STRING'
}),
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Filters.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Filters.js
index 6f07dd880..e2d03e195 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Filters.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Filters.js
@@ -1,16 +1,26 @@
var React = require('react')
var PropTypes = require('react').PropTypes
var MissionSelect2 = require('./tools/select2s/MissionSelect2')
+var VJSelect2 = require('./tools/select2s/VJSelect2')
var TimetableSelect2 = require('./tools/select2s/TimetableSelect2')
-const Filters = ({filters, pagination, onFilter, onResetFilters, onUpdateStartTimeFilter, onUpdateEndTimeFilter, onToggleWithoutSchedule, onSelect2Timetable, onSelect2JourneyPattern}) => {
+const Filters = ({filters, pagination, onFilter, onResetFilters, onUpdateStartTimeFilter, onUpdateEndTimeFilter, onToggleWithoutSchedule, onToggleWithoutTimeTable, onSelect2Timetable, onSelect2JourneyPattern, onSelect2VehicleJourney}) => {
return (
<div className='row'>
<div className='col-lg-12'>
<div className='form form-filter'>
<div className='ffg-row'>
+ {/* ID course */}
+ <div className="form-group w33">
+ <VJSelect2
+ onSelect2VehicleJourney={onSelect2VehicleJourney}
+ filters={filters}
+ isFilter={true}
+ />
+ </div>
+
{/* Missions */}
- <div className='form-group w40'>
+ <div className='form-group w33'>
<MissionSelect2
onSelect2JourneyPattern={onSelect2JourneyPattern}
filters={filters}
@@ -19,7 +29,7 @@ const Filters = ({filters, pagination, onFilter, onResetFilters, onUpdateStartTi
</div>
{/* Calendriers */}
- <div className='form-group w40'>
+ <div className='form-group w33'>
<TimetableSelect2
onSelect2Timetable={onSelect2Timetable}
hasRoute={true}
@@ -87,9 +97,9 @@ const Filters = ({filters, pagination, onFilter, onResetFilters, onUpdateStartTi
</div>
{/* Switch avec/sans horaires */}
- <div className='form-group has_switch w40'>
- <label className='control-label col-sm-8'>Afficher les courses sans horaires</label>
- <div className='form-group col-sm-4' style={{padding: 0}}>
+ <div className='form-group has_switch'>
+ <label className='control-label pull-left'>Afficher les courses sans horaires</label>
+ <div className='form-group pull-left' style={{padding: 0}}>
<div className='checkbox'>
<label>
<input
@@ -104,6 +114,25 @@ const Filters = ({filters, pagination, onFilter, onResetFilters, onUpdateStartTi
</div>
</div>
+ <div className="ffg-row">
+ {/* Switch avec/sans calendrier */}
+ <div className='form-group has_switch'>
+ <label className='control-label pull-left'>Afficher les courses sans calendrier</label>
+ <div className='form-group pull-left' style={{padding: 0}}>
+ <div className='checkbox'>
+ <label>
+ <input
+ type='checkbox'
+ onChange={onToggleWithoutTimeTable}
+ checked={filters.query.withoutTimeTable}
+ ></input>
+ <span className='switch-label' data-checkedvalue='Oui' data-uncheckedvalue='Non'></span>
+ </label>
+ </div>
+ </div>
+ </div>
+ </div>
+
{/* Actions */}
<div className='actions'>
<span
@@ -131,7 +160,8 @@ Filters.propTypes = {
onUpdateStartTimeFilter: PropTypes.func.isRequired,
onUpdateEndTimeFilter: PropTypes.func.isRequired,
onSelect2Timetable: PropTypes.func.isRequired,
- onSelect2JourneyPattern: PropTypes.func.isRequired
+ onSelect2JourneyPattern: PropTypes.func.isRequired,
+ onSelect2VehicleJourney: PropTypes.func.isRequired
}
module.exports = Filters
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Tools.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Tools.js
index e486dd155..b417828db 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Tools.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/Tools.js
@@ -6,7 +6,7 @@ var ShiftVehicleJourney = require('../containers/tools/ShiftVehicleJourney')
var DuplicateVehicleJourney = require('../containers/tools/DuplicateVehicleJourney')
var EditVehicleJourney = require('../containers/tools/EditVehicleJourney')
var NotesEditVehicleJourney = require('../containers/tools/NotesEditVehicleJourney')
-var CalendarsEditVehicleJourney = require('../containers/tools/CalendarsEditVehicleJourney')
+var TimetablesEditVehicleJourney = require('../containers/tools/TimetablesEditVehicleJourney')
var actions = require('../actions')
const Tools = ({vehicleJourneys, onCancelSelection}) => {
@@ -17,7 +17,7 @@ const Tools = ({vehicleJourneys, onCancelSelection}) => {
<DuplicateVehicleJourney />
<ShiftVehicleJourney />
<EditVehicleJourney />
- <CalendarsEditVehicleJourney />
+ <TimetablesEditVehicleJourney />
<NotesEditVehicleJourney />
<DeleteVehicleJourneys />
</ul>
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js
index 6f338f747..de370ac1b 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/VehicleJourney.js
@@ -15,6 +15,7 @@ class VehicleJourney extends Component {
bool = true
this.previousCity = sp.stop_area_cityname
}
+
return bool
}
@@ -51,9 +52,11 @@ class VehicleJourney extends Component {
<div className='th'>
<div className='strong mb-xs'>{this.props.value.objectid ? actions.humanOID(this.props.value.objectid) : '-'}</div>
<div>{actions.humanOID(this.props.value.journey_pattern.objectid)}</div>
- {this.props.value.time_tables.map((tt, i)=>
- <div key={i}>{this.timeTableURL(tt)}</div>
- )}
+ <div>
+ {this.props.value.time_tables.map((tt, i)=>
+ <span key={i} className='vj_tt'>{this.timeTableURL(tt)}</span>
+ )}
+ </div>
{(this.props.filters.policy['vehicle_journeys.edit'] == true) &&
<div className={(this.props.value.deletable ? 'disabled ' : '') + 'checkbox'}>
@@ -73,7 +76,7 @@ class VehicleJourney extends Component {
</div>
{this.props.value.vehicle_journey_at_stops.map((vj, i) =>
<div key={i} className='td text-center'>
- <div className={'cellwrap' + (vj.dummy ? ' headlined' : '') + (this.cityNameChecker(vj) ? ' headlined' : '')}>
+ <div className={'cellwrap' + (this.cityNameChecker(vj) ? ' headlined' : '')}>
{this.props.filters.toggleArrivals &&
<div data-headline='Arrivée à'>
<span className={((this.isDisabled(this.props.value.deletable, vj.dummy) || this.props.filters.policy['vehicle_journeys.edit'] == false) ? 'disabled ' : '') + 'input-group time'}>
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js
index 1e121b473..314d481d4 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js
@@ -71,6 +71,7 @@ class CreateModal extends Component {
<div className='form-group'>
<label className='control-label is-required'>Nom public de la mission</label>
<MissionSelect2
+ selection={this.props.modal.modalProps}
onSelect2JourneyPattern={this.props.onSelect2JourneyPattern}
isFilter={false}
/>
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CalendarsEditVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js
index e32c873e6..d6c1179ba 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CalendarsEditVehicleJourney.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/TimetablesEditVehicleJourney.js
@@ -4,13 +4,13 @@ var PropTypes = require('react').PropTypes
var actions = require('../../actions')
var TimetableSelect2 = require('./select2s/TimetableSelect2')
-class CalendarsEditVehicleJourney extends Component {
+class TimetablesEditVehicleJourney extends Component {
constructor(props) {
super(props)
}
handleSubmit() {
- this.props.onCalendarsEditVehicleJourney(this.props.modal.modalProps.vehicleJourneys)
+ this.props.onTimetablesEditVehicleJourney(this.props.modal.modalProps.vehicleJourneys, this.props.modal.modalProps.timetables)
this.props.onModalClose()
$('#CalendarsEditVehicleJourneyModal').modal('hide')
}
@@ -134,14 +134,14 @@ class CalendarsEditVehicleJourney extends Component {
}
}
-CalendarsEditVehicleJourney.propTypes = {
+TimetablesEditVehicleJourney.propTypes = {
onOpenCalendarsEditModal: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired,
- onCalendarsEditVehicleJourney: PropTypes.func.isRequired,
+ onTimetablesEditVehicleJourney: PropTypes.func.isRequired,
onDeleteCalendarModal: PropTypes.func.isRequired,
onSelect2Timetable: PropTypes.func.isRequired,
onAddSelectedTimetable: PropTypes.func.isRequired,
filters: PropTypes.object.isRequired
}
-module.exports = CalendarsEditVehicleJourney
+module.exports = TimetablesEditVehicleJourney
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js
index 1f5e5e98f..a6b8dcfa1 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js
@@ -27,6 +27,7 @@ class BSelect4 extends React.Component{
theme: 'bootstrap',
width: '100%',
placeholder: 'Filtrer par transporteur...',
+ language: require('./fr'),
ajax: {
url: origin + path + '/companies.json' + '?line_id=' + line,
dataType: 'json',
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js
index 75cbd1f3c..36aaa5cfd 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js
@@ -13,18 +13,20 @@ class BSelect4 extends React.Component{
super(props)
}
+
render() {
return (
<Select2
- data={(this.props.isFilter) ? [this.props.filters.query.journeyPattern.published_name] : undefined}
- value={(this.props.isFilter) ? this.props.filters.query.journeyPattern.published_name : undefined}
+ data={(this.props.isFilter) ? [this.props.filters.query.journeyPattern.published_name] : ((this.props.selection.selectedJPModal) ? [this.props.selection.selectedJPModal.published_name] : undefined)}
+ value={(this.props.isFilter) ? this.props.filters.query.journeyPattern.published_name : ((this.props.selection.selectedJPModal) ? this.props.selection.selectedJPModal.published_name : undefined) }
onSelect={(e) => this.props.onSelect2JourneyPattern(e)}
multiple={false}
ref='journey_pattern_id'
options={{
allowClear: false,
theme: 'bootstrap',
- placeholder: 'Filtrer par mission...',
+ placeholder: 'Filtrer par code, nom ou OID de mission...',
+ language: require('./fr'),
width: '100%',
ajax: {
url: origin + path + '/journey_patterns_collection.json',
@@ -32,7 +34,7 @@ class BSelect4 extends React.Component{
delay: '500',
data: function(params) {
return {
- q: {published_name_cont: params.term},
+ q: {published_name_or_objectid_or_registration_number_cont: params.term},
};
},
processResults: function(data, params) {
@@ -41,14 +43,15 @@ class BSelect4 extends React.Component{
item => _.assign(
{},
item,
- {text: item.published_name}
+ { text: '<small><em>Nom: </em></small>' + item.published_name + '<br/><small><em>Code: </em></small>' + item.registration_number + '<br/><small><em>ID: </em></small>' + _.last(_.split(item.object_id, ':')) }
)
)
};
},
cache: true
},
- minimumInputLength: 3,
+ minimumInputLength: 2,
+ escapeMarkup: function (markup) { return markup; },
templateResult: formatRepo
}}
/>
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
index c28d8e06f..b236e7d94 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js
@@ -26,6 +26,7 @@ class BSelect4 extends React.Component{
theme: 'bootstrap',
width: '100%',
placeholder: 'Filtrer par calendrier...',
+ language: require('./fr'),
ajax: {
url: origin + path + this.props.chunkURL,
dataType: 'json',
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/VJSelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/VJSelect2.js
new file mode 100644
index 000000000..cc2ee4b9e
--- /dev/null
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/VJSelect2.js
@@ -0,0 +1,68 @@
+var _ = require('lodash')
+var React = require('react')
+var PropTypes = require('react').PropTypes
+var Select2 = require('react-select2')
+
+// get JSON full path
+var origin = window.location.origin
+var path = window.location.pathname.split('/', 7).join('/')
+
+
+class BSelect4b extends React.Component{
+ constructor(props) {
+ super(props)
+ }
+ humanOID(oid) {
+ var a = oid.split(':')
+ return a[a.length - 1]
+ }
+
+ render() {
+ return (
+ <Select2
+ data={(this.props.isFilter) ? [this.props.filters.query.vehicleJourney.objectid] : undefined}
+ value={(this.props.isFilter) ? this.props.filters.query.vehicleJourney.objectid : undefined}
+ onSelect={(e) => this.props.onSelect2VehicleJourney(e)}
+ multiple={false}
+ ref='vehicle_journey_objectid'
+ options={{
+ allowClear: false,
+ theme: 'bootstrap',
+ placeholder: 'Filtrer par ID course...',
+ width: '100%',
+ language: require('./fr'),
+ ajax: {
+ url: origin + path + '/vehicle_journeys.json',
+ dataType: 'json',
+ delay: '500',
+ data: function(params) {
+ return {
+ q: {objectid_cont: params.term},
+ };
+ },
+ processResults: function(data, params) {
+ return {
+ results: data.vehicle_journeys.map(
+ item => _.assign(
+ {},
+ item,
+ { id: item.objectid, text: _.last(_.split(item.objectid, ':')) }
+ )
+ )
+ };
+ },
+ cache: true
+ },
+ minimumInputLength: 1,
+ templateResult: formatRepo
+ }}
+ />
+ )
+ }
+}
+
+const formatRepo = (props) => {
+ if(props.text) return props.text
+}
+
+module.exports = BSelect4b
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/fr.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/fr.js
new file mode 100644
index 000000000..20154d412
--- /dev/null
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/fr.js
@@ -0,0 +1,9 @@
+module.exports = {
+ errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},
+ inputTooLong:function(e){var t=e.input.length-e.maximum,n="Supprimez "+t+" caractère";return t!==1&&(n+="s"),n},
+ inputTooShort:function(e){var t=e.minimum-e.input.length,n="Saisissez "+t+" caractère";return t!==1&&(n+="s"),n},
+ loadingMore:function(){return"Chargement de résultats supplémentaires…"},
+ maximumSelected:function(e){var t="Vous pouvez seulement sélectionner "+e.maximum+" élément";return e.maximum!==1&&(t+="s"),t},
+ noResults:function(){return"Aucun résultat trouvé"},
+ searching:function(){return"Recherche en cours…"}
+}
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Filters.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Filters.js
index 7570dd466..831b47ca1 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Filters.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/Filters.js
@@ -22,6 +22,9 @@ const mapDispatchToProps = (dispatch) => {
onToggleWithoutSchedule: () =>{
dispatch(actions.toggleWithoutSchedule())
},
+ onToggleWithoutTimeTable: () =>{
+ dispatch(actions.toggleWithoutTimeTable())
+ },
onResetFilters: (e, pagination) =>{
dispatch(actions.checkConfirmModal(e, actions.resetFilters(dispatch), pagination.stateChanged, dispatch))
},
@@ -33,6 +36,9 @@ const mapDispatchToProps = (dispatch) => {
},
onSelect2JourneyPattern: (e) => {
dispatch(actions.filterSelect2JourneyPattern(e.params.data))
+ },
+ onSelect2VehicleJourney: (e) => {
+ dispatch(actions.filterSelect2VehicleJourney(e.params.data))
}
}
}
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/CalendarsEditVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/TimetablesEditVehicleJourney.js
index 130acb017..6d0096019 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/CalendarsEditVehicleJourney.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/TimetablesEditVehicleJourney.js
@@ -1,5 +1,5 @@
var connect = require('react-redux').connect
-var CalendarsEditComponent = require('../../components/tools/CalendarsEditVehicleJourney')
+var TimetablesEditComponent = require('../../components/tools/TimetablesEditVehicleJourney')
var actions = require('../../actions')
const mapStateToProps = (state) => {
@@ -22,8 +22,8 @@ const mapDispatchToProps = (dispatch) => {
onDeleteCalendarModal: (timetable) => {
dispatch(actions.deleteCalendarModal(timetable))
},
- onCalendarsEditVehicleJourney: (calendars) =>{
- dispatch(actions.editVehicleJourneyCalendars(calendars))
+ onTimetablesEditVehicleJourney: (vehicleJourneys, timetables) =>{
+ dispatch(actions.editVehicleJourneyTimetables(vehicleJourneys, timetables))
},
onSelect2Timetable: (e) =>{
dispatch(actions.selectTTCalendarsModal(e.params.data))
@@ -34,6 +34,6 @@ const mapDispatchToProps = (dispatch) => {
}
}
-const CalendarsEditVehicleJourney = connect(mapStateToProps, mapDispatchToProps)(CalendarsEditComponent)
+const TimetablesEditVehicleJourney = connect(mapStateToProps, mapDispatchToProps)(TimetablesEditComponent)
-module.exports = CalendarsEditVehicleJourney
+module.exports = TimetablesEditVehicleJourney
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js
index 4c9423c1f..489446ab9 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/index.js
@@ -8,10 +8,10 @@ var actions = require("./actions")
var enableBatching = require('./batch').enableBatching
// logger, DO NOT REMOVE
-// var applyMiddleware = require('redux').applyMiddleware
-// var createLogger = require('redux-logger')
-// var thunkMiddleware = require('redux-thunk').default
-// var promise = require('redux-promise')
+var applyMiddleware = require('redux').applyMiddleware
+var createLogger = require('redux-logger')
+var thunkMiddleware = require('redux-thunk').default
+var promise = require('redux-promise')
var selectedJP = []
@@ -38,13 +38,17 @@ var initialState = {
journeyPattern: {
published_name: ''
},
+ vehicleJourney: {
+ objectid: ''
+ },
company: {
name: ''
},
timetable: {
comment: ''
},
- withoutSchedule: true
+ withoutSchedule: true,
+ withoutTimeTable: false
}
},
@@ -76,16 +80,17 @@ if (window.jpOrigin){
}
let params = {
'q[journey_pattern_id_eq]': initialState.filters.query.journeyPattern.id,
+ 'q[objectid_cont]': initialState.filters.query.vehicleJourney.objectid
}
initialState.filters.queryString = actions.encodeParams(params)
}
-// const loggerMiddleware = createLogger()
+const loggerMiddleware = createLogger()
let store = createStore(
enableBatching(vehicleJourneysApp),
- initialState
- // applyMiddleware(thunkMiddleware, promise, loggerMiddleware)
+ initialState,
+ applyMiddleware(thunkMiddleware, promise, loggerMiddleware)
)
render(
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/filters.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/filters.js
index 80b62c6b4..09588f824 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/filters.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/filters.js
@@ -15,11 +15,14 @@ const filters = (state = {}, action) => {
minute: '59'
}
}
- newQuery = _.assign({}, state.query, {interval: interval, journeyPattern: {}, timetable: {}, withoutSchedule: true })
+ newQuery = _.assign({}, state.query, {interval: interval, journeyPattern: {}, vehicleJourney: {}, timetable: {}, withoutSchedule: true, withoutTimeTable: false })
return _.assign({}, state, {query: newQuery, queryString: ''})
case 'TOGGLE_WITHOUT_SCHEDULE':
newQuery = _.assign({}, state.query, {withoutSchedule: !state.query.withoutSchedule})
return _.assign({}, state, {query: newQuery})
+ case 'TOGGLE_WITHOUT_TIMETABLE':
+ newQuery = _.assign({}, state.query, {withoutTimeTable: !state.query.withoutTimeTable})
+ return _.assign({}, state, {query: newQuery})
case 'UPDATE_END_TIME_FILTER':
newInterval = JSON.parse(JSON.stringify(state.query.interval))
newInterval.end[action.unit] = actions.pad(action.val, action.unit)
@@ -44,6 +47,9 @@ const filters = (state = {}, action) => {
case 'SELECT_JP_FILTER':
newQuery = _.assign({}, state.query, {journeyPattern : action.selectedItem})
return _.assign({}, state, {query: newQuery})
+ case 'SELECT_VJ_FILTER':
+ newQuery = _.assign({}, state.query, {vehicleJourney : action.selectedItem})
+ return _.assign({}, state, {query: newQuery})
case 'TOGGLE_ARRIVALS':
return _.assign({}, state, {toggleArrivals: !state.toggleArrivals})
case 'QUERY_FILTER_VEHICLEJOURNEYS':
@@ -52,11 +58,12 @@ const filters = (state = {}, action) => {
case 'CREATE_QUERY_STRING':
let params = {
'q[journey_pattern_id_eq]': state.query.journeyPattern.id || undefined,
+ 'q[objectid_cont]': state.query.vehicleJourney.objectid || undefined,
'q[time_tables_id_eq]': state.query.timetable.id || undefined,
- // Fixme 3358
- // 'q[vehicle_journey_at_stops_departure_time_gteq]': (state.query.interval.start.hour + ':' + state.query.interval.start.minute),
- // 'q[vehicle_journey_at_stops_departure_time_lteq]': (state.query.interval.end.hour + ':' + state.query.interval.end.minute),
- // 'q[vehicle_journey_without_departure_time]' : state.query.withoutSchedule
+ 'q[vehicle_journey_at_stops_departure_time_gteq]': (state.query.interval.start.hour + ':' + state.query.interval.start.minute),
+ 'q[vehicle_journey_at_stops_departure_time_lteq]': (state.query.interval.end.hour + ':' + state.query.interval.end.minute),
+ 'q[vehicle_journey_without_departure_time]': state.query.withoutSchedule,
+ 'q[vehicle_journey_without_time_table]': state.query.withoutTimeTable
}
let queryString = actions.encodeParams(params)
return _.assign({}, state, {queryString: queryString})
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js
index 3b13ab9de..e504c2531 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/modal.js
@@ -63,17 +63,6 @@ const modal = (state = {}, action) => {
case 'ADD_SELECTED_TIMETABLE':
if(state.modalProps.selectedTimetable){
newModalProps = JSON.parse(JSON.stringify(state.modalProps))
- newModalProps.vehicleJourneys.map((vj) => {
- let isPresent = false
- vj.time_tables.forEach((tt) =>{
- if (_.isEqual(newModalProps.selectedTimetable.objectid, tt.objectid)){
- isPresent = true
- }
- })
- if (!isPresent){
- vj.time_tables.push(newModalProps.selectedTimetable)
- }
- })
if (!_.find(newModalProps.timetables, newModalProps.selectedTimetable)){
newModalProps.timetables.push(newModalProps.selectedTimetable)
}
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js
index 2db76deae..d153739ce 100644
--- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js
+++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js
@@ -1,7 +1,7 @@
var _ = require('lodash')
var actions = require("../actions")
-const vehicleJourney= (state = {}, action) => {
+const vehicleJourney= (state = {}, action, keep) => {
switch (action.type) {
case 'SELECT_VEHICLEJOURNEY':
return _.assign({}, state, {selected: !state.selected})
@@ -61,10 +61,14 @@ const vehicleJourney= (state = {}, action) => {
actions.checkSchedules(shiftedSchedule)
shiftedVjas = _.assign({}, state.vehicle_journey_at_stops[i], shiftedSchedule)
vjas = _.assign({}, state.vehicle_journey_at_stops[i], shiftedVjas)
- delete vjas['id']
+ if(!keep){
+ delete vjas['id']
+ }
return vjas
}else {
- delete vjas['id']
+ if(!keep){
+ delete vjas['id']
+ }
return vjas
}
})
@@ -147,13 +151,14 @@ const vehicleJourneys = (state = [], action) => {
return vj
}
})
- case 'EDIT_VEHICLEJOURNEYS_CALENDARS':
+ case 'EDIT_VEHICLEJOURNEYS_TIMETABLES':
+ let newTimetables = JSON.parse(JSON.stringify(action.timetables))
return state.map((vj,i) =>{
if(vj.selected){
let updatedVJ = _.assign({}, vj)
action.vehicleJourneys.map((vjm, j) =>{
if(vj.objectid == vjm.objectid){
- updatedVJ.time_tables = vjm.time_tables
+ updatedVJ.time_tables = newTimetables
}
})
return updatedVJ
@@ -164,7 +169,7 @@ const vehicleJourneys = (state = [], action) => {
case 'SHIFT_VEHICLEJOURNEY':
return state.map((vj, i) => {
if (vj.selected){
- return vehicleJourney(vj, action)
+ return vehicleJourney(vj, action, true)
}else{
return vj
}
@@ -179,7 +184,7 @@ const vehicleJourneys = (state = [], action) => {
selectedIndex = i
for (i = 0; i< action.data.duplicate_number.value; i++){
action.data.additional_time.value = val * (i + 1)
- dupeVj = vehicleJourney(vj, action)
+ dupeVj = vehicleJourney(vj, action, false)
dupeVj.published_journey_name = dupeVj.published_journey_name + '-' + i
dupeVj.selected = false
delete dupeVj['objectid']
diff --git a/app/assets/javascripts/select2.coffee b/app/assets/javascripts/select2.coffee
index 1870f7f9a..af3dc6d75 100644
--- a/app/assets/javascripts/select2.coffee
+++ b/app/assets/javascripts/select2.coffee
@@ -1,19 +1,42 @@
+bind_select2 = (el, cfg = {}) ->
+ target = $(el)
+ default_cfg =
+ theme: 'bootstrap'
+ language: 'fr'
+ placeholder: target.data('select2ed-placeholder')
+ allowClear: false
+
+ target.select2 $.extend({}, default_cfg, cfg)
+
+bind_select2_ajax = (el, cfg = {}) ->
+ target = $(el)
+ cfg =
+ ajax:
+ data: (params) ->
+ q:
+ "#{target.data('term')}": params.term
+ url: target.data('url'),
+ dataType: 'json',
+ delay: 125,
+ processResults: (data, params) -> results: data
+ minimumInputLength: 3
+ templateResult: (item) ->
+ item.text
+ templateSelection: (item) ->
+ item.text
+
+ bind_select2(el, cfg)
+
@select_2 = ->
$("[data-select2ed='true']").each ->
- target = $(this)
- target.select2
- theme: 'bootstrap'
- language: 'fr'
- placeholder: target.data('select2ed-placeholder')
- allowClear: true
+ bind_select2(this)
+
+ $("[data-select2-ajax='true']").each ->
+ bind_select2_ajax(this)
$('select.form-control.tags').each ->
- target = $(this)
- target.select2
- theme: 'bootstrap'
- language: 'fr'
- allowClear: true
- tags: true
+ bind_select2(this, {tags: true})
+
$(document).on 'turbolinks:load', select_2
diff --git a/app/assets/javascripts/time_table_combinations.coffee b/app/assets/javascripts/time_table_combinations.coffee
new file mode 100644
index 000000000..8923af958
--- /dev/null
+++ b/app/assets/javascripts/time_table_combinations.coffee
@@ -0,0 +1,6 @@
+@combinedTypeToggle = ->
+ $('#time_table_combination_combined_type').on 'click', ->
+ $(this).closest('.has_switch').siblings('.form-group').each ->
+ $(this).toggleClass('hidden')
+
+$(document).on 'turbolinks:load', combinedTypeToggle
diff --git a/app/assets/stylesheets/OpenLayers/custom.sass b/app/assets/stylesheets/OpenLayers/custom.sass
index a13f6c831..7a5b4baf1 100644
--- a/app/assets/stylesheets/OpenLayers/custom.sass
+++ b/app/assets/stylesheets/OpenLayers/custom.sass
@@ -1,5 +1,64 @@
.map
- // ...
-
.list-group-item &
margin-top: 15px
+
+
+ .ol-scale-line
+ background-color: transparent
+ bottom: 5px
+ right: 5px
+ left: auto
+ padding: 3px
+ position: absolute
+
+ .ol-scale-line-inner
+ position: relative
+ border: none
+ border-bottom: 2px solid $darkblue
+ border-top: none
+ color: $darkblue
+ font-size: 0.85em
+ text-align: center
+ font-weight: 700
+
+ &:before
+ content: ''
+ display: block
+ position: absolute
+ left: 0
+ bottom: 0
+ right: 0
+ height: 5px
+ border-left: 2px solid $darkblue
+ border-right: 2px solid $darkblue
+
+ .ol-zoom
+ background-color: transparent
+
+ .ol-zoom-in, .ol-zoom-out
+ background-color: $darkblue
+ color: #fff
+ border-radius: 3px
+ margin: 0
+
+ .ol-zoom-in
+ border-bottom-left-radius: 0
+ border-bottom-right-radius: 0
+
+ .ol-zoom-out
+ margin-top: 1px
+ border-top-left-radius: 0
+ border-top-right-radius: 0
+
+ .ol-zoomslider
+ margin: 2px
+ width: calc(1.375em + 4px)
+ background-color: rgba($darkblue, 0.25)
+
+ button.ol-zoomslider-thumb
+ margin: 0 -2px 0 -2px
+ padding: 0 2px
+ background-color: $darkblue
+ color: #fff
+ border-radius: 0
+ z-index: 5
diff --git a/app/assets/stylesheets/OpenLayers/ol.css b/app/assets/stylesheets/OpenLayers/ol.css
index ea50e7ebe..02c19f3af 100644
--- a/app/assets/stylesheets/OpenLayers/ol.css
+++ b/app/assets/stylesheets/OpenLayers/ol.css
@@ -1 +1,226 @@
-.ol-control,.ol-scale-line{position:absolute;padding:2px}.ol-box{box-sizing:border-box;border-radius:2px;border:2px solid #00f}.ol-mouse-position{top:8px;right:8px;position:absolute}.ol-scale-line{background:rgba(0,60,136,.3);border-radius:4px;bottom:8px;left:8px}.ol-scale-line-inner{border:1px solid #eee;border-top:none;color:#eee;font-size:10px;text-align:center;margin:1px;will-change:contents,width}.ol-overlay-container{will-change:left,right,top,bottom}.ol-unsupported{display:none}.ol-viewport .ol-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.ol-control{background-color:rgba(255,255,255,.4);border-radius:4px}.ol-control:hover{background-color:rgba(255,255,255,.6)}.ol-zoom{top:.5em;left:.5em}.ol-rotate{top:.5em;right:.5em;transition:opacity .25s linear,visibility 0s linear}.ol-rotate.ol-hidden{opacity:0;visibility:hidden;transition:opacity .25s linear,visibility 0s linear .25s}.ol-zoom-extent{top:4.643em;left:.5em}.ol-full-screen{right:.5em;top:.5em}@media print{.ol-control{display:none}}.ol-control button{display:block;margin:1px;padding:0;color:#fff;font-size:1.14em;font-weight:700;text-decoration:none;text-align:center;height:1.375em;width:1.375em;line-height:.4em;background-color:rgba(0,60,136,.5);border:none;border-radius:2px}.ol-control button::-moz-focus-inner{border:none;padding:0}.ol-zoom-extent button{line-height:1.4em}.ol-compass{display:block;font-weight:400;font-size:1.2em;will-change:transform}.ol-touch .ol-control button{font-size:1.5em}.ol-touch .ol-zoom-extent{top:5.5em}.ol-control button:focus,.ol-control button:hover{text-decoration:none;background-color:rgba(0,60,136,.7)}.ol-zoom .ol-zoom-in{border-radius:2px 2px 0 0}.ol-zoom .ol-zoom-out{border-radius:0 0 2px 2px}.ol-attribution{text-align:right;bottom:.5em;right:.5em;max-width:calc(100% - 1.3em)}.ol-attribution ul{margin:0;padding:0 .5em;font-size:.7rem;line-height:1.375em;color:#000;text-shadow:0 0 2px #fff}.ol-attribution li{display:inline;list-style:none;line-height:inherit}.ol-attribution li:not(:last-child):after{content:" "}.ol-attribution img{max-height:2em;max-width:inherit;vertical-align:middle}.ol-attribution button,.ol-attribution ul{display:inline-block}.ol-attribution.ol-collapsed ul{display:none}.ol-attribution.ol-logo-only ul{display:block}.ol-attribution:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-attribution.ol-uncollapsible{bottom:0;right:0;border-radius:4px 0 0;height:1.1em;line-height:1em}.ol-attribution.ol-logo-only{background:0 0;bottom:.4em;height:1.1em;line-height:1em}.ol-attribution.ol-uncollapsible img{margin-top:-.2em;max-height:1.6em}.ol-attribution.ol-logo-only button,.ol-attribution.ol-uncollapsible button{display:none}.ol-zoomslider{top:4.5em;left:.5em;height:200px}.ol-zoomslider button{position:relative;height:10px}.ol-touch .ol-zoomslider{top:5.5em}.ol-overviewmap{left:.5em;bottom:.5em}.ol-overviewmap.ol-uncollapsible{bottom:0;left:0;border-radius:0 4px 0 0}.ol-overviewmap .ol-overviewmap-map,.ol-overviewmap button{display:inline-block}.ol-overviewmap .ol-overviewmap-map{border:1px solid #7b98bc;height:150px;margin:2px;width:150px}.ol-overviewmap:not(.ol-collapsed) button{bottom:1px;left:2px;position:absolute}.ol-overviewmap.ol-collapsed .ol-overviewmap-map,.ol-overviewmap.ol-uncollapsible button{display:none}.ol-overviewmap:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-overviewmap-box{border:2px dotted rgba(0,60,136,.7)} \ No newline at end of file
+.ol-control,.ol-scale-line {
+ position:absolute;
+ padding:2px
+}
+.ol-box {
+ box-sizing:border-box;
+ border-radius:2px;
+ border:2px solid #00f
+}
+.ol-mouse-position {
+ top:8px;
+ right:8px;
+ position:absolute
+}
+.ol-scale-line {
+ background:rgba(0,60,136,.3);
+ border-radius:4px;
+ bottom:8px;
+ left:8px
+}
+.ol-scale-line-inner {
+ border:1px solid #eee;
+ border-top:none;
+ color:#eee;
+ font-size:10px;
+ text-align:center;
+ margin:1px;
+ will-change:contents,width
+}
+.ol-overlay-container {
+ will-change:left,right,top,bottom
+}
+.ol-unsupported {
+ display:none
+}
+.ol-viewport .ol-unselectable {
+ -webkit-touch-callout:none;
+ -webkit-user-select:none;
+ -khtml-user-select:none;
+ -moz-user-select:none;
+ -ms-user-select:none;
+ user-select:none;
+ -webkit-tap-highlight-color:transparent
+}
+.ol-control {
+ background-color:rgba(255,255,255,.4);
+ border-radius:4px
+}
+.ol-control:hover {
+ background-color:rgba(255,255,255,.6)
+}
+.ol-zoom {
+ top:.5em;
+ left:.5em
+}
+.ol-rotate{
+ top:.5em;
+ right:.5em;
+ transition:opacity .25s linear,visibility 0s linear
+}
+.ol-rotate.ol-hidden {
+ opacity:0;
+ visibility:hidden;
+ transition:opacity .25s linear,visibility 0s linear .25s
+}
+.ol-zoom-extent {
+ top:4.643em;
+ left:.5em
+}
+.ol-full-screen {
+ right:.5em;
+ top:.5em
+}
+@media print{
+ .ol-control{
+ display:none
+ }
+}
+.ol-control button {
+ display:block;
+ margin:1px;
+ padding:0;
+ color:#fff;
+ font-size:1.14em;
+ font-weight:700;
+ text-decoration:none;
+ text-align:center;
+ height:1.375em;
+ width:1.375em;
+ line-height:.4em;
+ background-color:rgba(0,60,136,.5);
+ border:none;
+ border-radius:2px
+}
+.ol-control button::-moz-focus-inner {
+ border:none;
+ padding:0
+}
+.ol-zoom-extent button {
+ line-height:1.4em
+}
+.ol-compass {
+ display:block;
+ font-weight:400;
+ font-size:1.2em;
+ will-change:transform
+}
+.ol-touch .ol-control button {
+ font-size:1.5em
+}
+.ol-touch .ol-zoom-extent {
+ top:5.5em
+}
+.ol-control button:focus,.ol-control button:hover {
+ text-decoration:none;
+ background-color:rgba(0,60,136,.7)
+}
+.ol-zoom .ol-zoom-in {
+ border-radius:2px 2px 0 0
+}
+.ol-zoom .ol-zoom-out {
+ border-radius:0 0 2px 2px
+}
+.ol-attribution {
+ text-align:right;
+ bottom:.5em;
+ right:.5em;
+ max-width:calc(100% - 1.3em)
+}
+.ol-attribution ul {
+ margin:0;
+ padding:0 .5em;
+ font-size:.7rem;
+ line-height:1.375em;
+ color:#000;
+ text-shadow:0 0 2px #fff
+}
+.ol-attribution li {
+ display:inline;
+ list-style:none;
+ line-height:inherit
+}
+.ol-attribution li:not(:last-child):after {
+ content:" "
+}
+.ol-attribution img {
+ max-height:2em;
+ max-width:inherit;
+ vertical-align:middle
+}
+.ol-attribution button,.ol-attribution ul {
+ display:inline-block
+}
+.ol-attribution.ol-collapsed ul {
+ display:none
+}
+.ol-attribution.ol-logo-only ul {
+ display:block
+}
+.ol-attribution:not(.ol-collapsed) {
+ background:rgba(255,255,255,.8)
+}
+.ol-attribution.ol-uncollapsible {
+ bottom:0;
+ right:0;
+ border-radius:4px 0 0;
+ height:1.1em;
+ line-height:1em
+}
+.ol-attribution.ol-logo-only {
+ background:0 0;
+ bottom:.4em;
+ height:1.1em;
+ line-height:1em
+}
+.ol-attribution.ol-uncollapsible img {
+ margin-top:-.2em;
+ max-height:1.6em
+}
+.ol-attribution.ol-logo-only button,.ol-attribution.ol-uncollapsible button {
+ display:none
+}
+.ol-zoomslider {
+ top:4.5em;
+ left:.5em;
+ height:200px
+}
+.ol-zoomslider button {
+ position:relative;
+ height:10px
+}
+.ol-touch .ol-zoomslider {
+ top:5.5em
+}
+.ol-overviewmap {
+ left:.5em;
+ bottom:.5em
+}
+.ol-overviewmap.ol-uncollapsible {
+ bottom:0;
+ left:0;
+ border-radius:0 4px 0 0
+}
+.ol-overviewmap .ol-overviewmap-map,.ol-overviewmap button {
+ display:inline-block
+}
+.ol-overviewmap .ol-overviewmap-map {
+ border:1px solid #7b98bc;
+ height:150px;
+ margin:2px;
+ width:150px
+}
+.ol-overviewmap:not(.ol-collapsed) button {
+ bottom:1px;
+ left:2px;
+ position:absolute
+}
+.ol-overviewmap.ol-collapsed .ol-overviewmap-map,.ol-overviewmap.ol-uncollapsible button {
+ display:none
+}
+.ol-overviewmap:not(.ol-collapsed) {
+ background:rgba(255,255,255,.8)
+}
+.ol-overviewmap-box {
+ border:2px dotted rgba(0,60,136,.7)
+}
diff --git a/app/assets/stylesheets/application.sass b/app/assets/stylesheets/application.sass
index 47cccba65..e3f776640 100644
--- a/app/assets/stylesheets/application.sass
+++ b/app/assets/stylesheets/application.sass
@@ -5,6 +5,8 @@
@import 'base/config'
@import 'base/utilities'
+@import 'OpenLayers/custom'
+
@import 'typography/fonts'
@import 'typography/sboiv'
@import 'typography/typography'
diff --git a/app/assets/stylesheets/base.sass b/app/assets/stylesheets/base.sass
index 3035fd64c..83d92076c 100644
--- a/app/assets/stylesheets/base.sass
+++ b/app/assets/stylesheets/base.sass
@@ -13,3 +13,6 @@
// Select2
@import 'select2'
@import 'select2-bootstrap'
+
+// OL3
+@import 'OpenLayers/ol'
diff --git a/app/assets/stylesheets/components/_buttons.sass b/app/assets/stylesheets/components/_buttons.sass
index fd3561dc8..a59699383 100644
--- a/app/assets/stylesheets/components/_buttons.sass
+++ b/app/assets/stylesheets/components/_buttons.sass
@@ -181,6 +181,7 @@ table, .table
right: auto
&:last-child
- > .th > .btn-group .dropdown-menu
- left: auto
- right: 0
+ &:not(:first-child)
+ > .th > .btn-group .dropdown-menu
+ left: auto
+ right: 0
diff --git a/app/assets/stylesheets/components/_forms.sass b/app/assets/stylesheets/components/_forms.sass
index 46f40291a..7a5323011 100644
--- a/app/assets/stylesheets/components/_forms.sass
+++ b/app/assets/stylesheets/components/_forms.sass
@@ -337,7 +337,7 @@ table, .table
+ .switch-label
position: relative
display: inline-block
- width: 50px
+ width: 100% /* 50px */
height: 30px
padding-left: 60px
line-height: 30px
diff --git a/app/assets/stylesheets/components/_olMap.sass b/app/assets/stylesheets/components/_olMap.sass
index acbbbeade..9aaad78dc 100644
--- a/app/assets/stylesheets/components/_olMap.sass
+++ b/app/assets/stylesheets/components/_olMap.sass
@@ -35,30 +35,3 @@
.map
height: 300px
width: 100%
-
-.ol-scale-line
- // background-color: rgba($blue, 0.5)
- bottom: 5px
- right: 5px
- padding: 3px
- position: absolute
-
- .ol-scale-line-inner
- position: relative
- border-bottom: 1px solid $darkgrey
- border-top: none
- color: $blue
- font-size: 0.85em
- text-align: center
- font-weight: 700
-
- &:before
- content: ''
- display: block
- position: absolute
- left: 0
- bottom: 0
- right: 0
- height: 5px
- border-left: 1px solid $darkgrey
- border-right: 1px solid $darkgrey
diff --git a/app/assets/stylesheets/components/_select2.sass b/app/assets/stylesheets/components/_select2.sass
index cbb3a80da..960e8b10b 100644
--- a/app/assets/stylesheets/components/_select2.sass
+++ b/app/assets/stylesheets/components/_select2.sass
@@ -2,9 +2,15 @@
// Select2 Customisation //
//-----------------------//
+// Dirty hotfix for select2 i18n not working properly
+// .select2-results__options
+// .select2-results__message, .loading-results
+// display: none
+
.select2-selection__placeholder
color: rgba($grey, 0.65)
font-style: italic
+ padding: 0 6px
// With Font Awesome adjusts.
.select2-selection__rendered
@@ -66,3 +72,10 @@
.select2-container--bootstrap .select2-selection
border-color: rgba($grey, 0.3)
+
+// Tags
+.form-filter
+ .form-group.select2ed
+ .form-control.tags + .select2-container--bootstrap
+ input.select2-search__field
+ padding: 0 6px
diff --git a/app/assets/stylesheets/components/_tables.sass b/app/assets/stylesheets/components/_tables.sass
index bc04b49e3..0cd91a1a8 100644
--- a/app/assets/stylesheets/components/_tables.sass
+++ b/app/assets/stylesheets/components/_tables.sass
@@ -218,8 +218,9 @@
vertical-align: top
overflow: auto
white-space: nowrap
- border-right: 1px solid rgba($grey, 0.5)
+ // border-right: 1px solid rgba($grey, 0.5)
max-width: 100%
+ min-width: 280px
padding-right: 1px
.t2e-item
@@ -231,20 +232,13 @@
&:first-child
border-left: none
+ &:last-child
+ border-right: 1px solid rgba($grey, 0.5)
.th
> *:first-child
padding-right: 30px
- .td
- > div
- // > .has_radio
- // top: 50%
- // margin-top: -10px
- //
- // &.headlined > .has_radio
- // margin-top: calc((1.4em + 6px) * -1)
-
.th + .td, .td:first-child
> .headlined
[data-headline]
diff --git a/app/assets/stylesheets/modules/_routes_stopoints.sass b/app/assets/stylesheets/modules/_routes_stopoints.sass
index 88e662849..fd62cee2a 100644
--- a/app/assets/stylesheets/modules/_routes_stopoints.sass
+++ b/app/assets/stylesheets/modules/_routes_stopoints.sass
@@ -48,7 +48,7 @@
+ .map_container
> .map_metas
position: relative
- padding-left: 25px
+ padding-left: 30px
&:before
content: ''
@@ -60,7 +60,7 @@
z-index: 3
top: 0
bottom: 0
- left: 5px
+ left: 10px
&:last-child > .wrapper:last-child > div:first-child
span:after
diff --git a/app/assets/stylesheets/modules/_vj_collection.sass b/app/assets/stylesheets/modules/_vj_collection.sass
index 8ff983310..56769e52b 100644
--- a/app/assets/stylesheets/modules/_vj_collection.sass
+++ b/app/assets/stylesheets/modules/_vj_collection.sass
@@ -105,6 +105,13 @@
.t2e-item
position: relative
+ .th .vj_tt
+ display: inline-block
+ vertical-align: top
+
+ + .vj_tt
+ margin-left: 5px
+
&.has-error
&:before
content: ''
diff --git a/app/controllers/autocomplete_calendars_controller.rb b/app/controllers/autocomplete_calendars_controller.rb
new file mode 100644
index 000000000..dbdd1a9fc
--- /dev/null
+++ b/app/controllers/autocomplete_calendars_controller.rb
@@ -0,0 +1,7 @@
+class AutocompleteCalendarsController < ApplicationController
+ respond_to :json, :only => [:autocomplete]
+
+ def autocomplete
+ @calendars = Calendar.search(params[:q]).result.paginate(page: params[:page])
+ end
+end
diff --git a/app/controllers/time_table_combinations_controller.rb b/app/controllers/time_table_combinations_controller.rb
index ebae9f225..bbb262247 100644
--- a/app/controllers/time_table_combinations_controller.rb
+++ b/app/controllers/time_table_combinations_controller.rb
@@ -1,46 +1,26 @@
class TimeTableCombinationsController < ChouetteController
- respond_to :js, :only => [:new,:create]
-
belongs_to :referential do
- belongs_to :time_table, :parent_class => Chouette::TimeTable
- end
- after_filter :clean_flash
-
- def clean_flash
- # only run this in case it's an Ajax request.
- return unless request.xhr?
- flash.discard
+ belongs_to :time_table, :parent_class => Chouette::TimeTable
end
def new
- @time_table_combination = TimeTableCombination.new(:source_id => parent.id)
- render :action => :new
+ @combination = TimeTableCombination.new(source_id: parent.id)
end
-
def create
- Rails.logger.warn( params.inspect)
- @time_table_combination = TimeTableCombination.new( params[:time_table_combination].merge( :source_id => parent.id))
- Rails.logger.warn( @time_table_combination.inspect)
- @year = params[:year] ? params[:year].to_i : Date.today.cwyear
- if @time_table_combination.valid?
- begin
- @time_table = @time_table_combination.combine
- flash[:notice] = t('time_table_combinations.success')
- render "create_success"
- rescue => e
- Rails.logger.error( "TimeTableCombination error, @time_table_combination=#{@time_table_combination.inspect}")
- Rails.logger.error( e.inspect)
- flash[:error] = t('time_table_combinations.failure')
- render "create_failure"
- end
- else
- render "create_failure"
- end
-
+ @combination = TimeTableCombination.new(params[:time_table_combination].merge(source_id: parent.id))
+ @combination.valid? ? perform_combination : render(:new)
end
- protected
- alias_method :time_table_combination, :resource
-
+ def perform_combination
+ begin
+ @time_table = @combination.combine
+ flash[:notice] = t('time_table_combinations.success')
+ redirect_to referential_time_table_path(referential, @time_table)
+ rescue => e
+ flash[:notice] = e.message
+ flash[:error] = t('time_table_combinations.failure')
+ render :new
+ end
+ end
end
diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb
index 8436dc020..dcf8f3e5e 100644
--- a/app/controllers/time_tables_controller.rb
+++ b/app/controllers/time_tables_controller.rb
@@ -95,6 +95,15 @@ class TimeTablesController < ChouetteController
render :new
end
+ def actualize
+ @time_table = resource
+ if @time_table.calendar
+ @time_table.actualize
+ flash[:notice] = t('.success')
+ end
+ redirect_to referential_time_table_path @referential, @time_table
+ end
+
def tags
@tags = ActsAsTaggableOn::Tag.where("tags.name LIKE ?", "%#{params[:tag]}%")
respond_to do |format|
@@ -112,8 +121,8 @@ class TimeTablesController < ChouetteController
scope = select_time_tables.tagged_with(tags, :wild => true, :any => true) if tags.any?
end
scope = ransack_periode(scope)
-
@q = scope.search(params[:q])
+
if sort_column && sort_direction
@time_tables ||= @q.result(:distinct => true).order("#{sort_column} #{sort_direction}")
else
@@ -139,24 +148,29 @@ class TimeTablesController < ChouetteController
end
private
- # Fake ransack filter
def ransack_periode scope
return scope unless params[:q]
- periode = params[:q]
- return scope if periode['end_date_lteq(1i)'].empty? || periode['start_date_gteq(1i)'].empty?
+ return scope unless params[:q]['end_date_lteq(1i)'].present?
- begin_range = Date.civil(periode["start_date_gteq(1i)"].to_i, periode["start_date_gteq(2i)"].to_i, periode["start_date_gteq(3i)"].to_i)
- end_range = Date.civil(periode["end_date_lteq(1i)"].to_i, periode["end_date_lteq(2i)"].to_i, periode["end_date_lteq(3i)"].to_i)
+ begin_range = flatten_date('start_date_gteq')
+ end_range = flatten_date('end_date_lteq')
if begin_range > end_range
flash.now[:error] = t('referentials.errors.validity_period')
else
+ scope = scope.overlapping(begin_range, end_range)
+ params[:q] = params[:q].slice('comment_cont', 'color_cont_any')
@begin_range = begin_range
@end_range = end_range
end
scope
end
+ def flatten_date key
+ date_int = %w(1 2 3).map {|e| params[:q]["#{key}(#{e}i)"].to_i }
+ Date.new(*date_int)
+ end
+
def sort_column
referential.time_tables.column_names.include?(params[:sort]) ? params[:sort] : 'comment'
end
diff --git a/app/controllers/vehicle_journeys_controller.rb b/app/controllers/vehicle_journeys_controller.rb
index cca75af5b..71787ba78 100644
--- a/app/controllers/vehicle_journeys_controller.rb
+++ b/app/controllers/vehicle_journeys_controller.rb
@@ -3,7 +3,7 @@ class VehicleJourneysController < ChouetteController
before_action :user_permissions, only: :index
respond_to :json, :only => :index
- respond_to :js, :only => [:select_journey_pattern, :edit, :new, :index]
+ respond_to :js, :only => [:select_journey_pattern, :select_vehicle_journey, :edit, :new, :index]
belongs_to :referential do
belongs_to :line, :parent_class => Chouette::Line do
@@ -18,12 +18,17 @@ class VehicleJourneysController < ChouetteController
def select_journey_pattern
if params[:journey_pattern_id]
- selected_journey_pattern = Chouette::JourneyPattern.find( params[:journey_pattern_id])
+ selected_journey_pattern = Chouette::JourneyPattern.find(params[:journey_pattern_id])
@vehicle_journey = vehicle_journey
@vehicle_journey.update_journey_pattern(selected_journey_pattern)
end
end
+ def select_vehicle_journey
+ if params[:vehicle_journey_objectid]
+ @vehicle_journey = Chouette::VehicleJourney.find(params[:vehicle_journey_objectid])
+ end
+ end
def create
create!(:alert => t('activerecord.errors.models.vehicle_journey.invalid_times'))
@@ -78,11 +83,10 @@ class VehicleJourneysController < ChouetteController
protected
def collection
scope = route.vehicle_journeys.with_stops
- @q = scope.search filtered_ransack_params
+ scope = maybe_filter_by_departure_time(scope)
+ scope = maybe_filter_out_journeys_with_time_tables(scope)
- # Fixme 3358
- # grouping = ransack_periode_filter
- # @q.build_grouping(grouping) if grouping
+ @q = scope.search filtered_ransack_params
@ppage = 20
@vehicle_journeys = @q.result.paginate(:page => params[:page], :per_page => @ppage)
@@ -91,17 +95,29 @@ class VehicleJourneysController < ChouetteController
@vehicle_journeys
end
- def ransack_periode_filter
- if params[:q] && params[:q][:vehicle_journey_at_stops_departure_time_gteq]
- between = [:departure_time_gteq, :departure_time_lteq].map do |filter|
- "2000-01-01 #{params[:q]["vehicle_journey_at_stops_#{filter}"]}:00 UTC"
- end
- {
- :m => 'or',
- :vehicle_journey_at_stops_departure_time_between => between.join(' to '),
- :vehicle_journey_at_stops_id_null => params[:q][:vehicle_journey_without_departure_time]
- }
+ def maybe_filter_by_departure_time(scope)
+ if params[:q] &&
+ params[:q][:vehicle_journey_at_stops_departure_time_gteq] &&
+ params[:q][:vehicle_journey_at_stops_departure_time_lteq]
+ scope = scope.where_departure_time_between(
+ params[:q][:vehicle_journey_at_stops_departure_time_gteq],
+ params[:q][:vehicle_journey_at_stops_departure_time_lteq],
+ allow_empty:
+ params[:q][:vehicle_journey_without_departure_time] == 'true'
+ )
end
+
+ scope
+ end
+
+ def maybe_filter_out_journeys_with_time_tables(scope)
+ if params[:q] &&
+ params[:q][:vehicle_journey_without_time_table] == 'true'
+ return scope
+ .without_time_tables
+ end
+
+ scope
end
def filtered_ransack_params
@@ -140,14 +156,28 @@ class VehicleJourneysController < ChouetteController
private
def vehicle_journey_params
- params.require(:vehicle_journey).permit( { footnote_ids: [] } , :journey_pattern_id, :number, :published_journey_name,
- :published_journey_identifier, :comment, :transport_mode,
- :mobility_restricted_suitability, :flexible_service, :status_value,
- :facility, :vehicle_type_identifier, :objectid, :time_table_tokens,
- { date: [ :hour, :minute ] }, :button, :referential_id, :line_id,
- :route_id, :id, { vehicle_journey_at_stops_attributes: [ :arrival_time,
- :id, :_destroy,
- :stop_point_id,
- :departure_time] } )
+ params.require(:vehicle_journey).permit(
+ { footnote_ids: [] },
+ :journey_pattern_id,
+ :number,
+ :published_journey_name,
+ :published_journey_identifier,
+ :comment,
+ :transport_mode,
+ :mobility_restricted_suitability,
+ :flexible_service,
+ :status_value,
+ :facility,
+ :vehicle_type_identifier,
+ :objectid,
+ :time_table_tokens,
+ { date: [:hour, :minute] },
+ :button,
+ :referential_id,
+ :line_id,
+ :route_id,
+ :id,
+ { vehicle_journey_at_stops_attributes: [:arrival_time, :id, :_destroy, :stop_point_id, :departure_time] }
+ )
end
end
diff --git a/app/helpers/newapplication_helper.rb b/app/helpers/newapplication_helper.rb
index f03228d73..e189199a2 100644
--- a/app/helpers/newapplication_helper.rb
+++ b/app/helpers/newapplication_helper.rb
@@ -160,7 +160,7 @@ module NewapplicationHelper
end.join.html_safe
end
- content_tag :div, trigger + menu, class: 'btn-group'
+ # content_tag :div, trigger + menu, class: 'btn-group'
end
diff --git a/app/models/calendar.rb b/app/models/calendar.rb
index 91a17e853..39e0d6d49 100644
--- a/app/models/calendar.rb
+++ b/app/models/calendar.rb
@@ -19,6 +19,17 @@ class Calendar < ActiveRecord::Base
[:contains_date]
end
+ def convert_to_time_table
+ Chouette::TimeTable.new.tap do |tt|
+ self.dates.each do |d|
+ tt.dates << Chouette::TimeTableDate.new(date: d, in_out: true)
+ end
+ self.date_ranges.each do |p|
+ tt.periods << Chouette::TimeTablePeriod.new(period_start: p.begin, period_end: p.end)
+ end
+ end
+ end
+
class Period
include ActiveAttr::Model
diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb
index 60684411a..eacc5c827 100644
--- a/app/models/chouette/time_table.rb
+++ b/app/models/chouette/time_table.rb
@@ -20,6 +20,10 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
belongs_to :calendar
belongs_to :created_from, class_name: 'Chouette::TimeTable'
+ scope :overlapping, -> (date_start, date_end) do
+ joins(:periods).where('(period_start, period_end) OVERLAPS (?, ?)', date_start, date_end)
+ end
+
after_save :save_shortcuts
def self.object_id_key
@@ -130,6 +134,12 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
[Chouette::TimeTable.maximum(:end_date)].compact.max
end
+ def actualize
+ self.dates.clear
+ self.periods.clear
+ self.merge! self.calendar.convert_to_time_table
+ end
+
def month_inspect(date)
(date.beginning_of_month..date.end_of_month).map do |d|
{
@@ -278,6 +288,10 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
[bounding_min, bounding_max].compact
end
+ def display_day_types
+ %w(monday tuesday wednesday thursday friday saturday sunday).select{ |d| self.send(d) }.map{ |d| self.human_attribute_name(d).first(2)}.join('')
+ end
+
def day_by_mask(flag)
int_day_types & flag == flag
end
@@ -513,6 +527,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
self.dates.to_a.sort! { |a,b| a.date <=> b.date}
self.save!
end
+ self.convert_continuous_dates_to_periods
end
# remove dates form tt which aren't in another_tt
@@ -528,6 +543,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
self.dates.to_a.sort! { |a,b| a.date <=> b.date}
self.save!
end
+ self.convert_continuous_dates_to_periods
end
@@ -546,6 +562,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
self.periods.to_a.sort! { |a,b| a.period_start <=> b.period_start}
self.save!
end
+ self.convert_continuous_dates_to_periods
end
def duplicate
diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb
index 297e462f0..d20a3d315 100644
--- a/app/models/chouette/vehicle_journey.rb
+++ b/app/models/chouette/vehicle_journey.rb
@@ -51,9 +51,7 @@ module Chouette
at_stops = self.vehicle_journey_at_stops.to_a.dup
(route.stop_points.map(&:id) - at_stops.map(&:stop_point_id)).each do |id|
# Set stop_point id for fake vjas with no departure time yep.
- params = {}
- params[:stop_point_id] = id if journey_pattern.stop_points.map(&:id).include?(id)
- at_stops.insert(route.stop_points.map(&:id).index(id), Chouette::VehicleJourneyAtStop.new(params))
+ at_stops.insert(route.stop_points.map(&:id).index(id), Chouette::VehicleJourneyAtStop.new(stop_point_id: id))
end
at_stops
end
@@ -219,7 +217,51 @@ module Chouette
AND "vehicle_journey_at_stops"."stop_point_id" =
"journey_patterns"."departure_stop_point_id"
')
- .order("vehicle_journey_at_stops.departure_time")
+ .order('"vehicle_journey_at_stops"."departure_time"')
+ end
+
+ # Requires a SELECT DISTINCT and a join with
+ # "vehicle_journey_at_stops".
+ #
+ # Example:
+ # .select('DISTINCT "vehicle_journeys".*')
+ # .joins('
+ # LEFT JOIN "vehicle_journey_at_stops"
+ # ON "vehicle_journey_at_stops"."vehicle_journey_id" =
+ # "vehicle_journeys"."id"
+ # ')
+ # .where_departure_time_between('08:00', '09:45')
+ def self.where_departure_time_between(
+ start_time,
+ end_time,
+ allow_empty: false
+ )
+ self
+ .where(
+ %Q(
+ "vehicle_journey_at_stops"."departure_time" >= ?
+ AND "vehicle_journey_at_stops"."departure_time" < ?
+ #{
+ if allow_empty
+ 'OR "vehicle_journey_at_stops"."id" IS NULL'
+ end
+ }
+ ),
+ "2000-01-01 #{start_time}:00 UTC",
+ "2000-01-01 #{end_time}:00 UTC"
+ )
+ end
+
+ def self.without_time_tables
+ # Joins the VehicleJourney–TimeTable through table to select only those
+ # VehicleJourneys that don't have an associated TimeTable.
+ self
+ .joins('
+ LEFT JOIN "time_tables_vehicle_journeys"
+ ON "time_tables_vehicle_journeys"."vehicle_journey_id" =
+ "vehicle_journeys"."id"
+ ')
+ .where('"time_tables_vehicle_journeys"."vehicle_journey_id" IS NULL')
end
end
diff --git a/app/models/time_table_combination.rb b/app/models/time_table_combination.rb
index 519c02f2b..9b5111014 100644
--- a/app/models/time_table_combination.rb
+++ b/app/models/time_table_combination.rb
@@ -1,42 +1,61 @@
class TimeTableCombination
+
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
- attr_accessor :source_id, :combined_id, :operation
+ attr_accessor :source_id, :combined_type, :operation, :time_table_id, :calendar_id
+
+ validates_presence_of :source_id, :combined_type, :operation
+
+ validates :time_table_id, presence: true, if: "calendar_id.blank?"
+ validates :calendar_id, presence: true, if: "time_table_id.blank?"
- validates_presence_of :source_id, :combined_id, :operation
- validates_inclusion_of :operation, :in => %w( union intersection disjunction), :allow_nil => true
+ validates_inclusion_of :combined_type, :in => %w(time_table calendar)
+ validates_inclusion_of :operation, :in => %w(union intersection disjunction), :allow_nil => true
def clean
- self.source_id = nil
- self.combined_id = nil
- self.operation = nil
+ self.source_id = nil
+ self.time_table_id = nil
+ self.calendar_id = nil
+ self.combined_type = nil
+ self.operation = nil
self.errors.clear
end
def self.operations
- %w( union intersection disjunction)
+ %w(union intersection disjunction)
end
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
+ self.combined_type = "time_table"
end
def persisted?
false
end
+ def target
+ id = self.send("#{combined_type}_id")
+ klass = combined_type == 'calendar' ? Calendar : Chouette::TimeTable
+ target = klass.find id
+ target = target.convert_to_time_table unless target.is_a? Chouette::TimeTable
+ target
+ end
+
def combine
- source = Chouette::TimeTable.find( source_id)
- combined = Chouette::TimeTable.find( combined_id)
- if operation == "union"
+ source = Chouette::TimeTable.find source_id
+ combined = self.target
+
+ case operation
+ when 'union'
source.merge! combined
- elsif operation == "intersection"
+ when 'intersection'
source.intersect! combined
- elsif operation == "disjunction"
+ when 'disjunction'
source.disjoin! combined
else
raise "unknown operation"
diff --git a/app/policies/time_table_policy.rb b/app/policies/time_table_policy.rb
index 6ca02f451..82e4ca194 100644
--- a/app/policies/time_table_policy.rb
+++ b/app/policies/time_table_policy.rb
@@ -17,6 +17,10 @@ class TimeTablePolicy < ApplicationPolicy
organisation_match? && user.has_permission?('time_tables.destroy')
end
+ def duplicate?
+ organisation_match? && create?
+ end
+
def update? ; edit? end
def new? ; create? end
end
diff --git a/app/views/access_link_pairs/_access_link_pair.html.slim b/app/views/access_link_pairs/_access_link_pair.html.slim
index c313f9044..3eebfd7f6 100644
--- a/app/views/access_link_pairs/_access_link_pair.html.slim
+++ b/app/views/access_link_pairs/_access_link_pair.html.slim
@@ -1,4 +1,5 @@
tr
+ - require 'pry'; binding.pry
td
.link
.access_point
diff --git a/app/views/autocomplete_calendars/autocomplete.rabl b/app/views/autocomplete_calendars/autocomplete.rabl
new file mode 100644
index 000000000..9aba2c37b
--- /dev/null
+++ b/app/views/autocomplete_calendars/autocomplete.rabl
@@ -0,0 +1,5 @@
+collection @calendars, :object_root => false
+attribute :id, :name, :short_name, :shared
+node :text do |cal|
+ "#{cal.id} - #{cal.name}"
+end
diff --git a/app/views/autocomplete_time_tables/index.rabl b/app/views/autocomplete_time_tables/index.rabl
index 8ec7b314e..80e3f8684 100644
--- a/app/views/autocomplete_time_tables/index.rabl
+++ b/app/views/autocomplete_time_tables/index.rabl
@@ -1,10 +1,15 @@
collection @time_tables, :object_root => false
node do |time_table|
- { :id => time_table.id, :comment => time_table.comment, :objectid => time_table.objectid,
+ {
+ :id => time_table.id, :comment => time_table.comment, :objectid => time_table.objectid,
:time_table_bounding => time_table.presenter.time_table_bounding,
:composition_info => time_table.presenter.composition_info,
:tags => time_table.tags.join(','),
- :day_types => %w(monday tuesday wednesday thursday friday saturday sunday).select{ |d| time_table.send(d) }.map{ |d| time_table.human_attribute_name(d).first(2)}.join('')}
+ :text => "#{time_table.comment} - #{time_table.display_day_types} - #{time_table.objectid.parts.try(:third)}",
+ :color => time_table.color,
+ :day_types => time_table.display_day_types,
+ :short_id => time_table.objectid.parts.try(:third)
+ }
end
diff --git a/app/views/group_of_lines/_group_of_line.html.slim b/app/views/group_of_lines/_group_of_line.html.slim
index fb9f95894..e33201f74 100644
--- a/app/views/group_of_lines/_group_of_line.html.slim
+++ b/app/views/group_of_lines/_group_of_line.html.slim
@@ -2,11 +2,11 @@
.panel-heading
.panel-title.clearfix
span.pull-right
- - if edit && policy(group_of_line).update?
- = link_to edit_line_referential_group_of_line_path(@line_referential, group_of_line), class: 'btn btn-default btn-sm' do
- span.fa.fa-pencil
- - if delete && policy(group_of_line).destroy?
- = link_to('<span class="fa fa-trash-o"></span>'.html_safe, line_referential_group_of_line_path(@line_referential, group_of_line), :method => :delete, :data => {:confirm => t('group_of_lines.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm')
+ / - if edit && policy(group_of_line).update?
+ = link_to edit_line_referential_group_of_line_path(@line_referential, group_of_line), class: 'btn btn-default btn-sm' do
+ span.fa.fa-pencil
+ / - if delete && policy(group_of_line).destroy?
+ = link_to('<span class="fa fa-trash-o"></span>'.html_safe, line_referential_group_of_line_path(@line_referential, group_of_line), :method => :delete, :data => {:confirm => t('group_of_lines.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm')
h5
= link_to [@line_referential, group_of_line], :class => "preview", :title => "#{Chouette::GroupOfLine.model_name.human.capitalize} #{group_of_line.name}" do
diff --git a/app/views/referential_lines/_filters.html.slim b/app/views/referential_lines/_filters.html.slim
new file mode 100644
index 000000000..aa355884b
--- /dev/null
+++ b/app/views/referential_lines/_filters.html.slim
@@ -0,0 +1,16 @@
+= search_form_for @q, url: referential_line_path(@referential, @line), class: 'form form-filter' do |f|
+ .ffg-row
+ .input-group.search_bar
+ = f.search_field :name_or_objectid_cont, class: 'form-control', placeholder: "Indiquez un nom d'itinéraire ou un OiD..."
+ span.input-group-btn
+ button.btn.btn-default#search-btn type='submit'
+ span.fa.fa-search
+
+ .ffg-row
+ .form-group.togglable
+ = f.label Chouette::Route.human_attribute_name(:wayback), required: false, class: 'control-label'
+ = f.input :wayback_eq_any, as: :checkboxes, class: 'form-control', collection: Chouette::Route.wayback.values, as: :check_boxes, label: false, required: false, wrapper_html: { class: 'checkbox_list'}, label_method: lambda{|l| ("<span>" + t("enumerize.route.wayback.#{l}") + "</span>").html_safe}
+
+ .actions
+ = link_to 'Effacer', referential_line_path(@referential, @line), class: 'btn btn-link'
+ = f.submit 'Filtrer', class: 'btn btn-default'
diff --git a/app/views/referential_lines/show.html.slim b/app/views/referential_lines/show.html.slim
index b60342f19..1e24f0f15 100644
--- a/app/views/referential_lines/show.html.slim
+++ b/app/views/referential_lines/show.html.slim
@@ -49,13 +49,7 @@
- if params[:q].present? or @routes.any?
.row
.col-lg-12
- = search_form_for @q, url: referential_line_path(@referential, @line), class: 'form form-filter' do |f|
- .input-group.search_bar
- = f.search_field :name_cont, class: 'form-control', placeholder: "Indiquez un nom d'itinéraire..."
-
- span.input-group-btn
- button.btn.btn-default type='submit'
- span.fa.fa-search
+ = render 'filters'
- if @routes.any?
.row
diff --git a/app/views/routes/show.html.slim b/app/views/routes/show.html.slim
index 7ab628690..d994e3861 100644
--- a/app/views/routes/show.html.slim
+++ b/app/views/routes/show.html.slim
@@ -8,7 +8,8 @@
/ Below is secundary actions & optional contents (filters, ...)
.row.mb-sm
.col-lg-12.text-right
- = link_to t('journey_patterns.index.title'), [@referential, @line, @route, :journey_patterns_collection], data: {turbolinks: false}, class: 'btn btn-primary'
+ - if @route_sp.any?
+ = link_to t('journey_patterns.index.title'), [@referential, @line, @route, :journey_patterns_collection], data: {turbolinks: false}, class: 'btn btn-primary'
- if @route.journey_patterns.present?
= link_to t('vehicle_journeys.actions.index'), [@referential, @line, @route, :vehicle_journeys], data: {turbolinks: false}, class: 'btn btn-primary'
@@ -19,7 +20,7 @@
span.fa.fa-trash
span = t('actions.destroy')
-/ PägeContent
+/ PageContent
.page_content
.container-fluid
.row
@@ -30,6 +31,10 @@
@route.human_attribute_name(:wayback) => (@route.wayback ? @route.wayback_text : '-' ),
@route.human_attribute_name(:opposite_route) => (@route.opposite_route ? @route.opposite_route.name : '-') }
+ - if @route_sp.any?
+ .col-lg-6.col-md-6.col-sm-12.col-xs-12
+ #route_map.map.mb-lg
+
.row
.col-lg-12
- if @route_sp.any?
@@ -48,3 +53,7 @@
- else
= replacement_msg t('stop_areas.search_no_results')
+
+= javascript_tag do
+ | window.route = "#{URI.escape(route_json_for_edit(@route))}"
+= javascript_include_tag 'es6_browserified/itineraries/show.js'
diff --git a/app/views/time_table_combinations/_combine.html.slim b/app/views/time_table_combinations/_combine.html.slim
deleted file mode 100644
index a2e9a9c6e..000000000
--- a/app/views/time_table_combinations/_combine.html.slim
+++ /dev/null
@@ -1,12 +0,0 @@
-#modal_combine.modal.fade tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"
- .modal-dialog
- .modal-content
- .modal-header
- button.close type="button" data-dismiss="modal"
- span aria-hidden="true" &times;
- span.sr-only Close
-
- h4.modal-title id="myModalLabel"
- = t('time_tables.show.combine_form')
-
- == render "time_table_combinations/combine_form" \ No newline at end of file
diff --git a/app/views/time_table_combinations/_combine_form.html.slim b/app/views/time_table_combinations/_combine_form.html.slim
deleted file mode 100644
index 2367cd4af..000000000
--- a/app/views/time_table_combinations/_combine_form.html.slim
+++ /dev/null
@@ -1,11 +0,0 @@
-= semantic_form_for [@referential, @time_table, @time_table_combination], :remote => true do |form|
- .modal-body
- == render "shared/flash_messages"
-
- = form.inputs do
- = form.input :operation, as: :radio, :collection => Hash[TimeTableCombination.operations.map {|b| [t( b, :scope => "time_table_combinations.operations"),b]}]
- = form.input :combined_id, :label => t('.time_tables'), as: :search_time_table, :json => referential_autocomplete_time_tables_path(@referential, :format => :json), :hint_text => t('search_hint'), :no_result_text => t('no_result_text'), :searching_text => t('searching_term'), :tokenLimit => 1
-
- .modal-footer
- = form.actions do
- = form.action :submit, as: :button , :label => t('time_tables.show.combine') \ No newline at end of file
diff --git a/app/views/time_table_combinations/_form.html.slim b/app/views/time_table_combinations/_form.html.slim
new file mode 100644
index 000000000..3716f6713
--- /dev/null
+++ b/app/views/time_table_combinations/_form.html.slim
@@ -0,0 +1,22 @@
+= simple_form_for [@referential, @time_table, @combination], html: {class: 'form-horizontal', id: 'tt_combination_form'}, wrapper: :horizontal_form do |f|
+ .row
+ .col-lg-12
+ .form-group.has_switch
+ = f.label :combined_type, class: 'col-sm-4 control-label required' do
+ = 'Type de calendriers '
+ abbr title='Champ requis' *
+ = f.input :combined_type, as: :boolean, checked_value: 'time_table', unchecked_value: 'calendar', required: false, label: content_tag(:span, t("time_table_combinations.combined_type.#{@combination.combined_type}"), class: 'switch-label', data: { checkedValue: 'Calendriers', uncheckedValue: 'Modèles de calendriers' }), wrapper_html: { class: 'col-sm-8' }
+
+ = f.input :time_table_id, as: :select, input_html: {class: 'tt_combination_target', style: "width: 100%", data: { 'select2-ajax': 'true', term: 'comment_or_objectid_cont', url: referential_autocomplete_time_tables_path(@referential, format: :json)}}, wrapper_html: {class: @combination.combined_type != 'time_table' ? 'hidden' : ''}
+
+ = f.input :calendar_id, as: :select, input_html: { class: 'tt_combination_target', style: "width: 100%", data: { 'select2-ajax': 'true', term: 'name_cont', url: autocomplete_calendars_path}}, wrapper_html: {class: @combination.combined_type != 'calendar' ? 'hidden' : ''}
+
+ .separator
+
+ .row
+ .col-lg-12
+ = f.label :operation, class: 'col-sm-4 control-label'
+ = f.input :operation, as: :radio_buttons, label: false, collection: TimeTableCombination.operations, label_method: lambda{|o| t("time_table_combinations.operations.#{o}")}, wrapper_html: { class: 'col-sm-8' }
+
+
+ = f.button :submit, t('actions.submit'), class: 'btn btn-default formSubmitr', form: 'tt_combination_form'
diff --git a/app/views/time_table_combinations/create_failure.js.slim b/app/views/time_table_combinations/create_failure.js.slim
deleted file mode 100644
index c5b544483..000000000
--- a/app/views/time_table_combinations/create_failure.js.slim
+++ /dev/null
@@ -1,3 +0,0 @@
-| var combine_form_partial = "#{j render 'time_table_combinations/combine_form'}";
-
-| $('#new_time_table_combination').replaceWith(combine_form_partial); \ No newline at end of file
diff --git a/app/views/time_table_combinations/create_success.js.slim b/app/views/time_table_combinations/create_success.js.slim
deleted file mode 100644
index f18eea4bc..000000000
--- a/app/views/time_table_combinations/create_success.js.slim
+++ /dev/null
@@ -1,6 +0,0 @@
-| var combine_form_partial = "#{j render 'time_table_combinations/combine_form'}";
-
-| $('#new_time_table_combination').replaceWith(combine_form_partial);
-
-| var time_table_partial = "#{j render 'time_tables/show_time_table'}";
-| $('#time_table_show').replaceWith(time_table_partial); \ No newline at end of file
diff --git a/app/views/time_table_combinations/new.html.slim b/app/views/time_table_combinations/new.html.slim
new file mode 100644
index 000000000..e49a10bc6
--- /dev/null
+++ b/app/views/time_table_combinations/new.html.slim
@@ -0,0 +1,12 @@
+/ PageHeader
+= pageheader 'map-marker',
+ t('time_tables.show.combine_form'),
+ '',
+ ''
+
+/ PageContent
+.page_content
+ .container-fluid
+ .row
+ .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-10.col-sm-offset-1
+ = render 'form'
diff --git a/app/views/time_table_combinations/new.js.slim b/app/views/time_table_combinations/new.js.slim
deleted file mode 100644
index 749ec04f6..000000000
--- a/app/views/time_table_combinations/new.js.slim
+++ /dev/null
@@ -1,2 +0,0 @@
-| var combine_form_partial = "#{j render 'time_table_combinations/combine_form'}";
-| $('#new_time_table_combination').replaceWith(combine_form_partial); \ No newline at end of file
diff --git a/app/views/time_tables/_filter.html.slim b/app/views/time_tables/_filter.html.slim
index d29c628a9..cee915911 100644
--- a/app/views/time_tables/_filter.html.slim
+++ b/app/views/time_tables/_filter.html.slim
@@ -7,12 +7,13 @@
span.fa.fa-search
.ffg-row
- .form-group.togglable
- = f.label @time_tables.human_attribute_name(:color), required: false, class: 'control-label'
- = f.input :color_cont_any, collection: ["#9B9B9B", "#FFA070", "#C67300", "#7F551B", "#41CCE3", "#09B09C", "#3655D7", "#6321A0", "#E796C6", "#DD2DAA"], as: :check_boxes, label: false, label_method: lambda{|tt| ("<span style='height:19px;'><span class='fa fa-circle' style='position:relative;top:0;margin-top:0;color:" + tt + "'></span></span>").html_safe }, required: false, wrapper_html: { class: 'checkbox_list' }
+ / .form-group.togglable
+ / = f.label @time_tables.human_attribute_name(:color), required: false, class: 'control-label'
+ / = f.input :color_cont_any, collection: ["#9B9B9B", "#FFA070", "#C67300", "#7F551B", "#41CCE3", "#09B09C", "#3655D7", "#6321A0", "#E796C6", "#DD2DAA"], as: :check_boxes, label: false, label_method: lambda{|tt| ("<span style='height:19px;'><span class='fa fa-circle' style='position:relative;top:0;margin-top:0;color:" + tt + "'></span></span>").html_safe }, required: false, wrapper_html: { class: 'checkbox_list' }
- / = f.label @time_tables.human_attribute_name(:tag_search), required: false, class: 'control-label'
- / = f.input :tag_search, as: :tags, collection: Chouette::TimeTable.tags_on(:tags).pluck(:name), label: false, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Indiquez une étiquette...' }, wrapper_html: { class: 'select2ed'}, include_blank: false
+ .form-group
+ = f.label @time_tables.human_attribute_name(:tag_search), required: false, class: 'control-label'
+ = f.input :tag_search, as: :tags, collection: Chouette::TimeTable.tags_on(:tags).pluck(:name), label: false, input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Indiquez une étiquette...' }, wrapper_html: { class: 'select2ed'}, include_blank: false
.form-group.togglable
= f.label @time_tables.human_attribute_name(:bounding_dates), required: false, class: 'control-label'
diff --git a/app/views/time_tables/show.html.slim b/app/views/time_tables/show.html.slim
index 220ac3995..1c5984a7d 100644
--- a/app/views/time_tables/show.html.slim
+++ b/app/views/time_tables/show.html.slim
@@ -11,12 +11,14 @@
.col-lg-12.text-right
/ - if policy(@time_table).create? && @referential.organisation == current_organisation
/ = link_to t('time_tables.actions.new'), new_referential_time_table_path(@referential), class: 'btn btn-primary'
+ - if @time_table.calendar
+ = link_to t('actions.actualize'), actualize_referential_time_table_path(@referential, @time_table), method: :post, class: 'btn btn-primary'
/- if policy(@time_table).create? && @referential.organisation == current_organisation
- = link_to t('actions.combine'), new_referential_time_table_time_table_combination_path(@referential, @time_table), {remote: true, 'data-toggle' => "modal", 'data-target' => '#modal_combine', class: 'btn btn-primary' }
+ = link_to t('actions.combine'), new_referential_time_table_time_table_combination_path(@referential, @time_table), class: 'btn btn-primary'
- - if policy(@time_table).create? && @referential.organisation == current_organisation
- = link_to t('actions.clone'), duplicate_referential_time_table_path(@referential, @time_table), class: 'btn btn-primary'
+ - if policy(@time_table).duplicate?
+ = link_to t('actions.duplicate'), duplicate_referential_time_table_path(@referential, @time_table), class: 'btn btn-primary'
- if policy(@time_table).destroy?
= link_to referential_time_table_path(@referential, @time_table), method: :delete, data: {confirm: t('time_tables.actions.destroy_confirm')}, class: 'btn btn-primary' do
@@ -44,8 +46,3 @@
= link_to '', referential_time_table_path(@referential, @time_table, year: (@year + 1)), class: 'next_page'
= render 'show_time_table'
-
- .row
- .col-lg-12
- / WTF ??!
- = render 'time_table_combinations/combine'
diff --git a/app/views/time_tables/show.rabl b/app/views/time_tables/show.rabl
index a0a799985..53c9daec0 100644
--- a/app/views/time_tables/show.rabl
+++ b/app/views/time_tables/show.rabl
@@ -9,7 +9,8 @@ node do |tt|
current_month: tt.month_inspect(Date.today),
periode_range: month_periode_enum(3),
current_periode_range: Date.today.beginning_of_month,
- color: tt.color ? tt.color : ''
+ color: tt.color ? tt.color : '',
+ short_id: tt.objectid.parts.try(:third)
}
end
diff --git a/app/views/vehicle_journeys/show.rabl b/app/views/vehicle_journeys/show.rabl
index 7db9b531d..1ef9bc6b5 100644
--- a/app/views/vehicle_journeys/show.rabl
+++ b/app/views/vehicle_journeys/show.rabl
@@ -31,7 +31,7 @@ end
child(:vehicle_journey_at_stops_matrix, :object_root => false) do |vehicle_stops|
node do |vehicle_stop|
- node(:dummy) { !vehicle_stop.stop_point_id? }
+ node(:dummy) { !vehicle_stop.id? }
node(:stop_area_object_id) do
vehicle_stop.stop_point ? vehicle_stop.stop_point.stop_area.objectid : nil
end
diff --git a/config/locales/actions.en.yml b/config/locales/actions.en.yml
index 5bfd9d9fb..6e2dd3aa2 100644
--- a/config/locales/actions.en.yml
+++ b/config/locales/actions.en.yml
@@ -13,6 +13,7 @@ en:
clean_up: 'Clean up'
sync: 'Synchronize'
combine: 'Combine'
+ actualize: 'Actualize'
or: "or"
cancel: "Cancel"
search_hint: "Type in a search term"
diff --git a/config/locales/actions.fr.yml b/config/locales/actions.fr.yml
index 94afc1393..8f2fc90f8 100644
--- a/config/locales/actions.fr.yml
+++ b/config/locales/actions.fr.yml
@@ -14,6 +14,7 @@ fr:
clean_up: 'Purger'
sync: 'Synchroniser'
combine: 'Combiner'
+ actualize: 'Actualiser'
or: "ou"
cancel: "Annuler"
search_hint: "Entrez un texte à rechercher"
diff --git a/config/locales/time_table_combinations.en.yml b/config/locales/time_table_combinations.en.yml
index e7bf9d90e..142270d13 100644
--- a/config/locales/time_table_combinations.en.yml
+++ b/config/locales/time_table_combinations.en.yml
@@ -2,6 +2,9 @@ en:
time_table_combinations:
success: "operation applied on timetable"
failure: "operation failed on timetable"
+ combined_type:
+ calendar: 'Calendars'
+ time_table: 'Time tables'
operations:
union: "merge"
intersection: "intersect"
@@ -13,3 +16,5 @@ en:
time_table_combination:
combined_id: "Time table id"
operation: "operation"
+ time_table_id: "Search a calendar"
+ calendar_id: "Search a calendar"
diff --git a/config/locales/time_table_combinations.fr.yml b/config/locales/time_table_combinations.fr.yml
index 562c7b58d..5a23cf029 100644
--- a/config/locales/time_table_combinations.fr.yml
+++ b/config/locales/time_table_combinations.fr.yml
@@ -2,14 +2,19 @@ fr:
time_table_combinations:
success: "opération appliquée sur le calendrier"
failure: "opération échouée"
+ combined_type:
+ calendar: 'Modèles de calendriers'
+ time_table: 'Calendriers'
operations:
- union: "ajouter les dates"
- intersection: "conserver les dates communes"
- disjunction: "soustraire les dates"
+ union: "Ajouter les dates"
+ intersection: "Conserver les dates communes"
+ disjunction: "Soustraire les dates"
combine_form:
time_tables: "Calendrier à combiner"
activemodel:
attributes:
time_table_combination:
combined_id: "Id Calendrier"
- operation: "opération"
+ operation: "Type d'opération"
+ time_table_id: "Rechercher un calendrier"
+ calendar_id: "Rechercher un calendrier"
diff --git a/config/locales/time_tables.en.yml b/config/locales/time_tables.en.yml
index 495770987..6c5aac012 100644
--- a/config/locales/time_tables.en.yml
+++ b/config/locales/time_tables.en.yml
@@ -20,6 +20,8 @@ en:
add_period: "Add a period"
add_date: "Add a peculiar date"
add_excluded_date: "Add an excluded date"
+ actualize:
+ success: "Actualize succeded"
new:
title: "Add a new timetable"
edit:
diff --git a/config/locales/time_tables.fr.yml b/config/locales/time_tables.fr.yml
index 812d8cdd2..36a588eb4 100644
--- a/config/locales/time_tables.fr.yml
+++ b/config/locales/time_tables.fr.yml
@@ -20,6 +20,8 @@ fr:
add_period: "Ajouter une période"
add_date: "Ajouter une date particulière"
add_excluded_date: "Ajouter une date exclue"
+ actualize:
+ success: "Actualisation terminée"
new:
title: "Ajouter un calendrier"
duplicate:
@@ -68,7 +70,7 @@ fr:
time_table:
comment: "Nom"
color: "Couleur associée"
- bounding_dates: 'Période de validité englobante'
+ bounding_dates: 'Période contenue dans le calendrier'
version: "Abréviation"
day_types: "Jours d'application des périodes"
none: "aucun"
diff --git a/config/routes.rb b/config/routes.rb
index 8415d49df..f75578106 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -72,7 +72,9 @@ ChouetteIhm::Application.routes.draw do
resources :networks
end
- resources :calendars
+ resources :calendars do
+ get :autocomplete, on: :collection, controller: 'autocomplete_calendars'
+ end
resources :referentials do
resources :api_keys
@@ -118,6 +120,7 @@ ChouetteIhm::Application.routes.draw do
resource :vehicle_journeys_collection, :only => [:show, :update]
resources :vehicle_journeys, :vehicle_journey_frequencies do
get 'select_journey_pattern', :on => :member
+ get 'select_vehicle_journey', :on => :member
resources :vehicle_translations
resources :time_tables
end
@@ -165,6 +168,7 @@ ChouetteIhm::Application.routes.draw do
get :tags
end
member do
+ post 'actualize'
get 'duplicate'
get 'month', defaults: { format: :json }
end
diff --git a/spec/controllers/autocomplete_calendars_controller_spec.rb b/spec/controllers/autocomplete_calendars_controller_spec.rb
new file mode 100644
index 000000000..3ff75fadf
--- /dev/null
+++ b/spec/controllers/autocomplete_calendars_controller_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe AutocompleteCalendarsController, type: :controller do
+
+end
diff --git a/spec/factories/chouette_vehicle_journey.rb b/spec/factories/chouette_vehicle_journey.rb
index 9ba660800..452909f23 100644
--- a/spec/factories/chouette_vehicle_journey.rb
+++ b/spec/factories/chouette_vehicle_journey.rb
@@ -11,13 +11,18 @@ FactoryGirl.define do
end
factory :vehicle_journey do
- after(:create) do |vehicle_journey|
+ transient do
+ stop_arrival_time '01:00:00'
+ stop_departure_time '03:00:00'
+ end
+
+ after(:create) do |vehicle_journey, evaluator|
vehicle_journey.journey_pattern.stop_points.each_with_index do |stop_point, index|
vehicle_journey.vehicle_journey_at_stops << create(:vehicle_journey_at_stop,
:vehicle_journey => vehicle_journey,
:stop_point => stop_point,
- :arrival_time => '2000-01-01 01:00:00 UTC',
- :departure_time => '2000-01-01 03:00:00 UTC')
+ :arrival_time => "2000-01-01 #{evaluator.stop_arrival_time} UTC",
+ :departure_time => "2000-01-01 #{evaluator.stop_departure_time} UTC")
end
end
diff --git a/spec/features/calendars_permissions_spec.rb b/spec/features/calendars_permissions_spec.rb
new file mode 100644
index 000000000..6eb0ea08e
--- /dev/null
+++ b/spec/features/calendars_permissions_spec.rb
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+require 'spec_helper'
+
+describe 'Calendars', type: :feature do
+ login_user
+
+ let(:calendar) { create :calendar, organisation_id: 1 }
+
+ describe 'permissions' do
+ before do
+ allow_any_instance_of(CalendarPolicy).to receive(:edit?).and_return permission
+ allow_any_instance_of(CalendarPolicy).to receive(:destroy?).and_return permission
+ allow_any_instance_of(CalendarPolicy).to receive(:share?).and_return permission
+ visit path
+ end
+
+ context 'on show view' do
+ let( :path ){ calendar_path(calendar) }
+
+ context 'if present → ' do
+ let( :permission ){ true }
+ it 'view shows the corresponding buttons' do
+ expect(page).to have_css('a.btn.btn-default', text: 'Editer')
+ expect(page).to have_css('a.btn.btn-primary', text: 'Supprimer')
+ end
+ end
+
+ context 'if absent → ' do
+ let( :permission ){ false }
+ it 'view does not show the corresponding buttons' do
+ expect(page).not_to have_css('a.btn.btn-default', text: 'Editer')
+ expect(page).not_to have_css('a.btn.btn-primary', text: 'Supprimer')
+ end
+ end
+ end
+
+ context 'on edit view' do
+ let( :path ){ edit_calendar_path(calendar) }
+
+ context 'if present → ' do
+ let( :permission ){ true }
+ it 'view shows the corresponding checkbox' do
+ expect( page ).to have_css('div.has_switch label.boolean[for=calendar_shared]')
+ end
+ end
+
+ context 'if absent → ' do
+ let( :permission ){ false }
+ it 'view does not show the corresponding checkbox' do
+ expect( page ).not_to have_css('div.has_switch label.boolean[for=calendar_shared]')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/group_of_lines_permissions_spec.rb b/spec/features/group_of_lines_permissions_spec.rb
new file mode 100644
index 000000000..5c03481ec
--- /dev/null
+++ b/spec/features/group_of_lines_permissions_spec.rb
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+
+describe "Group of lines", :type => :feature do
+ skip 'delete param of view seems to be constantly false' do
+ login_user
+
+ let(:line) { create(:line_with_stop_areas, :network => network, :company => company) }
+
+ let(:line_referential) { create :line_referential }
+ let(:network) { create(:network) }
+ let(:company) { create(:company) }
+
+ let(:group_of_line) { create :group_of_line, line_referential: line_referential }
+
+ describe 'permissions' do
+ before do
+ group_of_line.lines << line
+ allow_any_instance_of(LinePolicy).to receive(:destroy?).and_return permission
+ visit path
+ end
+
+ context 'on show view' do
+ let( :path ){ line_referential_group_of_line_path(line_referential, group_of_line, delete: true) }
+
+ context 'if permissions present → ' do
+ let( :permission ){ true }
+
+ it 'shows the appropriate buttons' do
+ expected_url = line_referential_line_path(line.line_referential, line)
+ expect( page ).to have_link('Supprimer', href: expected_url)
+ end
+ end
+ context 'if permissions absent → ' do
+ let( :permission ){ false }
+
+ it 'shows the appropriate buttons' do
+ expect( page ).not_to have_link('Supprimer')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/group_of_lines_spec.rb b/spec/features/group_of_lines_spec.rb
index 79500fe33..59101ccd5 100644
--- a/spec/features/group_of_lines_spec.rb
+++ b/spec/features/group_of_lines_spec.rb
@@ -37,7 +37,7 @@ describe "Group of lines", :type => :feature do
describe "show" do
it "displays group of line" do
visit line_referential_group_of_lines_path(line_referential)
- click_link "#{subject.name}"
+ click_link subject.name
expect(page).to have_content(subject.name)
end
diff --git a/spec/features/line_footnotes_permissions_spec.rb b/spec/features/line_footnotes_permissions_spec.rb
new file mode 100644
index 000000000..4de2a6137
--- /dev/null
+++ b/spec/features/line_footnotes_permissions_spec.rb
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+
+describe 'Line Footnotes', type: :feature do
+ login_user
+
+ let!(:line) { create :line_with_stop_areas, network: network, company: company, line_referential: line_referential }
+ let(:referential) { Referential.first }
+ let( :line_referential ){ referential.line_referential }
+ let(:network) { create(:network) }
+ let(:company) { create(:company) }
+
+
+ describe 'permissions' do
+ before do
+ allow_any_instance_of(LinePolicy).to receive(:update_footnote?).and_return permission
+ visit path
+ end
+
+ describe 'on show view' do
+ let( :path ){ referential_line_footnotes_path(line_referential, line) }
+
+ context 'if present → ' do
+ let( :permission ){ true }
+
+ it 'displays the corresponding button' do
+ expect( page ).to have_link('Editer', href: edit_referential_line_footnotes_path(line_referential, line))
+ end
+ end
+
+ context 'if absent → ' do
+ let( :permission ){ false }
+
+ it 'does not display the corresponding button' do
+ expect( page ).not_to have_link('Editer', href: edit_referential_line_footnotes_path(line_referential, line))
+ end
+ end
+ end
+
+ end
+end
diff --git a/spec/features/line_footnotes_spec.rb b/spec/features/line_footnotes_spec.rb
index 0273ee288..4d77cba41 100644
--- a/spec/features/line_footnotes_spec.rb
+++ b/spec/features/line_footnotes_spec.rb
@@ -27,18 +27,6 @@ describe 'Line Footnotes', type: :feature do
expect(page).not_to have_content(I18n.t('actions.add'))
end
- context 'user has permission to edit footnotes' do
- it 'shows edit link for footnotes' do
- expect(page).to have_content(I18n.t('actions.edit'))
- end
- end
-
- context 'user does not have permission to edit footnotes' do
- it 'does not show edit link for footnotes' do
- @user.update_attribute(:permissions, [])
- visit referential_line_footnotes_path(referential.line_referential, line)
- expect(page).not_to have_content(I18n.t('lines.actions.edit_footnotes'))
- end
- end
end
+
end
diff --git a/spec/features/lines_permissions_spec.rb b/spec/features/lines_permissions_spec.rb
new file mode 100644
index 000000000..5d53d6568
--- /dev/null
+++ b/spec/features/lines_permissions_spec.rb
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+
+describe "Lines", :type => :feature do
+ login_user
+
+ let(:line_referential) { create :line_referential }
+
+ let(:network) { create(:network) }
+ let(:company) { create(:company) }
+ let(:line) { create :line_with_stop_areas, network: network, company: company, line_referential: line_referential }
+ context 'permissions' do
+ before do
+ create :group_of_line
+ line_referential.lines << line
+ line_referential.organisations << Organisation.first
+ allow_any_instance_of(LinePolicy).to receive(:create?).and_return permission
+ allow_any_instance_of(LinePolicy).to receive(:destroy?).and_return permission
+ visit path
+ end
+
+ context 'on index view' do
+ let( :path ){ line_referential_lines_path(line_referential) }
+
+ context 'if present → ' do
+ let( :permission ){ true }
+
+ it 'displays the corresponding button' do
+ expected_href = new_line_referential_line_path(line_referential)
+ expect( page ).to have_link('Ajouter une ligne', href: expected_href)
+ end
+ end
+
+ context 'if absent → ' do
+ let( :permission ){ false }
+
+ it 'does not display the corresponding button' do
+ expect( page ).not_to have_link('Ajouter une ligne')
+ end
+ end
+ end
+
+ context 'on show view' do
+ skip 'policies always false' do
+ let( :path ){ line_referential_line_path(line_referential, line) }
+
+ context 'if present → ' do
+ let( :permission ){ true }
+
+ it 'displays the corresponding buttons' do
+ expected_href = new_line_referential_line_path(line_referential)
+ expect( page ).to have_link('Ajouter une ligne', href: expected_href)
+ end
+ end
+
+ context 'if absent → ' do
+ let( :permission ){ false }
+
+ it 'does not display the corresponding button' do
+ expect( page ).not_to have_link('Ajouter une ligne')
+ end
+ end
+ end
+
+ end
+ end
+end
diff --git a/spec/features/referential_lines_permissions_spec.rb b/spec/features/referential_lines_permissions_spec.rb
new file mode 100644
index 000000000..0d156f0d6
--- /dev/null
+++ b/spec/features/referential_lines_permissions_spec.rb
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+
+describe 'ReferentialLines', type: :feature do
+ login_user
+ let!(:referential_metadata) { create :referential_metadata, referential: referential }
+ let( :line ){ referential.lines.first }
+
+ context 'permissions' do
+ before do
+ allow_any_instance_of(RoutePolicy).to receive(:create?).and_return permission
+ visit path
+ end
+
+ context 'on show view' do
+ let( :path ){ referential_line_path(referential, line) }
+
+ context 'if present → ' do
+ let( :permission ){ true }
+ it 'shows the corresponding button' do
+ expected_href = new_referential_line_route_path(referential, line)
+ expect( page ).to have_link("Ajouter un itinéraire", href: expected_href)
+ end
+ end
+ context 'if absent → ' do
+ let( :permission ){ false }
+ it 'does not show the corresponding button' do
+ expect( page ).not_to have_link("Ajouter un itinéraire")
+ end
+ end
+ end
+
+ end
+
+ # describe 'show' do
+ # it 'displays referential line' do
+ # visit referential_line_path(referential, referential.lines.first)
+ # expect(page).to have_content(referential.lines.first.name)
+ # end
+ # it 'displays referential line' do
+ # visit referential_line_path(referential, referential.lines.first, sort: "stop_points")
+ # expect(page).to have_content(referential.lines.first.name)
+ # end
+ # end
+end
diff --git a/spec/features/routes_permissions_spec.rb b/spec/features/routes_permissions_spec.rb
new file mode 100644
index 000000000..36c13b24a
--- /dev/null
+++ b/spec/features/routes_permissions_spec.rb
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+require 'spec_helper'
+
+describe "Routes", :type => :feature do
+ login_user
+
+ let(:line) { create :line }
+ let(:route) { create(:route, :line => line) }
+
+
+ describe 'permissions' do
+ before do
+ @user.update(organisation: referential.organisation)
+ allow_any_instance_of(RoutePolicy).to receive(:edit?).and_return permission
+ allow_any_instance_of(RoutePolicy).to receive(:destroy?).and_return permission
+ visit path
+ end
+
+ describe 'on show view' do
+ let( :path ){ referential_line_route_path(referential, line, route) }
+
+ context 'if present → ' do
+ let( :permission ){ true }
+ it 'view shows the corresponding buttons' do
+ expected_edit_url = edit_referential_line_route_path(referential, line, route)
+ expected_delete_url = referential_line_route_path(referential, line, route)
+ expect( page ).to have_link('Editer', href: expected_edit_url)
+ expect( page ).to have_link('Supprimer', href: expected_delete_url)
+ end
+ end
+
+ context 'if absent → ' do
+ let( :permission ){ false }
+ it 'view does not show the corresponding buttons' do
+ expect( page ).not_to have_link('Editer')
+ expect( page ).not_to have_link('Supprimer')
+ end
+ end
+ end
+
+ end
+end
diff --git a/spec/features/routes_spec.rb b/spec/features/routes_spec.rb
index 4b90a6ec6..6d9ba990d 100644
--- a/spec/features/routes_spec.rb
+++ b/spec/features/routes_spec.rb
@@ -47,6 +47,7 @@ describe "Routes", :type => :feature do
xit "Puts (http) an update request" do
#visit edit_boarding_alighting_referential_line_route_path(referential, line, route)
visit referential_line_route_path(referential, line, route)
+
click_link I18n.t('routes.actions.edit_boarding_alighting')
#select('', :from => '')
# Changes the boarding of the first stop
@@ -61,8 +62,10 @@ describe "Routes", :type => :feature do
before(:each) { visit referential_line_route_path(referential, line, route) }
context 'user has permission to edit journey patterns' do
- it 'shows edit links for journey patterns' do
- expect(page).to have_content(I18n.t('actions.edit'))
+ skip "not sure the spec is correct or the code" do
+ it 'shows edit links for journey patterns' do
+ expect(page).to have_link(I18n.t('actions.edit'), href: edit_referential_line_route_journey_pattern_path(referential, line, route, journey_pattern))
+ end
end
end
@@ -126,12 +129,6 @@ describe "Routes", :type => :feature do
end
end
- context 'user has permission to destroy routes' do
- it 'shows destroy buttons for routes' do
- expect(page).to have_content(I18n.t('actions.edit'))
- end
- end
-
context 'user does not have permission to destroy routes' do
it 'does not show destroy buttons for routes' do
@user.update_attribute(:permissions, [])
diff --git a/spec/features/time_tables_permissions_spec.rb b/spec/features/time_tables_permissions_spec.rb
new file mode 100644
index 000000000..bd94a3aa1
--- /dev/null
+++ b/spec/features/time_tables_permissions_spec.rb
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+require 'spec_helper'
+
+describe "TimeTables", :type => :feature do
+ login_user
+
+ let(:time_table) { create :time_table }
+
+ describe 'permissions' do
+ before do
+ allow_any_instance_of(TimeTablePolicy).to receive(:duplicate?).and_return permission
+ visit path
+ end
+
+ context 'on show' do
+ let(:path){ referential_time_table_path(referential, time_table)}
+
+ context "if permission's absent → " do
+ let(:permission){ false }
+
+ it 'does not show the corresponsing button' do
+ expect(page).not_to have_link('Dupliquer ce calendrier')
+ end
+ end
+
+ context "if permission's present → " do
+ let(:permission){ true }
+
+ it 'shows the corresponsing button' do
+ expected_href = duplicate_referential_time_table_path(referential, time_table)
+ expect(page).to have_link('Dupliquer', href: expected_href)
+ end
+ end
+ end
+
+ end
+
+end
diff --git a/spec/features/workbenches_permissions_spec.rb b/spec/features/workbenches_permissions_spec.rb
new file mode 100644
index 000000000..962ffdedc
--- /dev/null
+++ b/spec/features/workbenches_permissions_spec.rb
@@ -0,0 +1,42 @@
+# coding: utf-8
+
+describe 'Workbenches', type: :feature do
+ login_user
+
+ let(:line_referential) { create :line_referential }
+ let(:workbench) { create :workbench, line_referential: line_referential, organisation: @user.organisation }
+ # let!(:line) { create :line, line_referential: line_referential }
+
+ # let(:referential_metadatas) { Array.new(2) { |i| create :referential_metadata, lines: [line] } }
+
+ describe 'permissions' do
+ before do
+ allow_any_instance_of(ReferentialPolicy).to receive(:create?).and_return permission
+ visit path
+ end
+
+ context 'on show view' do
+ let( :path ){ workbench_path(workbench) }
+
+ context 'if present → ' do
+ let( :permission ){ true }
+
+ it 'shows the corresponding button' do
+ expected_href = new_referential_path(workbench_id: workbench)
+ expect( page ).to have_link('Ajouter', href: expected_href)
+ end
+ end
+
+ context 'if absent → ' do
+ let( :permission ){ false }
+
+ it 'does not show the corresponding button' do
+ expect( page ).not_to have_link('Ajouter')
+ end
+ end
+ # let!(:ready_referential) { create :referential, workbench: workbench, metadatas: referential_metadatas, ready: true, organisation: @user.organisation }
+ # let!(:unready_referential) { create :referential, workbench: workbench }
+
+ end
+ end
+end
diff --git a/spec/features/workbenches_spec.rb b/spec/features/workbenches_spec.rb
index 717be96fa..c11fbd03d 100644
--- a/spec/features/workbenches_spec.rb
+++ b/spec/features/workbenches_spec.rb
@@ -1,5 +1,4 @@
# coding: utf-8
-require 'spec_helper'
describe 'Workbenches', type: :feature do
login_user
diff --git a/spec/javascripts/time_table/actions_spec.js b/spec/javascripts/time_table/actions_spec.js
index 1ab5635a0..9756e797f 100644
--- a/spec/javascripts/time_table/actions_spec.js
+++ b/spec/javascripts/time_table/actions_spec.js
@@ -13,11 +13,12 @@ const day = {
}
describe('actions', () => {
it('should create an action to update dayTypes', () => {
+ let obj = {}
const expectedAction = {
type: 'UPDATE_DAY_TYPES',
- index: 1
+ dayTypes: obj
}
- expect(actions.updateDayTypes(1)).toEqual(expectedAction)
+ expect(actions.updateDayTypes(obj)).toEqual(expectedAction)
})
it('should create an action to update comment', () => {
diff --git a/spec/javascripts/time_table/reducers/metas_spec.js b/spec/javascripts/time_table/reducers/metas_spec.js
index 61e3048db..79dbe1ea3 100644
--- a/spec/javascripts/time_table/reducers/metas_spec.js
+++ b/spec/javascripts/time_table/reducers/metas_spec.js
@@ -24,11 +24,11 @@ describe('metas reducer', () => {
})
it('should handle UPDATE_DAY_TYPES', () => {
- const arr = [false, true, true, true, true, true, true]
+ const arr = [false, false, true, true, true, true, true]
expect(
metasReducer(state, {
type: 'UPDATE_DAY_TYPES',
- index: 0
+ dayTypes: arr
})
).toEqual(Object.assign({}, state, {day_types: arr, calendar: {name: 'Aucun'}}))
})
diff --git a/spec/javascripts/vehicle_journeys/actions_spec.js b/spec/javascripts/vehicle_journeys/actions_spec.js
index 351b8038b..19f65046f 100644
--- a/spec/javascripts/vehicle_journeys/actions_spec.js
+++ b/spec/javascripts/vehicle_journeys/actions_spec.js
@@ -249,11 +249,13 @@ describe('when clicking on delete button next to a timetable inside modal', () =
describe('when clicking on validate button inside calendars modal', () => {
it('should create an action to update vj calendars', () => {
const vehicleJourneys = []
+ const timetables = []
const expectedAction = {
- type: 'EDIT_VEHICLEJOURNEYS_CALENDARS',
- vehicleJourneys
+ type: 'EDIT_VEHICLEJOURNEYS_TIMETABLES',
+ vehicleJourneys,
+ timetables
}
- expect(actions.editVehicleJourneyCalendars(vehicleJourneys)).toEqual(expectedAction)
+ expect(actions.editVehicleJourneyTimetables(vehicleJourneys, timetables)).toEqual(expectedAction)
})
})
describe('when clicking on add button inside calendars modal', () => {
diff --git a/spec/javascripts/vehicle_journeys/reducers/filters_spec.js b/spec/javascripts/vehicle_journeys/reducers/filters_spec.js
index 1dea403cb..2ab88386a 100644
--- a/spec/javascripts/vehicle_journeys/reducers/filters_spec.js
+++ b/spec/javascripts/vehicle_journeys/reducers/filters_spec.js
@@ -28,8 +28,10 @@ describe('filters reducer', () => {
}
},
journeyPattern: {},
+ vehicleJourney: {},
timetable: {},
withoutSchedule: true,
+ withoutTimeTable: false
},
queryString: ''
}
@@ -144,7 +146,16 @@ describe('filters reducer', () => {
})
it('should handle CREATE_QUERY_STRING', () => {
- let strResult = 'q%5Bjourney_pattern_id_eq%5D=undefined&q%5Btime_tables_id_eq%5D=undefined'
+ let strResult = [
+ "q%5Bjourney_pattern_id_eq%5D=undefined",
+ "&q%5Bobjectid_cont%5D=undefined",
+ "&q%5Btime_tables_id_eq%5D=undefined",
+ "&q%5Bvehicle_journey_at_stops_departure_time_gteq%5D=11%3A11",
+ "&q%5Bvehicle_journey_at_stops_departure_time_lteq%5D=22%3A22",
+ "&q%5Bvehicle_journey_without_departure_time%5D=true",
+ "&q%5Bvehicle_journey_without_time_table%5D=false"
+ ].join('')
+
expect(
statusReducer(state, {
type: 'CREATE_QUERY_STRING',
diff --git a/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js b/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js
index 6dc07e9bd..f805852c7 100644
--- a/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js
+++ b/spec/javascripts/vehicle_journeys/reducers/vehicle_journeys_spec.js
@@ -251,15 +251,14 @@ describe('vehicleJourneys reducer', () => {
})
- it('should handle EDIT_VEHICLEJOURNEYS_CALENDARS', () => {
+ it('should handle EDIT_VEHICLEJOURNEYS_TIMETABLES', () => {
let newState = JSON.parse(JSON.stringify(state))
- newState.map((vj, i) =>{
- return Object.assign({}, vj, {time_tables : vj.time_tables[0]})
- })
+ newState[0].time_tables = [fakeTimeTables[0]]
expect(
vjReducer(state, {
- type: 'EDIT_VEHICLEJOURNEYS_CALENDARS',
- vehicleJourneys: newState
+ type: 'EDIT_VEHICLEJOURNEYS_TIMETABLES',
+ vehicleJourneys: state,
+ timetables: [fakeTimeTables[0]]
})
).toEqual(newState)
})
diff --git a/spec/models/calendar_spec.rb b/spec/models/calendar_spec.rb
index 36981961f..33d9676cd 100644
--- a/spec/models/calendar_spec.rb
+++ b/spec/models/calendar_spec.rb
@@ -9,6 +9,18 @@ RSpec.describe Calendar, :type => :model do
it { is_expected.to validate_presence_of(:short_name) }
it { is_expected.to validate_uniqueness_of(:short_name) }
+ describe '#to_time_table' do
+ let(:calendar) { create(:calendar, date_ranges: [Date.today..(Date.today + 1.month)]) }
+
+ it 'should convert calendar to an instance of Chouette::TimeTable' do
+ time_table = calendar.convert_to_time_table
+ expect(time_table).to be_an_instance_of(Chouette::TimeTable)
+ expect(time_table.periods[0].period_start).to eq(calendar.date_ranges[0].begin)
+ expect(time_table.periods[0].period_end).to eq(calendar.date_ranges[0].end)
+ expect(time_table.dates.map(&:date)).to match_array(calendar.dates)
+ end
+ end
+
describe 'validations' do
it 'validates that dates and date_ranges do not overlap' do
calendar = build(:calendar, dates: [Date.today], date_ranges: [Date.today..Date.tomorrow])
@@ -69,7 +81,6 @@ RSpec.describe Calendar, :type => :model do
end
describe 'intersect?' do
-
it 'should detect date in common with other date_ranges' do
november = period(begin: '2016-11-01', end: '2016-11-30')
mid_november_mid_december = period(begin: '2016-11-15', end: '2016-12-15')
@@ -111,7 +122,6 @@ RSpec.describe Calendar, :type => :model do
end
describe 'DateValue' do
-
subject { date_value }
def date_value(attributes = {})
@@ -141,8 +151,6 @@ RSpec.describe Calendar, :type => :model do
end
it { is_expected.to validate_presence_of(:value) }
-
end
-
end
diff --git a/spec/models/chouette/time_table_spec.rb b/spec/models/chouette/time_table_spec.rb
index 1d0fa8585..505ca12be 100644
--- a/spec/models/chouette/time_table_spec.rb
+++ b/spec/models/chouette/time_table_spec.rb
@@ -1198,6 +1198,7 @@ end
expect(subject.dates[2].date).to eq(Date.new(2014,7,20))
end
end
+
context "timetable with dates against timetable with dates and periods all covered" do
before do
subject.periods.clear
@@ -1218,12 +1219,15 @@ end
subject.disjoin! another_tt
subject.reload
end
+
it "should have 0 result periods" do
expect(subject.periods.size).to eq(0)
end
+
it "should have no remained day_types" do
subject.int_day_types == 0
end
+
it "should have 0 dates left" do
expect(subject.dates.size).to eq(0)
end
@@ -1243,12 +1247,15 @@ end
subject.disjoin! another_tt
subject.reload
end
+
it "should have 0 result periods" do
expect(subject.periods.size).to eq(0)
end
+
it "should have 0 day_types" do
expect(subject.int_day_types).to eq(0)
end
+
it "should have 6 dates " do
expect(subject.dates.size).to eq(6)
expect(subject.dates[0].date).to eq(Date.new(2014,8,11))
@@ -1274,24 +1281,26 @@ end
subject.disjoin! another_tt
subject.reload
end
- it "should have 0 result periods" do
- expect(subject.periods.size).to eq(0)
+
+ it "should have 3 result periods" do
+ expect(subject.periods.size).to eq(3)
+ [
+ ['2014-08-11', '2014-08-13'],
+ ['2014-08-18', '2014-08-20'],
+ ['2014-08-25', '2014-08-27']
+ ].each_with_index do |period, index|
+ expect(subject.periods[index].period_start.to_s).to eq(period[0])
+ expect(subject.periods[index].period_end.to_s).to eq(period[1])
+ end
end
+
it "should have 0 day_types" do
expect(subject.int_day_types).to eq(0)
end
- it "should have 10 dates " do
- expect(subject.dates.size).to eq(10)
- expect(subject.dates[0].date).to eq(Date.new(2014,8,6))
- expect(subject.dates[1].date).to eq(Date.new(2014,8,11))
- expect(subject.dates[2].date).to eq(Date.new(2014,8,12))
- expect(subject.dates[3].date).to eq(Date.new(2014,8,13))
- expect(subject.dates[4].date).to eq(Date.new(2014,8,18))
- expect(subject.dates[5].date).to eq(Date.new(2014,8,19))
- expect(subject.dates[6].date).to eq(Date.new(2014,8,20))
- expect(subject.dates[7].date).to eq(Date.new(2014,8,25))
- expect(subject.dates[8].date).to eq(Date.new(2014,8,26))
- expect(subject.dates[9].date).to eq(Date.new(2014,8,27))
+
+ it "should have 1 dates " do
+ expect(subject.dates.size).to eq(1)
+ expect(subject.dates.first.date.to_s).to eq('2014-08-06')
end
end
@@ -1311,24 +1320,26 @@ end
subject.disjoin! another_tt
subject.reload
end
- it "should have same 0 result periods" do
- expect(subject.periods.size).to eq(0)
+
+ it "should have same 3 result periods" do
+ expect(subject.periods.size).to eq(3)
+ [
+ ['2014-08-11', '2014-08-13'],
+ ['2014-08-18', '2014-08-20'],
+ ['2014-08-25', '2014-08-27']
+ ].each_with_index do |period, index|
+ expect(subject.periods[index].period_start.to_s).to eq(period[0])
+ expect(subject.periods[index].period_end.to_s).to eq(period[1])
+ end
end
+
it "should have 0 day_types" do
expect(subject.int_day_types).to eq(0)
end
- it "should have only 10 dates " do
- expect(subject.dates.size).to eq(10)
- expect(subject.dates[0].date).to eq(Date.new(2014,8,6))
- expect(subject.dates[1].date).to eq(Date.new(2014,8,11))
- expect(subject.dates[2].date).to eq(Date.new(2014,8,12))
- expect(subject.dates[3].date).to eq(Date.new(2014,8,13))
- expect(subject.dates[4].date).to eq(Date.new(2014,8,18))
- expect(subject.dates[5].date).to eq(Date.new(2014,8,19))
- expect(subject.dates[6].date).to eq(Date.new(2014,8,20))
- expect(subject.dates[7].date).to eq(Date.new(2014,8,25))
- expect(subject.dates[8].date).to eq(Date.new(2014,8,26))
- expect(subject.dates[9].date).to eq(Date.new(2014,8,27))
+
+ it "should have only 1 dates " do
+ expect(subject.dates.size).to eq(1)
+ expect(subject.dates.first.date.to_s).to eq('2014-08-06')
end
end
diff --git a/spec/models/chouette/vehicle_journey_spec.rb b/spec/models/chouette/vehicle_journey_spec.rb
index b22183ab6..ed76c278c 100644
--- a/spec/models/chouette/vehicle_journey_spec.rb
+++ b/spec/models/chouette/vehicle_journey_spec.rb
@@ -197,7 +197,7 @@ describe Chouette::VehicleJourney, :type => :model do
expect(vehicle_journey.reload.vehicle_journey_at_stops).to be_empty
at_stops = vehicle_journey.reload.vehicle_journey_at_stops_matrix
- at_stops.map{|stop| expect(stop.stop_point_id).to be_nil }
+ at_stops.map{|stop| expect(stop.id).to be_nil }
expect(at_stops.count).to eq route.stop_points.count
end
@@ -284,7 +284,7 @@ describe Chouette::VehicleJourney, :type => :model do
first stop that they make" do
journey_missing_stop = create(:vehicle_journey)
journey_early = create(
- :vehicle_journey,
+ :vehicle_journey,
route: journey_missing_stop.route,
journey_pattern: journey_missing_stop.journey_pattern
)
@@ -310,6 +310,82 @@ describe Chouette::VehicleJourney, :type => :model do
end
end
+ describe ".departure_time_between" do
+ it "selects vehicle journeys whose departure times are between the
+ specified range" do
+ journey_early = create(
+ :vehicle_journey,
+ stop_departure_time: '02:00:00'
+ )
+
+ route = journey_early.route
+ journey_pattern = journey_early.journey_pattern
+
+ journey_middle = create(
+ :vehicle_journey,
+ route: route,
+ journey_pattern: journey_pattern,
+ stop_departure_time: '03:00:00'
+ )
+ journey_late = create(
+ :vehicle_journey,
+ route: route,
+ journey_pattern: journey_pattern,
+ stop_departure_time: '04:00:00'
+ )
+
+ expect(route
+ .vehicle_journeys
+ .select('DISTINCT "vehicle_journeys".*')
+ .joins('
+ LEFT JOIN "vehicle_journey_at_stops"
+ ON "vehicle_journey_at_stops"."vehicle_journey_id" =
+ "vehicle_journeys"."id"
+ ')
+ .where_departure_time_between('02:30', '03:30')
+ .to_a
+ ).to eq([journey_middle])
+ end
+
+ it "can include vehicle journeys that have nil stops" do
+ journey = create(:vehicle_journey_empty)
+ route = journey.route
+
+ expect(route
+ .vehicle_journeys
+ .select('DISTINCT "vehicle_journeys".*')
+ .joins('
+ LEFT JOIN "vehicle_journey_at_stops"
+ ON "vehicle_journey_at_stops"."vehicle_journey_id" =
+ "vehicle_journeys"."id"
+ ')
+ .where_departure_time_between('02:30', '03:30', allow_empty: true)
+ .to_a
+ ).to eq([journey])
+ end
+ end
+
+ describe ".without_time_tables" do
+ it "selects only vehicle journeys that have no associated calendar" do
+ journey = create(:vehicle_journey)
+ route = journey.route
+
+ journey_with_time_table = create(
+ :vehicle_journey,
+ route: route,
+ journey_pattern: journey.journey_pattern
+ )
+ journey_with_time_table.time_tables << create(:time_table)
+
+ expect(
+ route
+ .vehicle_journeys
+ .without_time_tables
+ .to_a
+ ).to eq([journey])
+ end
+ end
+
subject { create(:vehicle_journey_odd) }
describe "in_relation_to_a_journey_pattern methods" do
let!(:route) { create(:route)}
diff --git a/spec/models/time_table_combination_spec.rb b/spec/models/time_table_combination_spec.rb
index 4c99a14fa..0a8b3296a 100644
--- a/spec/models/time_table_combination_spec.rb
+++ b/spec/models/time_table_combination_spec.rb
@@ -48,12 +48,16 @@ describe TimeTableCombination, :type => :model do
combined.int_day_types = 508
combined.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,15), :period_end => Date.new(2014,9,15))
combined.save
- subject.operation = 'union'
- subject.source_id = source.id
- subject.combined_id = combined.id
+
+ subject.operation = 'union'
+ subject.source_id = source.id
+ subject.time_table_id = combined.id
+ subject.combined_type = 'time_table'
+
subject.combine
source.reload
end
+
it "should add combined to source" do
expect(source.periods.size).to eq(1)
expect(source.periods[0].period_start).to eq(Date.new(2014,8,1))
@@ -72,20 +76,26 @@ describe TimeTableCombination, :type => :model do
combined.int_day_types = 508
combined.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,15), :period_end => Date.new(2014,9,15))
combined.save
- subject.operation = 'intersection'
- subject.source_id = source.id
- subject.combined_id = combined.id
+
+ subject.operation = 'intersection'
+ subject.source_id = source.id
+ subject.time_table_id = combined.id
+ subject.combined_type = 'time_table'
+
subject.combine
source.reload
end
+
it "should intersect combined to source" do
expect(source.int_day_types).to eq(0)
- expect(source.periods.size).to eq(0)
- expect(source.dates.size).to eq(17)
- expect(source.dates[0].date).to eq(Date.new(2014,8,15))
- expect(source.dates[16].date).to eq(Date.new(2014,8,31))
+ expect(source.periods.size).to eq(1)
+ expect(source.dates.size).to eq(0)
+
+ expect(source.periods.first.period_start.to_s).to eq('2014-08-15')
+ expect(source.periods.first.period_end.to_s).to eq('2014-08-31')
end
end
+
context "when operation is disjoin" do
before(:each) do
source.periods.clear
@@ -98,18 +108,23 @@ describe TimeTableCombination, :type => :model do
combined.int_day_types = 508
combined.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,15), :period_end => Date.new(2014,9,15))
combined.save
- subject.operation = 'disjunction'
- subject.source_id = source.id
- subject.combined_id = combined.id
+
+ subject.operation = 'disjunction'
+ subject.source_id = source.id
+ subject.time_table_id = combined.id
+ subject.combined_type = 'time_table'
+
subject.combine
source.reload
end
+
it "should disjoin combined to source" do
expect(source.int_day_types).to eq(0)
- expect(source.periods.size).to eq(0)
- expect(source.dates.size).to eq(14)
- expect(source.dates[0].date).to eq(Date.new(2014,8,1))
- expect(source.dates[13].date).to eq(Date.new(2014,8,14))
+ expect(source.periods.size).to eq(1)
+ expect(source.dates.size).to eq(0)
+
+ expect(source.periods.first.period_start.to_s).to eq('2014-08-01')
+ expect(source.periods.first.period_end.to_s).to eq('2014-08-14')
end
end
end
diff --git a/spec/policies/application_policy_spec.rb b/spec/policies/application_policy_spec.rb
new file mode 100644
index 000000000..d7e8e5e27
--- /dev/null
+++ b/spec/policies/application_policy_spec.rb
@@ -0,0 +1,19 @@
+RSpec.describe ApplicationPolicy, type: :policy do
+
+ subject { described_class }
+
+ permissions :organisation_match? do
+ let( :user_context ) { create_user_context(user: user, referential: referential) }
+ let( :referentail ) { create :referential }
+ let( :user ) { create :user }
+
+ it "denies a user with a different organisation" do
+ expect_it.not_to permit(user_context, referential)
+ end
+
+ it "allows a user with a different organisation" do
+ user.update_attribute :organisation, referential.organisation
+ expect_it.to permit(user_context, referential)
+ end
+ end
+end
diff --git a/spec/policies/company_policy_spec.rb b/spec/policies/company_policy_spec.rb
deleted file mode 100644
index 7109b628f..000000000
--- a/spec/policies/company_policy_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe CompanyPolicy do
-end
diff --git a/spec/policies/group_of_line_policy_spec.rb b/spec/policies/group_of_line_policy_spec.rb
deleted file mode 100644
index 04914f519..000000000
--- a/spec/policies/group_of_line_policy_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe GroupOfLinePolicy do
-end
diff --git a/spec/policies/line_policy_spec.rb b/spec/policies/line_policy_spec.rb
deleted file mode 100644
index b76616d13..000000000
--- a/spec/policies/line_policy_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe LinePolicy do
-end
diff --git a/spec/policies/network_policy_spec.rb b/spec/policies/network_policy_spec.rb
deleted file mode 100644
index dcdb6bdb2..000000000
--- a/spec/policies/network_policy_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe NetworkPolicy do
-end
diff --git a/spec/policies/referential_policy_spec.rb b/spec/policies/referential_policy_spec.rb
deleted file mode 100644
index 084ecc9f0..000000000
--- a/spec/policies/referential_policy_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ReferentialPolicy do
-end
diff --git a/spec/policies/stop_area_policy_spec.rb b/spec/policies/stop_area_policy_spec.rb
deleted file mode 100644
index a03c87460..000000000
--- a/spec/policies/stop_area_policy_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe StopAreaPolicy do
-end
diff --git a/spec/policies/time_table_policy_spec.rb b/spec/policies/time_table_policy_spec.rb
new file mode 100644
index 000000000..63bd316e4
--- /dev/null
+++ b/spec/policies/time_table_policy_spec.rb
@@ -0,0 +1,26 @@
+RSpec.describe TimeTablePolicy, type: :policy do
+
+ permissions :duplicate? do
+ context "user of a different organisation" do
+ it "is denied" do
+ expect_it.not_to permit(user_context, referential)
+ end
+ it "even if she has the time_tables.create permission" do
+ add_permissions 'time_tables.create', for_user: user
+ expect_it.not_to permit(user_context, referential)
+ end
+ end
+ context "user of the same organisation" do
+ before do
+ user.update_attribute :organisation, referential.organisation
+ end
+ it "is denied" do
+ expect_it.not_to permit(user_context, referential)
+ end
+ it "unless she has the time_tables.create permission" do
+ add_permissions 'time_tables.create', for_user: user
+ expect_it.to permit(user_context, referential)
+ end
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c99cede55..6176babea 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,14 +1,16 @@
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'simplecov'
-if ENV['JOB_NAME']
- require 'simplecov-rcov'
- SimpleCov.formatters = [
- SimpleCov::Formatter::HTMLFormatter,
- SimpleCov::Formatter::RcovFormatter
- ]
-end
-SimpleCov.start 'rails' do
- add_filter 'vendor'
+unless ENV['NO_RCOV']
+ if ENV['JOB_NAME']
+ require 'simplecov-rcov'
+ SimpleCov.formatters = [
+ SimpleCov::Formatter::HTMLFormatter,
+ SimpleCov::Formatter::RcovFormatter
+ ]
+ end
+ SimpleCov.start 'rails' do
+ add_filter 'vendor'
+ end
end
ENV["RAILS_ENV"] = 'test'
diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb
deleted file mode 100644
index 5e1becafb..000000000
--- a/spec/support/helpers.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'support/helpers/session_helpers'
-RSpec.configure do |config|
- config.include Features::SessionHelpers, type: :feature
-end
diff --git a/spec/support/helpers/session_helpers.rb b/spec/support/helpers/session_helpers.rb
index b92c5f0a1..c2bb3a04a 100644
--- a/spec/support/helpers/session_helpers.rb
+++ b/spec/support/helpers/session_helpers.rb
@@ -22,3 +22,6 @@ module Features
end
end
end
+RSpec.configure do |config|
+ config.include Features::SessionHelpers, type: :feature
+end
diff --git a/spec/support/pundit.rb b/spec/support/pundit.rb
new file mode 100644
index 000000000..d818ce754
--- /dev/null
+++ b/spec/support/pundit.rb
@@ -0,0 +1,31 @@
+require 'pundit/rspec'
+
+module Support
+ module ApplicationPolicy
+ def add_permissions(*permissions, for_user:)
+ for_user.permissions ||= []
+ for_user.permissions += permissions.flatten
+ end
+
+ def create_user_context(user:, referential:)
+ OpenStruct.new(user: user, context: {referential: referential})
+ end
+ end
+
+ module ApplicationPolicyMacros
+ def self.extended into
+ into.module_eval do
+ subject { described_class }
+ let( :user_context ) { create_user_context(user: user, referential: referential) }
+ let( :referentail ) { create :referential }
+ let( :user ) { create :user }
+ end
+ end
+
+ end
+end
+
+RSpec.configure do | c |
+ c.include Support::ApplicationPolicy, type: :policy
+ c.extend Support::ApplicationPolicyMacros, type: :policy
+end
diff --git a/spec/support/subject.rb b/spec/support/subject.rb
new file mode 100644
index 000000000..d0c070314
--- /dev/null
+++ b/spec/support/subject.rb
@@ -0,0 +1,11 @@
+module Support
+ module Subject
+ def expect_it
+ expect(subject)
+ end
+ end
+end
+
+RSpec.configure do |conf|
+ conf.include Support::Subject
+end