diff options
17 files changed, 301 insertions, 118 deletions
diff --git a/INSTALL.md b/INSTALL.md index 8586803dd..7bfcb7074 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -74,9 +74,7 @@ on your [profile page](http://stif-portail-dev.af83.priv/users/edit) # Troubleshouting If PG complains about illegal type `hstore` in your tests that is probably because the shared extension is not installed, here is waht to do: + + bundle exec rake db:test:purge - bundle exec rake db:schema:dump # if not up to date - - RAILS_ENV=test bundle exec rake db:drop - RAILS_ENV=test bundle exec rake db:create - RAILS_ENV=test bundle exec rake db:schema:load +Thanks to `lib/tasks/extensions.rake`. 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 a023360a5..d54f1ba06 100644 --- a/app/assets/javascripts/es6_browserified/time_tables/actions/index.js +++ b/app/assets/javascripts/es6_browserified/time_tables/actions/index.js @@ -63,6 +63,11 @@ const actions = { name: selectedTag.name } }), + deletePeriod: (index, dayTypes) => ({ + type: 'DELETE_PERIOD', + index, + dayTypes + }), monthName(strDate) { let monthList = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"] var date = new Date(strDate) @@ -74,7 +79,7 @@ const actions = { let M = actions.monthName(strDate).toLowerCase() let Y = origin[0] - if(mLimit) { + if(mLimit && M.length > mLimit) { M = M.substr(0, mLimit) + '.' } @@ -92,6 +97,9 @@ const actions = { // We compare periods & currentDate, to determine if it is included or not let testDate = false periods.map((p, i) => { + if(p.deleted){ + return false + } let begin = new Date(p.period_start) let end = new Date(p.period_end) diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/Navigate.js b/app/assets/javascripts/es6_browserified/time_tables/components/Navigate.js index df8c6e844..5db373f9c 100644 --- a/app/assets/javascripts/es6_browserified/time_tables/components/Navigate.js +++ b/app/assets/javascripts/es6_browserified/time_tables/components/Navigate.js @@ -16,44 +16,68 @@ let Navigate = ({ dispatch, metas, timetable, pagination, status, filters}) => { <div className="row mt-md"> <div className="col-lg-8 col-lg-offset-2 col-md-8 col-md-offset-2 col-sm-10 col-sm-offset-1 text-right"> <div className="pagination"> - <form className='page_links' onSubmit={e => {e.preventDefault()}}> - <select - value={pagination.currentPage} - onChange={(e)=>{ - e.preventDefault() - dispatch(actions.checkConfirmModal(e, actions.changePage(dispatch, pagination, e.currentTarget.value), pagination.stateChanged, dispatch)) - }} - > - {_.map(pagination.periode_range, (month, i) => ( - <option - value={month} - key={i} + <form className='form-inline' onSubmit={e => {e.preventDefault()}}> + {/* date selector */} + <div className="form-group"> + <div className="dropdown month_selector" style={{display: 'inline-block'}}> + <div + className='btn btn-default dropdown-toggle' + id='date_selector' + data-toggle='dropdown' + aria-haspopup='true' + aria-expanded='true' + > + {pagination.currentPage ? (actions.monthName(pagination.currentPage) + ' ' + new Date(pagination.currentPage).getFullYear()) : ''} + <span className='caret'></span> + </div> + <ul + className='dropdown-menu' + aria-labelledby='date_selector' > - {actions.monthName(month) + ' ' + new Date(month).getFullYear()} - </option> - ))} - </select> - <button - onClick={e => { - e.preventDefault() - dispatch(actions.checkConfirmModal(e, actions.goToPreviousPage(dispatch, pagination), pagination.stateChanged, dispatch)) - }} - type='button' - data-target='#ConfirmModal' - className={(firstPage ? 'disabled ' : '') + 'previous_page'} - disabled={(firstPage ? 'disabled' : '')} - ></button> - <button - onClick={e => { - e.preventDefault() - dispatch(actions.checkConfirmModal(e, actions.goToNextPage(dispatch, pagination), pagination.stateChanged, dispatch)) - }} - type='button' - data-target='#ConfirmModal' - className={(lastPage ? 'disabled ' : '') + 'next_page'} - disabled={(lastPage ? 'disabled' : '')} - ></button> - </form> + {_.map(pagination.periode_range, (month, i) => ( + <li key={i}> + <button + type='button' + value={month} + onClick={e => { + e.preventDefault() + dispatch(actions.checkConfirmModal(e, actions.changePage(dispatch, pagination, e.currentTarget.value), pagination.stateChanged, dispatch)) + }} + > + {actions.monthName(month) + ' ' + new Date(month).getFullYear()} + </button> + </li> + ))} + </ul> + </div> + </div> + + {/* prev/next */} + <div className="form-group"> + <div className="page_links"> + <button + onClick={e => { + e.preventDefault() + dispatch(actions.checkConfirmModal(e, actions.goToPreviousPage(dispatch, pagination), pagination.stateChanged, dispatch)) + }} + type='button' + data-target='#ConfirmModal' + className={(firstPage ? 'disabled ' : '') + 'previous_page'} + disabled={(firstPage ? 'disabled' : '')} + ></button> + <button + onClick={e => { + e.preventDefault() + dispatch(actions.checkConfirmModal(e, actions.goToNextPage(dispatch, pagination), pagination.stateChanged, dispatch)) + }} + type='button' + data-target='#ConfirmModal' + className={(lastPage ? 'disabled ' : '') + 'next_page'} + disabled={(lastPage ? 'disabled' : '')} + ></button> + </div> + </div> + </form> </div> </div> </div> diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js index 61098d9ea..0511734ba 100644 --- a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js +++ b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodManager.js @@ -14,14 +14,50 @@ class PeriodManager extends Component { className='period_manager' id={this.props.value.id} > - <strong>{(this.props.value.period_start.split('-')[2]) + ' > ' + actions.getHumanDate(this.props.value.period_end, 3)}</strong> + <p className='strong'> + {actions.getHumanDate(this.props.value.period_start, 3).substr(0, 7) + ' > ' + actions.getHumanDate(this.props.value.period_end, 3)} + </p> + + <div className='dropdown'> + <div + className='btn dropdown-toggle' + id='period_actions' + data-toggle='dropdown' + aria-haspopup='true' + aria-expanded='true' + > + <span className='fa fa-cog'></span> + </div> + <ul + className='dropdown-menu' + aria-labelledby='date_selector' + > + <li> + <button + type='button' + > + Modifier + </button> + </li> + <li className='delete-action'> + <button + type='button' + onClick={() => this.props.onDeletePeriod(this.props.index, this.props.metas.day_types)} + > + <span className='fa fa-trash'></span> + Supprimer + </button> + </li> + </ul> + </div> </div> ) } } PeriodManager.propTypes = { - value: PropTypes.object.isRequired + value: PropTypes.object.isRequired, + onDeletePeriod: PropTypes.func.isRequired } module.exports = PeriodManager diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodsInDay.js b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodsInDay.js index adc500c86..59409fc7d 100644 --- a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodsInDay.js +++ b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodsInDay.js @@ -14,16 +14,18 @@ class PeriodsInDay extends Component { let periods = this.props.value periods.map((p, i) => { - let begin = new Date(p.period_start).getTime() - let end = new Date(p.period_end).getTime() + if (!p.deleted){ + let begin = new Date(p.period_start).getTime() + let end = new Date(p.period_end).getTime() - if(currentDate >= begin && currentDate <= end) { - if(currentDate == begin) { - cls += ' in_periods start_period' - } else if(currentDate == end) { - cls += ' in_periods end_period' - } else { - cls += ' in_periods' + if(currentDate >= begin && currentDate <= end) { + if(currentDate == begin) { + cls += ' in_periods start_period' + } else if(currentDate == end) { + cls += ' in_periods end_period' + } else { + cls += ' in_periods' + } } } }) @@ -36,21 +38,28 @@ class PeriodsInDay extends Component { className={this.isIn(this.props.currentDate)} > {this.props.value.map((p, i) => { - let begin = new Date(p.period_start).getTime() - let end = new Date(p.period_end).getTime() - let d = this.props.currentDate.getTime() + if(!p.deleted){ + let begin = new Date(p.period_start).getTime() + let end = new Date(p.period_end).getTime() + let d = this.props.currentDate.getTime() - if(d >= begin && d <= end) { - if(d == begin) { - return ( - <PeriodManager - key={i} - value={p} - /> - ) - } else { - return false + if(d >= begin && d <= end) { + if(d == begin || (this.props.currentDate.getUTCDate() == 1)) { + return ( + <PeriodManager + key={i} + index={i} + value={p} + onDeletePeriod={this.props.onDeletePeriod} + metas={this.props.metas} + /> + ) + } else { + return false + } } + }else{ + return false } })} </div> @@ -61,7 +70,8 @@ class PeriodsInDay extends Component { PeriodsInDay.propTypes = { value: PropTypes.array.isRequired, currentDate: PropTypes.object.isRequired, - index: PropTypes.number.isRequired + index: PropTypes.number.isRequired, + onDeletePeriod: PropTypes.func.isRequired } module.exports = PeriodsInDay 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 cc47c2052..eecdf174d 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 ? ' included' : '')} + className={'daynumber' + ((this.props.value.in_periods && this.props.dayTypeActive) ? ' included' : '')} > {this.props.value.mday} </span> @@ -28,7 +28,8 @@ class TimeTableDay extends Component { TimeTableDay.propTypes = { value: PropTypes.object.isRequired, - index: PropTypes.number.isRequired + index: PropTypes.number.isRequired, + dayTypeActive: PropTypes.bool.isRequired } module.exports = TimeTableDay 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 b27dddbf1..b9b191792 100644 --- a/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js +++ b/app/assets/javascripts/es6_browserified/time_tables/components/Timetable.js @@ -19,26 +19,6 @@ class Timetable extends Component{ return currentDate } - componentDidUpdate(prevProps, prevState) { - if(this.props.status.isFetching == false){ - $('.table-2entries').each(function() { - var refH = [] - var refCol = [] - - $(this).find('.t2e-head').children('.td').each(function() { - var h = $(this).outerHeight(); - refH.push(h) - }); - - $(this).find('.t2e-item').children('.td-group').each(function() { - for(var nth = 0; nth < refH.length; nth++) { - $(this).find('.td:nth-child('+ (nth + 1) +')').css('height', refH[nth]); - } - }); - }); - } - } - render() { return ( <div className='row'> @@ -48,9 +28,9 @@ class Timetable extends Component{ <div className="th"> <div className="strong">Synthèse</div> </div> - <div className="td">Journées d'application</div> - <div className="td">Périodes</div> - <div className="td">Exceptions</div> + <div className="td"><span>Journées d'application</span></div> + <div className="td"><span>Périodes</span></div> + <div className="td"><span>Exceptions</span></div> </div> <div className="t2e-item-list w80"> <div> @@ -66,6 +46,7 @@ class Timetable extends Component{ key={i} index={i} value={d} + dayTypeActive={this.props.metas.day_types[d.wday]} /> )} </div> @@ -84,6 +65,8 @@ class Timetable extends Component{ index={i} value={this.props.timetable.time_table_periods} currentDate={this.currentDate(this.props.timetable.current_periode_range, d.mday)} + onDeletePeriod={this.props.onDeletePeriod} + metas={this.props.metas} /> {/* exceptions */} @@ -106,7 +89,8 @@ class Timetable extends Component{ Timetable.propTypes = { metas: PropTypes.object.isRequired, timetable: PropTypes.object.isRequired, - status: PropTypes.object.isRequired + status: PropTypes.object.isRequired, + onDeletePeriod: PropTypes.func.isRequired } module.exports = Timetable diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js b/app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js index 62fe20419..be31be061 100644 --- a/app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js +++ b/app/assets/javascripts/es6_browserified/time_tables/containers/Timetable.js @@ -1,5 +1,6 @@ var connect = require('react-redux').connect var TimetableComponent = require('../components/Timetable') +var actions = require('../actions') const mapStateToProps = (state) => { return { @@ -11,6 +12,9 @@ const mapStateToProps = (state) => { const mapDispatchToProps = (dispatch) => { return { + onDeletePeriod: (index, dayTypes) =>{ + dispatch(actions.deletePeriod(index, dayTypes)) + } } } 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 1c492859f..845f0814b 100644 --- a/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js +++ b/app/assets/javascripts/es6_browserified/time_tables/reducers/timetable.js @@ -1,5 +1,6 @@ const _ = require('lodash') var actions = require('../actions') +let newState = {} const timetable = (state = {}, action) => { switch (action.type) { @@ -12,7 +13,7 @@ const timetable = (state = {}, action) => { }) return _.assign({}, fetchedState, {current_month: actions.updateSynthesis(fetchedState, actions.strToArrayDayTypes(action.json.day_types))}) case 'RECEIVE_MONTH': - let newState = _.assign({}, state, { + newState = _.assign({}, state, { current_month: action.json.days }) return _.assign({}, newState, {current_month: actions.updateSynthesis(newState, actions.strToArrayDayTypes(action.json.day_types))}) @@ -27,6 +28,15 @@ const timetable = (state = {}, action) => { $('#ConfirmModal').modal('hide') actions.fetchTimeTables(action.dispatch, action.page) return _.assign({}, state, {current_periode_range: action.page}) + case 'DELETE_PERIOD': + let ttperiods = state.time_table_periods.map((period, i) =>{ + if(i == action.index){ + period.deleted = true + } + return period + }) + newState = _.assign({}, state, {time_table_periods : ttperiods}) + return _.assign({}, newState, {current_month: actions.updateSynthesis(newState, action.dayTypes)}) default: return state } diff --git a/app/assets/stylesheets/components/_buttons.sass b/app/assets/stylesheets/components/_buttons.sass index 07758d56c..342e6503d 100644 --- a/app/assets/stylesheets/components/_buttons.sass +++ b/app/assets/stylesheets/components/_buttons.sass @@ -117,7 +117,6 @@ table, .table padding: 5px 15px > li.delete-action - > a, > button display: block position: relative diff --git a/app/assets/stylesheets/components/_dropdown.sass b/app/assets/stylesheets/components/_dropdown.sass index eb2cc8f74..99dc6292e 100644 --- a/app/assets/stylesheets/components/_dropdown.sass +++ b/app/assets/stylesheets/components/_dropdown.sass @@ -14,9 +14,11 @@ &:hover, &:focus color: #262626 background-color: whitesmoke + outline: none > .disabled > a, > .disabled > button cursor: not-allowed &, &:hover, &:focus color: rgba($darkgrey, 0.5) background-color: transparent + outline: none diff --git a/app/assets/stylesheets/modules/_timetables.sass b/app/assets/stylesheets/modules/_timetables.sass index e44a254c5..2b430fb6a 100644 --- a/app/assets/stylesheets/modules/_timetables.sass +++ b/app/assets/stylesheets/modules/_timetables.sass @@ -3,15 +3,30 @@ //---------------// #periods - .t2e-head > .th - height: 135px - text-align: left - border-color: $darkgrey - border-top-width: 2px + .t2e-head + > .th + height: 135px + text-align: left + border-color: $darkgrey + border-top-width: 2px + + > .strong + padding-top: 123px + transform: translateY(-1.4em) + + .t2e-head > .td, .t2e-item > .td-group > .td + height: 65px - > .strong - padding-top: 123px - transform: translateY(-1.4em) + .t2e-head > .td + line-height: 50px + + > span + display: inline-block + vertical-align: middle + line-height: 1.4 + + .t2e-item-list > div + border-color: #fff .t2e-item .th @@ -59,7 +74,7 @@ background-color: transparent &.included - background-color: rgba($gold, 0.7) + background-color: rgba($gold, 0.5) > .td-group width: 34px @@ -76,15 +91,36 @@ > .td &.in_periods - background-color: rgba($gold, 0.7) - border-left-color: rgba($gold, 0.7) - border-right-color: rgba($gold, 0.7) + background-color: rgba($gold, 0.5) + border-left-color: rgba($gold, 0.5) + border-right-color: rgba($gold, 0.5) &.start_period border-left-color: rgba($grey, 0.5) &.end_period border-right-color: rgba($grey, 0.5) + .form-group > .month_selector + > .btn.btn-default + background-color: rgba($grey, 0.15) + color: $darkgrey + border: none + border-radius: 0 + padding: 8px 15px 7px 15px + + &:active, &.active + box-shadow: none + + > .caret + margin-left: 10px + color: $blue + + > .dropdown-menu + margin-top: 1px + border-radius: 0 0 4px 4px + max-height: 230px + overflow: auto + .period_manager display: block height: auto @@ -92,5 +128,68 @@ white-space: nowrap position: absolute left: 8px - top: 6px + top: 50% + transform: translateY(-50%) z-index: 5 + + > * + display: inline-block + vertical-align: middle + margin: 0 + + &.dropdown + margin-left: 5px + + .btn.dropdown-toggle + color: $blue + background-color: rgba(#fff, 0) + padding: 1px 5px + border-radius: 0 + transition: 0.2s + + &:hover, &:focus, &:active, &.active + background-color: rgba(#fff, 1) + border-color: $blue + outline: none + box-shadow: none + transition: 0.2s + + .open > .btn.dropdown-toggle + background-color: rgba(#fff, 1) + border-color: $blue + box-shadow: none + transition: 0.2s + + .dropdown-menu + margin: 0 + border-radius: 0 + box-shadow: 0 0 3px rgba($darkgrey, 0.25) + min-width: 120px + + > li > a, > li > button + padding: 5px 15px + + > li.delete-action + > a, > button + display: block + position: relative + margin-top: 11px + + &:before + content: '' + display: block + position: absolute + left: 15px + right: 15px + top: -6px + height: 1px + background-color: $grey + + .fa:first-child + margin-right: 0.5em + + .td-group.last_wday ~ .td-group.last_wday ~ .td-group.last_wday ~ .td-group.last_wday + > .td, ~ .td-group > .td + > .period_manager .dropdown-menu + left: auto + right: 0 diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb index c68a60804..accf119a3 100644 --- a/app/controllers/errors_controller.rb +++ b/app/controllers/errors_controller.rb @@ -1,9 +1,14 @@ class ErrorsController < ApplicationController def not_found - render :status => 404, :formats => [:html] + render template: 'errors/not_found', status: 404, formats: [:html] end def server_error - render :status => 500, :formats => [:html] + render template: 'errors/server_error', status: 500, formats: [:html] end -end
\ No newline at end of file + + def not_allowed + render template: 'errors/not_found', status: 403, formats: [:html] + end +end + diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim index b46cf09a4..1025c1658 100644 --- a/app/views/workbenches/show.html.slim +++ b/app/views/workbenches/show.html.slim @@ -7,6 +7,7 @@ / Below is secundary actions & optional contents (filters, ...) .row.mb-sm .col-lg-12.text-right + = link_to Import.model_name.human.pluralize.capitalize, workbench_imports_path(@workbench), class: 'btn btn-primary' - if policy(Referential).create? = link_to t('referentials.actions.new'), new_referential_path(workbench_id: @workbench), class: 'btn btn-primary' diff --git a/config/routes.rb b/config/routes.rb index a8c332fb8..538c069ed 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -213,9 +213,11 @@ ChouetteIhm::Application.routes.draw do get '/help/(*slug)' => 'help#show' - get '/404', to: 'errors#not_found' - get '/403', to: 'errors#not_allowed' - get '/422', to: 'errors#server_error' - get '/500', to: 'errors#server_error' + if Rails.env.production? + get '404', to: 'errors#not_found' + get '403', to: 'errors#not_allowed' + get '422', to: 'errors#server_error' + get '500', to: 'errors#server_error' + end end diff --git a/spec/models/chouette/routing_constraint_zone_spec.rb b/spec/models/chouette/routing_constraint_zone_spec.rb index 0f34db5f9..87ee9e9ac 100644 --- a/spec/models/chouette/routing_constraint_zone_spec.rb +++ b/spec/models/chouette/routing_constraint_zone_spec.rb @@ -13,7 +13,7 @@ describe Chouette::RoutingConstraintZone, type: :model do it 'validates the presence of route_id' do expect { routing_constraint_zone.update!(route_id: nil) - }.to raise_error + }.to raise_error(NoMethodError) end it 'validates the presence of stop_point_ids' do diff --git a/spec/tasks/reflex_rake_spec.rb b/spec/tasks/reflex_rake_spec.rb index 49874231e..04c5886aa 100644 --- a/spec/tasks/reflex_rake_spec.rb +++ b/spec/tasks/reflex_rake_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'reflex:sync' do - pending 'On first sync' do + context 'On first sync' do before(:each) do ['getOP', 'getOR'].each do |method| stub_request(:get, "#{Rails.application.config.reflex_api_url}/?format=xml&idRefa=0&method=#{method}"). |
