decidim-initiatives 0.20.1 → 0.23.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) 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/javascripts/decidim/initiatives/admin/initiatives_types.js.es6 +18 -0
  6. data/app/assets/stylesheet/decidim/initiatives/initiatives-votes.css.scss +0 -1
  7. data/app/assets/stylesheet/decidim/initiatives/initiatives.scss +6 -8
  8. data/app/assets/stylesheet/decidim/initiatives/popularity_item.css.scss +0 -1
  9. data/app/assets/stylesheet/decidim/initiatives/print-initiative.css.scss +0 -3
  10. data/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives/show.erb +4 -3
  11. data/app/cells/decidim/initiatives/initiative_m_cell.rb +25 -0
  12. data/app/cells/decidim/initiatives_votes/vote/show.erb +12 -9
  13. data/app/cells/decidim/initiatives_votes/vote_cell.rb +7 -0
  14. data/app/commands/decidim/initiatives/admin/create_initiative_type.rb +6 -1
  15. data/app/commands/decidim/initiatives/admin/send_initiative_to_technical_validation.rb +17 -0
  16. data/app/commands/decidim/initiatives/admin/update_initiative.rb +29 -10
  17. data/app/commands/decidim/initiatives/admin/update_initiative_type.rb +6 -1
  18. data/app/commands/decidim/initiatives/attachment_methods.rb +37 -0
  19. data/app/commands/decidim/initiatives/create_initiative.rb +25 -3
  20. data/app/commands/decidim/initiatives/unvote_initiative.rb +4 -10
  21. data/app/commands/decidim/initiatives/vote_initiative.rb +47 -31
  22. data/app/controllers/concerns/decidim/initiatives/admin/filterable.rb +51 -0
  23. data/app/controllers/concerns/decidim/initiatives/orderable.rb +3 -1
  24. data/app/controllers/concerns/decidim/initiatives/single_initiative_type.rb +26 -0
  25. data/app/controllers/decidim/initiatives/admin/answers_controller.rb +2 -3
  26. data/app/controllers/decidim/initiatives/admin/initiatives_controller.rb +28 -15
  27. data/app/controllers/decidim/initiatives/create_initiative_controller.rb +36 -6
  28. data/app/controllers/decidim/initiatives/initiative_signatures_controller.rb +19 -23
  29. data/app/controllers/decidim/initiatives/initiative_votes_controller.rb +11 -5
  30. data/app/controllers/decidim/initiatives/initiatives_controller.rb +28 -13
  31. data/app/controllers/decidim/initiatives/initiatives_type_scopes_controller.rb +9 -1
  32. data/app/controllers/decidim/initiatives/versions_controller.rb +20 -0
  33. data/app/controllers/decidim/initiatives/{initiative_widgets_controller.rb → widgets_controller.rb} +2 -2
  34. data/app/events/decidim/initiatives/admin/initiative_sent_to_technical_validation_event.rb +21 -0
  35. data/app/events/decidim/initiatives/admin/support_threshold_reached_event.rb +13 -0
  36. data/app/forms/decidim/initiatives/admin/initiative_form.rb +49 -7
  37. data/app/forms/decidim/initiatives/admin/initiative_type_form.rb +8 -1
  38. data/app/forms/decidim/initiatives/initiative_form.rb +56 -1
  39. data/app/forms/decidim/initiatives/vote_form.rb +133 -76
  40. data/app/helpers/decidim/initiatives/application_helper.rb +104 -0
  41. data/app/helpers/decidim/initiatives/initiative_helper.rb +13 -0
  42. data/app/helpers/decidim/initiatives/initiatives_helper.rb +10 -0
  43. data/app/jobs/decidim/initiatives/export_initiatives_job.rb +25 -0
  44. data/app/mailers/decidim/initiatives/initiatives_mailer.rb +0 -21
  45. data/app/models/concerns/decidim/initiatives/has_area.rb +30 -0
  46. data/app/models/decidim/initiative.rb +184 -44
  47. data/app/models/decidim/initiatives_type.rb +5 -2
  48. data/app/models/decidim/initiatives_type_scope.rb +5 -1
  49. data/app/models/decidim/initiatives_vote.rb +19 -23
  50. data/app/permissions/decidim/initiatives/admin/permissions.rb +19 -8
  51. data/app/permissions/decidim/initiatives/permissions.rb +37 -14
  52. data/app/presenters/decidim/initiatives/initiative_stats_presenter.rb +1 -5
  53. data/app/queries/decidim/initiatives/admin/manageable_initiatives.rb +7 -39
  54. data/app/serializers/decidim/initiatives/initiative_serializer.rb +32 -0
  55. data/app/services/decidim/initiatives/diff_renderer.rb +18 -0
  56. data/app/services/decidim/initiatives/initiative_search.rb +59 -15
  57. data/app/services/decidim/initiatives/status_change_notifier.rb +4 -5
  58. data/app/types/decidim/initiatives/initiative_api_type.rb +26 -0
  59. data/app/types/decidim/initiatives/initiative_committee_member_type.rb +18 -0
  60. data/app/types/decidim/initiatives/initiative_type.rb +42 -0
  61. data/app/views/decidim/initiatives/admin/answers/_info_initiative.html.erb +1 -1
  62. data/app/views/decidim/initiatives/admin/exports/_dropdown.html.erb +8 -0
  63. data/app/views/decidim/initiatives/admin/initiatives/_form.html.erb +59 -14
  64. data/app/views/decidim/initiatives/admin/initiatives/_initiative_attachments.erb +43 -0
  65. data/app/views/decidim/initiatives/admin/initiatives/export_pdf_signatures.pdf.erb +12 -9
  66. data/app/views/decidim/initiatives/admin/initiatives/index.html.erb +10 -45
  67. data/app/views/decidim/initiatives/admin/initiatives_types/_form.html.erb +47 -10
  68. data/app/views/decidim/initiatives/admin/initiatives_types/_initiative_type_scopes.html.erb +28 -25
  69. data/app/views/decidim/initiatives/create_initiative/fill_data.html.erb +46 -10
  70. data/app/views/decidim/initiatives/create_initiative/finish.html.erb +17 -10
  71. data/app/views/decidim/initiatives/create_initiative/previous_form.html.erb +2 -1
  72. data/app/views/decidim/initiatives/create_initiative/promotal_committee.html.erb +1 -1
  73. data/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb +1 -2
  74. data/app/views/decidim/initiatives/create_initiative/show_similar_initiatives.html.erb +1 -1
  75. data/app/views/decidim/initiatives/initiative_signatures/fill_personal_data.html.erb +1 -1
  76. data/app/views/decidim/initiatives/initiative_signatures/update_buttons_and_counters.js.erb +1 -1
  77. data/app/views/decidim/initiatives/initiative_votes/update_buttons_and_counters.js.erb +1 -1
  78. data/app/views/decidim/initiatives/initiatives/_author.html.erb +1 -1
  79. data/app/views/decidim/initiatives/initiatives/_filters.html.erb +16 -28
  80. data/app/views/decidim/initiatives/initiatives/_index_header.html.erb +39 -5
  81. data/app/views/decidim/initiatives/initiatives/_initiatives.html.erb +11 -1
  82. data/app/views/decidim/initiatives/initiatives/_interactions.html.erb +2 -3
  83. data/app/views/decidim/initiatives/initiatives/_progress_bar.html.erb +24 -9
  84. data/app/views/decidim/initiatives/initiatives/_tags.html.erb +3 -0
  85. data/app/views/decidim/initiatives/initiatives/_vote_cabin.html.erb +1 -13
  86. data/app/views/decidim/initiatives/initiatives/index.html.erb +1 -1
  87. data/app/views/decidim/initiatives/initiatives/show.html.erb +2 -3
  88. data/app/views/decidim/initiatives/versions/index.html.erb +8 -0
  89. data/app/views/decidim/initiatives/versions/show.html.erb +10 -0
  90. data/app/views/layouts/decidim/_initiative_creation_header.html.erb +2 -1
  91. data/app/views/layouts/decidim/_initiative_header.html.erb +2 -1
  92. data/app/views/layouts/decidim/_initiative_signature_creation_header.html.erb +1 -1
  93. data/app/views/layouts/decidim/initiative.html.erb +1 -0
  94. data/app/views/layouts/decidim/initiative_creation.html.erb +1 -2
  95. data/app/views/layouts/decidim/initiative_signature_creation.html.erb +2 -2
  96. data/config/locales/am-ET.yml +1 -0
  97. data/config/locales/ar.yml +12 -21
  98. data/config/locales/bg-BG.yml +13 -0
  99. data/config/locales/bg.yml +13 -0
  100. data/config/locales/ca.yml +99 -21
  101. data/config/locales/cs.yml +110 -32
  102. data/config/locales/da-DK.yml +1 -0
  103. data/config/locales/da.yml +1 -0
  104. data/config/locales/de.yml +75 -21
  105. data/config/locales/el.yml +525 -0
  106. data/config/locales/en.yml +102 -24
  107. data/config/locales/eo.yml +1 -0
  108. data/config/locales/es-MX.yml +99 -21
  109. data/config/locales/es-PY.yml +99 -21
  110. data/config/locales/es.yml +103 -25
  111. data/config/locales/et-EE.yml +1 -0
  112. data/config/locales/et.yml +1 -0
  113. data/config/locales/eu.yml +4 -21
  114. data/config/locales/fi-plain.yml +99 -21
  115. data/config/locales/fi.yml +117 -39
  116. data/config/locales/fr-CA.yml +557 -0
  117. data/config/locales/fr.yml +101 -23
  118. data/config/locales/ga-IE.yml +1 -0
  119. data/config/locales/gl.yml +4 -21
  120. data/config/locales/hr-HR.yml +1 -0
  121. data/config/locales/hr.yml +1 -0
  122. data/config/locales/hu.yml +27 -21
  123. data/config/locales/id-ID.yml +4 -21
  124. data/config/locales/is-IS.yml +4 -17
  125. data/config/locales/is.yml +251 -0
  126. data/config/locales/it.yml +116 -61
  127. data/config/locales/ja-JP.yml +529 -0
  128. data/config/locales/ja.yml +549 -0
  129. data/config/locales/ko-KR.yml +1 -0
  130. data/config/locales/ko.yml +1 -0
  131. data/config/locales/lt-LT.yml +1 -0
  132. data/config/locales/lt.yml +1 -0
  133. data/config/locales/lv.yml +525 -0
  134. data/config/locales/mt-MT.yml +1 -0
  135. data/config/locales/mt.yml +1 -0
  136. data/config/locales/nl.yml +76 -21
  137. data/config/locales/no.yml +62 -31
  138. data/config/locales/om-ET.yml +1 -0
  139. data/config/locales/pl.yml +260 -189
  140. data/config/locales/pt-BR.yml +5 -22
  141. data/config/locales/pt.yml +231 -179
  142. data/config/locales/ro-RO.yml +533 -0
  143. data/config/locales/ru.yml +4 -21
  144. data/config/locales/sk-SK.yml +468 -0
  145. data/config/locales/sk.yml +458 -0
  146. data/config/locales/sl.yml +24 -0
  147. data/config/locales/so-SO.yml +1 -0
  148. data/config/locales/sr-CS.yml +8 -0
  149. data/config/locales/sv.yml +102 -31
  150. data/config/locales/ti-ER.yml +1 -0
  151. data/config/locales/tr-TR.yml +4 -21
  152. data/config/locales/uk.yml +4 -21
  153. data/config/locales/vi-VN.yml +1 -0
  154. data/config/locales/vi.yml +1 -0
  155. data/config/locales/zh-CN.yml +549 -0
  156. data/config/locales/zh-TW.yml +1 -0
  157. data/db/migrate/20191106144259_add_settings_to_initiatives_types.rb +8 -0
  158. data/db/migrate/20191107134847_add_scopes_to_initiatives_votes.rb +28 -0
  159. data/db/migrate/20191116170841_allow_multiple_initiative_votes_counter_caches.rb +32 -0
  160. data/db/migrate/20191118105634_allow_multiple_offline_votes.rb +34 -0
  161. data/db/migrate/20200320105920_index_foreign_keys_in_decidim_initiatives.rb +8 -0
  162. data/db/migrate/20200320105921_index_foreign_keys_in_decidim_initiatives_votes.rb +8 -0
  163. data/db/migrate/20200417120551_add_custom_signature_end_time_option.rb +7 -0
  164. data/db/migrate/20200424110930_add_attachments_enabled_option.rb +7 -0
  165. data/db/migrate/20200514085422_add_area_to_initiatives.rb +7 -0
  166. data/db/migrate/20200514102631_add_area_enabled_option_to_initiatives.rb +7 -0
  167. data/db/migrate/20200528151456_remove_user_groups_from_initiative_votes.rb +7 -0
  168. data/db/migrate/20200827154214_add_commentable_counter_cache_to_initiatives.rb +9 -0
  169. data/db/seeds/city.jpeg +0 -0
  170. data/db/seeds/city2.jpeg +0 -0
  171. data/lib/decidim/api/initiative_type_interface.rb +13 -0
  172. data/lib/decidim/initiatives/admin_engine.rb +5 -0
  173. data/lib/decidim/initiatives/api.rb +7 -0
  174. data/lib/decidim/initiatives/engine.rb +11 -2
  175. data/lib/decidim/initiatives/participatory_space.rb +18 -1
  176. data/lib/decidim/initiatives/query_extensions.rb +40 -0
  177. data/lib/decidim/initiatives/test/factories.rb +51 -4
  178. data/lib/decidim/initiatives/version.rb +1 -1
  179. data/lib/tasks/decidim_initiatives.rake +1 -3
  180. metadata +92 -21
  181. data/app/views/decidim/initiatives/initiative_widgets/show.html.erb +0 -4
  182. data/app/views/decidim/initiatives/initiatives/_supports.html.erb +0 -22
  183. data/app/views/decidim/initiatives/initiatives/signature_identities.html.erb +0 -42
  184. data/app/views/decidim/initiatives/initiatives_mailer/notify_validating_request.html.erb +0 -3
