diff options
| author | vlatka pavisic | 2016-11-09 15:10:29 +0100 |
|---|---|---|
| committer | vlatka pavisic | 2016-11-09 15:10:29 +0100 |
| commit | 21c6807d2167ffdbcaed58844d1ebafb06c22d6e (patch) | |
| tree | d4f0bca5b97266f08a956de2b946a1bf79a3e964 | |
| parent | 56c0f55d2d8d566b931664b85c76dbe3a58e31cc (diff) | |
| parent | 0dbc80d54b1362c9eb0fc87d8d93f3d60ade68e1 (diff) | |
| download | chouette-core-21c6807d2167ffdbcaed58844d1ebafb06c22d6e.tar.bz2 | |
Refs #1872 : Fix conflicts
62 files changed, 2062 insertions, 287 deletions
diff --git a/.gitignore b/.gitignore index b6a61fd27..762c156eb 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ coverage .idea bin/ +# Ignore node modules +/node_modules @@ -10,6 +10,9 @@ gem 'uglifier', '~> 2.7.2' # Use CoffeeScript for .js.coffee assets and views gem 'coffee-rails', '~> 4.0.0' +# ES6 powa +gem 'browserify-rails' + # Use jquery as the JavaScript library gem 'jquery-rails', '~> 3.1.4' # Update to v4 for Rails 4.2 # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks @@ -125,6 +128,7 @@ gem 'letter_opener' group :development do gem 'capistrano', '2.13.5' gem 'capistrano-ext' + gem 'capistrano-npm', require: false gem 'guard' gem 'guard-rspec' gem 'rails-erd' diff --git a/Gemfile.lock b/Gemfile.lock index 631c0bfbe..a3ede77d1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -90,6 +90,8 @@ GEM binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) breadcrumbs_on_rails (2.3.0) + browserify-rails (1.1.0) + railties (>= 4.0.0, < 5.0) builder (3.2.2) calendar_helper (0.2.5) open4 @@ -101,6 +103,8 @@ GEM net-ssh-gateway (>= 1.1.0) capistrano-ext (1.2.1) capistrano (>= 1.0.0) + capistrano-npm (0.0.2) + capistrano (>= 2.5.5) capybara (2.4.4) mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -574,9 +578,11 @@ DEPENDENCIES better_errors binding_of_caller breadcrumbs_on_rails + browserify-rails calendar_helper (= 0.2.5) capistrano (= 2.13.5) capistrano-ext + capistrano-npm capybara (~> 2.4.0) cocoon codifligne! @@ -674,4 +680,4 @@ DEPENDENCIES will_paginate-bootstrap (~> 1.0.1) BUNDLED WITH - 1.12.5 + 1.13.6 diff --git a/app/assets/javascripts/es6_browserified/actions/index.js b/app/assets/javascripts/es6_browserified/actions/index.js new file mode 100644 index 000000000..8967c0322 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/actions/index.js @@ -0,0 +1,33 @@ +module.exports = { + addStop : () => { + return { + type: 'ADD_STOP' + } + }, + moveStopUp : (index) => { + return { + type: 'MOVE_STOP_UP', + index + } + }, + moveStopDown : (index) => { + return { + type: 'MOVE_STOP_DOWN', + index + } + }, + deleteStop: (index) => { + return { + type: 'DELETE_STOP', + index + } + }, + updateInputValue: (index, text) => { + console.log('action',index, text) + return { + type : "UPDATE_INPUT_VALUE", + index, + text + } + } +} diff --git a/app/assets/javascripts/es6_browserified/components/App.js b/app/assets/javascripts/es6_browserified/components/App.js new file mode 100644 index 000000000..7488b0b39 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/components/App.js @@ -0,0 +1,12 @@ +var React = require('react') +var AddTodo = require('../containers/AddTodo') +var VisibleTodoList = require('../containers/VisibleTodoList') + +const App = () => ( + <div> + <AddTodo /> + <VisibleTodoList /> + </div> +) + +module.exports = App diff --git a/app/assets/javascripts/es6_browserified/components/BSelect2.js b/app/assets/javascripts/es6_browserified/components/BSelect2.js new file mode 100644 index 000000000..7e4782563 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/components/BSelect2.js @@ -0,0 +1,96 @@ +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('/', 3).join('/') + +class BSelect3 extends React.Component{ + constructor(props) { + super(props) + this.state = { + edit: false + } + } + onToggleEdit(e) { + e.preventDefault() + this.setState({edit: !this.state.edit}) + } + onChange(e) { + console.log(e.currentTarget.value, e.currentTarget.textContent) + this.props.onChange(this.props.index, {text: e.currentTarget.textContent, id: e.currentTarget.value}) + this.setState({edit: false}) + } + render() { + if(this.state.edit) + return ( + <div> + <BSelect2 {...this.props} onSelect={ this.onChange.bind(this) }/> + </div> + ) + else + return ( + <div> + <span + title="Cliquez pour changer l'arrêt" + style={{cursor: 'pointer', display: 'block'}} + onClick={this.onToggleEdit.bind(this)} + > + {this.props.value.text} + </span> + </div> + ) + } +} + +const BSelect2 = (props) => { + return ( + <Select2 + value={props.value.id} + onSelect={ props.onSelect } + options={{ + placeholder: 'Sélectionnez un arrêt existant...', + theme: 'bootstrap', + ajax: { + url: origin + path + '/autocomplete_stop_areas.json', + dataType: 'json', + delay: '500', + data: function(params) { + return { + q: params.term + }; + }, + processResults: function(data, params) { + return { + results: data.map( + item => Object.assign( + {}, + item, + { text: item.name + ", " + item.zip_code + " " + item.short_city_name } + ) + ) + }; + }, + cache: true + }, + minimumInputLength: 3, + templateResult: formatRepo + }} + /> + ) +} + +// to fix: this is for custom results return +const formatRepo = (props) => { + if(props.text) return props.text + // console.log(props) + // return ( + // <div> + // {props.short_name} + // <small><em>{props.zip_code} {props.short_city_name}</em></small> + // </div> + // ) +} + +module.exports = BSelect3 diff --git a/app/assets/javascripts/es6_browserified/components/Todo.js b/app/assets/javascripts/es6_browserified/components/Todo.js new file mode 100644 index 000000000..0e74e728f --- /dev/null +++ b/app/assets/javascripts/es6_browserified/components/Todo.js @@ -0,0 +1,62 @@ +var React = require('react') +var PropTypes = require('react').PropTypes +var BSelect2 = require('./BSelect2') + +const Container = {display: 'table', width: '100%'} +const firstBlock = {display: 'table-cell', verticalAlign: 'middle'} +const secondBlock = {display: 'table-cell', verticalAlign: 'middle', width: '150px', textAlign: 'right'} + +const Todo = (props) => { + return ( + <div className='list-group-item' style={Container}> + <div style={firstBlock}> + <div style={{display: 'inline-block', width: '9%', verticalAlign: 'middle'}}> + <span className='strong'>#{props.index}</span> + </div> + + <div style={{display: 'inline-block', width: '91%', verticalAlign: 'middle'}}> + <BSelect2 id={'route_stop_points_' + props.id} value={props.value} onChange={props.onChange} index={props.index} defaultData={props.defaultData}/> + </div> + </div> + + <div style={secondBlock}> + <div className='btn-group btn-group-sm'> + <div className='btn btn-default'> + <span className='fa fa-times'></span> + </div> + <div + className={'btn btn-primary' + (props.first ? ' disabled' : '')} + onClick={props.onMoveUpClick} + > + <span className='fa fa-arrow-up'></span> + </div> + <div + className={'btn btn-primary' + (props.last ? ' disabled' : '')} + onClick={props.onMoveDownClick} + > + <span className='fa fa-arrow-down'></span> + </div> + <div + className='btn btn-danger' + onClick={props.onDeleteClick} + > + <span className='fa fa-trash'></span> + </div> + </div> + </div> + </div> + ) +} + +Todo.propTypes = { + onDeleteClick: PropTypes.func.isRequired, + onMoveUpClick: PropTypes.func.isRequired, + onMoveDownClick: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired, + first: PropTypes.bool, + last: PropTypes.bool, + index: PropTypes.number, + defaultData: PropTypes.array +} + +module.exports = Todo diff --git a/app/assets/javascripts/es6_browserified/components/TodoList.js b/app/assets/javascripts/es6_browserified/components/TodoList.js new file mode 100644 index 000000000..367cfc256 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/components/TodoList.js @@ -0,0 +1,37 @@ +var React = require('react') +var PropTypes = require('react').PropTypes +var Todo = require('./Todo') + +const TodoList = ({ todos, onDeleteClick, onMoveUpClick, onMoveDownClick, onChange }) => { + console.log(todos) + return ( + <div className='list-group'> + {todos.map((todo, index) => + <Todo + key={'item-' + index} + onDeleteClick={() => onDeleteClick(index)} + onMoveUpClick={() => { + console.log(index, todos) + onMoveUpClick(index)} + } + onMoveDownClick={() => onMoveDownClick(index)} + onChange={ onChange } + first={ index === 0 } + last={ index === (todos.length - 1) } + index={ index } + defaultData={ todos } + value={ todo } + /> + )} + </div> + ) +} + +TodoList.propTypes = { + todos: PropTypes.array.isRequired, + onDeleteClick: PropTypes.func.isRequired, + onMoveUpClick: PropTypes.func.isRequired, + onMoveDownClick: PropTypes.func.isRequired +} + +module.exports = TodoList diff --git a/app/assets/javascripts/es6_browserified/containers/AddTodo.js b/app/assets/javascripts/es6_browserified/containers/AddTodo.js new file mode 100644 index 000000000..539b6f78e --- /dev/null +++ b/app/assets/javascripts/es6_browserified/containers/AddTodo.js @@ -0,0 +1,21 @@ +var React = require('react') +var connect = require('react-redux').connect +var addTodo = require('../actions').addStop + +let AddTodo = ({ dispatch }) => { + return ( + <div className="clearfix" style={{marginBottom: 10}}> + <form onSubmit={e => { + e.preventDefault() + dispatch(addTodo()) + }}> + <button type="submit" className="btn btn-primary btn-xs pull-right"> + <span className="fa fa-plus"></span> Ajouter un arrêt + </button> + </form> + </div> + ) +} +AddTodo = connect()(AddTodo) + +module.exports = AddTodo diff --git a/app/assets/javascripts/es6_browserified/containers/VisibleTodoList.js b/app/assets/javascripts/es6_browserified/containers/VisibleTodoList.js new file mode 100644 index 000000000..09da36060 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/containers/VisibleTodoList.js @@ -0,0 +1,37 @@ +var connect = require('react-redux').connect +var toggleTodo = require('../actions').toggleTodo +var deleteStop = require('../actions').deleteStop +var moveStopUp = require('../actions').moveStopUp +var moveStopDown = require('../actions').moveStopDown +var handleChange = require('../actions').updateInputValue +var TodoList = require('../components/TodoList') + +const mapStateToProps = (state) => { + return { + todos: state.todos + } +} + +const mapDispatchToProps = (dispatch) => { + return { + onDeleteClick: (index) =>{ + dispatch(deleteStop(index)) + }, + onMoveUpClick: (index) =>{ + dispatch(moveStopUp(index)) + }, + onMoveDownClick: (index) =>{ + dispatch(moveStopDown(index)) + }, + onChange: (index, text) =>{ + dispatch(handleChange(index, text)) + } + } +} + +const VisibleTodoList = connect( + mapStateToProps, + mapDispatchToProps +)(TodoList) + +module.exports = VisibleTodoList diff --git a/app/assets/javascripts/es6_browserified/reducers/index.js b/app/assets/javascripts/es6_browserified/reducers/index.js new file mode 100644 index 000000000..ae8423673 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/reducers/index.js @@ -0,0 +1,8 @@ +var combineReducers = require('redux').combineReducers +var todos = require('./todos') + +const todoApp = combineReducers({ + todos +}) + +module.exports = todoApp diff --git a/app/assets/javascripts/es6_browserified/reducers/todos.js b/app/assets/javascripts/es6_browserified/reducers/todos.js new file mode 100644 index 000000000..bf64632bd --- /dev/null +++ b/app/assets/javascripts/es6_browserified/reducers/todos.js @@ -0,0 +1,63 @@ +const todo = (state = {}, action, length) => { + switch (action.type) { + case 'ADD_STOP': + return { + text: '', + index: length + } + case 'UPDATE_INPUT_VALUE': + console.log('reducer', action) + if (state.index !== action.index) { + return state + } + + return Object.assign( + {}, + state, + {text: action.text.text, id: action.text.id} + ) + default: + return state + } +} + +const todos = (state = [], action) => { + switch (action.type) { + case 'ADD_STOP': + return [ + ...state, + todo(undefined, action, state.length) + ] + case 'MOVE_STOP_UP': + return [ + ...state.slice(0, action.index - 1), + state[action.index], + state[action.index - 1], + ...state.slice(action.index + 1) + ] + case 'MOVE_STOP_DOWN': + return [ + ...state.slice(0, action.index), + state[action.index + 1], + state[action.index], + ...state.slice(action.index + 2) + ] + case 'DELETE_STOP': + return [ + ...state.slice(0, action.index), + ...state.slice(action.index + 1).map((todo)=>{ + todo.index-- + return todo + }) + ] + case 'UPDATE_INPUT_VALUE': + return state.map((t, i) => (i === action.index) ? action.text : t) + // return state.map(t => + // todo(t, action) + // ) + default: + return state + } +} + +module.exports = todos diff --git a/app/assets/javascripts/es6_browserified/stop_points.js b/app/assets/javascripts/es6_browserified/stop_points.js new file mode 100644 index 000000000..9c0195f2b --- /dev/null +++ b/app/assets/javascripts/es6_browserified/stop_points.js @@ -0,0 +1,48 @@ +var React = require('react') +var render = require('react-dom').render +var Provider = require('react-redux').Provider +var createStore = require('redux').createStore +// var applyMiddleware = require('redux').applyMiddleware +var todoApp = require('./reducers') +var App = require('./components/App') +// var createLogger = require('redux-logger').default +// var thunkMiddleware = require('redux-thunk').default +// var promise = require('redux-promise') + +const getInitialState = () => { + let state = [] + let datas = JSON.parse(decodeURIComponent(window.itinerary_stop)) + for (let [index, value] of datas.entries()){ + + let fancyText = value.name + if(value.zip_code && value.city_name) + fancyText += ", " + value.zip_code + " " + value.city_name + + state.push({ + id: value.id, + name: value.name, + city_name: value.city_name, + zip_code: value.zip_code, + text: fancyText + }) + } + // console.log(state) + return state +} + +var initialState = {todos: getInitialState()} +// const loggerMiddleware = createLogger() +let store = createStore( + todoApp, + initialState + // applyMiddleware(thunkMiddleware, promise, loggerMiddleware) +) + +// console.log(store.getState()) + +render( + <Provider store={store}> + <App /> + </Provider>, + document.getElementById('stop_points') +) diff --git a/app/assets/stylesheets/application.sass.erb b/app/assets/stylesheets/application.sass.erb index 53b767384..c59a07d94 100644 --- a/app/assets/stylesheets/application.sass.erb +++ b/app/assets/stylesheets/application.sass.erb @@ -42,6 +42,9 @@ $body-bg: #eee @import 'vendor/typeahead' @import 'vendor/bootstrap_changes' @import 'vendor/simple_form' +// Select2 +@import 'vendor/select2' +@import 'vendor/select2-bootstrap' // Main css @import 'main/*' diff --git a/app/assets/stylesheets/vendor/select2-bootstrap.css b/app/assets/stylesheets/vendor/select2-bootstrap.css new file mode 100644 index 000000000..65f772696 --- /dev/null +++ b/app/assets/stylesheets/vendor/select2-bootstrap.css @@ -0,0 +1,721 @@ +/*! + * Select2 Bootstrap Theme v0.1.0-beta.9 (https://select2.github.io/select2-bootstrap-theme) + * Copyright 2015-2016 Florian Kissling and contributors (https://github.com/select2/select2-bootstrap-theme/graphs/contributors) + * Licensed under MIT (https://github.com/select2/select2-bootstrap-theme/blob/master/LICENSE) + */ + +.select2-container--bootstrap { + display: block; + width: 100% !important + /*------------------------------------* #COMMON STYLES + \*------------------------------------*/ + /** + * Search field in the Select2 dropdown. + */ + /** + * No outline for all search fields - in the dropdown + * and inline in multi Select2s. + */ + /** + * Adjust Select2's choices hover and selected styles to match + * Bootstrap 3's default dropdown styles. + * + * @see http://getbootstrap.com/components/#dropdowns + */ + /** + * Clear the selection. + */ + /** + * Address disabled Select2 styles. + * + * @see https://select2.github.io/examples.html#disabled + * @see http://getbootstrap.com/css/#forms-control-disabled + */ + /*------------------------------------* #DROPDOWN + \*------------------------------------*/ + /** + * Dropdown border color and box-shadow. + */ + /** + * Limit the dropdown height. + */ + /*------------------------------------* #SINGLE SELECT2 + \*------------------------------------*/ + /*------------------------------------* #MULTIPLE SELECT2 + \*------------------------------------*/ + /** + * Address Bootstrap control sizing classes + * + * 1. Reset Bootstrap defaults. + * 2. Adjust the dropdown arrow button icon position. + * + * @see http://getbootstrap.com/css/#forms-control-sizes + */ + /* 1 */ + /*------------------------------------* #RTL SUPPORT + \*------------------------------------*/ +} + +.select2-container--bootstrap .select2-selection { + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + background-color: #fff; + border: 1px solid #ccc; + border-radius: 4px; + color: #555555; + font-size: 14px; + outline: 0; +} + +.select2-container--bootstrap .select2-selection.form-control { + border-radius: 4px; +} + +.select2-container--bootstrap .select2-search--dropdown .select2-search__field { + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + background-color: #fff; + border: 1px solid #ccc; + border-radius: 4px; + color: #555555; + font-size: 14px; +} + +.select2-container--bootstrap .select2-search__field { + outline: 0; + /* Firefox 18- */ + /** + * Firefox 19+ + * + * @see http://stackoverflow.com/questions/24236240/color-for-styled-placeholder-text-is-muted-in-firefox + */ +} + +.select2-container--bootstrap .select2-search__field::-webkit-input-placeholder { + color: #999; +} + +.select2-container--bootstrap .select2-search__field:-moz-placeholder { + color: #999; +} + +.select2-container--bootstrap .select2-search__field::-moz-placeholder { + color: #999; + opacity: 1; +} + +.select2-container--bootstrap .select2-search__field:-ms-input-placeholder { + color: #999; +} + +.select2-container--bootstrap .select2-results__option { + padding: 6px 12px; + /** + * Disabled results. + * + * @see https://select2.github.io/examples.html#disabled-results + */ + /** + * Hover state. + */ + /** + * Selected state. + */ +} + +.select2-container--bootstrap .select2-results__option[role=group] { + padding: 0; +} + +.select2-container--bootstrap .select2-results__option[aria-disabled=true] { + color: #777777; + cursor: not-allowed; +} + +.select2-container--bootstrap .select2-results__option[aria-selected=true] { + background-color: #f5f5f5; + color: #262626; +} + +.select2-container--bootstrap .select2-results__option--highlighted[aria-selected] { + background-color: #337ab7; + color: #fff; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option { + padding: 6px 12px; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__group { + padding-left: 0; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option { + margin-left: -12px; + padding-left: 24px; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -24px; + padding-left: 36px; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -36px; + padding-left: 48px; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -48px; + padding-left: 60px; +} + +.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -60px; + padding-left: 72px; +} + +.select2-container--bootstrap .select2-results__group { + color: #777777; + display: block; + padding: 6px 12px; + font-size: 12px; + line-height: 1.42857143; + white-space: nowrap; +} + +.select2-container--bootstrap.select2-container--focus .select2-selection, .select2-container--bootstrap.select2-container--open .select2-selection { + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); + -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + -webkit-transition: border-color ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s; + transition: border-color ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s; + transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s; + border-color: #66afe9; +} + +.select2-container--bootstrap.select2-container--open { + /** + * Make the dropdown arrow point up while the dropdown is visible. + */ + /** + * Handle border radii of the container when the dropdown is showing. + */ +} + +.select2-container--bootstrap.select2-container--open .select2-selection .select2-selection__arrow b { + border-color: transparent transparent #999 transparent; + border-width: 0 4px 4px 4px; +} + +.select2-container--bootstrap.select2-container--open.select2-container--below .select2-selection { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + border-bottom-color: transparent; +} + +.select2-container--bootstrap.select2-container--open.select2-container--above .select2-selection { + border-top-right-radius: 0; + border-top-left-radius: 0; + border-top-color: transparent; +} + +.select2-container--bootstrap .select2-selection__clear { + color: #999; + cursor: pointer; + float: right; + font-weight: bold; + margin-right: 10px; +} + +.select2-container--bootstrap .select2-selection__clear:hover { + color: #333; +} + +.select2-container--bootstrap.select2-container--disabled .select2-selection { + border-color: #ccc; + -webkit-box-shadow: none; + box-shadow: none; +} + +.select2-container--bootstrap.select2-container--disabled .select2-selection, +.select2-container--bootstrap.select2-container--disabled .select2-search__field { + cursor: not-allowed; +} + +.select2-container--bootstrap.select2-container--disabled .select2-selection, +.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice { + background-color: #eeeeee; +} + +.select2-container--bootstrap.select2-container--disabled .select2-selection__clear, +.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice__remove { + display: none; +} + +.select2-container--bootstrap .select2-dropdown { + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + border-color: #66afe9; + overflow-x: hidden; + margin-top: -1px; +} + +.select2-container--bootstrap .select2-dropdown--above { + -webkit-box-shadow: 0px -6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0px -6px 12px rgba(0, 0, 0, 0.175); + margin-top: 1px; +} + +.select2-container--bootstrap .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; +} + +.select2-container--bootstrap .select2-selection--single { + height: 34px; + line-height: 1.42857143; + padding: 6px 24px 6px 12px; + /** + * Adjust the single Select2's dropdown arrow button appearance. + */ +} + +.select2-container--bootstrap .select2-selection--single .select2-selection__arrow { + position: absolute; + bottom: 0; + right: 12px; + top: 0; + width: 4px; +} + +.select2-container--bootstrap .select2-selection--single .select2-selection__arrow b { + border-color: #999 transparent transparent transparent; + border-style: solid; + border-width: 4px 4px 0 4px; + height: 0; + left: 0; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; +} + +.select2-container--bootstrap .select2-selection--single .select2-selection__rendered { + color: #555555; + padding: 0; +} + +.select2-container--bootstrap .select2-selection--single .select2-selection__placeholder { + color: #999; +} + +.select2-container--bootstrap .select2-selection--multiple { + min-height: 34px; + padding: 0; + height: auto; + /** + * Make Multi Select2's choices match Bootstrap 3's default button styles. + */ + /** + * Minus 2px borders. + */ + /** + * Clear the selection. + */ +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__rendered { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + display: block; + line-height: 1.42857143; + list-style: none; + margin: 0; + overflow: hidden; + padding: 0; + width: 100%; + text-overflow: ellipsis; + white-space: nowrap; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__placeholder { + color: #999; + float: left; + margin-top: 5px; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice { + color: #555555; + background: #fff; + border: 1px solid #ccc; + border-radius: 4px; + cursor: default; + float: left; + margin: 5px 0 0 6px; + padding: 0 6px; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field { + background: transparent; + padding: 0 12px; + height: 32px; + line-height: 1.42857143; + margin-top: 0; + min-width: 5em; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove { + color: #999; + cursor: pointer; + display: inline-block; + font-weight: bold; + margin-right: 3px; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove:hover { + color: #333; +} + +.select2-container--bootstrap .select2-selection--multiple .select2-selection__clear { + margin-top: 6px; +} + +.select2-container--bootstrap .select2-selection--single.input-sm, +.input-group-sm .select2-container--bootstrap .select2-selection--single, +.form-group-sm .select2-container--bootstrap .select2-selection--single { + border-radius: 3px; + font-size: 12px; + height: 30px; + line-height: 1.5; + padding: 5px 22px 5px 10px; + /* 2 */ +} + +.select2-container--bootstrap .select2-selection--single.input-sm .select2-selection__arrow b, +.input-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b, +.form-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b { + margin-left: -5px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-sm, +.input-group-sm .select2-container--bootstrap .select2-selection--multiple, +.form-group-sm .select2-container--bootstrap .select2-selection--multiple { + min-height: 30px; + border-radius: 3px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-selection__choice, +.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice, +.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice { + font-size: 12px; + line-height: 1.5; + margin: 4px 0 0 5px; + padding: 0 5px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-search--inline .select2-search__field, +.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field, +.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field { + padding: 0 10px; + font-size: 12px; + height: 28px; + line-height: 1.5; +} + +.select2-container--bootstrap .select2-selection--multiple.input-sm .select2-selection__clear, +.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear, +.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear { + margin-top: 5px; +} + +.select2-container--bootstrap .select2-selection--single.input-lg, +.input-group-lg .select2-container--bootstrap .select2-selection--single, +.form-group-lg .select2-container--bootstrap .select2-selection--single { + border-radius: 6px; + font-size: 18px; + height: 46px; + line-height: 1.3333333; + padding: 10px 31px 10px 16px; + /* 1 */ +} + +.select2-container--bootstrap .select2-selection--single.input-lg .select2-selection__arrow, +.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow, +.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow { + width: 5px; +} + +.select2-container--bootstrap .select2-selection--single.input-lg .select2-selection__arrow b, +.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b, +.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b { + border-width: 5px 5px 0 5px; + margin-left: -5px; + margin-left: -10px; + margin-top: -2.5px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-lg, +.input-group-lg .select2-container--bootstrap .select2-selection--multiple, +.form-group-lg .select2-container--bootstrap .select2-selection--multiple { + min-height: 46px; + border-radius: 6px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-selection__choice, +.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice, +.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice { + font-size: 18px; + line-height: 1.3333333; + border-radius: 4px; + margin: 9px 0 0 8px; + padding: 0 10px; +} + +.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-search--inline .select2-search__field, +.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field, +.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field { + padding: 0 16px; + font-size: 18px; + height: 44px; + line-height: 1.3333333; +} + +.select2-container--bootstrap .select2-selection--multiple.input-lg .select2-selection__clear, +.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear, +.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear { + margin-top: 10px; +} + +.select2-container--bootstrap .select2-selection.input-lg.select2-container--open .select2-selection--single { + /** + * Make the dropdown arrow point up while the dropdown is visible. + */ +} + +.select2-container--bootstrap .select2-selection.input-lg.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #999 transparent; + border-width: 0 5px 5px 5px; +} + +.input-group-lg .select2-container--bootstrap .select2-selection.select2-container--open .select2-selection--single { + /** + * Make the dropdown arrow point up while the dropdown is visible. + */ +} + +.input-group-lg .select2-container--bootstrap .select2-selection.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #999 transparent; + border-width: 0 5px 5px 5px; +} + +.select2-container--bootstrap[dir="rtl"] { + /** + * Single Select2 + * + * 1. Makes sure that .select2-selection__placeholder is positioned + * correctly. + */ + /** + * Multiple Select2 + */ +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--single { + padding-left: 24px; + padding-right: 12px; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__rendered { + padding-right: 0; + padding-left: 0; + text-align: right; + /* 1 */ +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__clear { + float: left; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__arrow { + left: 12px; + right: auto; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--single .select2-selection__arrow b { + margin-left: 0; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__choice, +.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder { + float: right; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + margin-left: 0; + margin-right: 6px; +} + +.select2-container--bootstrap[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { + margin-left: 2px; + margin-right: auto; +} + +/*------------------------------------* #ADDITIONAL GOODIES +\*------------------------------------*/ +/** + * Address Bootstrap's validation states + * + * If a Select2 widget parent has one of Bootstrap's validation state modifier + * classes, adjust Select2's border colors and focus states accordingly. + * You may apply said classes to the Select2 dropdown (body > .select2-container) + * via JavaScript match Bootstraps' to make its styles match. + * + * @see http://getbootstrap.com/css/#forms-control-validation + */ +.has-warning .select2-dropdown, +.has-warning .select2-selection { + border-color: #8a6d3b; +} + +.has-warning .select2-container--focus .select2-selection, +.has-warning .select2-container--open .select2-selection { + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + border-color: #66512c; +} + +.has-warning.select2-drop-active { + border-color: #66512c; +} + +.has-warning.select2-drop-active.select2-drop.select2-drop-above { + border-top-color: #66512c; +} + +.has-error .select2-dropdown, +.has-error .select2-selection { + border-color: #a94442; +} + +.has-error .select2-container--focus .select2-selection, +.has-error .select2-container--open .select2-selection { + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + border-color: #843534; +} + +.has-error.select2-drop-active { + border-color: #843534; +} + +.has-error.select2-drop-active.select2-drop.select2-drop-above { + border-top-color: #843534; +} + +.has-success .select2-dropdown, +.has-success .select2-selection { + border-color: #3c763d; +} + +.has-success .select2-container--focus .select2-selection, +.has-success .select2-container--open .select2-selection { + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + border-color: #2b542c; +} + +.has-success.select2-drop-active { + border-color: #2b542c; +} + +.has-success.select2-drop-active.select2-drop.select2-drop-above { + border-top-color: #2b542c; +} + +/** + * Select2 widgets in Bootstrap Input Groups + * + * When Select2 widgets are combined with other elements using Bootstraps + * "Input Group" component, we don't want specific edges of the Select2 + * container to have a border-radius. + * + * Use .select2-bootstrap-prepend and .select2-bootstrap-append on + * a Bootstrap 3 .input-group to let the contained Select2 widget know which + * edges should not be rounded as they are directly followed by another element. + * + * @see http://getbootstrap.com/components/#input-groups + */ +/** + * Mimick Bootstraps .input-group .form-control styles. + * + * @see https://github.com/twbs/bootstrap/blob/master/less/input-groups.less + */ +.input-group .select2-container--bootstrap { + display: table; + table-layout: fixed; + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; + /** + * Adjust z-index like Bootstrap does to show the focus-box-shadow + * above appended buttons in .input-group and .form-group. + */ +} + +.input-group .select2-container--bootstrap.select2-container--open, .input-group .select2-container--bootstrap.select2-container--focus { + z-index: 3; +} + +.input-group.select2-bootstrap-prepend .select2-container--bootstrap .select2-selection { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +.input-group.select2-bootstrap-append .select2-container--bootstrap .select2-selection { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} + +/** + * Adjust alignment of Bootstrap buttons in Bootstrap Input Groups to address + * Multi Select2's height which - depending on how many elements have been selected - + * may grow taller than its initial size. + * + * @see http://getbootstrap.com/components/#input-groups + */ +.select2-bootstrap-append .select2-container--bootstrap, +.select2-bootstrap-append .input-group-btn, +.select2-bootstrap-append .input-group-btn .btn, +.select2-bootstrap-prepend .select2-container--bootstrap, +.select2-bootstrap-prepend .input-group-btn, +.select2-bootstrap-prepend .input-group-btn .btn { + vertical-align: top; +} + +/** + * Temporary fix for https://github.com/select2/select2-bootstrap-theme/issues/9 + * + * Provides `!important` for certain properties of the class applied to the + * original `<select>` element to hide it. + * + * @see https://github.com/select2/select2/pull/3301 + * @see https://github.com/fk/select2/commit/31830c7b32cb3d8e1b12d5b434dee40a6e753ada + */ +.form-control.select2-hidden-accessible { + position: absolute !important; + width: 1px !important; +} + +/** + * Display override for inline forms + */ +.form-inline .select2-container--bootstrap { + display: inline-block; +} diff --git a/app/assets/stylesheets/vendor/select2.css b/app/assets/stylesheets/vendor/select2.css new file mode 100644 index 000000000..447b2b86c --- /dev/null +++ b/app/assets/stylesheets/vendor/select2.css @@ -0,0 +1,484 @@ +.select2-container { + box-sizing: border-box; + display: inline-block; + margin: 0; + position: relative; + vertical-align: middle; } + .select2-container .select2-selection--single { + box-sizing: border-box; + cursor: pointer; + display: block; + height: 28px; + user-select: none; + -webkit-user-select: none; } + .select2-container .select2-selection--single .select2-selection__rendered { + display: block; + padding-left: 8px; + padding-right: 20px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } + .select2-container .select2-selection--single .select2-selection__clear { + position: relative; } + .select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered { + padding-right: 8px; + padding-left: 20px; } + .select2-container .select2-selection--multiple { + box-sizing: border-box; + cursor: pointer; + display: block; + min-height: 32px; + user-select: none; + -webkit-user-select: none; } + .select2-container .select2-selection--multiple .select2-selection__rendered { + display: inline-block; + overflow: hidden; + padding-left: 8px; + text-overflow: ellipsis; + white-space: nowrap; } + .select2-container .select2-search--inline { + float: left; } + .select2-container .select2-search--inline .select2-search__field { + box-sizing: border-box; + border: none; + font-size: 100%; + margin-top: 5px; + padding: 0; } + .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button { + -webkit-appearance: none; } + +.select2-dropdown { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + box-sizing: border-box; + display: block; + position: absolute; + left: -100000px; + width: 100%; + z-index: 1051; } + +.select2-results { + display: block; } + +.select2-results__options { + list-style: none; + margin: 0; + padding: 0; } + +.select2-results__option { + padding: 6px; + user-select: none; + -webkit-user-select: none; } + .select2-results__option[aria-selected] { + cursor: pointer; } + +.select2-container--open .select2-dropdown { + left: 0; } + +.select2-container--open .select2-dropdown--above { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--open .select2-dropdown--below { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-search--dropdown { + display: block; + padding: 4px; } + .select2-search--dropdown .select2-search__field { + padding: 4px; + width: 100%; + box-sizing: border-box; } + .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button { + -webkit-appearance: none; } + .select2-search--dropdown.select2-search--hide { + display: none; } + +.select2-close-mask { + border: 0; + margin: 0; + padding: 0; + display: block; + position: fixed; + left: 0; + top: 0; + min-height: 100%; + min-width: 100%; + height: auto; + width: auto; + opacity: 0; + z-index: 99; + background-color: #fff; + filter: alpha(opacity=0); } + +.select2-hidden-accessible { + border: 0 !important; + clip: rect(0 0 0 0) !important; + height: 1px !important; + margin: -1px !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + width: 1px !important; } + +.select2-container--default .select2-selection--single { + background-color: #fff; + border: 1px solid #aaa; + border-radius: 4px; } + .select2-container--default .select2-selection--single .select2-selection__rendered { + color: #444; + line-height: 28px; } + .select2-container--default .select2-selection--single .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; } + .select2-container--default .select2-selection--single .select2-selection__placeholder { + color: #999; } + .select2-container--default .select2-selection--single .select2-selection__arrow { + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; } + .select2-container--default .select2-selection--single .select2-selection__arrow b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; } + +.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear { + float: left; } + +.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow { + left: 1px; + right: auto; } + +.select2-container--default.select2-container--disabled .select2-selection--single { + background-color: #eee; + cursor: default; } + .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear { + display: none; } + +.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; } + +.select2-container--default .select2-selection--multiple { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + cursor: text; } + .select2-container--default .select2-selection--multiple .select2-selection__rendered { + box-sizing: border-box; + list-style: none; + margin: 0; + padding: 0 5px; + width: 100%; } + .select2-container--default .select2-selection--multiple .select2-selection__rendered li { + list-style: none; } + .select2-container--default .select2-selection--multiple .select2-selection__placeholder { + color: #999; + margin-top: 5px; + float: left; } + .select2-container--default .select2-selection--multiple .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + margin-top: 5px; + margin-right: 10px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice { + background-color: #e4e4e4; + border: 1px solid #aaa; + border-radius: 4px; + cursor: default; + float: left; + margin-right: 5px; + margin-top: 5px; + padding: 0 5px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { + color: #999; + cursor: pointer; + display: inline-block; + font-weight: bold; + margin-right: 2px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { + color: #333; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline { + float: right; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + margin-left: 5px; + margin-right: auto; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { + margin-left: 2px; + margin-right: auto; } + +.select2-container--default.select2-container--focus .select2-selection--multiple { + border: solid black 1px; + outline: 0; } + +.select2-container--default.select2-container--disabled .select2-selection--multiple { + background-color: #eee; + cursor: default; } + +.select2-container--default.select2-container--disabled .select2-selection__choice__remove { + display: none; } + +.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple { + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--default .select2-search--dropdown .select2-search__field { + border: 1px solid #aaa; } + +.select2-container--default .select2-search--inline .select2-search__field { + background: transparent; + border: none; + outline: 0; + box-shadow: none; + -webkit-appearance: textfield; } + +.select2-container--default .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; } + +.select2-container--default .select2-results__option[role=group] { + padding: 0; } + +.select2-container--default .select2-results__option[aria-disabled=true] { + color: #999; } + +.select2-container--default .select2-results__option[aria-selected=true] { + background-color: #ddd; } + +.select2-container--default .select2-results__option .select2-results__option { + padding-left: 1em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__group { + padding-left: 0; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option { + margin-left: -1em; + padding-left: 2em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -2em; + padding-left: 3em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -3em; + padding-left: 4em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -4em; + padding-left: 5em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -5em; + padding-left: 6em; } + +.select2-container--default .select2-results__option--highlighted[aria-selected] { + background-color: #5897fb; + color: white; } + +.select2-container--default .select2-results__group { + cursor: default; + display: block; + padding: 6px; } + +.select2-container--classic .select2-selection--single { + background-color: #f7f7f7; + border: 1px solid #aaa; + border-radius: 4px; + outline: 0; + background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%); + background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%); + background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } + .select2-container--classic .select2-selection--single:focus { + border: 1px solid #5897fb; } + .select2-container--classic .select2-selection--single .select2-selection__rendered { + color: #444; + line-height: 28px; } + .select2-container--classic .select2-selection--single .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + margin-right: 10px; } + .select2-container--classic .select2-selection--single .select2-selection__placeholder { + color: #999; } + .select2-container--classic .select2-selection--single .select2-selection__arrow { + background-color: #ddd; + border: none; + border-left: 1px solid #aaa; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; + background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%); + background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%); + background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); } + .select2-container--classic .select2-selection--single .select2-selection__arrow b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; } + +.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear { + float: left; } + +.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow { + border: none; + border-right: 1px solid #aaa; + border-radius: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + left: 1px; + right: auto; } + +.select2-container--classic.select2-container--open .select2-selection--single { + border: 1px solid #5897fb; } + .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow { + background: transparent; + border: none; } + .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; } + +.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; + background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%); + background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%); + background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } + +.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%); + background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%); + background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); } + +.select2-container--classic .select2-selection--multiple { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + cursor: text; + outline: 0; } + .select2-container--classic .select2-selection--multiple:focus { + border: 1px solid #5897fb; } + .select2-container--classic .select2-selection--multiple .select2-selection__rendered { + list-style: none; + margin: 0; + padding: 0 5px; } + .select2-container--classic .select2-selection--multiple .select2-selection__clear { + display: none; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice { + background-color: #e4e4e4; + border: 1px solid #aaa; + border-radius: 4px; + cursor: default; + float: left; + margin-right: 5px; + margin-top: 5px; + padding: 0 5px; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove { + color: #888; + cursor: pointer; + display: inline-block; + font-weight: bold; + margin-right: 2px; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover { + color: #555; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + float: right; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + margin-left: 5px; + margin-right: auto; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { + margin-left: 2px; + margin-right: auto; } + +.select2-container--classic.select2-container--open .select2-selection--multiple { + border: 1px solid #5897fb; } + +.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--classic .select2-search--dropdown .select2-search__field { + border: 1px solid #aaa; + outline: 0; } + +.select2-container--classic .select2-search--inline .select2-search__field { + outline: 0; + box-shadow: none; } + +.select2-container--classic .select2-dropdown { + background-color: white; + border: 1px solid transparent; } + +.select2-container--classic .select2-dropdown--above { + border-bottom: none; } + +.select2-container--classic .select2-dropdown--below { + border-top: none; } + +.select2-container--classic .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; } + +.select2-container--classic .select2-results__option[role=group] { + padding: 0; } + +.select2-container--classic .select2-results__option[aria-disabled=true] { + color: grey; } + +.select2-container--classic .select2-results__option--highlighted[aria-selected] { + background-color: #3875d7; + color: white; } + +.select2-container--classic .select2-results__group { + cursor: default; + display: block; + padding: 6px; } + +.select2-container--classic.select2-container--open .select2-dropdown { + border-color: #5897fb; } diff --git a/app/controllers/referential_companies_controller.rb b/app/controllers/referential_companies_controller.rb index 104deba9f..a369488ba 100644 --- a/app/controllers/referential_companies_controller.rb +++ b/app/controllers/referential_companies_controller.rb @@ -27,7 +27,7 @@ class ReferentialCompaniesController < ChouetteController end def collection - @q = referential.companies.search(params[:q]) + @q = referential.workbench.companies.search(params[:q]) @companies ||= @q.result(:distinct => true).order(:name).paginate(:page => params[:page]) end diff --git a/app/controllers/referential_group_of_lines_controller.rb b/app/controllers/referential_group_of_lines_controller.rb index d40fd6090..4decef558 100644 --- a/app/controllers/referential_group_of_lines_controller.rb +++ b/app/controllers/referential_group_of_lines_controller.rb @@ -55,7 +55,7 @@ class ReferentialGroupOfLinesController < ChouetteController end def collection - @q = referential.group_of_lines.search(params[:q]) + @q = referential.workbench.group_of_lines.search(params[:q]) @group_of_lines ||= @q.result(:distinct => true).order(:name).paginate(:page => params[:page]) end diff --git a/app/controllers/referential_networks_controller.rb b/app/controllers/referential_networks_controller.rb index 2d3f4ad6b..00c680c65 100644 --- a/app/controllers/referential_networks_controller.rb +++ b/app/controllers/referential_networks_controller.rb @@ -35,7 +35,7 @@ class ReferentialNetworksController < ChouetteController end def collection - @q = referential.networks.search(params[:q]) + @q = referential.workbench.networks.search(params[:q]) @networks ||= @q.result(:distinct => true).order(:name).paginate(:page => params[:page]) end diff --git a/app/controllers/referentials_controller.rb b/app/controllers/referentials_controller.rb index 3ae59f975..003c85d3a 100644 --- a/app/controllers/referentials_controller.rb +++ b/app/controllers/referentials_controller.rb @@ -57,11 +57,7 @@ class ReferentialsController < BreadcrumbController end def create_resource(referential) - if referential.created_from - referential.clone_association referential.created_from - else - referential.organisation = current_organisation - end + referential.organisation = current_organisation unless referential.created_from super end diff --git a/app/controllers/stop_areas_controller.rb b/app/controllers/stop_areas_controller.rb index 8f6a1565a..1f55b1de8 100644 --- a/app/controllers/stop_areas_controller.rb +++ b/app/controllers/stop_areas_controller.rb @@ -26,6 +26,7 @@ class StopAreasController < BreadcrumbController end def add_children + authorize stop_area @stop_area = stop_area @children = stop_area.children build_breadcrumb :edit diff --git a/app/models/organisation.rb b/app/models/organisation.rb index 86386772c..31443d1c7 100644 --- a/app/models/organisation.rb +++ b/app/models/organisation.rb @@ -39,20 +39,22 @@ class Organisation < ActiveRecord::Base end end + def self.sync_update code, name, scope + org = Organisation.find_or_initialize_by(code: code) + if scope + org.sso_attributes ||= {} + org.sso_attributes[:functional_scope] = scope + end + org.name = name + org.synced_at = Time.now + org.save + org + end + def self.portail_sync self.portail_api_request.each do |el| - Organisation.find_or_create_by(code: el['code']).tap do |org| - org.name = el['name'] - if el['functional_scope'] - org.sso_attributes ||= {} - org.sso_attributes[:functional_scope] = el['functional_scope'].delete('\\"') - end - if org.changed? - org.synced_at = Time.now - org.save - puts "✓ Organisation #{org.name} has been updated" unless Rails.env.test? - end - end + org = self.sync_update el['code'], el['name'], el['functional_scope'] + puts "✓ Organisation #{org.name} has been updated" unless Rails.env.test? end end end diff --git a/app/models/referential.rb b/app/models/referential.rb index afadf5edd..8b8df3294 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -30,7 +30,7 @@ class Referential < ActiveRecord::Base validates_presence_of :line_referential belongs_to :created_from, class_name: 'Referential' - has_many :lines, through: :line_referential + has_many :associated_lines, through: :line_referential, source: :lines has_many :companies, through: :line_referential has_many :group_of_lines, through: :line_referential has_many :networks, through: :line_referential @@ -43,6 +43,10 @@ class Referential < ActiveRecord::Base has_many :stop_areas, through: :stop_area_referential belongs_to :workbench + def lines + workbench ? workbench.lines : associated_lines + end + def slug_excluded_values if ! slug.nil? if slug.start_with? "pg_" @@ -128,13 +132,6 @@ class Referential < ActiveRecord::Base }) end - def clone_association from - self.organisation = from.organisation - self.line_referential = from.line_referential - self.stop_area_referential = from.stop_area_referential - self.workbench = from.workbench - end - def self.available_srids [ [ "RGF 93 Lambert 93 (2154)", 2154 ], @@ -171,7 +168,8 @@ class Referential < ActiveRecord::Base projection_type || "" end - before_validation :assign_line_and_stop_area_referential, :on => :create, if: :workbench + before_validation :assign_line_and_stop_area_referential, :on => :create, if: :workbench, unless: :created_from + before_validation :clone_associations, :on => :create, if: :created_from before_create :create_schema after_create :create_referential_metadata, if: :workbench, unless: :created_from @@ -185,6 +183,13 @@ class Referential < ActiveRecord::Base self.referential_metadatas.create end + def clone_associations + self.organisation = created_from.organisation + self.line_referential = created_from.line_referential + self.stop_area_referential = created_from.stop_area_referential + self.workbench = created_from.workbench + end + def clone_referential_metadatas self.created_from.referential_metadatas.each do |meta| self.referential_metadatas << ReferentialMetadata.new_from(meta) diff --git a/app/models/user.rb b/app/models/user.rb index 8f0c32c54..5cfdf0605 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -29,16 +29,10 @@ class User < ActiveRecord::Base after_destroy :check_destroy_organisation def cas_extra_attributes=(extra_attributes) - extra = extra_attributes.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo} - self.name = extra[:full_name] - self.email = extra[:email] - - self.organisation = Organisation.find_or_create_by(code: extra[:organisation_code]).tap do |org| - org.name = extra[:organisation_name] - org.sso_attributes ||= {} - org.sso_attributes[:functional_scope] = extra[:functional_scope].delete('\\"') if extra[:functional_scope] - org.synced_at = Time.now - end + extra = extra_attributes.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo} + self.name = extra[:full_name] + self.email = extra[:email] + self.organisation = Organisation.sync_update extra[:organisation_code], extra[:organisation_name], extra[:functional_scope] end def self.portail_api_request @@ -60,25 +54,14 @@ class User < ActiveRecord::Base def self.portail_sync self.portail_api_request.each do |el| - User.find_or_create_by(username: el['username']).tap do |user| - user.name = "#{el['firstname']} #{el['lastname']}" - user.email = el['email'] - user.locked_at = el['locked_at'] - - # Set organisation - user.organisation = Organisation.find_or_create_by(code: el['organization_code']).tap do |org| - org.name = el['organization_name'] - org.sso_attributes ||= {} - org.sso_attributes[:functional_scope] = el['functional_scope'].delete('\\"') if el['functional_scope'] - org.synced_at = Time.now - end - - if user.changed? - user.synced_at = Time.now - user.save - puts "✓ user #{user.username} has been updated" unless Rails.env.test? - end - end + user = User.find_or_initialize_by(username: el['username']) + user.name = "#{el['firstname']} #{el['lastname']}" + user.email = el['email'] + user.locked_at = el['locked_at'] + user.organisation = Organisation.sync_update el['organization_code'], el['organization_name'], el['functional_scope'] + user.synced_at = Time.now + user.save + puts "✓ user #{user.username} has been updated" unless Rails.env.test? end end diff --git a/app/models/workbench.rb b/app/models/workbench.rb index 3525fe55e..a83fea70d 100644 --- a/app/models/workbench.rb +++ b/app/models/workbench.rb @@ -3,6 +3,12 @@ class Workbench < ActiveRecord::Base belongs_to :line_referential belongs_to :stop_area_referential + has_many :lines, -> (workbench) { Stif::MyWorkbenchScopes.new(workbench).line_scope(self) }, through: :line_referential + has_many :networks, through: :line_referential + has_many :companies, through: :line_referential + has_many :group_of_lines, through: :line_referential + has_many :stop_areas, through: :stop_area_referential + validates :name, presence: true validates :organisation, presence: true diff --git a/app/views/referential_companies/_company.html.slim b/app/views/referential_companies/_company.html.slim index 06e13764e..e6090540d 100644 --- a/app/views/referential_companies/_company.html.slim +++ b/app/views/referential_companies/_company.html.slim @@ -2,10 +2,12 @@ .panel-heading .panel-title.clearfix span.pull-right - = link_to edit_referential_company_path(@referential, company), class: 'btn btn-default btn-sm' do - span.fa.fa-pencil - = link_to referential_company_path(@referential, company), :method => :delete, :data => {:confirm => t('companies.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm' do - span.fa.fa-trash-o + - if policy(company).update? + = link_to edit_referential_company_path(@referential, company), class: 'btn btn-default btn-sm' do + span.fa.fa-pencil + - if policy(company).destroy? + = link_to referential_company_path(@referential, company), :method => :delete, :data => {:confirm => t('companies.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm' do + span.fa.fa-trash-o h5 = link_to [@referential, company], class: 'preview', title: "#{Chouette::Company.model_name.human.capitalize} #{company.name}" do span.name @@ -13,4 +15,4 @@ .panel-body p = company.human_attribute_name('code') - = company.code
\ No newline at end of file + = company.code diff --git a/app/views/referential_companies/index.html.slim b/app/views/referential_companies/index.html.slim index b32f206ca..6af6d7fc8 100644 --- a/app/views/referential_companies/index.html.slim +++ b/app/views/referential_companies/index.html.slim @@ -19,6 +19,7 @@ - content_for :sidebar do ul.actions - li - = link_to t('companies.actions.new'), new_referential_company_path(@referential), class: 'add' - br
\ No newline at end of file + - if policy(Chouette::Company).create? + li + = link_to t('companies.actions.new'), new_referential_company_path(@referential), class: 'add' + br diff --git a/app/views/referential_companies/show.html.slim b/app/views/referential_companies/show.html.slim index a445dad61..a1a767bbd 100644 --- a/app/views/referential_companies/show.html.slim +++ b/app/views/referential_companies/show.html.slim @@ -44,12 +44,15 @@ - content_for :sidebar do ul.actions - li - = link_to t('companies.actions.new'), new_referential_company_path(@referential), class: 'add' - li - = link_to t('companies.actions.edit'), edit_referential_company_path(@referential, @company), class: 'edit' - li - = link_to t('companies.actions.destroy'), referential_company_path(@referential, @company), :method => :delete, :data => {:confirm => t('companies.actions.destroy_confirm')}, class: 'remove' - br - - = creation_tag(@company)
\ No newline at end of file + - if policy(Chouette::Company).create? + li + = link_to t('companies.actions.new'), new_referential_company_path(@referential), class: 'add' + - if policy(@company).update? + li + = link_to t('companies.actions.edit'), edit_referential_company_path(@referential, @company), class: 'edit' + - if policy(@company).destroy? + li + = link_to t('companies.actions.destroy'), referential_company_path(@referential, @company), :method => :delete, :data => {:confirm => t('companies.actions.destroy_confirm')}, class: 'remove' + br + + = creation_tag(@company) diff --git a/app/views/referential_lines/_line.html.slim b/app/views/referential_lines/_line.html.slim index 0dffb50aa..1c8b8eaa8 100644 --- a/app/views/referential_lines/_line.html.slim +++ b/app/views/referential_lines/_line.html.slim @@ -3,7 +3,7 @@ ul.ce-LineBlock-header-list li = check_box_tag "ids[]", line.id, false, class: "multiple_selection", style: "display: none;" - + - if line.number && line.number.length <= 3 span.label.label-default.line_number style="#{number_style(line)}" = line.number @@ -13,11 +13,11 @@ h5.ce-LineBlock-header-title = truncate(line.name, length: 24) li - - if edit + - if edit && policy(Chouette::Line).update? = link_to edit_referential_line_path(@referential, line), class: 'btn btn-default btn-sm' do span.fa.fa-pencil - - if delete + - if delete && policy(Chouette::Line).destroy? = link_to referential_line_path(@referential, line), method: :delete, data: { confirm: t('lines.actions.destroy_confirm') }, class: 'btn btn-danger btn-sm' do span.fa.fa-trash-o @@ -46,4 +46,4 @@ = line.human_attribute_name('group_of_line') = link_to_if( line.group_of_lines.first, line.group_of_lines.first.name, referential_group_of_line_path(@referential, line.group_of_lines.first), :title => "#{line.human_attribute_name('group_of_line')} #{line.group_of_lines.first.name}") - else - = t('lines.form.several_group_of_lines', :count => line.group_of_lines.count)
\ No newline at end of file + = t('lines.form.several_group_of_lines', :count => line.group_of_lines.count) diff --git a/app/views/referential_lines/index.html.slim b/app/views/referential_lines/index.html.slim index 4922cde85..5647bde0c 100644 --- a/app/views/referential_lines/index.html.slim +++ b/app/views/referential_lines/index.html.slim @@ -24,25 +24,27 @@ - content_for :sidebar do ul.actions - li - = link_to t('lines.actions.new'), new_referential_line_path(@referential), class: 'add' + - if policy(Chouette::Line).create? + li + = link_to t('lines.actions.new'), new_referential_line_path(@referential), class: 'add' - #multiple_selection_menu - h4> = t(".multi_selection") + - if policy(Chouette::Line).destroy? + #multiple_selection_menu + h4> = t(".multi_selection") - .disabled - a.enable href="#" - = t(".multi_selection_enable") + .disabled + a.enable href="#" + = t(".multi_selection_enable") - .enabled style="display: none;" - a.disable href="#" - = t(".multi_selection_disable") + .enabled style="display: none;" + a.disable href="#" + = t(".multi_selection_disable") - ul.actions - = link_to t(".delete_selected"), referential_lines_path(@referential), "data-multiple-method" => "delete", :class => "remove", "confirmation-text" => t("lines.actions.destroy_selection_confirm") + ul.actions + = link_to t(".delete_selected"), referential_lines_path(@referential), "data-multiple-method" => "delete", :class => "remove", "confirmation-text" => t("lines.actions.destroy_selection_confirm") a.select_all href="#" = t(".select_all") = " | " a.deselect_all href="#" - = t(".deselect_all")
\ No newline at end of file + = t(".deselect_all") diff --git a/app/views/referential_lines/show.html.slim b/app/views/referential_lines/show.html.slim index ae8314a14..495f0bda7 100644 --- a/app/views/referential_lines/show.html.slim +++ b/app/views/referential_lines/show.html.slim @@ -121,15 +121,19 @@ h3.routes = t('.itineraries') - content_for :sidebar do ul.actions - li - = link_to t('lines.actions.new'), new_referential_line_path(@referential), class: 'add' - li - = link_to t('lines.actions.edit'), edit_referential_line_path(@referential, @line), class: 'edit' - li - = link_to t('lines.actions.destroy'), referential_line_path(@referential, @line), method: :delete, :data => {:confirm => t('lines.actions.destroy_confirm')}, class: 'remove' + - if policy(Chouette::Line).create? + li + = link_to t('lines.actions.new'), new_referential_line_path(@referential), class: 'add' + - if policy(@line).update? + li + = link_to t('lines.actions.edit'), edit_referential_line_path(@referential, @line), class: 'edit' + - if policy(@line).destroy? + li + = link_to t('lines.actions.destroy'), referential_line_path(@referential, @line), method: :delete, :data => {:confirm => t('lines.actions.destroy_confirm')}, class: 'remove' - if !@line.hub_restricted? || (@line.hub_restricted? && @line.routes.size < 2) - li - = link_to t('routes.actions.new'), new_referential_line_route_path(@referential, @line), class: 'add' + / FIXME #825 + li + / = link_to t('routes.actions.new'), new_referential_line_route_path(@referential, @line), class: 'add' - = creation_tag(@line)
\ No newline at end of file + = creation_tag(@line) diff --git a/app/views/referential_networks/_network.html.slim b/app/views/referential_networks/_network.html.slim index dc1aa6b5c..f7c7b66eb 100644 --- a/app/views/referential_networks/_network.html.slim +++ b/app/views/referential_networks/_network.html.slim @@ -2,13 +2,14 @@ .panel-heading .panel-title.clearfix span.pull-right - = link_to edit_referential_network_path(@referential, network), class: 'btn btn-default btn-sm' do - span.fa.fa-pencil - - = link_to referential_network_path(@referential, network), method: :delete, :data => { :confirm => t('networks.actions.destroy_confirm') }, class: 'btn btn-danger btn-sm' do - span.fa.fa-trash-o + - if policy(network).update? + = link_to edit_referential_network_path(@referential, network), class: 'btn btn-default btn-sm' do + span.fa.fa-pencil + - if policy(network).destroy? + = link_to referential_network_path(@referential, network), method: :delete, :data => { :confirm => t('networks.actions.destroy_confirm') }, class: 'btn btn-danger btn-sm' do + span.fa.fa-trash-o h5 = link_to [@referential, network], class: 'preview', title: "#{Chouette::Network.model_name.human.capitalize} #{network.name}" do span.name - = truncate(network.name, :length => 20)
\ No newline at end of file + = truncate(network.name, :length => 20) diff --git a/app/views/referential_networks/index.html.slim b/app/views/referential_networks/index.html.slim index f3ead931e..e3e9f2a07 100644 --- a/app/views/referential_networks/index.html.slim +++ b/app/views/referential_networks/index.html.slim @@ -19,5 +19,6 @@ - content_for :sidebar do ul.actions li + - if policy(Chouette::Network).create? = link_to t('networks.actions.new'), new_referential_network_path(@referential), class: 'add' - br
\ No newline at end of file + br diff --git a/app/views/referential_networks/show.html.slim b/app/views/referential_networks/show.html.slim index 936f6a4a8..d579d311b 100644 --- a/app/views/referential_networks/show.html.slim +++ b/app/views/referential_networks/show.html.slim @@ -36,12 +36,15 @@ - content_for :sidebar do ul.actions - li - = link_to t('networks.actions.new'), new_referential_network_path(@referential), class: 'add' - li - = link_to t('networks.actions.edit'), edit_referential_network_path(@referential, @network), class: 'edit' - li - = link_to t('networks.actions.destroy'), referential_network_path(@referential, @network), method: :delete, data: { :confirm => t('networks.actions.destroy_confirm')}, class: 'remove' - br - - = creation_tag(@network)
\ No newline at end of file + - if policy(Chouette::Network).create? + li + = link_to t('networks.actions.new'), new_referential_network_path(@referential), class: 'add' + - if policy(@network).update? + li + = link_to t('networks.actions.edit'), edit_referential_network_path(@referential, @network), class: 'edit' + - if policy(@network).destroy? + li + = link_to t('networks.actions.destroy'), referential_network_path(@referential, @network), method: :delete, data: { :confirm => t('networks.actions.destroy_confirm')}, class: 'remove' + br + + = creation_tag(@network) diff --git a/app/views/referential_stop_areas/_genealogical.html.slim b/app/views/referential_stop_areas/_genealogical.html.slim index a44884c92..162c24d9b 100644 --- a/app/views/referential_stop_areas/_genealogical.html.slim +++ b/app/views/referential_stop_areas/_genealogical.html.slim @@ -5,7 +5,7 @@ h3 = genealogical_title = link_to([@referential, @stop_area.parent], :title => t("area_types.label.#{@stop_area.parent.stop_area_type}") + "#{@stop_area.parent.name}") do = image_tag "map/" + @stop_area.parent.stop_area_type + ".png" = @stop_area.parent.name - + .link = image_tag "icons/link.png" @@ -18,7 +18,7 @@ h3 = genealogical_title .link = image_tag "icons/link.png" - else - .no_parent = + .no_parent .target = image_tag "map/" + @stop_area.stop_area_type + ".png" @@ -51,4 +51,4 @@ h3 = genealogical_title span = route.line.number = link_to([@referential, route.line , route]) do - span = route.name
\ No newline at end of file + span = route.name diff --git a/app/views/referential_stop_areas/_stop_area.html.slim b/app/views/referential_stop_areas/_stop_area.html.slim index f94bd319e..bb9ed7ce3 100644 --- a/app/views/referential_stop_areas/_stop_area.html.slim +++ b/app/views/referential_stop_areas/_stop_area.html.slim @@ -2,11 +2,13 @@ .panel-heading .panel-title.clearfix span.pull-right - = link_to edit_referential_stop_area_path(@referential, stop_area), class: 'btn btn-default btn-sm' do - span.fa.fa-pencil + - if policy(stop_area).update? + = link_to edit_referential_stop_area_path(@referential, stop_area), class: 'btn btn-default btn-sm' do + span.fa.fa-pencil - = link_to referential_stop_area_path(@referential, stop_area), method: :delete, :data => {:confirm => t('stop_areas.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm' do - span.fa.fa-trash-o + - if policy(stop_area).destroy? + = link_to referential_stop_area_path(@referential, stop_area), method: :delete, :data => {:confirm => t('stop_areas.actions.destroy_confirm')}, class: 'btn btn-danger btn-sm' do + span.fa.fa-trash-o h5 = link_to([@referential, stop_area], class: "preview", :title => t("area_types.label.#{stop_area.stop_area_type}") + " #{stop_area.name}") do @@ -34,11 +36,11 @@ - else - stop_area.routing_lines.each do |line| span.label.label-default.line = line.number - + - else = "#{t('.lines')} : " - if stop_area.lines.blank? = t(".no_object") - else - stop_area.lines.each do |line| - span.label.label-default.line = line.number || truncate( line.name, length: 4 )
\ No newline at end of file + span.label.label-default.line = line.number || truncate( line.name, length: 4 ) diff --git a/app/views/referential_stop_areas/index.html.slim b/app/views/referential_stop_areas/index.html.slim index 85bd15d20..1b634b09c 100644 --- a/app/views/referential_stop_areas/index.html.slim +++ b/app/views/referential_stop_areas/index.html.slim @@ -26,7 +26,8 @@ - content_for :sidebar do ul.actions + - if policy(Chouette::StopArea).create? + li + = link_to t('stop_areas.actions.new'), new_referential_stop_area_path(@referential), class: 'add' li - = link_to t('stop_areas.actions.new'), new_referential_stop_area_path(@referential), class: 'add' - li - / = link_to t('stop_areas.actions.default_geometry'), default_geometry_referential_stop_areas_path(@referential), :method => :put, :class => "calculator"
\ No newline at end of file + / = link_to t('stop_areas.actions.default_geometry'), default_geometry_referential_stop_areas_path(@referential), :method => :put, :class => "calculator" diff --git a/app/views/referential_stop_areas/show.html.slim b/app/views/referential_stop_areas/show.html.slim index 76414edf0..2278c4812 100644 --- a/app/views/referential_stop_areas/show.html.slim +++ b/app/views/referential_stop_areas/show.html.slim @@ -109,7 +109,7 @@ p.after_map .genealogical.clearfix - = render "stop_areas/genealogical" + = render "referential_stop_areas/genealogical" - if manage_access_points div @@ -122,22 +122,25 @@ p.after_map tr td ul.actions - li - = link_to t('stop_areas.actions.new'), new_referential_stop_area_path(@referential), class: 'add' - li - = link_to t('stop_areas.actions.edit'), edit_referential_stop_area_path(@referential, @stop_area), class: 'edit' - li - = link_to t('stop_areas.actions.destroy'), referential_stop_area_path(@referential, @stop_area), method: :delete, data: { :confirm => t('stop_areas.actions.destroy_confirm') }, class: 'remove' + - if policy(Chouette::StopArea).new? + li + = link_to t('stop_areas.actions.new'), new_referential_stop_area_path(@referential), class: 'add' + - if policy(@stop_area).update? + li + = link_to t('stop_areas.actions.edit'), edit_referential_stop_area_path(@referential, @stop_area), class: 'edit' + - if policy(@stop_area).destroy? + li + = link_to t('stop_areas.actions.destroy'), referential_stop_area_path(@referential, @stop_area), method: :delete, data: { :confirm => t('stop_areas.actions.destroy_confirm') }, class: 'remove' - if manage_itl - tr - td - h4 = t('.itl_managment') - ul.actions - li - = link_to t('stop_areas.actions.add_routing_lines'), add_routing_lines_referential_stop_area_path(@referential, @stop_area), class: 'add_routing_lines' - li - = link_to t('stop_areas.actions.add_routing_stops'), add_routing_stops_referential_stop_area_path(@referential, @stop_area), class: 'add_routing_stops' + / tr + / td + / h4 = t('.itl_managment') + / ul.actions + / li + / = link_to t('stop_areas.actions.add_routing_lines'), add_routing_lines_referential_stop_area_path(@referential, @stop_area), class: 'add_routing_lines' + / li + / = link_to t('stop_areas.actions.add_routing_stops'), add_routing_stops_referential_stop_area_path(@referential, @stop_area), class: 'add_routing_stops' - else tr @@ -145,17 +148,17 @@ p.after_map h4 = t('.stop_managment') ul.actions li - = link_to t('stop_areas.actions.select_parent'), select_parent_referential_stop_area_path(@referential, @stop_area), class: 'parent' + / = link_to t('stop_areas.actions.select_parent'), select_parent_referential_stop_area_path(@referential, @stop_area), class: 'parent' - if @stop_area.parent == nil li - = link_to t('stop_areas.actions.clone_as_parent'), new_referential_stop_area_stop_area_copy_path(@referential, @stop_area, hierarchy: 'parent'), class: 'clone' + / = link_to t('stop_areas.actions.clone_as_parent'), new_referential_stop_area_stop_area_copy_path(@referential, @stop_area, hierarchy: 'parent'), class: 'clone' - if manage_children li - = link_to t('stop_areas.actions.add_children'), add_children_referential_stop_area_path(@referential, @stop_area), class: 'children' + / = link_to t('stop_areas.actions.add_children'), add_children_referential_stop_area_path(@referential, @stop_area), class: 'children' li - = link_to t('stop_areas.actions.clone_as_child'), new_referential_stop_area_stop_area_copy_path(@referential, @stop_area, hierarchy: 'child'), class: 'clone' + / = link_to t('stop_areas.actions.clone_as_child'), new_referential_stop_area_stop_area_copy_path(@referential, @stop_area, hierarchy: 'child'), class: 'clone' - if manage_access_points tr @@ -163,9 +166,9 @@ p.after_map h4 = t(".access_managment") ul.actions li - = link_to t('access_points.actions.new'), new_referential_stop_area_access_point_path(@referential,@stop_area), class: 'add' + / = link_to t('access_points.actions.new'), new_referential_stop_area_access_point_path(@referential,@stop_area), class: 'add' li - = link_to t('stop_areas.actions.manage_access_links'), access_links_referential_stop_area_path(@referential,@stop_area), class: 'access_link' + / = link_to t('stop_areas.actions.manage_access_links'), access_links_referential_stop_area_path(@referential,@stop_area), class: 'access_link' br diff --git a/app/views/referentials/_counts.html.slim b/app/views/referentials/_counts.html.slim index fc3ad251e..9754ebc99 100644 --- a/app/views/referentials/_counts.html.slim +++ b/app/views/referentials/_counts.html.slim @@ -67,4 +67,4 @@ li.list-group-item span.badge = @referential.access_points.size = image_tag "map/access_in_out.png" - = Referential.human_attribute_name("access_points")
\ No newline at end of file + = Referential.human_attribute_name("access_points") diff --git a/app/views/referentials/index.html.slim b/app/views/referentials/index.html.slim index e37f157de..c03943ac7 100644 --- a/app/views/referentials/index.html.slim +++ b/app/views/referentials/index.html.slim @@ -14,12 +14,3 @@ / FIXME #823 - if false li = link_to t('referentials.actions.new'), new_referential_path, class: 'add' - - ul - / FIXME #820 - / Don't blame me. See #820 - li = link_to 'Données Reflex', stop_area_referential_path(1) - - / FIXME #824 - / Don't blame me. See #824 - li = link_to 'Données CodifLigne', line_referential_path(1) diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim index 044a745ec..1fc8f108f 100644 --- a/app/views/referentials/show.html.slim +++ b/app/views/referentials/show.html.slim @@ -66,6 +66,7 @@ h2 li = link_to t('referentials.actions.destroy'), referential_path(@referential), method: :delete, data: {:confirm => t('referentials.actions.destroy_confirm')}, class: "remove" li = link_to t('api_keys.actions.new'), new_referential_api_key_path(@referential), class: 'add' + li = link_to t('referentials.actions.clone'), new_referential_path(from: @referential.id), class: 'add' br h4 = t('.clean_up') diff --git a/app/views/routes/_form.html.slim b/app/views/routes/_form.html.slim index d23188fa1..32d738de1 100644 --- a/app/views/routes/_form.html.slim +++ b/app/views/routes/_form.html.slim @@ -1,3 +1,56 @@ += simple_form_for [@referential, @line, @route] do |f| + .row + .col-lg-4.col-md-4.col-sm-4.col-xs-4 + = f.input :name + .col-lg-4.col-md-4.col-sm-4.col-xs-4 + = f.input :published_name + .col-lg-4.col-md-4.col-sm-4.col-xs-4 + = f.input :number + + .row + .col-lg-6.col-md-6.col-sm-5.col-xs-5 + = f.input :comment + .col-lg-6.col-md-6.col-sm-7.col-xs-7 + = f.input :opposite_route, collection: @line.routes.select { |r| r.id != @route.id } + + .row + .col-lg-4.col-md-4.col-sm-4.col-xs-4 + = f.input :direction, include_blank: false + .col-lg-4.col-md-4.col-sm-4.col-xs-4 + = f.input :wayback, include_blank: false + .col-lg-4.col-md-4.col-sm-4.col-xs-4 + = f.input :objectid, required: !@route.new_record?, input_html: { title: t("formtastic.titles#{format_restriction_for_locales(@referential)}.route.objectid") } + + .row style="margin-top:20px" + .col-lg-12.col-md-12.col-sm-12.col-xs-12 + #stop_points + / div.clearfix style="margin-bottom:5px" + / label style="margin:0" Arrêts + / .btn.btn-primary.btn-xs.pull-right data-event="add_stop_point" + / span.fa.fa-plus + / = " #{t('routes.actions.add_stop_point')}" + + / = link_to_add_association f, :stop_points, class: 'btn btn-primary btn-xs pull-right' do + / span.fa.fa-plus + / = " #{t('routes.actions.add_stop_point')}" + / THIS IS BROKEN + / = link_to t('routes.actions.new_stop_point'), new_referential_stop_area_path(@referential), target: '_blank' + + / .list-group + / = f.simple_fields_for :stop_points do |point| + / = render 'stop_point_fields', f: point + + .row + .col-lg-12.col-md-12.col-sm-12.col-xs-12.text-right + = link_to 'Annuler', :back, class: 'btn btn-link' + = f.button :submit, class: 'btn btn-danger' + +// Get JSON data for route stop points += javascript_tag do + | window.itinerary_stop = "#{URI.escape(@route.stop_areas.all.to_json)}" + +/ StopPoints Reactux component += javascript_include_tag 'es6_browserified/stop_points.js' = semantic_form_for [@referential, @line, @route] do |form| = form.inputs do = form.input :name diff --git a/app/views/routes/_stop_point_fields.html.slim b/app/views/routes/_stop_point_fields.html.slim index 814e882c2..3b51e5e0d 100644 --- a/app/views/routes/_stop_point_fields.html.slim +++ b/app/views/routes/_stop_point_fields.html.slim @@ -1,16 +1,23 @@ -.nested-fields.stop_point.row - = f.inputs do - .col-md-1.resize - = link_to_remove_association "<i class='fa fa-trash-o'></i>".html_safe, f - span.handle alt="#{t('stop_points.index.move')}" title="#{t('stop_points.index.move')}" > - i.fa.fa-arrows - - .col-md-11 - - if f.object.stop_area.nil? || f.object.new_record? - = f.input :id, as: :hidden, :input_html => { :class => "stop_point_id added_stop_point", :value => "" } - = f.input :position, as: :hidden, :input_html => { :class => "position" } +.list-group-item + div style="display:inline-block;vertical-align:middle;width:75%;" + - if f.object.stop_area.nil? || f.object.new_record? + / = f.input :stop_area_id, label: false = f.input :stop_area_id, :label => false, as: :search_stop_area, :json => referential_autocomplete_stop_areas_path(@referential, :format => :json)+"?filter=physical", :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :tokenLimit => 1, :input_html => { :class => "new_stop_point stop_area_id", :"data-pre" => Rabl::Renderer.new('autocomplete_stop_areas/index', [f.object.stop_area].compact, :view_path => 'app/views', :format => :json, :scope => self ).render } - - else - = f.input :id, as: :hidden, :input_html => { class: 'stop_point_id' } - = f.input :position, as: :hidden, :input_html => { class: 'position' } - = f.input :stop_area_id, label: false, as: :search_stop_area, :json => referential_autocomplete_stop_areas_path(@referential, :format => :json)+"?filter=physical", :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :tokenLimit => 1, :input_html => { :class => "stop_area_id", :"data-pre" => Rabl::Renderer.new('autocomplete_stop_areas/index', [f.object.stop_area].compact, :view_path => 'app/views', :format => :json, :scope => self ).render }
\ No newline at end of file + + - else + = "#{@route.stop_areas.find(f.object.stop_area_id).name} " + em.small + = "#{@route.stop_areas.find(f.object.stop_area_id).zip_code} #{@route.stop_areas.find(f.object.stop_area_id).city_name}" + + div.text-right style="display:inline-block;vertical-align:middle;width:25%;" + .btn-group.btn-group-sm style="padding:0;" + .btn.btn-default + span.fa.fa-times + .btn.btn-primary + span.fa.fa-arrow-up + .btn.btn-primary + span.fa.fa-arrow-down + .btn.btn-danger + span.fa.fa-trash + / = link_to_remove_association f, class: 'btn btn-danger', data: {confirm: 'Are you sure?'} do + / span.fa.fa-trash diff --git a/app/views/routes/_test.html.slim b/app/views/routes/_test.html.slim new file mode 100644 index 000000000..deb525d32 --- /dev/null +++ b/app/views/routes/_test.html.slim @@ -0,0 +1,36 @@ +.list-group-item + = f.inputs do + - if f.object.stop_area.nil? || f.object.new_record? + div style="display:inline-block;vertical-align:middle;width:75%;" + span + span.text-danger = "[#{@route.stop_areas.find(f.object.stop_area_id).position.inspect}] " + = @route.stop_areas.find(f.object.stop_area_id).name + + / = f.input :stop_area_id, :label => false, as: :search_stop_area, :json => referential_autocomplete_stop_areas_path(@referential, :format => :json)+"?filter=physical", :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :tokenLimit => 1, :input_html => { :class => "new_stop_point stop_area_id", :"data-pre" => Rabl::Renderer.new('autocomplete_stop_areas/index', [f.object.stop_area].compact, :view_path => 'app/views', :format => :json, :scope => self ).render } + + = f.input :stop_area_id, :label => false, as: :search_stop_area + + = f.input :id, as: :hidden, :input_html => { :class => "stop_point_id added_stop_point", :value => "" } + = f.input :position, as: :hidden, :input_html => { :class => "position" } + + - else + div style="display:inline-block;vertical-align:middle;width:75%;" + span + span.text-danger = "[#{@route.stop_areas.find(f.object.stop_area_id).position.inspect}] " + = @route.stop_areas.find(f.object.stop_area_id).name + + / = f.input :stop_area_id, label: false, as: :search_stop_area, :json => referential_autocomplete_stop_areas_path(@referential, :format => :json)+"?filter=physical", :hint_text => t('search_hint'), :no_result_text => t('no_result_text'),:searching_text => t('searching_term'), :tokenLimit => 1, :input_html => { :class => "stop_area_id", :"data-pre" => Rabl::Renderer.new('autocomplete_stop_areas/index', [f.object.stop_area].compact, :view_path => 'app/views', :format => :json, :scope => self ).render } + + = f.input :id, as: :hidden, :input_html => { class: 'stop_point_id' } + = f.input :position, as: :hidden, :input_html => { class: 'position' } + + div.text-right style="display:inline-block;;vertical-align:middle;width:25%;" + .btn-group.btn-group-sm style="padding:0;" + .btn.btn-default + span.fa.fa-times + .btn.btn-primary + span.fa.fa-arrow-up + .btn.btn-primary + span.fa.fa-arrow-down + = link_to_remove_association f, class: 'btn btn-danger' do + span.fa.fa-trash diff --git a/app/views/routes/edit.html.slim b/app/views/routes/edit.html.slim index 7e2c1f982..a0431dc32 100644 --- a/app/views/routes/edit.html.slim +++ b/app/views/routes/edit.html.slim @@ -1,3 +1,5 @@ = title_tag t('routes.edit.title', route: @route.name ) -== render 'form'
\ No newline at end of file +.row + .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-8.col-sm-offset-2 + == render 'form' diff --git a/app/views/routes/new.html.slim b/app/views/routes/new.html.slim index e91ebf362..51410a2e5 100644 --- a/app/views/routes/new.html.slim +++ b/app/views/routes/new.html.slim @@ -1,3 +1,5 @@ = title_tag t('routes.new.title') -== render 'form'
\ No newline at end of file +.row + .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-8.col-sm-offset-2 + == render 'form' diff --git a/app/views/shared/_header.html.slim b/app/views/shared/_header.html.slim index 27b0139c2..73e705e35 100644 --- a/app/views/shared/_header.html.slim +++ b/app/views/shared/_header.html.slim @@ -7,7 +7,7 @@ nav.navbar.navbar-default.navbar-fixed-top role="navigation" span.icon-bar span.icon-bar span.icon-bar - span.icon-bar.version = APP_VERSION + / span.icon-bar.version = APP_VERSION = link_to referentials_path, class: 'navbar-brand' do / = image_tag("logo_chouette.png") @@ -85,12 +85,12 @@ nav.navbar.navbar-default.navbar-fixed-top role="navigation" = link_to referential_route_sections_path(@referential) do span.badge.pull-right = @referential.route_sections.size = Referential.human_attribute_name("route_sections") - + li = link_to referential_timebands_path(@referential) do span.badge.pull-right = @referential.timebands.size = Referential.human_attribute_name("timebands") - + li = link_to Referential.human_attribute_name("imports"), referential_imports_path(@referential) li @@ -128,4 +128,4 @@ nav.navbar.navbar-default.navbar-fixed-top role="navigation" li = link_to t('layouts.user.sign_out'), destroy_user_session_path, method: :delete li.divider li - = tab_link_to Organisation.model_name.human, organisation_path
\ No newline at end of file + = tab_link_to Organisation.model_name.human, organisation_path diff --git a/config/application.rb b/config/application.rb index 52da477a5..93a4cc8fd 100644 --- a/config/application.rb +++ b/config/application.rb @@ -26,5 +26,8 @@ module ChouetteIhm # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] config.i18n.default_locale = :fr + + # Configure Browserify to use babelify to compile ES6 + config.browserify_rails.commandline_options = "-t [ babelify --presets [ es2015 react ] ]" end end diff --git a/config/deploy.rb b/config/deploy.rb index cd6391ec3..34d1b6e4d 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -23,6 +23,11 @@ ssh_options[:forward_agent] = true require "bundler/capistrano" require 'whenever/capistrano' +require 'capistrano/npm' +set :npm_options, '--production --silent --no-progress' + +after 'deploy:finalize_update', 'npm:install' + # Whenever set :whenever_variables, ->{ "'environment=#{fetch :whenever_environment}&bundle_command=bin/bundle exec&additionnal_path=/var/lib/gems/2.2.0/bin'" } # invoke bin/bundle to use 'correct' ruby environment diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index d2f4ec33a..928236c4a 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -5,4 +5,4 @@ Rails.application.config.assets.version = '1.0' # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -# Rails.application.config.assets.precompile += %w( search.js ) +Rails.application.config.assets.precompile += %w( es6_browserified/*.js ) diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb index d5492e529..472863fa8 100644 --- a/config/initializers/simple_form.rb +++ b/config/initializers/simple_form.rb @@ -5,8 +5,9 @@ SimpleForm.setup do |config| # wrapper, change the order or even add your own to the # stack. The options given below are used to wrap the # whole input. - config.wrappers :default, class: :input, - hint_class: :field_with_hint, error_class: :field_with_errors do |b| + config.wrappers :default, class: 'form-group', + error_class: 'has-error' do |b| + # hint_class: :field_with_hint, error_class: :field_with_errors do |b| ## Extensions enabled by default # Any of these extensions can be disabled for a # given input by passing: `f.input EXTENSION_NAME => false`. @@ -41,8 +42,8 @@ SimpleForm.setup do |config| ## Inputs b.use :label_input - b.use :hint, wrap_with: { tag: :span, class: :hint } b.use :error, wrap_with: { tag: :span, class: :error } + b.use :hint, wrap_with: { tag: :span, class: :hint } ## full_messages_for # If you want to display the full error message for the attribute, you can @@ -72,7 +73,7 @@ SimpleForm.setup do |config| config.error_notification_tag = :div # CSS class to add for error notification helper. - config.error_notification_class = 'error_notification' + config.error_notification_class = 'alert alert-error' # ID to add for error notification helper. # config.error_notification_id = nil @@ -90,25 +91,24 @@ SimpleForm.setup do |config| # config.collection_wrapper_class = nil # You can wrap each item in a collection of radio/check boxes with a tag, - # defaulting to :span. Please note that when using :boolean_style = :nested, - # SimpleForm will force this option to be a label. + # defaulting to :span. # config.item_wrapper_tag = :span # You can define a class to use in all item wrappers. Defaulting to none. # config.item_wrapper_class = nil # How the label text should be generated altogether with the required text. - # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" } + config.label_text = lambda { |label, required, explicit_label| "#{label} #{required}" } # You can define the class to use on all labels. Default is nil. # config.label_class = nil # You can define the default class to be used on forms. Can be overriden # with `html: { :class }`. Defaulting to none. - # config.default_form_class = nil + config.default_form_class = 'form' # You can define which elements should obtain additional classes - # config.generate_additional_classes_for = [:wrapper, :label, :input] + config.generate_additional_classes_for = [:label, :input] # Whether attributes are required by default (or not). Default is true. # config.required_by_default = true diff --git a/config/initializers/simple_form_bootstrap.rb b/config/initializers/simple_form_bootstrap.rb index 4f4dc23b3..be0f4bf55 100644 --- a/config/initializers/simple_form_bootstrap.rb +++ b/config/initializers/simple_form_bootstrap.rb @@ -14,8 +14,8 @@ SimpleForm.setup do |config| b.use :label, class: 'control-label' b.use :input, class: 'form-control' - b.use :error, wrap_with: { tag: 'span', class: 'help-block' } - b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + b.use :error, wrap_with: { tag: 'span', class: 'help-block small' } + b.use :hint, wrap_with: { tag: 'p', class: 'help-block small' } end config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| @@ -26,8 +26,8 @@ SimpleForm.setup do |config| b.use :label, class: 'control-label' b.use :input - b.use :error, wrap_with: { tag: 'span', class: 'help-block' } - b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + b.use :error, wrap_with: { tag: 'span', class: 'help-block small' } + b.use :hint, wrap_with: { tag: 'p', class: 'help-block small' } end config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| @@ -38,8 +38,8 @@ SimpleForm.setup do |config| ba.use :label_input end - b.use :error, wrap_with: { tag: 'span', class: 'help-block' } - b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + b.use :error, wrap_with: { tag: 'span', class: 'help-block small' } + b.use :hint, wrap_with: { tag: 'p', class: 'help-block small' } end config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| @@ -47,8 +47,8 @@ SimpleForm.setup do |config| b.optional :readonly b.use :label, class: 'control-label' b.use :input - b.use :error, wrap_with: { tag: 'span', class: 'help-block' } - b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + b.use :error, wrap_with: { tag: 'span', class: 'help-block small' } + b.use :hint, wrap_with: { tag: 'p', class: 'help-block small' } end config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| @@ -62,8 +62,8 @@ SimpleForm.setup do |config| b.wrapper tag: 'div', class: 'col-sm-9' do |ba| ba.use :input, class: 'form-control' - ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } - ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + ba.use :error, wrap_with: { tag: 'span', class: 'help-block small' } + ba.use :hint, wrap_with: { tag: 'p', class: 'help-block small' } end end @@ -76,8 +76,8 @@ SimpleForm.setup do |config| b.wrapper tag: 'div', class: 'col-sm-9' do |ba| ba.use :input - ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } - ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + ba.use :error, wrap_with: { tag: 'span', class: 'help-block small' } + ba.use :hint, wrap_with: { tag: 'p', class: 'help-block small' } end end @@ -90,8 +90,8 @@ SimpleForm.setup do |config| ba.use :label_input end - wr.use :error, wrap_with: { tag: 'span', class: 'help-block' } - wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + wr.use :error, wrap_with: { tag: 'span', class: 'help-block small' } + wr.use :hint, wrap_with: { tag: 'p', class: 'help-block small' } end end @@ -103,8 +103,8 @@ SimpleForm.setup do |config| b.wrapper tag: 'div', class: 'col-sm-9' do |ba| ba.use :input - ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } - ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + ba.use :error, wrap_with: { tag: 'span', class: 'help-block small' } + ba.use :hint, wrap_with: { tag: 'p', class: 'help-block small' } end end @@ -118,45 +118,32 @@ SimpleForm.setup do |config| b.use :label, class: 'sr-only' b.use :input, class: 'form-control' - b.use :error, wrap_with: { tag: 'span', class: 'help-block' } - b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + b.use :error, wrap_with: { tag: 'span', class: 'help-block small' } + b.use :hint, wrap_with: { tag: 'p', class: 'help-block small' } end - config.wrappers :form_without_label, :tag => 'div', :class => 'form-group', :error_class => 'error' do |b| - + config.wrappers :multi_select, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| b.use :html5 - b.use :placeholder - b.optional :maxlength - b.optional :pattern - b.optional :min_max b.optional :readonly - - b.wrapper tag: 'div', class: 'col-sm-12' do |ba| + b.use :label, class: 'control-label' + b.wrapper tag: 'div', class: 'form-inline' do |ba| ba.use :input, class: 'form-control' - ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } - ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + ba.use :error, wrap_with: { tag: 'span', class: 'help-block small' } + ba.use :hint, wrap_with: { tag: 'p', class: 'help-block small' } end - end - - config.wrappers :nested, :tag => 'span', :error_class => 'has-error' do |b| - b.use :html5 - b.use :placeholder - b.optional :readonly - b.use :input - b.use :error, wrap_with: { tag: 'span', class: 'help-block' } - b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } end - # Wrappers for forms and inputs using the Bootstrap toolkit. # Check the Bootstrap docs (http://getbootstrap.com) # to learn about the different styles for forms and inputs, # buttons and other elements. - config.default_wrapper = :horizontal_form + config.default_wrapper = :vertical_form config.wrapper_mappings = { check_boxes: :vertical_radio_and_checkboxes, radio_buttons: :vertical_radio_and_checkboxes, file: :vertical_file_input, boolean: :vertical_boolean, + datetime: :multi_select, + date: :multi_select, + time: :multi_select } end - diff --git a/config/locales/referentials.en.yml b/config/locales/referentials.en.yml index 3691a8227..4609069c7 100644 --- a/config/locales/referentials.en.yml +++ b/config/locales/referentials.en.yml @@ -24,6 +24,7 @@ en: destroy_confirm: "Do you confirm to destroy this data space ?" destroy: "Destroy this data space" edit: "Edit this data space" + clone: "Clone this data space" errors: pg_excluded: "can't begins with pg_" public_excluded: "public is a reserved value" @@ -81,4 +82,4 @@ en: notice: referential: archived: "The data space has been successfully archived" - unarchived: "The data space has been successfully unarchived"
\ No newline at end of file + unarchived: "The data space has been successfully unarchived" diff --git a/config/locales/referentials.fr.yml b/config/locales/referentials.fr.yml index cada9c3a0..18ef4e8da 100644 --- a/config/locales/referentials.fr.yml +++ b/config/locales/referentials.fr.yml @@ -24,6 +24,7 @@ fr: destroy_confirm: "Etes vous sûr de vouloir supprimer cet espace de données ?" destroy: "Supprimer cet espace de données" edit: "Modifier cet espace de données" + clone: "Cloner cet espace de données" errors: pg_excluded: "ne peut pas commencer par pg_ (valeurs réservées)" public_excluded: "public est une valeur réservée" diff --git a/lib/stif/my_workbench_scopes.rb b/lib/stif/my_workbench_scopes.rb new file mode 100644 index 000000000..89c4e659c --- /dev/null +++ b/lib/stif/my_workbench_scopes.rb @@ -0,0 +1,23 @@ +module Stif + class MyWorkbenchScopes + attr_accessor :workbench + + def initialize(workbench) + @workbench = workbench + end + + def line_scope(initial_scope) + ids = self.parse_functional_scope + ids ? initial_scope.where(objectid: ids) : initial_scope + end + + def parse_functional_scope + return false unless @workbench.organisation.sso_attributes + begin + JSON.parse @workbench.organisation.sso_attributes['functional_scope'] + rescue Exception => e + Rails.logger.error "MyWorkbenchScopes : #{e}" + end + end + end +end diff --git a/lib/tasks/ci.rake b/lib/tasks/ci.rake index 7fca878b6..2b584c08b 100644 --- a/lib/tasks/ci.rake +++ b/lib/tasks/ci.rake @@ -3,6 +3,7 @@ namespace :ci do task :setup do cp "config/database/jenkins.yml", "config/database.yml" sh "RAILS_ENV=test rake db:migrate" + sh "npm install" end def git_branch diff --git a/package.json b/package.json new file mode 100644 index 000000000..99c7916c1 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "something", + "dependencies": { + "babel-polyfill": "^6.16.0", + "babel-preset-es2015": "^6.18.0", + "babel-preset-react": "^6.16.0", + "babelify": "^7.3.0", + "browserify": "^13.1.1", + "browserify-incremental": "^3.1.1", + "react": "^15.3.2", + "react-dom": "^15.3.2", + "react-redux": "^4.4.5", + "react-select2": "^4.0.2", + "redux": "^3.6.0" + }, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } +} diff --git a/spec/features/access_points_spec.rb b/spec/features/access_points_spec.rb index a78545ee4..327c5879a 100644 --- a/spec/features/access_points_spec.rb +++ b/spec/features/access_points_spec.rb @@ -40,24 +40,25 @@ describe "Access points", :type => :feature do end - describe "new" do - it "creates an access point" do - visit referential_stop_area_path(referential, stop_area) - click_link I18n.t("access_points.actions.new") - fill_in "access_point[name]", :with => "My Access Point Name" - click_button(I18n.t('formtastic.create',model: I18n.t('activerecord.models.access_point.one'))) - expect(page).to have_content("My Access Point Name") - end - end + # Fixme #1780 + # describe "new" do + # it "creates an access point" do + # visit referential_stop_area_path(referential, stop_area) + # click_link I18n.t("access_points.actions.new") + # fill_in "access_point[name]", :with => "My Access Point Name" + # click_button(I18n.t('formtastic.create',model: I18n.t('activerecord.models.access_point.one'))) + # expect(page).to have_content("My Access Point Name") + # end + # end - describe "edit" do - it "edits an acess point" do - visit referential_stop_area_access_point_path(referential, stop_area, subject) - click_link I18n.t("access_points.actions.edit") - fill_in "access_point[name]", :with => "My New Access Point Name" - click_button(I18n.t('formtastic.update',model: I18n.t('activerecord.models.access_point.one'))) - expect(page).to have_content("My New Access Point Name") - end - end + # describe "edit" do + # it "edits an acess point" do + # visit referential_stop_area_access_point_path(referential, stop_area, subject) + # click_link I18n.t("access_points.actions.edit") + # fill_in "access_point[name]", :with => "My New Access Point Name" + # click_button(I18n.t('formtastic.update',model: I18n.t('activerecord.models.access_point.one'))) + # expect(page).to have_content("My New Access Point Name") + # end + # end end diff --git a/spec/features/routes_spec.rb b/spec/features/routes_spec.rb index bb4b8ae3b..70f3448ab 100644 --- a/spec/features/routes_spec.rb +++ b/spec/features/routes_spec.rb @@ -41,39 +41,6 @@ describe "Routes", :type => :feature do end end - describe "from line's page, select a route and edit it" do - it "return to line's page with changed name" do - visit referential_line_path(referential,line) - click_link "#{route.name}" - click_link "Modifier cette séquence d'arrêts" - fill_in "route_name", :with => "#{route.name}-changed" - click_button("Modifier séquence d'arrêts") - expect(page).to have_content("#{route.name}-changed") - end - end - - describe "from line's page, select a route and delete it" do - it "return to line's page without route name" do - visit referential_line_path(referential,line) - click_link "#{route.name}" - click_link "Supprimer cette séquence d'arrêts" - expect(page).not_to have_content(route.name) - end - end - - describe "from route's page, select edit boarding/alighting and update it" do - it "Edits boarding/alighting properties on route stops" do - visit referential_line_route_path(referential, line, route) - click_link I18n.t('routes.actions.edit_boarding_alighting') - expect(page).to have_content(I18n.t('routes.edit_boarding_alighting.title')) - stop_points.each do |sp| - expect(page).to have_content(sp.stop_area.name) - expect(page).to have_content(sp.for_boarding) - expect(page).to have_content(sp.for_alighting) - end - end - end - describe "Modifies boarding/alighting properties on route stops" do it "Puts (http) an update request" do #visit edit_boarding_alighting_referential_line_route_path(referential, line, route) diff --git a/spec/models/organisation_spec.rb b/spec/models/organisation_spec.rb index c0aba2eb8..823ee7ea6 100644 --- a/spec/models/organisation_spec.rb +++ b/spec/models/organisation_spec.rb @@ -36,7 +36,7 @@ describe Organisation, :type => :model do it 'should retrieve functional scope' do Organisation.portail_sync org = Organisation.find_by(code: 'RATP') - expect(org.sso_attributes['functional_scope']).to eq "[STIF:CODIFLIGNE:Line:C00840, STIF:CODIFLIGNE:Line:C00086]" + expect(org.sso_attributes['functional_scope']).to eq "[\"STIF:CODIFLIGNE:Line:C00840\", \"STIF:CODIFLIGNE:Line:C00086\"]" end it 'should update existing organisations' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index c20e80ca1..bb43be63e 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -36,7 +36,7 @@ describe User, :type => :model do it 'should store organisation functional_scope' do User.authenticate_with_cas_ticket(ticket) org = Organisation.find_by(code: ticket.extra_attributes[:organisation_code]) - expect(org.sso_attributes['functional_scope']).to eq "[STIF:CODIFLIGNE:Line:C00840, STIF:CODIFLIGNE:Line:C00086]" + expect(org.sso_attributes['functional_scope']).to eq "[\"STIF:CODIFLIGNE:Line:C00840\", \"STIF:CODIFLIGNE:Line:C00086\"]" end it 'should not create a new organisation if organisation is already present' do diff --git a/spec/models/workbench_spec.rb b/spec/models/workbench_spec.rb index 023a65ea2..84149ddb0 100644 --- a/spec/models/workbench_spec.rb +++ b/spec/models/workbench_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' RSpec.describe Workbench, :type => :model do - it 'should have a valid factory' do expect(FactoryGirl.build(:workbench)).to be_valid end @@ -12,4 +11,26 @@ RSpec.describe Workbench, :type => :model do it { should belong_to(:organisation) } it { should belong_to(:line_referential) } it { should belong_to(:stop_area_referential) } + + it { should have_many(:lines).through(:line_referential) } + it { should have_many(:networks).through(:line_referential) } + it { should have_many(:companies).through(:line_referential) } + it { should have_many(:group_of_lines).through(:line_referential) } + + it { should have_many(:stop_areas).through(:stop_area_referential) } + + context '.lines' do + let!(:ids) { ['STIF:CODIFLIGNE:Line:C00840', 'STIF:CODIFLIGNE:Line:C00086'] } + let!(:organisation) { create :organisation, sso_attributes: { functional_scope: ids.to_json } } + let(:workbench) { create :workbench, organisation: organisation } + + it 'should filter lines based on my organisation functional_scope' do + ids.insert('STIF:CODIFLIGNE:Line:0000').each do |id| + create :line, objectid: id, line_referential: workbench.line_referential + end + lines = workbench.lines + expect(lines.count).to eq 2 + expect(lines.map(&:objectid)).to include(*ids) + end + end end |
