Merge pull request #8390 from tchak/refactor-repetitions-row-id-use

refactor(repetition): use row_id instead of row
This commit is contained in:
Paul Chavard 2023-01-10 19:40:07 +01:00 committed by GitHub
commit 341311cd7f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 47 additions and 36 deletions

View file

@ -1,9 +1,9 @@
- row_dom_id = "row-#{SecureRandom.hex(4)}" - row_id = @row.first.row_id
.row{ id: row_dom_id } .row{ id: row_id }
- @row.each do |champ| - @row.each do |champ|
= fields_for champ.input_name, champ do |form| = fields_for champ.input_name, champ do |form|
= render EditableChamp::EditableChampComponent.new form: form, champ: champ, seen_at: @seen_at = render EditableChamp::EditableChampComponent.new form: form, champ: champ, seen_at: @seen_at
.flex.row-reverse{ 'data-turbo': 'true' } .flex.row-reverse{ 'data-turbo': 'true' }
= link_to champs_repetition_path(@champ.id, champ_ids: @row.map(&:id), row_id: row_dom_id), data: { turbo_method: :delete }, class: 'fr-btn fr-btn--sm fr-btn--tertiary fr-text-action-high--red-marianne' do = link_to champs_repetition_path(@champ.id, row_id:), data: { turbo_method: :delete }, class: 'fr-btn fr-btn--sm fr-btn--tertiary fr-text-action-high--red-marianne' do
Supprimer lélément Supprimer lélément

View file

@ -8,7 +8,7 @@ class Champs::RepetitionController < ApplicationController
def remove def remove
champ = policy_scope(Champ).includes(:champs).find(params[:champ_id]) champ = policy_scope(Champ).includes(:champs).find(params[:champ_id])
champ.champs.where(id: params[:champ_ids]).destroy_all champ.champs.where(row_id: params[:row_id]).destroy_all
@row_id = params[:row_id] @row_id = params[:row_id]
end end
end end

View file

@ -40,13 +40,11 @@ module Mutations
end end
def find_annotation(dossier, annotation_id) def find_annotation(dossier, annotation_id)
stable_id, row = Champ.decode_typed_id(annotation_id) stable_id, row_id = Champ.decode_typed_id(annotation_id)
Champ.joins(:type_de_champ).find_by(type_de_champ: { Champ.joins(:type_de_champ).find_by(type_de_champ: {
type_champ: annotation_type_champ, type_champ: annotation_type_champ, stable_id:, private: true
stable_id:, }, private: true, row_id:, dossier:)
private: true
}, private: true, row:, dossier:)
end end
def annotation_type_champ def annotation_type_champ

View file

@ -26,13 +26,11 @@ module Mutations
private private
def find_annotation(dossier, annotation_id) def find_annotation(dossier, annotation_id)
stable_id, row = Champ.decode_typed_id(annotation_id) stable_id, row_id = Champ.decode_typed_id(annotation_id)
Champ.joins(:type_de_champ).find_by(type_de_champ: { Champ.joins(:type_de_champ).find_by(type_de_champ: {
type_champ: TypeDeChamp.type_champs.fetch(:repetition), type_champ: TypeDeChamp.type_champs.fetch(:repetition), stable_id:, private: true
stable_id: stable_id, }, private: true, row_id:, dossier:)
private: true
}, private: true, row: row, dossier: dossier)
end end
end end
end end

View file

