Merge pull request #10869 from demarches-simplifiees/add_id_to_column_second_part
Tech: utilise les objets `SortedColumn`
This commit is contained in:
commit
163fa42007
23 changed files with 409 additions and 267 deletions
|
@ -3,37 +3,6 @@
|
||||||
class Dossiers::NotifiedToggleComponent < ApplicationComponent
|
class Dossiers::NotifiedToggleComponent < ApplicationComponent
|
||||||
def initialize(procedure:, procedure_presentation:)
|
def initialize(procedure:, procedure_presentation:)
|
||||||
@procedure = procedure
|
@procedure = procedure
|
||||||
@procedure_presentation = procedure_presentation
|
@sorted_column = procedure_presentation.sorted_column
|
||||||
@current_sort = procedure_presentation.sort
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def opposite_order
|
|
||||||
@procedure_presentation.opposite_order_for(current_table, current_column)
|
|
||||||
end
|
|
||||||
|
|
||||||
def active?
|
|
||||||
sorted_by_notifications? && order_desc?
|
|
||||||
end
|
|
||||||
|
|
||||||
def order_desc?
|
|
||||||
current_order == 'desc'
|
|
||||||
end
|
|
||||||
|
|
||||||
def current_order
|
|
||||||
@current_sort['order']
|
|
||||||
end
|
|
||||||
|
|
||||||
def current_table
|
|
||||||
@current_sort['table']
|
|
||||||
end
|
|
||||||
|
|
||||||
def current_column
|
|
||||||
@current_sort['column']
|
|
||||||
end
|
|
||||||
|
|
||||||
def sorted_by_notifications?
|
|
||||||
current_table == 'notifications' && current_column == 'notifications'
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
= form_tag update_sort_instructeur_procedure_path(procedure_id: @procedure.id, column_id: @procedure.notifications_column.id, order: opposite_order), method: :get, data: { controller: 'autosubmit' } do
|
= form_tag update_sort_instructeur_procedure_path(@procedure),
|
||||||
|
method: :get, data: { controller: 'autosubmit' } do
|
||||||
.fr-fieldset__element.fr-m-0
|
.fr-fieldset__element.fr-m-0
|
||||||
.fr-checkbox-group.fr-checkbox-group--sm
|
.fr-checkbox-group.fr-checkbox-group--sm
|
||||||
= check_box_tag :order, opposite_order, active?
|
= hidden_field_tag 'sorted_column[id]', @procedure.notifications_column.id
|
||||||
= label_tag :order, t('.show_notified_first'), class: 'fr-label'
|
= hidden_field_tag 'sorted_column[order]', 'asc', id: nil
|
||||||
|
= check_box_tag 'sorted_column[order]', 'desc', @sorted_column.sort_by_notifications?
|
||||||
|
= label_tag 'sorted_column[order]', t('.show_notified_first'), class: 'fr-label'
|
||||||
= submit_tag t('.show_notified_first'), data: {"checkbox-target": 'submit' }, class: 'visually-hidden'
|
= submit_tag t('.show_notified_first'), data: {"checkbox-target": 'submit' }, class: 'visually-hidden'
|
||||||
|
|
|
@ -1,47 +1,34 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Instructeurs::ColumnTableHeaderComponent < ApplicationComponent
|
class Instructeurs::ColumnTableHeaderComponent < ApplicationComponent
|
||||||
attr_reader :procedure_presentation, :column
|
def initialize(procedure_presentation:)
|
||||||
# maybe extract a ColumnSorter class?
|
@procedure = procedure_presentation.procedure
|
||||||
#
|
@columns = procedure_presentation.displayed_fields_for_headers
|
||||||
|
@sorted_column = procedure_presentation.sorted_column
|
||||||
def initialize(procedure_presentation:, column:)
|
|
||||||
@procedure_presentation = procedure_presentation
|
|
||||||
@column = column
|
|
||||||
end
|
|
||||||
|
|
||||||
def column_id
|
|
||||||
column.id
|
|
||||||
end
|
|
||||||
|
|
||||||
def sorted_by_current_column?
|
|
||||||
procedure_presentation.sort['table'] == column.table &&
|
|
||||||
procedure_presentation.sort['column'] == column.column
|
|
||||||
end
|
|
||||||
|
|
||||||
def sorted_ascending?
|
|
||||||
current_sort_order == 'asc'
|
|
||||||
end
|
|
||||||
|
|
||||||
def sorted_descending?
|
|
||||||
current_sort_order == 'desc'
|
|
||||||
end
|
|
||||||
|
|
||||||
def aria_sort
|
|
||||||
if sorted_by_current_column?
|
|
||||||
if sorted_ascending?
|
|
||||||
{ "aria-sort": "ascending" }
|
|
||||||
elsif sorted_descending?
|
|
||||||
{ "aria-sort": "descending" }
|
|
||||||
end
|
|
||||||
else
|
|
||||||
{}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def current_sort_order
|
def update_sort_path(column)
|
||||||
procedure_presentation.sort['order']
|
id = column.id
|
||||||
|
order = opposite_order_for(column)
|
||||||
|
|
||||||
|
update_sort_instructeur_procedure_path(@procedure, sorted_column: { id:, order: })
|
||||||
|
end
|
||||||
|
|
||||||
|
def opposite_order_for(column)
|
||||||
|
@sorted_column.column == column ? @sorted_column.opposite_order : 'asc'
|
||||||
|
end
|
||||||
|
|
||||||
|
def label_and_arrow(column)
|
||||||
|
return column.label if @sorted_column.column != column
|
||||||
|
|
||||||
|
@sorted_column.ascending? ? "#{column.label} ↑" : "#{column.label} ↓"
|
||||||
|
end
|
||||||
|
|
||||||
|
def aria_sort(column)
|
||||||
|
return {} if @sorted_column.column != column
|
||||||
|
|
||||||
|
@sorted_column.ascending? ? { "aria-sort": "ascending" } : { "aria-sort": "descending" }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
%th{ aria_sort, scope: "col", class: column.classname }
|
- @columns.each do |column|
|
||||||
= link_to update_sort_instructeur_procedure_path(@procedure_presentation.procedure, column_id:, order: @procedure_presentation.opposite_order_for(column.table, column.column)) do
|
%th{ aria_sort(column), scope: "col", class: column.classname }
|
||||||
- if sorted_by_current_column?
|
= link_to label_and_arrow(column), update_sort_path(column)
|
||||||
- if sorted_ascending?
|
|
||||||
#{column.label} ↑
|
|
||||||
- else
|
|
||||||
#{column.label} ↓
|
|
||||||
- else
|
|
||||||
#{column.label}
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ module Instructeurs
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_sort
|
def update_sort
|
||||||
procedure_presentation.update_sort(params[:column_id], params[:order])
|
procedure_presentation.update!(sorted_column_params)
|
||||||
|
|
||||||
redirect_back(fallback_location: instructeur_procedure_url(procedure))
|
redirect_back(fallback_location: instructeur_procedure_url(procedure))
|
||||||
end
|
end
|
||||||
|
@ -411,5 +411,9 @@ module Instructeurs
|
||||||
def cookies_export_key
|
def cookies_export_key
|
||||||
"exports_#{@procedure.id}_seen_at"
|
"exports_#{@procedure.id}_seen_at"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sorted_column_params
|
||||||
|
params.permit(sorted_column: [:order, :id])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,8 +18,13 @@ class Column
|
||||||
@displayable = displayable
|
@displayable = displayable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# the id is a String to be used in forms
|
||||||
def id = h_id.to_json
|
def id = h_id.to_json
|
||||||
|
|
||||||
|
# the h_id is a Hash and hold enough information to find the column
|
||||||
|
# in the ColumnType class, aka be able to do the h_id -> column conversion
|
||||||
def h_id = { procedure_id: @procedure_id, column_id: "#{table}/#{column}" }
|
def h_id = { procedure_id: @procedure_id, column_id: "#{table}/#{column}" }
|
||||||
|
|
||||||
def ==(other) = h_id == other.h_id # using h_id instead of id to avoid inversion of keys
|
def ==(other) = h_id == other.h_id # using h_id instead of id to avoid inversion of keys
|
||||||
|
|
||||||
def to_json
|
def to_json
|
||||||
|
@ -27,4 +32,12 @@ class Column
|
||||||
table:, column:, label:, classname:, type:, scope:, value_column:, filterable:, displayable:
|
table:, column:, label:, classname:, type:, scope:, value_column:, filterable:, displayable:
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def notifications?
|
||||||
|
table == 'notifications' && column == 'notifications'
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find(h_id)
|
||||||
|
Procedure.with_discarded.find(h_id[:procedure_id]).find_column(h_id:)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,17 +4,29 @@ module ColumnsConcern
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
||||||
|
# we cannot use column.id ( == { procedure_id, column_id }.to_json)
|
||||||
|
# as the order of the keys is not guaranteed
|
||||||
|
# instead, we are using h_id == { procedure_id:, column_id: }
|
||||||
|
# another way to find a column is to look for its label
|
||||||
def find_column(h_id: nil, label: nil)
|
def find_column(h_id: nil, label: nil)
|
||||||
return columns.find { _1.h_id == h_id } if h_id.present?
|
column = columns.find { _1.h_id == h_id } if h_id.present?
|
||||||
return columns.find { _1.label == label } if label.present?
|
column = columns.find { _1.label == label } if label.present?
|
||||||
|
|
||||||
|
raise ActiveRecord::RecordNotFound if column.nil?
|
||||||
|
|
||||||
|
column
|
||||||
end
|
end
|
||||||
|
|
||||||
def columns
|
def columns
|
||||||
columns = dossier_columns
|
Current.procedure_columns ||= {}
|
||||||
columns.concat(standard_columns)
|
|
||||||
columns.concat(individual_columns) if for_individual
|
Current.procedure_columns[id] ||= begin
|
||||||
columns.concat(moral_columns) if !for_individual
|
columns = dossier_columns
|
||||||
columns.concat(types_de_champ_columns)
|
columns.concat(standard_columns)
|
||||||
|
columns.concat(individual_columns) if for_individual
|
||||||
|
columns.concat(moral_columns) if !for_individual
|
||||||
|
columns.concat(types_de_champ_columns)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def dossier_id_column
|
def dossier_id_column
|
||||||
|
@ -57,6 +69,10 @@ module ColumnsConcern
|
||||||
columns
|
columns
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def default_sorted_column
|
||||||
|
SortedColumn.new(column: notifications_column, order: 'desc')
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def standard_columns
|
def standard_columns
|
||||||
|
|
|
@ -9,4 +9,5 @@ class Current < ActiveSupport::CurrentAttributes
|
||||||
attribute :no_reply_email
|
attribute :no_reply_email
|
||||||
attribute :request_id
|
attribute :request_id
|
||||||
attribute :user
|
attribute :user
|
||||||
|
attribute :procedure_columns
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ProcedurePresentation < ApplicationRecord
|
class ProcedurePresentation < ApplicationRecord
|
||||||
EXTRA_SORT_COLUMNS = {
|
|
||||||
'notifications' => ['notifications'],
|
|
||||||
'self' => ['id', 'state']
|
|
||||||
}
|
|
||||||
|
|
||||||
TABLE = 'table'
|
TABLE = 'table'
|
||||||
COLUMN = 'column'
|
COLUMN = 'column'
|
||||||
ORDER = 'order'
|
ORDER = 'order'
|
||||||
|
@ -23,13 +18,12 @@ class ProcedurePresentation < ApplicationRecord
|
||||||
delegate :procedure, :instructeur, to: :assign_to
|
delegate :procedure, :instructeur, to: :assign_to
|
||||||
|
|
||||||
validate :check_allowed_displayed_fields
|
validate :check_allowed_displayed_fields
|
||||||
validate :check_allowed_sort_column
|
|
||||||
validate :check_allowed_sort_order
|
|
||||||
validate :check_allowed_filter_columns
|
validate :check_allowed_filter_columns
|
||||||
validate :check_filters_max_length
|
validate :check_filters_max_length
|
||||||
validate :check_filters_max_integer
|
validate :check_filters_max_integer
|
||||||
|
|
||||||
attribute :sorted_column, :jsonb
|
attribute :sorted_column, :sorted_column
|
||||||
|
def sorted_column = super || procedure.default_sorted_column # Dummy override to set default value
|
||||||
|
|
||||||
attribute :a_suivre_filters, :jsonb, array: true
|
attribute :a_suivre_filters, :jsonb, array: true
|
||||||
attribute :suivis_filters, :jsonb, array: true
|
attribute :suivis_filters, :jsonb, array: true
|
||||||
|
@ -146,37 +140,8 @@ class ProcedurePresentation < ApplicationRecord
|
||||||
displayed_columns: columns.map(&:h_id)
|
displayed_columns: columns.map(&:h_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
if !sort_to_column_id(sort).in?(column_ids)
|
if !sorted_column.column.in?(columns)
|
||||||
default_column_id = procedure.dossier_id_column.id
|
update(sorted_column: nil)
|
||||||
update_sort(default_column_id, "desc")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_sort(column_id, order)
|
|
||||||
h_id = JSON.parse(column_id, symbolize_names: true)
|
|
||||||
column = procedure.find_column(h_id:)
|
|
||||||
order = order.presence || opposite_order_for(column.table, column.column)
|
|
||||||
|
|
||||||
update!(
|
|
||||||
sort: {
|
|
||||||
TABLE => column.table,
|
|
||||||
COLUMN => column.column,
|
|
||||||
ORDER => order
|
|
||||||
},
|
|
||||||
sorted_column: {
|
|
||||||
order:,
|
|
||||||
id: h_id
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def opposite_order_for(table, column)
|
|
||||||
if sort.values_at(TABLE, COLUMN) == [table, column]
|
|
||||||
sort['order'] == 'asc' ? 'desc' : 'asc'
|
|
||||||
elsif [table, column] == ["notifications", "notifications"]
|
|
||||||
'desc' # default order for notifications
|
|
||||||
else
|
|
||||||
'asc'
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -187,7 +152,9 @@ class ProcedurePresentation < ApplicationRecord
|
||||||
private
|
private
|
||||||
|
|
||||||
def sorted_ids(dossiers, count)
|
def sorted_ids(dossiers, count)
|
||||||
table, column, order = sort.values_at(TABLE, COLUMN, 'order')
|
table = sorted_column.column.table
|
||||||
|
column = sorted_column.column.column
|
||||||
|
order = sorted_column.order
|
||||||
|
|
||||||
case table
|
case table
|
||||||
when 'notifications'
|
when 'notifications'
|
||||||
|
@ -297,11 +264,6 @@ class ProcedurePresentation < ApplicationRecord
|
||||||
end.reduce(:&)
|
end.reduce(:&)
|
||||||
end
|
end
|
||||||
|
|
||||||
# type_de_champ/4373429
|
|
||||||
def sort_to_column_id(sort)
|
|
||||||
[sort[TABLE], sort[COLUMN]].join(SLASH)
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_type_de_champ(column)
|
def find_type_de_champ(column)
|
||||||
TypeDeChamp
|
TypeDeChamp
|
||||||
.joins(:revision_types_de_champ)
|
.joins(:revision_types_de_champ)
|
||||||
|
@ -316,17 +278,6 @@ class ProcedurePresentation < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_allowed_sort_column
|
|
||||||
check_allowed_field(:sort, sort, EXTRA_SORT_COLUMNS)
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_allowed_sort_order
|
|
||||||
order = sort['order']
|
|
||||||
if !["asc", "desc"].include?(order)
|
|
||||||
errors.add(:sort, "#{order} n’est pas une ordre permis")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_allowed_filter_columns
|
def check_allowed_filter_columns
|
||||||
filters.each do |key, columns|
|
filters.each do |key, columns|
|
||||||
return true if key == 'migrated'
|
return true if key == 'migrated'
|
||||||
|
|
22
app/models/sorted_column.rb
Normal file
22
app/models/sorted_column.rb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class SortedColumn
|
||||||
|
attr_reader :column, :order
|
||||||
|
|
||||||
|
def initialize(column:, order:)
|
||||||
|
@column = column
|
||||||
|
@order = order
|
||||||
|
end
|
||||||
|
|
||||||
|
def ascending? = @order == 'asc'
|
||||||
|
|
||||||
|
def opposite_order = ascending? ? 'desc' : 'asc'
|
||||||
|
|
||||||
|
def ==(other)
|
||||||
|
other&.column == column && other.order == order
|
||||||
|
end
|
||||||
|
|
||||||
|
def sort_by_notifications?
|
||||||
|
@column.notifications? && @order == 'desc'
|
||||||
|
end
|
||||||
|
end
|
38
app/types/column_type.rb
Normal file
38
app/types/column_type.rb
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ColumnType < ActiveRecord::Type::Value
|
||||||
|
# value can come from:
|
||||||
|
# setter: column (Column),
|
||||||
|
# form_input: column.id == { procedure_id:, column_id: }.to_json (String),
|
||||||
|
# from db: { procedure_id:, column_id: } (Hash)
|
||||||
|
def cast(value)
|
||||||
|
case value
|
||||||
|
in NilClass
|
||||||
|
nil
|
||||||
|
in Column
|
||||||
|
value
|
||||||
|
# from form
|
||||||
|
in String => id
|
||||||
|
h_id = JSON.parse(id, symbolize_names: true)
|
||||||
|
Column.find(h_id)
|
||||||
|
# from db
|
||||||
|
in Hash => h_id
|
||||||
|
Column.find(h_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# db -> ruby
|
||||||
|
def deserialize(value) = cast(value)
|
||||||
|
|
||||||
|
# ruby -> db
|
||||||
|
def serialize(value)
|
||||||
|
case value
|
||||||
|
in NilClass
|
||||||
|
nil
|
||||||
|
in Column
|
||||||
|
JSON.generate(value.h_id)
|
||||||
|
else
|
||||||
|
raise ArgumentError, "Invalid value for Column serialization: #{value}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
36
app/types/sorted_column_type.rb
Normal file
36
app/types/sorted_column_type.rb
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class SortedColumnType < ActiveRecord::Type::Value
|
||||||
|
# form_input or setter -> type
|
||||||
|
def cast(value)
|
||||||
|
value = value.deep_symbolize_keys if value.respond_to?(:deep_symbolize_keys)
|
||||||
|
|
||||||
|
case value
|
||||||
|
in SortedColumn
|
||||||
|
value
|
||||||
|
in NilClass # default value
|
||||||
|
nil
|
||||||
|
# from form (id is a string) or from db (id is a hash)
|
||||||
|
in { order: 'asc'|'desc', id: String|Hash } => h
|
||||||
|
SortedColumn.new(column: ColumnType.new.cast(h[:id]), order: h[:order])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# db -> ruby
|
||||||
|
def deserialize(value) = cast(value&.then { JSON.parse(_1) })
|
||||||
|
|
||||||
|
# ruby -> db
|
||||||
|
def serialize(value)
|
||||||
|
case value
|
||||||
|
in NilClass
|
||||||
|
nil
|
||||||
|
in SortedColumn
|
||||||
|
JSON.generate({
|
||||||
|
id: value.column.h_id,
|
||||||
|
order: value.order
|
||||||
|
})
|
||||||
|
else
|
||||||
|
raise ArgumentError, "Invalid value for SortedColumn serialization: #{value}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -93,8 +93,7 @@
|
||||||
%th.text-center
|
%th.text-center
|
||||||
%input{ type: "checkbox", disabled: @disable_checkbox_all, checked: @disable_checkbox_all, data: { action: "batch-operation#onCheckAll" }, id: dom_id(BatchOperation.new, :checkbox_all), aria: { label: t('views.instructeurs.dossiers.select_all') } }
|
%input{ type: "checkbox", disabled: @disable_checkbox_all, checked: @disable_checkbox_all, data: { action: "batch-operation#onCheckAll" }, id: dom_id(BatchOperation.new, :checkbox_all), aria: { label: t('views.instructeurs.dossiers.select_all') } }
|
||||||
|
|
||||||
- @procedure_presentation.displayed_fields_for_headers.each do |column|
|
= render Instructeurs::ColumnTableHeaderComponent.new(procedure_presentation: @procedure_presentation)
|
||||||
= render Instructeurs::ColumnTableHeaderComponent.new(procedure_presentation: @procedure_presentation, column:)
|
|
||||||
|
|
||||||
%th.follow-col
|
%th.follow-col
|
||||||
Actions
|
Actions
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require Rails.root.join("app/types/column_type")
|
||||||
require Rails.root.join("app/types/export_item_type")
|
require Rails.root.join("app/types/export_item_type")
|
||||||
|
require Rails.root.join("app/types/sorted_column_type")
|
||||||
|
|
||||||
ActiveSupport.on_load(:active_record) do
|
ActiveSupport.on_load(:active_record) do
|
||||||
|
ActiveRecord::Type.register(:column, ColumnType)
|
||||||
ActiveRecord::Type.register(:export_item, ExportItemType)
|
ActiveRecord::Type.register(:export_item, ExportItemType)
|
||||||
|
ActiveRecord::Type.register(:sorted_column, SortedColumnType)
|
||||||
end
|
end
|
||||||
|
|
|
@ -481,7 +481,7 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
|
|
||||||
patch 'update_displayed_fields'
|
patch 'update_displayed_fields'
|
||||||
get 'update_sort/:column_id' => 'procedures#update_sort', as: 'update_sort'
|
get 'update_sort' => 'procedures#update_sort', as: 'update_sort'
|
||||||
post 'add_filter'
|
post 'add_filter'
|
||||||
post 'update_filter'
|
post 'update_filter'
|
||||||
get 'remove_filter'
|
get 'remove_filter'
|
||||||
|
|
|
@ -886,11 +886,11 @@ describe Instructeurs::ProceduresController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'can change order' do
|
it 'can change order' do
|
||||||
column_id = procedure.find_column(label: "Nom").id
|
column = procedure.find_column(label: "Nom")
|
||||||
expect { get :update_sort, params: { procedure_id: procedure.id, column_id:, order: 'asc' } }
|
expect { get :update_sort, params: { procedure_id: procedure.id, sorted_column: { id: column.id, order: 'asc' } } }
|
||||||
.to change { procedure_presentation.sort }
|
.to change { procedure_presentation.sorted_column }
|
||||||
.from({ "column" => "notifications", "order" => "desc", "table" => "notifications" })
|
.from(procedure.default_sorted_column)
|
||||||
.to({ "column" => "nom", "order" => "asc", "table" => "individual" })
|
.to(SortedColumn.new(column:, order: 'asc'))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -47,24 +47,4 @@ describe '20201001161931_migrate_filters_to_use_stable_id' do
|
||||||
expect(procedure_presentation_without_migration.filters['suivis']).to be_present
|
expect(procedure_presentation_without_migration.filters['suivis']).to be_present
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the procedure presentation is invalid' do
|
|
||||||
before do
|
|
||||||
procedure_presentation_with_migration.update_column(
|
|
||||||
:sort,
|
|
||||||
{ table: 'invalid-table', column: 'invalid-column', order: 'invalid-order' }
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'removes the "migrated" key properly' do
|
|
||||||
run_task
|
|
||||||
expect(procedure_presentation_with_migration).not_to be_valid
|
|
||||||
expect(procedure_presentation_with_migration.filters).not_to have_key('migrated')
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'leaves the other keys unchanged' do
|
|
||||||
run_task
|
|
||||||
expect(procedure_presentation_without_migration.filters['suivis']).to be_present
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -45,10 +45,10 @@ describe '20240920130741_migrate_procedure_presentation_to_columns.rake' do
|
||||||
|
|
||||||
order, column_id = procedure_presentation
|
order, column_id = procedure_presentation
|
||||||
.sorted_column
|
.sorted_column
|
||||||
.then { |sorted| [sorted['order'], sorted['id']] }
|
.then { |sorted| [sorted.order, sorted.column.h_id] }
|
||||||
|
|
||||||
expect(order).to eq('desc')
|
expect(order).to eq('desc')
|
||||||
expect(column_id).to eq("procedure_id" => procedure_id, "column_id" => "self/en_construction_at")
|
expect(column_id).to eq(procedure_id: procedure_id, column_id: "self/en_construction_at")
|
||||||
|
|
||||||
expect(procedure_presentation.tous_filters).to eq([])
|
expect(procedure_presentation.tous_filters).to eq([])
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
describe ColumnsConcern do
|
describe ColumnsConcern do
|
||||||
|
describe '#find_column' do
|
||||||
|
let(:procedure) { build(:procedure) }
|
||||||
|
let(:notifications_column) { procedure.notifications_column }
|
||||||
|
|
||||||
|
it do
|
||||||
|
label = notifications_column.label
|
||||||
|
expect(procedure.find_column(label:)).to eq(notifications_column)
|
||||||
|
|
||||||
|
h_id = notifications_column.h_id
|
||||||
|
expect(procedure.find_column(h_id:)).to eq(notifications_column)
|
||||||
|
|
||||||
|
unknwon = 'unknown'
|
||||||
|
expect { procedure.find_column(h_id: unknwon) }.to raise_error(ActiveRecord::RecordNotFound)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#columns" do
|
describe "#columns" do
|
||||||
subject { procedure.columns }
|
subject { procedure.columns }
|
||||||
|
|
||||||
|
|
|
@ -41,13 +41,6 @@ describe ProcedurePresentation do
|
||||||
it { expect(build(:procedure_presentation, displayed_fields: [{ table: "user", column: "reset_password_token", "order" => "asc" }])).to be_invalid }
|
it { expect(build(:procedure_presentation, displayed_fields: [{ table: "user", column: "reset_password_token", "order" => "asc" }])).to be_invalid }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'of sort' do
|
|
||||||
it { expect(build(:procedure_presentation, sort: { table: "notifications", column: "notifications", "order" => "asc" })).to be_valid }
|
|
||||||
it { expect(build(:procedure_presentation, sort: { table: "self", column: "id", "order" => "asc" })).to be_valid }
|
|
||||||
it { expect(build(:procedure_presentation, sort: { table: "self", column: "state", "order" => "asc" })).to be_valid }
|
|
||||||
it { expect(build(:procedure_presentation, sort: { table: "user", column: "reset_password_token", "order" => "asc" })).to be_invalid }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'of filters' do
|
context 'of filters' do
|
||||||
it { expect(build(:procedure_presentation, filters: { "suivis" => [{ table: "user", column: "reset_password_token", "order" => "asc" }] })).to be_invalid }
|
it { expect(build(:procedure_presentation, filters: { "suivis" => [{ table: "user", column: "reset_password_token", "order" => "asc" }] })).to be_invalid }
|
||||||
it { expect(build(:procedure_presentation, filters: { "suivis" => [{ table: "user", column: "email", "value" => "exceedingly long filter value" * 10 }] })).to be_invalid }
|
it { expect(build(:procedure_presentation, filters: { "suivis" => [{ table: "user", column: "email", "value" => "exceedingly long filter value" * 10 }] })).to be_invalid }
|
||||||
|
@ -61,19 +54,18 @@ describe ProcedurePresentation do
|
||||||
|
|
||||||
describe '#sorted_ids' do
|
describe '#sorted_ids' do
|
||||||
let(:instructeur) { create(:instructeur) }
|
let(:instructeur) { create(:instructeur) }
|
||||||
let(:assign_to) { create(:assign_to, procedure: procedure, instructeur: instructeur) }
|
let(:assign_to) { create(:assign_to, procedure:, instructeur:) }
|
||||||
let(:sort) { { 'table' => table, 'column' => column, 'order' => order } }
|
let(:sorted_column) { SortedColumn.new(column:, order:) }
|
||||||
let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to, sort: sort) }
|
let(:procedure_presentation) { create(:procedure_presentation, assign_to:, sorted_column:) }
|
||||||
|
|
||||||
subject { procedure_presentation.send(:sorted_ids, procedure.dossiers, procedure.dossiers.count) }
|
subject { procedure_presentation.send(:sorted_ids, procedure.dossiers, procedure.dossiers.count) }
|
||||||
|
|
||||||
context 'for notifications table' do
|
context 'for notifications table' do
|
||||||
let(:table) { 'notifications' }
|
let(:column) { procedure.notifications_column }
|
||||||
let(:column) { 'notifications' }
|
|
||||||
|
|
||||||
let!(:notified_dossier) { create(:dossier, :en_construction, procedure: procedure) }
|
let!(:notified_dossier) { create(:dossier, :en_construction, procedure:) }
|
||||||
let!(:recent_dossier) { create(:dossier, :en_construction, procedure: procedure) }
|
let!(:recent_dossier) { create(:dossier, :en_construction, procedure:) }
|
||||||
let!(:older_dossier) { create(:dossier, :en_construction, procedure: procedure) }
|
let!(:older_dossier) { create(:dossier, :en_construction, procedure:) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
notified_dossier.update!(last_champ_updated_at: Time.zone.local(2018, 9, 20))
|
notified_dossier.update!(last_champ_updated_at: Time.zone.local(2018, 9, 20))
|
||||||
|
@ -96,7 +88,7 @@ describe ProcedurePresentation do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a dossier terminé' do
|
context 'with a dossier terminé' do
|
||||||
let!(:notified_dossier) { create(:dossier, :accepte, procedure: procedure) }
|
let!(:notified_dossier) { create(:dossier, :accepte, procedure:) }
|
||||||
let(:order) { 'desc' }
|
let(:order) { 'desc' }
|
||||||
|
|
||||||
it { is_expected.to eq([notified_dossier, recent_dossier, older_dossier].map(&:id)) }
|
it { is_expected.to eq([notified_dossier, recent_dossier, older_dossier].map(&:id)) }
|
||||||
|
@ -104,11 +96,10 @@ describe ProcedurePresentation do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for self table' do
|
context 'for self table' do
|
||||||
let(:table) { 'self' }
|
|
||||||
let(:order) { 'asc' } # Desc works the same, no extra test required
|
let(:order) { 'asc' } # Desc works the same, no extra test required
|
||||||
|
|
||||||
context 'for created_at column' do
|
context 'for created_at column' do
|
||||||
let(:column) { 'created_at' }
|
let!(:column) { procedure.find_column(label: 'Créé le') }
|
||||||
let!(:recent_dossier) { Timecop.freeze(Time.zone.local(2018, 10, 17)) { create(:dossier, procedure: procedure) } }
|
let!(:recent_dossier) { Timecop.freeze(Time.zone.local(2018, 10, 17)) { create(:dossier, procedure: procedure) } }
|
||||||
let!(:older_dossier) { Timecop.freeze(Time.zone.local(2003, 11, 11)) { create(:dossier, procedure: procedure) } }
|
let!(:older_dossier) { Timecop.freeze(Time.zone.local(2003, 11, 11)) { create(:dossier, procedure: procedure) } }
|
||||||
|
|
||||||
|
@ -116,7 +107,7 @@ describe ProcedurePresentation do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for en_construction_at column' do
|
context 'for en_construction_at column' do
|
||||||
let(:column) { 'en_construction_at' }
|
let!(:column) { procedure.find_column(label: 'En construction le') }
|
||||||
let!(:recent_dossier) { create(:dossier, :en_construction, procedure: procedure, en_construction_at: Time.zone.local(2018, 10, 17)) }
|
let!(:recent_dossier) { create(:dossier, :en_construction, procedure: procedure, en_construction_at: Time.zone.local(2018, 10, 17)) }
|
||||||
let!(:older_dossier) { create(:dossier, :en_construction, procedure: procedure, en_construction_at: Time.zone.local(2013, 1, 1)) }
|
let!(:older_dossier) { create(:dossier, :en_construction, procedure: procedure, en_construction_at: Time.zone.local(2013, 1, 1)) }
|
||||||
|
|
||||||
|
@ -124,7 +115,7 @@ describe ProcedurePresentation do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for updated_at column' do
|
context 'for updated_at column' do
|
||||||
let(:column) { 'updated_at' }
|
let(:column) { procedure.find_column(label: 'Mis à jour le') }
|
||||||
let(:recent_dossier) { create(:dossier, procedure: procedure) }
|
let(:recent_dossier) { create(:dossier, procedure: procedure) }
|
||||||
let(:older_dossier) { create(:dossier, procedure: procedure) }
|
let(:older_dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
|
||||||
|
@ -140,10 +131,10 @@ describe ProcedurePresentation do
|
||||||
context 'for type_de_champ table' do
|
context 'for type_de_champ table' do
|
||||||
context 'with no revisions' do
|
context 'with no revisions' do
|
||||||
let(:table) { 'type_de_champ' }
|
let(:table) { 'type_de_champ' }
|
||||||
let(:column) { procedure.active_revision.types_de_champ_public.first.stable_id.to_s }
|
let(:column) { procedure.find_column(label: first_type_de_champ.libelle) }
|
||||||
|
|
||||||
let(:beurre_dossier) { create(:dossier, procedure: procedure) }
|
let(:beurre_dossier) { create(:dossier, procedure:) }
|
||||||
let(:tartine_dossier) { create(:dossier, procedure: procedure) }
|
let(:tartine_dossier) { create(:dossier, procedure:) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
beurre_dossier.project_champs_public.first.update(value: 'beurre')
|
beurre_dossier.project_champs_public.first.update(value: 'beurre')
|
||||||
|
@ -165,12 +156,11 @@ describe ProcedurePresentation do
|
||||||
|
|
||||||
context 'with a revision adding a new type_de_champ' do
|
context 'with a revision adding a new type_de_champ' do
|
||||||
let!(:tdc) { { type_champ: :text, libelle: 'nouveau champ' } }
|
let!(:tdc) { { type_champ: :text, libelle: 'nouveau champ' } }
|
||||||
let(:table) { 'type_de_champ' }
|
let(:column) { procedure.find_column(label: 'nouveau champ') }
|
||||||
let(:column) { procedure.active_revision.types_de_champ_public.last.stable_id.to_s }
|
|
||||||
|
|
||||||
let(:nothing_dossier) { create(:dossier, procedure: procedure) }
|
let!(:nothing_dossier) { create(:dossier, procedure:) }
|
||||||
let(:beurre_dossier) { create(:dossier, procedure: procedure) }
|
let!(:beurre_dossier) { create(:dossier, procedure:) }
|
||||||
let(:tartine_dossier) { create(:dossier, procedure: procedure) }
|
let!(:tartine_dossier) { create(:dossier, procedure:) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
nothing_dossier
|
nothing_dossier
|
||||||
|
@ -182,20 +172,19 @@ describe ProcedurePresentation do
|
||||||
|
|
||||||
context 'asc' do
|
context 'asc' do
|
||||||
let(:order) { 'asc' }
|
let(:order) { 'asc' }
|
||||||
it { is_expected.to eq([beurre_dossier, tartine_dossier, nothing_dossier].map(&:id)) }
|
it { is_expected.to eq([nothing_dossier, beurre_dossier, tartine_dossier].map(&:id)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'desc' do
|
context 'desc' do
|
||||||
let(:order) { 'desc' }
|
let(:order) { 'desc' }
|
||||||
it { is_expected.to eq([nothing_dossier, tartine_dossier, beurre_dossier].map(&:id)) }
|
it { is_expected.to eq([tartine_dossier, beurre_dossier, nothing_dossier].map(&:id)) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for type_de_champ_private table' do
|
context 'for type_de_champ_private table' do
|
||||||
context 'with no revisions' do
|
context 'with no revisions' do
|
||||||
let(:table) { 'type_de_champ' }
|
let(:column) { procedure.find_column(label: procedure.active_revision.types_de_champ_private.first.libelle) }
|
||||||
let(:column) { procedure.active_revision.types_de_champ_private.first.stable_id.to_s }
|
|
||||||
|
|
||||||
let(:biere_dossier) { create(:dossier, procedure: procedure) }
|
let(:biere_dossier) { create(:dossier, procedure: procedure) }
|
||||||
let(:vin_dossier) { create(:dossier, procedure: procedure) }
|
let(:vin_dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
@ -217,38 +206,9 @@ describe ProcedurePresentation do
|
||||||
it { is_expected.to eq([vin_dossier, biere_dossier].map(&:id)) }
|
it { is_expected.to eq([vin_dossier, biere_dossier].map(&:id)) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a revision adding a new type_de_champ' do
|
|
||||||
let!(:tdc) { { type_champ: :text, private: true, libelle: 'nouveau champ' } }
|
|
||||||
let(:table) { 'type_de_champ' }
|
|
||||||
let(:column) { procedure.active_revision.types_de_champ_private.last.stable_id.to_s }
|
|
||||||
|
|
||||||
let(:nothing_dossier) { create(:dossier, procedure: procedure) }
|
|
||||||
let(:biere_dossier) { create(:dossier, procedure: procedure) }
|
|
||||||
let(:vin_dossier) { create(:dossier, procedure: procedure) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
nothing_dossier
|
|
||||||
procedure.draft_revision.add_type_de_champ(tdc)
|
|
||||||
procedure.publish_revision!
|
|
||||||
biere_dossier.project_champs_private.last.update(value: 'biere')
|
|
||||||
vin_dossier.project_champs_private.last.update(value: 'vin')
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'asc' do
|
|
||||||
let(:order) { 'asc' }
|
|
||||||
it { is_expected.to eq([biere_dossier, vin_dossier, nothing_dossier].map(&:id)) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'desc' do
|
|
||||||
let(:order) { 'desc' }
|
|
||||||
it { is_expected.to eq([nothing_dossier, vin_dossier, biere_dossier].map(&:id)) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for individual table' do
|
context 'for individual table' do
|
||||||
let(:table) { 'individual' }
|
|
||||||
let(:order) { 'asc' } # Desc works the same, no extra test required
|
let(:order) { 'asc' } # Desc works the same, no extra test required
|
||||||
|
|
||||||
let(:procedure) { create(:procedure, :for_individual) }
|
let(:procedure) { create(:procedure, :for_individual) }
|
||||||
|
@ -257,26 +217,25 @@ describe ProcedurePresentation do
|
||||||
let!(:last_dossier) { create(:dossier, procedure: procedure, individual: build(:individual, gender: 'Mme', prenom: 'Zora', nom: 'Zemmour')) }
|
let!(:last_dossier) { create(:dossier, procedure: procedure, individual: build(:individual, gender: 'Mme', prenom: 'Zora', nom: 'Zemmour')) }
|
||||||
|
|
||||||
context 'for gender column' do
|
context 'for gender column' do
|
||||||
let(:column) { 'gender' }
|
let(:column) { procedure.find_column(label: 'Civilité') }
|
||||||
|
|
||||||
it { is_expected.to eq([first_dossier, last_dossier].map(&:id)) }
|
it { is_expected.to eq([first_dossier, last_dossier].map(&:id)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for prenom column' do
|
context 'for prenom column' do
|
||||||
let(:column) { 'prenom' }
|
let(:column) { procedure.find_column(label: 'Prénom') }
|
||||||
|
|
||||||
it { is_expected.to eq([first_dossier, last_dossier].map(&:id)) }
|
it { is_expected.to eq([first_dossier, last_dossier].map(&:id)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for nom column' do
|
context 'for nom column' do
|
||||||
let(:column) { 'nom' }
|
let(:column) { procedure.find_column(label: 'Nom') }
|
||||||
|
|
||||||
it { is_expected.to eq([first_dossier, last_dossier].map(&:id)) }
|
it { is_expected.to eq([first_dossier, last_dossier].map(&:id)) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for followers_instructeurs table' do
|
context 'for followers_instructeurs table' do
|
||||||
let(:table) { 'followers_instructeurs' }
|
|
||||||
let(:order) { 'asc' } # Desc works the same, no extra test required
|
let(:order) { 'asc' } # Desc works the same, no extra test required
|
||||||
|
|
||||||
let!(:dossier_z) { create(:dossier, :en_construction, procedure: procedure) }
|
let!(:dossier_z) { create(:dossier, :en_construction, procedure: procedure) }
|
||||||
|
@ -290,15 +249,14 @@ describe ProcedurePresentation do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for email column' do
|
context 'for email column' do
|
||||||
let(:column) { 'email' }
|
let(:column) { procedure.find_column(label: 'Email instructeur') }
|
||||||
|
|
||||||
it { is_expected.to eq([dossier_a, dossier_z, dossier_without_instructeur].map(&:id)) }
|
it { is_expected.to eq([dossier_a, dossier_z, dossier_without_instructeur].map(&:id)) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for avis table' do
|
context 'for avis table' do
|
||||||
let(:table) { 'avis' }
|
let(:column) { procedure.find_column(label: 'Avis oui/non') }
|
||||||
let(:column) { 'question_answer' }
|
|
||||||
let(:order) { 'asc' }
|
let(:order) { 'asc' }
|
||||||
|
|
||||||
let!(:dossier_yes) { create(:dossier, procedure:) }
|
let!(:dossier_yes) { create(:dossier, procedure:) }
|
||||||
|
@ -315,8 +273,7 @@ describe ProcedurePresentation do
|
||||||
|
|
||||||
context 'for other tables' do
|
context 'for other tables' do
|
||||||
# All other columns and tables work the same so it’s ok to test only one
|
# All other columns and tables work the same so it’s ok to test only one
|
||||||
let(:table) { 'etablissement' }
|
let(:column) { procedure.find_column(label: 'Code postal') }
|
||||||
let(:column) { 'code_postal' }
|
|
||||||
let(:order) { 'asc' } # Desc works the same, no extra test required
|
let(:order) { 'asc' } # Desc works the same, no extra test required
|
||||||
|
|
||||||
let!(:huitieme_dossier) { create(:dossier, procedure: procedure, etablissement: create(:etablissement, code_postal: '75008')) }
|
let!(:huitieme_dossier) { create(:dossier, procedure: procedure, etablissement: create(:etablissement, code_postal: '75008')) }
|
||||||
|
@ -971,7 +928,7 @@ describe ProcedurePresentation do
|
||||||
describe '#update_displayed_fields' do
|
describe '#update_displayed_fields' do
|
||||||
let(:procedure_presentation) do
|
let(:procedure_presentation) do
|
||||||
create(:procedure_presentation, assign_to:).tap do |pp|
|
create(:procedure_presentation, assign_to:).tap do |pp|
|
||||||
pp.update_sort(procedure.find_column(label: 'Demandeur').id, 'desc')
|
pp.update(sorted_column: SortedColumn.new(column: procedure.find_column(label: 'Demandeur'), order: 'desc'))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -992,26 +949,8 @@ describe ProcedurePresentation do
|
||||||
{ "column_id" => "self/updated_at", "procedure_id" => procedure.id }
|
{ "column_id" => "self/updated_at", "procedure_id" => procedure.id }
|
||||||
])
|
])
|
||||||
|
|
||||||
expect(procedure_presentation.sorted_column['id']).to eq("column_id" => "self/id", "procedure_id" => procedure.id)
|
expect(procedure_presentation.sorted_column).to eq(procedure.default_sorted_column)
|
||||||
expect(procedure_presentation.sorted_column['order']).to eq('desc')
|
expect(procedure_presentation.sorted_column.order).to eq('desc')
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#update_sort' do
|
|
||||||
let(:procedure_presentation) { create(:procedure_presentation, assign_to:) }
|
|
||||||
|
|
||||||
subject do
|
|
||||||
column_id = procedure.find_column(label: 'En construction le').id
|
|
||||||
procedure_presentation.update_sort(column_id, 'asc')
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should update sort and order' do
|
|
||||||
expect(procedure_presentation.sorted_column).to be_nil
|
|
||||||
|
|
||||||
subject
|
|
||||||
|
|
||||||
expect(procedure_presentation.sorted_column['id']).to eq("column_id" => "self/en_construction_at", "procedure_id" => procedure.id)
|
|
||||||
expect(procedure_presentation.sorted_column['order']).to eq('asc')
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
28
spec/models/sorted_column_spec.rb
Normal file
28
spec/models/sorted_column_spec.rb
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
describe SortedColumn do
|
||||||
|
let(:column) { Column.new(procedure_id: 1, table: 'table', column: 'column') }
|
||||||
|
let(:sorted_column) { SortedColumn.new(column: column, order: 'asc') }
|
||||||
|
|
||||||
|
describe '==' do
|
||||||
|
it 'returns true for the same sorted column' do
|
||||||
|
other = SortedColumn.new(column: column, order: 'asc')
|
||||||
|
expect(sorted_column == other).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false if the order is different' do
|
||||||
|
other = SortedColumn.new(column: column, order: 'desc')
|
||||||
|
expect(sorted_column == other).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false if the column is different' do
|
||||||
|
other_column = Column.new(procedure_id: 1, table: 'table', column: 'other')
|
||||||
|
other = SortedColumn.new(column: other_column, order: 'asc')
|
||||||
|
expect(sorted_column == other).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false if the other is nil' do
|
||||||
|
expect(sorted_column == nil).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
71
spec/types/column_type_spec.rb
Normal file
71
spec/types/column_type_spec.rb
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
describe ColumnType do
|
||||||
|
let(:type) { ColumnType.new }
|
||||||
|
|
||||||
|
describe 'cast' do
|
||||||
|
it 'from Column' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
expect(type.cast(column)).to eq(column)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'from nil' do
|
||||||
|
expect(type.cast(nil)).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'from form' do
|
||||||
|
it 'with valid column id' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
|
||||||
|
expect(Column).to receive(:find).with(column.h_id).and_return(column)
|
||||||
|
expect(type.cast(column.id)).to eq(column)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'with invalid column id' do
|
||||||
|
expect { type.cast('invalid') }.to raise_error(JSON::ParserError)
|
||||||
|
|
||||||
|
id = { procedure_id: 'invalid', column_id: 'nop' }.to_json
|
||||||
|
expect { type.cast(id) }.to raise_error(ActiveRecord::RecordNotFound)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'from db' do
|
||||||
|
it 'with valid column id' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
expect(Column).to receive(:find).with(column.h_id).and_return(column)
|
||||||
|
expect(type.cast(column.h_id)).to eq(column)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'with invalid column id' do
|
||||||
|
h_id = { procedure_id: 'invalid', column_id: 'nop' }
|
||||||
|
expect { type.cast(h_id) }.to raise_error(ActiveRecord::RecordNotFound)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'deserialize' do
|
||||||
|
context 'with valid value' do
|
||||||
|
it 'works' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
expect(Column).to receive(:find).with(column.h_id).and_return(column)
|
||||||
|
|
||||||
|
expect(type.deserialize(column.h_id)).to eq(column)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'serialize' do
|
||||||
|
it 'with SortedColumn' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
expect(type.serialize(column)).to eq(column.h_id.to_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'with nil' do
|
||||||
|
expect(type.serialize(nil)).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'with invalid value' do
|
||||||
|
expect { type.serialize('invalid') }.to raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
71
spec/types/sorted_column_type_spec.rb
Normal file
71
spec/types/sorted_column_type_spec.rb
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
describe SortedColumnType do
|
||||||
|
let(:type) { SortedColumnType.new }
|
||||||
|
|
||||||
|
describe 'cast' do
|
||||||
|
it 'from SortedColumn' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
sorted_column = SortedColumn.new(column:, order: 'asc')
|
||||||
|
expect(type.cast(sorted_column)).to eq(sorted_column)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'from nil' do
|
||||||
|
expect(type.cast(nil)).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'from form' do
|
||||||
|
it 'with valid column id' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
h = { order: 'asc', id: column.id }
|
||||||
|
|
||||||
|
expect(Column).to receive(:find).with(column.h_id).and_return(column)
|
||||||
|
expect(type.cast(h)).to eq(SortedColumn.new(column: column, order: 'asc'))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'with invalid column id' do
|
||||||
|
h = { order: 'asc', id: 'invalid' }
|
||||||
|
expect { type.cast(h) }.to raise_error(JSON::ParserError)
|
||||||
|
|
||||||
|
h = { order: 'asc', id: { procedure_id: 'invalid', column_id: 'nop' }.to_json }
|
||||||
|
expect { type.cast(h) }.to raise_error(ActiveRecord::RecordNotFound)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'with invalid order' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
h = { order: 'invalid', id: column.id }
|
||||||
|
expect { type.cast(h) }.to raise_error(NoMatchingPatternError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'deserialize' do
|
||||||
|
context 'with valid value' do
|
||||||
|
it 'works' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
expect(Column).to receive(:find).with(column.h_id).and_return(column)
|
||||||
|
expect(type.deserialize({ id: column.h_id, order: 'asc' }.to_json)).to eq(SortedColumn.new(column: column, order: 'asc'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with nil' do
|
||||||
|
it { expect(type.deserialize(nil)).to eq(nil) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'serialize' do
|
||||||
|
it 'with SortedColumn' do
|
||||||
|
column = Column.new(procedure_id: 1, table: 'table', column: 'column')
|
||||||
|
sorted_column = SortedColumn.new(column: column, order: 'asc')
|
||||||
|
expect(type.serialize(sorted_column)).to eq({ id: column.h_id, order: 'asc' }.to_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'with nil' do
|
||||||
|
expect(type.serialize(nil)).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'with invalid value' do
|
||||||
|
expect { type.serialize('invalid') }.to raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Add table
Add a link
Reference in a new issue