@@ -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,8 +137,14 @@ 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
- @scopes ||= InitiativesTypeScope.where(decidim_initiatives_types_id: @form.type_id)
147
+ @scopes ||= @form.available_scopes
122
148
  end
123
149
 
124
150
  def current_initiative
@@ -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
@@ -20,30 +20,27 @@ module Decidim
20
20
 
21
21
  # GET /initiatives/:initiative_id/initiative_signatures/:step
22
22
  def show
23
- group_id = params[:group_id] || (session[:initiative_vote_form] ||= {})["group_id"]
24
- enforce_permission_to :sign_initiative, :initiative, initiative: current_initiative, group_id: group_id, signature_has_steps: signature_has_steps?
23
+ enforce_permission_to :sign_initiative, :initiative, initiative: current_initiative, signature_has_steps: signature_has_steps?
25
24
  send("#{step}_step", initiative_vote_form: session[:initiative_vote_form])
26
25
  end
27
26
 
28
27
  # PUT /initiatives/:initiative_id/initiative_signatures/:step
29
28
  def update
30
- group_id = params.dig(:initiatives_vote, :group_id) || session[:initiative_vote_form]["group_id"]
31
- enforce_permission_to :sign_initiative, :initiative, initiative: current_initiative, group_id: group_id, signature_has_steps: signature_has_steps?
29
+ enforce_permission_to :sign_initiative, :initiative, initiative: current_initiative, signature_has_steps: signature_has_steps?
32
30
  send("#{step}_step", params)
33
31
  end
34
32
 
35
33
  # POST /initiatives/:initiative_id/initiative_signatures
36
34
  def create
37
- group_id = params[:group_id] || session[:initiative_vote_form]&.dig("group_id")
38
- enforce_permission_to :vote, :initiative, initiative: current_initiative, group_id: group_id
35
+ enforce_permission_to :vote, :initiative, initiative: current_initiative
36
+
39
37
  @form = form(Decidim::Initiatives::VoteForm)
40
38
  .from_params(
41
- initiative_id: current_initiative.id,
42
- author_id: current_user.id,
43
- group_id: group_id
39
+ initiative: current_initiative,
40
+ signer: current_user
44
41
  )
45
42
 
46
- VoteInitiative.call(@form, current_user) do
43
+ VoteInitiative.call(@form) do
47
44
  on(:ok) do
48
45
  current_initiative.reload
49
46
  render :update_buttons_and_counters
@@ -62,11 +59,11 @@ module Decidim
62
59
  def fill_personal_data_step(_unused)
63
60
  @form = form(Decidim::Initiatives::VoteForm)
64
61
  .from_params(
65
- initiative_id: current_initiative.id,
66
- author_id: current_user.id,
67
- group_id: params[:group_id]
62
+ initiative: current_initiative,
63
+ signer: current_user
68
64
  )
69
- session[:initiative_vote_form] = { group_id: @form.group_id }
65
+
66
+ session[:initiative_vote_form] = {}
70
67
  skip_step unless initiative_type.collect_user_extra_fields
71
68
  render_wizard
72
69
  end
@@ -128,7 +125,7 @@ module Decidim
128
125
  end
129
126
  end
130
127
 
131
- VoteInitiative.call(@vote_form, current_user) do
128
+ VoteInitiative.call(@vote_form) do
132
129
  on(:ok) do
133
130
  session[:initiative_vote_form] = {}
134
131
  end
@@ -139,25 +136,24 @@ module Decidim
139
136
  jump_to previous_step
140
137
  end
141
138
  end
139
+
142
140
  render_wizard
143
141
  end
144
142
 
145
143
  def build_vote_form(parameters)
146
144
  @vote_form = form(Decidim::Initiatives::VoteForm).from_params(parameters).tap do |form|
147
- form.initiative_id = current_initiative.id
148
- form.author_id = current_user.id
145
+ form.initiative = current_initiative
146
+ form.signer = current_user
149
147
  end
150
148
 
151
- session[:initiative_vote_form] = session[:initiative_vote_form].merge(@vote_form.attributes_with_values)
149
+ session[:initiative_vote_form] ||= {}
150
+ session[:initiative_vote_form] = session[:initiative_vote_form].merge(@vote_form.attributes_with_values.except(:initiative, :signer))
152
151
  end