@ -2177,6 +2177,7 @@ type Revision {
type Row { type Row {
champs: [Champ!]! champs: [Champ!]!
id: ID!
} }
type SelectionUtilisateur implements GeoArea { type SelectionUtilisateur implements GeoArea {

View file

@ -3,6 +3,7 @@ module Types::Champs
implements Types::ChampType implements Types::ChampType
class Row < Types::BaseObject class Row < Types::BaseObject
global_id_field :id
field :champs, [Types::ChampType], null: false field :champs, [Types::ChampType], null: false
end end
@ -18,7 +19,7 @@ module Types::Champs
def rows def rows
Loaders::Association.for(object.class, champs: :type_de_champ).load(object).then do |champs| Loaders::Association.for(object.class, champs: :type_de_champ).load(object).then do |champs|
object.association(:champs).target = champs.filter(&:visible?) object.association(:champs).target = champs.filter(&:visible?)
object.rows.map { { champs: _1 } } object.rows.map { { champs: _1, id: GraphQL::Schema::UniqueWithinType.encode('Row', _1.first.row_id) } }
end end
end end
end end

View file

@ -22,6 +22,7 @@
# type_de_champ_id :integer # type_de_champ_id :integer
# #
class Champ < ApplicationRecord class Champ < ApplicationRecord
self.ignored_columns = [:row]
belongs_to :dossier, inverse_of: false, touch: true, optional: false belongs_to :dossier, inverse_of: false, touch: true, optional: false
belongs_to :type_de_champ, inverse_of: :champ, optional: false belongs_to :type_de_champ, inverse_of: :champ, optional: false
belongs_to :parent, class_name: 'Champ', optional: true belongs_to :parent, class_name: 'Champ', optional: true
@ -77,7 +78,7 @@ class Champ < ApplicationRecord
includes(:type_de_champ) includes(:type_de_champ)
.joins(dossier: { revision: :revision_types_de_champ }) .joins(dossier: { revision: :revision_types_de_champ })
.where('procedure_revision_types_de_champ.type_de_champ_id = champs.type_de_champ_id') .where('procedure_revision_types_de_champ.type_de_champ_id = champs.type_de_champ_id')
.order(:row, :position) .order(:row_id, :position)
end end
scope :public_ordered, -> { public_only.ordered } scope :public_ordered, -> { public_only.ordered }
scope :private_ordered, -> { private_only.ordered } scope :private_ordered, -> { private_only.ordered }
@ -146,8 +147,8 @@ class Champ < ApplicationRecord
end end
def to_typed_id def to_typed_id
if row.present? if row_id.present?
GraphQL::Schema::UniqueWithinType.encode('Champ', "#{stable_id}|#{row}") GraphQL::Schema::UniqueWithinType.encode('Champ', "#{stable_id}|#{row_id}")
else else
type_de_champ.to_typed_id type_de_champ.to_typed_id
end end
@ -225,7 +226,7 @@ class Champ < ApplicationRecord
end end
def clone def clone
champ_attributes = [:parent_id, :private, :row, :row_id, :type, :type_de_champ_id] champ_attributes = [:parent_id, :private, :row_id, :type, :type_de_champ_id]
value_attributes = private? ? [] : [:value, :value_json, :data, :external_id] value_attributes = private? ? [] : [:value, :value_json, :data, :external_id]
relationships = private? ? [] : [:etablissement, :geo_areas] relationships = private? ? [] : [:etablissement, :geo_areas]
@ -237,7 +238,7 @@ class Champ < ApplicationRecord
private private
def champs_for_condition def champs_for_condition
dossier.champs.filter { _1.row.nil? || _1.row == row } dossier.champs.filter { _1.row_id.nil? || _1.row_id == row_id }
end end
def html_id def html_id

View file

@ -26,16 +26,15 @@ class Champs::RepetitionChamp < Champ
delegate :libelle_for_export, to: :type_de_champ delegate :libelle_for_export, to: :type_de_champ
def rows def rows
champs.group_by(&:row).values champs.group_by(&:row_id).values
end end
def add_row(revision) def add_row(revision)
added_champs = [] added_champs = []
transaction do transaction do
row = (blank? ? -1 : champs.last.row) + 1
row_id = ULID.generate row_id = ULID.generate
revision.children_of(type_de_champ).each do |type_de_champ| revision.children_of(type_de_champ).each do |type_de_champ|
added_champs << type_de_champ.champ.build(row:, row_id:) added_champs << type_de_champ.champ.build(row_id:)
end end
self.champs << added_champs self.champs << added_champs
end end

View file

@ -116,8 +116,8 @@ module DossierRebaseConcern
.where(type_de_champ: { stable_id: parent_stable_id }) .where(type_de_champ: { stable_id: parent_stable_id })
champs_repetition.each do |champ_repetition| champs_repetition.each do |champ_repetition|
champ_repetition.champs.index_by(&:row).each do |(row, champ)| champ_repetition.champs.map(&:row_id).uniq.each do |row_id|
create_champ(target_coordinate, champ_repetition, row:, row_id: champ.row_id) create_champ(target_coordinate, champ_repetition, row_id:)
end end
end end
else else
@ -125,8 +125,8 @@ module DossierRebaseConcern
end end
end end
def create_champ(target_coordinate, parent, row: nil, row_id: nil) def create_champ(target_coordinate, parent, row_id: nil)
params = { revision: target_coordinate.revision, row:, row_id: }.compact params = { revision: target_coordinate.revision, row_id: }.compact
champ = target_coordinate champ = target_coordinate
.type_de_champ .type_de_champ
.build_champ(params) .build_champ(params)

View file

@ -112,7 +112,7 @@ class DossierPreloader
end end
parent.association(name).target = champs.sort_by do |champ| parent.association(name).target = champs.sort_by do |champ|
[champ.row, positions[dossier.revision_id][champ.type_de_champ_id]] [champ.row_id, positions[dossier.revision_id][champ.type_de_champ_id]]
end end
# Load children champs # Load children champs

View file

@ -66,7 +66,7 @@ class GeoArea < ApplicationRecord
id: id, id: id,
champ_label: champ.libelle, champ_label: champ.libelle,
champ_id: champ.stable_id, champ_id: champ.stable_id,
champ_row: champ.row, champ_row: champ.row_id,
champ_private: champ.private?, champ_private: champ.private?,
dossier_id: champ.dossier_id dossier_id: champ.dossier_id
).compact ).compact

View file

@ -0,0 +1,5 @@
class RemoveChampsRowIndex < ActiveRecord::Migration[6.1]
def change
remove_index :champs, name: "index_champs_on_type_de_champ_id_and_dossier_id_and_row"
end
end

View file

@ -0,0 +1,7 @@
class AddChampsRowIdIndex < ActiveRecord::Migration[6.1]
disable_ddl_transaction!
def change
add_index :champs, [:type_de_champ_id, :dossier_id, :row_id], unique: true, algorithm: :concurrently
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2023_01_09_140138) do ActiveRecord::Schema.define(version: 2023_01_10_181426) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto" enable_extension "pgcrypto"
@ -240,7 +240,7 @@ ActiveRecord::Schema.define(version: 2023_01_09_140138) do
t.index ["row"], name: "index_champs_on_row" t.index ["row"], name: "index_champs_on_row"
t.index ["row_id"], name: "index_champs_on_row_id" t.index ["row_id"], name: "index_champs_on_row_id"
t.index ["type"], name: "index_champs_on_type" t.index ["type"], name: "index_champs_on_type"
t.index ["type_de_champ_id", "dossier_id", "row"], name: "index_champs_on_type_de_champ_id_and_dossier_id_and_row", unique: true t.index ["type_de_champ_id", "dossier_id", "row_id"], name: "index_champs_on_type_de_champ_id_and_dossier_id_and_row_id", unique: true
t.index ["type_de_champ_id"], name: "index_champs_on_type_de_champ_id" t.index ["type_de_champ_id"], name: "index_champs_on_type_de_champ_id"
end end

