Merge pull request #7544 from betagouv/types_de_champ_controller_manage_condition
feat: rajoute les conditions dans l'éditeur
This commit is contained in:
commit
b9945696f3
26 changed files with 419 additions and 138 deletions
|
@ -1,3 +1,3 @@
|
|||
%ul.types-de-champ-block{ id: block_id, data: sortable_options }
|
||||
- @coordinates.each do |coordinate|
|
||||
= render TypesDeChampEditor::ChampComponent.new(coordinate: coordinate)
|
||||
- @coordinates.each.with_index do |coordinate, i|
|
||||
= render TypesDeChampEditor::ChampComponent.new(coordinate: coordinate, upper_coordinates: @coordinates.take(i))
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
class TypesDeChampEditor::ChampComponent < ApplicationComponent
|
||||
def initialize(coordinate:, focused: false)
|
||||
attr_reader :coordinate, :upper_coordinates
|
||||
|
||||
def initialize(coordinate:, upper_coordinates:, focused: false)
|
||||
@coordinate = coordinate
|
||||
@focused = focused
|
||||
@upper_coordinates = upper_coordinates
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :coordinate
|
||||
delegate :type_de_champ, :revision, :procedure, to: :coordinate
|
||||
|
||||
def can_be_mandatory?
|
||||
|
|
|
@ -83,3 +83,5 @@
|
|||
.editor-block.flex-grow.cell
|
||||
= render TypesDeChampEditor::BlockComponent.new(block: coordinate, coordinates: coordinate.revision_types_de_champ)
|
||||
= render TypesDeChampEditor::AddChampButtonComponent.new(revision: coordinate.revision, parent: coordinate, is_annotation: coordinate.private?)
|
||||
|
||||
= render(TypesDeChampEditor::ConditionsComponent.new(tdc: type_de_champ, upper_tdcs: @upper_coordinates.map(&:type_de_champ), procedure_id: procedure.id))
|
||||
|
|
|
@ -201,7 +201,11 @@ class TypesDeChampEditor::ConditionsComponent < ApplicationComponent
|
|||
end
|
||||
|
||||
def render?
|
||||
if Flipper.enabled?(:conditional, controller.current_user)
|
||||
@condition.present? || available_targets_for_select.any?
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def input_name_for(name)
|
||||
|
|
|
@ -22,11 +22,11 @@ class TypesDeChampEditor::ConditionsErrorsComponent < ApplicationComponent
|
|||
elsif left.type == :unmanaged
|
||||
t('unmanaged', scope: '.errors',
|
||||
libelle: targeted_champ.libelle,
|
||||
type_champ: t(targeted_champ.type_champ, scope: '.type'))
|
||||
type_champ: t(targeted_champ.type_champ, scope: 'activerecord.attributes.type_de_champ.type_champs')&.downcase)
|
||||
else
|
||||
t('incompatible', scope: '.errors',
|
||||
libelle: targeted_champ.libelle,
|
||||
type_champ: t(targeted_champ.type_champ, scope: '.type'),
|
||||
type_champ: t(targeted_champ.type_champ, scope: 'activerecord.attributes.type_de_champ.type_champs')&.downcase,
|
||||
operator: t(operator_name, scope: 'logic.operators').downcase,
|
||||
right: right.to_s.downcase)
|
||||
end
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
---
|
||||
fr:
|
||||
type:
|
||||
number: un nombre
|
||||
string: un texte
|
||||
boolean: soit oui, soit non
|
||||
yes_no: soit oui, soit non
|
||||
address: une adresse
|
||||
errors:
|
||||
not_available: "Un champ cible n'est plus disponible. Il est soit supprimé, soit déplacé en dessous de ce champ."
|
||||
unmanaged: "Le champ « %{libelle} » est %{type_champ} et ne peut pas être utilisé comme champ cible."
|
||||
incompatible: "Le champ « %{libelle} » est %{type_champ}. Il ne peut pas être %{operator} %{right}."
|
||||
unmanaged: "Le champ « %{libelle} » est de type « %{type_champ} » et ne peut pas être utilisé comme champ cible."
|
||||
incompatible: "Le champ « %{libelle} » est de type « %{type_champ} ». Il ne peut pas être %{operator} %{right}."
|
||||
|
|
|
@ -6,54 +6,58 @@ module Administrateurs
|
|||
|
||||
def update
|
||||
condition = condition_form.to_condition
|
||||
tdc.update!(condition: condition)
|
||||
@tdc.update!(condition: condition)
|
||||
|
||||
render 'administrateurs/types_de_champ/update.turbo_stream.haml'
|
||||
@condition_component = build_condition_component
|
||||
end
|
||||
|
||||
def add_row
|
||||
condition = Logic.add_empty_condition_to(tdc.condition)
|
||||
tdc.update!(condition: condition)
|
||||
condition = Logic.add_empty_condition_to(@tdc.condition)
|
||||
@tdc.update!(condition: condition)
|
||||
|
||||
render 'administrateurs/types_de_champ/update.turbo_stream.haml'
|
||||
@condition_component = build_condition_component
|
||||
end
|
||||
|
||||
def delete_row
|
||||
condition = condition_form.delete_row(row_index).to_condition
|
||||
tdc.update!(condition: condition)
|
||||
@tdc.update!(condition: condition)
|
||||
|
||||
render 'administrateurs/types_de_champ/update.turbo_stream.haml'
|
||||
@condition_component = build_condition_component
|
||||
end
|
||||
|
||||
def destroy
|
||||
tdc.update!(condition: nil)
|
||||
@tdc.update!(condition: nil)
|
||||
|
||||
render 'administrateurs/types_de_champ/update.turbo_stream.haml'
|
||||
@condition_component = build_condition_component
|
||||
end
|
||||
|
||||
def change_targeted_champ
|
||||
condition = condition_form.change_champ(row_index).to_condition
|
||||
tdc.update!(condition: condition)
|
||||
@tdc.update!(condition: condition)
|
||||
|
||||
render 'administrateurs/types_de_champ/update.turbo_stream.haml'
|
||||
@condition_component = build_condition_component
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_condition_component
|
||||
TypesDeChampEditor::ConditionsComponent.new(
|
||||
tdc: @tdc,
|
||||
upper_tdcs: @upper_tdcs,
|
||||
procedure_id: @procedure.id
|
||||
)
|
||||
end
|
||||
|
||||
def condition_form
|
||||
ConditionForm.new(condition_params)
|
||||
end
|
||||
|
||||
def retrieve_coordinate_and_uppers
|
||||
@coordinate = draft_revision.coordinate_for(tdc)
|
||||
@upper_coordinates = draft_revision
|
||||
.revision_types_de_champ_public
|
||||
.includes(:type_de_champ)
|
||||
.take_while { |c| c != @coordinate }
|
||||
end
|
||||
|
||||
def tdc
|
||||
@tdc ||= draft_revision.find_and_ensure_exclusive_use(params[:stable_id])
|
||||
@tdc = draft_revision.find_and_ensure_exclusive_use(params[:stable_id])
|
||||
@coordinate = draft_revision.coordinate_for(@tdc)
|
||||
@upper_tdcs = draft_revision
|
||||
.upper_coordinates(@coordinate.position)
|
||||
.map(&:type_de_champ)
|
||||
end
|
||||
|
||||
def draft_revision
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
module Administrateurs
|
||||
class TypesDeChampController < AdministrateurController
|
||||
before_action :retrieve_procedure, only: [:create, :update, :move, :move_up, :move_down, :destroy]
|
||||
before_action :procedure_revisable?, only: [:create, :update, :move, :move_up, :move_down, :destroy]
|
||||
before_action :retrieve_procedure, :procedure_revisable?
|
||||
|
||||
def create
|
||||
type_de_champ = @procedure.draft_revision.add_type_de_champ(type_de_champ_create_params)
|
||||
type_de_champ = draft.add_type_de_champ(type_de_champ_create_params)
|
||||
|
||||
if type_de_champ.valid?
|
||||
@coordinate = @procedure.draft_revision.coordinate_for(type_de_champ)
|
||||
@coordinate = draft.coordinate_for(type_de_champ)
|
||||
@created = champ_component_from(@coordinate, focused: true)
|
||||
@morphed = champ_components_starting_at(@coordinate.position + 1)
|
||||
|
||||
reset_procedure
|
||||
flash.notice = "Formulaire enregistré"
|
||||
else
|
||||
|
@ -16,12 +18,12 @@ module Administrateurs
|
|||
end
|
||||
|
||||
def update
|
||||
type_de_champ = @procedure.draft_revision.find_and_ensure_exclusive_use(params[:stable_id])
|
||||
type_de_champ = draft.find_and_ensure_exclusive_use(params[:stable_id])
|
||||
|
||||
if type_de_champ.update(type_de_champ_update_params)
|
||||
if params[:should_render]
|
||||
@coordinate = @procedure.draft_revision.coordinate_for(type_de_champ)
|
||||
end
|
||||
@coordinate = draft.coordinate_for(type_de_champ)
|
||||
@morphed = champ_components_starting_at(@coordinate.position)
|
||||
|
||||
reset_procedure
|
||||
flash.notice = "Formulaire enregistré"
|
||||
else
|
||||
|
@ -31,27 +33,53 @@ module Administrateurs
|
|||
|
||||
def move
|
||||
flash.notice = "Formulaire enregistré"
|
||||
@procedure.draft_revision.move_type_de_champ(params[:stable_id], params[:position].to_i)
|
||||
draft.move_type_de_champ(params[:stable_id], params[:position].to_i)
|
||||
end
|
||||
|
||||
def move_up
|
||||
flash.notice = "Formulaire enregistré"
|
||||
@coordinate = @procedure.draft_revision.move_up_type_de_champ(params[:stable_id])
|
||||
@coordinate = draft.move_up_type_de_champ(params[:stable_id])
|
||||
@destroyed = @coordinate
|
||||
@created = champ_component_from(@coordinate)
|
||||
# update the one component below
|
||||
@morphed = champ_components_starting_at(@coordinate.position + 1).take(1)
|
||||
end
|
||||
|
||||
def move_down
|
||||
flash.notice = "Formulaire enregistré"
|
||||
@coordinate = @procedure.draft_revision.move_down_type_de_champ(params[:stable_id])
|
||||
@coordinate = draft.move_down_type_de_champ(params[:stable_id])
|
||||
@destroyed = @coordinate
|
||||
@created = champ_component_from(@coordinate)
|
||||
# update the one component above
|
||||
@morphed = champ_components_starting_at(@coordinate.position - 1).take(1)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@coordinate = @procedure.draft_revision.remove_type_de_champ(params[:stable_id])
|
||||
@coordinate = draft.remove_type_de_champ(params[:stable_id])
|
||||
reset_procedure
|
||||
flash.notice = "Formulaire enregistré"
|
||||
|
||||
@destroyed = @coordinate
|
||||
@morphed = champ_components_starting_at(@coordinate.position)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def champ_components_starting_at(position)
|
||||
draft
|
||||
.coordinates_starting_at(position)
|
||||
.lazy
|
||||
.map { |c| champ_component_from(c) }
|
||||
end
|
||||
|
||||
def champ_component_from(coordinate, focused: false)
|
||||
TypesDeChampEditor::ChampComponent.new(
|
||||
coordinate: coordinate,
|
||||
upper_coordinates: draft.upper_coordinates(coordinate.position),
|
||||
focused: focused
|
||||
)
|
||||
end
|
||||
|
||||
def type_de_champ_create_params
|
||||
params
|
||||
.required(:type_de_champ)
|
||||
|
@ -82,5 +110,9 @@ module Administrateurs
|
|||
:znieff
|
||||
])
|
||||
end
|
||||
|
||||
def draft
|
||||
@procedure.draft_revision
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,10 +33,10 @@ class Logic::ChampValue < Logic::Term
|
|||
end
|
||||
end
|
||||
|
||||
def to_s = "#{type_de_champ.libelle} Nº#{stable_id}"
|
||||
def to_s = "#{type_de_champ&.libelle} Nº#{stable_id}" # TODO: gerer le cas ou un tdc est supprimé
|
||||
|
||||
def type
|
||||
case type_de_champ.type_champ
|
||||
case type_de_champ&.type_champ # TODO: gerer le cas ou un tdc est supprimé
|
||||
when MANAGED_TYPE_DE_CHAMP.fetch(:yes_no),
|
||||
MANAGED_TYPE_DE_CHAMP.fetch(:checkbox)
|
||||
CHAMP_VALUE_TYPE.fetch(:boolean)
|
||||
|
|
|
@ -59,7 +59,7 @@ class ProcedureRevision < ApplicationRecord
|
|||
h = { type_de_champ: tdc, parent_id: parent_id, position: position }
|
||||
coordinate = revision_types_de_champ.create!(h)
|
||||
|
||||
reorder(coordinate.reload.siblings)
|
||||
renumber(coordinate.reload.siblings)
|
||||
end
|
||||
|
||||
# they are not aware of the addition
|
||||
|
@ -88,7 +88,7 @@ class ProcedureRevision < ApplicationRecord
|
|||
|
||||
siblings.insert(position, siblings.delete_at(siblings.index(coordinate)))
|
||||
|
||||
reorder(siblings)
|
||||
renumber(siblings)
|
||||
coordinate.reload
|
||||
|
||||
coordinate
|
||||
|
@ -107,7 +107,7 @@ class ProcedureRevision < ApplicationRecord
|
|||
types_de_champ_public.reset
|
||||
types_de_champ_private.reset
|
||||
|
||||
reorder(coordinate.siblings)
|
||||
renumber(coordinate.siblings)
|
||||
|
||||
coordinate
|
||||
end
|
||||
|
@ -197,6 +197,14 @@ class ProcedureRevision < ApplicationRecord
|
|||
revision_types_de_champ.find_by!(type_de_champ: tdc)
|
||||
end
|
||||
|
||||
def upper_coordinates(position)
|
||||
revision_types_de_champ_public.filter { |c| c.position < position }
|
||||
end
|
||||
|
||||
def coordinates_starting_at(position)
|
||||
revision_types_de_champ_public.reload.filter { |c| position <= c.position }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def compute_estimated_fill_duration
|
||||
|
@ -221,10 +229,10 @@ class ProcedureRevision < ApplicationRecord
|
|||
.joins(:type_de_champ)
|
||||
.find_by(type_de_champ: { stable_id: stable_id })
|
||||
|
||||
[coordinate, coordinate.type_de_champ]
|
||||
[coordinate, coordinate&.type_de_champ]
|
||||
end
|
||||
|
||||
def reorder(siblings)
|
||||
def renumber(siblings)
|
||||
siblings.to_a.compact.each.with_index do |sibling, position|
|
||||
sibling.update_column(:position, position)
|
||||
end
|
||||
|
@ -482,7 +490,8 @@ class ProcedureRevision < ApplicationRecord
|
|||
types_de_champ_public
|
||||
.map.with_index
|
||||
.filter_map { |tdc, i| tdc.condition.present? ? [tdc, i] : nil }
|
||||
.flat_map { |tdc, i| tdc.condition.errors(stable_ids.take(i)) }
|
||||
.each { |message| errors.add(:condition, message) }
|
||||
.map { |tdc, i| [tdc, tdc.condition.errors(stable_ids.take(i))] }
|
||||
.filter { |_tdc, errors| errors.present? }
|
||||
.each { |tdc, message| errors.add(:condition, message, type_de_champ: tdc) }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
- rendered = render @condition_component
|
||||
|
||||
- if rendered.present?
|
||||
= turbo_stream.morph dom_id(@tdc, :conditions) do
|
||||
- rendered
|
||||
end
|
||||
- else
|
||||
= turbo_stream.remove dom_id(@tdc, :conditions)
|
|
@ -0,0 +1 @@
|
|||
= render partial: 'update'
|
|
@ -0,0 +1 @@
|
|||
= render partial: 'update'
|
|
@ -0,0 +1 @@
|
|||
= render partial: 'update'
|
|
@ -0,0 +1 @@
|
|||
= render partial: 'update'
|
|
@ -0,0 +1 @@
|
|||
= render partial: 'update'
|
|
@ -1,9 +1,19 @@
|
|||
- sibling = coordinate.previous_sibling
|
||||
- if @destroyed.present?
|
||||
= turbo_stream.remove dom_id(@destroyed, :type_de_champ_editor)
|
||||
|
||||
- if @created.present?
|
||||
- if @created.coordinate.previous_sibling.present?
|
||||
= turbo_stream.after dom_id(@created.coordinate.previous_sibling, :type_de_champ_editor) do
|
||||
= render @created
|
||||
- else
|
||||
= turbo_stream.prepend dom_id(@created.coordinate.block, :types_de_champ_editor_block) do
|
||||
= render @created
|
||||
|
||||
- @morphed&.each do |champ_component|
|
||||
= turbo_stream.morph dom_id(champ_component.coordinate, :type_de_champ_editor) do
|
||||
= render champ_component
|
||||
|
||||
= turbo_stream.morph dom_id(@coordinate.revision, :estimated_fill_duration) do
|
||||
= render TypesDeChampEditor::EstimatedFillDurationComponent.new(revision: @coordinate.revision, is_annotation: @coordinate.private?)
|
||||
|
||||
- if sibling.present?
|
||||
= turbo_stream.after dom_id(sibling, :type_de_champ_editor) do
|
||||
= render TypesDeChampEditor::ChampComponent.new(coordinate: coordinate, focused: true)
|
||||
- else
|
||||
= turbo_stream.prepend dom_id(coordinate.block, :types_de_champ_editor_block) do
|
||||
= render TypesDeChampEditor::ChampComponent.new(coordinate: coordinate, focused: true)
|
||||
= turbo_stream.dispatch 'sortable:sort'
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
- if @coordinate&.type_de_champ&.valid?
|
||||
= render partial: 'insert', locals: { coordinate: @coordinate }
|
||||
= render partial: 'insert'
|
||||
|
|
|
@ -1,4 +1 @@
|
|||
= turbo_stream.remove dom_id(@coordinate, :type_de_champ_editor)
|
||||
= turbo_stream.dispatch 'sortable:sort'
|
||||
= turbo_stream.morph dom_id(@coordinate.revision, :estimated_fill_duration) do
|
||||
= render TypesDeChampEditor::EstimatedFillDurationComponent.new(revision: @coordinate.revision, is_annotation: @coordinate.private?)
|
||||
= render partial: 'insert'
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
= turbo_stream.remove dom_id(@coordinate, :type_de_champ_editor)
|
||||
= render partial: 'insert', locals: { coordinate: @coordinate }
|
||||
= render partial: 'insert'
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
= turbo_stream.remove dom_id(@coordinate, :type_de_champ_editor)
|
||||
= render partial: 'insert', locals: { coordinate: @coordinate }
|
||||
= render partial: 'insert'
|
||||
|
|
|
@ -1,5 +1 @@
|
|||
- if @coordinate&.type_de_champ&.valid?
|
||||
= turbo_stream.morph dom_id(@coordinate, :type_de_champ_editor) do
|
||||
= render TypesDeChampEditor::ChampComponent.new(coordinate: @coordinate)
|
||||
= turbo_stream.morph dom_id(@coordinate.revision, :estimated_fill_duration) do
|
||||
= render TypesDeChampEditor::EstimatedFillDurationComponent.new(revision: @coordinate.revision, is_annotation: @coordinate.private?)
|
||||
= render partial: 'insert'
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
describe TypesDeChampEditor::ConditionsComponent, type: :component do
|
||||
include Logic
|
||||
|
||||
# TODO: remove along with feature flipping
|
||||
before do
|
||||
allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(nil)
|
||||
allow(Flipper).to receive(:enabled?).with(:conditional, anything).and_return(true)
|
||||
end
|
||||
|
||||
describe 'render' do
|
||||
let(:tdc) { create(:type_de_champ, condition: condition) }
|
||||
let(:condition) { nil }
|
||||
|
|
|
@ -5,9 +5,7 @@ describe Administrateurs::ConditionsController, type: :controller do
|
|||
let(:first_coordinate) { procedure.draft_revision.revision_types_de_champ.first }
|
||||
let(:second_tdc) { procedure.draft_revision.types_de_champ.second }
|
||||
|
||||
before do
|
||||
sign_in(procedure.administrateurs.first.user)
|
||||
end
|
||||
before { sign_in(procedure.administrateurs.first.user) }
|
||||
|
||||
let(:default_params) do
|
||||
{
|
||||
|
@ -17,9 +15,7 @@ describe Administrateurs::ConditionsController, type: :controller do
|
|||
end
|
||||
|
||||
describe '#update' do
|
||||
before do
|
||||
post :update, params: params
|
||||
end
|
||||
before { post :update, params: params, format: :turbo_stream }
|
||||
|
||||
let(:params) { default_params.merge(type_de_champ: { condition_form: condition_form }) }
|
||||
|
||||
|
@ -38,26 +34,22 @@ describe Administrateurs::ConditionsController, type: :controller do
|
|||
it do
|
||||
expect(second_tdc.reload.condition).to eq(ds_eq(champ_value(1), constant(2)))
|
||||
expect(assigns(:coordinate)).to eq(procedure.draft_revision.coordinate_for(second_tdc))
|
||||
expect(assigns(:upper_coordinates)).to eq([first_coordinate])
|
||||
expect(assigns(:upper_tdcs)).to eq([first_coordinate.type_de_champ])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#add_row' do
|
||||
before do
|
||||
post :add_row, params: default_params
|
||||
end
|
||||
before { post :add_row, params: default_params, format: :turbo_stream }
|
||||
|
||||
it do
|
||||
expect(second_tdc.reload.condition).to eq(empty_operator(empty, empty))
|
||||
expect(assigns(:coordinate)).to eq(procedure.draft_revision.coordinate_for(second_tdc))
|
||||
expect(assigns(:upper_coordinates)).to eq([first_coordinate])
|
||||
expect(assigns(:upper_tdcs)).to eq([first_coordinate.type_de_champ])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#delete_row' do
|
||||
before do
|
||||
delete :delete_row, params: params.merge(row_index: 0)
|
||||
end
|
||||
before { delete :delete_row, params: params.merge(row_index: 0), format: :turbo_stream }
|
||||
|
||||
let(:params) { default_params.merge(type_de_champ: { condition_form: condition_form }) }
|
||||
|
||||
|
@ -76,20 +68,20 @@ describe Administrateurs::ConditionsController, type: :controller do
|
|||
it do
|
||||
expect(second_tdc.reload.condition).to eq(nil)
|
||||
expect(assigns(:coordinate)).to eq(procedure.draft_revision.coordinate_for(second_tdc))
|
||||
expect(assigns(:upper_coordinates)).to eq([first_coordinate])
|
||||
expect(assigns(:upper_tdcs)).to eq([first_coordinate.type_de_champ])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#destroy' do
|
||||
before do
|
||||
second_tdc.update(condition: empty_operator(empty, empty))
|
||||
delete :destroy, params: default_params
|
||||
delete :destroy, params: default_params, format: :turbo_stream
|
||||
end
|
||||
|
||||
it do
|
||||
expect(second_tdc.reload.condition).to eq(nil)
|
||||
expect(assigns(:coordinate)).to eq(procedure.draft_revision.coordinate_for(second_tdc))
|
||||
expect(assigns(:upper_coordinates)).to eq([first_coordinate])
|
||||
expect(assigns(:upper_tdcs)).to eq([first_coordinate.type_de_champ])
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -98,7 +90,7 @@ describe Administrateurs::ConditionsController, type: :controller do
|
|||
|
||||
before do
|
||||
second_tdc.update(condition: empty_operator(empty, empty))
|
||||
patch :change_targeted_champ, params: params
|
||||
patch :change_targeted_champ, params: params, format: :turbo_stream
|
||||
end
|
||||
|
||||
let(:params) { default_params.merge(type_de_champ: { condition_form: condition_form }) }
|
||||
|
@ -118,7 +110,7 @@ describe Administrateurs::ConditionsController, type: :controller do
|
|||
it do
|
||||
expect(second_tdc.reload.condition).to eq(ds_eq(champ_value(number_tdc.stable_id), constant(0)))
|
||||
expect(assigns(:coordinate)).to eq(procedure.draft_revision.coordinate_for(second_tdc))
|
||||
expect(assigns(:upper_coordinates)).to eq([first_coordinate])
|
||||
expect(assigns(:upper_tdcs)).to eq([first_coordinate.type_de_champ])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,65 +1,159 @@
|
|||
describe Administrateurs::TypesDeChampController, type: :controller do
|
||||
let(:admin) { create(:administrateur) }
|
||||
|
||||
describe '#types_de_champs editor' do
|
||||
let(:procedure) { create(:procedure) }
|
||||
|
||||
before do
|
||||
admin.procedures << procedure
|
||||
sign_in(admin.user)
|
||||
let(:procedure) do
|
||||
create(:procedure).tap do |p|
|
||||
p.draft_revision.add_type_de_champ(type_champ: :integer_number, libelle: 'l1')
|
||||
p.draft_revision.add_type_de_champ(type_champ: :integer_number, libelle: 'l2')
|
||||
p.draft_revision.add_type_de_champ(type_champ: :integer_number, libelle: 'l3')
|
||||
p.draft_revision.add_type_de_champ(type_champ: :yes_no, libelle: 'bon dossier', private: true)
|
||||
end
|
||||
end
|
||||
|
||||
let(:type_champ) { TypeDeChamp.type_champs.fetch(:text) }
|
||||
def first_coordinate = procedure.draft_revision.revision_types_de_champ_public.first
|
||||
def second_coordinate = procedure.draft_revision.revision_types_de_champ_public.reload.second
|
||||
def third_coordinate = procedure.draft_revision.revision_types_de_champ_public.reload.third
|
||||
|
||||
context "create type_de_champ text" do
|
||||
before do
|
||||
post :create, params: {
|
||||
def extract_libelle(champ_component) = [champ_component.coordinate.libelle, champ_component.upper_coordinates.map(&:libelle)]
|
||||
|
||||
def morpheds
|
||||
assigns(:morphed)
|
||||
.map { |component| extract_libelle(component) }.to_a
|
||||
end
|
||||
|
||||
before { sign_in(procedure.administrateurs.first.user) }
|
||||
|
||||
describe '#create' do
|
||||
let(:params) { default_params }
|
||||
|
||||
let(:default_params) do
|
||||
{
|
||||
procedure_id: procedure.id,
|
||||
type_de_champ: {
|
||||
type_champ: type_champ,
|
||||
libelle: 'Nouveau champ',
|
||||
private: false,
|
||||
placeholder: "custom placeholder"
|
||||
libelle: 'l1.5',
|
||||
placeholder: "custom placeholder",
|
||||
after_stable_id: first_coordinate.stable_id
|
||||
}
|
||||
}
|
||||
}, format: :turbo_stream
|
||||
end
|
||||
|
||||
it { expect(response).to have_http_status(:ok) }
|
||||
subject { post :create, params: params, format: :turbo_stream }
|
||||
|
||||
context "create type_de_champ text" do
|
||||
let(:type_champ) { TypeDeChamp.type_champs.fetch(:text) }
|
||||
|
||||
# l1, l2, l3 => l1, l1.5, l2, l3
|
||||
# created: (l1.5, [l1]), morphed: (l2, [l1, l1.5]), (l3, [l1, l1.5, l2])
|
||||
it do
|
||||
is_expected.to have_http_status(:ok)
|
||||
expect(flash.alert).to eq(nil)
|
||||
expect(assigns(:coordinate)).to eq(second_coordinate)
|
||||
expect(extract_libelle(assigns(:created))).to eq(['l1.5', ['l1']])
|
||||
expect(morpheds).to eq([['l2', ['l1', 'l1.5']], ['l3', ['l1', 'l1.5', 'l2']]])
|
||||
end
|
||||
end
|
||||
|
||||
context "validate type_de_champ linked_drop_down_list" do
|
||||
let(:type_champ) { TypeDeChamp.type_champs.fetch(:linked_drop_down_list) }
|
||||
|
||||
before do
|
||||
post :create, params: {
|
||||
procedure_id: procedure.id,
|
||||
type_de_champ: {
|
||||
type_champ: type_champ,
|
||||
libelle: 'Nouveau champ',
|
||||
private: false
|
||||
}
|
||||
}, format: :turbo_stream
|
||||
it do
|
||||
is_expected.to have_http_status(:ok)
|
||||
expect(flash.alert).to eq(nil)
|
||||
end
|
||||
|
||||
it { expect(response).to have_http_status(:ok) }
|
||||
end
|
||||
|
||||
context "create type_de_champ linked_drop_down_list" do
|
||||
let(:type_champ) { TypeDeChamp.type_champs.fetch(:linked_drop_down_list) }
|
||||
let(:params) { default_params.deep_merge(type_de_champ: { drop_down_list_value: '--value--' }) }
|
||||
|
||||
before do
|
||||
post :create, params: {
|
||||
procedure_id: procedure.id,
|
||||
type_de_champ: {
|
||||
type_champ: type_champ,
|
||||
libelle: 'Nouveau champ',
|
||||
drop_down_list_value: '--value--',
|
||||
private: false
|
||||
}
|
||||
}, format: :turbo_stream
|
||||
it do
|
||||
is_expected.to have_http_status(:ok)
|
||||
expect(flash.alert).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it { expect(response).to have_http_status(:ok) }
|
||||
describe '#update' do
|
||||
let(:params) do
|
||||
{
|
||||
procedure_id: procedure.id,
|
||||
stable_id: second_coordinate.stable_id,
|
||||
type_de_champ: {
|
||||
libelle: 'updated'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
subject { post :update, params: params, format: :turbo_stream }
|
||||
|
||||
# l1, l2, l3 => l1, updated, l3
|
||||
# morphed: (updated, [l1]), (l3, [l1, updated])
|
||||
it do
|
||||
is_expected.to have_http_status(:ok)
|
||||
expect(flash.alert).to eq(nil)
|
||||
expect(second_coordinate.libelle).to eq('updated')
|
||||
|
||||
expect(assigns(:coordinate)).to eq(second_coordinate)
|
||||
expect(morpheds).to eq([['updated', ['l1']], ['l3', ['l1', 'updated']]])
|
||||
end
|
||||
end
|
||||
|
||||
# l1, l2, l3 => l1, l3, l2
|
||||
# destroyed: l3, created: (l3, [l1]), morphed: (l2, [l1, l3])
|
||||
describe '#move_up' do
|
||||
let(:params) do
|
||||
{ procedure_id: procedure.id, stable_id: third_coordinate.stable_id }
|
||||
end
|
||||
|
||||
subject { patch :move_up, params: params, format: :turbo_stream }
|
||||
|
||||
it do
|
||||
is_expected.to have_http_status(:ok)
|
||||
expect(flash.alert).to eq(nil)
|
||||
expect(second_coordinate.libelle).to eq('l3')
|
||||
expect(assigns(:coordinate)).to eq(second_coordinate)
|
||||
expect(assigns(:destroyed).libelle).to eq('l3')
|
||||
expect(extract_libelle(assigns(:created))).to eq(['l3', ['l1']])
|
||||
expect(morpheds).to eq([['l2', ['l1', 'l3']]])
|
||||
end
|
||||
end
|
||||
|
||||
# l1, l2, l3 => l2, l1, l3
|
||||
# destroyed: l1, created: (l1, [l2]), morphed: (l2, [])
|
||||
describe '#move_down' do
|
||||
let(:params) do
|
||||
{ procedure_id: procedure.id, stable_id: first_coordinate.stable_id }
|
||||
end
|
||||
|
||||
subject { patch :move_down, params: params, format: :turbo_stream }
|
||||
|
||||
it do
|
||||
is_expected.to have_http_status(:ok)
|
||||
expect(flash.alert).to eq(nil)
|
||||
|
||||
expect(assigns(:coordinate)).to eq(second_coordinate)
|
||||
expect(assigns(:destroyed).libelle).to eq('l1')
|
||||
expect(extract_libelle(assigns(:created))).to eq(['l1', ['l2']])
|
||||
expect(morpheds).to eq([['l2', []]])
|
||||
end
|
||||
end
|
||||
|
||||
# l1, l2, l3 => l1, l3
|
||||
# destroyed: l2, morphed: (l3, [l1])
|
||||
describe '#destroy' do
|
||||
let(:params) do
|
||||
{ procedure_id: procedure.id, stable_id: second_coordinate.stable_id }
|
||||
end
|
||||
|
||||
subject { delete :destroy, params: params, format: :turbo_stream }
|
||||
|
||||
it do
|
||||
used_to_be_second_coordinate = second_coordinate
|
||||
|
||||
is_expected.to have_http_status(:ok)
|
||||
expect(flash.alert).to eq(nil)
|
||||
expect(assigns(:coordinate)).to eq(used_to_be_second_coordinate)
|
||||
expect(assigns(:destroyed).libelle).to eq('l2')
|
||||
expect(morpheds).to eq([['l3', ['l1']]])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
129
spec/system/administrateurs/condition_spec.rb
Normal file
129
spec/system/administrateurs/condition_spec.rb
Normal file
|
@ -0,0 +1,129 @@
|
|||
describe 'As an administrateur I can edit types de champ condition', js: true do
|
||||
include Logic
|
||||
|
||||
let(:administrateur) { procedure.administrateurs.first }
|
||||
let(:procedure) do
|
||||
create(:procedure).tap do |p|
|
||||
p.draft_revision.add_type_de_champ(type_champ: :integer_number, libelle: 'age')
|
||||
# private
|
||||
p.draft_revision.add_type_de_champ(type_champ: :boolean, libelle: 'bon dossier', private: true)
|
||||
|
||||
p.draft_revision.add_type_de_champ(type_champ: :text, libelle: 'nom du parent')
|
||||
end
|
||||
end
|
||||
|
||||
let(:first_tdc) { procedure.draft_revision.types_de_champ.first }
|
||||
let(:second_tdc) { procedure.draft_revision.types_de_champ.second }
|
||||
|
||||
before do
|
||||
login_as administrateur.user, scope: :user
|
||||
# TODO: remove along with feature flipping
|
||||
allow(Flipper).to receive(:enabled?).with(:conditional, anything).and_return(true)
|
||||
visit champs_admin_procedure_path(procedure)
|
||||
end
|
||||
|
||||
scenario "adding a new condition" do
|
||||
within '.type-de-champ:nth-child(2)' do
|
||||
click_on 'cliquer pour activer'
|
||||
|
||||
within '.condition-table tbody tr:nth-child(1)' do
|
||||
expect(page).to have_select('type_de_champ[condition_form][rows][][targeted_champ]', options: ['Sélectionner', 'age'])
|
||||
|
||||
within('.target') { select('age') }
|
||||
within('.operator') { select('Supérieur ou égal à') }
|
||||
within('.value') { fill_in with: 18 }
|
||||
end
|
||||
end
|
||||
|
||||
expected_condition = greater_than_eq(champ_value(first_tdc.stable_id), constant(18))
|
||||
wait_until { second_tdc.reload.condition == expected_condition }
|
||||
end
|
||||
|
||||
scenario "the first type de champ is removed" do
|
||||
within '.type-de-champ:nth-child(1)' do
|
||||
click_on 'Supprimer'
|
||||
page.accept_alert
|
||||
end
|
||||
|
||||
# the condition table is deleted
|
||||
expect(page).to have_no_content('Logique conditionnelle')
|
||||
end
|
||||
|
||||
context 'with a preexisting condition' do
|
||||
before do
|
||||
second_tdc.update(condition: greater_than_eq(champ_value(first_tdc.stable_id), constant(18)))
|
||||
|
||||
page.refresh
|
||||
end
|
||||
|
||||
scenario "removing all conditions" do
|
||||
within '.type-de-champ:nth-child(2)' do
|
||||
click_on 'cliquer pour désactiver'
|
||||
page.accept_alert
|
||||
|
||||
# the condition table is deleted
|
||||
expect(page).to have_no_table
|
||||
end
|
||||
end
|
||||
|
||||
scenario "removing a condition" do
|
||||
within '.type-de-champ:nth-child(2)' do
|
||||
within '.condition-table tbody tr:nth-child(1)' do
|
||||
within('.delete-column') { click_on 'Supprimer la ligne' }
|
||||
end
|
||||
|
||||
# the condition table is deleted
|
||||
expect(page).to have_no_table
|
||||
end
|
||||
end
|
||||
|
||||
scenario "adding a second row" do
|
||||
within '.type-de-champ:nth-child(2)' do
|
||||
click_on 'Ajouter une condition'
|
||||
|
||||
# the condition table has 2 rows
|
||||
within '.condition-table tbody' do
|
||||
expect(page).to have_selector('tr', count: 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario "changing target champ to a not managed type" do
|
||||
expect(page).to have_no_selector('.condition-error')
|
||||
|
||||
within '.type-de-champ:nth-child(1)' do
|
||||
select('Départements', from: 'Type de champ')
|
||||
end
|
||||
|
||||
within '.type-de-champ:nth-child(2)' do
|
||||
expect(page).to have_selector('.condition-error')
|
||||
end
|
||||
end
|
||||
|
||||
scenario "moving a target champ below the condition" do
|
||||
expect(page).to have_no_selector('.condition-error')
|
||||
|
||||
within '.type-de-champ:nth-child(1)' do
|
||||
click_on 'Déplacer le champ vers le bas'
|
||||
end
|
||||
|
||||
# the now first champ has an error
|
||||
within '.type-de-champ:nth-child(1)' do
|
||||
expect(page).to have_selector('.condition-error')
|
||||
end
|
||||
end
|
||||
|
||||
scenario "moving the condition champ above the target" do
|
||||
expect(page).to have_no_selector('.condition-error')
|
||||
|
||||
within '.type-de-champ:nth-child(2)' do
|
||||
click_on 'Déplacer le champ vers le haut'
|
||||
end
|
||||
|
||||
# the now first champ has an error
|
||||
within '.type-de-champ:nth-child(1)' do
|
||||
expect(page).to have_selector('.condition-error')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue