Skip to content

Commit 260a632

Browse files
authored
add custom select fields (#4)
* add custom select fields * specs * erb lint * specfix * fix specs * readme
1 parent ddd42d3 commit 260a632

File tree

32 files changed

+380
-84
lines changed

32 files changed

+380
-84
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ spec/decidim_dummy_app
1616
# default development application
1717
development_app
1818
.rubocop-https*-yml
19+
.byebug_history
20+
.rbenv-vars
21+
.env

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,16 @@ Currently, the following ENV variables are supported:
9696
| EXTRA_USER_FIELDS_GENDERS | Options for the gender field (you need to add the corresponding I18n keys, ie: `decidim.extra_user_fields.genders.prefer_not_to_say` ) | `female male other prefer_not_to_say` |
9797
| EXTRA_USER_FIELDS_AGE_RANGES | Options for the age range field (you need to add the corresponding I18n keys, e.g., `decidim.extra_user_fields.age_ranges.up_to_16`) | `up_to_16 17_to_30 31_to_60 61_or_more prefer_not_to_say` |
9898

99+
## Custom fields
100+
101+
If your use case include fields not defined in this module, it is possible to define custom fields of different types:
102+
103+
1. **Select fields** This configuration option allows you to define any number of extra user fields of the type "Select".
104+
105+
106+
See the next section "Configuration through an initializer" for more information.
107+
108+
99109
### Configuration through an initializer
100110

101111
It is also possible to configure the module using the an initializer:
@@ -110,6 +120,30 @@ Decidim::ExtraUserFields.configure do |config|
110120
config.age_ranges = ["30_or_younger", "31_or_older", "prefer_not_to_say"]
111121

112122
...
123+
124+
125+
# I extra select fields are needed, they can be added here.
126+
# The key is the field name and the value is a hash with the options.
127+
# You can (optionally) add I18n keys for the options (if not the text will be used as it is).
128+
# For the user interface, you can defined labels and descriptions for the fields (optionally):
129+
# decidim.extra_user_fields.select_fields.field_name.label
130+
# decidim.extra_user_fields.select_fields.field_name.description
131+
# For the admin interface, you can defined labels and descriptions for the fields (optionally):
132+
# decidim.extra_user_fields.admin.extra_user_fields.select_fields.field_name.label
133+
# decidim.extra_user_fields.admin.extra_user_fields.select_fields.field_name.description
134+
config_accessor :select_fields do
135+
{
136+
participant_type: {
137+
# "" => "",
138+
"individual" => "decidim.extra_user_fields.participant_types.individual",
139+
"organization" => "decidim.extra_user_fields.participant_types.organization"
140+
},
141+
favorite_pet: {
142+
"cat" => "my_app.favorite_pets.cat".
143+
"dog" => "my_app.favorite_pets.dog"
144+
}
145+
}
146+
end
113147
end
114148
```
115149

app/commands/concerns/decidim/extra_user_fields/create_registrations_commands_overrides.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def extended_data
5454
phone_number: form.phone_number,
5555
location: form.location,
5656
underage: form.underage,
57+
select_fields: form.select_fields,
5758
statutory_representative_email: form.statutory_representative_email
5859
)
5960
end

app/commands/concerns/decidim/extra_user_fields/omniauth_commands_overrides.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ def extended_data
8181
phone_number: form.phone_number,
8282
location: form.location,
8383
underage: form.underage,
84+
select_fields: form.select_fields,
8485
statutory_representative_email: form.statutory_representative_email
8586
)
8687
end

app/commands/concerns/decidim/extra_user_fields/update_account_commands_overrides.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def extended_data
3030
phone_number: @form.phone_number,
3131
location: @form.location,
3232
underage: @form.underage,
33+
select_fields: @form.select_fields,
3334
statutory_representative_email: @form.statutory_representative_email
3435
)
3536
end

app/commands/decidim/extra_user_fields/admin/update_extra_user_fields.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ def extra_user_fields
5555
},
5656
"location" => { "enabled" => form.location.presence || false },
5757
"underage" => { "enabled" => form.underage || false },
58-
"underage_limit" => form.underage_limit || Decidim::ExtraUserFields.underage_limit
58+
"underage_limit" => form.underage_limit || Decidim::ExtraUserFields.underage_limit,
59+
"select_fields" => form.select_fields.to_a
5960
}
6061
end
6162
# rubocop:enable Metrics/CyclomaticComplexity

app/forms/concerns/decidim/extra_user_fields/forms_definitions.rb

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module FormsDefinitions
2222
attribute :location, String
2323
attribute :underage, ActiveRecord::Type::Boolean
2424
attribute :statutory_representative_email, String
25+
attribute :select_fields, Hash, default: {}
2526

2627
# EndBlock
2728

@@ -46,6 +47,7 @@ module FormsDefinitions
4647
"valid_email_2/email": { disposable: true },
4748
if: :underage_accepted?
4849
validate :birth_date_under_limit
50+
validate :select_fields_configured
4951

5052
# EndBlock
5153
end
@@ -61,11 +63,8 @@ def map_model(model)
6163
self.phone_number = extended_data[:phone_number]
6264
self.location = extended_data[:location]
6365
self.underage = extended_data[:underage]
66+
self.select_fields = extended_data[:select_fields] || {}
6467
self.statutory_representative_email = extended_data[:statutory_representative_email]
65-
66-
# Block ExtraUserFields MapModel
67-
68-
# EndBlock
6968
end
7069

7170
private
@@ -109,6 +108,10 @@ def underage?
109108
extra_user_fields_enabled && current_organization.activated_extra_field?(:underage)
110109
end
111110

111+
def select_fields?
112+
extra_user_fields_enabled && current_organization.activated_extra_field?(:select_fields)
113+
end
114+
112115
def underage_accepted?
113116
underage? && underage == "1"
114117
end
@@ -146,6 +149,21 @@ def underage_within_limit?(age)
146149
def underage_limit
147150
current_organization.extra_user_fields["underage_limit"]
148151
end
152+
153+
def select_fields_configured
154+
return unless select_fields?
155+
156+
select_fields.each do |field, value|
157+
next unless current_organization.extra_user_field_configuration(:select_fields).include?(field.to_s)
158+
159+
conf = Decidim::ExtraUserFields.select_fields.with_indifferent_access[field]
160+
next unless conf.is_a?(Hash)
161+
next if conf.with_indifferent_access.has_key?(value)
162+
163+
label = I18n.t("decidim.extra_user_fields.select_fields.#{field}.label", default: field.to_s.humanize)
164+
errors.add(:base, I18n.t("decidim.extra_user_fields.errors.select_fields", field: label))
165+
end
166+
end
149167
end
150168
end
151169
end

app/forms/decidim/extra_user_fields/admin/extra_user_fields_form.rb

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ class ExtraUserFieldsForm < Decidim::Form
1919

2020
attribute :phone_number_pattern, String
2121
translatable_attribute :phone_number_placeholder, String
22-
# Block ExtraUserFields Attributes
2322

24-
# EndBlock
23+
attribute :select_fields, Array, default: []
2524

2625
def map_model(model)
2726
self.enabled = model.extra_user_fields["enabled"]
@@ -36,9 +35,13 @@ def map_model(model)
3635
self.underage_limit = model.extra_user_fields.fetch("underage_limit", Decidim::ExtraUserFields.underage_limit)
3736
self.phone_number_pattern = model.extra_user_fields.dig("phone_number", "pattern")
3837
self.phone_number_placeholder = model.extra_user_fields.dig("phone_number", "placeholder")
39-
# Block ExtraUserFields MapModel
38+
self.select_fields = model.extra_user_fields["select_fields"] || []
39+
end
4040

41-
# EndBlock
41+
def select_fields
42+
super.filter do |field|
43+
Decidim::ExtraUserFields.select_fields.keys.map(&:to_s).include?(field)
44+
end
4245
end
4346
end
4447
end

app/helpers/decidim/extra_user_fields/admin/application_helper.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ def extra_user_fields_export_users_dropdown
1818
end.join.html_safe
1919
end
2020
end
21+
22+
def custom_select_fields(form)
23+
return {} unless Decidim::ExtraUserFields.select_fields.is_a?(Hash)
24+
25+
Decidim::ExtraUserFields.select_fields.keys.index_with do |field|
26+
form.object.select_fields.include?(field.to_s)
27+
end
28+
end
2129
end
2230
end
2331
end

app/helpers/decidim/extra_user_fields/application_helper.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ def phone_number_extra_user_field_pattern
2424
def phone_number_extra_user_field_placeholder
2525
current_organization.extra_user_field_configuration(:phone_number)["placeholder"]
2626
end
27+
28+
def custom_select_fields_options
29+
Decidim::ExtraUserFields.select_fields.filter_map do |field, options|
30+
next unless options.is_a?(Hash)
31+
next if options.blank?
32+
next if current_organization.extra_user_field_configuration(:select_fields).include?(field)
33+
34+
[
35+
field,
36+
options.map do |option, label|
37+
label = I18n.t(label, default: label.split(".").last.to_s.humanize) if label.present?
38+
[label, option]
39+
end
40+
]
41+
end.to_h
42+
end
2743
end
2844
end
2945
end

app/models/concerns/decidim/extra_user_fields/organization_overrides.rb

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,40 @@ module OrganizationOverrides
1010

1111
# If true display registration field in signup form
1212
def extra_user_fields_enabled?
13-
extra_user_fields["enabled"].presence && at_least_one_extra_field?
13+
extra_user_fields["enabled"].present? && at_least_one_extra_field?
1414
end
1515

1616
def at_least_one_extra_field?
17-
extra_user_fields.reject { |key| %w(enabled underage_limit).include?(key) }
18-
.map { |_, value| value["enabled"] }.any?
17+
extra_user_fields.filter_map do |field, _value|
18+
next if %w(enabled underage_limit).include?(field)
19+
20+
activated_extra_field?(field)
21+
end.any?
1922
end
2023

2124
# Check if the given value is enabled in extra_user_fields
22-
def activated_extra_field?(sym)
23-
extra_user_fields.dig(sym.to_s, "enabled") == true
25+
def activated_extra_field?(field)
26+
value = extra_user_fields[field.to_s]
27+
28+
if value.is_a?(Hash)
29+
value["enabled"]
30+
else
31+
value
32+
end.present?
2433
end
2534

2635
def age_limit?
2736
extra_user_fields["underage_limit"].to_i
2837
end
2938

30-
def extra_user_field_configuration(sym)
31-
return {} unless activated_extra_field?(sym)
39+
def extra_user_field_configuration(field)
40+
return {} unless activated_extra_field?(field)
41+
42+
value = extra_user_fields[field.to_s]
43+
44+
return value.except("enabled") if value.is_a?(Hash)
3245

33-
extra_user_fields[sym.to_s].except("enabled")
46+
value
3447
end
3548
end
3649
end

app/serializers/decidim/extra_user_fields/user_export_serializer.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def serialize
1313
def extra_user_fields
1414
extended_data = resource.extended_data.symbolize_keys
1515

16-
[:gender, :age_range, :country, :postal_code, :date_of_birth, :phone_number, :location, :underage, :statutory_representative_email].index_with do |key|
16+
extra_fields.index_with do |key|
1717
extended_data[key]
1818
end
1919
end
@@ -36,10 +36,8 @@ def extra_fields
3636
:phone_number,
3737
:location,
3838
:underage,
39+
:select_fields,
3940
:statutory_representative_email
40-
# Block ExtraUserFields AddExtraField
41-
42-
# EndBlock
4341
]
4442
end
4543
end

app/views/decidim/extra_user_fields/_profile_form.html.erb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,8 @@
3333
<%= f.hidden_field :underage, value: current_user.extended_data["underage"] || "0" %>
3434
<%= f.hidden_field :statutory_representative_email, value: current_user.extended_data["statutory_representative_email"] || "" %>
3535
<% end %>
36+
37+
<% if current_organization.activated_extra_field?(:select_fields) %>
38+
<%= render partial: "decidim/extra_user_fields/select_fields", locals: { f: f } %>
39+
<% end %>
3640
<% end %>

app/views/decidim/extra_user_fields/_registration_form.html.erb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<h2 class="h4"><%= t(".signup.legend") %></h2>
44

55
<% if current_organization.activated_extra_field?(:date_of_birth) %>
6-
<div><%= f.date_field :date_of_birth, id: "user_date_of_birth" %></div>
6+
<div><%= f.date_field :date_of_birth %></div>
77
<% end %>
88

99
<% if current_organization.activated_extra_field?(:gender) %>
@@ -49,9 +49,10 @@
4949
</div>
5050
<% end %>
5151
<% end %>
52-
<%# Block ExtraUserFields SignUpFormFields %>
5352

54-
<%# EndBlock %>
53+
<% if current_organization.activated_extra_field?(:select_fields) %>
54+
<%= render partial: "decidim/extra_user_fields/select_fields", locals: { f: f } %>
55+
<% end %>
5556

5657
</div>
5758
<%= append_javascript_pack_tag "decidim_extra_user_fields.js" %>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<% f.object.custom_select_fields_options.each do |field, options| %>
2+
<div class="fieldset">
3+
<%= label_tag f.field_id("select_fields_#{field}") do %>
4+
<%= t("decidim.extra_user_fields.select_fields.#{field}.label", default: field.to_s.humanize) %>
5+
<% if (help = t("decidim.extra_user_fields.select_fields.#{field}.description", default: "")).present? %>
6+
<span class="help-text"><%= help %></span>
7+
<% end %>
8+
9+
<%= select_tag "user[select_fields][#{field}]",
10+
options_for_select(options, f.object.select_fields[field]),
11+
id: f.field_id("select_fields_#{field}") %>
12+
<% end %>
13+
</div>
14+
<% end %>

app/views/decidim/extra_user_fields/admin/extra_user_fields/_form.html.erb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@
3333
<%= render partial: "decidim/extra_user_fields/admin/extra_user_fields/fields/phone_number", locals: { form: form } %>
3434
<%= render partial: "decidim/extra_user_fields/admin/extra_user_fields/fields/location", locals: { form: form } %>
3535
<%= render partial: "decidim/extra_user_fields/admin/extra_user_fields/fields/underage", locals: { form: form } %>
36+
37+
<div class="card-divider">
38+
<h2 class="card-title"><%= t(".extra_user_fields.section_extras") %></h2>
39+
<p class="help-text"><%= t(".extra_user_fields.section_extras_description") %></p>
40+
</div>
41+
42+
<%= render partial: "decidim/extra_user_fields/admin/extra_user_fields/fields/select_fields", locals: { form: form } %>
3643
</div>
3744
</div>
3845
</div>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<% custom_select_fields(form).each do |field, checked| %>
2+
<div class="card-section">
3+
<div class="row column">
4+
<%= label_tag "extra_user_fields_select_field_#{field}" do %>
5+
6+
<%= check_box_tag "extra_user_fields[select_fields][]",
7+
field,
8+
checked,
9+
id: "extra_user_fields_select_field_#{field}" %>
10+
<%= t("decidim.extra_user_fields.admin.extra_user_fields.select_fields.#{field}.label", default: field.to_s.humanize ) %>
11+
<span class="help-text"><%= t("decidim.extra_user_fields.admin.extra_user_fields.select_fields.#{field}.description", default: "") %></span>
12+
<% end %>
13+
</div>
14+
</div>
15+
<% end %>

bin/rails

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
11
#!/usr/bin/env ruby
22
# frozen_string_literal: true
33

4-
# This command will automatically be run when you run "rails" with Rails gems
5-
# installed from the root of your application.
4+
Dir.chdir("development_app")
65

7-
ENGINE_ROOT = File.expand_path("..", __dir__)
8-
ENGINE_PATH = File.expand_path("../lib/decidim/extra_user_fields/engine", __dir__)
9-
10-
# Set up gems listed in the Gemfile.
11-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12-
13-
require "bundler/setup"
14-
15-
require "rails/all"
16-
require "rails/engine/commands"
6+
load "bin/rails"

bin/shakapacker

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env ruby
2+
# frozen_string_literal: true
3+
4+
Dir.chdir("development_app")
5+
6+
load "bin/shakapacker"

bin/shakapacker-dev-server

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env ruby
2+
# frozen_string_literal: true
3+
4+
Dir.chdir("development_app")
5+
6+
load "bin/shakapacker-dev-server"

0 commit comments

Comments
 (0)