153
152
 
154
153
  def session_vote_form
155
- raw_birth_date = session[:initiative_vote_form]["date_of_birth"]
156
- return unless raw_birth_date
154
+ attributes = session[:initiative_vote_form].merge(initiative: current_initiative, signer: current_user)
157
155
 
158
- @vote_form = form(Decidim::Initiatives::VoteForm).from_params(
159
- session[:initiative_vote_form].merge("date_of_birth" => Date.parse(raw_birth_date))
160
- )
156
+ @vote_form = form(Decidim::Initiatives::VoteForm).from_params(attributes)
161
157
  end
162
158
 
163
159
  def initiative_type
@@ -13,9 +13,14 @@ module Decidim
13
13
 
14
14
  # POST /initiatives/:initiative_id/initiative_vote
15
15
  def create
16
- enforce_permission_to :vote, :initiative, initiative: current_initiative, group_id: params[:group_id]
17
- @form = form(Decidim::Initiatives::VoteForm).from_params(initiative_id: current_initiative.id, author_id: current_user.id, group_id: params[:group_id])
18
- VoteInitiative.call(@form, current_user) do
16
+ enforce_permission_to :vote, :initiative, initiative: current_initiative
17
+
18
+ @form = form(Decidim::Initiatives::VoteForm).from_params(
19
+ initiative: current_initiative,
20
+ signer: current_user
21
+ )
22
+
23
+ VoteInitiative.call(@form) do
19
24
  on(:ok) do
