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.
- checksums.yaml +4 -4
- data/README.md +22 -0
- data/app/assets/images/decidim/gamification/badges/initiatives.svg +1 -87
- data/app/assets/images/decidim/initiatives/icon.svg +1 -3
- data/app/assets/javascripts/decidim/initiatives/admin/initiatives_types.js.es6 +18 -0
- data/app/assets/stylesheet/decidim/initiatives/initiatives-votes.css.scss +0 -1
- data/app/assets/stylesheet/decidim/initiatives/initiatives.scss +6 -8
- data/app/assets/stylesheet/decidim/initiatives/popularity_item.css.scss +0 -1
- data/app/assets/stylesheet/decidim/initiatives/print-initiative.css.scss +0 -3
- data/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives/show.erb +4 -3
- data/app/cells/decidim/initiatives/initiative_m_cell.rb +25 -0
- data/app/cells/decidim/initiatives_votes/vote/show.erb +12 -9
- data/app/cells/decidim/initiatives_votes/vote_cell.rb +7 -0
- data/app/commands/decidim/initiatives/admin/create_initiative_type.rb +6 -1
- data/app/commands/decidim/initiatives/admin/send_initiative_to_technical_validation.rb +17 -0
- data/app/commands/decidim/initiatives/admin/update_initiative.rb +29 -10
- data/app/commands/decidim/initiatives/admin/update_initiative_type.rb +6 -1
- data/app/commands/decidim/initiatives/attachment_methods.rb +37 -0
- data/app/commands/decidim/initiatives/create_initiative.rb +25 -3
- data/app/commands/decidim/initiatives/unvote_initiative.rb +4 -10
- data/app/commands/decidim/initiatives/vote_initiative.rb +47 -31
- data/app/controllers/concerns/decidim/initiatives/admin/filterable.rb +51 -0
- data/app/controllers/concerns/decidim/initiatives/orderable.rb +3 -1
- data/app/controllers/concerns/decidim/initiatives/single_initiative_type.rb +26 -0
- data/app/controllers/decidim/initiatives/admin/answers_controller.rb +2 -3
- data/app/controllers/decidim/initiatives/admin/initiatives_controller.rb +28 -15
- data/app/controllers/decidim/initiatives/create_initiative_controller.rb +36 -6
- data/app/controllers/decidim/initiatives/initiative_signatures_controller.rb +19 -23
- data/app/controllers/decidim/initiatives/initiative_votes_controller.rb +11 -5
- data/app/controllers/decidim/initiatives/initiatives_controller.rb +28 -13
- data/app/controllers/decidim/initiatives/initiatives_type_scopes_controller.rb +9 -1
- data/app/controllers/decidim/initiatives/versions_controller.rb +20 -0
- data/app/controllers/decidim/initiatives/{initiative_widgets_controller.rb → widgets_controller.rb} +2 -2
- data/app/events/decidim/initiatives/admin/initiative_sent_to_technical_validation_event.rb +21 -0
- data/app/events/decidim/initiatives/admin/support_threshold_reached_event.rb +13 -0
- data/app/forms/decidim/initiatives/admin/initiative_form.rb +49 -7
- data/app/forms/decidim/initiatives/admin/initiative_type_form.rb +8 -1
- data/app/forms/decidim/initiatives/initiative_form.rb +56 -1
- data/app/forms/decidim/initiatives/vote_form.rb +133 -76
- data/app/helpers/decidim/initiatives/application_helper.rb +104 -0
- data/app/helpers/decidim/initiatives/initiative_helper.rb +13 -0
- data/app/helpers/decidim/initiatives/initiatives_helper.rb +10 -0
- data/app/jobs/decidim/initiatives/export_initiatives_job.rb +25 -0
- data/app/mailers/decidim/initiatives/initiatives_mailer.rb +0 -21
- data/app/models/concerns/decidim/initiatives/has_area.rb +30 -0
- data/app/models/decidim/initiative.rb +184 -44
- data/app/models/decidim/initiatives_type.rb +5 -2
- data/app/models/decidim/initiatives_type_scope.rb +5 -1
- data/app/models/decidim/initiatives_vote.rb +19 -23
- data/app/permissions/decidim/initiatives/admin/permissions.rb +19 -8
- data/app/permissions/decidim/initiatives/permissions.rb +37 -14
- data/app/presenters/decidim/initiatives/initiative_stats_presenter.rb +1 -5
- data/app/queries/decidim/initiatives/admin/manageable_initiatives.rb +7 -39
- data/app/serializers/decidim/initiatives/initiative_serializer.rb +32 -0
- data/app/services/decidim/initiatives/diff_renderer.rb +18 -0
- data/app/services/decidim/initiatives/initiative_search.rb +59 -15
- data/app/services/decidim/initiatives/status_change_notifier.rb +4 -5
- data/app/types/decidim/initiatives/initiative_api_type.rb +26 -0
- data/app/types/decidim/initiatives/initiative_committee_member_type.rb +18 -0
- data/app/types/decidim/initiatives/initiative_type.rb +42 -0
- data/app/views/decidim/initiatives/admin/answers/_info_initiative.html.erb +1 -1
- data/app/views/decidim/initiatives/admin/exports/_dropdown.html.erb +8 -0
- data/app/views/decidim/initiatives/admin/initiatives/_form.html.erb +59 -14
- data/app/views/decidim/initiatives/admin/initiatives/_initiative_attachments.erb +43 -0
- data/app/views/decidim/initiatives/admin/initiatives/export_pdf_signatures.pdf.erb +12 -9
- data/app/views/decidim/initiatives/admin/initiatives/index.html.erb +10 -45
- data/app/views/decidim/initiatives/admin/initiatives_types/_form.html.erb +47 -10
- data/app/views/decidim/initiatives/admin/initiatives_types/_initiative_type_scopes.html.erb +28 -25
- data/app/views/decidim/initiatives/create_initiative/fill_data.html.erb +46 -10
- data/app/views/decidim/initiatives/create_initiative/finish.html.erb +17 -10
- data/app/views/decidim/initiatives/create_initiative/previous_form.html.erb +2 -1
- data/app/views/decidim/initiatives/create_initiative/promotal_committee.html.erb +1 -1
- data/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb +1 -2
- data/app/views/decidim/initiatives/create_initiative/show_similar_initiatives.html.erb +1 -1
- data/app/views/decidim/initiatives/initiative_signatures/fill_personal_data.html.erb +1 -1
- data/app/views/decidim/initiatives/initiative_signatures/update_buttons_and_counters.js.erb +1 -1
- data/app/views/decidim/initiatives/initiative_votes/update_buttons_and_counters.js.erb +1 -1
- data/app/views/decidim/initiatives/initiatives/_author.html.erb +1 -1
- data/app/views/decidim/initiatives/initiatives/_filters.html.erb +16 -28
- data/app/views/decidim/initiatives/initiatives/_index_header.html.erb +39 -5
- data/app/views/decidim/initiatives/initiatives/_initiatives.html.erb +11 -1
- data/app/views/decidim/initiatives/initiatives/_interactions.html.erb +2 -3
- data/app/views/decidim/initiatives/initiatives/_progress_bar.html.erb +24 -9
- data/app/views/decidim/initiatives/initiatives/_tags.html.erb +3 -0
- data/app/views/decidim/initiatives/initiatives/_vote_cabin.html.erb +1 -13
- data/app/views/decidim/initiatives/initiatives/index.html.erb +1 -1
- data/app/views/decidim/initiatives/initiatives/show.html.erb +2 -3
- data/app/views/decidim/initiatives/versions/index.html.erb +8 -0
- data/app/views/decidim/initiatives/versions/show.html.erb +10 -0
- data/app/views/layouts/decidim/_initiative_creation_header.html.erb +2 -1
- data/app/views/layouts/decidim/_initiative_header.html.erb +2 -1
- data/app/views/layouts/decidim/_initiative_signature_creation_header.html.erb +1 -1
- data/app/views/layouts/decidim/initiative.html.erb +1 -0
- data/app/views/layouts/decidim/initiative_creation.html.erb +1 -2
- data/app/views/layouts/decidim/initiative_signature_creation.html.erb +2 -2
- data/config/locales/am-ET.yml +1 -0
- data/config/locales/ar.yml +12 -21
- data/config/locales/bg-BG.yml +13 -0
- data/config/locales/bg.yml +13 -0
- data/config/locales/ca.yml +99 -21
- data/config/locales/cs.yml +110 -32
- data/config/locales/da-DK.yml +1 -0
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +75 -21
- data/config/locales/el.yml +525 -0
- data/config/locales/en.yml +102 -24
- data/config/locales/eo.yml +1 -0
- data/config/locales/es-MX.yml +99 -21
- data/config/locales/es-PY.yml +99 -21
- data/config/locales/es.yml +103 -25
- data/config/locales/et-EE.yml +1 -0
- data/config/locales/et.yml +1 -0
- data/config/locales/eu.yml +4 -21
- data/config/locales/fi-plain.yml +99 -21
- data/config/locales/fi.yml +117 -39
- data/config/locales/fr-CA.yml +557 -0
- data/config/locales/fr.yml +101 -23
- data/config/locales/ga-IE.yml +1 -0
- data/config/locales/gl.yml +4 -21
- data/config/locales/hr-HR.yml +1 -0
- data/config/locales/hr.yml +1 -0
- data/config/locales/hu.yml +27 -21
- data/config/locales/id-ID.yml +4 -21
- data/config/locales/is-IS.yml +4 -17
- data/config/locales/is.yml +251 -0
- data/config/locales/it.yml +116 -61
- data/config/locales/ja-JP.yml +529 -0
- data/config/locales/ja.yml +549 -0
- data/config/locales/ko-KR.yml +1 -0
- data/config/locales/ko.yml +1 -0
- data/config/locales/lt-LT.yml +1 -0
- data/config/locales/lt.yml +1 -0
- data/config/locales/lv.yml +525 -0
- data/config/locales/mt-MT.yml +1 -0
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +76 -21
- data/config/locales/no.yml +62 -31
- data/config/locales/om-ET.yml +1 -0
- data/config/locales/pl.yml +260 -189
- data/config/locales/pt-BR.yml +5 -22
- data/config/locales/pt.yml +231 -179
- data/config/locales/ro-RO.yml +533 -0
- data/config/locales/ru.yml +4 -21
- data/config/locales/sk-SK.yml +468 -0
- data/config/locales/sk.yml +458 -0
- data/config/locales/sl.yml +24 -0
- data/config/locales/so-SO.yml +1 -0
- data/config/locales/sr-CS.yml +8 -0
- data/config/locales/sv.yml +102 -31
- data/config/locales/ti-ER.yml +1 -0
- data/config/locales/tr-TR.yml +4 -21
- data/config/locales/uk.yml +4 -21
- data/config/locales/vi-VN.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +549 -0
- data/config/locales/zh-TW.yml +1 -0
- data/db/migrate/20191106144259_add_settings_to_initiatives_types.rb +8 -0
- data/db/migrate/20191107134847_add_scopes_to_initiatives_votes.rb +28 -0
- data/db/migrate/20191116170841_allow_multiple_initiative_votes_counter_caches.rb +32 -0
- data/db/migrate/20191118105634_allow_multiple_offline_votes.rb +34 -0
- data/db/migrate/20200320105920_index_foreign_keys_in_decidim_initiatives.rb +8 -0
- data/db/migrate/20200320105921_index_foreign_keys_in_decidim_initiatives_votes.rb +8 -0
- data/db/migrate/20200417120551_add_custom_signature_end_time_option.rb +7 -0
- data/db/migrate/20200424110930_add_attachments_enabled_option.rb +7 -0
- data/db/migrate/20200514085422_add_area_to_initiatives.rb +7 -0
- data/db/migrate/20200514102631_add_area_enabled_option_to_initiatives.rb +7 -0
- data/db/migrate/20200528151456_remove_user_groups_from_initiative_votes.rb +7 -0
- data/db/migrate/20200827154214_add_commentable_counter_cache_to_initiatives.rb +9 -0
- data/db/seeds/city.jpeg +0 -0
- data/db/seeds/city2.jpeg +0 -0
- data/lib/decidim/api/initiative_type_interface.rb +13 -0
- data/lib/decidim/initiatives/admin_engine.rb +5 -0
- data/lib/decidim/initiatives/api.rb +7 -0
- data/lib/decidim/initiatives/engine.rb +11 -2
- data/lib/decidim/initiatives/participatory_space.rb +18 -1
- data/lib/decidim/initiatives/query_extensions.rb +40 -0
- data/lib/decidim/initiatives/test/factories.rb +51 -4
- data/lib/decidim/initiatives/version.rb +1 -1
- data/lib/tasks/decidim_initiatives.rake +1 -3
- metadata +92 -21
- data/app/views/decidim/initiatives/initiative_widgets/show.html.erb +0 -4
- data/app/views/decidim/initiatives/initiatives/_supports.html.erb +0 -22
- data/app/views/decidim/initiatives/initiatives/signature_identities.html.erb +0 -42
- data/app/views/decidim/initiatives/initiatives_mailer/notify_validating_request.html.erb +0 -3
@@ -4,6 +4,9 @@ module Decidim
|
|
4
4
|
# Initiative type.
|
5
5
|
class InitiativesType < ApplicationRecord
|
6
6
|
include Decidim::HasResourcePermission
|
7
|
+
include Decidim::TranslatableResource
|
8
|
+
|
9
|
+
translatable_fields :title, :description, :extra_fields_legal_information
|
7
10
|
|
8
11
|
belongs_to :organization,
|
9
12
|
foreign_key: "decidim_organization_id",
|
@@ -21,8 +24,8 @@ module Decidim
|
|
21
24
|
|
22
25
|
enum signature_type: [:online, :offline, :any], _suffix: true
|
23
26
|
|
24
|
-
validates :signature_type, presence: true
|
25
|
-
validates :
|
27
|
+
validates :title, :description, :signature_type, presence: true
|
28
|
+
validates :document_number_authorization_handler, presence: true, if: ->(form) { form.collect_user_extra_fields? }
|
26
29
|
|
27
30
|
mount_uploader :banner_image, Decidim::BannerImageUploader
|
28
31
|
|
@@ -25,8 +25,12 @@ module Decidim
|
|
25
25
|
greater_than: 0
|
26
26
|
}
|
27
27
|
|
28
|
+
def global_scope?
|
29
|
+
decidim_scopes_id.nil?
|
30
|
+
end
|
31
|
+
|
28
32
|
def scope_name
|
29
|
-
return { I18n.locale.to_s => I18n.t("decidim.scopes.global") } if
|
33
|
+
return { I18n.locale.to_s => I18n.t("decidim.scopes.global") } if global_scope?
|
30
34
|
|
31
35
|
scope&.name.presence || { I18n.locale.to_s => I18n.t("decidim.initiatives.unavailable_scope") }
|
32
36
|
end
|
@@ -11,37 +11,43 @@ module Decidim
|
|
11
11
|
foreign_key: "decidim_author_id",
|
12
12
|
class_name: "Decidim::User"
|
13
13
|
|
14
|
-
belongs_to :user_group,
|
15
|
-
foreign_key: "decidim_user_group_id",
|
16
|
-
class_name: "Decidim::UserGroup",
|
17
|
-
optional: true
|
18
|
-
|
19
14
|
belongs_to :initiative,
|
20
15
|
foreign_key: "decidim_initiative_id",
|
21
16
|
class_name: "Decidim::Initiative",
|
22
17
|
inverse_of: :votes
|
23
18
|
|
24
|
-
|
19
|
+
belongs_to :scope,
|
20
|
+
foreign_key: "decidim_scope_id",
|
21
|
+
class_name: "Decidim::Scope",
|
22
|
+
optional: true
|
23
|
+
|
24
|
+
validates :initiative, uniqueness: { scope: [:author, :scope] }
|
25
|
+
validates :initiative, uniqueness: { scope: [:hash_id, :scope] }
|
25
26
|
|
26
27
|
after_commit :update_counter_cache, on: [:create, :destroy]
|
27
28
|
|
28
|
-
scope :
|
29
|
-
scope :votes, -> { where(decidim_user_group_id: nil) }
|
29
|
+
scope :for_scope, ->(scope) { where(scope: scope) }
|
30
30
|
|
31
|
-
#
|
31
|
+
# Public: Generates a hashed representation of the initiative support.
|
32
32
|
#
|
33
|
-
#
|
33
|
+
# Used when exporting the votes as CSV.
|
34
34
|
def sha1
|
35
|
-
return unless decidim_user_group_id.nil?
|
36
|
-
|
37
35
|
title = translated_attribute(initiative.title)
|
38
36
|
description = translated_attribute(initiative.description)
|
39
37
|
|
40
38
|
Digest::SHA1.hexdigest "#{authorization_unique_id}#{title}#{description}"
|
41
39
|
end
|
42
40
|
|
41
|
+
def decrypted_metadata
|
42
|
+
@decrypted_metadata ||= encrypted_metadata ? encryptor.decrypt(encrypted_metadata) : {}
|
43
|
+
end
|
44
|
+
|
43
45
|
private
|
44
46
|
|
47
|
+
def encryptor
|
48
|
+
@encryptor ||= Decidim::Initiatives::DataEncryptor.new(secret: "personal user metadata")
|
49
|
+
end
|
50
|
+
|
45
51
|
def authorization_unique_id
|
46
52
|
first_authorization = Decidim::Initiatives::UserAuthorizations
|
47
53
|
.for(author)
|
@@ -51,17 +57,7 @@ module Decidim
|
|
51
57
|
end
|
52
58
|
|
53
59
|
def update_counter_cache
|
54
|
-
initiative.
|
55
|
-
.votes
|
56
|
-
.where(decidim_initiative_id: initiative.id)
|
57
|
-
.count
|
58
|
-
|
59
|
-
initiative.initiative_supports_count = Decidim::InitiativesVote
|
60
|
-
.supports
|
61
|
-
.where(decidim_initiative_id: initiative.id)
|
62
|
-
.count
|
63
|
-
|
64
|
-
initiative.save
|
60
|
+
initiative.update_online_votes_counters
|
65
61
|
end
|
66
62
|
end
|
67
63
|
end
|
@@ -35,6 +35,7 @@ module Decidim
|
|
35
35
|
initiative_type_scope_action?
|
36
36
|
initiative_committee_action?
|
37
37
|
initiative_admin_user_action?
|
38
|
+
initiative_export_action?
|
38
39
|
moderator_action?
|
39
40
|
allow! if permission_action.subject == :attachment
|
40
41
|
|
@@ -69,6 +70,8 @@ module Decidim
|
|
69
70
|
def attachment_action?
|
70
71
|
return unless permission_action.subject == :attachment
|
71
72
|
|
73
|
+
disallow! && return unless initiative.attachments_enabled?
|
74
|
+
|
72
75
|
attachment = context.fetch(:attachment, nil)
|
73
76
|
attached = attachment&.attached_to
|
74
77
|
|
@@ -144,18 +147,24 @@ module Decidim
|
|
144
147
|
when :accept
|
145
148
|
allowed = initiative.published? &&
|
146
149
|
initiative.signature_end_date < Date.current &&
|
147
|
-
initiative.
|
150
|
+
initiative.supports_goal_reached?
|
148
151
|
toggle_allow(allowed)
|
149
152
|
when :reject
|
150
153
|
allowed = initiative.published? &&
|
151
154
|
initiative.signature_end_date < Date.current &&
|
152
|
-
initiative.
|
155
|
+
!initiative.supports_goal_reached?
|
153
156
|
toggle_allow(allowed)
|
157
|
+
when :send_to_technical_validation
|
158
|
+
toggle_allow(allowed_to_send_to_technical_validation?)
|
154
159
|
else
|
155
160
|
allow!
|
156
161
|
end
|
157
162
|
end
|
158
163
|
|
164
|
+
def initiative_export_action?
|
165
|
+
allow! if permission_action.subject == :initiatives && permission_action.action == :export
|
166
|
+
end
|
167
|
+
|
159
168
|
def moderator_action?
|
160
169
|
return unless permission_action.subject == :moderation
|
161
170
|
|
@@ -180,18 +189,20 @@ module Decidim
|
|
180
189
|
when :update
|
181
190
|
toggle_allow(initiative.created?)
|
182
191
|
when :send_to_technical_validation
|
183
|
-
|
184
|
-
!initiative.created_by_individual? ||
|
185
|
-
initiative.enough_committee_members?
|
186
|
-
)
|
187
|
-
|
188
|
-
toggle_allow(allowed)
|
192
|
+
toggle_allow(allowed_to_send_to_technical_validation?)
|
189
193
|
when :manage_membership
|
190
194
|
toggle_allow(initiative.promoting_committee_enabled?)
|
191
195
|
else
|
192
196
|
disallow!
|
193
197
|
end
|
194
198
|
end
|
199
|
+
|
200
|
+
def allowed_to_send_to_technical_validation?
|
201
|
+
initiative.created? && (
|
202
|
+
!initiative.created_by_individual? ||
|
203
|
+
initiative.enough_committee_members?
|
204
|
+
)
|
205
|
+
end
|
195
206
|
end
|
196
207
|
end
|
197
208
|
end
|
@@ -18,16 +18,18 @@ module Decidim
|
|
18
18
|
list_public_initiatives?
|
19
19
|
read_public_initiative?
|
20
20
|
search_initiative_types_and_scopes?
|
21
|
+
request_membership?
|
21
22
|
|
22
23
|
return permission_action unless user
|
23
24
|
|
24
25
|
create_initiative?
|
25
|
-
request_membership?
|
26
26
|
|
27
27
|
vote_initiative?
|
28
28
|
sign_initiative?
|
29
29
|
unvote_initiative?
|
30
30
|
|
31
|
+
initiative_attachment?
|
32
|
+
|
31
33
|
permission_action
|
32
34
|
end
|
33
35
|
|
@@ -37,6 +39,10 @@ module Decidim
|
|
37
39
|
@initiative ||= context.fetch(:initiative, nil) || context.fetch(:current_participatory_space, nil)
|
38
40
|
end
|
39
41
|
|
42
|
+
def initiative_type
|
43
|
+
@initiative_type ||= context[:initiative_type]
|
44
|
+
end
|
45
|
+
|
40
46
|
def list_public_initiatives?
|
41
47
|
allow! if permission_action.subject == :initiative &&
|
42
48
|
permission_action.action == :list
|
@@ -78,16 +84,28 @@ module Decidim
|
|
78
84
|
return unless permission_action.subject == :initiative &&
|
79
85
|
permission_action.action == :request_membership
|
80
86
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
87
|
+
toggle_allow(can_request_membership?)
|
88
|
+
end
|
89
|
+
|
90
|
+
def can_request_membership?
|
91
|
+
return access_request_without_user? if user.blank?
|
92
|
+
|
93
|
+
access_request_membership?
|
94
|
+
end
|
89
95
|
|
90
|
-
|
96
|
+
def access_request_without_user?
|
97
|
+
!initiative.published? && initiative.promoting_committee_enabled? || Decidim::Initiatives.do_not_require_authorization
|
98
|
+
end
|
99
|
+
|
100
|
+
def access_request_membership?
|
101
|
+
!initiative.published? &&
|
102
|
+
initiative.promoting_committee_enabled? &&
|
103
|
+
!initiative.has_authorship?(user) &&
|
104
|
+
(
|
105
|
+
Decidim::Initiatives.do_not_require_authorization ||
|
106
|
+
UserAuthorizations.for(user).any? ||
|
107
|
+
Decidim::UserGroups::ManageableUserGroups.for(user).verified.any?
|
108
|
+
)
|
91
109
|
end
|
92
110
|
|
93
111
|
def has_initiatives?
|
@@ -124,13 +142,19 @@ module Decidim
|
|
124
142
|
|
125
143
|
can_unvote = initiative.accepts_online_unvotes? &&
|
126
144
|
initiative.organization&.id == user.organization&.id &&
|
127
|
-
initiative.votes.where(
|
128
|
-
(can_user_support?(initiative) || Decidim::UserGroups::ManageableUserGroups.for(user).verified.any?) &&
|
145
|
+
initiative.votes.where(author: user).any? &&
|
129
146
|
authorized?(:vote, resource: initiative, permissions_holder: initiative.type)
|
130
147
|
|
131
148
|
toggle_allow(can_unvote)
|
132
149
|
end
|
133
150
|
|
151
|
+
def initiative_attachment?
|
152
|
+
return unless permission_action.action == :add_attachment &&
|
153
|
+
permission_action.subject == :initiative
|
154
|
+
|
155
|
+
toggle_allow(initiative_type.attachments_enabled?)
|
156
|
+
end
|
157
|
+
|
134
158
|
def public_report_content_action?
|
135
159
|
return unless permission_action.action == :create &&
|
136
160
|
permission_action.subject == :moderation
|
@@ -155,8 +179,7 @@ module Decidim
|
|
155
179
|
def can_vote?
|
156
180
|
initiative.votes_enabled? &&
|
157
181
|
initiative.organization&.id == user.organization&.id &&
|
158
|
-
initiative.votes.where(
|
159
|
-
(can_user_support?(initiative) || Decidim::UserGroups::ManageableUserGroups.for(user).verified.any?) &&
|
182
|
+
initiative.votes.where(author: user).empty? &&
|
160
183
|
authorized?(:vote, resource: initiative, permissions_holder: initiative.type)
|
161
184
|
end
|
162
185
|
|
@@ -6,16 +6,12 @@ module Decidim
|
|
6
6
|
class InitiativeStatsPresenter < Rectify::Presenter
|
7
7
|
attribute :initiative, Decidim::Initiative
|
8
8
|
|
9
|
-
def supports_count
|
10
|
-
initiative.initiative_supports_count
|
11
|
-
end
|
12
|
-
|
13
9
|
def comments_count
|
14
10
|
Rails.cache.fetch(
|
15
11
|
"initiative/#{initiative.id}/comments_count",
|
16
12
|
expires_in: Decidim::Initiatives.stats_cache_expiration_time
|
17
13
|
) do
|
18
|
-
|
14
|
+
initiative.comments_count
|
19
15
|
end
|
20
16
|
end
|
21
17
|
|
@@ -7,57 +7,25 @@ module Decidim
|
|
7
7
|
# Regular users will get only their initiatives. Administrators will
|
8
8
|
# retrieve all initiatives.
|
9
9
|
class ManageableInitiatives < Rectify::Query
|
10
|
-
attr_reader :organization, :user, :q, :state
|
11
|
-
|
12
10
|
# Syntactic sugar to initialize the class and return the queried objects
|
13
11
|
#
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
# state - String
|
18
|
-
def self.for(organization, user, query, state)
|
19
|
-
new(organization, user, query, state).query
|
12
|
+
# user - Decidim::User
|
13
|
+
def self.for(user)
|
14
|
+
new(user).query
|
20
15
|
end
|
21
16
|
|
22
17
|
# Initializes the class.
|
23
18
|
#
|
24
|
-
#
|
25
|
-
|
26
|
-
# query - String
|
27
|
-
# state - String
|
28
|
-
def initialize(organization, user, query, state)
|
29
|
-
@organization = organization
|
19
|
+
# user - Decidim::User
|
20
|
+
def initialize(user)
|
30
21
|
@user = user
|
31
|
-
@q = query
|
32
|
-
@state = state
|
33
22
|
end
|
34
23
|
|
35
24
|
# Retrieves all initiatives / Initiatives created by the user.
|
36
25
|
def query
|
37
|
-
if user.admin?
|
38
|
-
base = Initiative
|
39
|
-
.where(organization: organization)
|
40
|
-
.with_state(state)
|
41
|
-
else
|
42
|
-
ids = InitiativesCreated.by(user).with_state(state).pluck(:id)
|
43
|
-
ids += InitiativesPromoted.by(user).with_state(state).pluck(:id)
|
44
|
-
base = Initiative.where(id: ids)
|
45
|
-
end
|
46
|
-
|
47
|
-
return base if q.blank?
|
48
|
-
|
49
|
-
organization.available_locales.each_with_index do |loc, index|
|
50
|
-
base = if index.zero?
|
51
|
-
base.where("title->>? ilike ?", loc, "%#{q}%")
|
52
|
-
.or(Initiative.where("description->>? ilike ?", loc, "%#{q}%"))
|
53
|
-
else
|
54
|
-
base
|
55
|
-
.or(Initiative.where("title->>? ilike ?", loc, "%#{q}%"))
|
56
|
-
.or(Initiative.where("description->>? ilike ?", loc, "%#{q}%"))
|
57
|
-
end
|
58
|
-
end
|
26
|
+
return Initiative.where(organization: @user.organization) if @user.admin?
|
59
27
|
|
60
|
-
|
28
|
+
Initiative.where(id: InitiativesCreated.by(@user) + InitiativesPromoted.by(@user))
|
61
29
|
end
|
62
30
|
end
|
63
31
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Initiatives
|
5
|
+
class InitiativeSerializer < Decidim::Exporters::Serializer
|
6
|
+
# Serializes an inititative
|
7
|
+
def serialize
|
8
|
+
{
|
9
|
+
id: resource.id,
|
10
|
+
title: resource.title,
|
11
|
+
description: resource.description,
|
12
|
+
state: resource.state,
|
13
|
+
created_at: resource.created_at,
|
14
|
+
published_at: resource.published_at,
|
15
|
+
signature_end_date: resource.signature_end_date,
|
16
|
+
signature_type: resource.signature_type,
|
17
|
+
signatures: resource.supports_count,
|
18
|
+
scope: {
|
19
|
+
name: resource.scope&.name
|
20
|
+
},
|
21
|
+
type: {
|
22
|
+
title: resource.type&.title
|
23
|
+
},
|
24
|
+
authors: {
|
25
|
+
id: resource.author_users.map(&:id),
|
26
|
+
name: resource.author_users.map(&:name)
|
27
|
+
}
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Initiatives
|
5
|
+
class DiffRenderer < BaseDiffRenderer
|
6
|
+
private
|
7
|
+
|
8
|
+
# Lists which attributes will be diffable and how they should be rendered.
|
9
|
+
def attribute_types
|
10
|
+
{
|
11
|
+
description: :i18n_html,
|
12
|
+
title: :i18n,
|
13
|
+
state: :string
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -16,7 +16,9 @@ module Decidim
|
|
16
16
|
def base_query
|
17
17
|
Decidim::Initiative
|
18
18
|
.includes(scoped_type: [:scope])
|
19
|
+
.joins("JOIN decidim_users ON decidim_users.id = decidim_initiatives.decidim_author_id")
|
19
20
|
.where(organization: options[:organization])
|
21
|
+
.published
|
20
22
|
end
|
21
23
|
|
22
24
|
# Handle the search_text filter
|
@@ -29,22 +31,38 @@ module Decidim
|
|
29
31
|
"%#{search_text}%"
|
30
32
|
)
|
31
33
|
)
|
34
|
+
.or(
|
35
|
+
query.where(
|
36
|
+
"cast(decidim_initiatives.id as text) ILIKE ?", "%#{search_text}%"
|
37
|
+
)
|
38
|
+
)
|
39
|
+
.or(
|
40
|
+
query.where(
|
41
|
+
"decidim_users.name ILIKE ? OR decidim_users.nickname ILIKE ?", "%#{search_text}%", "%#{search_text}%"
|
42
|
+
)
|
43
|
+
)
|
32
44
|
end
|
33
45
|
|
34
46
|
# Handle the state filter
|
35
47
|
def search_state
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
48
|
+
accepted = state.member?("accepted") ? query.accepted : nil
|
49
|
+
rejected = state.member?("rejected") ? query.rejected : nil
|
50
|
+
answered = state.member?("answered") ? query.answered : nil
|
51
|
+
open = state.member?("open") ? query.open : nil
|
52
|
+
closed = state.member?("closed") ? query.closed : nil
|
53
|
+
|
54
|
+
query
|
55
|
+
.where(id: accepted)
|
56
|
+
.or(query.where(id: rejected))
|
57
|
+
.or(query.where(id: answered))
|
58
|
+
.or(query.where(id: open))
|
59
|
+
.or(query.where(id: closed))
|
42
60
|
end
|
43
61
|
|
44
|
-
def
|
45
|
-
return query if
|
62
|
+
def search_type_id
|
63
|
+
return query if type_ids.include?("all")
|
46
64
|
|
47
|
-
types = InitiativesTypeScope.where(decidim_initiatives_types_id:
|
65
|
+
types = InitiativesTypeScope.where(decidim_initiatives_types_id: type_ids).pluck(:id)
|
48
66
|
|
49
67
|
query.where(scoped_type: types)
|
50
68
|
end
|
@@ -58,13 +76,39 @@ module Decidim
|
|
58
76
|
end
|
59
77
|
|
60
78
|
def search_scope_id
|
61
|
-
return if
|
79
|
+
return query if scope_ids.include?("all")
|
62
80
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
81
|
+
clean_scope_ids = scope_ids
|
82
|
+
|
83
|
+
conditions = []
|
84
|
+
conditions << "decidim_initiatives_type_scopes.decidim_scopes_id IS NULL" if clean_scope_ids.delete("global")
|
85
|
+
conditions.concat(["? = ANY(decidim_scopes.part_of)"] * clean_scope_ids.count) if clean_scope_ids.any?
|
86
|
+
|
87
|
+
query.joins(:scoped_type).references(:decidim_scopes).where(conditions.join(" OR "), *clean_scope_ids.map(&:to_i))
|
88
|
+
end
|
89
|
+
|
90
|
+
def search_area_id
|
91
|
+
return query if area_ids.include?("all")
|
92
|
+
|
93
|
+
query.where(decidim_area_id: area_ids)
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
# Private: Returns an array with checked type ids.
|
99
|
+
def type_ids
|
100
|
+
[type_id].flatten
|
101
|
+
end
|
102
|
+
|
103
|
+
# Private: Returns an array with checked scope ids.
|
104
|
+
def scope_ids
|
105
|
+
[scope_id].flatten
|
106
|
+
end
|
107
|
+
|
108
|
+
# Private: Returns an array with checked area ids, handling area_types which are coded as its
|
109
|
+
# areas ids joined by _.
|
110
|
+
def area_ids
|
111
|
+
area_id.map { |id| id.split("_") }.flatten.uniq
|
68
112
|
end
|
69
113
|
end
|
70
114
|
end
|