diff options
| author | Robert | 2017-06-27 14:25:35 +0200 |
|---|---|---|
| committer | Robert | 2017-06-27 14:25:35 +0200 |
| commit | f20df3c08dfec0e3dda68401204f7d49470119a7 (patch) | |
| tree | 4f27a34130d4ff044d48729f16d2dff154047ce5 /app | |
| parent | 970954938043d8d73c4457ee2d91e22c0e422e65 (diff) | |
| parent | eabd56ff9f2c7979192e54b4ae11673f1cc778c1 (diff) | |
| download | chouette-core-f20df3c08dfec0e3dda68401204f7d49470119a7.tar.bz2 | |
conflicts resolved
Diffstat (limited to 'app')
43 files changed, 977 insertions, 248 deletions
diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js index 0af1bb53d..e90d2d307 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js @@ -134,9 +134,10 @@ const actions = { type: 'SHIFT_VEHICLEJOURNEY', data }), - duplicateVehicleJourney : (data) => ({ + duplicateVehicleJourney : (data, departureDelta) => ({ type: 'DUPLICATE_VEHICLEJOURNEY', - data + data, + departureDelta }), deleteVehicleJourneys : () => ({ type: 'DELETE_VEHICLEJOURNEYS' @@ -458,20 +459,20 @@ const actions = { schedule.arrival_time.hour = parseInt(schedule.arrival_time.hour) + hours } - if(schedule.departure_time.hour > 23){ + if(parseInt(schedule.departure_time.hour) > 23){ schedule.departure_time.hour = '23' schedule.departure_time.minute = '59' } - if(schedule.arrival_time.hour > 23){ + if(parseInt(schedule.arrival_time.hour) > 23){ schedule.arrival_time.hour = '23' schedule.arrival_time.minute = '59' } - if(schedule.departure_time.hour < 0){ + if(parseInt(schedule.departure_time.hour) < 0){ schedule.departure_time.hour = '00' schedule.departure_time.minute = '00' } - if(schedule.arrival_time.hour > 23){ + if(parseInt(schedule.arrival_time.hour) < 0){ schedule.arrival_time.hour = '00' schedule.arrival_time.minute = '00' } diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js index 0cf102693..aa1a13b11 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/DuplicateVehicleJourney.js @@ -18,8 +18,8 @@ class DuplicateVehicleJourney extends Component { } } let val = actions.getDuplicateDelta(_.find(actions.getSelected(this.props.vehicleJourneys)[0].vehicle_journey_at_stops, {'dummy': false}), newDeparture) - this.refs.additional_time.value = parseInt(this.refs.additional_time.value) + val - this.props.onDuplicateVehicleJourney(this.refs) + this.refs.additional_time.value = parseInt(this.refs.additional_time.value) + this.props.onDuplicateVehicleJourney(this.refs, val) this.props.onModalClose() $('#DuplicateVehicleJourneyModal').modal('hide') } @@ -51,10 +51,9 @@ class DuplicateVehicleJourney extends Component { <div className='modal-dialog'> <div className='modal-content'> <div className='modal-header'> - <h4 className='modal-title'>Dupliquer une course</h4> - {(this.props.modal.type == 'duplicate') && ( - <em>Dupliquer les horaires de la course {actions.humanOID(actions.getSelected(this.props.vehicleJourneys)[0].objectid)}</em> - )} + <h4 className='modal-title'> + Dupliquer { actions.getSelected(this.props.vehicleJourneys).length > 1 ? 'plusieurs courses' : 'une course' } + </h4> </div> {(this.props.modal.type == 'duplicate') && ( diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js index 932c56532..9919ee9dd 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/components/tools/EditVehicleJourney.js @@ -70,7 +70,7 @@ class EditVehicleJourney extends Component { <input type='text' className='form-control' - value={(this.props.modal.modalProps.vehicleJourney.journey_pattern.objectid) + ' - ' + (this.props.modal.modalProps.vehicleJourney.journey_pattern.name)} + value={actions.humanOID(this.props.modal.modalProps.vehicleJourney.journey_pattern.objectid) + ' - ' + (this.props.modal.modalProps.vehicleJourney.journey_pattern.name)} disabled={true} /> </div> diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js index 6cf6f4039..224b52a19 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/containers/tools/DuplicateVehicleJourney.js @@ -19,8 +19,8 @@ const mapDispatchToProps = (dispatch) => { onOpenDuplicateModal: () =>{ dispatch(actions.openDuplicateModal()) }, - onDuplicateVehicleJourney: (data) =>{ - dispatch(actions.duplicateVehicleJourney(data)) + onDuplicateVehicleJourney: (data, departureDelta) =>{ + dispatch(actions.duplicateVehicleJourney(data, departureDelta)) } } } diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js index c7e8d58e7..d463d4b8f 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/reducers/vehicleJourneys.js @@ -182,11 +182,12 @@ const vehicleJourneys = (state = [], action) => { let dupes = [] let selectedIndex let val = action.data.additional_time.value + let departureDelta = action.departureDelta state.map((vj, i) => { if(vj.selected){ selectedIndex = i for (i = 0; i< action.data.duplicate_number.value; i++){ - action.data.additional_time.value = val * (i + 1) + action.data.additional_time.value = (parseInt(val) * (i + 1)) + departureDelta dupeVj = vehicleJourney(vj, action, false) dupeVj.published_journey_name = dupeVj.published_journey_name + '-' + i dupeVj.selected = false diff --git a/app/assets/stylesheets/components/_dropdown.sass b/app/assets/stylesheets/components/_dropdown.sass index 99dc6292e..8a8d69063 100644 --- a/app/assets/stylesheets/components/_dropdown.sass +++ b/app/assets/stylesheets/components/_dropdown.sass @@ -3,6 +3,8 @@ //-------------// .dropdown-menu + z-index: 2001 + > li > button display: block width: 100% diff --git a/app/controllers/calendars_controller.rb b/app/controllers/calendars_controller.rb index 415ebcaeb..23af4129b 100644 --- a/app/controllers/calendars_controller.rb +++ b/app/controllers/calendars_controller.rb @@ -5,6 +5,11 @@ class CalendarsController < BreadcrumbController respond_to :html respond_to :js, only: :index + def show + show! do + @calendar = @calendar.decorate + end + end private def calendar_params diff --git a/app/controllers/lines_controller.rb b/app/controllers/lines_controller.rb index 7eedaeb05..1e2056aad 100644 --- a/app/controllers/lines_controller.rb +++ b/app/controllers/lines_controller.rb @@ -25,6 +25,11 @@ class LinesController < BreadcrumbController def show @group_of_lines = resource.group_of_lines show! do + @line = @line.decorate(context: { + line_referential: @line_referential, + current_organisation: current_organisation + }) + build_breadcrumb :show end end diff --git a/app/controllers/referentials_controller.rb b/app/controllers/referentials_controller.rb index aa5b359da..1239d512f 100644 --- a/app/controllers/referentials_controller.rb +++ b/app/controllers/referentials_controller.rb @@ -24,19 +24,21 @@ class ReferentialsController < BreadcrumbController end def show - resource.switch - show! do |format| - format.json { - render :json => { :lines_count => resource.lines.count, - :networks_count => resource.networks.count, - :vehicle_journeys_count => resource.vehicle_journeys.count + resource.vehicle_journey_frequencies.count, - :time_tables_count => resource.time_tables.count, - :referential_id => resource.id} - } - format.html { build_breadcrumb :show} - end - - @reflines = lines_collection.paginate(page: params[:page], per_page: 10) + resource.switch + show! do |format| + @referential = @referential.decorate + + format.json { + render :json => { :lines_count => resource.lines.count, + :networks_count => resource.networks.count, + :vehicle_journeys_count => resource.vehicle_journeys.count + resource.vehicle_journey_frequencies.count, + :time_tables_count => resource.time_tables.count, + :referential_id => resource.id} + } + format.html { build_breadcrumb :show} + end + + @reflines = lines_collection.paginate(page: params[:page], per_page: 10) end def edit diff --git a/app/controllers/routes_controller.rb b/app/controllers/routes_controller.rb index 73febc4b9..786bd57cc 100644 --- a/app/controllers/routes_controller.rb +++ b/app/controllers/routes_controller.rb @@ -42,6 +42,12 @@ class RoutesController < ChouetteController end show! do + @route = @route.decorate(context: { + referential: @referential, + line: @line, + route_sp: @route_sp + }) + build_breadcrumb :show end end diff --git a/app/controllers/routing_constraint_zones_controller.rb b/app/controllers/routing_constraint_zones_controller.rb index 7707427b0..9d2fd712c 100644 --- a/app/controllers/routing_constraint_zones_controller.rb +++ b/app/controllers/routing_constraint_zones_controller.rb @@ -16,6 +16,10 @@ class RoutingConstraintZonesController < ChouetteController def show @routing_constraint_zone = collection.find(params[:id]) + @routing_constraint_zone = @routing_constraint_zone.decorate(context: { + referential: @referential, + line: @line + }) end protected diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb index 5c4552afb..3704f2885 100644 --- a/app/controllers/time_tables_controller.rb +++ b/app/controllers/time_tables_controller.rb @@ -14,6 +14,10 @@ class TimeTablesController < ChouetteController @year = params[:year] ? params[:year].to_i : Date.today.cwyear @time_table_combination = TimeTableCombination.new show! do + @time_table = @time_table.decorate(context: { + referential: @referential + }) + build_breadcrumb :show end end diff --git a/app/controllers/workbenches_controller.rb b/app/controllers/workbenches_controller.rb index ccd55965b..83762d83f 100644 --- a/app/controllers/workbenches_controller.rb +++ b/app/controllers/workbenches_controller.rb @@ -11,11 +11,18 @@ class WorkbenchesController < BreadcrumbController scope = ransack_status(scope) # Ignore archived_at_not_null/archived_at_null managed by ransack_status scope - q_for_result = - scope.ransack(params[:q].merge(archived_at_not_null: nil, archived_at_null: nil)) - @wbench_refs = sort_result(q_for_result.result).paginate(page: params[:page], per_page: 30) + # We clone params[:q] so we can delete fake ransack filter arguments before calling search method, + # which will allow us to preserve params[:q] for sorting + ransack_params = params[:q].merge(archived_at_not_null: nil, archived_at_null: nil).clone + ransack_params.delete('associated_lines_id_eq') + + @q = scope.ransack(ransack_params) + @wbench_refs = sort_result(@q.result).paginate(page: params[:page], per_page: 30) + @wbench_refs = ModelDecorator.decorate( + @wbench_refs, + with: ReferentialDecorator + ) - @q = scope.ransack(params[:q]) show! do build_breadcrumb :show end @@ -59,7 +66,6 @@ class WorkbenchesController < BreadcrumbController def ransack_associated_lines scope if params[:q] && params[:q]['associated_lines_id_eq'] scope = scope.include_metadatas_lines([params[:q]['associated_lines_id_eq']]) - params[:q].delete('associated_lines_id_eq') end scope end diff --git a/app/decorators/calendar_decorator.rb b/app/decorators/calendar_decorator.rb new file mode 100644 index 000000000..37e2cfe80 --- /dev/null +++ b/app/decorators/calendar_decorator.rb @@ -0,0 +1,18 @@ +class CalendarDecorator < Draper::Decorator + delegate_all + + def action_links + links = [] + + if h.policy(object).destroy? + links << Link.new( + content: h.destroy_link_content, + href: h.calendar_path(object), + method: :delete, + data: { confirm: h.t('calendars.actions.destroy_confirm') } + ) + end + + links + end +end diff --git a/app/decorators/company_decorator.rb b/app/decorators/company_decorator.rb index 3a0cc16ce..51c1f3c61 100644 --- a/app/decorators/company_decorator.rb +++ b/app/decorators/company_decorator.rb @@ -1,4 +1,6 @@ class CompanyDecorator < Draper::Decorator + decorates Chouette::Company + delegate_all def self.collection_decorator_class @@ -9,4 +11,43 @@ class CompanyDecorator < Draper::Decorator object.lines.count end + # Requires: + # context: { + # line_referential: + # } + def action_links + links = [] + + if h.policy(Chouette::Company).create? + links << Link.new( + content: h.t('companies.actions.new'), + href: h.new_line_referential_company_path(context[:line_referential]) + ) + end + + if h.policy(object).update? + links << Link.new( + content: h.t('companies.actions.edit'), + href: h.edit_line_referential_company_path( + context[:line_referential], + object + ) + ) + end + + if h.policy(object).destroy? + links << Link.new( + content: t('companies.actions.destroy'), + href: h.line_referential_company_path( + context[:line_referential], + object + ), + method: :delete, + data: { confirm: h.t('companies.actions.destroy_confirm') } + ) + end + + links + end + end diff --git a/app/decorators/line_decorator.rb b/app/decorators/line_decorator.rb new file mode 100644 index 000000000..f351103b2 --- /dev/null +++ b/app/decorators/line_decorator.rb @@ -0,0 +1,45 @@ +class LineDecorator < Draper::Decorator + decorates Chouette::Line + + delegate_all + + # Requires: + # context: { + # line_referential: , + # current_organisation: + # } + def action_links + links = [] + + links << Link.new( + content: h.t('lines.actions.show_network'), + href: [context[:line_referential], object.network] + ) + + links << Link.new( + content: h.t('lines.actions.show_company'), + href: [context[:line_referential], object.company] + ) + + if h.policy(Chouette::Line).create? && + context[:line_referential].organisations.include?( + context[:current_organisation] + ) + links << Link.new( + content: h.t('lines.actions.new'), + href: h.new_line_referential_line_path(context[:line_referential]) + ) + end + + if h.policy(object).destroy? + links << Link.new( + content: h.destroy_link_content('lines.actions.destroy_confirm'), + href: h.line_referential_line_path(context[:line_referential], object), + method: :delete, + data: { confirm: h.t('lines.actions.destroy_confirm') } + ) + end + + links + end +end diff --git a/app/decorators/model_decorator.rb b/app/decorators/model_decorator.rb new file mode 100644 index 000000000..dee014cc3 --- /dev/null +++ b/app/decorators/model_decorator.rb @@ -0,0 +1,3 @@ +class ModelDecorator < PaginatingDecorator + delegate :model +end diff --git a/app/decorators/referential_decorator.rb b/app/decorators/referential_decorator.rb new file mode 100644 index 000000000..b95b04f9f --- /dev/null +++ b/app/decorators/referential_decorator.rb @@ -0,0 +1,56 @@ +class ReferentialDecorator < Draper::Decorator + delegate_all + + def action_links + links = [ + Link.new( + content: h.t('time_tables.index.title'), + href: h.referential_time_tables_path(object) + ) + ] + + if h.policy(object).clone? + links << Link.new( + content: h.t('actions.clone'), + href: h.new_referential_path(from: object.id) + ) + end + + if h.policy(object).edit? + + if object.archived? + links << Link.new( + content: h.t('actions.unarchive'), + href: h.unarchive_referential_path(object.id), + method: :put + ) + else + links << HTMLElement.new( + :button, + 'Purger', + type: 'button', + data: { + toggle: 'modal', + target: '#purgeModal' + } + ) + links << Link.new( + content: h.t('actions.archive'), + href: h.archive_referential_path(object.id), + method: :put + ) + end + end + + if h.policy(object).destroy? && !object.archived? + links << Link.new( + content: h.destroy_link_content, + href: h.referential_path(object), + method: :delete, + data: { confirm: h.t('referentials.actions.destroy_confirm') } + ) + end + + links + end +end diff --git a/app/decorators/route_decorator.rb b/app/decorators/route_decorator.rb new file mode 100644 index 000000000..99b174dff --- /dev/null +++ b/app/decorators/route_decorator.rb @@ -0,0 +1,64 @@ +class RouteDecorator < Draper::Decorator + decorates Chouette::Route + + delegate_all + + # Requires: + # context: { + # referential: , + # line: , + # route_sp + # } + def action_links + links = [] + + if context[:route_sp].any? + links << Link.new( + content: h.t('journey_patterns.index.title'), + href: [ + context[:referential], + context[:line], + object, + :journey_patterns_collection + ] + ) + end + + if object.journey_patterns.present? + links << Link.new( + content: h.t('vehicle_journeys.actions.index'), + href: [ + context[:referential], + context[:line], + object, + :vehicle_journeys + ] + ) + end + + links << Link.new( + content: h.t('vehicle_journey_exports.new.title'), + href: h.referential_line_route_vehicle_journey_exports_path( + context[:referential], + context[:line], + object, + format: :zip + ) + ) + + if h.policy(object).destroy? + links << Link.new( + content: h.destroy_link_content, + href: h.referential_line_route_path( + context[:referential], + context[:line], + object + ), + method: :delete, + data: { confirm: h.t('routes.actions.destroy_confirm') } + ) + end + + links + end +end diff --git a/app/decorators/routing_constraint_zone_decorator.rb b/app/decorators/routing_constraint_zone_decorator.rb new file mode 100644 index 000000000..0b438a554 --- /dev/null +++ b/app/decorators/routing_constraint_zone_decorator.rb @@ -0,0 +1,42 @@ +class RoutingConstraintZoneDecorator < Draper::Decorator + decorates Chouette::RoutingConstraintZone + + delegate_all + + # Requires: + # context: { + # referential: , + # line: + # } + def action_links + links = [] + + if h.policy(object).update? + links << Link.new( + content: h.t('actions.edit'), + href: h.edit_referential_line_routing_constraint_zone_path( + context[:referential], + context[:line], + object + ) + ) + end + + if h.policy(object).destroy? + links << Link.new( + content: h.destroy_link_content, + href: h.referential_line_routing_constraint_zone_path( + context[:referential], + context[:line], + object + ), + method: :delete, + data: { + confirm: h.t('routing_constraint_zones.actions.destroy_confirm') + } + ) + end + + links + end +end diff --git a/app/decorators/time_table_decorator.rb b/app/decorators/time_table_decorator.rb new file mode 100644 index 000000000..526537310 --- /dev/null +++ b/app/decorators/time_table_decorator.rb @@ -0,0 +1,53 @@ +class TimeTableDecorator < Draper::Decorator + decorates Chouette::TimeTable + + delegate_all + + # Requires: + # context: { + # referential: , + # } + def action_links + links = [] + + if object.calendar + links << Link.new( + content: h.t('actions.actualize'), + href: h.actualize_referential_time_table_path( + context[:referential], + object + ), + method: :post + ) + end + + links << Link.new( + content: h.t('actions.combine'), + href: h.new_referential_time_table_time_table_combination_path( + context[:referential], + object + ) + ) + + if h.policy(object).duplicate? + links << Link.new( + content: h.t('actions.duplicate'), + href: h.duplicate_referential_time_table_path( + context[:referential], + object + ) + ) + end + + if h.policy(object).destroy? + links << Link.new( + content: h.destroy_link_content, + href: h.referential_time_table_path(context[:referential], object), + method: :delete, + data: { confirm: h.t('time_tables.actions.destroy_confirm') } + ) + end + + links + end +end diff --git a/app/helpers/lines_helper.rb b/app/helpers/lines_helper.rb index 45e6cd939..ccf3a12a2 100644 --- a/app/helpers/lines_helper.rb +++ b/app/helpers/lines_helper.rb @@ -6,11 +6,11 @@ module LinesHelper end def sorted_transport_submode - Chouette::Line.transport_submode.values.sort_by{|m| t("enumerize.line.transport_submode.#{m}") } + Chouette::Line.transport_submode.values.sort_by{|m| t("enumerize.line.transport_submode.#{m}").parameterize } end def sorted_transport_mode - Chouette::Line.transport_mode.values.sort_by{|m| t("enumerize.line.transport_mode.#{m}") } + Chouette::Line.transport_mode.values.sort_by{|m| t("enumerize.line.transport_mode.#{m}").parameterize } end def colors?(line) diff --git a/app/helpers/links_helper.rb b/app/helpers/links_helper.rb new file mode 100644 index 000000000..683b66a52 --- /dev/null +++ b/app/helpers/links_helper.rb @@ -0,0 +1,5 @@ +module LinksHelper + def destroy_link_content(translation_key = 'actions.destroy') + content_tag(:span, nil, class: 'fa fa-trash') + t(translation_key) + end +end diff --git a/app/helpers/multiple_selection_toolbox_helper.rb b/app/helpers/multiple_selection_toolbox_helper.rb new file mode 100644 index 000000000..85294af6d --- /dev/null +++ b/app/helpers/multiple_selection_toolbox_helper.rb @@ -0,0 +1,40 @@ +module MultipleSelectionToolboxHelper + # Box of links that floats at the bottom right of the page + def multiple_selection_toolbox(actions) + links = content_tag :ul do + delete_path = nil + + if params[:controller] = 'workbenches' + delete_path = referentials_workbench_path + end + + actions.map do |action| + if action == :delete + action_link = link_to( + '#', + method: :delete, + data: { + path: delete_path, + confirm: 'Etes-vous sûr(e) de vouloir effectuer cette action ?' + }, + title: t("actions.#{action}") + ) do + content_tag :span, '', class: 'fa fa-trash' + end + end + + content_tag :li, action_link, class: 'st_action' + end.join.html_safe + end + + label = content_tag( + :span, + ("<span>0</span> élément(s) sélectionné(s)").html_safe, + class: 'info-msg' + ) + + content_tag :div, '', class: 'select_toolbox noselect' do + links + label + end + end +end diff --git a/app/helpers/table_builder_helper.rb b/app/helpers/table_builder_helper.rb new file mode 100644 index 000000000..b93e9b22b --- /dev/null +++ b/app/helpers/table_builder_helper.rb @@ -0,0 +1,234 @@ +require 'table_builder_helper/column' +require 'table_builder_helper/custom_links' +require 'table_builder_helper/url' + +# table_builder_2 +# A Rails helper that constructs an HTML table from a collection of objects. It +# receives the collection and an array of columns that get transformed into +# `<td>`s. A column of checkboxes can be added to the left side of the table +# for multiple selection. Columns are sortable by default, but sorting can be +# disabled either at the table level or at the column level. An optional +# `links` argument takes a set of symbols corresponding to controller actions +# that should be inserted in a gear menu next to each row in the table. That +# menu will also be populated with links defined in `collection#action_links`, +# a list of `Link` objects defined in a decorator for the given object. +# +# Depends on `params` and `current_referential`. +# +# Example: +# table_builder_2( +# @companies, +# [ +# TableBuilderHelper::Column.new( +# name: 'ID Codif', +# attribute: Proc.new { |n| n.try(:objectid).try(:local_id) }, +# sortable: false +# ), +# TableBuilderHelper::Column.new( +# key: :name, +# attribute: 'name' +# ), +# TableBuilderHelper::Column.new( +# key: :phone, +# attribute: 'phone' +# ), +# TableBuilderHelper::Column.new( +# key: :email, +# attribute: 'email' +# ), +# TableBuilderHelper::Column.new( +# key: :url, +# attribute: 'url' +# ), +# ], +# links: [:show, :edit], +# cls: 'table has-search' +# ) +module TableBuilderHelper + # TODO: rename this after migration from `table_builder` + def table_builder_2( + # An `ActiveRecord::Relation`, wrapped in a decorator to provide a list of + # `Link` objects via an `#action_links` method + collection, + + # An array of `TableBuilderHelper::Column`s + columns, + + # When false, no columns will be sortable + sortable: true, + + # When true, adds a column of checkboxes to the left side of the table + selectable: false, + + # A set of controller actions that will be added as links to the top of the + # gear menu + links: [], + + # A CSS class to apply to the <table> + cls: '' + ) + content_tag :table, + thead(collection, columns, sortable, selectable, links.any?) + + tbody(collection, columns, selectable, links), + class: cls + end + + private + + def thead(collection, columns, sortable, selectable, has_links) + content_tag :thead do + content_tag :tr do + hcont = [] + + if selectable + hcont << content_tag(:th, checkbox(id_name: '0', value: 'all')) + end + + columns.each do |column| + hcont << content_tag(:th, build_column_header( + column, + sortable, + collection.model, + params, + params[:sort], + params[:direction] + )) + end + + # Inserts a blank column for the gear menu + hcont << content_tag(:th, '') if has_links + + hcont.join.html_safe + end + end + end + + def tbody(collection, columns, selectable, links) + content_tag :tbody do + collection.map do |item| + + content_tag :tr do + bcont = [] + + if selectable + bcont << content_tag( + :td, + checkbox(id_name: item.try(:id), value: item.try(:id)) + ) + end + + columns.each do |column| + value = column.value(item) + + if column_is_linkable?(column) + # Build a link to the `item` + polymorph_url = URL.polymorphic_url_parts(item) + bcont << content_tag(:td, link_to(value, polymorph_url), title: 'Voir') + else + bcont << content_tag(:td, value) + end + end + + if links.any? + bcont << content_tag( + :td, + build_links(item, links), + class: 'actions' + ) + end + + bcont.join.html_safe + end + end.join.html_safe + end + end + + def build_links(item, links) + trigger = content_tag( + :div, + class: 'btn dropdown-toggle', + data: { toggle: 'dropdown' } + ) do + content_tag :span, '', class: 'fa fa-cog' + end + + menu = content_tag :ul, class: 'dropdown-menu' do + ( + CustomLinks.new(item, pundit_user, links).links + + item.action_links.select { |link| link.is_a?(Link) } + ).map do |link| + gear_menu_link(link) + end.join.html_safe + end + + content_tag :div, trigger + menu, class: 'btn-group' + end + + def build_column_header( + column, + table_is_sortable, + collection_model, + params, + sort_on, + sort_direction + ) + if !table_is_sortable + return column.header_label(collection_model) + end + + return column.name if !column.sortable + + direction = + if column.key.to_s == sort_on && sort_direction == 'desc' + 'asc' + else + 'desc' + end + + link_to(params.merge({direction: direction, sort: column.key})) do + arrow_up = content_tag( + :span, + '', + class: "fa fa-sort-asc #{direction == 'desc' ? 'active' : ''}" + ) + arrow_down = content_tag( + :span, + '', + class: "fa fa-sort-desc #{direction == 'asc' ? 'active' : ''}" + ) + + arrow_icons = content_tag :span, arrow_up + arrow_down, class: 'orderers' + + ( + column.header_label(collection_model) + + arrow_icons + ).html_safe + end + end + + def checkbox(id_name:, value:) + content_tag :div, '', class: 'checkbox' do + check_box_tag(id_name, value).concat( + content_tag(:label, '', for: id_name) + ) + end + end + + def column_is_linkable?(column) + column.attribute == 'name' || column.attribute == 'comment' + end + + def gear_menu_link(link) + content_tag( + :li, + link_to( + link.href, + method: link.method, + data: link.data + ) do + link.content + end, + class: ('delete-action' if link.method == :delete) + ) + end +end diff --git a/app/helpers/table_builder_helper/column.rb b/app/helpers/table_builder_helper/column.rb new file mode 100644 index 000000000..800a8282e --- /dev/null +++ b/app/helpers/table_builder_helper/column.rb @@ -0,0 +1,36 @@ +module TableBuilderHelper + class Column + attr_reader :key, :name, :attribute, :sortable + + def initialize(key: nil, name: '', attribute:, sortable: true) + if key.nil? && name.empty? + raise ColumnMustHaveKeyOrNameError + end + + @key = key + @name = name + @attribute = attribute + @sortable = sortable + end + + def value(obj) + if @attribute.is_a?(Proc) + @attribute.call(obj) + else + obj.try(@attribute) + end + end + + def header_label(model = nil) + return @name unless @name.empty? + + # Transform `Chouette::Line` into "line" + model_key = model.to_s.demodulize.underscore + + I18n.t("activerecord.attributes.#{model_key}.#{@key}") + end + end + + + class ColumnMustHaveKeyOrNameError < StandardError; end +end diff --git a/app/helpers/table_builder_helper/custom_links.rb b/app/helpers/table_builder_helper/custom_links.rb new file mode 100644 index 000000000..abb907678 --- /dev/null +++ b/app/helpers/table_builder_helper/custom_links.rb @@ -0,0 +1,77 @@ +require 'table_builder_helper/url' + +module TableBuilderHelper + class CustomLinks + ACTIONS_TO_HTTP_METHODS = { + delete: :delete, + archive: :put, + unarchive: :put + } + + def initialize(obj, user_context, actions) + @obj = obj + @user_context = user_context + @actions = actions + end + + def links + actions_after_policy_check.map do |action| + Link.new( + content: I18n.t("actions.#{action}"), + href: polymorphic_url(action), + method: method_for_action(action) + ) + end + end + + def polymorphic_url(action) + polymorph_url = [] + + unless [:show, :delete].include?(action) + polymorph_url << action + end + + polymorph_url += URL.polymorphic_url_parts(@obj) + end + + def method_for_action(action) + ACTIONS_TO_HTTP_METHODS[action] + end + + def actions_after_policy_check + @actions.select do |action| + # Has policy and can destroy + (action == :delete && + Pundit.policy(@user_context, @obj).present? && + Pundit.policy(@user_context, @obj).destroy?) || + + # Doesn't have policy + (action == :delete && + !Pundit.policy(@user_context, @obj).present?) || + + # Has policy and can update + (action == :edit && + Pundit.policy(@user_context, @obj).present? && + Pundit.policy(@user_context, @obj).update?) || + + # Doesn't have policy + (action == :edit && + !Pundit.policy(@user_context, @obj).present?) || + + # Object isn't archived + (action == :archive && !@obj.archived?) || + + # Object is archived + (action == :unarchive && @obj.archived?) || + + action_is_allowed_regardless_of_policy(action) + end + end + + private + + def action_is_allowed_regardless_of_policy(action) + ![:delete, :edit, :archive, :unarchive].include?(action) + end + end +end diff --git a/app/helpers/table_builder_helper/url.rb b/app/helpers/table_builder_helper/url.rb new file mode 100644 index 000000000..f60864ac1 --- /dev/null +++ b/app/helpers/table_builder_helper/url.rb @@ -0,0 +1,25 @@ +module TableBuilderHelper + # Depends on `current_referential`, defined in object controllers + class URL + def self.polymorphic_url_parts(item) + polymorph_url = [] + + unless item.is_a?(Calendar) || item.is_a?(Referential) + if current_referential + polymorph_url << current_referential + polymorph_url << item.line if item.respond_to? :line + polymorph_url << item.route.line if item.is_a?(Chouette::RoutingConstraintZone) + polymorph_url << item if item.respond_to? :line_referential + polymorph_url << item.stop_area if item.respond_to? :stop_area + polymorph_url << item if item.respond_to? :stop_points || item.is_a?(Chouette::TimeTable) + elsif item.respond_to? :referential + polymorph_url << item.referential + end + else + polymorph_url << item + end + + polymorph_url + end + end +end diff --git a/app/models/calendar.rb b/app/models/calendar.rb index 02349b90b..2462501bc 100644 --- a/app/models/calendar.rb +++ b/app/models/calendar.rb @@ -1,4 +1,7 @@ require 'range_ext' +require_relative 'calendar/date_value' +require_relative 'calendar/period' + class Calendar < ActiveRecord::Base belongs_to :organisation @@ -31,9 +34,11 @@ class Calendar < ActiveRecord::Base end end + + ### Calendar::Period # Required by coocon def build_period - Period.new + Calendar::Period.new end def periods @@ -41,11 +46,9 @@ class Calendar < ActiveRecord::Base end def init_periods - if date_ranges - date_ranges.each_with_index.map { |r, index| Period.from_range(index, r) } - else - [] - end + (date_ranges || []) + .each_with_index + .map( &Calendar::Period.method(:from_range) ) end private :init_periods @@ -78,7 +81,7 @@ class Calendar < ActiveRecord::Base ['begin', 'end'].map do |attr| period_attribute[attr] = flatten_date_array(period_attribute, attr) end - period = Period.new(period_attribute.merge(id: index)) + period = Calendar::Period.new(period_attribute.merge(id: index)) @periods << period unless period.marked_for_destruction? end @@ -101,11 +104,11 @@ class Calendar < ActiveRecord::Base private :clear_periods -### dates + ### Calendar::DateValue # Required by coocon def build_date_value - DateValue.new + Calendar::DateValue.new end def date_values @@ -114,7 +117,7 @@ class Calendar < ActiveRecord::Base def init_date_values if dates - dates.each_with_index.map { |d, index| DateValue.from_date(index, d) } + dates.each_with_index.map { |d, index| Calendar::DateValue.from_date(index, d) } else [] end @@ -148,7 +151,7 @@ class Calendar < ActiveRecord::Base @date_values = [] attributes.each do |index, date_value_attribute| date_value_attribute['value'] = flatten_date_array(date_value_attribute, 'value') - date_value = DateValue.new(date_value_attribute.merge(id: index)) + date_value = Calendar::DateValue.new(date_value_attribute.merge(id: index)) @date_values << date_value unless date_value.marked_for_destruction? end diff --git a/app/models/calendar/calendar_date.rb b/app/models/calendar/calendar_date.rb deleted file mode 100644 index cfee95a25..000000000 --- a/app/models/calendar/calendar_date.rb +++ /dev/null @@ -1,29 +0,0 @@ -class Calendar - class CalendarDate < ::Date - - module IllegalDate - attr_reader :year, :month, :day - def to_s(*_args) - "%d-%02d-%02d" % [year, month, day] - end - end - - def self.new(*args) - super(*args) - rescue - o = allocate() - o.instance_exec do - @illegal = true - @year, @month, @day = args - extend IllegalDate - end - o - end - - def self.from_date(date) - new date.year, date.month, date.day - end - - def legal?; !!!@illegal end - end -end diff --git a/app/models/calendar/date_value.rb b/app/models/calendar/date_value.rb index 709dc2c14..a4a405d43 100644 --- a/app/models/calendar/date_value.rb +++ b/app/models/calendar/date_value.rb @@ -1,33 +1,32 @@ -class Calendar::DateValue - include ActiveAttr::Model +class Calendar < ActiveRecord::Base - attribute :id, type: Integer - attribute :value, type: Date + class DateValue + include ActiveAttr::Model - validates_presence_of :value - validate :validate_date - - def self.from_date(index, date) - new id: index, value: Calendar::CalendarDate.from_date(date) - end + attribute :id, type: Integer + attribute :value, type: Date - # Stuff required for coocon - def new_record? - !persisted? - end + validates_presence_of :value - def persisted? - id.present? - end + def self.from_date(index, date) + new id: index, value: date + end - def mark_for_destruction - self._destroy = true - end + # Stuff required for coocon + def new_record? + !persisted? + end + + def persisted? + id.present? + end + + def mark_for_destruction + self._destroy = true + end - def validate_date - errors.add(:value, I18n.t('activerecord.errors.models.calendar.attributes.dates.illegal_date', date: value.to_s)) unless value.try(:legal?) + attribute :_destroy, type: Boolean + alias_method :marked_for_destruction?, :_destroy end - attribute :_destroy, type: Boolean - alias_method :marked_for_destruction?, :_destroy end diff --git a/app/models/calendar/period.rb b/app/models/calendar/period.rb index eb1bb5370..bfde242f3 100644 --- a/app/models/calendar/period.rb +++ b/app/models/calendar/period.rb @@ -1,83 +1,63 @@ -class Calendar::Period - include ActiveAttr::Model +class Calendar < ActiveRecord::Base + + class Period + include ActiveAttr::Model - attribute :id, type: Integer - attribute :begin, type: Date - attribute :end, type: Date + attribute :id, type: Integer + attribute :begin, type: Date + attribute :end, type: Date - validate :check_end_greather_than_begin - validates_presence_of :begin, :end - validate :validate_dates + validates_presence_of :begin, :end + validate :check_end_greather_than_begin - def initialize(args={}) - super - self.begin = Calendar::CalendarDate.from_date(self.begin) if Date === self.begin - self.end = Calendar::CalendarDate.from_date(self.end) if Date === self.end - end - - def check_end_greather_than_begin - if self.begin and self.end and self.begin > self.end - errors.add(:end, :invalid) + def check_end_greather_than_begin + if self.begin and self.end and self.begin > self.end + errors.add(:end, :invalid) + end end - end - def self.from_range(index, range) - new \ - id: index, - begin: Calendar::CalendarDate.from_date(range.begin), - end: Calendar::CalendarDate.from_date(range.end) - end + def self.from_range(range, index) + last = range.exclude_end? ? range.end - 1.day : range.end + Period.new id: index, begin: range.begin, end: last + end - def range - if self.begin and self.end and self.begin <= self.end - Range.new self.begin, self.end + def range + if self.begin and self.end and self.begin <= self.end + Range.new self.begin, self.end + end end - end - def intersect?(*other) - return false if range.nil? + def intersect?(*other) + return false if range.nil? - other = other.flatten - other = other.delete_if { |o| o.id == id } if id + other = other.flatten + other = other.delete_if { |o| o.id == id } if id - other.any? do |period| - if other_range = period.range - (range & other_range).present? + other.any? do |period| + if other_range = period.range + (range & other_range).present? + end end end - end - def validate_dates - validate_begin - validate_end - end - - def validate_begin - errors.add(:begin, I18n.t('activerecord.errors.models.calendar.attributes.dates.illegal_date', date: self.begin.to_s)) unless self.begin.try( :legal? ) - end - - def validate_end - errors.add(:end, I18n.t('activerecord.errors.models.calendar.attributes.dates.illegal_date', date: self.end.to_s)) unless self.end.try( :legal? ) - end + def cover? date + range.cover? date + end - def cover? date - range.cover? date - end + # Stuff required for coocon + def new_record? + !persisted? + end - # Stuff required for coocon - def new_record? - !persisted? - end + def persisted? + id.present? + end - def persisted? - id.present? - end + def mark_for_destruction + self._destroy = true + end - def mark_for_destruction - self._destroy = true + attribute :_destroy, type: Boolean + alias_method :marked_for_destruction?, :_destroy end - - attribute :_destroy, type: Boolean - alias_method :marked_for_destruction?, :_destroy end - diff --git a/app/models/chouette/journey_pattern.rb b/app/models/chouette/journey_pattern.rb index 34b0d9345..a146dcff1 100644 --- a/app/models/chouette/journey_pattern.rb +++ b/app/models/chouette/journey_pattern.rb @@ -14,19 +14,18 @@ class Chouette::JourneyPattern < Chouette::TridentActiveRecord validates_presence_of :route validates_presence_of :name + validates :stop_points, length: { minimum: 2, too_short: :minimum }, on: :update enum section_status: { todo: 0, completed: 1, control: 2 } attr_accessor :control_checked after_update :control_route_sections, :unless => "control_checked" - def self.state_update route, state transaction do state.each do |item| item.delete('errors') jp = find_by(objectid: item['object_id']) || state_create_instance(route, item) next if item['deletable'] && jp.persisted? && jp.destroy - # Update attributes and stop_points associations jp.update_attributes(state_permited_attributes(item)) jp.state_stop_points_update(item) if !jp.errors.any? && jp.persisted? diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb index 44dd85864..3a5851310 100644 --- a/app/models/chouette/vehicle_journey.rb +++ b/app/models/chouette/vehicle_journey.rb @@ -256,7 +256,7 @@ module Chouette .where( %Q( "vehicle_journey_at_stops"."departure_time" >= ? - AND "vehicle_journey_at_stops"."departure_time" < ? + AND "vehicle_journey_at_stops"."departure_time" <= ? #{ if allow_empty 'OR "vehicle_journey_at_stops"."id" IS NULL' diff --git a/app/models/concerns/default_attributes_support.rb b/app/models/concerns/default_attributes_support.rb index ecad26856..7928093e6 100644 --- a/app/models/concerns/default_attributes_support.rb +++ b/app/models/concerns/default_attributes_support.rb @@ -63,10 +63,10 @@ module DefaultAttributesSupport def fix_uniq_objectid base_objectid = objectid.rpartition(":").first self.objectid = "#{base_objectid}:#{id}" - if !valid? + if !valid?(:objectid) base_objectid="#{objectid}_" cnt=1 - while !valid? + while !valid?(:objectid) self.objectid = "#{base_objectid}#{cnt}" cnt += 1 end diff --git a/app/views/calendars/show.html.slim b/app/views/calendars/show.html.slim index 3886cefaa..d7849005b 100644 --- a/app/views/calendars/show.html.slim +++ b/app/views/calendars/show.html.slim @@ -8,10 +8,12 @@ / Below is secondary actions & optional contents (filters, ...) .row.mb-sm .col-lg-12.text-right - - if policy(@calendar).destroy? - = link_to calendar_path(@calendar), method: :delete, data: { confirm: t('calendars.actions.destroy_confirm') }, class: 'btn btn-primary' do - span.fa.fa-trash - span = t('actions.destroy') + - @calendar.action_links.each do |link| + = link_to link.href, + method: link.method, + data: link.data, + class: 'btn btn-primary' do + = link.content / PageContent .page_content @@ -23,4 +25,4 @@ Calendar.human_attribute_name(:shared) => t("#{@calendar.shared}"), 'Organisation' => @calendar.organisation.name, Calendar.human_attribute_name(:dates) => @calendar.dates.collect{|d| l(d, format: :short)}.join(', ').html_safe, - Calendar.human_attribute_name(:date_ranges) => @calendar.date_ranges.collect{|d| t('validity_range', debut: l(d.begin, format: :short), end: l(d.end, format: :short))}.join('<br>').html_safe } + Calendar.human_attribute_name(:date_ranges) => @calendar.date_ranges.collect{|d| t('validity_range', debut: l(d.begin, format: :short), end: l(d.end - (d.exclude_end? ? 1.day : 0), format: :short))}.join('<br>').html_safe } diff --git a/app/views/lines/show.html.slim b/app/views/lines/show.html.slim index dbc019e72..6f75432e1 100644 --- a/app/views/lines/show.html.slim +++ b/app/views/lines/show.html.slim @@ -7,17 +7,12 @@ / Below is secundary actions & optional contents .row .col-lg-12.text-right.mb-sm - = link_to t('lines.actions.show_network'), [@line_referential, @line.network], class: 'btn btn-primary' - = link_to t('lines.actions.show_company'), [@line_referential, @line.company], class: 'btn btn-primary' - - - if policy(Chouette::Line).create? && @line_referential.organisations.include?(current_organisation) - = link_to t('lines.actions.new'), new_line_referential_line_path(@line_referential), class: 'btn btn-primary' - - if false && policy(@line).update? - = link_to t('lines.actions.edit'), edit_line_referential_line_path(@line_referential, @line), class: 'btn btn-primary' - - if policy(@line).destroy? - = link_to line_referential_line_path(@line_referential, @line), method: :delete, data: {confirm: t('lines.actions.destroy_confirm')}, class: 'btn btn-primary' do - span.fa.fa-trash - span = t('lines.actions.destroy') + - @line.action_links.each do |link| + = link_to link.href, + method: link.method, + data: link.data, + class: 'btn btn-primary' do + = link.content / PageContent .page_content diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim index 3c1e36302..dfa264c0b 100644 --- a/app/views/referentials/show.html.slim +++ b/app/views/referentials/show.html.slim @@ -8,23 +8,15 @@ / Below is secondary actions & optional contents (filters, ...) .row.mb-sm .col-lg-12.text-right - = link_to t('time_tables.index.title'), referential_time_tables_path(@referential), class: 'btn btn-primary' - - - if policy(@referential).clone? - = link_to t('actions.clone'), new_referential_path(from: @referential.id), class: 'btn btn-primary' - - - if policy(@referential).edit? - button.btn.btn-primary type='button' data-toggle='modal' data-target='#purgeModal' Purger - - - if @referential.archived? - = link_to t('actions.unarchive'), unarchive_referential_path(@referential.id), method: :put, class: 'btn btn-primary' + - @referential.action_links.each do |link| + - if link.is_a?(HTMLElement) + = link.to_html(class: 'btn btn-primary') - else - = link_to t('actions.archive'), archive_referential_path(@referential.id), method: :put, class: 'btn btn-primary' - - - if policy(@referential).destroy? - = link_to referential_path(@referential), method: :delete, data: {confirm: t('referentials.actions.destroy_confirm')}, class: 'btn btn-primary' do - span.fa.fa-trash - span = t('actions.destroy') + = link_to link.href, + method: link.method, + data: link.data, + class: 'btn btn-primary' do + = link.content / PageContent .page_content diff --git a/app/views/routes/show.html.slim b/app/views/routes/show.html.slim index 6d2d4e90d..92a5080ae 100644 --- a/app/views/routes/show.html.slim +++ b/app/views/routes/show.html.slim @@ -8,17 +8,12 @@ / Below is secundary actions & optional contents (filters, ...) .row.mb-sm .col-lg-12.text-right - - if @route_sp.any? - = link_to t('journey_patterns.index.title'), [@referential, @line, @route, :journey_patterns_collection], class: 'btn btn-primary' - - if @route.journey_patterns.present? - = link_to t('vehicle_journeys.actions.index'), [@referential, @line, @route, :vehicle_journeys], class: 'btn btn-primary' - - = link_to t('vehicle_journey_exports.new.title'), referential_line_route_vehicle_journey_exports_path(@referential, @line, @route, format: :zip), class: 'btn btn-primary' - - - if policy(@route).destroy? - = link_to referential_line_route_path(@referential, @line, @route), method: :delete, data: {confirm: t('routes.actions.destroy_confirm')}, class: 'btn btn-primary' do - span.fa.fa-trash - span = t('actions.destroy') + - @route.action_links.each do |link| + = link_to link.href, + method: link.method, + data: link.data, + class: 'btn btn-primary' do + = link.content / PageContent .page_content diff --git a/app/views/routing_constraint_zones/show.html.slim b/app/views/routing_constraint_zones/show.html.slim index f0c244387..1dad4f561 100644 --- a/app/views/routing_constraint_zones/show.html.slim +++ b/app/views/routing_constraint_zones/show.html.slim @@ -7,13 +7,12 @@ / Below is secundary actions & optional contents .row .col-lg-12.text-right.mb-sm - - if policy(@routing_constraint_zone).update? - = link_to t('actions.edit'), edit_referential_line_routing_constraint_zone_path(@referential, @line, @routing_constraint_zone), class: 'btn btn-primary' - - - if policy(@routing_constraint_zone).destroy? - = link_to referential_line_routing_constraint_zone_path(@referential, @line, @routing_constraint_zone), method: :delete, data: {confirm: t('routing_constraint_zones.actions.destroy_confirm')}, class: 'btn btn-primary' do - span.fa.fa-trash - span = t('actions.destroy') + - @routing_constraint_zone.action_links.each do |link| + = link_to link.href, + method: link.method, + data: link.data, + class: 'btn btn-primary' do + = link.content / PageContent .page_content diff --git a/app/views/time_tables/show.html.slim b/app/views/time_tables/show.html.slim index 2e71ebb9e..f596fd480 100644 --- a/app/views/time_tables/show.html.slim +++ b/app/views/time_tables/show.html.slim @@ -10,21 +10,12 @@ / Below is secundary actions & optional contents (filters, ...) .row.mb-sm .col-lg-12.text-right - / - if policy(@time_table).create? && @referential.organisation == current_organisation - / = link_to t('time_tables.actions.new'), new_referential_time_table_path(@referential), class: 'btn btn-primary' - - if @time_table.calendar - = link_to t('actions.actualize'), actualize_referential_time_table_path(@referential, @time_table), method: :post, class: 'btn btn-primary' - - /- if policy(@time_table).create? && @referential.organisation == current_organisation - = link_to t('actions.combine'), new_referential_time_table_time_table_combination_path(@referential, @time_table), class: 'btn btn-primary' - - - if policy(@time_table).duplicate? - = link_to t('actions.duplicate'), duplicate_referential_time_table_path(@referential, @time_table), class: 'btn btn-primary' - - - if policy(@time_table).destroy? - = link_to referential_time_table_path(@referential, @time_table), method: :delete, data: {confirm: t('time_tables.actions.destroy_confirm')}, class: 'btn btn-primary' do - span.fa.fa-trash - span = t('actions.destroy') + - @time_table.action_links.each do |link| + = link_to link.href, + method: link.method, + data: link.data, + class: 'btn btn-primary' do + = link.content / PageContent .page_content diff --git a/app/views/workbenches/_filters.html.slim b/app/views/workbenches/_filters.html.slim index 7c5055963..0aedbdd62 100644 --- a/app/views/workbenches/_filters.html.slim +++ b/app/views/workbenches/_filters.html.slim @@ -12,7 +12,7 @@ = f.input :associated_lines_id_eq, as: :select, collection: @workbench.lines.includes(:company).order(:name), input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Indiquez une ligne...' }, label: false, label_method: :display_name, wrapper_html: { class: 'select2ed'} .form-group.togglable - = f.label @wbench_refs.human_attribute_name(:status), required: false, class: 'control-label' + = f.label Referential.human_attribute_name(:status), required: false, class: 'control-label' .form-group.checkbox_list = f.input :archived_at_not_null, label: ("<span>Conservé<span class='fa fa-archive'></span></span>").html_safe, as: :boolean, wrapper_html: { class: 'checkbox-wrapper' } = f.input :archived_at_null, label: ("<span>En préparation<span class='sb sb-lg sb-preparing'></span></span>").html_safe, as: :boolean, wrapper_html: { class: 'checkbox-wrapper' } @@ -22,7 +22,7 @@ = f.input :organisation_name_eq_any, collection: Organisation.order('name').pluck(:name), as: :check_boxes, label: false, label_method: lambda{|w| ("<span>#{w}</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' } .form-group.togglable - = f.label @wbench_refs.human_attribute_name(:validity_period), required: false, class: 'control-label' + = f.label Referential.human_attribute_name(:validity_period), required: false, class: 'control-label' .filter_menu = f.simple_fields_for :validity_period do |p| = p.input :begin_gteq, as: :date, label: t('simple_form.from'), wrapper_html: { class: 'date filter_menu-item' }, default: @begin_range, include_blank: @begin_range ? false : true diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim index 77e670923..37c396b46 100644 --- a/app/views/workbenches/show.html.slim +++ b/app/views/workbenches/show.html.slim @@ -22,18 +22,47 @@ - if @wbench_refs.any? .row .col-lg-12 - = table_builder @wbench_refs, - { :name => 'name', - :status => Proc.new {|w| w.archived? ? ("<div class='td-block'><span class='fa fa-archive'></span><span>Conservé</span></div>").html_safe : ("<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>En préparation</span></div>").html_safe}, - :organisation => Proc.new {|w| w.organisation.name}, - :validity_period => Proc.new {|w| w.validity_period.nil? ? '-' : t('validity_range', debut: l(w.try(:validity_period).try(:begin), format: :short), end: l(w.try(:validity_period).try(:end), format: :short))}, - :lines => Proc.new {|w| w.lines.count}, - :created_at => Proc.new {|w| l(w.created_at, format: :short)}, - :updated_at => Proc.new {|w| l(w.updated_at, format: :short)}, - :published_at => ''}, - [:show, :edit, :archive, :unarchive, :delete], - [:delete], - 'table has-filter has-search' + .select_table + = table_builder_2 @wbench_refs, + [ \ + TableBuilderHelper::Column.new( \ + key: :name, \ + attribute: 'name' \ + ), \ + TableBuilderHelper::Column.new( \ + key: :status, \ + attribute: Proc.new {|w| w.archived? ? ("<div class='td-block'><span class='fa fa-archive'></span><span>Conservé</span></div>").html_safe : ("<div class='td-block'><span class='sb sb-lg sb-preparing'></span><span>En préparation</span></div>").html_safe} \ + ), \ + TableBuilderHelper::Column.new( \ + key: :organisation, \ + attribute: Proc.new {|w| w.organisation.name} \ + ), \ + TableBuilderHelper::Column.new( \ + key: :validity_period, \ + attribute: Proc.new {|w| w.validity_period.nil? ? '-' : t('validity_range', debut: l(w.try(:validity_period).try(:begin), format: :short), end: l(w.try(:validity_period).try(:end), format: :short))} \ + ), \ + TableBuilderHelper::Column.new( \ + key: :lines, \ + attribute: Proc.new {|w| w.lines.count} \ + ), \ + TableBuilderHelper::Column.new( \ + key: :created_at, \ + attribute: Proc.new {|w| l(w.created_at, format: :short)} \ + ), \ + TableBuilderHelper::Column.new( \ + key: :updated_at, \ + attribute: Proc.new {|w| l(w.updated_at, format: :short)} \ + ), \ + TableBuilderHelper::Column.new( \ + key: :published_at, \ + attribute: '' \ + ) \ + ], + selectable: true, + links: [:show, :edit], + cls: 'table has-filter has-search' + + = multiple_selection_toolbox([:delete]) = new_pagination @wbench_refs, 'pull-right' |
