decidim-initiatives 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +22 -0
  3. data/app/assets/images/decidim/gamification/badges/initiatives.svg +1 -87
  4. data/app/assets/images/decidim/initiatives/icon.svg +1 -3
  5. data/app/assets/stylesheet/decidim/initiatives/initiatives-votes.css.scss +0 -1
  6. data/app/assets/stylesheet/decidim/initiatives/initiatives.scss +0 -8
  7. data/app/assets/stylesheet/decidim/initiatives/popularity_item.css.scss +0 -1
  8. data/app/assets/stylesheet/decidim/initiatives/print-initiative.css.scss +0 -3
  9. data/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives/show.erb +4 -3
  10. data/app/cells/decidim/initiatives/initiative_m_cell.rb +11 -0
  11. data/app/commands/decidim/initiatives/admin/create_initiative_type.rb +3 -0
  12. data/app/commands/decidim/initiatives/admin/send_initiative_to_technical_validation.rb +17 -0
  13. data/app/commands/decidim/initiatives/admin/update_initiative.rb +29 -10
  14. data/app/commands/decidim/initiatives/admin/update_initiative_type.rb +3 -0
  15. data/app/commands/decidim/initiatives/attachment_methods.rb +33 -0
  16. data/app/commands/decidim/initiatives/create_initiative.rb +23 -1
  17. data/app/commands/decidim/initiatives/vote_initiative.rb +16 -0
  18. data/app/controllers/concerns/decidim/initiatives/admin/filterable.rb +18 -4
  19. data/app/controllers/concerns/decidim/initiatives/orderable.rb +3 -1
  20. data/app/controllers/concerns/decidim/initiatives/single_initiative_type.rb +26 -0
  21. data/app/controllers/decidim/initiatives/admin/initiatives_controller.rb +20 -1
  22. data/app/controllers/decidim/initiatives/create_initiative_controller.rb +35 -5
  23. data/app/controllers/decidim/initiatives/initiatives_controller.rb +17 -3
  24. data/app/controllers/decidim/initiatives/versions_controller.rb +20 -0
  25. data/app/events/decidim/initiatives/admin/initiative_sent_to_technical_validation_event.rb +21 -0
  26. data/app/events/decidim/initiatives/admin/support_threshold_reached_event.rb +13 -0
  27. data/app/forms/decidim/initiatives/admin/initiative_form.rb +31 -0
  28. data/app/forms/decidim/initiatives/admin/initiative_type_form.rb +5 -1
  29. data/app/forms/decidim/initiatives/initiative_form.rb +34 -0
  30. data/app/forms/decidim/initiatives/vote_form.rb +3 -1
  31. data/app/helpers/decidim/initiatives/application_helper.rb +104 -0
  32. data/app/helpers/decidim/initiatives/initiative_helper.rb +13 -0
  33. data/app/helpers/decidim/initiatives/initiatives_helper.rb +10 -0
  34. data/app/jobs/decidim/initiatives/export_initiatives_job.rb +25 -0
  35. data/app/mailers/decidim/initiatives/initiatives_mailer.rb +0 -21
  36. data/app/models/concerns/decidim/initiatives/has_area.rb +30 -0
  37. data/app/models/decidim/initiative.rb +62 -10
  38. data/app/permissions/decidim/initiatives/admin/permissions.rb +7 -0
  39. data/app/permissions/decidim/initiatives/permissions.rb +35 -10
  40. data/app/serializers/decidim/initiatives/initiative_serializer.rb +32 -0
  41. data/app/services/decidim/initiatives/diff_renderer.rb +18 -0
  42. data/app/services/decidim/initiatives/initiative_search.rb +59 -15
  43. data/app/services/decidim/initiatives/status_change_notifier.rb +4 -5
  44. data/app/views/decidim/initiatives/admin/exports/_dropdown.html.erb +8 -0
  45. data/app/views/decidim/initiatives/admin/initiatives/_form.html.erb +24 -1
  46. data/app/views/decidim/initiatives/admin/initiatives/_initiative_attachments.erb +43 -0
  47. data/app/views/decidim/initiatives/admin/initiatives/index.html.erb +8 -3
  48. data/app/views/decidim/initiatives/admin/initiatives_types/_form.html.erb +12 -0
  49. data/app/views/decidim/initiatives/create_initiative/fill_data.html.erb +44 -10
  50. data/app/views/decidim/initiatives/create_initiative/finish.html.erb +17 -10
  51. data/app/views/decidim/initiatives/create_initiative/previous_form.html.erb +2 -1
  52. data/app/views/decidim/initiatives/create_initiative/promotal_committee.html.erb +1 -1
  53. data/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb +1 -2
  54. data/app/views/decidim/initiatives/create_initiative/show_similar_initiatives.html.erb +1 -1
  55. data/app/views/decidim/initiatives/initiative_signatures/fill_personal_data.html.erb +1 -0
  56. data/app/views/decidim/initiatives/initiatives/_author.html.erb +1 -1
  57. data/app/views/decidim/initiatives/initiatives/_filters.html.erb +16 -28
  58. data/app/views/decidim/initiatives/initiatives/_index_header.html.erb +3 -3
  59. data/app/views/decidim/initiatives/initiatives/_initiatives.html.erb +1 -1
  60. data/app/views/decidim/initiatives/initiatives/_interactions.html.erb +2 -3
  61. data/app/views/decidim/initiatives/initiatives/_tags.html.erb +3 -0
  62. data/app/views/decidim/initiatives/initiatives/index.html.erb +1 -1
  63. data/app/views/decidim/initiatives/initiatives/show.html.erb +1 -0
  64. data/app/views/decidim/initiatives/versions/index.html.erb +8 -0
  65. data/app/views/decidim/initiatives/versions/show.html.erb +10 -0
  66. data/app/views/layouts/decidim/_initiative_creation_header.html.erb +2 -1
  67. data/app/views/layouts/decidim/_initiative_header.html.erb +2 -1
  68. data/app/views/layouts/decidim/_initiative_signature_creation_header.html.erb +1 -1
  69. data/app/views/layouts/decidim/initiative_creation.html.erb +1 -2
  70. data/app/views/layouts/decidim/initiative_signature_creation.html.erb +2 -2
  71. data/config/locales/ar.yml +12 -19
  72. data/config/locales/bg-BG.yml +13 -0
  73. data/config/locales/ca.yml +79 -17
  74. data/config/locales/cs.yml +88 -26
  75. data/config/locales/da-DK.yml +1 -0
  76. data/config/locales/de.yml +67 -16
  77. data/config/locales/el.yml +528 -0
  78. data/config/locales/en.yml +82 -20
  79. data/config/locales/es-MX.yml +79 -17
  80. data/config/locales/es-PY.yml +79 -17
  81. data/config/locales/es.yml +81 -19
  82. data/config/locales/et-EE.yml +1 -0
  83. data/config/locales/eu.yml +4 -7
  84. data/config/locales/fi-plain.yml +79 -17
  85. data/config/locales/fi.yml +97 -35
  86. data/config/locales/fr-CA.yml +529 -0
  87. data/config/locales/fr.yml +66 -16
  88. data/config/locales/ga-IE.yml +1 -0
  89. data/config/locales/gl.yml +4 -7
  90. data/config/locales/hr-HR.yml +1 -0
  91. data/config/locales/hu.yml +21 -18
  92. data/config/locales/id-ID.yml +4 -7
  93. data/config/locales/is-IS.yml +4 -7
  94. data/config/locales/it.yml +105 -57
  95. data/config/locales/ja-JP.yml +535 -0
  96. data/config/locales/lt-LT.yml +1 -0
  97. data/config/locales/lv-LV.yml +529 -0
  98. data/config/locales/mt-MT.yml +1 -0
  99. data/config/locales/nl.yml +66 -16
  100. data/config/locales/no.yml +14 -29
  101. data/config/locales/pl.yml +241 -176
  102. data/config/locales/pt-BR.yml +5 -8
  103. data/config/locales/pt.yml +227 -176
  104. data/config/locales/ro-RO.yml +532 -0
  105. data/config/locales/ru.yml +4 -7
  106. data/config/locales/sk-SK.yml +468 -0
  107. data/config/locales/sk.yml +462 -0
  108. data/config/locales/sl.yml +18 -0
  109. data/config/locales/sr-CS.yml +8 -0
  110. data/config/locales/sv.yml +77 -26
  111. data/config/locales/tr-TR.yml +4 -7
  112. data/config/locales/uk.yml +4 -7
  113. data/db/migrate/20200320105920_index_foreign_keys_in_decidim_initiatives.rb +8 -0
  114. data/db/migrate/20200320105921_index_foreign_keys_in_decidim_initiatives_votes.rb +8 -0
  115. data/db/migrate/20200417120551_add_custom_signature_end_time_option.rb +7 -0
  116. data/db/migrate/20200424110930_add_attachments_enabled_option.rb +7 -0
  117. data/db/migrate/20200514085422_add_area_to_initiatives.rb +7 -0
  118. data/db/migrate/20200514102631_add_area_enabled_option_to_initiatives.rb +7 -0
  119. data/db/seeds/city2.jpeg +0 -0
  120. data/lib/decidim/initiatives/admin_engine.rb +4 -0
  121. data/lib/decidim/initiatives/engine.rb +1 -0
  122. data/lib/decidim/initiatives/participatory_space.rb +9 -1
  123. data/lib/decidim/initiatives/test/factories.rb +30 -1
  124. data/lib/decidim/initiatives/version.rb +1 -1
  125. metadata +55 -15
  126. data/app/views/decidim/initiatives/initiatives_mailer/notify_validating_request.html.erb +0 -3