20
25
  current_initiative.reload
21
26
  render :update_buttons_and_counters
@@ -31,8 +36,9 @@ module Decidim
31
36
 
32
37
  # DELETE /initiatives/:initiative_id/initiative_vote
33
38
  def destroy
34
- enforce_permission_to :unvote, :initiative, initiative: current_initiative, group_id: params[:group_id]
35
- UnvoteInitiative.call(current_initiative, current_user, params[:group_id]) do
39
+ enforce_permission_to :unvote, :initiative, initiative: current_initiative
40
+
41
+ UnvoteInitiative.call(current_initiative, current_user) do
36
42
  on(:ok) do
37
43
  current_initiative.reload
38
44
  render :update_buttons_and_counters
@@ -19,18 +19,29 @@ module Decidim
19
19
  helper PaginateHelper
20
20
  helper InitiativeHelper
21
21
  include InitiativeSlug
22
-
23
22
  include FilterResource
24
23
  include Paginable
25
24
  include Decidim::Initiatives::Orderable
26
25
  include TypeSelectorOptions
27
26
  include NeedsInitiative
27
+ include SingleInitiativeType
28
28
 
29
29
  helper_method :collection, :initiatives, :filter, :stats
30
30
 
31
31
  # GET /initiatives
32
32
  def index
33
33
  enforce_permission_to :list, :initiative
34
+
35
+ return unless search.results.blank? && params.dig("filter", "state") != %w(closed)
36
+
37
+ @closed_initiatives = search_klass.new(search_params.merge(state: %w(closed)))
38
+
39
+ if @closed_initiatives.results.present?
40
+ params[:filter] ||= {}
41
+ params[:filter][:date] = %w(closed)
42
+ @forced_closed_initiatives = true
43
+ @search = @closed_initiatives
44
+ end
34
45
  end
35
46
 
36
47
  # GET /initiatives/:id
@@ -38,15 +49,6 @@ module Decidim
38
49
  enforce_permission_to :read, :initiative, initiative: current_initiative
39
50
  end
40
51
 
41
- # GET /initiatives/:id/signature_identities
42
- def signature_identities
43
- @voted_groups = InitiativesVote
44
- .supports
45
- .where(initiative: current_initiative, author: current_user)
46
- .pluck(:decidim_user_group_id)
47
- render layout: false
48
- end
49
-
50
52
  private
51
53
 
52
54
  alias current_initiative current_participatory_space
@@ -70,13 +72,26 @@ module Decidim
70
72
  def default_filter_params
71
73
  {
72
74
  search_text: "",
73
- state: "open",
74
- type: "all",
75
+ state: ["open"],
76
+ type_id: default_filter_type_params,
75
77
  author: "any",
76
- scope_id: nil
78
+ scope_id: default_filter_scope_params,
79
+ area_id: default_filter_area_params
77
80
  }
78
81
  end
79
82
 
83
+ def default_filter_type_params
84
+ %w(all) + Decidim::InitiativesType.where(organization: current_organization).pluck(:id).map(&:to_s)
85
+ end
86
+
87
+ def default_filter_scope_params
88
+ %w(all global) + current_organization.scopes.pluck(:id).map(&:to_s)
89
+ end
90
+
91
+ def default_filter_area_params
92
+ %w(all) + current_organization.areas.pluck(:id).map(&:to_s)
93
+ end
94
+
80
95
  def context_params
