decidim-proposals 0.14.4 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -0
- data/app/assets/images/decidim/gamification/badges/accepted_proposals.svg +194 -104
- data/app/assets/images/decidim/gamification/badges/proposals.svg +192 -108
- data/app/assets/javascripts/decidim/proposals/admin/proposals.es6 +25 -20
- data/app/cells/decidim/proposals/proposal_activity_cell.rb +19 -0
- data/app/commands/decidim/proposals/admin/answer_proposal.rb +6 -2
- data/app/commands/decidim/proposals/admin/create_proposal.rb +4 -4
- data/app/commands/decidim/proposals/admin/import_participatory_text.rb +49 -0
- data/app/commands/decidim/proposals/admin/import_proposals.rb +7 -21
- data/app/commands/decidim/proposals/admin/merge_proposals.rb +68 -0
- data/app/commands/decidim/proposals/admin/publish_participatory_text.rb +65 -0
- data/app/commands/decidim/proposals/admin/split_proposals.rb +67 -0
- data/app/commands/decidim/proposals/admin/update_proposal.rb +67 -0
- data/app/commands/decidim/proposals/create_collaborative_draft.rb +19 -14
- data/app/commands/decidim/proposals/create_proposal.rb +4 -2
- data/app/commands/decidim/proposals/endorse_proposal.rb +5 -1
- data/app/commands/decidim/proposals/publish_proposal.rb +15 -3
- data/app/commands/decidim/proposals/unvote_proposal.rb +34 -3
- data/app/commands/decidim/proposals/vote_proposal.rb +32 -2
- data/app/controllers/decidim/proposals/admin/participatory_texts_controller.rb +62 -0
- data/app/controllers/decidim/proposals/admin/proposals_controller.rb +28 -1
- data/app/controllers/decidim/proposals/admin/proposals_merges_controller.rb +27 -0
- data/app/controllers/decidim/proposals/admin/proposals_splits_controller.rb +27 -0
- data/app/controllers/decidim/proposals/collaborative_drafts_controller.rb +0 -1
- data/app/controllers/decidim/proposals/proposal_endorsements_controller.rb +6 -2
- data/app/controllers/decidim/proposals/proposal_votes_controller.rb +15 -0
- data/app/controllers/decidim/proposals/proposals_controller.rb +1 -1
- data/app/forms/decidim/proposals/admin/import_participatory_text_form.rb +28 -0
- data/app/forms/decidim/proposals/admin/preview_participatory_text_form.rb +21 -0
- data/app/forms/decidim/proposals/admin/proposal_form.rb +4 -1
- data/app/forms/decidim/proposals/admin/proposals_fork_form.rb +57 -0
- data/app/forms/decidim/proposals/admin/proposals_merge_form.rb +13 -0
- data/app/forms/decidim/proposals/admin/proposals_split_form.rb +12 -0
- data/app/helpers/decidim/proposals/application_helper.rb +23 -0
- data/app/helpers/decidim/proposals/map_helper.rb +1 -1
- data/app/helpers/decidim/proposals/participatory_texts_helper.rb +18 -0
- data/app/helpers/decidim/proposals/proposal_endorsements_helper.rb +1 -1
- data/app/helpers/decidim/proposals/proposal_wizard_helper.rb +2 -1
- data/app/jobs/decidim/proposals/notify_proposals_mentioned_job.rb +3 -4
- data/app/models/decidim/proposals/participatory_text.rb +13 -0
- data/app/models/decidim/proposals/proposal.rb +31 -9
- data/app/models/decidim/proposals/proposal_vote.rb +21 -1
- data/app/permissions/decidim/proposals/admin/permissions.rb +30 -0
- data/app/presenters/decidim/proposals/admin_log/proposal_presenter.rb +5 -1
- data/app/presenters/decidim/proposals/log/resource_presenter.rb +18 -0
- data/app/presenters/decidim/proposals/official_author_presenter.rb +4 -0
- data/app/queries/decidim/proposals/metrics/accepted_proposals_metric_manage.rb +29 -0
- data/app/queries/decidim/proposals/metrics/proposals_metric_manage.rb +53 -0
- data/app/queries/decidim/proposals/metrics/votes_metric_manage.rb +57 -0
- data/app/services/decidim/proposals/proposal_builder.rb +72 -0
- data/app/services/decidim/proposals/proposal_search.rb +2 -2
- data/app/views/decidim/proposals/admin/participatory_texts/_article-preview.html.erb +13 -0
- data/app/views/decidim/proposals/admin/participatory_texts/_bulk-actions.html.erb +1 -0
- data/app/views/decidim/proposals/admin/participatory_texts/index.html.erb +43 -0
- data/app/views/decidim/proposals/admin/participatory_texts/new_import.html.erb +39 -0
- data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +7 -2
- data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +4 -0
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_dropdown.html.erb +36 -0
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_merge.html.erb +15 -0
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_recategorize.html.erb +15 -0
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_split.html.erb +15 -0
- data/app/views/decidim/proposals/admin/proposals/edit.html.erb +7 -0
- data/app/views/decidim/proposals/admin/proposals/index.html.erb +2 -2
- data/app/views/decidim/proposals/collaborative_drafts/compare.html.erb +2 -2
- data/app/views/decidim/proposals/collaborative_drafts/complete.html.erb +1 -1
- data/app/views/decidim/proposals/collaborative_drafts/show.html.erb +1 -1
- data/app/views/decidim/proposals/proposal_endorsements/_identity.html.erb +5 -1
- data/app/views/decidim/proposals/proposal_endorsements/update_buttons_and_counters.js.erb +1 -1
- data/app/views/decidim/proposals/proposal_votes/update_buttons_and_counters.js.erb +13 -4
- data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +2 -2
- data/app/views/decidim/proposals/proposals/_endorsement_identities_cabin.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/_proposal_similar.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/_voting_rules.html.erb +15 -4
- data/app/views/decidim/proposals/proposals/new.html.erb +1 -1
- data/config/locales/ca.yml +72 -4
- data/config/locales/de.yml +71 -3
- data/config/locales/en.yml +71 -3
- data/config/locales/es-PY.yml +71 -3
- data/config/locales/es.yml +73 -5
- data/config/locales/eu.yml +71 -3
- data/config/locales/fi.yml +81 -13
- data/config/locales/fr.yml +71 -3
- data/config/locales/gl.yml +71 -3
- data/config/locales/hu.yml +71 -3
- data/config/locales/it.yml +71 -3
- data/config/locales/nl.yml +71 -3
- data/config/locales/pl.yml +71 -3
- data/config/locales/pt-BR.yml +72 -4
- data/config/locales/pt.yml +71 -3
- data/config/locales/sv.yml +71 -3
- data/db/migrate/20180927111721_create_participatory_texts.rb +13 -0
- data/db/migrate/20180930125321_add_participatory_text_level_to_proposals.rb +7 -0
- data/db/migrate/20180930125321_add_position_to_proposals.rb +7 -0
- data/db/migrate/20181003074440_fix_user_groups_ids_in_proposals_endorsements.rb +16 -0
- data/db/migrate/20181010114622_add_temporary_votes.rb +9 -0
- data/db/migrate/20181016132225_add_organization_as_author.rb +13 -0
- data/db/migrate/20181017084221_make_author_polymorhpic_for_proposal_endorsements.rb +31 -0
- data/lib/decidim/content_parsers/proposal_parser.rb +9 -3
- data/lib/decidim/proposals.rb +3 -1
- data/lib/decidim/proposals/admin_engine.rb +12 -1
- data/lib/decidim/proposals/component.rb +60 -23
- data/lib/decidim/proposals/engine.rb +55 -12
- data/lib/decidim/proposals/markdown_to_proposals.rb +90 -0
- data/lib/decidim/proposals/participatory_text_section.rb +21 -0
- data/lib/decidim/proposals/test/factories.rb +35 -7
- data/lib/decidim/proposals/version.rb +1 -1
- metadata +86 -19
data/lib/decidim/proposals.rb
CHANGED
@@ -4,6 +4,7 @@ require "decidim/proposals/admin"
|
|
4
4
|
require "decidim/proposals/engine"
|
5
5
|
require "decidim/proposals/admin_engine"
|
6
6
|
require "decidim/proposals/component"
|
7
|
+
require "acts_as_list"
|
7
8
|
|
8
9
|
module Decidim
|
9
10
|
# This namespace holds the logic of the `Proposals` component. This component
|
@@ -12,7 +13,8 @@ module Decidim
|
|
12
13
|
autoload :ProposalSerializer, "decidim/proposals/proposal_serializer"
|
13
14
|
autoload :CommentableProposal, "decidim/proposals/commentable_proposal"
|
14
15
|
autoload :CommentableCollaborativeDraft, "decidim/proposals/commentable_collaborative_draft"
|
15
|
-
autoload :
|
16
|
+
autoload :MarkdownToProposals, "decidim/proposals/markdown_to_proposals"
|
17
|
+
autoload :ParticipatoryTextSection, "decidim/proposals/participatory_text_section"
|
16
18
|
|
17
19
|
include ActiveSupport::Configurable
|
18
20
|
|
@@ -10,14 +10,25 @@ module Decidim
|
|
10
10
|
paths["lib/tasks"] = nil
|
11
11
|
|
12
12
|
routes do
|
13
|
-
resources :proposals, only: [:index, :new, :create] do
|
13
|
+
resources :proposals, only: [:index, :new, :create, :edit, :update] do
|
14
14
|
post :update_category, on: :collection
|
15
15
|
collection do
|
16
16
|
resource :proposals_import, only: [:new, :create]
|
17
|
+
resource :proposals_merge, only: [:create]
|
18
|
+
resource :proposals_split, only: [:create]
|
17
19
|
end
|
18
20
|
resources :proposal_answers, only: [:edit, :update]
|
19
21
|
resources :proposal_notes, only: [:index, :create]
|
20
22
|
end
|
23
|
+
scope "/proposal_components/:component_id" do
|
24
|
+
resources :participatory_texts, only: :index do
|
25
|
+
collection do
|
26
|
+
get :new_import
|
27
|
+
post :import
|
28
|
+
post :publish
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
21
32
|
|
22
33
|
root to: "proposals#index"
|
23
34
|
end
|
@@ -21,6 +21,7 @@ Decidim.register_component(:proposals) do |component|
|
|
21
21
|
|
22
22
|
component.settings(:global) do |settings|
|
23
23
|
settings.attribute :vote_limit, type: :integer, default: 0
|
24
|
+
settings.attribute :minimum_votes_per_user, type: :integer, default: 0
|
24
25
|
settings.attribute :proposal_limit, type: :integer, default: 0
|
25
26
|
settings.attribute :proposal_length, type: :integer, default: 500
|
26
27
|
settings.attribute :proposal_edit_before_minutes, type: :integer, default: 5
|
@@ -33,6 +34,7 @@ Decidim.register_component(:proposals) do |component|
|
|
33
34
|
settings.attribute :attachments_allowed, type: :boolean, default: false
|
34
35
|
settings.attribute :resources_permissions_enabled, type: :boolean, default: true
|
35
36
|
settings.attribute :collaborative_drafts_enabled, type: :boolean, default: false
|
37
|
+
settings.attribute :participatory_texts_enabled, type: :boolean, default: false
|
36
38
|
settings.attribute :announcement, type: :text, translated: true, editor: true
|
37
39
|
settings.attribute :new_proposal_help_text, type: :text, translated: true, editor: true
|
38
40
|
settings.attribute :proposal_wizard_step_1_help_text, type: :text, translated: true, editor: true
|
@@ -110,13 +112,18 @@ Decidim.register_component(:proposals) do |component|
|
|
110
112
|
end
|
111
113
|
|
112
114
|
component.seeds do |participatory_space|
|
115
|
+
admin_user = Decidim::User.find_by(
|
116
|
+
organization: participatory_space.organization,
|
117
|
+
email: "admin@example.org"
|
118
|
+
)
|
119
|
+
|
113
120
|
step_settings = if participatory_space.allows_steps?
|
114
121
|
{ participatory_space.active_step.id => { votes_enabled: true, votes_blocked: false, creation_enabled: true } }
|
115
122
|
else
|
116
123
|
{}
|
117
124
|
end
|
118
125
|
|
119
|
-
|
126
|
+
params = {
|
120
127
|
name: Decidim::Components::Namer.new(participatory_space.organization.available_locales, :proposals).i18n_name,
|
121
128
|
manifest_name: :proposals,
|
122
129
|
published_at: Time.current,
|
@@ -126,7 +133,16 @@ Decidim.register_component(:proposals) do |component|
|
|
126
133
|
collaborative_drafts_enabled: true
|
127
134
|
},
|
128
135
|
step_settings: step_settings
|
129
|
-
|
136
|
+
}
|
137
|
+
|
138
|
+
component = Decidim.traceability.perform_action!(
|
139
|
+
"publish",
|
140
|
+
Decidim::Component,
|
141
|
+
admin_user,
|
142
|
+
visibility: "all"
|
143
|
+
) do
|
144
|
+
Decidim::Component.create!(params)
|
145
|
+
end
|
130
146
|
|
131
147
|
if participatory_space.scope
|
132
148
|
scopes = participatory_space.scope.descendants
|
@@ -147,7 +163,7 @@ Decidim.register_component(:proposals) do |component|
|
|
147
163
|
[nil, nil]
|
148
164
|
end
|
149
165
|
|
150
|
-
|
166
|
+
params = {
|
151
167
|
component: component,
|
152
168
|
category: participatory_space.categories.sample,
|
153
169
|
scope: Faker::Boolean.boolean(0.5) ? global : scopes.sample,
|
@@ -157,10 +173,23 @@ Decidim.register_component(:proposals) do |component|
|
|
157
173
|
answer: answer,
|
158
174
|
answered_at: Time.current,
|
159
175
|
published_at: Time.current
|
160
|
-
|
176
|
+
}
|
177
|
+
|
178
|
+
proposal = Decidim.traceability.perform_action!(
|
179
|
+
"publish",
|
180
|
+
Decidim::Proposals::Proposal,
|
181
|
+
admin_user,
|
182
|
+
visibility: "all"
|
183
|
+
) do
|
184
|
+
proposal = Decidim::Proposals::Proposal.new(params)
|
185
|
+
proposal.add_coauthor(participatory_space.organization)
|
186
|
+
proposal.save!
|
187
|
+
proposal
|
188
|
+
end
|
189
|
+
|
161
190
|
if n.positive?
|
162
191
|
Decidim::User.where(decidim_organization_id: participatory_space.decidim_organization_id).all.sample(n).each do |author|
|
163
|
-
user_group = [true, false].sample ? author.
|
192
|
+
user_group = [true, false].sample ? Decidim::UserGroups::ManageableUserGroups.for(author).verified.sample : nil
|
164
193
|
proposal.add_coauthor(author, user_group: user_group)
|
165
194
|
end
|
166
195
|
end
|
@@ -203,13 +232,19 @@ Decidim.register_component(:proposals) do |component|
|
|
203
232
|
if index.even?
|
204
233
|
group = Decidim::UserGroup.create!(
|
205
234
|
name: Faker::Name.name,
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
235
|
+
nickname: Faker::Twitter.unique.screen_name,
|
236
|
+
extended_data: {
|
237
|
+
document_number: Faker::Code.isbn,
|
238
|
+
phone: Faker::PhoneNumber.phone_number,
|
239
|
+
verified_at: Time.current
|
240
|
+
},
|
241
|
+
decidim_organization_id: component.organization.id
|
242
|
+
)
|
243
|
+
Decidim::UserGroupMembership.create!(
|
244
|
+
user: author,
|
245
|
+
role: "creator",
|
246
|
+
user_group: group
|
210
247
|
)
|
211
|
-
author.user_groups << group
|
212
|
-
author.save!
|
213
248
|
end
|
214
249
|
Decidim::Proposals::ProposalEndorsement.create!(proposal: proposal, author: author, user_group: author.user_groups.first)
|
215
250
|
end
|
@@ -239,18 +274,20 @@ Decidim.register_component(:proposals) do |component|
|
|
239
274
|
end
|
240
275
|
author = Decidim::User.where(organization: component.organization).all.sample
|
241
276
|
|
242
|
-
draft = Decidim.traceability.
|
243
|
-
Decidim::Proposals::CollaborativeDraft
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
277
|
+
draft = Decidim.traceability.perform_action!("create", Decidim::Proposals::CollaborativeDraft, author) do
|
278
|
+
draft = Decidim::Proposals::CollaborativeDraft.new(
|
279
|
+
component: component,
|
280
|
+
category: participatory_space.categories.sample,
|
281
|
+
scope: Faker::Boolean.boolean(0.5) ? global : scopes.sample,
|
282
|
+
title: Faker::Lorem.sentence(2),
|
283
|
+
body: Faker::Lorem.paragraphs(2).join("\n"),
|
284
|
+
state: state,
|
285
|
+
published_at: Time.current
|
286
|
+
)
|
287
|
+
draft.coauthorships.build(author: participatory_space.organization)
|
288
|
+
draft.save!
|
289
|
+
draft
|
290
|
+
end
|
254
291
|
|
255
292
|
if n == 2
|
256
293
|
author2 = Decidim::User.where(organization: component.organization).all.sample
|
@@ -113,8 +113,8 @@ module Decidim
|
|
113
113
|
|
114
114
|
initializer "decidim_proposals.mentions_listener" do
|
115
115
|
Decidim::Comments::CommentCreation.subscribe do |data|
|
116
|
-
|
117
|
-
Decidim::Proposals::NotifyProposalsMentionedJob.perform_later(data[:comment_id],
|
116
|
+
proposals = data.dig(:metadatas, :proposal).try(:linked_proposals)
|
117
|
+
Decidim::Proposals::NotifyProposalsMentionedJob.perform_later(data[:comment_id], proposals) if proposals
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
@@ -140,22 +140,42 @@ module Decidim
|
|
140
140
|
Decidim::Gamification.register_badge(:proposals) do |badge|
|
141
141
|
badge.levels = [1, 5, 10, 30, 60]
|
142
142
|
|
143
|
-
badge.
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
143
|
+
badge.valid_for = [:user, :user_group]
|
144
|
+
|
145
|
+
badge.reset = lambda { |model|
|
146
|
+
if model.is_a?(User)
|
147
|
+
Decidim::Coauthorship.where(
|
148
|
+
coauthorable_type: "Decidim::Proposals::Proposal",
|
149
|
+
author: model,
|
150
|
+
user_group: nil
|
151
|
+
).count
|
152
|
+
elsif model.is_a?(UserGroup)
|
153
|
+
Decidim::Coauthorship.where(
|
154
|
+
coauthorable_type: "Decidim::Proposals::Proposal",
|
155
|
+
user_group: model
|
156
|
+
).count
|
157
|
+
end
|
148
158
|
}
|
149
159
|
end
|
150
160
|
|
151
161
|
Decidim::Gamification.register_badge(:accepted_proposals) do |badge|
|
152
162
|
badge.levels = [1, 5, 15, 30, 50]
|
153
163
|
|
154
|
-
badge.
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
164
|
+
badge.valid_for = [:user, :user_group]
|
165
|
+
|
166
|
+
badge.reset = lambda { |model|
|
167
|
+
proposal_ids = if model.is_a?(User)
|
168
|
+
Decidim::Coauthorship.where(
|
169
|
+
coauthorable_type: "Decidim::Proposals::Proposal",
|
170
|
+
author: model,
|
171
|
+
user_group: nil
|
172
|
+
).select(:coauthorable_id)
|
173
|
+
elsif model.is_a?(UserGroup)
|
174
|
+
Decidim::Coauthorship.where(
|
175
|
+
coauthorable_type: "Decidim::Proposals::Proposal",
|
176
|
+
user_group: model
|
177
|
+
).select(:coauthorable_id)
|
178
|
+
end
|
159
179
|
|
160
180
|
Decidim::Proposals::Proposal.where(id: proposal_ids).accepted.count
|
161
181
|
}
|
@@ -169,6 +189,29 @@ module Decidim
|
|
169
189
|
}
|
170
190
|
end
|
171
191
|
end
|
192
|
+
|
193
|
+
initializer "decidim_proposals.register_metrics" do
|
194
|
+
Decidim.metrics_registry.register(
|
195
|
+
:proposals,
|
196
|
+
"Decidim::Proposals::Metrics::ProposalsMetricManage",
|
197
|
+
Decidim::MetricRegistry::HIGHLIGHTED,
|
198
|
+
2
|
199
|
+
)
|
200
|
+
|
201
|
+
Decidim.metrics_registry.register(
|
202
|
+
:accepted_proposals,
|
203
|
+
"Decidim::Proposals::Metrics::AcceptedProposalsMetricManage",
|
204
|
+
Decidim::MetricRegistry::NOT_HIGHLIGHTED,
|
205
|
+
3
|
206
|
+
)
|
207
|
+
|
208
|
+
Decidim.metrics_registry.register(
|
209
|
+
:votes,
|
210
|
+
"Decidim::Proposals::Metrics::VotesMetricManage",
|
211
|
+
Decidim::MetricRegistry::HIGHLIGHTED,
|
212
|
+
3
|
213
|
+
)
|
214
|
+
end
|
172
215
|
end
|
173
216
|
end
|
174
217
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "redcarpet"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module Proposals
|
7
|
+
# This class parses a participatory text document in markdown and
|
8
|
+
# produces Proposals in the form of sections and articles.
|
9
|
+
#
|
10
|
+
# This implementation uses Redcarpet Base renderer.
|
11
|
+
# Redcarpet::Render::Base performs a callback for every block it finds, what MarkdownToProposals
|
12
|
+
# does is to implement callbacks for the blocks which it is interested in performing some actions.
|
13
|
+
#
|
14
|
+
class MarkdownToProposals < ::Redcarpet::Render::Base
|
15
|
+
# Public: Initializes the serializer with a proposal.
|
16
|
+
def initialize(component, current_user)
|
17
|
+
super()
|
18
|
+
@component = component
|
19
|
+
@current_user = current_user
|
20
|
+
@last_position = 0
|
21
|
+
@num_sections = 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse(document)
|
25
|
+
renderer = self
|
26
|
+
parser = ::Redcarpet::Markdown.new(renderer)
|
27
|
+
parser.render(document)
|
28
|
+
end
|
29
|
+
|
30
|
+
##########################################
|
31
|
+
# Redcarpet callbacks
|
32
|
+
##########################################
|
33
|
+
|
34
|
+
# Recarpet callback to process headers.
|
35
|
+
# Creates Paricipatory Text Proposals at Section and Subsection levels.
|
36
|
+
def header(title, level)
|
37
|
+
participatory_text_level = if level > 1
|
38
|
+
Decidim::Proposals::ParticipatoryTextSection::LEVELS[:sub_section]
|
39
|
+
else
|
40
|
+
Decidim::Proposals::ParticipatoryTextSection::LEVELS[:section]
|
41
|
+
end
|
42
|
+
|
43
|
+
create_proposal(title, title, participatory_text_level)
|
44
|
+
|
45
|
+
@num_sections += 1
|
46
|
+
title
|
47
|
+
end
|
48
|
+
|
49
|
+
# Recarpet callback to process paragraphs.
|
50
|
+
# Creates Paricipatory Text Proposals at Article level.
|
51
|
+
def paragraph(text)
|
52
|
+
return if text.blank?
|
53
|
+
|
54
|
+
create_proposal(
|
55
|
+
(@last_position + 1 - @num_sections).to_s,
|
56
|
+
text,
|
57
|
+
Decidim::Proposals::ParticipatoryTextSection::LEVELS[:article]
|
58
|
+
)
|
59
|
+
|
60
|
+
text
|
61
|
+
end
|
62
|
+
|
63
|
+
# ignore images
|
64
|
+
def image(_link, _title, _alt_text)
|
65
|
+
""
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def create_proposal(title, body, participatory_text_level)
|
71
|
+
attributes = {
|
72
|
+
component: @component,
|
73
|
+
title: title,
|
74
|
+
body: body,
|
75
|
+
participatory_text_level: participatory_text_level
|
76
|
+
}
|
77
|
+
|
78
|
+
proposal = Decidim::Proposals::ProposalBuilder.create(
|
79
|
+
attributes: attributes,
|
80
|
+
author: @component.organization,
|
81
|
+
action_user: @current_user
|
82
|
+
)
|
83
|
+
|
84
|
+
@last_position = proposal.position
|
85
|
+
|
86
|
+
proposal
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
# The data store for a Proposal in the Decidim::Proposals component.
|
6
|
+
module ParticipatoryTextSection
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
LEVELS = {
|
10
|
+
section: "section", sub_section: "sub-section", article: "article"
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
included do
|
14
|
+
# Public: is this section an :article?
|
15
|
+
def article?
|
16
|
+
participatory_text_level == LEVELS[:article]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -158,6 +158,25 @@ FactoryBot.define do
|
|
158
158
|
}
|
159
159
|
end
|
160
160
|
end
|
161
|
+
|
162
|
+
trait :with_minimum_votes_per_user do
|
163
|
+
transient do
|
164
|
+
minimum_votes_per_user { 3 }
|
165
|
+
end
|
166
|
+
|
167
|
+
settings do
|
168
|
+
{
|
169
|
+
minimum_votes_per_user: minimum_votes_per_user
|
170
|
+
}
|
171
|
+
end
|
172
|
+
end
|
173
|
+
trait :with_participatory_texts_enabled do
|
174
|
+
settings do
|
175
|
+
{
|
176
|
+
participatory_texts_enabled: true
|
177
|
+
}
|
178
|
+
end
|
179
|
+
end
|
161
180
|
end
|
162
181
|
|
163
182
|
factory :proposal, class: "Decidim::Proposals::Proposal" do
|
@@ -167,7 +186,7 @@ FactoryBot.define do
|
|
167
186
|
user_groups { [] }
|
168
187
|
end
|
169
188
|
|
170
|
-
title {
|
189
|
+
title { generate(:title) }
|
171
190
|
body { Faker::Lorem.sentences(3).join("\n") }
|
172
191
|
component { create(:proposal_component) }
|
173
192
|
published_at { Time.current }
|
@@ -178,14 +197,23 @@ FactoryBot.define do
|
|
178
197
|
users = evaluator.users || [create(:user, organization: proposal.component.participatory_space.organization)]
|
179
198
|
users.each_with_index do |user, idx|
|
180
199
|
user_group = evaluator.user_groups[idx]
|
181
|
-
|
200
|
+
proposal.coauthorships.build(author: user, user_group: user_group)
|
182
201
|
end
|
183
202
|
end
|
184
203
|
end
|
185
204
|
|
205
|
+
trait :published do
|
206
|
+
published_at { Time.current }
|
207
|
+
end
|
208
|
+
|
209
|
+
trait :unpublished do
|
210
|
+
published_at { nil }
|
211
|
+
end
|
212
|
+
|
186
213
|
trait :official do
|
187
214
|
after :build do |proposal|
|
188
215
|
proposal.coauthorships.clear
|
216
|
+
proposal.coauthorships.build(author: proposal.organization)
|
189
217
|
end
|
190
218
|
end
|
191
219
|
|
@@ -210,7 +238,7 @@ FactoryBot.define do
|
|
210
238
|
|
211
239
|
trait :with_answer do
|
212
240
|
state { "accepted" }
|
213
|
-
answer {
|
241
|
+
answer { generate_localized_title }
|
214
242
|
answered_at { Time.current }
|
215
243
|
end
|
216
244
|
|
@@ -219,8 +247,8 @@ FactoryBot.define do
|
|
219
247
|
end
|
220
248
|
|
221
249
|
trait :hidden do
|
222
|
-
|
223
|
-
create(:moderation, hidden_at: Time.current)
|
250
|
+
after :create do |proposal|
|
251
|
+
create(:moderation, hidden_at: Time.current, reportable: proposal)
|
224
252
|
end
|
225
253
|
end
|
226
254
|
|
@@ -266,7 +294,7 @@ FactoryBot.define do
|
|
266
294
|
user_groups { [] }
|
267
295
|
end
|
268
296
|
|
269
|
-
title {
|
297
|
+
title { generate(:title) }
|
270
298
|
body { Faker::Lorem.sentences(3).join("\n") }
|
271
299
|
component { create(:proposal_component) }
|
272
300
|
address { "#{Faker::Address.street_name}, #{Faker::Address.city}" }
|
@@ -277,7 +305,7 @@ FactoryBot.define do
|
|
277
305
|
users = evaluator.users || [create(:user, organization: collaborative_draft.component.participatory_space.organization)]
|
278
306
|
users.each_with_index do |user, idx|
|
279
307
|
user_group = evaluator.user_groups[idx]
|
280
|
-
|
308
|
+
collaborative_draft.coauthorships.build(author: user, user_group: user_group)
|
281
309
|
end
|
282
310
|
end
|
283
311
|
end
|