@@ -32,6 +32,7 @@ module Decidim
32
32
  percentage_after = @initiative.reload.percentage
33
33
 
34
34
  notify_percentage_change(percentage_before, percentage_after)
35
+ notify_support_threshold_reached(percentage_after)
35
36
 
36
37
  broadcast(:ok, vote)
37
38
  end
@@ -92,6 +93,21 @@ module Decidim
92
93
  }
93
94
  )
94
95
  end
96
+
97
+ def notify_support_threshold_reached(percentage)
98
+ return unless percentage >= 100
99
+
100
+ Decidim::EventsManager.publish(
101
+ event: "decidim.events.initiatives.support_threshold_reached",
102
+ event_class: Decidim::Initiatives::Admin::SupportThresholdReachedEvent,
103
+ resource: @initiative,
104
+ followers: organization_admins
105
+ )
106
+ end
107
+
108
+ def organization_admins
109
+ Decidim::User.where(organization: @initiative.organization, admin: true)
110
+ end
95
111
  end
96
112
  end
97
113
  end
@@ -14,22 +14,36 @@ module Decidim
14
14
  private
15
15
 
16
16
  def base_query
17
- collection
17
+ collection.joins(:scoped_type).left_joins(:area).joins("JOIN decidim_users ON decidim_users.id = decidim_initiatives.decidim_author_id")
18
18
  end
