+
+
+
{{ t('condition') }} {{ cindex + 1 }}
diff --git a/app/javascript/template_builder/i18n.js b/app/javascript/template_builder/i18n.js
index 7070c9e5..e20c20fb 100644
--- a/app/javascript/template_builder/i18n.js
+++ b/app/javascript/template_builder/i18n.js
@@ -148,7 +148,9 @@ const en = {
preferences: 'Preferences',
available_in_pro: 'Available in Pro',
some_fields_are_missing_in_the_formula: 'Some fields are missing in the formula.',
- learn_more: 'Learn more'
+ learn_more: 'Learn more',
+ and: 'and',
+ or: 'or'
}
const es = {
@@ -301,7 +303,9 @@ const es = {
preferences: 'Preferencias',
available_in_pro: 'Disponible en Pro',
some_fields_are_missing_in_the_formula: 'Faltan algunos campos en la fórmula.',
- learn_more: 'Aprende más'
+ learn_more: 'Aprende más',
+ and: 'y',
+ or: 'o'
}
const it = {
@@ -454,7 +458,9 @@ const it = {
preferences: 'Preferenze',
available_in_pro: 'Disponibile in Pro',
some_fields_are_missing_in_the_formula: 'Alcuni campi mancano nella formula.',
- learn_more: 'Scopri di più'
+ learn_more: 'Scopri di più',
+ and: 'e',
+ or: 'o'
}
const pt = {
@@ -607,7 +613,9 @@ const pt = {
preferences: 'Preferências',
available_in_pro: 'Disponível no Pro',
some_fields_are_missing_in_the_formula: 'Faltam alguns campos na fórmula.',
- learn_more: 'Saiba mais'
+ learn_more: 'Saiba mais',
+ and: 'e',
+ or: 'ou'
}
const fr = {
@@ -760,7 +768,9 @@ const fr = {
preferences: 'Préférences',
available_in_pro: 'Disponible en version Pro',
some_fields_are_missing_in_the_formula: 'Certains champs manquent dans la formule.',
- learn_more: 'En savoir plus'
+ learn_more: 'En savoir plus',
+ and: 'et',
+ or: 'ou'
}
const de = {
@@ -913,7 +923,9 @@ const de = {
preferences: 'Einstellungen',
available_in_pro: 'In Pro verfügbar',
some_fields_are_missing_in_the_formula: 'Einige Felder fehlen in der Formel.',
- learn_more: 'Erfahren Sie mehr'
+ learn_more: 'Erfahren Sie mehr',
+ and: 'und',
+ or: 'oder'
}
export { en, es, it, pt, fr, de }
diff --git a/lib/submitters/submit_values.rb b/lib/submitters/submit_values.rb
index 65ecad75..a956b425 100644
--- a/lib/submitters/submit_values.rb
+++ b/lib/submitters/submit_values.rb
@@ -175,38 +175,46 @@ module Submitters
submitter.submission.template_fields.each do |field|
next if field['submitter_uuid'] != submitter.uuid
- submitter.values.delete(field['uuid']) unless check_field_condition(submitter, field, fields_uuid_index)
+ submitter.values.delete(field['uuid']) unless check_field_conditions(submitter, field, fields_uuid_index)
end
submitter.values
end
- def check_field_condition(submitter, field, fields_uuid_index)
+ def check_field_conditions(submitter, field, fields_uuid_index)
return true if field['conditions'].blank?
submitter_values = submitter.values
- field['conditions'].reduce(true) do |acc, c|
- case c['action']
- when 'empty', 'unchecked'
- acc && submitter_values[c['field_uuid']].blank?
- when 'not_empty', 'checked'
- acc && submitter_values[c['field_uuid']].present?
- when 'equal', 'contains'
- field = fields_uuid_index[c['field_uuid']]
- option = field['options'].find { |o| o['uuid'] == c['value'] }
- values = Array.wrap(submitter_values[c['field_uuid']])
-
- acc && values.include?(option['value'].presence || "Option #{field['options'].index(option)}")
- when 'not_equal', 'does_not_contain'
- field = fields_uuid_index[c['field_uuid']]
- option = field['options'].find { |o| o['uuid'] == c['value'] }
- values = Array.wrap(submitter_values[c['field_uuid']])
-
- acc && values.exclude?(option['value'].presence || "Option #{field['options'].index(option)}")
+ field['conditions'].each_with_object([]) do |c, acc|
+ if c['operation'] == 'or'
+ acc.push(acc.pop || check_field_condition(c, submitter_values, fields_uuid_index))
else
- acc
+ acc.push(check_field_condition(c, submitter_values, fields_uuid_index))
end
+ end.exclude?(false)
+ end
+
+ def check_field_condition(condition, submitter_values, fields_uuid_index)
+ case condition['action']
+ when 'empty', 'unchecked'
+ submitter_values[condition['field_uuid']].blank?
+ when 'not_empty', 'checked'
+ submitter_values[condition['field_uuid']].present?
+ when 'equal', 'contains'
+ field = fields_uuid_index[condition['field_uuid']]
+ option = field['options'].find { |o| o['uuid'] == condition['value'] }
+ values = Array.wrap(submitter_values[condition['field_uuid']])
+
+ values.include?(option['value'].presence || "#{I18n.t('option')} #{field['options'].index(option)}")
+ when 'not_equal', 'does_not_contain'
+ field = fields_uuid_index[condition['field_uuid']]
+ option = field['options'].find { |o| o['uuid'] == condition['value'] }
+ values = Array.wrap(submitter_values[condition['field_uuid']])
+
+ values.exclude?(option['value'].presence || "#{I18n.t('option')} #{field['options'].index(option)}")
+ else
+ true
end
end
diff --git a/spec/system/signing_form_spec.rb b/spec/system/signing_form_spec.rb
index 349e029b..c6e512fe 100644
--- a/spec/system/signing_form_spec.rb
+++ b/spec/system/signing_form_spec.rb
@@ -579,6 +579,199 @@ RSpec.describe 'Signing Form', type: :system do
end
end
+ context 'when the field with conditions' do
+ let(:template) { create(:template, account:, author:, only_field_types: ['text']) }
+ let(:submission) { create(:submission, :with_submitters, template:) }
+ let(:template_attachment) { template.schema.first }
+ let(:template_submitter) { submission.template_submitters.first }
+ let(:submitter) { submission.submitters.first }
+ let(:fields) do
+ [
+ {
+ 'uuid' => 'da7e0d56-fdb0-441a-bbed-d0f6f2e10fd6',
+ 'submitter_uuid' => submitter.uuid,
+ 'name' => 'Full Name',
+ 'type' => 'text',
+ 'required' => false,
+ 'preferences' => {},
+ 'conditions' => [],
+ 'areas' => [
+ {
+ 'x' => 0.1117351575121163,
+ 'y' => 0.08950650415231329,
+ 'w' => 0.2,
+ 'h' => 0.02857142857142857,
+ 'attachment_uuid' => template_attachment['attachment_uuid'],
+ 'page' => 0
+ }
+ ]
+ },
+ {
+ 'uuid' => 'd32ad52a-8f6b-4e32-b0d6-6258fb47440b',
+ 'submitter_uuid' => submitter.uuid,
+ 'name' => 'Email',
+ 'type' => 'text',
+ 'required' => false,
+ 'preferences' => {},
+ 'conditions' => [],
+ 'validation' => { 'pattern' => '^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$' },
+ 'areas' => [
+ {
+ 'x' => 0.1097914983844911,
+ 'y' => 0.1417641720258019,
+ 'w' => 0.2,
+ 'h' => 0.02857142857142857,
+ 'attachment_uuid' => template_attachment['attachment_uuid'],
+ 'page' => 0
+ }
+ ]
+ },
+ {
+ 'uuid' => 'c6e013ae-f9f6-4b3a-ad33-b7e772a0a49f',
+ 'submitter_uuid' => submitter.uuid,
+ 'name' => 'Phone',
+ 'type' => 'text',
+ 'required' => false,
+ 'preferences' => {},
+ 'areas' => [
+ {
+ 'x' => 0.1100060581583199,
+ 'y' => 0.2553160344676159,
+ 'w' => 0.2,
+ 'h' => 0.02857142857142857,
+ 'attachment_uuid' => template_attachment['attachment_uuid'],
+ 'page' => 0
+ }
+ ]
+ },
+ {
+ 'uuid' => '64523936-22fd-41f8-b997-ede8fbe467cc',
+ 'submitter_uuid' => submitter.uuid,
+ 'name' => 'Comment',
+ 'type' => 'text',
+ 'required' => false,
+ 'preferences' => {},
+ 'conditions' => [
+ { 'field_uuid' => 'da7e0d56-fdb0-441a-bbed-d0f6f2e10fd6', 'action' => 'not_empty' },
+ { 'field_uuid' => 'd32ad52a-8f6b-4e32-b0d6-6258fb47440b', 'action' => 'not_empty' },
+ { 'field_uuid' => 'c6e013ae-f9f6-4b3a-ad33-b7e772a0a49f', 'action' => 'not_empty', 'operation' => 'or' }
+ ],
+ 'areas' => [
+ {
+ 'x' => 0.1145875403877221,
+ 'y' => 0.1982961365432846,
+ 'w' => 0.2,
+ 'h' => 0.02857142857142857,
+ 'attachment_uuid' => template_attachment['attachment_uuid'],
+ 'page' => 0
+ }
+ ]
+ }
+ ]
+ end
+
+ before do
+ template.update(fields:)
+ submission.update(template_fields: fields)
+ end
+
+ it 'completes the form and saves the conditional field when all required fields are filled' do
+ visit submit_form_path(slug: submitter.slug)
+ fill_in 'Full Name (optional)', with: 'John Doe'
+ click_button 'next'
+
+ fill_in 'Email (optional)', with: 'john.due@example.com'
+ click_button 'next'
+
+ fill_in 'Phone (optional)', with: '+1 (773) 229-8825'
+ click_button 'next'
+
+ fill_in 'Comment', with: 'This is a comment'
+ click_button 'Complete'
+
+ expect(page).to have_content('Form has been completed!')
+
+ submitter.reload
+
+ expect(submitter.completed_at).to be_present
+ expect(field_value(submitter, 'Full Name')).to eq 'John Doe'
+ expect(field_value(submitter, 'Email')).to eq 'john.due@example.com'
+ expect(field_value(submitter, 'Phone')).to eq '+1 (773) 229-8825'
+ expect(field_value(submitter, 'Comment')).to eq 'This is a comment'
+ end
+
+ it 'completes the form and saves the conditional field when minimum required fields are filled' do
+ visit submit_form_path(slug: submitter.slug)
+ fill_in 'Full Name (optional)', with: 'John Doe'
+ click_button 'next'
+
+ fill_in 'Email (optional)', with: 'john.due@example.com'
+ click_button 'next'
+
+ fill_in 'Phone (optional)', with: ''
+ click_button 'next'
+
+ fill_in 'Comment', with: 'This is a comment'
+ click_button 'Complete'
+
+ expect(page).to have_content('Form has been completed!')
+
+ submitter.reload
+
+ expect(submitter.completed_at).to be_present
+ expect(field_value(submitter, 'Full Name')).to eq 'John Doe'
+ expect(field_value(submitter, 'Email')).to eq 'john.due@example.com'
+ expect(field_value(submitter, 'Phone')).to be_empty
+ expect(field_value(submitter, 'Comment')).to eq 'This is a comment'
+ end
+
+ it 'completes the form without saving the conditional field when not enough fields are filled' do
+ visit submit_form_path(slug: submitter.slug)
+
+ fill_in 'Full Name (optional)', with: 'Jane Doe'
+ click_button 'next'
+
+ fill_in 'Email (optional)', with: ''
+ click_button 'next'
+
+ fill_in 'Phone (optional)', with: ''
+ click_button 'Complete'
+
+ expect(page).to have_content('Form has been completed!')
+
+ submitter.reload
+
+ expect(submitter.completed_at).to be_present
+ expect(field_value(submitter, 'Full Name')).to eq 'Jane Doe'
+ expect(field_value(submitter, 'Email')).to be_empty
+ expect(field_value(submitter, 'Phone')).to be_empty
+ expect(field_value(submitter, 'Comment')).to be_nil
+ end
+
+ it 'completes the form without saving the conditional field when only partial fields are filled' do
+ visit submit_form_path(slug: submitter.slug)
+
+ fill_in 'Full Name (optional)', with: ''
+ click_button 'next'
+
+ fill_in 'Email (optional)', with: 'john.due@example.com'
+ click_button 'next'
+
+ fill_in 'Phone (optional)', with: '+1 (773) 229-8825'
+ click_button 'Complete'
+
+ expect(page).to have_content('Form has been completed!')
+
+ submitter.reload
+
+ expect(submitter.completed_at).to be_present
+ expect(field_value(submitter, 'Full Name')).to be_empty
+ expect(field_value(submitter, 'Email')).to eq 'john.due@example.com'
+ expect(field_value(submitter, 'Phone')).to eq '+1 (773) 229-8825'
+ expect(field_value(submitter, 'Comment')).to be_nil
+ end
+ end
+
it 'sends completed email' do
template = create(:template, account:, author:, only_field_types: %w[text signature])
submission = create(:submission, template:)