diff options
78 files changed, 783 insertions, 316 deletions
diff --git a/Dockerfile b/Dockerfile index e484de431..17c05110a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,6 +19,7 @@ RUN mkdir /app && apt-get update &&\ apt-get clean && apt-get -y autoremove && rm -rf /var/lib/apt/lists/* && \ cd /app && rm config/database.yml && mv config/database.yml.docker config/database.yml && \ cd /app && rm config/secrets.yml && mv config/secrets.yml.docker config/secrets.yml && \ + mkdir -p /app/tmp/imports && \ mv script/launch-cron /app && \ bundle exec whenever --output '/proc/1/fd/1' --update-crontab stif-boiv --set 'environment=production&bundle_command=bundle exec' --roles=app,db,web @@ -125,7 +125,7 @@ gem 'enumerize', '~> 2.1.2' gem 'deep_cloneable', '~> 2.0.0' gem 'acts-as-taggable-on', '~> 4.0.0' -gem 'acts_as_list', '~> 0.6.0' +gem 'acts_as_list', '~> 0.9.11' gem 'acts_as_tree', '~> 2.1.0', require: 'acts_as_tree' gem 'rabl' diff --git a/Gemfile.lock b/Gemfile.lock index 4fb77eeb9..2071eee78 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -86,7 +86,7 @@ GEM tzinfo (~> 1.1) acts-as-taggable-on (4.0.0) activerecord (>= 4.0) - acts_as_list (0.6.0) + acts_as_list (0.9.11) activerecord (>= 3.0) acts_as_tree (2.1.0) activerecord (>= 3.0.0) @@ -593,7 +593,7 @@ DEPENDENCIES active_attr activerecord-postgis-adapter (~> 3.0.0) acts-as-taggable-on (~> 4.0.0) - acts_as_list (~> 0.6.0) + acts_as_list (~> 0.9.11) acts_as_tree (~> 2.1.0) apartment (~> 1.0.0) awesome_print diff --git a/app/assets/javascripts/smart_date.coffee b/app/assets/javascripts/smart_date.coffee index 48aa1c2f9..9c8b44207 100644 --- a/app/assets/javascripts/smart_date.coffee +++ b/app/assets/javascripts/smart_date.coffee @@ -14,11 +14,16 @@ window.isLeapYear = (year) -> window.smartCorrectDate = -> allSelectors = $(@).parent().children('select') - allVals = allSelectors.map (index, sel) -> - parseInt($(sel).val()) + + yearSelect = allSelectors.filter("[name$='(1i)]']") + monthSelect = allSelectors.filter("[name$='(2i)]']") + daySelect = allSelectors.filter("[name$='(3i)]']") + # We expect [day, month, year], so french + allVals = [daySelect, monthSelect, yearSelect].map (sel, index) -> + parseInt(sel.val()) + correctedDay = correctDay allVals - daySelector = allSelectors.first() - $(daySelector).val(correctedDay) + daySelect.val(correctedDay) $ -> $(document).on 'change', '.smart_date select', smartCorrectDate diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8b66e6097..7f071a6a4 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -12,6 +12,7 @@ class ApplicationController < ActionController::Base # Load helpers in rails engine helper LanguageEngine::Engine.helpers + layout :layout_by_resource def set_locale # I18n.locale = session[:language] || I18n.default_locale @@ -56,4 +57,15 @@ class ApplicationController < ActionController::Base def after_sign_out_path_for(resource_or_scope) new_user_session_path end + + private + + def layout_by_resource + if devise_controller? + "devise" + else + "application" + end + end + end diff --git a/app/controllers/concerns/metadata_controller_support.rb b/app/controllers/concerns/metadata_controller_support.rb index db83e79ae..4dcbfe5d0 100644 --- a/app/controllers/concerns/metadata_controller_support.rb +++ b/app/controllers/concerns/metadata_controller_support.rb @@ -20,7 +20,7 @@ module MetadataControllerSupport def set_modifier_metadata _resource = @resources || [resource] _resource.flatten.each do |r| - r.try :set_metadata!, :modifier_username, user_for_metadata + r.try(:set_metadata!, :modifier_username, user_for_metadata) if r.valid? end end end diff --git a/app/controllers/journey_patterns_collections_controller.rb b/app/controllers/journey_patterns_collections_controller.rb index db92d48f3..c1a307464 100644 --- a/app/controllers/journey_patterns_collections_controller.rb +++ b/app/controllers/journey_patterns_collections_controller.rb @@ -25,6 +25,8 @@ class JourneyPatternsCollectionsController < ChouetteController @q = @q.includes(:stop_points) @ppage = 10 @journey_patterns ||= @q.paginate(page: params[:page], per_page: @ppage).order(:name) + @custom_fields = Chouette::JourneyPattern.custom_fields_definitions(referential.workgroup) + respond_to do |format| format.json do @journey_patterns = @journey_patterns.includes(stop_points: {stop_area: :stop_area_referential}) diff --git a/app/controllers/line_referentials_controller.rb b/app/controllers/line_referentials_controller.rb index 03dab3f8f..e661fbb04 100644 --- a/app/controllers/line_referentials_controller.rb +++ b/app/controllers/line_referentials_controller.rb @@ -2,6 +2,12 @@ class LineReferentialsController < ChouetteController defaults :resource_class => LineReferential + def show + show! do + @line_referential = LineReferentialDecorator.decorate(@line_referential) + end + end + def sync authorize resource, :synchronize? @sync = resource.line_referential_syncs.build diff --git a/app/controllers/merges_controller.rb b/app/controllers/merges_controller.rb index 1ce64ed58..663b6e750 100644 --- a/app/controllers/merges_controller.rb +++ b/app/controllers/merges_controller.rb @@ -1,5 +1,5 @@ class MergesController < ChouetteController - # include PolicyChecker + include PolicyChecker defaults resource_class: Merge belongs_to :workbench diff --git a/app/controllers/stop_area_referentials_controller.rb b/app/controllers/stop_area_referentials_controller.rb index f2d375e49..0e6a54b49 100644 --- a/app/controllers/stop_area_referentials_controller.rb +++ b/app/controllers/stop_area_referentials_controller.rb @@ -1,6 +1,13 @@ class StopAreaReferentialsController < ChouetteController defaults :resource_class => StopAreaReferential + + def show + show! do + @stop_area_referential = StopAreaReferentialDecorator.decorate(@stop_area_referential) + end + end + def sync authorize resource, :synchronize? @sync = resource.stop_area_referential_syncs.build diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb index 2ac8532e0..4ca2293f0 100644 --- a/app/controllers/time_tables_controller.rb +++ b/app/controllers/time_tables_controller.rb @@ -77,7 +77,7 @@ class TimeTablesController < ChouetteController end def index - request.format.kml? ? @per_page = nil : @per_page = 12 + # request.format.kml? ? @per_page = nil : @per_page = 12 index! do |format| format.html { @@ -130,6 +130,7 @@ class TimeTablesController < ChouetteController @time_tables ||= begin time_tables = @q.result(:distinct => true) + sort_column if sort_column == "bounding_dates" time_tables = @q.result(:distinct => false).paginate(page: params[:page], per_page: 10) ids = time_tables.pluck(:id).uniq @@ -186,10 +187,13 @@ class TimeTablesController < ChouetteController private def sort_column - valid_cols = referential.time_tables.column_names - valid_cols << "bounding_dates" - valid_cols << "vehicle_journeys_count" - valid_cols.include?(params[:sort]) ? params[:sort] : 'comment' + @@valid_cols ||= begin + valid_cols = %w(id color comment) + valid_cols << "bounding_dates" + valid_cols << "vehicle_journeys_count" + valid_cols + end + @@valid_cols.include?(params[:sort]) ? params[:sort] : 'comment' end def sort_direction %w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc' diff --git a/app/decorators/line_decorator.rb b/app/decorators/line_decorator.rb index 0e7b6b9ae..077978c36 100644 --- a/app/decorators/line_decorator.rb +++ b/app/decorators/line_decorator.rb @@ -35,11 +35,6 @@ class LineDecorator < AF83::Decorator edit_action_link do |l| l.content {|l| l.primary? ? h.t('actions.edit') : h.t('lines.actions.edit') } end - - action_link on: :index, secondary: :index do |l| - l.content t('lines.actions.new') - l.href { h.new_line_referential_line_path(context[:line_referential]) } - end end ### the option :policy will automatically check for the corresponding method diff --git a/app/decorators/line_referential_decorator.rb b/app/decorators/line_referential_decorator.rb new file mode 100644 index 000000000..1ca0312c3 --- /dev/null +++ b/app/decorators/line_referential_decorator.rb @@ -0,0 +1,13 @@ +class LineReferentialDecorator < AF83::Decorator + decorates LineReferential + + with_instance_decorator do |instance_decorator| + + instance_decorator.action_link policy: :synchronize, primary: :show do |l| + l.content t('actions.sync') + l.href { h. sync_line_referential_path(object.id) } + l.method :post + end + + end +end diff --git a/app/decorators/stop_area_referential_decorator.rb b/app/decorators/stop_area_referential_decorator.rb new file mode 100644 index 000000000..d30501ec9 --- /dev/null +++ b/app/decorators/stop_area_referential_decorator.rb @@ -0,0 +1,13 @@ +class StopAreaReferentialDecorator < AF83::Decorator + decorates StopAreaReferential + + with_instance_decorator do |instance_decorator| + + instance_decorator.action_link policy: :synchronize, primary: :show do |l| + l.content t('actions.sync') + l.href { h. sync_stop_area_referential_path(object.id) } + l.method :post + end + + end +end diff --git a/app/helpers/line_referential_syncs_helper.rb b/app/helpers/line_referential_syncs_helper.rb new file mode 100644 index 000000000..37f08b154 --- /dev/null +++ b/app/helpers/line_referential_syncs_helper.rb @@ -0,0 +1,31 @@ +module LineReferentialSyncsHelper + + def last_line_ref_sync_message(line_ref_sync) + line_ref_sync.line_referential_sync_messages.last + end + + def line_referential_sync_created_at(line_ref_sync) + l(last_line_ref_sync_message(line_ref_sync).created_at, format: :short_with_time) + end + + def line_referential_sync_status(line_ref_sync) + status = line_ref_sync.status + + if %w[new pending].include? status + content_tag :span, '', class: "fa fa-clock-o" + else + cls ='' + cls = 'success' if status == 'successful' + cls = 'danger' if status == 'failed' + + content_tag :span, '', class: "fa fa-circle text-#{cls}" + end + end + + def line_referential_sync_message(line_ref_sync) + last_line_ref_sync_message = last_line_ref_sync_message(line_ref_sync) + data = last_line_ref_sync_message.message_attributes.symbolize_keys! + data[:processing_time] = distance_of_time_in_words(data[:processing_time].to_i) + t("line_referential_sync.message.#{last_line_ref_sync_message.message_key}", last_line_ref_sync_message.message_attributes.symbolize_keys!).html_safe + end +end diff --git a/app/helpers/multiple_selection_toolbox_helper.rb b/app/helpers/multiple_selection_toolbox_helper.rb index 7e02c6d73..012851b4a 100644 --- a/app/helpers/multiple_selection_toolbox_helper.rb +++ b/app/helpers/multiple_selection_toolbox_helper.rb @@ -4,7 +4,7 @@ module MultipleSelectionToolboxHelper # #5206 method too long def multiple_selection_toolbox(actions, collection_name:) links = content_tag :ul do - + # #5206 `if params[:controller]` mieux passer comme parametre si besoin delete_path = nil @@ -19,8 +19,7 @@ module MultipleSelectionToolboxHelper method: :delete, data: { path: delete_path, - # #5206 Missing Translations - confirm: t('actions.are_you_sure') + confirm: t('are_you_sure') }, title: t("actions.#{action}") ) do @@ -38,7 +37,7 @@ module MultipleSelectionToolboxHelper class: 'info-msg' ) - content_tag :div, '', + content_tag :div, '', class: 'select_toolbox noselect', id: "selected-#{collection_name}-action-box" do links + label diff --git a/app/helpers/referentials_helper.rb b/app/helpers/referentials_helper.rb index 9c3852322..a01d901e6 100644 --- a/app/helpers/referentials_helper.rb +++ b/app/helpers/referentials_helper.rb @@ -1,13 +1,15 @@ module ReferentialsHelper # Outputs a green check icon and the text "Oui" or a red exclamation mark # icon and the text "Non" based on `status` - def line_status(status) + def line_status(status, verbose=true) if status - content_tag(:span, nil, class: 'fa fa-exclamation-circle fa-lg text-danger') + - t('activerecord.attributes.line.deactivated') + out = content_tag(:span, nil, class: 'fa fa-exclamation-circle fa-lg text-danger') + out += t('activerecord.attributes.line.deactivated') if verbose + out else - content_tag(:span, nil, class: 'fa fa-check-circle fa-lg text-success') + - t('activerecord.attributes.line.activated') + out = content_tag(:span, nil, class: 'fa fa-check-circle fa-lg text-success') + out += t('activerecord.attributes.line.activated') if verbose + out end end diff --git a/app/helpers/stop_area_referential_syncs_helper.rb b/app/helpers/stop_area_referential_syncs_helper.rb new file mode 100644 index 000000000..3e2837fda --- /dev/null +++ b/app/helpers/stop_area_referential_syncs_helper.rb @@ -0,0 +1,31 @@ +module StopAreaReferentialSyncsHelper + + def last_stop_area_ref_sync_message(stop_area_ref_sync) + stop_area_ref_sync.stop_area_referential_sync_messages.last + end + + def stop_area_referential_sync_created_at(stop_area_ref_sync) + l(last_stop_area_ref_sync_message(stop_area_ref_sync).created_at, format: :short_with_time) + end + + def stop_area_referential_sync_status(stop_area_ref_sync) + status = stop_area_ref_sync.status + + if %w[new pending].include? status + content_tag :span, '', class: "fa fa-clock-o" + else + cls ='' + cls = 'success' if status == 'successful' + cls = 'danger' if status == 'failed' + + content_tag :span, '', class: "fa fa-circle text-#{cls}" + end + end + + def stop_area_referential_sync_message(stop_area_ref_sync) + last_stop_area_ref_sync_message = last_stop_area_ref_sync_message(stop_area_ref_sync) + data = last_stop_area_ref_sync_message.message_attributes.symbolize_keys! + data[:processing_time] = distance_of_time_in_words(data[:processing_time].to_i) + t("stop_area_referential_sync.message.#{last_stop_area_ref_sync_message.message_key}", last_stop_area_ref_sync_message.message_attributes.symbolize_keys!).html_safe + end +end diff --git a/app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js b/app/javascript/helpers/CustomFieldsInputs.js index 827c36b76..abc8097d5 100644 --- a/app/javascript/vehicle_journeys/components/tools/CustomFieldsInputs.js +++ b/app/javascript/helpers/CustomFieldsInputs.js @@ -34,8 +34,21 @@ export default class CustomFieldsInputs extends Component { ref={'custom_fields.' + cf.code} className='form-control' disabled={this.props.disabled} - defaultValue={cf.value} - onChange={(e) => this.props.onUpdate(cf.code, e.target.value) } + value={cf.value} + onChange={(e) => {this.props.onUpdate(cf.code, e.target.value); this.forceUpdate()} } + /> + ) + } + + integerInput(cf){ + return( + <input + type='number' + ref={'custom_fields.' + cf.code} + className='form-control' + disabled={this.props.disabled} + value={cf.value} + onChange={(e) => {this.props.onUpdate(cf.code, e.target.value); this.forceUpdate()} } /> ) } diff --git a/app/javascript/journey_patterns/components/CreateModal.js b/app/javascript/journey_patterns/components/CreateModal.js index 946c13d9c..51f6f6c1b 100644 --- a/app/javascript/journey_patterns/components/CreateModal.js +++ b/app/javascript/journey_patterns/components/CreateModal.js @@ -1,15 +1,17 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import actions from '../actions' +import CustomFieldsInputs from '../../helpers/CustomFieldsInputs' export default class CreateModal extends Component { constructor(props) { super(props) + this.custom_fields = _.assign({}, this.props.custom_fields) } handleSubmit() { if(actions.validateFields(this.refs) == true) { - this.props.onAddJourneyPattern(this.refs) + this.props.onAddJourneyPattern(_.assign({}, this.refs, {custom_fields: this.custom_fields})) this.props.onModalClose() $('#NewJourneyPatternModal').modal('hide') } @@ -78,8 +80,14 @@ export default class CreateModal extends Component { /> </div> </div> + <CustomFieldsInputs + values={this.props.custom_fields} + onUpdate={(code, value) => this.custom_fields[code]["value"] = value} + disabled={false} + /> </div> </div> + <div className='modal-footer'> <button className='btn btn-link' diff --git a/app/javascript/journey_patterns/components/EditModal.js b/app/javascript/journey_patterns/components/EditModal.js index 1960849fb..a23a57f96 100644 --- a/app/javascript/journey_patterns/components/EditModal.js +++ b/app/javascript/journey_patterns/components/EditModal.js @@ -1,19 +1,27 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import actions from '../actions' +import CustomFieldsInputs from '../../helpers/CustomFieldsInputs' export default class EditModal extends Component { constructor(props) { super(props) + this.updateValue = this.updateValue.bind(this) } handleSubmit() { if(actions.validateFields(this.refs) == true) { - this.props.saveModal(this.props.modal.modalProps.index, this.refs) + this.props.saveModal(this.props.modal.modalProps.index, _.assign({}, this.refs, {custom_fields: this.custom_fields})) $('#JourneyPatternModal').modal('hide') } } + updateValue(attribute, e) { + actions.resetValidation(e.currentTarget) + this.props.modal.modalProps.journeyPattern[attribute] = e.target.value + this.forceUpdate() + } + renderModalTitle() { if (this.props.editMode) { return ( @@ -28,6 +36,9 @@ export default class EditModal extends Component { } render() { + if(this.props.modal.modalProps.journeyPattern){ + this.custom_fields = _.assign({}, this.props.modal.modalProps.journeyPattern.custom_fields) + } return ( <div className={ 'modal fade ' + ((this.props.modal.type == 'edit') ? 'in' : '') } id='JourneyPatternModal'> <div className='modal-container'> @@ -48,8 +59,8 @@ export default class EditModal extends Component { className='form-control' disabled={!this.props.editMode} id={this.props.modal.modalProps.index} - defaultValue={this.props.modal.modalProps.journeyPattern.name} - onKeyDown={(e) => actions.resetValidation(e.currentTarget)} + value={this.props.modal.modalProps.journeyPattern.name} + onChange={(e) => this.updateValue('name', e)} required /> </div> @@ -64,8 +75,8 @@ export default class EditModal extends Component { className='form-control' disabled={!this.props.editMode} id={this.props.modal.modalProps.index} - defaultValue={this.props.modal.modalProps.journeyPattern.published_name} - onKeyDown={(e) => actions.resetValidation(e.currentTarget)} + value={this.props.modal.modalProps.journeyPattern.published_name} + onChange={(e) => this.updateValue('published_name', e)} required /> </div> @@ -79,12 +90,19 @@ export default class EditModal extends Component { className='form-control' disabled={!this.props.editMode} id={this.props.modal.modalProps.index} - defaultValue={this.props.modal.modalProps.journeyPattern.registration_number} - onKeyDown={(e) => actions.resetValidation(e.currentTarget)} + value={this.props.modal.modalProps.journeyPattern.registration_number} + onChange={(e) => this.updateValue('registration_number', e)} /> </div> </div> </div> + <div className='row'> + <CustomFieldsInputs + values={this.props.modal.modalProps.journeyPattern.custom_fields} + onUpdate={(code, value) => this.custom_fields[code]["value"] = value} + disabled={!this.props.editMode} + /> + </div> <div> <label className='control-label'>{I18n.attribute_name('journey_pattern', 'checksum')}</label> <input @@ -92,7 +110,7 @@ export default class EditModal extends Component { ref='checksum' className='form-control' disabled='disabled' - defaultValue={this.props.modal.modalProps.journeyPattern.checksum} + value={this.props.modal.modalProps.journeyPattern.checksum} /> </div> </div> diff --git a/app/javascript/journey_patterns/containers/AddJourneyPattern.js b/app/javascript/journey_patterns/containers/AddJourneyPattern.js index b093fd111..9e85afd5e 100644 --- a/app/javascript/journey_patterns/containers/AddJourneyPattern.js +++ b/app/javascript/journey_patterns/containers/AddJourneyPattern.js @@ -7,7 +7,8 @@ const mapStateToProps = (state) => { modal: state.modal, journeyPatterns: state.journeyPatterns, editMode: state.editMode, - status: state.status + status: state.status, + custom_fields: state.custom_fields } } diff --git a/app/javascript/journey_patterns/containers/Modal.js b/app/javascript/journey_patterns/containers/Modal.js index 33ee8583c..fc04843e4 100644 --- a/app/javascript/journey_patterns/containers/Modal.js +++ b/app/javascript/journey_patterns/containers/Modal.js @@ -7,7 +7,8 @@ const mapStateToProps = (state) => { return { editMode: state.editMode, modal: state.modal, - journeyPattern: state.journeyPattern + journeyPattern: state.journeyPattern, + custom_fields: state.custom_fields, } } diff --git a/app/javascript/journey_patterns/reducers/index.js b/app/javascript/journey_patterns/reducers/index.js index 2ffaf86d4..d3a1d29a2 100644 --- a/app/javascript/journey_patterns/reducers/index.js +++ b/app/javascript/journey_patterns/reducers/index.js @@ -12,7 +12,8 @@ const journeyPatternsApp = combineReducers({ journeyPatterns, pagination, stopPointsList, - modal + modal, + custom_fields: (state = [], action) => state }) export default journeyPatternsApp diff --git a/app/javascript/journey_patterns/reducers/journeyPatterns.js b/app/javascript/journey_patterns/reducers/journeyPatterns.js index b046f2b38..1a6a27da6 100644 --- a/app/javascript/journey_patterns/reducers/journeyPatterns.js +++ b/app/javascript/journey_patterns/reducers/journeyPatterns.js @@ -103,7 +103,8 @@ export default function journeyPatterns (state = [], action) { return _.assign({}, j, { name: action.data.name.value, published_name: action.data.published_name.value, - registration_number: action.data.registration_number.value + registration_number: action.data.registration_number.value, + custom_fields: action.data.custom_fields, }) } else { return j diff --git a/app/javascript/packs/journey_patterns/index.js b/app/javascript/packs/journey_patterns/index.js index 075eea13a..bd7df2634 100644 --- a/app/javascript/packs/journey_patterns/index.js +++ b/app/javascript/packs/journey_patterns/index.js @@ -34,7 +34,8 @@ var initialState = { type: '', modalProps: {}, confirmModal: {} - } + }, + custom_fields: window.custom_fields } // const loggerMiddleware = createLogger() diff --git a/app/javascript/time_tables/components/Metas.js b/app/javascript/time_tables/components/Metas.js index d9746a379..186af540a 100644 --- a/app/javascript/time_tables/components/Metas.js +++ b/app/javascript/time_tables/components/Metas.js @@ -76,7 +76,6 @@ export default function Metas({metas, onUpdateDayTypes, onUpdateComment, onUpdat <label htmlFor="" className="control-label col-sm-4">{I18n.attribute_name('time_table', 'tag_list')}</label> <div className="col-sm-8"> <TagsSelect2 - initialTags={metas.initial_tags} tags={metas.tags} onSelect2Tags={(e) => onSelect2Tags(e)} onUnselect2Tags={(e) => onUnselect2Tags(e)} diff --git a/app/javascript/time_tables/components/TagsSelect2.js b/app/javascript/time_tables/components/TagsSelect2.js index dd8d6e9c0..fe610ed58 100644 --- a/app/javascript/time_tables/components/TagsSelect2.js +++ b/app/javascript/time_tables/components/TagsSelect2.js @@ -27,7 +27,7 @@ export default class TagsSelect2 extends Component { return ( <Select2 value={(this.props.tags.length) ? map(this.props.tags, 'id') : undefined} - data={(this.props.initialTags.length) ? this.mapKeys(this.props.initialTags) : undefined} + data={(this.props.tags.length) ? this.mapKeys(this.props.tags) : undefined} onSelect={(e) => this.props.onSelect2Tags(e)} onUnselect={(e) => setTimeout( () => this.props.onUnselect2Tags(e, 150))} multiple={true} @@ -74,4 +74,4 @@ export default class TagsSelect2 extends Component { const formatRepo = (props) => { if(props.name) return props.name -}
\ No newline at end of file +} diff --git a/app/javascript/time_tables/containers/Metas.js b/app/javascript/time_tables/containers/Metas.js index ebccf556e..7bc3ef4e1 100644 --- a/app/javascript/time_tables/containers/Metas.js +++ b/app/javascript/time_tables/containers/Metas.js @@ -24,6 +24,7 @@ const mapDispatchToProps = (dispatch) => { }, onSelect2Tags: (e) => { e.preventDefault() + $(e.target).find('[data-select2-tag]').remove() dispatch(actions.select2Tags(e.params.data)) }, onUnselect2Tags: (e) => { diff --git a/app/javascript/time_tables/reducers/metas.js b/app/javascript/time_tables/reducers/metas.js index 51e1ec149..012f29511 100644 --- a/app/javascript/time_tables/reducers/metas.js +++ b/app/javascript/time_tables/reducers/metas.js @@ -31,11 +31,13 @@ export default function metas(state = {}, action) { return assign({}, state, {color: action.color}) case 'UPDATE_SELECT_TAG': let tags = [...state.tags] - tags.push(action.selectedItem) + if(tags.length == 0 || tags[tags.length-1].name != action.selectedItem.name){ + tags.push(action.selectedItem) + } return assign({}, state, {tags: tags}) case 'UPDATE_UNSELECT_TAG': return assign({}, state, {tags: filter(state.tags, (t) => (t.id != action.selectedItem.id))}) default: return state } -}
\ No newline at end of file +} diff --git a/app/javascript/vehicle_journeys/components/tools/CreateModal.js b/app/javascript/vehicle_journeys/components/tools/CreateModal.js index f49b51f08..1d470cd43 100644 --- a/app/javascript/vehicle_journeys/components/tools/CreateModal.js +++ b/app/javascript/vehicle_journeys/components/tools/CreateModal.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import actions from '../../actions' import MissionSelect2 from './select2s/MissionSelect2' import CompanySelect2 from './select2s/CompanySelect2' -import CustomFieldsInputs from './CustomFieldsInputs' +import CustomFieldsInputs from '../../../helpers/CustomFieldsInputs' export default class CreateModal extends Component { constructor(props) { diff --git a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js index e4e266c79..60d982845 100644 --- a/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js +++ b/app/javascript/vehicle_journeys/components/tools/EditVehicleJourney.js @@ -2,7 +2,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import actions from '../../actions' import CompanySelect2 from './select2s/CompanySelect2' -import CustomFieldsInputs from './CustomFieldsInputs' +import CustomFieldsInputs from '../../../helpers/CustomFieldsInputs' export default class EditVehicleJourney extends Component { constructor(props) { diff --git a/app/models/chouette/journey_pattern.rb b/app/models/chouette/journey_pattern.rb index 830a6a808..5b5015107 100644 --- a/app/models/chouette/journey_pattern.rb +++ b/app/models/chouette/journey_pattern.rb @@ -2,6 +2,7 @@ module Chouette class JourneyPattern < Chouette::TridentActiveRecord has_metadata include ChecksumSupport + include CustomFieldsSupport include JourneyPatternRestrictions include ObjectidSupport @@ -52,12 +53,19 @@ module Chouette end def self.state_permited_attributes item - { + attrs = { name: item['name'], published_name: item['published_name'], registration_number: item['registration_number'], costs: item['costs'] } + attrs["custom_field_values"] = Hash[ + *(item["custom_fields"] || {}) + .map { |k, v| [k, v["value"]] } + .flatten + ] + + attrs end def self.state_create_instance route, item diff --git a/app/models/chouette/purchase_window.rb b/app/models/chouette/purchase_window.rb index e10b106ec..d22674637 100644 --- a/app/models/chouette/purchase_window.rb +++ b/app/models/chouette/purchase_window.rb @@ -46,8 +46,9 @@ module Chouette ] end - # def checksum_attributes - # end - + def color + _color = read_attribute(:color) + _color.present? ? _color : nil + end end end diff --git a/app/models/chouette/route.rb b/app/models/chouette/route.rb index c5e909d7e..a5eab3002 100644 --- a/app/models/chouette/route.rb +++ b/app/models/chouette/route.rb @@ -80,7 +80,11 @@ module Chouette validates :wayback, inclusion: { in: self.wayback.values } after_commit :calculate_costs!, on: [:create, :update], - if: ->() { TomTom.enabled? } + if: ->() { + # Ensure the call back doesn't run during a referential merge + !referential.in_referential_suite? && + TomTom.enabled? + } def duplicate opposite=false overrides = { diff --git a/app/models/chouette/stop_area.rb b/app/models/chouette/stop_area.rb index 4ddc7403b..b933e1944 100644 --- a/app/models/chouette/stop_area.rb +++ b/app/models/chouette/stop_area.rb @@ -436,6 +436,12 @@ module Chouette ActiveSupport::TimeZone[time_zone]&.utc_offset end + def full_time_zone_name + return unless time_zone.present? + return unless ActiveSupport::TimeZone[time_zone].present? + ActiveSupport::TimeZone[time_zone].tzinfo.name + end + def country return unless country_code country = ISO3166::Country[country_code] diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb index b59c95665..29e3808e7 100644 --- a/app/models/chouette/time_table.rb +++ b/app/models/chouette/time_table.rb @@ -16,7 +16,7 @@ module Chouette end ransacker :unaccented_comment, formatter: ->(val){ val.parameterize } do - Arel.sql('unaccent(comment)') + Arel.sql('unaccent(time_tables.comment)') end has_and_belongs_to_many :vehicle_journeys, :class_name => 'Chouette::VehicleJourney' @@ -81,6 +81,11 @@ module Chouette chunk.values.delete_if {|dates| dates.count < 2} end + def color + _color = read_attribute(:color) + _color.present? ? _color : nil + end + def convert_continuous_dates_to_periods chunks = self.continuous_dates diff --git a/app/models/import/gtfs.rb b/app/models/import/gtfs.rb index 70f448132..a20c468c1 100644 --- a/app/models/import/gtfs.rb +++ b/app/models/import/gtfs.rb @@ -56,12 +56,16 @@ class Import::Gtfs < Import::Base attr_accessor :download_host def download_host - @download_host ||= Rails.application.config.rails_host.gsub("http://","") + @download_host ||= Rails.application.config.rails_host end def local_temp_directory - Rails.application.config.try(:import_temporary_directory) || - Rails.root.join('tmp', 'imports') + @local_temp_directory ||= + begin + directory = Rails.application.config.try(:import_temporary_directory) || Rails.root.join('tmp', 'imports') + FileUtils.mkdir_p directory + directory + end end def local_temp_file(&block) @@ -75,11 +79,20 @@ class Import::Gtfs < Import::Base Rails.application.routes.url_helpers.download_workbench_import_path(workbench, id, token: token_download) end + def download_uri + @download_uri ||= + begin + host = download_host + host = "http://#{host}" unless host =~ %r{https?://} + URI.join(host, download_path) + end + end + def download_local_file local_temp_file do |file| begin - Net::HTTP.start(download_host) do |http| - http.request_get(download_path) do |response| + Net::HTTP.start(download_uri.host, download_uri.port) do |http| + http.request_get(download_uri.request_uri) do |response| response.read_body do |segment| file.write segment end diff --git a/app/models/referential.rb b/app/models/referential.rb index 1794126a2..78b719fab 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -78,31 +78,29 @@ class Referential < ApplicationModel alias_method_chain :save, :table_lock_timeout - if Rails.env.development? - def self.force_register_models_with_checksum - paths = Rails.application.paths['app/models'].to_a - Rails.application.railties.each do |tie| - next unless tie.respond_to? :paths - paths += tie.paths['app/models'].to_a - end + def self.force_register_models_with_checksum + paths = Rails.application.paths['app/models'].to_a + Rails.application.railties.each do |tie| + next unless tie.respond_to? :paths + paths += tie.paths['app/models'].to_a + end - paths.each do |path| - next unless File.directory?(path) - Dir.chdir path do - Dir['**/*.rb'].each do |src| - next if src =~ /^concerns/ - # thanks for inconsistent naming ... - if src == "route_control/zdl_stop_area.rb" - RouteControl::ZDLStopArea - next - end - Rails.logger.info "Loading #{src}" - begin - src[0..-4].classify.safe_constantize - rescue => e - Rails.logger.info "Failed: #{e.message}" - nil - end + paths.each do |path| + next unless File.directory?(path) + Dir.chdir path do + Dir['**/*.rb'].each do |src| + next if src =~ /^concerns/ + # thanks for inconsistent naming ... + if src == "route_control/zdl_stop_area.rb" + RouteControl::ZDLStopArea + next + end + Rails.logger.info "Loading #{src}" + begin + src[0..-4].classify.safe_constantize + rescue => e + Rails.logger.info "Failed: #{e.message}" + nil end end end diff --git a/app/policies/merge_policy.rb b/app/policies/merge_policy.rb index 82eb72e08..154dc63f5 100644 --- a/app/policies/merge_policy.rb +++ b/app/policies/merge_policy.rb @@ -8,8 +8,4 @@ class MergePolicy < ApplicationPolicy def create? user.has_permission?('merges.create') end - - def update? - user.has_permission?('merges.update') - end end diff --git a/app/views/api/v1/journey_patterns/show.rabl b/app/views/api/v1/journey_patterns/show.rabl index aac66b6f3..d02781cfa 100644 --- a/app/views/api/v1/journey_patterns/show.rabl +++ b/app/views/api/v1/journey_patterns/show.rabl @@ -1,7 +1,7 @@ object @journey_pattern extends "api/v1/trident_objects/show" -[:id, :name, :published_name, :registration_number, :comment, :checksum].each do |attr| +[:id, :name, :published_name, :registration_number, :comment, :checksum, :custom_fields].each do |attr| attributes attr, :unless => lambda { |m| m.send( attr).nil?} end diff --git a/app/views/journey_patterns_collections/show.html.slim b/app/views/journey_patterns_collections/show.html.slim index b389a1da7..38c7f1b1b 100644 --- a/app/views/journey_patterns_collections/show.html.slim +++ b/app/views/journey_patterns_collections/show.html.slim @@ -20,5 +20,6 @@ | window.perms = #{raw @perms}; | window.features = #{raw @features}; | window.routeCostsUrl = "#{costs_referential_line_route_url(@referential, @route.line, @route, format: :json).html_safe}"; - + | window.custom_fields = #{(@custom_fields.to_json).html_safe}; + = javascript_pack_tag 'journey_patterns/index.js' diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim index 3921c8701..abf39c089 100644 --- a/app/views/layouts/application.html.slim +++ b/app/views/layouts/application.html.slim @@ -17,7 +17,11 @@ html lang=I18n.locale | I18n.locale = '#{I18n.locale}' body - = render 'layouts/navigation/main_nav' + nav#main_nav + // Left menu content + = render 'layouts/navigation/main_nav_left' + // Top menu content + = render 'layouts/navigation/main_nav_top' = render 'layouts/flash_messages', flash: flash = render 'layouts/navigation/page_header' = yield diff --git a/app/views/layouts/devise.html.slim b/app/views/layouts/devise.html.slim new file mode 100644 index 000000000..34a3a3f11 --- /dev/null +++ b/app/views/layouts/devise.html.slim @@ -0,0 +1,28 @@ +doctype html +html lang=I18n.locale + head + meta charset="utf-8" + meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" + + = csrf_meta_tag + + title = t('brandname') + + = stylesheet_link_tag 'base' + = stylesheet_link_tag 'application' + + = javascript_pack_tag 'application' + = javascript_include_tag 'application' + = javascript_tag do + | I18n.locale = '#{I18n.locale}' + + body + nav#main_nav + // Top menu content + = render 'layouts/navigation/main_nav_top' + = render 'layouts/flash_messages', flash: flash + = render 'layouts/navigation/page_header' + = yield + + = render 'shared/development_toolbar' + = yield :javascript diff --git a/app/views/layouts/navigation/_main_nav.html.slim b/app/views/layouts/navigation/_main_nav.html.slim deleted file mode 100644 index 806290223..000000000 --- a/app/views/layouts/navigation/_main_nav.html.slim +++ /dev/null @@ -1,6 +0,0 @@ -nav#main_nav - // Left menu content - = render 'layouts/navigation/main_nav_left' - - // Top menu content - = render 'layouts/navigation/main_nav_top' diff --git a/app/views/layouts/navigation/_main_nav_left_content.html.slim b/app/views/layouts/navigation/_main_nav_left_content.html.slim index e69de29bb..0b55578a7 100644 --- a/app/views/layouts/navigation/_main_nav_left_content.html.slim +++ b/app/views/layouts/navigation/_main_nav_left_content.html.slim @@ -0,0 +1,64 @@ + +- current_organisation.workbenches.each do |workbench| + #menu-items.panel-group + .menu-item.panel + .panel-heading + h4.panel-title + = link_to '#miOne', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do + = t('layouts.navbar.current_offer.other') + + #miOne.panel-collapse.collapse + .list-group + = link_to root_path, class: "list-group-item" do + span = t('layouts.navbar.dashboard') + = link_to workbench_output_path(workbench), class: 'list-group-item' do + span = t('layouts.navbar.workbench_outputs.organisation') + = link_to '#', class: 'list-group-item disabled' do + span = t('layouts.navbar.workbench_outputs.workgroup') + + .menu-item.panel + .panel-heading + h4.panel-title + = link_to '#miTwo', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do + - t('activerecord.models.workbench.one').capitalize + + #miTwo.panel-collapse.collapse + .list-group + = link_to workbench_path(workbench), class: "list-group-item" do + span = t('activerecord.models.referential.other').capitalize + = link_to workbench_imports_path(workbench), class: "list-group-item" do + span = t('activerecord.models.import.other').capitalize + = link_to workbench_exports_path(workbench), class: "list-group-item" do + span = t('activerecord.models.export.other').capitalize + = link_to workgroup_calendars_path(workbench.workgroup), class: 'list-group-item' do + span = t('activerecord.models.calendar.other').capitalize + = link_to workbench_compliance_check_sets_path(workbench), class: 'list-group-item' do + span = t('activerecord.models.compliance_check_set.other').capitalize + = link_to compliance_control_sets_path, class: 'list-group-item' do + span = t('activerecord.models.compliance_control_set.other').capitalize + + .menu-item.panel + .panel-heading + h4.panel-title + = link_to '#miFour', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do + = t('layouts.navbar.line_referential') + + #miFour.panel-collapse.collapse + .list-group + = link_to line_referential_lines_path(workbench.line_referential), class: "list-group-item" do + span = Chouette::Line.t.capitalize + = link_to line_referential_networks_path(workbench.line_referential), class: "list-group-item" do + span = Chouette::Network.t.capitalize + = link_to line_referential_companies_path(workbench.line_referential), class: "list-group-item" do + span = Chouette::Company.t.capitalize + + .menu-item.panel + .panel-heading + h4.panel-title + = link_to '#miFive', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do + = t('layouts.navbar.stop_area_referential') + + #miFive.panel-collapse.collapse + .list-group + = link_to stop_area_referential_stop_areas_path(workbench.stop_area_referential), class: "list-group-item" do + span = Chouette::StopArea.t.capitalize diff --git a/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim b/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim index 3741ef19b..9404eeae6 100644 --- a/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim +++ b/app/views/layouts/navigation/_main_nav_left_content_stif.html.slim @@ -1,109 +1,95 @@ -- @localizationUrl = "#{params[:controller]}##{params[:action]}" - -#menu-items.panel-group - .menu-item.panel - .panel-heading - h4.panel-title - = link_to '#miOne', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do - = t('layouts.navbar.current_offer.other') - - #miOne.panel-collapse.collapse - .list-group - = link_to root_path, class: "list-group-item #{(@localizationUrl == 'workbenches#index') ? 'active' : ''}" do - span = t('layouts.navbar.dashboard') - = link_to workbench_output_path(current_user.workbenches.first), class: 'list-group-item' do - span = t('layouts.navbar.workbench_outputs.organisation') - = link_to '#', class: 'list-group-item' do - span = t('layouts.navbar.workbench_outputs.idf') - - .menu-item.panel - .panel-heading - h4.panel-title - = link_to '#miTwo', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do - - t('activerecord.models.workbench.one').capitalize - - #miTwo.panel-collapse.collapse - .list-group - - current_user.workbenches.each do |current_workbench| - = link_to workbench_path(current_workbench), class: "list-group-item #{params[:controller] == 'workbenches' ? 'active' : ''}" do +- current_organisation.workbenches.each do |workbench| + #menu-items.panel-group + .menu-item.panel + .panel-heading + h4.panel-title + = link_to '#miOne', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do + = t('layouts.navbar.current_offer.other') + + #miOne.panel-collapse.collapse + .list-group + = link_to root_path, class: "list-group-item" do + span = t('layouts.navbar.dashboard') + = link_to workbench_output_path(workbench), class: 'list-group-item' do + span = t('layouts.navbar.workbench_outputs.organisation') + = link_to '#', class: 'list-group-item disabled' do + span = t('layouts.navbar.workbench_outputs.workgroup') + + .menu-item.panel + .panel-heading + h4.panel-title + = link_to '#miTwo', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do + - t('activerecord.models.workbench.one').capitalize + + #miTwo.panel-collapse.collapse + .list-group + = link_to workbench_path(workbench), class: "list-group-item" do span = t('activerecord.models.referential.other').capitalize - = link_to workbench_imports_path(current_workbench), class: "list-group-item #{(params[:controller] == 'imports') ? 'active' : ''}" do + = link_to workbench_imports_path(workbench), class: "list-group-item" do span = t('activerecord.models.import.other').capitalize - = link_to workbench_exports_path(current_workbench), class: "list-group-item #{(params[:controller] == 'exports') ? 'active' : ''}" do + = link_to workbench_exports_path(workbench), class: "list-group-item" do span = t('activerecord.models.export.other').capitalize - = link_to workgroup_calendars_path(current_workbench.workgroup), class: 'list-group-item' do + = link_to workgroup_calendars_path(workbench.workgroup), class: 'list-group-item' do span = t('activerecord.models.calendar.other').capitalize - = link_to workbench_compliance_check_sets_path(current_workbench), class: 'list-group-item' do + = link_to workbench_compliance_check_sets_path(workbench), class: 'list-group-item' do span = t('activerecord.models.compliance_check_set.other').capitalize = link_to compliance_control_sets_path, class: 'list-group-item' do span = t('activerecord.models.compliance_control_set.other').capitalize - .menu-item.panel - .panel-heading - h4.panel-title - = link_to '#miThree', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do - = t('layouts.navbar.referential_datas') + .menu-item.panel + .panel-heading + h4.panel-title + = link_to '#miFour', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do + = t('layouts.navbar.line_referential') - #miThree.panel-collapse.collapse - - if @referential.try(:id) && respond_to?(:current_referential) + #miFour.panel-collapse.collapse .list-group - .list-group-item - = (current_referential.name).upcase - .list-group - = link_to referential_networks_path(current_referential), class: 'list-group-item' do - span = t('networks.index.title') - - = link_to referential_companies_path(current_referential), class: 'list-group-item' do - span = t('companies.index.title') - - = link_to '#', class: 'list-group-item disabled' do - span = t('layouts.navbar.shapes') - - = link_to referential_time_tables_path(current_referential), class: 'list-group-item' do - span = t('time_tables.index.title') - - - else - .panel-body - em.text-muted - = t('layouts.navbar.select_referential_for_more_features') - - .menu-item.panel - .panel-heading - h4.panel-title - = link_to '#miFour', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do - = t('layouts.navbar.sync') - - #miFour.panel-collapse.collapse - .list-group - = link_to line_referential_path(1), class: "list-group-item #{(@localizationUrl == 'line_referentials#show') ? 'active' : ''}" do - span = t('layouts.navbar.sync_ilico') - = link_to stop_area_referential_path(1), class: "list-group-item #{(@localizationUrl == 'stop_area_referentials#show') ? 'active' : ''}" do - span = t('layouts.navbar.sync_icar') - - .menu-item.panel - .panel-heading - h4.panel-title - = link_to '#miFive', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do - = t('layouts.navbar.tools') - - #miFive.panel-collapse.collapse - .list-group - = link_to Rails.application.config.try(:portal_url), target: '_blank', class: 'list-group-item' do - span - span.fa.fa-2x.fa-circle - = t('layouts.navbar.portal') - - = link_to Rails.application.config.try(:codifligne_url), target: '_blank', class: 'list-group-item' do - span - span.fa.fa-2x.fa-circle - = t('layouts.navbar.ilico') - - = link_to Rails.application.config.try(:reflex_url), target: '_blank', class: 'list-group-item' do - span - span.fa.fa-2x.fa-circle - = t('layouts.navbar.icar') - - = link_to '#', target: '_blank', class: 'list-group-item' do - span - span.fa.fa-2x.fa-circle - = t('layouts.navbar.support')
\ No newline at end of file + = link_to line_referential_path(workbench.line_referential), class: "list-group-item" do + span = t('layouts.navbar.sync_ilico') + = link_to line_referential_lines_path(workbench.line_referential), class: "list-group-item" do + span = Chouette::Line.t.capitalize + = link_to line_referential_networks_path(workbench.line_referential), class: "list-group-item" do + span = Chouette::Network.t.capitalize + = link_to line_referential_companies_path(workbench.line_referential), class: "list-group-item" do + span = Chouette::Company.t.capitalize + + .menu-item.panel + .panel-heading + h4.panel-title + = link_to '#miFive', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do + = t('layouts.navbar.stop_area_referential') + + #miFive.panel-collapse.collapse + .list-group + = link_to stop_area_referential_path(workbench.stop_area_referential), class: "list-group-item" do + span = t('layouts.navbar.sync_icar') + = link_to stop_area_referential_stop_areas_path(workbench.stop_area_referential), class: "list-group-item" do + span = Chouette::StopArea.t.capitalize + + .menu-item.panel + .panel-heading + h4.panel-title + = link_to '#miSix', data: {toggle: 'collapse', parent: '#menu-items'}, 'aria-expanded' => 'false' do + = t('layouts.navbar.tools') + + #miSix.panel-collapse.collapse + .list-group + = link_to Rails.application.config.try(:portal_url), target: '_blank', class: 'list-group-item' do + span + span.fa.fa-2x.fa-circle + = t('layouts.navbar.portal') + + = link_to Rails.application.config.try(:codifligne_url), target: '_blank', class: 'list-group-item' do + span + span.fa.fa-2x.fa-circle + = t('layouts.navbar.ilico') + + = link_to Rails.application.config.try(:reflex_url), target: '_blank', class: 'list-group-item' do + span + span.fa.fa-2x.fa-circle + = t('layouts.navbar.icar') + + = link_to '#', target: '_blank', class: 'list-group-item' do + span + span.fa.fa-2x.fa-circle + = t('layouts.navbar.support') diff --git a/app/views/line_referentials/show.html.slim b/app/views/line_referentials/show.html.slim index 763eb076e..1f184b6f2 100644 --- a/app/views/line_referentials/show.html.slim +++ b/app/views/line_referentials/show.html.slim @@ -1,47 +1,29 @@ - breadcrumb :line_referential, @line_referential - page_header_content_for @line_referential -- if policy(@line_referential).synchronize? - - content_for :page_header_actions do - = link_to(t('actions.sync'), sync_line_referential_path(@line_referential), method: :post, class: 'btn btn-default') - -- content_for :page_header_content do - .row.mb-md - .col-lg-12.text-right - = link_to line_referential_companies_path(@line_referential), class: 'btn btn-primary' do - = Referential.human_attribute_name(:companies) - em.small = " (#{@line_referential.companies.size})" - = link_to line_referential_networks_path(@line_referential), class: 'btn btn-primary' do - = Referential.human_attribute_name(:networks) - em.small = " (#{@line_referential.networks.size})" - = link_to line_referential_lines_path(@line_referential), class: 'btn btn-primary' do - = Referential.human_attribute_name(:lines) - em.small = " (#{@line_referential.lines.size})" .page_content .container-fluid .row .col-lg-12 - - unless @line_referential.line_referential_syncs.empty? - table.table - thead - tr - th = t('.synchronized') - th = t('.status') - th = t('.message') + = table_builder_2 @line_referential.line_referential_syncs, + [ \ + TableBuilderHelper::Column.new( \ + name: t('.synchronized'), \ + attribute: Proc.new { |sync| line_referential_sync_created_at(sync) }, \ + ), \ + TableBuilderHelper::Column.new( \ + name: t('.status'), \ + attribute: Proc.new { |sync| line_referential_sync_status(sync) }, \ + ), \ + TableBuilderHelper::Column.new( \ + name: t('.message'), \ + attribute: Proc.new { |sync| line_referential_sync_message(sync) }, \ + ), \ + ], + sortable: false, + cls: 'table' - tbody - - @line_referential.line_referential_syncs.each_with_index do |sync, i| - / Display only 10 msgs - - if i < 10 - - unless sync.line_referential_sync_messages.empty? - - sync.line_referential_sync_messages.last.tap do |log| - - if log.criticity = log.criticity - tr - td style='width: 150px' - = l(log.created_at, format: :short_with_time) - td.text-center - .fa.fa-circle class="text-#{criticity_class(log.criticity)}" - td - - data = log.message_attributes.symbolize_keys! - - data[:processing_time] = distance_of_time_in_words(data[:processing_time].to_i) - = t("line_referential_sync.message.#{log.message_key}", log.message_attributes.symbolize_keys!).html_safe + - unless @line_referential.line_referential_syncs.any? + .row.mt-xs + .col-lg-12 + = replacement_msg t('line_referential_syncs.search_no_results') diff --git a/app/views/lines/show.html.slim b/app/views/lines/show.html.slim index 9e1ae6d6f..b683b9be6 100644 --- a/app/views/lines/show.html.slim +++ b/app/views/lines/show.html.slim @@ -7,13 +7,13 @@ .col-lg-6.col-md-6.col-sm-12.col-xs-12 = definition_list t('metadatas'), { t('objectid') => @line.get_objectid.short_id, - @line.human_attribute_name(:deactivated) => (@line.deactivated? ? t('false') : t('true')), - @line.human_attribute_name(:network_id) => (@line.network.nil? ? t('lines.index.unset') : @line.network.name), - @line.human_attribute_name(:company_id) => (@line.company.nil? ? t('lines.index.unset') : @line.company.name), - @line.human_attribute_name(:secondary_companies) => (@line.secondary_companies.nil? ? t('lines.index.unset') : array_to_html_list(@line.secondary_companies.collect(&:name))), - @line.human_attribute_name(:number) => @line.number, - @line.human_attribute_name(:registration_number) => (@line.registration_number ? @line.registration_number : '-'), - @line.human_attribute_name(:transport_mode) => (@line.transport_mode.present? ? t("enumerize.transport_mode.#{@line.transport_mode}") : '-'), - @line.human_attribute_name(:transport_submode) => (@line.transport_submode.present? ? t("enumerize.transport_submode.#{@line.transport_submode}") : '-'), - @line.human_attribute_name(:url) => (@line.url ? @line.url : '-'), - @line.human_attribute_name(:seasonal) => (@line.seasonal? ? t('true') : t('false')),} + Chouette::Line.tmf(:state) => line_status(@line.deactivated), + Chouette::Line.tmf(:network_id) => (@line.network.nil? ? t('lines.index.unset') : @line.network.name), + Chouette::Line.tmf(:company_id) => (@line.company.nil? ? t('lines.index.unset') : @line.company.name), + Chouette::Line.tmf(:secondary_companies) => (@line.secondary_companies.nil? ? t('lines.index.unset') : array_to_html_list(@line.secondary_companies.collect(&:name))), + Chouette::Line.tmf(:number) => @line.number, + Chouette::Line.tmf(:registration_number) => (@line.registration_number ? @line.registration_number : '-'), + Chouette::Line.tmf(:transport_mode) => (@line.transport_mode.present? ? t("enumerize.transport_mode.#{@line.transport_mode}") : '-'), + Chouette::Line.tmf(:transport_submode) => (@line.transport_submode.present? ? t("enumerize.transport_submode.#{@line.transport_submode}") : '-'), + Chouette::Line.tmf(:url) => (@line.url ? @line.url : '-'), + Chouette::Line.tmf(:seasonal) => (@line.seasonal? ? t('true') : t('false')),} diff --git a/app/views/referential_lines/show.html.slim b/app/views/referential_lines/show.html.slim index 91868a002..4804da527 100644 --- a/app/views/referential_lines/show.html.slim +++ b/app/views/referential_lines/show.html.slim @@ -7,10 +7,10 @@ .col-lg-6.col-md-6.col-sm-12.col-xs-12 = definition_list t('metadatas'), { t('id_codif') => @line.get_objectid.short_id, - Chouette::Line.tmf('activated') => (@line.deactivated? ? t('false') : t('true')), + Chouette::Line.tmf('state') => line_status(@line.deactivated), Chouette::Line.tmf('network_id') => (@line.network.nil? ? t('lines.index.unset') : link_to(@line.network.name, [@referential, @line.network]) ), Chouette::Line.tmf('company') => (@line.company.nil? ? t('lines.index.unset') : link_to(@line.company.name, [@referential, @line.company]) ), - Chouette::Line.tmf('secondary_company') => (@line.secondary_companies.nil? ? t('lines.index.unset') : @line.secondary_companies.collect(&:name).join(', ')), + Chouette::Line.tmf('secondary_companies') => (@line.secondary_companies.nil? ? t('lines.index.unset') : @line.secondary_companies.collect(&:name).join(', ')), Chouette::Line.tmf('registration_number') => @line.number, Chouette::Line.tmf('published_name') => (@line.registration_number ? @line.registration_number : '-'), Chouette::Line.tmf('transport_mode') => (@line.transport_mode.present? ? t("enumerize.transport_mode.#{@line.transport_mode}") : '-'), diff --git a/app/views/stop_area_referentials/show.html.slim b/app/views/stop_area_referentials/show.html.slim index 911006c39..bca89a0f4 100644 --- a/app/views/stop_area_referentials/show.html.slim +++ b/app/views/stop_area_referentials/show.html.slim @@ -1,41 +1,29 @@ - breadcrumb :stop_area_referential, @stop_area_referential -- if policy(@stop_area_referential).synchronize? - - content_for :page_header_actions do - = link_to(t('actions.sync'), sync_stop_area_referential_path(@stop_area_referential), method: :post, class: 'btn btn-default') - -- content_for :page_header_content do - .row.mb-md - .col-lg-12.text-right - = link_to stop_area_referential_stop_areas_path(@stop_area_referential), class: 'btn btn-primary' do - = Referential.human_attribute_name(:stop_areas) - em.small = " (#{@stop_area_referential.stop_areas.count})" - page_header_content_for @stop_area_referential .page_content .container-fluid .row .col-lg-12 - - unless @stop_area_referential.stop_area_referential_syncs.empty? - table.table - thead - tr - th Synchronisé - th Statut - th Message + = table_builder_2 @stop_area_referential.stop_area_referential_syncs, + [ \ + TableBuilderHelper::Column.new( \ + name: t('.synchronized'), \ + attribute: Proc.new { |sync| stop_area_referential_sync_created_at(sync) }, \ + ), \ + TableBuilderHelper::Column.new( \ + name: t('.status'), \ + attribute: Proc.new { |sync| stop_area_referential_sync_status(sync) }, \ + ), \ + TableBuilderHelper::Column.new( \ + name: t('.message'), \ + attribute: Proc.new { |sync| stop_area_referential_sync_message(sync) }, \ + ), \ + ], + sortable: false, + cls: 'table' - tbody - - @stop_area_referential.stop_area_referential_syncs.each_with_index do |sync, i| - / Display only 10 msgs - - if i < 10 - - unless sync.stop_area_referential_sync_messages.empty? - - sync.stop_area_referential_sync_messages.last.tap do |log| - - if log.criticity = log.criticity - tr - td style='width:150px' - = l(log.created_at, format: :short_with_time) - td.text-center - .fa.fa-circle class="text-#{criticity_class(log.criticity)}" - td - - data = log.message_attributes.symbolize_keys! - - data[:processing_time] = distance_of_time_in_words(data[:processing_time].to_i) - = t("stop_area_referential_sync.message.#{log.message_key}", log.message_attributes.symbolize_keys!).html_safe + - unless @stop_area_referential.stop_area_referential_syncs.any? + .row.mt-xs + .col-lg-12 + = replacement_msg t('stop_area_referential_syncs.search_no_results') diff --git a/config/breadcrumbs.rb b/config/breadcrumbs.rb index e57cbc4f2..e60ff187f 100644 --- a/config/breadcrumbs.rb +++ b/config/breadcrumbs.rb @@ -169,7 +169,6 @@ end crumb :companies do |line_referential| link I18n.t('companies.index.title'), line_referential_companies_path(line_referential) - parent :line_referential, line_referential end crumb :company do |company| @@ -179,7 +178,6 @@ end crumb :networks do |line_referential| link I18n.t('networks.index.title'), line_referential_networks_path(line_referential) - parent :line_referential, line_referential end crumb :network do |network| @@ -189,7 +187,6 @@ end crumb :group_of_lines do |line_referential| link I18n.t('group_of_lines.index.title'), line_referential_group_of_lines_path(line_referential) - parent :line_referential, line_referential end crumb :group_of_line do |group_of_line| @@ -199,7 +196,6 @@ end crumb :lines do |line_referential| link I18n.t('lines.index.title'), line_referential_lines_path - parent :line_referential, line_referential end crumb :line do |line| diff --git a/config/locales/layouts.en.yml b/config/locales/layouts.en.yml index 954525ac4..31bff403c 100644 --- a/config/locales/layouts.en.yml +++ b/config/locales/layouts.en.yml @@ -15,12 +15,14 @@ en: return_to_dashboard: "Return to Dashboard" dashboard: Dashboard referential_datas: "Datas" - current_offer: + line_referential: "Line referential" + stop_area_referential: "Stop area referential" + current_offer: one: Current offer other: Current offers workbench_output: organisation: Organisation offers - idf: IDF offers + workgroup: Workgroup offers tools: Tools sync: Synchronization sync_icar: iCAR synchronization @@ -68,4 +70,4 @@ en: attributes: author: "Edited by" created_at: "Created at" - updated_at: "Updated at"
\ No newline at end of file + updated_at: "Updated at" diff --git a/config/locales/layouts.fr.yml b/config/locales/layouts.fr.yml index f125a002d..019c72701 100644 --- a/config/locales/layouts.fr.yml +++ b/config/locales/layouts.fr.yml @@ -15,12 +15,14 @@ fr: return_to_dashboard: "Retour au Tableau de Bord" dashboard: Tableau de bord referential_datas: "Données" - current_offer: + line_referential: "Référentiel de lignes" + stop_area_referential: "Référentiel d'arrêts" + current_offer: one: Offres courante other: Offres courantes workbench_outputs: - organisation: Offres de mon organisation - idf: Offres IDF + organisation: Offre de mon organisation + workgroup: Offre du groupe de travail tools: Outils sync: Synchronisation sync_icar: Synchronisation iCAR diff --git a/config/locales/line_referential_syncs.en.yml b/config/locales/line_referential_syncs.en.yml index 5cbab1173..8d17fcefc 100644 --- a/config/locales/line_referential_syncs.en.yml +++ b/config/locales/line_referential_syncs.en.yml @@ -1,4 +1,6 @@ en: + line_referential_syncs: + search_no_results: "No line referential synchronisation matching your query" activerecord: errors: models: diff --git a/config/locales/line_referential_syncs.fr.yml b/config/locales/line_referential_syncs.fr.yml index 33827fac9..7f1b1ba75 100644 --- a/config/locales/line_referential_syncs.fr.yml +++ b/config/locales/line_referential_syncs.fr.yml @@ -1,4 +1,6 @@ fr: + line_referential_syncs: + search_no_results: "Aucun synchronisation de référentiel de lignes ne correspond à votre recherche" activerecord: errors: models: diff --git a/config/locales/lines.en.yml b/config/locales/lines.en.yml index 1cd5150db..3d1ddc149 100644 --- a/config/locales/lines.en.yml +++ b/config/locales/lines.en.yml @@ -78,7 +78,7 @@ en: name: "Network" company_id: "Company" company: "Company" - secondary_company: "Secondary company" + secondary_companies: "Secondary companies" companies: name: "Company" registration_number: "Registration number" diff --git a/config/locales/lines.fr.yml b/config/locales/lines.fr.yml index 6f4a2e9bf..47baf96f8 100644 --- a/config/locales/lines.fr.yml +++ b/config/locales/lines.fr.yml @@ -79,7 +79,7 @@ fr: name: "Réseau" company_id: "Transporteur principal" company: "Transporteur principal" - secondary_company: "Transporteurs secondaires" + secondary_companies: "Transporteurs secondaires" companies: name: "Transporteur principal" registration_number: "Nom court" diff --git a/config/locales/merges.en.yml b/config/locales/merges.en.yml new file mode 100644 index 000000000..f9e90f1ef --- /dev/null +++ b/config/locales/merges.en.yml @@ -0,0 +1,23 @@ +fr: + merges: + referential_name: "Merged offer %{date}" + index: + title: "Merged offers" + new: + title: "New merged offer" + show: + title: "Merged offer %{name}" + actions: + create: Merge data spaces + activerecord: + models: + merge: "Merged offer" + attributes: + merge: + created_at: "Created at" + started_at: Started at + name: Name + ended_at: Ended at + status: "Status" + creator: "Creator" + referentials: "Data spaces" diff --git a/config/locales/merges.yml b/config/locales/merges.fr.yml index 345727b74..345727b74 100644 --- a/config/locales/merges.yml +++ b/config/locales/merges.fr.yml diff --git a/config/locales/purchase_windows.fr.yml b/config/locales/purchase_windows.fr.yml index 3d5582ead..7f2ec259f 100644 --- a/config/locales/purchase_windows.fr.yml +++ b/config/locales/purchase_windows.fr.yml @@ -27,7 +27,7 @@ fr: show: "Consulter" edit: Editer destroy: Supprimer - destroy_confirm: Etes vous sûr de supprimer cet calendrier commercial ? + destroy_confirm: Etes vous sûr de vouloir supprimer ce calendrier commercial ? errors: overlapped_periods: Une autre période chevauche cette période short_period: "Une période doit être d'une durée de deux jours minimum" diff --git a/config/locales/stop_area_referential_syncs.en.yml b/config/locales/stop_area_referential_syncs.en.yml index 2bfe0bc0a..1605f73f2 100644 --- a/config/locales/stop_area_referential_syncs.en.yml +++ b/config/locales/stop_area_referential_syncs.en.yml @@ -1,4 +1,6 @@ en: + stop_area_referential_syncs: + search_no_results: "No stop area referential synchronisation matching your query" activerecord: errors: models: diff --git a/config/locales/stop_area_referential_syncs.fr.yml b/config/locales/stop_area_referential_syncs.fr.yml index cbed11883..b4ed7202b 100644 --- a/config/locales/stop_area_referential_syncs.fr.yml +++ b/config/locales/stop_area_referential_syncs.fr.yml @@ -1,4 +1,6 @@ fr: + stop_area_referential_syncs: + search_no_results: "Aucun synchronisation de référentiel d'arrêts ne correspond à votre recherche" activerecord: errors: models: diff --git a/config/locales/stop_area_referentials.en.yml b/config/locales/stop_area_referentials.en.yml index 9d49d7c5d..3fa91bc92 100644 --- a/config/locales/stop_area_referentials.en.yml +++ b/config/locales/stop_area_referentials.en.yml @@ -4,7 +4,10 @@ en: sync: "Launch a new reflex synchronization" cancel_sync: "Cancel reflex synchronization" show: - title: 'Stop area referential' + title: 'Synchronization iCAR' + synchronized: Synchronized + status: status + message: Message activerecord: models: stop_area_referential: diff --git a/config/locales/stop_area_referentials.fr.yml b/config/locales/stop_area_referentials.fr.yml index bb4c4463a..956e801f1 100644 --- a/config/locales/stop_area_referentials.fr.yml +++ b/config/locales/stop_area_referentials.fr.yml @@ -5,6 +5,9 @@ fr: cancel_sync: "Annuler la synchronisation Reflex" show: title: 'Synchronisation iCAR' + synchronized: Synchronisé + status: Statut + message: Message activerecord: models: stop_area_referential: diff --git a/config/locales/zzz-stif.yml b/config/locales/zzz-stif.yml new file mode 100644 index 000000000..a9e6a0ef4 --- /dev/null +++ b/config/locales/zzz-stif.yml @@ -0,0 +1,5 @@ +fr: + layouts: + navbar: + workbench_outputs: + workgroup: Offre IDF diff --git a/db/migrate/20180416065012_add_custom_field_values_to_journey_patterns.rb b/db/migrate/20180416065012_add_custom_field_values_to_journey_patterns.rb new file mode 100644 index 000000000..df114488c --- /dev/null +++ b/db/migrate/20180416065012_add_custom_field_values_to_journey_patterns.rb @@ -0,0 +1,5 @@ +class AddCustomFieldValuesToJourneyPatterns < ActiveRecord::Migration + def change + add_column :journey_patterns, :custom_field_values, :jsonb + end +end diff --git a/db/schema.rb b/db/schema.rb index 7e0e9c2b5..d20c9f1f7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,13 +11,14 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180319043333) do +ActiveRecord::Schema.define(version: 20180416065012) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - enable_extension "postgis" enable_extension "hstore" + enable_extension "postgis" enable_extension "unaccent" + enable_extension "objectid" create_table "access_links", id: :bigserial, force: :cascade do |t| t.integer "access_point_id", limit: 8 @@ -92,9 +93,9 @@ ActiveRecord::Schema.define(version: 20180319043333) do t.integer "organisation_id", limit: 8 t.datetime "created_at" t.datetime "updated_at" - t.integer "workgroup_id", limit: 8 t.integer "int_day_types" t.date "excluded_dates", array: true + t.integer "workgroup_id", limit: 8 t.jsonb "metadata", default: {} end @@ -121,6 +122,7 @@ ActiveRecord::Schema.define(version: 20180319043333) do t.datetime "updated_at" t.date "end_date" t.string "date_type" + t.string "mode" end add_index "clean_ups", ["referential_id"], name: "index_clean_ups_on_referential_id", using: :btree @@ -143,10 +145,11 @@ ActiveRecord::Schema.define(version: 20180319043333) do t.text "import_xml" t.datetime "created_at" t.datetime "updated_at" - t.jsonb "custom_field_values" + t.jsonb "custom_field_values", default: {} t.jsonb "metadata", default: {} end + add_index "companies", ["line_referential_id", "registration_number"], name: "index_companies_on_referential_id_and_registration_number", using: :btree add_index "companies", ["line_referential_id"], name: "index_companies_on_line_referential_id", using: :btree add_index "companies", ["objectid"], name: "companies_objectid_key", unique: true, using: :btree add_index "companies", ["registration_number"], name: "companies_registration_number_key", using: :btree @@ -441,7 +444,7 @@ ActiveRecord::Schema.define(version: 20180319043333) do add_index "import_messages", ["resource_id"], name: "index_import_messages_on_resource_id", using: :btree create_table "import_resources", id: :bigserial, force: :cascade do |t| - t.integer "import_id", limit: 8 + t.integer "import_id", limit: 8 t.string "status" t.datetime "created_at" t.datetime "updated_at" @@ -449,9 +452,13 @@ ActiveRecord::Schema.define(version: 20180319043333) do t.string "reference" t.string "name" t.hstore "metrics" + t.integer "referential_id" + t.integer "parent_id" end add_index "import_resources", ["import_id"], name: "index_import_resources_on_import_id", using: :btree + add_index "import_resources", ["parent_id"], name: "index_import_resources_on_parent_id", using: :btree + add_index "import_resources", ["referential_id"], name: "index_import_resources_on_referential_id", using: :btree create_table "imports", id: :bigserial, force: :cascade do |t| t.string "status" @@ -509,6 +516,7 @@ ActiveRecord::Schema.define(version: 20180319043333) do t.string "data_source_ref" t.json "costs" t.jsonb "metadata", default: {} + t.jsonb "custom_field_values" end add_index "journey_patterns", ["objectid"], name: "journey_patterns_objectid_key", unique: true, using: :btree @@ -585,6 +593,7 @@ ActiveRecord::Schema.define(version: 20180319043333) do t.jsonb "metadata", default: {} end + add_index "lines", ["line_referential_id", "registration_number"], name: "index_lines_on_referential_id_and_registration_number", using: :btree add_index "lines", ["line_referential_id"], name: "index_lines_on_line_referential_id", using: :btree add_index "lines", ["objectid"], name: "lines_objectid_key", unique: true, using: :btree add_index "lines", ["registration_number"], name: "lines_registration_number_key", using: :btree @@ -857,14 +866,15 @@ ActiveRecord::Schema.define(version: 20180319043333) do t.integer "waiting_time" t.string "kind" t.jsonb "localized_names" + t.json "custom_field_values" t.datetime "confirmed_at" - t.jsonb "custom_field_values" t.jsonb "metadata", default: {} end add_index "stop_areas", ["name"], name: "index_stop_areas_on_name", using: :btree add_index "stop_areas", ["objectid"], name: "stop_areas_objectid_key", unique: true, using: :btree add_index "stop_areas", ["parent_id"], name: "index_stop_areas_on_parent_id", using: :btree + add_index "stop_areas", ["stop_area_referential_id", "registration_number"], name: "index_stop_areas_on_referential_id_and_registration_number", using: :btree add_index "stop_areas", ["stop_area_referential_id"], name: "index_stop_areas_on_stop_area_referential_id", using: :btree create_table "stop_areas_stop_areas", id: false, force: :cascade do |t| @@ -1058,9 +1068,9 @@ ActiveRecord::Schema.define(version: 20180319043333) do add_index "vehicle_journeys", ["route_id"], name: "index_vehicle_journeys_on_route_id", using: :btree create_table "versions", id: :bigserial, force: :cascade do |t| - t.string "item_type", null: false - t.integer "item_id", limit: 8, null: false - t.string "event", null: false + t.string "item_type", null: false + t.integer "item_id", null: false + t.string "event", null: false t.string "whodunnit" t.text "object" t.datetime "created_at" @@ -1114,6 +1124,7 @@ ActiveRecord::Schema.define(version: 20180319043333) do add_foreign_key "compliance_controls", "compliance_control_blocks" add_foreign_key "compliance_controls", "compliance_control_sets" add_foreign_key "group_of_lines_lines", "group_of_lines", name: "groupofline_group_fkey", on_delete: :cascade + add_foreign_key "import_resources", "referentials" add_foreign_key "journey_frequencies", "timebands", on_delete: :nullify add_foreign_key "journey_frequencies", "vehicle_journeys", on_delete: :nullify add_foreign_key "journey_patterns", "routes", name: "jp_route_fkey", on_delete: :cascade diff --git a/db/seeds/development/custom_fields.seeds.rb b/db/seeds/development/custom_fields.seeds.rb index eb3afc394..61a294bb0 100644 --- a/db/seeds/development/custom_fields.seeds.rb +++ b/db/seeds/development/custom_fields.seeds.rb @@ -40,7 +40,7 @@ Workgroup.find_each do |workgroup| workgroup.custom_fields.seed_by(code: "stop_area_test_integer") do |field| field.resource_type = "StopArea" - field.name = "Test de Nomber" + field.name = "Test de Nombre" field.field_type = "integer" end @@ -49,4 +49,10 @@ Workgroup.find_each do |workgroup| field.name = "Test de Piece Jointe" field.field_type = "attachment" end + + workgroup.custom_fields.seed_by(code: "journey_pattern_test_integer") do |field| + field.resource_type = "JourneyPattern" + field.name = "Test de Nombre" + field.field_type = "integer" + end end diff --git a/lib/tasks/referential.rake b/lib/tasks/referential.rake index d53157312..b3202035b 100644 --- a/lib/tasks/referential.rake +++ b/lib/tasks/referential.rake @@ -70,7 +70,7 @@ namespace :referential do def update_checksums_for_referential referential thing = %w(\\ | / —) - Referential.force_register_models_with_checksum if Rails.env.development? && Referential.models_with_checksum.empty? + Referential.force_register_models_with_checksum puts "\n \e[33m***\e[0m Referential #{referential.name}" referential.switch do Referential.models_with_checksum.each do |klass| diff --git a/spec/controllers/autocomplete_time_tables_controller_spec.rb b/spec/controllers/autocomplete_time_tables_controller_spec.rb index 85a8eb714..02bf83b6e 100644 --- a/spec/controllers/autocomplete_time_tables_controller_spec.rb +++ b/spec/controllers/autocomplete_time_tables_controller_spec.rb @@ -8,6 +8,11 @@ RSpec.describe AutocompleteTimeTablesController, type: :controller do let!(:time_table) { create :time_table, comment: 'écolà militaire' } let!(:blargh) { create :time_table, comment: 'écolàë militaire' } let!(:other_time_table) { create :time_table, comment: 'foo bar baz' } + let(:route){ create :route } + + before do + create :vehicle_journey, time_tables: [time_table, blargh, other_time_table], journey_pattern: route.full_journey_pattern + end describe 'GET #index' do it 'should be successful' do @@ -17,7 +22,7 @@ RSpec.describe AutocompleteTimeTablesController, type: :controller do context 'search by name' do it 'should be successful' do - get :index, referential_id: referential.id, q: {unaccented_comment_or_objectid_cont_any: 'écolà'}, :format => :json + get :index, referential_id: referential.id, q: {unaccented_comment_or_objectid_cont_any: 'écolà'}, format: :json expect(response).to be_success expect(assigns(:time_tables)).to include(time_table) expect(assigns(:time_tables)).to include(blargh) @@ -25,13 +30,33 @@ RSpec.describe AutocompleteTimeTablesController, type: :controller do end it 'should be accent insensitive' do - get :index, referential_id: referential.id, q: {unaccented_comment_or_objectid_cont_any: 'ecola'}, :format => :json + get :index, referential_id: referential.id, q: {unaccented_comment_or_objectid_cont_any: 'ecola'}, format: :json expect(response).to be_success expect(assigns(:time_tables)).to include(time_table) expect(assigns(:time_tables)).to include(blargh) expect(assigns(:time_tables)).to_not include(other_time_table) end end + + context "within a route" do + context 'search by name' do + it 'should be successful' do + get :index, referential_id: referential.id, q: {unaccented_comment_or_objectid_cont_any: 'écolà'}, route_id: route.id, format: :json + expect(response).to be_success + expect(assigns(:time_tables)).to include(time_table) + expect(assigns(:time_tables)).to include(blargh) + expect(assigns(:time_tables)).to_not include(other_time_table) + end + + it 'should be accent insensitive' do + get :index, referential_id: referential.id, q: {unaccented_comment_or_objectid_cont_any: 'ecola'}, route_id: route.id, format: :json + expect(response).to be_success + expect(assigns(:time_tables)).to include(time_table) + expect(assigns(:time_tables)).to include(blargh) + expect(assigns(:time_tables)).to_not include(other_time_table) + end + end + end end end diff --git a/spec/features/merges_permissions_spec.rb b/spec/features/merges_permissions_spec.rb new file mode 100644 index 000000000..e8af3b5e8 --- /dev/null +++ b/spec/features/merges_permissions_spec.rb @@ -0,0 +1,31 @@ +describe "Merges", :type => :feature do + login_user + + describe 'permissions' do + before do + allow_any_instance_of(MergePolicy).to receive(:create?).and_return permission + visit path + end + + describe 'on show view' do + let( :path ){ workbench_output_path(referential.workbench) } + let(:button_text) { I18n.t('merges.actions.create') } + + context 'if present → ' do + let( :permission ){ true } + it 'view shows the corresponding buttons' do + expected_new_url = new_workbench_merge_path(referential.workbench) + expect( page ).to have_link(button_text, href: expected_new_url) + end + end + + context 'if absent → ' do + let( :permission ){ false } + it 'view does not show the corresponding buttons' do + expect( page ).not_to have_link(button_text) + end + end + end + + end +end diff --git a/spec/models/chouette/route/route_base_spec.rb b/spec/models/chouette/route/route_base_spec.rb index 43ff28c40..e76f10a13 100644 --- a/spec/models/chouette/route/route_base_spec.rb +++ b/spec/models/chouette/route/route_base_spec.rb @@ -77,5 +77,24 @@ RSpec.describe Chouette::Route, :type => :model do expect(route).not_to receive(:calculate_costs!) route.save end + + it "doesn't call #calculate_costs! after_commit if in a ReferentialSuite", + truncation: true do + begin + allow(TomTom).to receive(:enabled?).and_return(true) + + referential_suite = create(:referential_suite) + referential = create(:referential, referential_suite: referential_suite) + + referential.switch do + route = build(:route) + + expect(route).not_to receive(:calculate_costs!) + route.save + end + ensure + referential.destroy + end + end end end diff --git a/spec/models/import/gtfs_spec.rb b/spec/models/import/gtfs_spec.rb index b4b23be00..96b93dc62 100644 --- a/spec/models/import/gtfs_spec.rb +++ b/spec/models/import/gtfs_spec.rb @@ -262,10 +262,53 @@ RSpec.describe Import::Gtfs do end end - describe "#download_host" do - it "should return host defined by Rails.application.config.rails_host (without http:// schema)" do - allow(Rails.application.config).to receive(:rails_host).and_return("http://download_host") + describe "#download_uri" do + let(:import) { Import::Gtfs.new } + + before do + allow(import).to receive(:download_path).and_return("/download_path") + end + + context "when download_host is 'front'" do + before { allow(import).to receive(:download_host).and_return("front") } + it "returns http://front/download_path" do + expect(import.download_uri.to_s).to eq('http://front/download_path') + end + end + + context "when download_host is 'front:3000'" do + before { allow(import).to receive(:download_host).and_return("front:3000") } + it "returns http://front:3000/download_path" do + expect(import.download_uri.to_s).to eq('http://front:3000/download_path') + end + end + + context "when download_host is 'http://front:3000'" do + before { allow(import).to receive(:download_host).and_return("http://front:3000") } + it "returns http://front:3000/download_path" do + expect(import.download_uri.to_s).to eq('http://front:3000/download_path') + end + end + + context "when download_host is 'https://front:3000'" do + before { allow(import).to receive(:download_host).and_return("https://front:3000") } + it "returns https://front:3000/download_path" do + expect(import.download_uri.to_s).to eq('https://front:3000/download_path') + end + end + context "when download_host is 'http://front'" do + before { allow(import).to receive(:download_host).and_return("http://front") } + it "returns http://front/download_path" do + expect(import.download_uri.to_s).to eq('http://front/download_path') + end + end + + end + + describe "#download_host" do + it "should return host defined by Rails.application.config.rails_host" do + allow(Rails.application.config).to receive(:rails_host).and_return("download_host") expect(Import::Gtfs.new.download_host).to eq("download_host") end end diff --git a/spec/models/route_spec.rb b/spec/models/route_spec.rb index b407cd866..58524038b 100644 --- a/spec/models/route_spec.rb +++ b/spec/models/route_spec.rb @@ -65,4 +65,39 @@ RSpec.describe Chouette::Route, :type => :model do end end end + + context "when creating stop_points" do + # Here we tests that acts_as_list does not mess with the positions + let(:stop_areas){ + 4.times.map{create :stop_area} + } + + it "should set a correct order to the stop_points" do + + order = [0, 3, 2, 1] + new = Referential.new + new.name = "mkmkm" + new.organisation = create(:organisation) + new.line_referential = create(:line_referential) + create(:line, line_referential: new.line_referential) + new.stop_area_referential = create(:stop_area_referential) + new.objectid_format = :netex + new.save! + new.switch + route = new.routes.new + + route.published_name = route.name = "Route" + route.line = new.line_referential.lines.last + order.each_with_index do |position, i| + _attributes = { + stop_area: stop_areas[i], + position: position + } + route.stop_points.build _attributes + end + route.save + expect(route).to be_valid + expect{route.run_callbacks(:commit)}.to_not raise_error + end + end end diff --git a/spec/policies/merge_policy_spec.rb b/spec/policies/merge_policy_spec.rb new file mode 100644 index 000000000..55d723080 --- /dev/null +++ b/spec/policies/merge_policy_spec.rb @@ -0,0 +1,9 @@ +RSpec.describe MergePolicy, type: :policy do + + let( :record ){ build_stubbed :route } + + permissions :create? do + it_behaves_like 'permitted policy outside referential', 'merges.create' + end + +end diff --git a/spec/views/line_referentials/show.html.slim_spec.rb b/spec/views/line_referentials/show.html.slim_spec.rb index 0516677cb..6734957c8 100644 --- a/spec/views/line_referentials/show.html.slim_spec.rb +++ b/spec/views/line_referentials/show.html.slim_spec.rb @@ -10,13 +10,11 @@ describe "/line_referentials/show", :type => :view do it "should not present syncing infos and button" do expect(view.content_for(:page_header_actions)).to_not have_selector("a[href=\"#{view.sync_line_referential_path(line_referential)}\"]") - expect(view.content_for(:page_header_meta)).to_not have_selector(".last-update") end with_permission "line_referentials.synchronize" do it "should present syncing infos and button" do expect(view.content_for(:page_header_actions)).to have_selector("a[href=\"#{view.sync_line_referential_path(line_referential)}\"]", count: 1) - expect(view.content_for(:page_header_meta)).to have_selector(".last-update", count: 1) end end end diff --git a/spec/views/line_referentials/stop_area_referentials/show.html.slim_spec.rb b/spec/views/stop_area_referentials/show.html.slim_spec.rb index 71a8d16f5..a7567a969 100644 --- a/spec/views/line_referentials/stop_area_referentials/show.html.slim_spec.rb +++ b/spec/views/stop_area_referentials/show.html.slim_spec.rb @@ -10,13 +10,11 @@ describe "/stop_area_referentials/show", :type => :view do it "should not present syncing infos and button" do expect(view.content_for(:page_header_actions)).to_not have_selector("a[href=\"#{view.sync_stop_area_referential_path(stop_area_referential)}\"]") - expect(view.content_for(:page_header_meta)).to_not have_selector(".last-update") end with_permission "stop_area_referentials.synchronize" do it "should present syncing infos and button" do expect(view.content_for(:page_header_actions)).to have_selector("a[href=\"#{view.sync_stop_area_referential_path(stop_area_referential)}\"]", count: 1) - expect(view.content_for(:page_header_meta)).to have_selector(".last-update", count: 1) end end end |