19
19
 
20
20
  def search_field_predicate
21
- :title_or_description_cont
21
+ :title_or_description_or_id_string_or_author_name_or_author_nickname_cont
22
22
  end
23
23
 
24
24
  def filters
25
- [:state_eq]
25
+ [:state_eq, :type_id_eq, :decidim_area_id_eq]
26
26
  end
27
27
 
28
28
  def filters_with_values
29
29
  {
30
- state_eq: Initiative.states.keys
30
+ state_eq: Initiative.states.keys,
31
+ type_id_eq: InitiativesType.where(organization: current_organization).pluck(:id),
32
+ decidim_area_id_eq: current_organization.areas.pluck(:id)
31
33
  }
32
34
  end
35
+
36
+ def dynamically_translated_filters
37
+ [:type_id_eq, :decidim_area_id_eq]
38
+ end
39
+
40
+ def translated_type_id_eq(id)
41
+ translated_attribute(Decidim::InitiativesType.find_by(id: id).title[I18n.locale.to_s])
42
+ end
43
+
44
+ def translated_decidim_area_id_eq(id)
45
+ translated_attribute(Decidim::Area.find_by(id: id).name[I18n.locale.to_s])
46
+ end
33
47
  end
34
48
  end
35
49
  end
@@ -14,7 +14,7 @@ module Decidim
14
14
  # Available orders based on enabled settings
