decidim-proposals 0.25.2 → 0.26.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/cells/decidim/proposals/collaborative_draft_m_cell.rb +1 -1
- data/app/cells/decidim/proposals/cost_report_cell.rb +3 -3
- data/app/cells/decidim/proposals/participatory_text_proposal_cell.rb +1 -1
- data/app/cells/decidim/proposals/proposal_m_cell.rb +4 -5
- data/app/cells/decidim/proposals/proposals_picker_cell.rb +7 -5
- data/app/commands/decidim/proposals/update_proposal.rb +3 -2
- data/app/controllers/concerns/decidim/proposals/orderable.rb +21 -8
- data/app/controllers/decidim/proposals/admin/proposals_merges_controller.rb +4 -1
- data/app/controllers/decidim/proposals/admin/proposals_splits_controller.rb +4 -1
- data/app/controllers/decidim/proposals/proposals_controller.rb +2 -2
- data/app/events/decidim/proposals/proposal_mentioned_event.rb +8 -0
- data/app/events/decidim/proposals/publish_proposal_event.rb +26 -0
- data/app/forms/decidim/proposals/admin/proposals_file_import_form.rb +31 -0
- data/app/forms/decidim/proposals/admin/proposals_fork_form.rb +8 -3
- data/app/helpers/decidim/proposals/application_helper.rb +1 -6
- data/app/helpers/decidim/proposals/map_helper.rb +1 -1
- data/app/helpers/decidim/proposals/proposals_helper.rb +1 -1
- data/app/models/decidim/proposals/proposal.rb +3 -2
- data/app/packs/src/decidim/proposals/admin/proposals_picker.js +15 -0
- data/app/presenters/decidim/proposals/proposal_presenter.rb +2 -48
- data/app/queries/decidim/proposals/similar_proposals.rb +1 -1
- data/app/services/decidim/proposals/proposal_search.rb +9 -4
- data/app/views/decidim/proposals/admin/imports/_proposals_fields.html.erb +11 -0
- data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +7 -2
- data/app/views/decidim/proposals/collaborative_drafts/_edit_form_fields.html.erb +1 -1
- data/app/views/decidim/proposals/collaborative_drafts/_filters_small_view.html.erb +3 -3
- data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +2 -2
- data/app/views/decidim/proposals/proposals/_filters.html.erb +2 -0
- data/app/views/decidim/proposals/proposals/_filters_small_view.html.erb +3 -3
- data/app/views/decidim/proposals/proposals/_proposals.html.erb +18 -0
- data/app/views/decidim/proposals/proposals/index.html.erb +0 -5
- data/app/views/decidim/proposals/proposals/participatory_texts/_index.html.erb +2 -2
- data/config/brakeman.ignore +88 -0
- data/config/locales/ar.yml +0 -5
- data/config/locales/bg.yml +0 -2
- data/config/locales/ca.yml +1 -5
- data/config/locales/cs.yml +60 -5
- data/config/locales/de.yml +0 -5
- data/config/locales/el.yml +0 -5
- data/config/locales/en.yml +57 -6
- data/config/locales/es-MX.yml +0 -5
- data/config/locales/es-PY.yml +0 -5
- data/config/locales/es.yml +56 -5
- data/config/locales/eu.yml +38 -5
- data/config/locales/fi-plain.yml +54 -5
- data/config/locales/fi.yml +56 -5
- data/config/locales/fr-CA.yml +55 -5
- data/config/locales/fr.yml +55 -5
- data/config/locales/gl.yml +53 -5
- data/config/locales/hu.yml +0 -5
- data/config/locales/id-ID.yml +0 -4
- data/config/locales/is-IS.yml +0 -2
- data/config/locales/it.yml +13 -5
- data/config/locales/ja.yml +66 -18
- data/config/locales/lv.yml +0 -5
- data/config/locales/nl.yml +57 -5
- data/config/locales/no.yml +0 -5
- data/config/locales/pl.yml +0 -5
- data/config/locales/pt-BR.yml +1 -6
- data/config/locales/pt.yml +37 -5
- data/config/locales/ro-RO.yml +57 -6
- data/config/locales/ru.yml +0 -2
- data/config/locales/sk.yml +0 -5
- data/config/locales/sr-CS.yml +0 -1
- data/config/locales/sv.yml +54 -5
- data/config/locales/tr-TR.yml +0 -5
- data/config/locales/uk.yml +0 -2
- data/config/locales/val-ES.yml +1 -0
- data/config/locales/zh-CN.yml +0 -5
- data/lib/decidim/proposals/component.rb +37 -4
- data/lib/decidim/proposals/import/proposal_answer_creator.rb +95 -0
- data/lib/decidim/proposals/import/proposal_creator.rb +124 -0
- data/lib/decidim/proposals/import/proposals_answers_verifier.rb +29 -0
- data/lib/decidim/proposals/import/proposals_verifier.rb +16 -0
- data/lib/decidim/proposals/import.rb +12 -0
- data/lib/decidim/proposals/proposal_serializer.rb +6 -3
- data/lib/decidim/proposals/test/factories.rb +1 -9
- data/lib/decidim/proposals/version.rb +1 -1
- data/lib/decidim/proposals.rb +1 -1
- metadata +32 -24
- data/lib/decidim/proposals/proposal_creator.rb +0 -98
data/config/locales/tr-TR.yml
CHANGED
@@ -122,7 +122,6 @@ tr:
|
|
122
122
|
name: Teklifler
|
123
123
|
settings:
|
124
124
|
global:
|
125
|
-
allow_card_image: Kart resmine izin ver
|
126
125
|
amendments_enabled: Değişiklikler etkinleştirildi
|
127
126
|
amendments_enabled_help: Etkinse, her adım için Değişiklik özelliklerini yapılandırın.
|
128
127
|
amendments_wizard_help_text: Değişiklik Sihirbazı yardım metni
|
@@ -169,7 +168,6 @@ tr:
|
|
169
168
|
answers_with_costs: Teklif yanıtlarında maliyetleri etkinleştirin
|
170
169
|
automatic_hashtags: Tüm tekliflere etiketler eklendi
|
171
170
|
comments_blocked: Yorumlar engellendi
|
172
|
-
creation_enabled: Teklif oluşturma etkin
|
173
171
|
endorsements_blocked: Onaylar engellendi
|
174
172
|
endorsements_enabled: Onaylar etkin
|
175
173
|
proposal_answering_enabled: Teklif yanıtlama etkin
|
@@ -262,7 +260,6 @@ tr:
|
|
262
260
|
email_intro: '"%{resource_title}" teklifi takip ettiğiniz "%{participatory_space_title}" listesine eklendi.'
|
263
261
|
email_outro: Bu bildirimi, "%{participatory_space_title}" takip ettiğiniz için aldınız. Bir önceki bağlantıdan takip etmeyi bırakabilirsiniz.
|
264
262
|
email_subject: Yeni teklif "%{resource_title}" %{participatory_space_title} eklendi
|
265
|
-
notification_title: <a href="%{resource_path}">%{resource_title}</a> önerisi %{participatory_space_title} alanına eklendi
|
266
263
|
proposal_rejected:
|
267
264
|
affected_user:
|
268
265
|
email_intro: 'Teklifiniz "%{resource_title}" reddedildi. Cevabı bu sayfada okuyabilirsiniz:'
|
@@ -501,11 +498,9 @@ tr:
|
|
501
498
|
title: Teklifleri içe aktar
|
502
499
|
proposals_merges:
|
503
500
|
create:
|
504
|
-
invalid: Seçilen teklifler birleştirilirken bir hata oluştu.
|
505
501
|
success: Teklifler, yeni bir taneyle başarılı bir şekilde birleştirildi.
|
506
502
|
proposals_splits:
|
507
503
|
create:
|
508
|
-
invalid: Seçilen teklifleri bölerken bir sorun vardı.
|
509
504
|
success: Teklifleri başarılı bir şekilde yenilere ayırdı.
|
510
505
|
valuation_assignments:
|
511
506
|
create:
|
data/config/locales/uk.yml
CHANGED
@@ -82,7 +82,6 @@ uk:
|
|
82
82
|
step:
|
83
83
|
announcement: Оголошення
|
84
84
|
comments_blocked: Коментарі вимкнено
|
85
|
-
creation_enabled: Внесення пропозицій увімкнено
|
86
85
|
endorsements_blocked: Надання підтримки вимкнене
|
87
86
|
endorsements_enabled: Надання підтримки увімкнено
|
88
87
|
proposal_answering_enabled: Відповіді на пропозиції увімкнено
|
@@ -122,7 +121,6 @@ uk:
|
|
122
121
|
proposal_published_for_space:
|
123
122
|
email_intro: До "%{participatory_space_title}", за яким ви стежите, була додана пропозиція "%{resource_title}".
|
124
123
|
email_outro: Ви отримали це сповіщення, тому що ви стежите за "%{participatory_space_title}". Ви можете припинити стежити за ним, перейшовши за наведеним вище посиланням.
|
125
|
-
notification_title: До %{participatory_space_title} було додано пропозицію <a href="%{resource_path}">%{resource_title}</a>
|
126
124
|
proposal_rejected:
|
127
125
|
follower:
|
128
126
|
email_intro: 'Пропозиція "%{resource_title}" була відхилена. Ви можете прочитати відповідь на сторінці:'
|
@@ -0,0 +1 @@
|
|
1
|
+
val:
|
data/config/locales/zh-CN.yml
CHANGED
@@ -115,7 +115,6 @@ zh-CN:
|
|
115
115
|
name: 建议
|
116
116
|
settings:
|
117
117
|
global:
|
118
|
-
allow_card_image: 允许卡片图像
|
119
118
|
amendments_enabled: 修改已启用
|
120
119
|
amendments_enabled_help: 如果激活,配置每一步的修正功能。
|
121
120
|
amendments_wizard_help_text: 修正向导帮助文本
|
@@ -162,7 +161,6 @@ zh-CN:
|
|
162
161
|
answers_with_costs: 启用建议答案的成本
|
163
162
|
automatic_hashtags: 添加到所有建议的标签
|
164
163
|
comments_blocked: 评论已阻止
|
165
|
-
creation_enabled: 建议创建已启用
|
166
164
|
endorsements_blocked: 已阻止授权
|
167
165
|
endorsements_enabled: 授权已启用
|
168
166
|
proposal_answering_enabled: 建议答案已启用
|
@@ -248,7 +246,6 @@ zh-CN:
|
|
248
246
|
email_intro: 提议 "%{resource_title}" 已被添加到"%{participatory_space_title}",您正在关注它。
|
249
247
|
email_outro: 您收到此通知是因为您正在关注 "%{participatory_space_title}"。您可以停止收到跟随上一个链接的通知。
|
250
248
|
email_subject: 新提议 "%{resource_title}" 已添加到 %{participatory_space_title}
|
251
|
-
notification_title: 提议 <a href="%{resource_path}">%{resource_title}</a> 已被添加到 %{participatory_space_title}
|
252
249
|
proposal_rejected:
|
253
250
|
affected_user:
|
254
251
|
email_intro: '您的提议 "%{resource_title}" 已被拒绝。您可以在此页中读取答案:'
|
@@ -480,11 +477,9 @@ zh-CN:
|
|
480
477
|
select_states: 检查要导入的建议的状态
|
481
478
|
proposals_merges:
|
482
479
|
create:
|
483
|
-
invalid: 合并选定的建议时出现问题。
|
484
480
|
success: 成功地将提案合并为一个新提案。
|
485
481
|
proposals_splits:
|
486
482
|
create:
|
487
|
-
invalid: 在分割选定的建议时遇到问题。
|
488
483
|
success: 成功地将建议分成新的建议。
|
489
484
|
valuation_assignments:
|
490
485
|
create:
|
@@ -22,6 +22,8 @@ Decidim.register_component(:proposals) do |component|
|
|
22
22
|
|
23
23
|
component.permissions_class_name = "Decidim::Proposals::Permissions"
|
24
24
|
|
25
|
+
POSSIBLE_SORT_ORDERS = %w(default random recent most_endorsed most_voted most_commented most_followed with_more_authors).freeze
|
26
|
+
|
25
27
|
component.settings(:global) do |settings|
|
26
28
|
settings.attribute :scopes_enabled, type: :boolean, default: false
|
27
29
|
settings.attribute :scope_id, type: :scope
|
@@ -34,12 +36,12 @@ Decidim.register_component(:proposals) do |component|
|
|
34
36
|
settings.attribute :threshold_per_proposal, type: :integer, default: 0
|
35
37
|
settings.attribute :can_accumulate_supports_beyond_threshold, type: :boolean, default: false
|
36
38
|
settings.attribute :proposal_answering_enabled, type: :boolean, default: true
|
39
|
+
settings.attribute :default_sort_order, type: :select, default: "default", choices: -> { POSSIBLE_SORT_ORDERS }
|
37
40
|
settings.attribute :official_proposals_enabled, type: :boolean, default: true
|
38
41
|
settings.attribute :comments_enabled, type: :boolean, default: true
|
39
42
|
settings.attribute :comments_max_length, type: :integer, required: false
|
40
43
|
settings.attribute :geocoding_enabled, type: :boolean, default: false
|
41
44
|
settings.attribute :attachments_allowed, type: :boolean, default: false
|
42
|
-
settings.attribute :allow_card_image, type: :boolean, default: false
|
43
45
|
settings.attribute :resources_permissions_enabled, type: :boolean, default: true
|
44
46
|
settings.attribute :collaborative_drafts_enabled, type: :boolean, default: false
|
45
47
|
settings.attribute :participatory_texts_enabled,
|
@@ -65,6 +67,7 @@ Decidim.register_component(:proposals) do |component|
|
|
65
67
|
settings.attribute :comments_blocked, type: :boolean, default: false
|
66
68
|
settings.attribute :creation_enabled, type: :boolean
|
67
69
|
settings.attribute :proposal_answering_enabled, type: :boolean, default: true
|
70
|
+
settings.attribute :default_sort_order, type: :select, include_blank: true, choices: -> { POSSIBLE_SORT_ORDERS }
|
68
71
|
settings.attribute :publish_answers_immediately, type: :boolean, default: true
|
69
72
|
settings.attribute :answers_with_costs, type: :boolean, default: false
|
70
73
|
settings.attribute :amendment_creation_enabled, type: :boolean, default: true
|
@@ -128,7 +131,7 @@ Decidim.register_component(:proposals) do |component|
|
|
128
131
|
collection = Decidim::Proposals::Proposal
|
129
132
|
.published
|
130
133
|
.where(component: component_instance)
|
131
|
-
.includes(:category, :component)
|
134
|
+
.includes(:scope, :category, :component)
|
132
135
|
|
133
136
|
if space.user_roles(:valuator).where(user: user).any?
|
134
137
|
collection.with_valuation_assigned_to(user, space)
|
@@ -146,7 +149,7 @@ Decidim.register_component(:proposals) do |component|
|
|
146
149
|
exports.collection do |component_instance|
|
147
150
|
Decidim::Comments::Export.comments_for_resource(
|
148
151
|
Decidim::Proposals::Proposal, component_instance
|
149
|
-
)
|
152
|
+
).includes(:author, :user_group, root_commentable: { component: { participatory_space: :organization } })
|
150
153
|
end
|
151
154
|
|
152
155
|
exports.include_in_open_data = true
|
@@ -155,7 +158,37 @@ Decidim.register_component(:proposals) do |component|
|
|
155
158
|
end
|
156
159
|
|
157
160
|
component.imports :proposals do |imports|
|
158
|
-
imports.
|
161
|
+
imports.form_view = "decidim/proposals/admin/imports/proposals_fields"
|
162
|
+
imports.form_class_name = "Decidim::Proposals::Admin::ProposalsFileImportForm"
|
163
|
+
|
164
|
+
imports.messages do |msg|
|
165
|
+
msg.set(:resource_name) { |count: 1| I18n.t("decidim.proposals.admin.imports.resources.proposals", count: count) }
|
166
|
+
msg.set(:title) { I18n.t("decidim.proposals.admin.imports.title.proposals") }
|
167
|
+
msg.set(:label) { I18n.t("decidim.proposals.admin.imports.label.proposals") }
|
168
|
+
msg.set(:help) { I18n.t("decidim.proposals.admin.imports.help.proposals") }
|
169
|
+
end
|
170
|
+
|
171
|
+
imports.creator Decidim::Proposals::Import::ProposalCreator
|
172
|
+
end
|
173
|
+
|
174
|
+
component.imports :answers do |imports|
|
175
|
+
imports.messages do |msg|
|
176
|
+
msg.set(:resource_name) { |count: 1| I18n.t("decidim.proposals.admin.imports.resources.answers", count: count) }
|
177
|
+
msg.set(:title) { I18n.t("decidim.proposals.admin.imports.title.answers") }
|
178
|
+
msg.set(:label) { I18n.t("decidim.proposals.admin.imports.label.answers") }
|
179
|
+
msg.set(:help) { I18n.t("decidim.proposals.admin.imports.help.answers") }
|
180
|
+
end
|
181
|
+
|
182
|
+
imports.creator Decidim::Proposals::Import::ProposalAnswerCreator
|
183
|
+
imports.example do |import_component|
|
184
|
+
organization = import_component.organization
|
185
|
+
[
|
186
|
+
%w(id state) + organization.available_locales.map { |l| "answer/#{l}" },
|
187
|
+
[1, "accepted"] + organization.available_locales.map { "Example answer" },
|
188
|
+
[2, "rejected"] + organization.available_locales.map { "Example answer" },
|
189
|
+
[3, "evaluating"] + organization.available_locales.map { "Example answer" }
|
190
|
+
]
|
191
|
+
end
|
159
192
|
end
|
160
193
|
|
161
194
|
component.seeds do |participatory_space|
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
module Import
|
6
|
+
# This class is responsible for creating the imported proposal answers
|
7
|
+
# and must be included in proposals component's import manifest.
|
8
|
+
class ProposalAnswerCreator < Decidim::Admin::Import::Creator
|
9
|
+
POSSIBLE_ANSWER_STATES = %w(evaluating accepted rejected).freeze
|
10
|
+
|
11
|
+
# Retuns the resource class to be created with the provided data.
|
12
|
+
def self.resource_klass
|
13
|
+
Decidim::Proposals::Proposal
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns a verifier class to be used to verify the correctness of the
|
17
|
+
# import data.
|
18
|
+
def self.verifier_klass
|
19
|
+
Decidim::Proposals::Import::ProposalsAnswersVerifier
|
20
|
+
end
|
21
|
+
|
22
|
+
# Add answer to proposal
|
23
|
+
#
|
24
|
+
# Returns a proposal
|
25
|
+
def produce
|
26
|
+
resource
|
27
|
+
end
|
28
|
+
|
29
|
+
def finish!
|
30
|
+
Decidim.traceability.perform_action!(
|
31
|
+
"answer",
|
32
|
+
resource,
|
33
|
+
current_user
|
34
|
+
) do
|
35
|
+
resource.save!
|
36
|
+
end
|
37
|
+
notify(resource)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def resource
|
43
|
+
@resource ||= begin
|
44
|
+
proposal = Decidim::Proposals::Proposal.find_by(id: id)
|
45
|
+
return nil unless proposal
|
46
|
+
return nil if proposal.emendation?
|
47
|
+
|
48
|
+
if proposal.component != component
|
49
|
+
proposal.errors.add(:component, :invalid)
|
50
|
+
return proposal
|
51
|
+
end
|
52
|
+
|
53
|
+
proposal.answer = answer
|
54
|
+
proposal.answered_at = Time.current
|
55
|
+
if POSSIBLE_ANSWER_STATES.include?(state)
|
56
|
+
proposal.state = state
|
57
|
+
proposal.state_published_at = Time.current if component.current_settings.publish_answers_immediately?
|
58
|
+
else
|
59
|
+
proposal.errors.add(:state, :invalid)
|
60
|
+
end
|
61
|
+
proposal
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def id
|
66
|
+
data[:id].to_i
|
67
|
+
end
|
68
|
+
|
69
|
+
def state
|
70
|
+
data[:state]
|
71
|
+
end
|
72
|
+
|
73
|
+
def answer
|
74
|
+
locale_hasher("answer", available_locales)
|
75
|
+
end
|
76
|
+
|
77
|
+
def available_locales
|
78
|
+
@available_locales ||= component.participatory_space.organization.available_locales
|
79
|
+
end
|
80
|
+
|
81
|
+
def component
|
82
|
+
context[:current_component]
|
83
|
+
end
|
84
|
+
|
85
|
+
def current_user
|
86
|
+
context[:current_user]
|
87
|
+
end
|
88
|
+
|
89
|
+
def notify(proposal)
|
90
|
+
::Decidim::Proposals::Admin::NotifyProposalAnswer.call(proposal, proposal.state)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
module Import
|
6
|
+
# This class is responsible for creating the imported proposals
|
7
|
+
# and must be included in proposals component's import manifest.
|
8
|
+
class ProposalCreator < Decidim::Admin::Import::Creator
|
9
|
+
# Retuns the resource class to be created with the provided data.
|
10
|
+
def self.resource_klass
|
11
|
+
Decidim::Proposals::Proposal
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns a verifier class to be used to verify the correctness of the
|
15
|
+
# import data.
|
16
|
+
def self.verifier_klass
|
17
|
+
Decidim::Proposals::Import::ProposalsVerifier
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(data, context = nil)
|
21
|
+
@data = data.except(:id, "id")
|
22
|
+
@context = context
|
23
|
+
end
|
24
|
+
|
25
|
+
# Produces a proposal from parsed data
|
26
|
+
#
|
27
|
+
# Returns a proposal
|
28
|
+
def produce
|
29
|
+
resource.add_coauthor(context[:current_user], user_group: context[:user_group])
|
30
|
+
|
31
|
+
resource
|
32
|
+
end
|
33
|
+
|
34
|
+
# Saves the proposal
|
35
|
+
def finish!
|
36
|
+
super # resource.save!
|
37
|
+
notify(resource)
|
38
|
+
publish(resource)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def resource
|
44
|
+
@resource ||= Decidim::Proposals::Proposal.new(
|
45
|
+
category: category,
|
46
|
+
scope: scope,
|
47
|
+
title: title,
|
48
|
+
body: body,
|
49
|
+
address: address,
|
50
|
+
latitude: latitude,
|
51
|
+
longitude: longitude,
|
52
|
+
component: component,
|
53
|
+
published_at: Time.current
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
def category
|
58
|
+
id = data.has_key?(:category) ? data[:category]["id"] : data[:"category/id"].to_i
|
59
|
+
Decidim::Category.find_by(id: id)
|
60
|
+
end
|
61
|
+
|
62
|
+
def scope
|
63
|
+
id = data.has_key?(:scope) ? data[:scope]["id"] : data[:"scope/id"].to_i
|
64
|
+
Decidim::Scope.find_by(id: id)
|
65
|
+
end
|
66
|
+
|
67
|
+
def title
|
68
|
+
locale_hasher("title", available_locales)
|
69
|
+
end
|
70
|
+
|
71
|
+
def body
|
72
|
+
locale_hasher("body", available_locales)
|
73
|
+
end
|
74
|
+
|
75
|
+
def address
|
76
|
+
data.has_key?(:address) ? data[:address] : nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def latitude
|
80
|
+
data.has_key?(:latitude) ? data[:latitude] : nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def longitude
|
84
|
+
data.has_key?(:longitude) ? data[:longitude] : nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def available_locales
|
88
|
+
@available_locales ||= component.participatory_space.organization.available_locales
|
89
|
+
end
|
90
|
+
|
91
|
+
def component
|
92
|
+
context[:current_component]
|
93
|
+
end
|
94
|
+
|
95
|
+
def notify(proposal)
|
96
|
+
return if proposal.coauthorships.empty?
|
97
|
+
|
98
|
+
Decidim::EventsManager.publish(
|
99
|
+
event: "decidim.events.proposals.proposal_published",
|
100
|
+
event_class: Decidim::Proposals::PublishProposalEvent,
|
101
|
+
resource: proposal,
|
102
|
+
followers: coauthors_followers(proposal)
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
def publish(proposal)
|
107
|
+
Decidim::EventsManager.publish(
|
108
|
+
event: "decidim.events.proposals.proposal_published",
|
109
|
+
event_class: Decidim::Proposals::PublishProposalEvent,
|
110
|
+
resource: proposal,
|
111
|
+
followers: proposal.participatory_space.followers - coauthors_followers(proposal),
|
112
|
+
extra: {
|
113
|
+
participatory_space: true
|
114
|
+
}
|
115
|
+
)
|
116
|
+
end
|
117
|
+
|
118
|
+
def coauthors_followers(proposal)
|
119
|
+
@coauthors_followers ||= proposal.authors.flat_map(&:followers)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
module Import
|
6
|
+
# This class is responsible for verifying the data for proposal answers
|
7
|
+
# import.
|
8
|
+
class ProposalsAnswersVerifier < Decidim::Admin::Import::Verifier
|
9
|
+
protected
|
10
|
+
|
11
|
+
def required_headers
|
12
|
+
%w(id state) + required_localized_headers("answer")
|
13
|
+
end
|
14
|
+
|
15
|
+
# Check if prepared resource is valid
|
16
|
+
#
|
17
|
+
# record - Decidim::Proposals::Proposal
|
18
|
+
#
|
19
|
+
# Returns true if record is valid
|
20
|
+
def valid_record?(record)
|
21
|
+
return false if record.nil?
|
22
|
+
return false if record.errors.any?
|
23
|
+
|
24
|
+
record.valid?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
module Import
|
6
|
+
# This class is responsible for verifying the data for proposals import.
|
7
|
+
class ProposalsVerifier < Decidim::Admin::Import::Verifier
|
8
|
+
protected
|
9
|
+
|
10
|
+
def required_headers
|
11
|
+
required_localized_headers("title") + required_localized_headers("body")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
module Import
|
6
|
+
autoload :ProposalAnswerCreator, "decidim/proposals/import/proposal_answer_creator"
|
7
|
+
autoload :ProposalCreator, "decidim/proposals/import/proposal_creator"
|
8
|
+
autoload :ProposalsAnswersVerifier, "decidim/proposals/import/proposals_answers_verifier"
|
9
|
+
autoload :ProposalsVerifier, "decidim/proposals/import/proposals_verifier"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -33,17 +33,20 @@ module Decidim
|
|
33
33
|
component: { id: component.id },
|
34
34
|
title: proposal.title,
|
35
35
|
body: proposal.body,
|
36
|
+
address: proposal.address,
|
37
|
+
latitude: proposal.latitude,
|
38
|
+
longitude: proposal.longitude,
|
36
39
|
state: proposal.state.to_s,
|
37
40
|
reference: proposal.reference,
|
38
41
|
answer: ensure_translatable(proposal.answer),
|
39
42
|
supports: proposal.proposal_votes_count,
|
40
43
|
endorsements: {
|
41
|
-
total_count: proposal.endorsements.
|
44
|
+
total_count: proposal.endorsements.size,
|
42
45
|
user_endorsements: user_endorsements
|
43
46
|
},
|
44
47
|
comments: proposal.comments_count,
|
45
|
-
attachments: proposal.attachments.
|
46
|
-
followers: proposal.
|
48
|
+
attachments: proposal.attachments.size,
|
49
|
+
followers: proposal.follows.size,
|
47
50
|
published_at: proposal.published_at,
|
48
51
|
url: url,
|
49
52
|
meeting_urls: meetings,
|
@@ -214,14 +214,6 @@ FactoryBot.define do
|
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
|
-
trait :with_card_image_allowed do
|
218
|
-
settings do
|
219
|
-
{
|
220
|
-
allow_card_image: true
|
221
|
-
}
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
217
|
trait :with_extra_hashtags do
|
226
218
|
transient do
|
227
219
|
automatic_hashtags { "AutoHashtag AnotherAutoHashtag" }
|
@@ -297,7 +289,7 @@ FactoryBot.define do
|
|
297
289
|
proposal.body = Decidim::ContentProcessor.parse_with_processor(:hashtag, proposal.body, current_organization: proposal.organization).rewrite
|
298
290
|
|
299
291
|
if proposal.component
|
300
|
-
users = evaluator.users || [create(:user, organization: proposal.component.participatory_space.organization)]
|
292
|
+
users = evaluator.users || [create(:user, :confirmed, organization: proposal.component.participatory_space.organization)]
|
301
293
|
users.each_with_index do |user, idx|
|
302
294
|
user_group = evaluator.user_groups[idx]
|
303
295
|
proposal.coauthorships.build(author: user, user_group: user_group)
|
data/lib/decidim/proposals.rb
CHANGED
@@ -4,6 +4,7 @@ require "decidim/proposals/admin"
|
|
4
4
|
require "decidim/proposals/api"
|
5
5
|
require "decidim/proposals/engine"
|
6
6
|
require "decidim/proposals/admin_engine"
|
7
|
+
require "decidim/proposals/import"
|
7
8
|
require "decidim/proposals/component"
|
8
9
|
|
9
10
|
module Decidim
|
@@ -11,7 +12,6 @@ module Decidim
|
|
11
12
|
# allows users to create proposals in a participatory process.
|
12
13
|
module Proposals
|
13
14
|
autoload :ProposalSerializer, "decidim/proposals/proposal_serializer"
|
14
|
-
autoload :ProposalCreator, "decidim/proposals/proposal_creator"
|
15
15
|
autoload :CommentableProposal, "decidim/proposals/commentable_proposal"
|
16
16
|
autoload :CommentableCollaborativeDraft, "decidim/proposals/commentable_collaborative_draft"
|
17
17
|
autoload :MarkdownToProposals, "decidim/proposals/markdown_to_proposals"
|