View file

@ -231,9 +231,10 @@ FactoryBot.define do
parent = revision.revision_types_de_champ.find { |rtdc| rtdc.type_de_champ == champ_repetition.type_de_champ } parent = revision.revision_types_de_champ.find { |rtdc| rtdc.type_de_champ == champ_repetition.type_de_champ }
types_de_champ = revision.revision_types_de_champ.filter { |rtdc| rtdc.parent == parent }.map(&:type_de_champ) types_de_champ = revision.revision_types_de_champ.filter { |rtdc| rtdc.parent == parent }.map(&:type_de_champ)
evaluator.rows.times do |row| evaluator.rows.times do
row_id = ULID.generate
champ_repetition.champs << types_de_champ.map do |type_de_champ| champ_repetition.champs << types_de_champ.map do |type_de_champ|
build(:"champ_#{type_de_champ.type_champ}", dossier: champ_repetition.dossier, row: row, type_de_champ: type_de_champ, parent: champ_repetition, private: champ_repetition.private?) build(:"champ_#{type_de_champ.type_champ}", dossier: champ_repetition.dossier, row_id:, type_de_champ: type_de_champ, parent: champ_repetition, private: champ_repetition.private?)
end end
end end
end end

View file

@ -501,14 +501,14 @@ describe Champ do
let(:champ) { dossier.champs_public.find(&:repetition?) } let(:champ) { dossier.champs_public.find(&:repetition?) }
let(:champ_text) { champ.champs.find { |c| c.type_champ == 'text' } } let(:champ_text) { champ.champs.find { |c| c.type_champ == 'text' } }
let(:champ_integer) { champ.champs.find { |c| c.type_champ == 'integer_number' } } let(:champ_integer) { champ.champs.find { |c| c.type_champ == 'integer_number' } }
let(:champ_text_attrs) { attributes_for(:champ_text, type_de_champ: tdc_text, row: 1) } let(:champ_text_attrs) { attributes_for(:champ_text, type_de_champ: tdc_text, row_id: ULID.generate) }
before do before do
procedure.active_revision.add_type_de_champ(libelle: 'sub integer', type_champ: 'integer_number', parent_stable_id: tdc_repetition.stable_id) procedure.active_revision.add_type_de_champ(libelle: 'sub integer', type_champ: 'integer_number', parent_stable_id: tdc_repetition.stable_id)
end end
context 'when creating the model directly' do context 'when creating the model directly' do
let(:champ_text_row_1) { create(:champ_text, type_de_champ: tdc_text, row: 2, parent: champ, dossier: nil) } let(:champ_text_row_1) { create(:champ_text, type_de_champ: tdc_text, row_id: ULID.generate, parent: champ, dossier: nil) }
it 'associates nested champs to the parent dossier' do it 'associates nested champs to the parent dossier' do
expect(champ_text_row_1.dossier_id).to eq(champ.dossier_id) expect(champ_text_row_1.dossier_id).to eq(champ.dossier_id)

View file

@ -278,7 +278,7 @@ describe Dossier do
# Add two rows then remove previous to last row in order to create a "hole" in the sequence # Add two rows then remove previous to last row in order to create a "hole" in the sequence
repetition_champ.add_row(repetition_champ.dossier.revision) repetition_champ.add_row(repetition_champ.dossier.revision)
repetition_champ.add_row(repetition_champ.dossier.revision) repetition_champ.add_row(repetition_champ.dossier.revision)
repetition_champ.champs.where(row: repetition_champ.champs.last.row - 1).destroy_all repetition_champ.champs.where(row_id: repetition_champ.rows[-2].first.row_id).destroy_all
repetition_champ.reload repetition_champ.reload
end end