15
15
  def available_orders
16
16
  @available_orders ||= begin
17
- available_orders = %w(random recent most_voted most_commented)
17
+ available_orders = %w(random recent most_voted most_commented recently_published)
18
18
  available_orders
19
19
  end
20
20
  end
@@ -31,6 +31,8 @@ module Decidim
31
31
  initiatives.order_by_most_commented
32
32
  when "recent"
33
33
  initiatives.order_by_most_recent
34
+ when "recently_published"
35
+ initiatives.order_by_most_recently_published
34
36
  else
35
37
  initiatives.order_randomly(random_seed)
36
38
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ module Initiatives
7
+ # Common methods for elements that need specific behaviour when there is only one initiative type.
8
+ module SingleInitiativeType
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ helper_method :single_initiative_type?
13
+
14
+ private
15
+
16
+ def current_organization_initiatives_type
17
+ Decidim::InitiativesType.where(organization: current_organization)
18
+ end
19
+
20
+ def single_initiative_type?
21
+ current_organization_initiatives_type.count == 1
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -8,6 +8,7 @@ module Decidim
8
8
  # Controller used to manage the initiatives
9
9
  class InitiativesController < Decidim::Initiatives::Admin::ApplicationController
10
10
  include Decidim::Initiatives::NeedsInitiative
11
+ include Decidim::Initiatives::SingleInitiativeType
11
12
  include Decidim::Initiatives::TypeSelectorOptions
12
13
  include Decidim::Initiatives::Admin::Filterable
13
14
 
@@ -28,11 +29,14 @@ module Decidim
28
29
  # GET /admin/initiatives/:id/edit
29
30
  def edit
30
31
  enforce_permission_to :edit, :initiative, initiative: current_initiative
32
+
33
+ form_attachment_model = form(AttachmentForm).from_model(current_initiative.attachments.first)
31
34
  @form = form(Decidim::Initiatives::Admin::InitiativeForm)
32
35
  .from_model(
33
36
  current_initiative,
34
37
  initiative: current_initiative
35
38
  )
39
+ @form.attachment = form_attachment_model
36
40
 
37
41
  render layout: "decidim/admin/initiative"
38
42
  end
@@ -107,7 +111,7 @@ module Decidim
107
111
 
108
112
  SendInitiativeToTechnicalValidation.call(current_initiative, current_user) do
109
113
  on(:ok) do
