diff options
19 files changed, 104 insertions, 34 deletions
diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js index 5beb80573..1a6c67b6b 100644 --- a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js +++ b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js @@ -118,7 +118,7 @@ const PeriodForm = ({modal, timetable, metas, onOpenAddPeriodForm, onClosePeriod <div className="text-right"> <button type='button' - className='btn btn-outline-primary add_fields' + className='btn btn-outline-primary' onClick={onOpenAddPeriodForm} > Ajouter une période diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js index 1e121b473..314d481d4 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/CreateModal.js @@ -71,6 +71,7 @@ class CreateModal extends Component { <div className='form-group'> <label className='control-label is-required'>Nom public de la mission</label> <MissionSelect2 + selection={this.props.modal.modalProps} onSelect2JourneyPattern={this.props.onSelect2JourneyPattern} isFilter={false} /> diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js index 1f5e5e98f..a6b8dcfa1 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/CompanySelect2.js @@ -27,6 +27,7 @@ class BSelect4 extends React.Component{ theme: 'bootstrap', width: '100%', placeholder: 'Filtrer par transporteur...', + language: require('./fr'), ajax: { url: origin + path + '/companies.json' + '?line_id=' + line, dataType: 'json', diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js index bc93f3905..36aaa5cfd 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/MissionSelect2.js @@ -13,11 +13,12 @@ class BSelect4 extends React.Component{ super(props) } + render() { return ( <Select2 - data={(this.props.isFilter) ? [this.props.filters.query.journeyPattern.published_name] : undefined} - value={(this.props.isFilter) ? this.props.filters.query.journeyPattern.published_name : undefined} + data={(this.props.isFilter) ? [this.props.filters.query.journeyPattern.published_name] : ((this.props.selection.selectedJPModal) ? [this.props.selection.selectedJPModal.published_name] : undefined)} + value={(this.props.isFilter) ? this.props.filters.query.journeyPattern.published_name : ((this.props.selection.selectedJPModal) ? this.props.selection.selectedJPModal.published_name : undefined) } onSelect={(e) => this.props.onSelect2JourneyPattern(e)} multiple={false} ref='journey_pattern_id' @@ -25,6 +26,7 @@ class BSelect4 extends React.Component{ allowClear: false, theme: 'bootstrap', placeholder: 'Filtrer par code, nom ou OID de mission...', + language: require('./fr'), width: '100%', ajax: { url: origin + path + '/journey_patterns_collection.json', @@ -41,7 +43,7 @@ class BSelect4 extends React.Component{ item => _.assign( {}, item, - {text: item.published_name} + { text: '<small><em>Nom: </em></small>' + item.published_name + '<br/><small><em>Code: </em></small>' + item.registration_number + '<br/><small><em>ID: </em></small>' + _.last(_.split(item.object_id, ':')) } ) ) }; @@ -49,6 +51,7 @@ class BSelect4 extends React.Component{ cache: true }, minimumInputLength: 2, + escapeMarkup: function (markup) { return markup; }, templateResult: formatRepo }} /> diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js index c28d8e06f..b236e7d94 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/TimetableSelect2.js @@ -26,6 +26,7 @@ class BSelect4 extends React.Component{ theme: 'bootstrap', width: '100%', placeholder: 'Filtrer par calendrier...', + language: require('./fr'), ajax: { url: origin + path + this.props.chunkURL, dataType: 'json', diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/VJSelect2.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/VJSelect2.js index c54c67f36..cc2ee4b9e 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/VJSelect2.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/VJSelect2.js @@ -30,6 +30,7 @@ class BSelect4b extends React.Component{ theme: 'bootstrap', placeholder: 'Filtrer par ID course...', width: '100%', + language: require('./fr'), ajax: { url: origin + path + '/vehicle_journeys.json', dataType: 'json', diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/fr.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/fr.js new file mode 100644 index 000000000..20154d412 --- /dev/null +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/select2s/fr.js @@ -0,0 +1,9 @@ +module.exports = { + errorLoading:function(){return"Les résultats ne peuvent pas être chargés."}, + inputTooLong:function(e){var t=e.input.length-e.maximum,n="Supprimez "+t+" caractère";return t!==1&&(n+="s"),n}, + inputTooShort:function(e){var t=e.minimum-e.input.length,n="Saisissez "+t+" caractère";return t!==1&&(n+="s"),n}, + loadingMore:function(){return"Chargement de résultats supplémentaires…"}, + maximumSelected:function(e){var t="Vous pouvez seulement sélectionner "+e.maximum+" élément";return e.maximum!==1&&(t+="s"),t}, + noResults:function(){return"Aucun résultat trouvé"}, + searching:function(){return"Recherche en cours…"} +} diff --git a/app/assets/javascripts/select2.coffee b/app/assets/javascripts/select2.coffee index e8d9c313e..07efac6d1 100644 --- a/app/assets/javascripts/select2.coffee +++ b/app/assets/javascripts/select2.coffee @@ -1,20 +1,42 @@ +bind_select2 = (el, cfg = {}) -> + target = $(el) + default_cfg = + theme: 'bootstrap' + language: 'fr' + placeholder: target.data('select2ed-placeholder') + allowClear: true + + target.select2 $.extend({}, default_cfg, cfg) + +bind_select2_ajax = (el, cfg = {}) -> + target = $(el) + cfg = + ajax: + data: (params) -> + q: + "#{target.data('term')}": params.term + url: target.data('url'), + dataType: 'json', + delay: 125, + processResults: (data, params) -> results: data + minimumInputLength: 3 + templateResult: (item) -> + item.text + templateSelection: (item) -> + item.text + + bind_select2(el, cfg) + @select_2 = -> $("[data-select2ed='true']").each -> - target = $(this) - target.select2 - theme: 'bootstrap' - language: 'fr' - placeholder: target.data('select2ed-placeholder') - allowClear: true + bind_select2(this) + + $("[data-select2-ajax='true']").each -> + bind_select2_ajax(this) $('select.form-control.tags').each -> - target = $(this) - target.select2 - theme: 'bootstrap' - language: 'fr' - placeholder: target.data('select2ed-placeholder') - allowClear: true - tags: true + bind_select2(this, {tags: true}) + $(document).on 'turbolinks:load', select_2 diff --git a/app/assets/javascripts/time_table_combinations.coffee b/app/assets/javascripts/time_table_combinations.coffee new file mode 100644 index 000000000..8fd9dadb1 --- /dev/null +++ b/app/assets/javascripts/time_table_combinations.coffee @@ -0,0 +1,8 @@ +$(document).on("change", '#time_table_combination_combined_type', (e) -> + el = $("#time_table_combination_#{$(this).val()}_id") + other = $(".tt_combination_target:not(##{el.attr('id')})") + + if el.length + el.prop('disabled', false).parents('.form-group').removeClass('hidden').show() + other.prop('disabled', true).parents('.form-group').hide() +) diff --git a/app/assets/stylesheets/components/_select2.sass b/app/assets/stylesheets/components/_select2.sass index 2a0863173..960e8b10b 100644 --- a/app/assets/stylesheets/components/_select2.sass +++ b/app/assets/stylesheets/components/_select2.sass @@ -2,6 +2,11 @@ // Select2 Customisation // //-----------------------// +// Dirty hotfix for select2 i18n not working properly +// .select2-results__options +// .select2-results__message, .loading-results +// display: none + .select2-selection__placeholder color: rgba($grey, 0.65) font-style: italic diff --git a/app/controllers/autocomplete_calendars_controller.rb b/app/controllers/autocomplete_calendars_controller.rb new file mode 100644 index 000000000..dbdd1a9fc --- /dev/null +++ b/app/controllers/autocomplete_calendars_controller.rb @@ -0,0 +1,7 @@ +class AutocompleteCalendarsController < ApplicationController + respond_to :json, :only => [:autocomplete] + + def autocomplete + @calendars = Calendar.search(params[:q]).result.paginate(page: params[:page]) + end +end diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb index 0ddfa14bf..7cbc4fe8b 100644 --- a/app/models/chouette/time_table.rb +++ b/app/models/chouette/time_table.rb @@ -499,7 +499,6 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord add_included_day d end end - self.convert_continuous_dates_to_periods end # if remained excluded dates are valid in other tt , remove it from result self.dates.each do |date| diff --git a/app/models/time_table_combination.rb b/app/models/time_table_combination.rb index f9b63340a..ec3c74641 100644 --- a/app/models/time_table_combination.rb +++ b/app/models/time_table_combination.rb @@ -3,15 +3,20 @@ class TimeTableCombination include ActiveModel::Conversion extend ActiveModel::Naming - attr_accessor :source_id, :combined_type, :target_id, :operation + attr_accessor :source_id, :combined_type, :operation, :time_table_id, :calendar_id + + validates_presence_of :source_id, :combined_type, :operation + + validates :time_table_id, presence: true, if: "calendar_id.blank?" + validates :calendar_id, presence: true, if: "time_table_id.blank?" - validates_presence_of :source_id, :combined_type, :operation, :target_id validates_inclusion_of :operation, :in => %w(union intersection disjunction), :allow_nil => true validates_inclusion_of :combined_type, :in => %w(time_table calendar) def clean self.source_id = nil - self.target_id = nil + self.time_table_id = nil + self.calendar_id = nil self.combined_type = nil self.operation = nil self.errors.clear @@ -32,8 +37,9 @@ class TimeTableCombination end def target + id = self.send("#{combined_type}_id") klass = combined_type == 'calendar' ? Calendar : Chouette::TimeTable - target = klass.find target_id + target = klass.find id target = target.convert_to_time_table unless target.is_a? Chouette::TimeTable target end diff --git a/app/views/autocomplete_calendars/autocomplete.rabl b/app/views/autocomplete_calendars/autocomplete.rabl new file mode 100644 index 000000000..9aba2c37b --- /dev/null +++ b/app/views/autocomplete_calendars/autocomplete.rabl @@ -0,0 +1,5 @@ +collection @calendars, :object_root => false +attribute :id, :name, :short_name, :shared +node :text do |cal| + "#{cal.id} - #{cal.name}" +end diff --git a/app/views/autocomplete_time_tables/index.rabl b/app/views/autocomplete_time_tables/index.rabl index 8ec7b314e..f52429e9d 100644 --- a/app/views/autocomplete_time_tables/index.rabl +++ b/app/views/autocomplete_time_tables/index.rabl @@ -5,6 +5,7 @@ node do |time_table| :time_table_bounding => time_table.presenter.time_table_bounding, :composition_info => time_table.presenter.composition_info, :tags => time_table.tags.join(','), + :text => "#{time_table.objectid.parts.try(:third)} - #{time_table.comment}", :day_types => %w(monday tuesday wednesday thursday friday saturday sunday).select{ |d| time_table.send(d) }.map{ |d| time_table.human_attribute_name(d).first(2)}.join('')} end diff --git a/app/views/time_table_combinations/_form.html.slim b/app/views/time_table_combinations/_form.html.slim index 47a5cee73..1cda41597 100644 --- a/app/views/time_table_combinations/_form.html.slim +++ b/app/views/time_table_combinations/_form.html.slim @@ -1,18 +1,12 @@ - h1 = @time_table.comment - = simple_form_for [@referential, @time_table, @combination], html: {class: 'form-horizontal'}, wrapper: :horizontal_form do |form| .row .col-lg-12 = form.input :combined_type, as: :select, collection: ['time_table', 'calendar'] - = form.input :operation, as: :select, collection: TimeTableCombination.operations - = form.input :target_id, as: :select, 'data-select2ed': 'true', collection: Chouette::TimeTable.all.map{|t| [t.comment, t.id]} + = form.input :time_table_id, as: :select, input_html: {class: 'tt_combination_target', data: { select2_ajax: 'true', term: 'comment_cont', url: referential_autocomplete_time_tables_path(@referential, format: :json)}}, disabled: @combination.combined_type != 'time_table', wrapper_html: {class: @combination.combined_type != 'time_table' ? 'hidden' : ''} - = form.input :target_id, as: :select, 'data-select2ed': 'true', collection: Calendar.all.map{|t| [t.name, t.id]}, disabled: true + = form.input :calendar_id, as: :select, input_html: { class: 'tt_combination_target', data: { select2_ajax: 'true', term: 'name_cont', url: autocomplete_calendars_path}}, disabled: @combination.combined_type != 'calendar', wrapper_html: {class: @combination.combined_type != 'calendar' ? 'hidden' : ''} = form.button :submit, t('actions.submit') - / = form.input :combined_id, :label => t('.time_tables'), as: :search_time_table, :json => referential_autocomplete_time_tables_path(@referential, :format => :json), hint_text: t('search_hint'), no_result_text: t('no_result_text'), :searching_text => t('searching_term'), :tokenLimit => 1 - - diff --git a/config/routes.rb b/config/routes.rb index 06f64c4dd..4342052f7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -72,7 +72,9 @@ ChouetteIhm::Application.routes.draw do resources :networks end - resources :calendars + resources :calendars do + get :autocomplete, on: :collection, controller: 'autocomplete_calendars' + end resources :referentials do resources :api_keys diff --git a/spec/controllers/autocomplete_calendars_controller_spec.rb b/spec/controllers/autocomplete_calendars_controller_spec.rb new file mode 100644 index 000000000..3ff75fadf --- /dev/null +++ b/spec/controllers/autocomplete_calendars_controller_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe AutocompleteCalendarsController, type: :controller do + +end diff --git a/spec/models/time_table_combination_spec.rb b/spec/models/time_table_combination_spec.rb index 60dcdb5b0..0a8b3296a 100644 --- a/spec/models/time_table_combination_spec.rb +++ b/spec/models/time_table_combination_spec.rb @@ -51,7 +51,7 @@ describe TimeTableCombination, :type => :model do subject.operation = 'union' subject.source_id = source.id - subject.target_id = combined.id + subject.time_table_id = combined.id subject.combined_type = 'time_table' subject.combine @@ -79,7 +79,7 @@ describe TimeTableCombination, :type => :model do subject.operation = 'intersection' subject.source_id = source.id - subject.target_id = combined.id + subject.time_table_id = combined.id subject.combined_type = 'time_table' subject.combine @@ -111,7 +111,7 @@ describe TimeTableCombination, :type => :model do subject.operation = 'disjunction' subject.source_id = source.id - subject.target_id = combined.id + subject.time_table_id = combined.id subject.combined_type = 'time_table' subject.combine |