81
96
  {
82
97
  organization: current_organization,
@@ -15,7 +15,15 @@ module Decidim
15
15
  private
16
16
 
17
17
  def scoped_types
18
- @scoped_types ||= InitiativesType.find(params[:type_id]).scopes
18
+ @scoped_types ||= if initiative_type.only_global_scope_enabled?
19
+ initiative_type.scopes.where(scope: nil)
20
+ else
21
+ initiative_type.scopes
22
+ end
23
+ end
24
+
25
+ def initiative_type
26
+ @initiative_type ||= InitiativesType.find(params[:type_id])
19
27
  end
20
28
  end
21
29
  end
@@ -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
@@ -3,7 +3,7 @@
3
3
  module Decidim
4
4
  module Initiatives
5
5
  # This controller provides a widget that allows embedding the initiative
6
- class InitiativeWidgetsController < Decidim::WidgetsController
6
+ class WidgetsController < Decidim::WidgetsController
7
7
  helper InitiativesHelper
8
8
  helper PaginateHelper
9
9
  helper InitiativeHelper
@@ -23,7 +23,7 @@ module Decidim
23
23
  end
24
24
 
25
25
  def iframe_url
26
- @iframe_url ||= initiative_initiative_widget_url(model)
26
+ @iframe_url ||= initiative_widget_url(model)
27
27
  end
28
28
  end
29
29
  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,30 +14,50 @@ 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
- attribute :offline_votes, Integer
22
+ attribute :offline_votes, Hash[String => 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
- validates :offline_votes,
33
- numericality: {
34
- only_integer: true,
35
- greater_than: 0
36
- }, allow_blank: true
38
+ validate :notify_missing_attachment_if_errored
39
+ validate :area_is_not_removed
37
40
 
38
41
  def map_model(model)
39
42
  self.type_id = model.type.id
40
43
  self.decidim_scope_id = model.scope&.id
44
+ self.offline_votes = model.offline_votes
45
+
46
+ if offline_votes.empty?
47
+ self.offline_votes = model.votable_initiative_type_scopes.each_with_object({}) do |initiative_scope_type, all_votes|
48
+ all_votes[initiative_scope_type.decidim_scopes_id || "global"] = [0, initiative_scope_type.scope_name]
49
+ end
50
+ else
51
+ offline_votes.delete("total")
52
+ self.offline_votes = offline_votes.each_with_object({}) do |(decidim_scope_id, votes), all_votes|
53
+ scope_name = model.votable_initiative_type_scopes.find do |initiative_scope_type|
54
+ initiative_scope_type.global_scope? && decidim_scope_id == "global" ||
55
+ initiative_scope_type.decidim_scopes_id == decidim_scope_id.to_i
56
+ end.scope_name
57
+
58
+ all_votes[decidim_scope_id || "global"] = [votes, scope_name]
59
+ end
60
+ end
41
61
  end
42
62
 
43
63
  def signature_type_updatable?
@@ -51,10 +71,18 @@ module Decidim
51
71
  false
52
72
  end
53
73
 
74
+ def area_updatable?
75
+ @area_updatable ||= current_user.admin? || context.initiative.created?
76
+ end
77
+
54
78
  def scoped_type_id
55
79
  return unless type && decidim_scope_id
56
80
 
57
- type.scopes.find_by!(decidim_scopes_id: decidim_scope_id).id
81
+ type.scopes.find_by(decidim_scopes_id: decidim_scope_id.presence).id
82
+ end
83
+
84
+ def area
85
+ @area ||= current_organization.areas.find_by(id: area_id)
58
86
  end
59
87
 
60
88
  private
@@ -62,6 +90,20 @@ module Decidim
62
90
  def type
63
91
  @type ||= type_id ? Decidim::InitiativesType.find(type_id) : context.initiative.type
64
92
  end
93
+
94
+ # This method will add an error to the `attachment` field only if there's
95
+ # any error in any other field. This is needed because when the form has
96
+ # an error, the attachment is lost, so we need a way to inform the user of
97
+ # this problem.
98
+ def notify_missing_attachment_if_errored
99
+ errors.add(:attachment, :needs_to_be_reattached) if errors.any? && attachment.present?
100
+ end
101
+
102
+ def area_is_not_removed
103
+ return if context.initiative.decidim_area_id.blank? || context.initiative.created?
104
+
105
+ errors.add(:area_id, :blank) if area_id.blank?
106
+ end
65
107
  end
66
108
  end
67
109
  end