tech(remaniement): extraction du passage d'une liste de champs a un simili arbre
This commit is contained in:
parent
ad77b9321b
commit
3b5d1bd55b
4 changed files with 186 additions and 13 deletions
|
@ -21,6 +21,17 @@
|
|||
# type_de_champ_id :integer
|
||||
#
|
||||
class Champs::HeaderSectionChamp < Champ
|
||||
|
||||
def level
|
||||
if parent.present?
|
||||
header_section_level_value.to_i + parent.current_section_level
|
||||
elsif header_section_level_value
|
||||
header_section_level_value.to_i
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
def search_terms
|
||||
# The user cannot enter any information here so it doesn’t make much sense to search
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module Champs::Treeable
|
||||
module TreeableConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
MAX_DEPTH = 6 # deepest level for header_sections is 3.
|
||||
|
@ -16,27 +16,22 @@ module Champs::Treeable
|
|||
# are added to the most_recent_subtree
|
||||
# given a root_depth at 0, we build a full tree
|
||||
# given a root_depth > 0, we build a partial tree (aka, a repetition)
|
||||
def to_tree(champs:, root_depth:, build_champs_subtree_component:)
|
||||
root = build_champs_subtree_component(header_section: nil)
|
||||
def to_tree(champs:, root_depth:)
|
||||
root = []
|
||||
depth_cache = Array.new(MAX_DEPTH)
|
||||
depth_cache[root_depth] = root
|
||||
most_recent_subtree = root
|
||||
|
||||
champs.each do |champ|
|
||||
if champ.header_section?
|
||||
champs_subtree = build_champs_subtree_component(header_section: champ)
|
||||
depth_cache[champs_subtree.level - 1].add_node(champs_subtree)
|
||||
most_recent_subtree = depth_cache[champs_subtree.level] = champs_subtree
|
||||
champs_subtree = [champ]
|
||||
depth_cache[champ.level - 1].push(champs_subtree)
|
||||
most_recent_subtree = depth_cache[champ.level] = champs_subtree
|
||||
else
|
||||
most_recent_subtree.add_node(champ)
|
||||
most_recent_subtree.push(champ)
|
||||
end
|
||||
end
|
||||
root
|
||||
end
|
||||
|
||||
# must be implemented to render subtree
|
||||
def build_champs_subtree_component(header_section:)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
|
@ -413,8 +413,13 @@ class TypeDeChamp < ApplicationRecord
|
|||
end
|
||||
|
||||
def header_section_level_value
|
||||
header_section_level.presence || 1
|
||||
if header_section_level.presence
|
||||
header_section_level.to_i
|
||||
else
|
||||
1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def previous_section_level(upper_tdcs)
|
||||
previous_header_section = upper_tdcs.reverse.find(&:header_section?)
|
||||
|
|
162
spec/models/concern/treeable_concern_spec.rb
Normal file
162
spec/models/concern/treeable_concern_spec.rb
Normal file
|
@ -0,0 +1,162 @@
|
|||
describe TreeableConcern do
|
||||
class ChampsToTree
|
||||
include TreeableConcern
|
||||
attr_reader :root
|
||||
def initialize(champs:, root_depth:)
|
||||
@root = to_tree(champs:, root_depth:)
|
||||
end
|
||||
end
|
||||
|
||||
subject { ChampsToTree.new(champs: champs, root_depth: 0).root }
|
||||
describe "to_tree" do
|
||||
let(:header_1) { build(:champ_header_section_level_1) }
|
||||
let(:header_1_2) { build(:champ_header_section_level_2) }
|
||||
let(:header_2) { build(:champ_header_section_level_1) }
|
||||
let(:champ_text) { build(:champ_text) }
|
||||
let(:champ_textarea) { build(:champ_textarea) }
|
||||
let(:champ_explication) { build(:champ_explication) }
|
||||
let(:champ_communes) { build(:champ_communes) }
|
||||
|
||||
context 'without section' do
|
||||
let(:champs) do
|
||||
[
|
||||
champ_text, champ_textarea
|
||||
]
|
||||
end
|
||||
it 'inlines champs at root level' do
|
||||
expect(subject.size).to eq(champs.size)
|
||||
expect(subject).to eq(champs)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with header_section and champs' do
|
||||
let(:champs) do
|
||||
[
|
||||
header_1,
|
||||
champ_explication,
|
||||
champ_text,
|
||||
header_2,
|
||||
champ_textarea
|
||||
]
|
||||
end
|
||||
|
||||
it 'wraps champs within preview header section' do
|
||||
expect(subject.size).to eq(2)
|
||||
expect(subject).to eq([
|
||||
[ header_1, champ_explication, champ_text ],
|
||||
[ header_2, champ_textarea ]
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
context 'leading champs, and in between sections only' do
|
||||
let(:champs) do
|
||||
[
|
||||
champ_text,
|
||||
champ_textarea,
|
||||
header_1,
|
||||
champ_explication,
|
||||
champ_communes,
|
||||
header_2,
|
||||
champ_textarea
|
||||
]
|
||||
end
|
||||
it 'chunk by uniq champs' do
|
||||
expect(subject.size).to eq(4)
|
||||
expect(subject).to eq([
|
||||
champ_text,
|
||||
champ_textarea,
|
||||
[header_1, champ_explication, champ_communes],
|
||||
[header_2, champ_textarea]
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with one sub sections' do
|
||||
let(:champs) do
|
||||
[
|
||||
header_1,
|
||||
champ_explication,
|
||||
header_1_2,
|
||||
champ_communes,
|
||||
header_2,
|
||||
champ_textarea
|
||||
]
|
||||
end
|
||||
it 'chunk by uniq champs' do
|
||||
expect(subject.size).to eq(2)
|
||||
expect(subject).to eq([
|
||||
[header_1, champ_explication, [header_1_2, champ_communes]],
|
||||
[header_2, champ_textarea]
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with consecutive subsection' do
|
||||
let(:header_1) { build(:champ_header_section_level_1) }
|
||||
let(:header_1_2_1) { build(:champ_header_section_level_2) }
|
||||
let(:header_1_2_2) { build(:champ_header_section_level_2) }
|
||||
let(:header_1_2_3) { build(:champ_header_section_level_2) }
|
||||
let(:champs) do
|
||||
[
|
||||
header_1,
|
||||
header_1_2_1,
|
||||
champ_text,
|
||||
header_1_2_2,
|
||||
champ_textarea,
|
||||
header_1_2_3,
|
||||
champ_communes
|
||||
]
|
||||
end
|
||||
it 'chunk by uniq champs' do
|
||||
expect(subject.size).to eq(1)
|
||||
expect(subject).to eq([
|
||||
[
|
||||
header_1,
|
||||
[header_1_2_1, champ_text],
|
||||
[header_1_2_2, champ_textarea],
|
||||
[header_1_2_3, champ_communes]
|
||||
]
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with one sub sections and one subsub section' do
|
||||
let(:header_1_2_3) { build(:champ_header_section_level_3) }
|
||||
|
||||
let(:champs) do
|
||||
[
|
||||
header_1,
|
||||
champ_explication,
|
||||
header_1_2,
|
||||
champ_communes,
|
||||
header_1_2_3,
|
||||
champ_text,
|
||||
header_2,
|
||||
champ_textarea
|
||||
]
|
||||
end
|
||||
|
||||
it 'chunk by uniq champs' do
|
||||
expect(subject.size).to eq(2)
|
||||
expect(subject).to eq([
|
||||
[
|
||||
header_1,
|
||||
champ_explication,
|
||||
[
|
||||
header_1_2,
|
||||
champ_communes,
|
||||
[
|
||||
header_1_2_3, champ_text
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
header_2,
|
||||
champ_textarea
|
||||
]
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue