decidim-admin 0.18.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of decidim-admin might be problematic. Click here for more details.

Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/decidim/admin/form.js.es6 +24 -8
  3. data/app/assets/stylesheets/decidim/admin/modules/_forms.scss +8 -0
  4. data/app/assets/stylesheets/decidim/admin/modules/_modules.scss +1 -0
  5. data/app/commands/decidim/admin/create_component.rb +4 -7
  6. data/app/commands/decidim/admin/create_participatory_space_private_user.rb +4 -2
  7. data/app/commands/decidim/admin/destroy_newsletter.rb +1 -0
  8. data/app/commands/decidim/admin/process_participatory_space_private_user_import_csv.rb +41 -0
  9. data/app/commands/decidim/admin/process_user_group_verification_csv.rb +1 -0
  10. data/app/commands/decidim/admin/reject_user_group.rb +1 -0
  11. data/app/commands/decidim/admin/remove_admin.rb +1 -1
  12. data/app/commands/decidim/admin/update_component_permissions.rb +1 -1
  13. data/app/commands/decidim/admin/update_organization.rb +1 -0
  14. data/app/commands/decidim/admin/verify_user_group.rb +1 -0
  15. data/app/controllers/decidim/admin/areas_controller.rb +1 -0
  16. data/app/controllers/decidim/admin/components_controller.rb +29 -5
  17. data/app/controllers/decidim/admin/concerns/has_private_users_csv_import.rb +58 -0
  18. data/app/controllers/decidim/admin/impersonations_controller.rb +19 -2
  19. data/app/controllers/decidim/admin/resource_permissions_controller.rb +4 -1
  20. data/app/controllers/decidim/admin/scopes_controller.rb +2 -0
  21. data/app/forms/decidim/admin/component_form.rb +41 -16
  22. data/app/forms/decidim/admin/managed_user_promotion_form.rb +1 -0
  23. data/app/forms/decidim/admin/participatory_space_private_user_csv_import_form.rb +13 -0
  24. data/app/forms/decidim/admin/selective_newsletter_form.rb +1 -0
  25. data/app/helpers/decidim/admin/application_helper.rb +1 -1
  26. data/app/helpers/decidim/admin/attributes_display_helper.rb +2 -0
  27. data/app/helpers/decidim/admin/newsletters_helper.rb +6 -0
  28. data/app/helpers/decidim/admin/resource_permissions_helper.rb +1 -1
  29. data/app/helpers/decidim/admin/settings_helper.rb +52 -10
  30. data/app/jobs/decidim/admin/expire_impersonation_job.rb +1 -0
  31. data/app/jobs/decidim/admin/import_participatory_space_private_user_csv_job.rb +27 -0
  32. data/app/jobs/decidim/admin/newsletter_job.rb +1 -0
  33. data/app/jobs/decidim/admin/verify_user_group_from_csv_job.rb +1 -0
  34. data/app/permissions/decidim/admin/permissions.rb +4 -0
  35. data/app/permissions/decidim/admin/user_manager_permissions.rb +2 -0
  36. data/app/queries/decidim/admin/newsletter_recipients.rb +3 -0
  37. data/app/queries/decidim/admin/user_filter.rb +1 -0
  38. data/app/queries/decidim/admin/user_groups_evaluation.rb +1 -0
  39. data/app/views/decidim/admin/attachment_collections/index.html.erb +1 -1
  40. data/app/views/decidim/admin/attachment_collections/show.html.erb +1 -1
  41. data/app/views/decidim/admin/attachments/index.html.erb +1 -1
  42. data/app/views/decidim/admin/attachments/show.html.erb +1 -1
  43. data/app/views/decidim/admin/categories/index.html.erb +2 -2
  44. data/app/views/decidim/admin/categories/show.html.erb +1 -1
  45. data/app/views/decidim/admin/components/_form.html.erb +6 -6
  46. data/app/views/decidim/admin/components/_settings_fields.html.erb +6 -5
  47. data/app/views/decidim/admin/impersonations/_form.html.erb +1 -3
  48. data/app/views/decidim/admin/newsletters/select_recipients_to_deliver.html.erb +1 -1
  49. data/app/views/decidim/admin/organization_appearance/_form.html.erb +0 -7
  50. data/app/views/decidim/admin/participatory_space_private_users/index.html.erb +4 -3
  51. data/app/views/decidim/admin/participatory_space_private_users_csv_imports/new.html.erb +19 -0
  52. data/app/views/decidim/admin/resource_permissions/edit.html.erb +1 -1
  53. data/app/views/decidim/admin/static_pages/_topic.html.erb +1 -1
  54. data/app/views/decidim/admin/static_pages/show.html.erb +1 -1
  55. data/app/views/layouts/decidim/admin/_application.html.erb +6 -6
  56. data/app/views/layouts/decidim/admin/_header.html.erb +1 -1
  57. data/config/locales/ar.yml +7 -1
  58. data/config/locales/ca.yml +23 -11
  59. data/config/locales/cs.yml +13 -2
  60. data/config/locales/de.yml +9 -0
  61. data/config/locales/en.yml +14 -2
  62. data/config/locales/es-MX.yml +13 -2
  63. data/config/locales/es-PY.yml +13 -2
  64. data/config/locales/es.yml +13 -1
  65. data/config/locales/fi-plain.yml +13 -2
  66. data/config/locales/fi.yml +14 -2
  67. data/config/locales/fr.yml +13 -2
  68. data/config/locales/hu.yml +13 -1
  69. data/config/locales/it.yml +12 -2
  70. data/config/locales/nl.yml +13 -1
  71. data/config/locales/sv.yml +0 -1
  72. data/config/locales/tr-TR.yml +0 -2
  73. data/lib/decidim/admin/test/manage_attachments_examples.rb +1 -1
  74. data/lib/decidim/admin/version.rb +1 -1
  75. metadata +14 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e1bb0a468fe74558d68a3e069223c66f93216b5d0b6a982ca573c79b9e5133a
4
- data.tar.gz: fbfd2c9a1b874ad641144ff67560e003cfeb4dac69ab83eddb8077d73b359784
3
+ metadata.gz: 3fe9da64e350f8f333b98343743715f137e5f48ed586e9c397bad527caff7738
4
+ data.tar.gz: 22ae4dbc9bdaf872065dd3b3ca4c4458b5e0d824bb1c7f6a8dc12db7926abed7
5
5
  SHA512:
6
- metadata.gz: 0e5c425a443047671cc90f357e4b43d183ac5a4c90703c6ca842257a985531f3f49a047bfae93106d4fe9d9823ba61c5a5db2c1d6e217e9ec5d07d0601d333c6
7
- data.tar.gz: f90542e7d01193e11ff18550dc1c4c4f51a71be5bb159cdae6e74fadfdcce4e43c56b71d1923a3fa6cb82766508f7896d02b6c519dbe4c92b49772752ec80b81
6
+ metadata.gz: 9459a7af134d40568c3f9d53b4edd9f45dbbab101a9d093597ae9ab81a82288876a574d23fe0ab05986c9d7f904bad4058e957eb8e159fa34f614f13a6619db2
7
+ data.tar.gz: 5188ed41e3f8cf190a64315add75292008af12766a0a1a33307d38f3b5404c2a667b2993ef94eb8738a54e3e76d9693867aefa5b4702585d80f15731334503af
@@ -1,17 +1,33 @@
1
- // Checks if the form contains a field with a special CSS class added in
2
- // Decidim::Admin::SettingsHelper. If so, prevents the checkbox from being clicked,
3
- // extracts the stored text and adds a new paragraph after the field.
1
+ // Checks if the form contains fields with special CSS classes added in
2
+ // Decidim::Admin::SettingsHelper and acts accordingly.
4
3
  $(() => {
5
- const $checkbox = $(".participatory_texts_disabled");
4
+ // Prevents checkbox with ".participatory_texts_disabled" class from being clicked.
5
+ const $participatoryTexts = $(".participatory_texts_disabled");
6
6
 
7
- $checkbox.click((event) => {
7
+ $participatoryTexts.click((event) => {
8
8
  event.preventDefault();
9
9
  return false;
10
10
  });
11
11
 
12
- if ($checkbox.length > 0) {
13
- const $text = $checkbox[0].dataset.text
12
+ // Target fields:
13
+ // - amendments_wizard_help_text
14
+ // - all fields with ".amendments_step_settings" class
15
+ // (1) Hides target fields if amendments_enabled component setting is NOT checked.
16
+ // (2) Toggles visibilty of target fields when amendments_enabled component setting is clicked.
17
+ const $amendmentsEnabled = $("input#component_settings_amendments_enabled");
14
18
 
15
- $checkbox.parent().after(`<p class="help-text">${$text}</p>`)
19
+ if ($amendmentsEnabled.length > 0) {
20
+ const $amendmentWizardHelpText = $("[id*='amendments_wizard_help_text']").parent();
21
+ const $amendmentStepSettings = $(".amendments_step_settings").parent();
22
+
23
+ if ($amendmentsEnabled.is(":not(:checked)")) {
24
+ $amendmentWizardHelpText.hide();
25
+ $amendmentStepSettings.hide().siblings(".help-text").hide();
26
+ }
27
+
28
+ $amendmentsEnabled.click(() => {
29
+ $amendmentWizardHelpText.toggle();
30
+ $amendmentStepSettings.toggle().siblings(".help-text").toggle();
31
+ });
16
32
  }
17
33
  });
@@ -134,3 +134,11 @@ textarea{
134
134
  cursor: not-allowed;
135
135
  opacity: .5;
136
136
  }
137
+
138
+ .edit_component .step-settings{
139
+ .card-section fieldset legend{
140
+ font-size: 24px;
141
+ font-weight: bold;
142
+ border-bottom: 1px solid grey;
143
+ }
144
+ }
@@ -34,3 +34,4 @@
34
34
  @import "decidim/modules/input-tags";
35
35
  @import "decidim/modules/input-mentions";
36
36
  @import "decidim/modules/input-hashtags";
37
+ @import "decidim/modules/input-gallery";
@@ -8,13 +8,10 @@ module Decidim
8
8
 
9
9
  # Public: Initializes the command.
10
10
  #
11
- # manifest - The component's manifest to create a component from.
12
- # form - The form from which the data in this component comes from.
13
- # participatory_space - The participatory space that will hold this component.
14
- def initialize(manifest, form, participatory_space)
15
- @manifest = manifest
11
+ # form - The form from which the data in this component comes from.
12
+ def initialize(form)
16
13
  @form = form
17
- @participatory_space = participatory_space
14
+ @manifest = form.manifest
18
15
  end
19
16
 
20
17
  # Public: Creates the Component.
@@ -39,7 +36,7 @@ module Decidim
39
36
  form.current_user,
40
37
  manifest_name: manifest.name,
41
38
  name: form.name,
42
- participatory_space: participatory_space,
39
+ participatory_space: form.participatory_space,
43
40
  weight: form.weight,
44
41
  settings: form.settings,
45
42
  default_step_settings: form.default_step_settings,
@@ -10,10 +10,11 @@ module Decidim
10
10
  # form - A form object with the params.
11
11
  # private_user_to - The private_user_to that will hold the
12
12
  # user role
13
- def initialize(form, current_user, private_user_to)
13
+ def initialize(form, current_user, private_user_to, via_csv = false)
14
14
  @form = form
15
15
  @current_user = current_user
16
16
  @private_user_to = private_user_to
17
+ @via_csv = via_csv
17
18
  end
18
19
 
19
20
  # Executes the command. Broadcasts these events:
@@ -41,8 +42,9 @@ module Decidim
41
42
  attr_reader :form, :private_user_to, :current_user, :user
42
43
 
43
44
  def create_private_user
45
+ action = @via_csv ? "create_via_csv" : "create"
44
46
  Decidim.traceability.perform_action!(
45
- :create,
47
+ action,
46
48
  Decidim::ParticipatorySpacePrivateUser,
47
49
  current_user,
48
50
  resource: {
@@ -17,6 +17,7 @@ module Decidim
17
17
  # Broadcasts :ok if it got destroyed
18
18
  def call
19
19
  return broadcast(:already_sent) if newsletter.sent?
20
+
20
21
  destroy_newsletter
21
22
  broadcast(:ok)
22
23
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ module Decidim
6
+ module Admin
7
+ class ProcessParticipatorySpacePrivateUserImportCsv < Rectify::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # form - the form object containing the uploaded file
11
+ # current_user - the user performing the action
12
+ # private_users_to - The private_users_to that will hold the user role
13
+ def initialize(form, current_user, private_users_to)
14
+ @form = form
15
+ @current_user = current_user
16
+ @private_users_to = private_users_to
17
+ end
18
+
19
+ # Executes the command. Broadcasts these events:
20
+ #
21
+ # - :ok when everything is valid.
22
+ # - :invalid if the form wasn't valid and we couldn't proceed.
23
+ #
24
+ # Returns nothing.
25
+ def call
26
+ return broadcast(:invalid) unless @form.valid?
27
+
28
+ process_csv
29
+ broadcast(:ok)
30
+ end
31
+
32
+ private
33
+
34
+ def process_csv
35
+ CSV.foreach(@form.file.path) do |email, user_name|
36
+ ImportParticipatorySpacePrivateUserCsvJob.perform_later(email, user_name, @private_users_to, @current_user) if email.present? && user_name.present?
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -22,6 +22,7 @@ module Decidim
22
22
  # Returns nothing.
23
23
  def call
24
24
  return broadcast(:invalid) unless @form.valid?
25
+
25
26
  process_csv
26
27
  broadcast(:ok)
27
28
  end
@@ -21,6 +21,7 @@ module Decidim
21
21
  # Returns nothing.
22
22
  def call
23
23
  return broadcast(:invalid) unless @user_group.valid?
24
+
24
25
  reject_user_group
25
26
  broadcast(:ok)
26
27
  end
@@ -35,7 +35,7 @@ module Decidim
35
35
  attr_reader :user, :current_user
36
36
 
37
37
  def user_role
38
- user.admin? ? :admin : user.roles
38
+ user.admin? ? :admin : user.roles.last
39
39
  end
40
40
  end
41
41
  end
@@ -75,7 +75,7 @@ module Decidim
75
75
  return permissions unless component.permissions
76
76
 
77
77
  permissions.deep_stringify_keys.reject do |action, config|
78
- HashDiff.diff(config, component.permissions[action]).empty?
78
+ Hashdiff.diff(config, component.permissions[action]).empty?
79
79
  end
80
80
  end
81
81
 
@@ -24,6 +24,7 @@ module Decidim
24
24
  return broadcast(:invalid) if form.invalid?
25
25
 
26
26
  return broadcast(:ok, @organization) if update_organization
27
+
27
28
  broadcast(:invalid)
28
29
  end
29
30
 
@@ -21,6 +21,7 @@ module Decidim
21
21
  # Returns nothing.
22
22
  def call
23
23
  return broadcast(:invalid) unless @user_group.valid?
24
+
24
25
  verify_user_group
25
26
  broadcast(:ok)
26
27
  end
@@ -79,6 +79,7 @@ module Decidim
79
79
 
80
80
  def area
81
81
  return @area if defined?(@area)
82
+
82
83
  @area = organization_areas.find_by(id: params[:id])
83
84
  end
84
85
  end
@@ -27,10 +27,10 @@ module Decidim
27
27
  end
28
28
 
29
29
  def create
30
- @form = form(ComponentForm).from_params(params)
30
+ @form = form(ComponentForm).from_params(form_params)
31
31
  enforce_permission_to :create, :component
32
32
 
33
- CreateComponent.call(manifest, @form, current_participatory_space) do
33
+ CreateComponent.call(@form) do
34
34
  on(:ok) do
35
35
  flash[:notice] = I18n.t("components.create.success", scope: "decidim.admin")
36
36
  redirect_to action: :index
@@ -52,7 +52,7 @@ module Decidim
52
52
 
53
53
  def update
54
54
  @component = query_scope.find(params[:id])
55
- @form = form(ComponentForm).from_params(params)
55
+ @form = form(ComponentForm).from_params(form_params)
56
56
  enforce_permission_to :update, :component, component: @component
57
57
 
58
58
  UpdateComponent.call(@form, @component) do
@@ -65,7 +65,7 @@ module Decidim
65
65
 
66
66
  on(:invalid) do
67
67
  flash[:alert] = I18n.t("components.update.error", scope: "decidim.admin")
68
- redirect_to action: :edit
68
+ render action: :edit
69
69
  end
70
70
  end
71
71
  end
@@ -113,12 +113,36 @@ module Decidim
113
113
 
114
114
  private
115
115
 
116
+ # Returns a Class with the attributes sanitized, coerced and filtered
117
+ # to the right type. See Decidim::SettingsManifest#schema.
118
+ def new_settings_schema(name, data)
119
+ manifest.settings(name).schema.new(data, current_organization.default_locale)
120
+ end
121
+
122
+ # Processes the component params so Decidim::Admin::ComponentForm
123
+ # can assign and validate the attributes when using #from_params.
124
+ def form_params
125
+ form_params = params[:component].permit!
126
+ form_params[:id] = params[:id]
127
+ form_params[:manifest] = manifest
128
+ form_params[:participatory_space] = current_participatory_space
129
+ form_params[:settings] = new_settings_schema(:global, form_params[:settings])
130
+ if form_params[:default_step_settings]
131
+ form_params[:default_step_settings] = new_settings_schema(:step, form_params[:default_step_settings])
132
+ else
133
+ form_params[:step_settings].each do |key, value|
134
+ form_params[:step_settings][key] = new_settings_schema(:step, value)
135
+ end
136
+ end
137
+ form_params
138
+ end
139
+
116
140
  def query_scope
117
141
  current_participatory_space.components
118
142
  end
119
143
 
120
144
  def manifest
121
- Decidim.find_component_manifest(params[:type])
145
+ @component&.manifest || Decidim.find_component_manifest(params[:type])
122
146
  end
123
147
 
124
148
  def default_name(manifest)
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ module Concerns
6
+ # PrivateUsers can be related to any ParticipatorySpace, in order to
7
+ # import private users from csv for a given type, you should create a new
8
+ # controller and include this concern.
9
+ #
10
+ # The only requirement is to define a `privatable_to` method that
11
+ # returns an instance of the model to relate the private_user to.
12
+ module HasPrivateUsersCsvImport
13
+ extend ActiveSupport::Concern
14
+
15
+ included do
16
+ helper_method :privatable_to
17
+
18
+ def new
19
+ enforce_permission_to :csv_import, :space_private_user
20
+ @form = form(ParticipatorySpacePrivateUserCsvImportForm).from_params({}, privatable_to: privatable_to)
21
+ render template: "decidim/admin/participatory_space_private_users_csv_imports/new"
22
+ end
23
+
24
+ def create
25
+ enforce_permission_to :csv_import, :space_private_user
26
+ @form = form(ParticipatorySpacePrivateUserCsvImportForm).from_params(params, privatable_to: privatable_to)
27
+
28
+ ProcessParticipatorySpacePrivateUserImportCsv.call(@form, current_user, current_participatory_space) do
29
+ on(:ok) do
30
+ flash[:notice] = I18n.t("participatory_space_private_users_csv_imports.create.success", scope: "decidim.admin")
31
+ redirect_to after_import_path
32
+ end
33
+
34
+ on(:invalid) do
35
+ flash[:alert] = I18n.t("participatory_space_private_users_csv_imports.create.invalid", scope: "decidim.admin")
36
+ render template: "decidim/admin/participatory_space_private_users_csv_imports/new"
37
+ end
38
+ end
39
+ end
40
+
41
+ # Public: Returns a String or Object that will be passed to `redirect_to` after
42
+ # importing private users. By default it redirects to the privatable_to.
43
+ #
44
+ # It can be redefined at controller level if you need to redirect elsewhere.
45
+ def after_import_path
46
+ privatable_to
47
+ end
48
+
49
+ # Public: The only method to be implemented at the controller. You need to
50
+ # return the object where the attachment will be attached to.
51
+ def privatable_to
52
+ raise NotImplementedError
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -68,14 +68,31 @@ module Decidim
68
68
 
69
69
  def user
70
70
  @user ||= if creating_managed_user?
71
- new_managed_user
71
+ existing_managed_user || new_managed_user
72
72
  else
73
73
  current_organization.users.find(params[:impersonatable_user_id])
74
74
  end
75
75
  end
76
76
 
77
+ def existing_managed_user
78
+ handler = Decidim::AuthorizationHandler.handler_for(
79
+ handler_name,
80
+ params.dig(:impersonate_user, :authorization)
81
+ )
82
+ return nil unless handler.unique_id
83
+
84
+ existing_authorization = Authorization.find_by(
85
+ name: handler_name,
86
+ unique_id: handler.unique_id
87
+ )
88
+ return nil unless existing_authorization
89
+ return nil unless existing_authorization.user.managed?
90
+
91
+ existing_authorization.user
92
+ end
93
+
77
94
  def new_managed_user
78
- Decidim::User.find_or_initialize_by(
95
+ Decidim::User.new(
79
96
  organization: current_organization,
80
97
  managed: true,
81
98
  name: params.dig(:impersonate_user, :name)
@@ -75,7 +75,10 @@ module Decidim
75
75
  return if params[:resource_name].blank?
76
76
 
77
77
  resource_id = params["#{params[:resource_name]}_id"]
78
- @resource ||= Decidim.find_resource_manifest(params[:resource_name])&.model_class&.find_by(id: resource_id)
78
+ resource_slug = params["#{params[:resource_name]}_slug"]
79
+
80
+ find_by = resource_slug.present? ? { slug: resource_slug } : { id: resource_id }
81
+ @resource ||= Decidim.find_resource_manifest(params[:resource_name])&.model_class&.find_by(find_by)
79
82
  @resource if @resource&.allow_resource_permissions?
80
83
  end
81
84
 
@@ -75,11 +75,13 @@ module Decidim
75
75
 
76
76
  def parent_scope
77
77
  return @parent_scope if defined?(@parent_scope)
78
+
78
79
  @parent_scope = scope ? scope.parent : organization_scopes.find_by(id: params[:scope_id])
79
80
  end
80
81
 
81
82
  def scope
82
83
  return @scope if defined?(@scope)
84
+
83
85
  @scope = organization_scopes.find_by(id: params[:id])
84
86
  end
85
87
 
@@ -13,15 +13,18 @@ module Decidim
13
13
  translatable_attribute :name, String
14
14
  validates :name, translatable_presence: true
15
15
 
16
- attribute :settings, Object
17
- attribute :default_step_settings, Object
18
- attribute :manifest
19
16
  attribute :weight, Integer, default: 0
20
17
 
18
+ attribute :manifest, Object
19
+ attribute :participatory_space, Object
20
+ validates :manifest, :participatory_space, presence: true
21
+
22
+ attribute :settings, Object
23
+ attribute :default_step_settings, Object
21
24
  attribute :step_settings, Hash[String => Object]
22
- attribute :participatory_space
23
25
 
24
- validate :must_be_able_to_change_participatory_texts_setting, if: :proposal_component?
26
+ validate :must_be_able_to_change_participatory_texts_setting
27
+ validate :amendments_visibility_options_must_be_valid
25
28
 
26
29
  def settings?
27
30
  settings.manifest.attributes.any?
@@ -31,23 +34,45 @@ module Decidim
31
34
  default_step_settings.manifest.attributes.any?
32
35
  end
33
36
 
34
- def component
35
- @component ||= Component.find_by(id: id)
37
+ private
38
+
39
+ # Overwrites Rectify::Form#form_attributes_valid? to validate nested `step_settings` attributes.
40
+ def form_attributes_valid?
41
+ return false unless errors.empty? && settings_errors_empty? # Preserves errors from custom validation methods
42
+
43
+ attributes_that_respond_to(:valid?).concat(
44
+ step_settings.each_value.select { |attribute| attribute.respond_to?(:valid?) }
45
+ ).all?(&:valid?)
36
46
  end
37
47
 
38
- def proposal_component?
39
- component&.manifest_name == "proposals"
48
+ def settings_errors_empty?
49
+ validations = [settings.errors.empty?]
50
+ validations << if default_step_settings.present?
51
+ default_step_settings.errors.empty?
52
+ else
53
+ step_settings.each_value.map(&:errors).all?(&:empty?)
54
+ end
55
+ validations.all?
40
56
  end
41
57
 
42
- # Validation for `Proposals` components. Prevents changing the global
43
- # setting `participatory_texts_enabled` when there are proposals.
44
- # Does not add a custom error message as it would be unused, because
45
- # the setting's checkbox is automatically being disabled on the frontend.
58
+ # Validates setting `participatory_texts_enabled` is not changed when there are proposals for the component.
46
59
  def must_be_able_to_change_participatory_texts_setting
47
- form_setting_value = settings[:participatory_texts_enabled].to_i == 1 # Convert "1"/"0" to true/false
48
- return if form_setting_value == component.settings.participatory_texts_enabled
60
+ return unless manifest&.name == :proposals && (component = Component.find_by(id: id))
61
+ return unless settings.participatory_texts_enabled != component.settings.participatory_texts_enabled
62
+
63
+ settings.errors.add(:participatory_texts_enabled) if Decidim::Proposals::Proposal.where(component: component).any?
64
+ end
65
+
66
+ # Validates setting `amendments_visibility` is included in Decidim::Amendment::VisibilityStepSetting.options.
67
+ def amendments_visibility_options_must_be_valid
68
+ return unless manifest&.name == :proposals && settings.amendments_enabled
69
+
70
+ visibility_options = Decidim::Amendment::VisibilityStepSetting.options.map(&:last)
71
+ step_settings.each do |step, settings|
72
+ next unless visibility_options.exclude? settings[:amendments_visibility]
49
73
 
50
- errors.add(:settings) if Decidim::Proposals::Proposal.where(component: component).any?
74
+ step_settings[step].errors.add(:amendments_visibility, :inclusion)
75
+ end
51
76
  end
52
77
  end
53
78
  end