decidim-proposals 0.22.0 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/decidim/proposals/add_proposal.js.es6 +6 -0
- data/app/assets/javascripts/decidim/proposals/admin/proposals_form.js.es6 +3 -0
- data/app/cells/decidim/proposals/collaborative_draft_cell.rb +1 -1
- data/app/cells/decidim/proposals/participatory_text_proposal/buttons.erb +2 -2
- data/app/cells/decidim/proposals/participatory_text_proposal_cell.rb +1 -1
- data/app/cells/decidim/proposals/proposal_cell.rb +1 -1
- data/app/cells/decidim/proposals/proposal_m_cell.rb +2 -2
- data/app/commands/decidim/proposals/admin/create_proposal.rb +4 -2
- data/app/commands/decidim/proposals/admin/publish_participatory_text.rb +6 -1
- data/app/commands/decidim/proposals/admin/update_participatory_text.rb +10 -2
- data/app/commands/decidim/proposals/admin/update_proposal.rb +4 -2
- data/app/commands/decidim/proposals/create_proposal.rb +6 -2
- data/app/commands/decidim/proposals/publish_collaborative_draft.rb +2 -2
- data/app/commands/decidim/proposals/update_proposal.rb +25 -9
- data/app/controllers/decidim/proposals/admin/proposals_controller.rb +2 -2
- data/app/controllers/decidim/proposals/collaborative_drafts_controller.rb +1 -10
- data/app/controllers/decidim/proposals/proposals_controller.rb +3 -17
- data/app/controllers/decidim/proposals/{proposal_widgets_controller.rb → widgets_controller.rb} +2 -2
- data/app/forms/decidim/proposals/admin/import_participatory_text_form.rb +3 -1
- data/app/forms/decidim/proposals/admin/participatory_text_proposal_form.rb +8 -1
- data/app/forms/decidim/proposals/admin/proposal_base_form.rb +20 -13
- data/app/forms/decidim/proposals/admin/proposal_form.rb +9 -2
- data/app/forms/decidim/proposals/proposal_form.rb +21 -12
- data/app/helpers/decidim/proposals/admin/proposals_helper.rb +2 -0
- data/app/helpers/decidim/proposals/application_helper.rb +13 -8
- data/app/helpers/decidim/proposals/proposals_helper.rb +1 -1
- data/app/models/decidim/proposals/collaborative_draft.rb +2 -2
- data/app/models/decidim/proposals/participatory_text.rb +3 -0
- data/app/models/decidim/proposals/proposal.rb +13 -40
- data/app/presenters/decidim/proposals/admin_log/value_types/proposal_title_body_presenter.rb +6 -1
- data/app/presenters/decidim/proposals/official_author_presenter.rb +1 -29
- data/app/presenters/decidim/proposals/proposal_presenter.rb +43 -6
- data/app/queries/decidim/proposals/similar_proposals.rb +4 -4
- data/app/services/decidim/proposals/collaborative_draft_search.rb +6 -16
- data/app/services/decidim/proposals/diff_renderer.rb +15 -5
- data/app/services/decidim/proposals/proposal_builder.rb +8 -2
- data/app/services/decidim/proposals/proposal_search.rb +7 -58
- data/app/types/decidim/proposals/proposal_type.rb +2 -2
- data/app/views/decidim/proposals/admin/proposals/_form.html.erb +6 -6
- data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +2 -11
- data/app/views/decidim/proposals/admin/proposals/index.html.erb +2 -2
- data/app/views/decidim/proposals/admin/proposals/show.html.erb +1 -1
- data/app/views/decidim/proposals/collaborative_drafts/_edit_form_fields.html.erb +5 -5
- data/app/views/decidim/proposals/collaborative_drafts/_filters.html.erb +1 -1
- data/app/views/decidim/proposals/collaborative_drafts/show.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +46 -18
- data/app/views/decidim/proposals/proposals/_filters.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/index.html.erb +0 -2
- data/app/views/decidim/proposals/proposals/show.html.erb +3 -3
- data/config/locales/am-ET.yml +1 -0
- data/config/locales/bg.yml +237 -0
- data/config/locales/ca.yml +12 -4
- data/config/locales/cs.yml +9 -1
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +3 -0
- data/config/locales/en.yml +8 -0
- data/config/locales/eo.yml +1 -0
- data/config/locales/es-MX.yml +8 -0
- data/config/locales/es-PY.yml +8 -0
- data/config/locales/es.yml +22 -14
- data/config/locales/et.yml +1 -0
- data/config/locales/eu.yml +0 -15
- data/config/locales/fi-plain.yml +8 -0
- data/config/locales/fi.yml +9 -1
- data/config/locales/fr-CA.yml +30 -0
- data/config/locales/fr.yml +36 -6
- data/config/locales/gl.yml +0 -15
- data/config/locales/hr.yml +1 -0
- data/config/locales/id-ID.yml +0 -15
- data/config/locales/is.yml +274 -0
- data/config/locales/it.yml +6 -0
- data/config/locales/ja-JP.yml +5 -26
- data/config/locales/ja.yml +889 -0
- data/config/locales/ko-KR.yml +1 -0
- data/config/locales/ko.yml +1 -0
- data/config/locales/lt.yml +1 -0
- data/config/locales/{lv-LV.yml → lv.yml} +0 -0
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +9 -1
- data/config/locales/om-ET.yml +1 -0
- data/config/locales/pl.yml +377 -374
- data/config/locales/pt-BR.yml +0 -15
- data/config/locales/pt.yml +1 -0
- data/config/locales/ro-RO.yml +1 -0
- data/config/locales/so-SO.yml +1 -0
- data/config/locales/sv.yml +49 -26
- data/config/locales/ti-ER.yml +1 -0
- data/config/locales/tr-TR.yml +0 -15
- data/config/locales/vi-VN.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +885 -0
- data/config/locales/zh-TW.yml +1 -0
- data/db/migrate/20200120215928_move_proposal_endorsements_to_core_endorsements.rb +2 -0
- data/db/migrate/20200120230130_drop_proposal_endorsements.rb +8 -0
- data/db/migrate/20200708091228_move_proposals_fields_to_i18n.rb +80 -0
- data/db/migrate/20200827154156_add_commentable_counter_cache_to_proposals.rb +12 -0
- data/db/migrate/20200915151348_fix_proposals_data_to_ensure_title_and_body_are_hashes.rb +37 -0
- data/db/migrate/20201002085508_fix_proposals_data.rb +37 -0
- data/lib/decidim/content_renderers/proposal_renderer.rb +3 -1
- data/lib/decidim/proposals/component.rb +9 -6
- data/lib/decidim/proposals/engine.rb +1 -1
- data/lib/decidim/proposals/markdown_to_proposals.rb +2 -2
- data/lib/decidim/proposals/proposal_serializer.rb +3 -3
- data/lib/decidim/proposals/test/capybara_proposals_picker.rb +2 -2
- data/lib/decidim/proposals/test/factories.rb +44 -18
- data/lib/decidim/proposals/version.rb +1 -1
- metadata +46 -22
@@ -4,8 +4,15 @@ module Decidim
|
|
4
4
|
module Proposals
|
5
5
|
module Admin
|
6
6
|
# A form object to be used when admin users want to create a proposal.
|
7
|
-
class ProposalForm < Admin::ProposalBaseForm
|
8
|
-
|
7
|
+
class ProposalForm < Decidim::Proposals::Admin::ProposalBaseForm
|
8
|
+
translatable_attribute :title, String do |field, _locale|
|
9
|
+
validates field, length: { in: 15..150 }, if: proc { |resource| resource.send(field).present? }
|
10
|
+
end
|
11
|
+
translatable_attribute :body, String
|
12
|
+
|
13
|
+
validates :title, :body, translatable_presence: true
|
14
|
+
|
15
|
+
validate :notify_missing_attachment_if_errored
|
9
16
|
end
|
10
17
|
end
|
11
18
|
end
|
@@ -4,6 +4,8 @@ module Decidim
|
|
4
4
|
module Proposals
|
5
5
|
# A form object to be used when public users want to create a proposal.
|
6
6
|
class ProposalForm < Decidim::Proposals::ProposalWizardCreateStepForm
|
7
|
+
include Decidim::TranslatableAttributes
|
8
|
+
|
7
9
|
mimic :proposal
|
8
10
|
|
9
11
|
attribute :address, String
|
@@ -14,14 +16,16 @@ module Decidim
|
|
14
16
|
attribute :has_address, Boolean
|
15
17
|
attribute :attachment, AttachmentForm
|
16
18
|
attribute :suggested_hashtags, Array[String]
|
19
|
+
attribute :photos, Array[String]
|
20
|
+
attribute :add_photos, Array
|
21
|
+
attribute :documents, Array[String]
|
22
|
+
attribute :add_documents, Array
|
17
23
|
|
18
|
-
validates :address, geocoding: true, if: ->(form) {
|
24
|
+
validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? }
|
19
25
|
validates :address, presence: true, if: ->(form) { form.has_address? }
|
20
26
|
validates :category, presence: true, if: ->(form) { form.category_id.present? }
|
21
27
|
validates :scope, presence: true, if: ->(form) { form.scope_id.present? }
|
22
|
-
|
23
|
-
validate :scope_belongs_to_participatory_space_scope
|
24
|
-
|
28
|
+
validates :scope_id, scope_belongs_to_component: true, if: ->(form) { form.scope_id.present? }
|
25
29
|
validate :notify_missing_attachment_if_errored
|
26
30
|
|
27
31
|
delegate :categories, to: :current_component
|
@@ -29,7 +33,8 @@ module Decidim
|
|
29
33
|
def map_model(model)
|
30
34
|
super
|
31
35
|
|
32
|
-
|
36
|
+
body = translated_attribute(model.body)
|
37
|
+
@suggested_hashtags = Decidim::ContentRenderers::HashtagRenderer.new(body).extra_hashtags.map(&:name).map(&:downcase)
|
33
38
|
|
34
39
|
# The scope attribute is with different key (decidim_scope_id), so it
|
35
40
|
# has to be manually mapped.
|
@@ -43,11 +48,11 @@ module Decidim
|
|
43
48
|
@category ||= categories.find_by(id: category_id)
|
44
49
|
end
|
45
50
|
|
46
|
-
# Finds the Scope from the given
|
51
|
+
# Finds the Scope from the given scope_id, uses participatory space scope if missing.
|
47
52
|
#
|
48
53
|
# Returns a Decidim::Scope
|
49
54
|
def scope
|
50
|
-
@scope ||= @scope_id ?
|
55
|
+
@scope ||= @scope_id ? current_component.scopes.find_by(id: @scope_id) : current_component.scope
|
51
56
|
end
|
52
57
|
|
53
58
|
# Scope identifier
|
@@ -57,8 +62,16 @@ module Decidim
|
|
57
62
|
@scope_id || scope&.id
|
58
63
|
end
|
59
64
|
|
65
|
+
def geocoding_enabled?
|
66
|
+
Decidim::Map.available?(:geocoding) && current_component.settings.geocoding_enabled?
|
67
|
+
end
|
68
|
+
|
60
69
|
def has_address?
|
61
|
-
|
70
|
+
geocoding_enabled? && has_address
|
71
|
+
end
|
72
|
+
|
73
|
+
def geocoded?
|
74
|
+
latitude.present? && longitude.present?
|
62
75
|
end
|
63
76
|
|
64
77
|
def extra_hashtags
|
@@ -84,10 +97,6 @@ module Decidim
|
|
84
97
|
|
85
98
|
private
|
86
99
|
|
87
|
-
def scope_belongs_to_participatory_space_scope
|
88
|
-
errors.add(:scope_id, :invalid) if current_participatory_space.out_of_scope?(scope)
|
89
|
-
end
|
90
|
-
|
91
100
|
# This method will add an error to the `attachment` field only if there's
|
92
101
|
# any error in any other field. This is needed because when the form has
|
93
102
|
# an error, the attachment is lost, so we need a way to inform the user of
|
@@ -139,18 +139,10 @@ module Decidim
|
|
139
139
|
render partial: "decidim/proposals/proposals/participatory_texts/proposal_vote_button.html", locals: { proposal: model, from_proposals_list: from_proposals_list }
|
140
140
|
end
|
141
141
|
|
142
|
-
def endorsers_for(proposal)
|
143
|
-
proposal.endorsements.for_listing.map { |identity| present(identity.normalized_author) }
|
144
|
-
end
|
145
|
-
|
146
142
|
def form_has_address?
|
147
143
|
@form.address.present? || @form.has_address
|
148
144
|
end
|
149
145
|
|
150
|
-
def authors_for(collaborative_draft)
|
151
|
-
collaborative_draft.identities.map { |identity| present(identity) }
|
152
|
-
end
|
153
|
-
|
154
146
|
def show_voting_rules?
|
155
147
|
return false unless votes_enabled?
|
156
148
|
|
@@ -178,6 +170,19 @@ module Decidim
|
|
178
170
|
base += [["voted", t(".voted")]] if current_settings.votes_enabled?
|
179
171
|
base
|
180
172
|
end
|
173
|
+
|
174
|
+
def filter_origin_values
|
175
|
+
origin_values = []
|
176
|
+
origin_values << TreePoint.new("official", t("decidim.proposals.application_helper.filter_origin_values.official")) if component_settings.official_proposals_enabled
|
177
|
+
origin_values << TreePoint.new("citizens", t("decidim.proposals.application_helper.filter_origin_values.citizens"))
|
178
|
+
origin_values << TreePoint.new("user_group", t("decidim.proposals.application_helper.filter_origin_values.user_groups")) if current_organization.user_groups_enabled?
|
179
|
+
origin_values << TreePoint.new("meeting", t("decidim.proposals.application_helper.filter_origin_values.meetings"))
|
180
|
+
|
181
|
+
TreeNode.new(
|
182
|
+
TreePoint.new("", t("decidim.proposals.application_helper.filter_origin_values.all")),
|
183
|
+
origin_values
|
184
|
+
)
|
185
|
+
end
|
181
186
|
end
|
182
187
|
end
|
183
188
|
end
|
@@ -44,7 +44,7 @@ module Decidim
|
|
44
44
|
[
|
45
45
|
Decidim::CheckBoxesTreeHelper::TreePoint.new("accepted", t("decidim.proposals.application_helper.filter_state_values.accepted")),
|
46
46
|
Decidim::CheckBoxesTreeHelper::TreePoint.new("evaluating", t("decidim.proposals.application_helper.filter_state_values.evaluating")),
|
47
|
-
Decidim::CheckBoxesTreeHelper::TreePoint.new("
|
47
|
+
Decidim::CheckBoxesTreeHelper::TreePoint.new("state_not_published", t("decidim.proposals.application_helper.filter_state_values.not_answered")),
|
48
48
|
Decidim::CheckBoxesTreeHelper::TreePoint.new("rejected", t("decidim.proposals.application_helper.filter_state_values.rejected"))
|
49
49
|
]
|
50
50
|
)
|
@@ -6,7 +6,7 @@ module Decidim
|
|
6
6
|
include Decidim::Resourceable
|
7
7
|
include Decidim::Coauthorable
|
8
8
|
include Decidim::HasComponent
|
9
|
-
include Decidim::
|
9
|
+
include Decidim::ScopableResource
|
10
10
|
include Decidim::HasReference
|
11
11
|
include Decidim::HasCategory
|
12
12
|
include Decidim::Reportable
|
@@ -28,7 +28,7 @@ module Decidim
|
|
28
28
|
class_name: "Decidim::User",
|
29
29
|
foreign_key: :decidim_user_id
|
30
30
|
|
31
|
-
geocoded_by :address
|
31
|
+
geocoded_by :address
|
32
32
|
|
33
33
|
scope :open, -> { where(state: "open") }
|
34
34
|
scope :withdrawn, -> { where(state: "withdrawn") }
|
@@ -7,7 +7,7 @@ module Decidim
|
|
7
7
|
include Decidim::Resourceable
|
8
8
|
include Decidim::Coauthorable
|
9
9
|
include Decidim::HasComponent
|
10
|
-
include Decidim::
|
10
|
+
include Decidim::ScopableResource
|
11
11
|
include Decidim::HasReference
|
12
12
|
include Decidim::HasCategory
|
13
13
|
include Decidim::Reportable
|
@@ -19,13 +19,16 @@ module Decidim
|
|
19
19
|
include Decidim::Loggable
|
20
20
|
include Decidim::Fingerprintable
|
21
21
|
include Decidim::DataPortability
|
22
|
-
include Decidim::Hashtaggable
|
23
22
|
include Decidim::Proposals::ParticipatoryTextSection
|
24
23
|
include Decidim::Amendable
|
25
24
|
include Decidim::NewsletterParticipant
|
26
25
|
include Decidim::Randomable
|
27
26
|
include Decidim::Endorsable
|
28
27
|
include Decidim::Proposals::Valuatable
|
28
|
+
include Decidim::TranslatableResource
|
29
|
+
include Decidim::TranslatableAttributes
|
30
|
+
|
31
|
+
translatable_fields :title, :body
|
29
32
|
|
30
33
|
POSSIBLE_STATES = %w(not_answered evaluating accepted rejected withdrawn).freeze
|
31
34
|
|
@@ -49,7 +52,7 @@ module Decidim
|
|
49
52
|
|
50
53
|
validates :title, :body, presence: true
|
51
54
|
|
52
|
-
geocoded_by :address
|
55
|
+
geocoded_by :address
|
53
56
|
|
54
57
|
scope :answered, -> { where.not(answered_at: nil) }
|
55
58
|
scope :not_answered, -> { where(answered_at: nil) }
|
@@ -66,27 +69,6 @@ module Decidim
|
|
66
69
|
scope :drafts, -> { where(published_at: nil) }
|
67
70
|
scope :except_drafts, -> { where.not(published_at: nil) }
|
68
71
|
scope :published, -> { where.not(published_at: nil) }
|
69
|
-
scope :official_origin, lambda {
|
70
|
-
where.not(coauthorships_count: 0)
|
71
|
-
.joins(:coauthorships)
|
72
|
-
.where(decidim_coauthorships: { decidim_author_type: "Decidim::Organization" })
|
73
|
-
}
|
74
|
-
scope :citizens_origin, lambda {
|
75
|
-
where.not(coauthorships_count: 0)
|
76
|
-
.joins(:coauthorships)
|
77
|
-
.where.not(decidim_coauthorships: { decidim_author_type: "Decidim::Organization" })
|
78
|
-
}
|
79
|
-
scope :user_group_origin, lambda {
|
80
|
-
where.not(coauthorships_count: 0)
|
81
|
-
.joins(:coauthorships)
|
82
|
-
.where(decidim_coauthorships: { decidim_author_type: "Decidim::UserBaseEntity" })
|
83
|
-
.where.not(decidim_coauthorships: { decidim_user_group_id: nil })
|
84
|
-
}
|
85
|
-
scope :meeting_origin, lambda {
|
86
|
-
where.not(coauthorships_count: 0)
|
87
|
-
.joins(:coauthorships)
|
88
|
-
.where(decidim_coauthorships: { decidim_author_type: "Decidim::Meetings::Meeting" })
|
89
|
-
}
|
90
72
|
scope :sort_by_valuation_assignments_count_asc, lambda {
|
91
73
|
order(sort_by_valuation_assignments_count_nulls_last_query + "ASC NULLS FIRST")
|
92
74
|
}
|
@@ -107,8 +89,8 @@ module Decidim
|
|
107
89
|
searchable_fields({
|
108
90
|
scope_id: :decidim_scope_id,
|
109
91
|
participatory_space: { component: :participatory_space },
|
110
|
-
D: :
|
111
|
-
A: :
|
92
|
+
D: :body,
|
93
|
+
A: :title,
|
112
94
|
datetime: :published_at
|
113
95
|
},
|
114
96
|
index_on_create: ->(proposal) { proposal.official? },
|
@@ -146,7 +128,7 @@ module Decidim
|
|
146
128
|
|
147
129
|
endorsements_participants_ids = Decidim::Endorsement.where(resource: proposals)
|
148
130
|
.where(decidim_author_type: "Decidim::UserBaseEntity")
|
149
|
-
.
|
131
|
+
.pluck(:decidim_author_id).to_a.compact.uniq
|
150
132
|
|
151
133
|
(endorsements_participants_ids + participants_has_voted_ids + coauthors_recipients_ids).flatten.compact.uniq
|
152
134
|
end
|
@@ -300,19 +282,6 @@ module Decidim
|
|
300
282
|
published_at.nil?
|
301
283
|
end
|
302
284
|
|
303
|
-
# method for sort_link by number of comments
|
304
|
-
ransacker :commentable_comments_count do
|
305
|
-
query = <<-SQL
|
306
|
-
(SELECT COUNT(decidim_comments_comments.id)
|
307
|
-
FROM decidim_comments_comments
|
308
|
-
WHERE decidim_comments_comments.decidim_commentable_id = decidim_proposals_proposals.id
|
309
|
-
AND decidim_comments_comments.decidim_commentable_type = 'Decidim::Proposals::Proposal'
|
310
|
-
GROUP BY decidim_comments_comments.decidim_commentable_id
|
311
|
-
)
|
312
|
-
SQL
|
313
|
-
Arel.sql(query)
|
314
|
-
end
|
315
|
-
|
316
285
|
# Defines the base query so that ransack can actually sort by this value
|
317
286
|
def self.sort_by_valuation_assignments_count_nulls_last_query
|
318
287
|
<<-SQL
|
@@ -359,6 +328,10 @@ module Decidim
|
|
359
328
|
Arel.sql("CASE WHEN state = 'withdrawn' THEN 'withdrawn' WHEN state_published_at IS NULL THEN NULL ELSE state END")
|
360
329
|
end
|
361
330
|
|
331
|
+
ransacker :title do
|
332
|
+
Arel.sql(%{("decidim_proposals_proposals"."title")::text})
|
333
|
+
end
|
334
|
+
|
362
335
|
ransacker :id_string do
|
363
336
|
Arel.sql(%{cast("decidim_proposals_proposals"."id" as text)})
|
364
337
|
end
|
data/app/presenters/decidim/proposals/admin_log/value_types/proposal_title_body_presenter.rb
CHANGED
@@ -5,10 +5,15 @@ module Decidim
|
|
5
5
|
module AdminLog
|
6
6
|
module ValueTypes
|
7
7
|
class ProposalTitleBodyPresenter < Decidim::Log::ValueTypes::DefaultPresenter
|
8
|
+
include Decidim::TranslatableAttributes
|
9
|
+
|
8
10
|
def present
|
9
11
|
return unless value
|
10
12
|
|
11
|
-
|
13
|
+
translated_value = translated_attribute(value)
|
14
|
+
return if translated_value.blank?
|
15
|
+
|
16
|
+
renderer = Decidim::ContentRenderers::HashtagRenderer.new(translated_value)
|
12
17
|
renderer.render(links: false).html_safe
|
13
18
|
end
|
14
19
|
end
|
@@ -5,38 +5,10 @@ module Decidim
|
|
5
5
|
#
|
6
6
|
# A dummy presenter to abstract out the author of an official proposal.
|
7
7
|
#
|
8
|
-
class OfficialAuthorPresenter
|
8
|
+
class OfficialAuthorPresenter < Decidim::OfficialAuthorPresenter
|
9
9
|
def name
|
10
10
|
I18n.t("decidim.proposals.models.proposal.fields.official_proposal")
|
11
11
|
end
|
12
|
-
|
13
|
-
def nickname
|
14
|
-
""
|
15
|
-
end
|
16
|
-
|
17
|
-
def badge
|
18
|
-
""
|
19
|
-
end
|
20
|
-
|
21
|
-
def profile_path
|
22
|
-
""
|
23
|
-
end
|
24
|
-
|
25
|
-
def avatar_url
|
26
|
-
ActionController::Base.helpers.asset_path("decidim/default-avatar.svg")
|
27
|
-
end
|
28
|
-
|
29
|
-
def deleted?
|
30
|
-
false
|
31
|
-
end
|
32
|
-
|
33
|
-
def can_be_contacted?
|
34
|
-
false
|
35
|
-
end
|
36
|
-
|
37
|
-
def has_tooltip?
|
38
|
-
false
|
39
|
-
end
|
40
12
|
end
|
41
13
|
end
|
42
14
|
end
|
@@ -9,6 +9,7 @@ module Decidim
|
|
9
9
|
include Rails.application.routes.mounted_helpers
|
10
10
|
include ActionView::Helpers::UrlHelper
|
11
11
|
include Decidim::SanitizeHelper
|
12
|
+
include Decidim::TranslatableAttributes
|
12
13
|
|
13
14
|
def author
|
14
15
|
@author ||= if official?
|
@@ -38,7 +39,7 @@ module Decidim
|
|
38
39
|
#
|
39
40
|
# Returns a String.
|
40
41
|
def title(links: false, extras: true, html_escape: false)
|
41
|
-
text = proposal.title
|
42
|
+
text = translated_attribute(proposal.title)
|
42
43
|
text = decidim_html_escape(text) if html_escape
|
43
44
|
|
44
45
|
renderer = Decidim::ContentRenderers::HashtagRenderer.new(text)
|
@@ -50,12 +51,9 @@ module Decidim
|
|
50
51
|
end
|
51
52
|
|
52
53
|
def body(links: false, extras: true, strip_tags: false)
|
53
|
-
text = proposal.body
|
54
|
+
text = translated_attribute(proposal.body)
|
54
55
|
|
55
|
-
if strip_tags
|
56
|
-
text = text.gsub(%r{<\/p>}, "\n\n")
|
57
|
-
text = strip_tags(text)
|
58
|
-
end
|
56
|
+
text = strip_tags(sanitize_text(text)) if strip_tags
|
59
57
|
|
60
58
|
renderer = Decidim::ContentRenderers::HashtagRenderer.new(text)
|
61
59
|
text = renderer.render(links: links, extras: extras).html_safe
|
@@ -93,6 +91,45 @@ module Decidim
|
|
93
91
|
def resource_manifest
|
94
92
|
proposal.class.resource_manifest
|
95
93
|
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def sanitize_unordered_lists(text)
|
98
|
+
text.gsub(%r{(?=.*<\/ul>)(?!.*?<li>.*?<\/ol>.*?<\/ul>)<li>}) { |li| li + "• " }
|
99
|
+
end
|
100
|
+
|
101
|
+
def sanitize_ordered_lists(text)
|
102
|
+
i = 0
|
103
|
+
|
104
|
+
text.gsub(%r{(?=.*<\/ol>)(?!.*?<li>.*?<\/ul>.*?<\/ol>)<li>}) do |li|
|
105
|
+
i += 1
|
106
|
+
|
107
|
+
li + "#{i}. "
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def add_line_feeds_to_paragraphs(text)
|
112
|
+
text.gsub("</p>") { |p| p + "\n\n" }
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_line_feeds_to_list_items(text)
|
116
|
+
text.gsub("</li>") { |li| li + "\n" }
|
117
|
+
end
|
118
|
+
|
119
|
+
# Adds line feeds after the paragraph and list item closing tags.
|
120
|
+
#
|
121
|
+
# Returns a String.
|
122
|
+
def add_line_feeds(text)
|
123
|
+
add_line_feeds_to_paragraphs(add_line_feeds_to_list_items(text))
|
124
|
+
end
|
125
|
+
|
126
|
+
# Maintains the paragraphs and lists separations with their bullet points and
|
127
|
+
# list numberings where appropriate.
|
128
|
+
#
|
129
|
+
# Returns a String.
|
130
|
+
def sanitize_text(text)
|
131
|
+
add_line_feeds(sanitize_ordered_lists(sanitize_unordered_lists(text)))
|
132
|
+
end
|
96
133
|
end
|
97
134
|
end
|
98
135
|
end
|
@@ -30,8 +30,8 @@ module Decidim
|
|
30
30
|
.published
|
31
31
|
.where(
|
32
32
|
"GREATEST(#{title_similarity}, #{body_similarity}) >= ?",
|
33
|
-
@proposal.title,
|
34
|
-
@proposal.body,
|
33
|
+
translated_attribute(@proposal.title),
|
34
|
+
translated_attribute(@proposal.body),
|
35
35
|
Decidim::Proposals.similarity_threshold
|
36
36
|
)
|
37
37
|
.limit(Decidim::Proposals.similarity_limit)
|
@@ -40,11 +40,11 @@ module Decidim
|
|
40
40
|
private
|
41
41
|
|
42
42
|
def title_similarity
|
43
|
-
"similarity(title, ?)"
|
43
|
+
"similarity(title::text, ?)"
|
44
44
|
end
|
45
45
|
|
46
46
|
def body_similarity
|
47
|
-
"similarity(body, ?)"
|
47
|
+
"similarity(body::text, ?)"
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|