110
- redirect_to edit_initiative_path(current_initiative), flash: {
114
+ redirect_to EngineRouter.main_proxy(current_initiative).initiatives_path(initiative_slug: nil), flash: {
111
115
  notice: I18n.t(
112
116
  "success",
113
117
  scope: %w(decidim initiatives admin initiatives edit)
@@ -117,6 +121,17 @@ module Decidim
117
121
  end
118
122
  end
119
123
 
124
+ # GET /admin/initiatives/export
125
+ def export
126
+ enforce_permission_to :export, :initiatives
127
+
128
+ Decidim::Initiatives::ExportInitiativesJob.perform_later(current_user, params[:format] || default_format)
129
+
130
+ flash[:notice] = t("decidim.admin.exports.notice")
131
+
132
+ redirect_back(fallback_location: initiatives_path)
133
+ end
134
+
120
135
  # GET /admin/initiatives/:id/export_votes
121
136
  def export_votes
122
137
  enforce_permission_to :export_votes, :initiative, initiative: current_initiative
@@ -162,6 +177,10 @@ module Decidim
162
177
  def pdf_signature_service
163
178
  @pdf_signature_service ||= Decidim.pdf_signature_service.to_s.safe_constantize
164
179
  end
180
+
181
+ def default_format
182
+ "json"
183
+ end
165
184
  end
166
185
  end
167
186
  end
@@ -12,11 +12,13 @@ module Decidim
12
12
  include Decidim::FormFactory
13
13
  include InitiativeHelper
14
14
  include TypeSelectorOptions
15
+ include SingleInitiativeType
15
16
 
16
17
  helper Decidim::Admin::IconLinkHelper
17
18
  helper InitiativeHelper
18
19
  helper_method :similar_initiatives
19
20
  helper_method :scopes
21
+ helper_method :areas
20
22
  helper_method :current_initiative
21
23
  helper_method :initiative_type
22
24
  helper_method :promotal_committee_required?
@@ -43,7 +45,14 @@ module Decidim
43
45
  def select_initiative_type_step(_parameters)
44
46
  @form = form(Decidim::Initiatives::SelectInitiativeTypeForm).instance
45
47
  session[:initiative] = {}
46
- render_wizard
48
+
49
+ if single_initiative_type?
50
+ redirect_to next_wizard_path
51
+ return
52
+ end
53
+
54
+ @form = form(Decidim::Initiatives::SelectInitiativeTypeForm).instance
55
+ render_wizard unless performed?
47
56
  end
48
57
 
49
58
  def previous_form_step(parameters)
@@ -68,10 +77,18 @@ module Decidim
68
77
 
69
78
  def fill_data_step(parameters)
70
79
  @form = build_form(Decidim::Initiatives::InitiativeForm, parameters)
80
+ @form.attachment = form(AttachmentForm).from_params({})
81
+
71
82
  render_wizard
72
83
  end
73
84
 
74
85
  def promotal_committee_step(parameters)
86
+ @form = build_form(Decidim::Initiatives::InitiativeForm, parameters)
87
+ unless @form.valid?
88
+ redirect_to previous_wizard_path(validate_form: true)
89
+ return
90
+ end
91
+
75
92
  skip_step unless promotal_committee_required?
76
93
 
77
94
  if session_initiative.has_key?(:id)
@@ -79,8 +96,6 @@ module Decidim
79
96
  return
80
97
  end
81
98
 
82
- @form = build_form(Decidim::Initiatives::InitiativeForm, parameters)
83
-
84
99
  CreateInitiative.call(@form, current_user) do
85
100
  on(:ok) do |initiative|
86
101
  session[:initiative][:id] = initiative.id
@@ -109,7 +124,12 @@ module Decidim
109
124
  end
110
125
 
111
126
  def build_form(klass, parameters)
112
- @form = form(klass).from_params(parameters)
127
+ @form = if single_initiative_type?
128
+ form(klass).from_params(parameters.merge(type_id: current_organization_initiatives_type.first.id), extra_context)
129
+ else
130
+ form(klass).from_params(parameters, extra_context)
131
+ end
132
+
113
133
  attributes = @form.attributes_with_values
114
134
  session[:initiative] = session_initiative.merge(attributes)
115
135
  @form.valid? if params[:validate_form]
@@ -117,6 +137,12 @@ module Decidim
117
137
  @form
118
138
  end
119
139
 
140
+ def extra_context
141
+ return {} unless initiative_type_id
142
+
143
+ { initiative_type: initiative_type }
144
+ end
145
+
120
146
  def scopes
121
147
  @scopes ||= InitiativesTypeScope.where(decidim_initiatives_types_id: @form.type_id)
122
148
  end
@@ -126,7 +152,11 @@ module Decidim
126
152
  end
127
153
 
128
154
  def initiative_type
129
- @initiative_type ||= InitiativesType.find(session_initiative[:type_id] || @form&.type_id)
155
+ @initiative_type ||= InitiativesType.find(initiative_type_id)
156
+ end
157
+
158
+ def initiative_type_id
159
+ session_initiative[:type_id] || @form&.type_id
130
160
  end
131
161
 
132
162
  def session_initiative
@@ -25,6 +25,7 @@ module Decidim
25
25
  include Decidim::Initiatives::Orderable
26
26
  include TypeSelectorOptions
27
27
  include NeedsInitiative
28
+ include SingleInitiativeType
28
29
 
29
30
  helper_method :collection, :initiatives, :filter, :stats
30
31
 
@@ -70,13 +71,26 @@ module Decidim
70
71
  def default_filter_params
71
72
  {
72
73
  search_text: "",
73
- state: "open",
74
- type: "all",
74
+ state: ["open"],
75
+ type_id: default_filter_type_params,
75
76
  author: "any",
76
- scope_id: nil
77
+ scope_id: default_filter_scope_params,
78
+ area_id: default_filter_area_params
77
79
  }
78
80
  end
79
81
 
82
+ def default_filter_type_params
83
+ %w(all) + Decidim::InitiativesType.where(organization: current_organization).pluck(:id).map(&:to_s)
84
+ end
85
+
86
+ def default_filter_scope_params
87
+ %w(all global) + current_organization.scopes.pluck(:id).map(&:to_s)
88
+ end
89
+
90
+ def default_filter_area_params
91
+ %w(all) + current_organization.areas.pluck(:id).map(&:to_s)
92
+ end
93
+
80
94
  def context_params
81
95
  {
82
96
  organization: current_organization,
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ # Exposes Initiatives versions so users can see how an Initiative
6
+ # has been updated through time.
7
+ class VersionsController < Decidim::Initiatives::ApplicationController
8
+ include ParticipatorySpaceContext
9
+ participatory_space_layout
10
+ helper InitiativeHelper
11
+
12
+ include NeedsInitiative
13
+ include Decidim::ResourceVersionsConcern
14
+
15
+ def versioned_resource
16
+ current_initiative
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # frozen-string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ module Admin
6
+ class InitiativeSentToTechnicalValidationEvent < Decidim::Events::SimpleEvent
7
+ include Rails.application.routes.mounted_helpers
8
+
9
+ i18n_attributes :admin_initiative_url, :admin_initiative_path
10
+
11
+ def admin_initiative_path
12
+ ResourceLocatorPresenter.new(resource).edit
13
+ end
14
+
15
+ def admin_initiative_url
16
+ decidim_admin_initiatives.edit_initiative_url(resource, resource.mounted_params)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ # frozen-string_literal: true
2
+
3
+ module Decidim
4
+ module Initiatives
5
+ module Admin
6
+ class SupportThresholdReachedEvent < Decidim::Events::SimpleEvent
7
+ def participatory_space
8
+ resource
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -14,20 +14,26 @@ module Decidim
14
14
  translatable_attribute :description, String
15
15
  attribute :type_id, Integer
16
16
  attribute :decidim_scope_id, Integer
17
+ attribute :area_id, Integer
17
18
  attribute :signature_type, String
18
19
  attribute :signature_start_date, Decidim::Attributes::LocalizedDate
19
20
  attribute :signature_end_date, Decidim::Attributes::LocalizedDate
20
21
  attribute :hashtag, String
21
22
  attribute :offline_votes, Integer
22
23
  attribute :state, String
24
+ attribute :attachment, AttachmentForm
23
25
 
24
26
  validates :title, :description, presence: true
27
+ validates :area, presence: true, if: ->(form) { form.area_id.present? }
25
28
  validates :signature_type, presence: true, if: :signature_type_updatable?
26
29
  validates :signature_start_date, presence: true, if: ->(form) { form.context.initiative.published? }
27
30
  validates :signature_end_date, presence: true, if: ->(form) { form.context.initiative.published? }
28
31
  validates :signature_end_date, date: { after: :signature_start_date }, if: lambda { |form|
29
32
  form.signature_start_date.present? && form.signature_end_date.present?
30
33
  }
34
+ validates :signature_end_date, date: { after: Date.current }, if: lambda { |form|
35
+ form.signature_start_date.blank? && form.signature_end_date.present?
36
+ }
31
37
 
32
38
  validates :offline_votes,
33
39
  numericality: {
@@ -35,6 +41,9 @@ module Decidim
35
41
  greater_than: 0
36
42
  }, allow_blank: true
37
43
 
44
+ validate :notify_missing_attachment_if_errored
45
+ validate :area_is_not_removed
46
+
38
47
  def map_model(model)
39
48
  self.type_id = model.type.id
40
49
  self.decidim_scope_id = model.scope&.id
@@ -51,17 +60,39 @@ module Decidim
51
60
  false
52
61
  end
53
62
 
63
+ def area_updatable?
64
+ @area_updatable ||= current_user.admin? || context.initiative.created?
65
+ end
66
+
54
67
  def scoped_type_id
55
68
  return unless type && decidim_scope_id
56
69
 
57
70
  type.scopes.find_by!(decidim_scopes_id: decidim_scope_id).id
58
71
  end
59
72
 
73
+ def area
74
+ @area ||= current_organization.areas.find_by(id: area_id)
75
+ end
76
+
60
77
  private
61
78
 
62
79
  def type
63
80
  @type ||= type_id ? Decidim::InitiativesType.find(type_id) : context.initiative.type
64
81
  end
82
+
83
+ # This method will add an error to the `attachment` field only if there's
84
+ # any error in any other field. This is needed because when the form has
85
+ # an error, the attachment is lost, so we need a way to inform the user of
86
+ # this problem.
87
+ def notify_missing_attachment_if_errored
88
+ errors.add(:attachment, :needs_to_be_reattached) if errors.any? && attachment.present?
89
+ end
90
+
91
+ def area_is_not_removed
92
+ return if context.initiative.decidim_area_id.blank? || context.initiative.created?
93
+
94
+ errors.add(:area_id, :blank) if area_id.blank?
95
+ end
65
96
  end
66
97
  end
67
98
  end
@@ -14,6 +14,9 @@ module Decidim
14
14
  attribute :banner_image, String
15
15
  attribute :signature_type, String
16
16
  attribute :undo_online_signatures_enabled, Boolean
17
+ attribute :attachments_enabled, Boolean
18
+ attribute :custom_signature_end_date_enabled, Boolean
19
+ attribute :area_enabled, Boolean
17
20
  attribute :promoting_committee_enabled, Boolean
18
21
  attribute :minimum_committee_members, Integer
19
22
  attribute :collect_user_extra_fields, Boolean
@@ -22,7 +25,8 @@ module Decidim
22
25
  attribute :document_number_authorization_handler, String
23
26
 
24
27
  validates :title, :description, translatable_presence: true
25
- validates :undo_online_signatures_enabled, :promoting_committee_enabled, inclusion: { in: [true, false] }
28
+ validates :attachments_enabled, :undo_online_signatures_enabled, :custom_signature_end_date_enabled,
29
+ :area_enabled, :promoting_committee_enabled, inclusion: { in: [true, false] }
26
30
  validates :minimum_committee_members, numericality: { only_integer: true }, allow_nil: true
27
31
  validates :banner_image, presence: true, if: ->(form) { form.context.initiative_type.nil? }
28
32