decidim-core 0.17.2 → 0.18.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of decidim-core might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/app/assets/javascripts/decidim.js.es6 +1 -0
- data/app/assets/javascripts/decidim/core/bundle.js +1 -1
- data/app/assets/javascripts/decidim/core/bundle.js.map +1 -1
- data/app/assets/javascripts/decidim/diff_mode_dropdown.js.es6 +16 -0
- data/app/assets/javascripts/decidim/represent_user_group.js.es6 +18 -0
- data/app/assets/stylesheets/decidim/_variables.scss +4 -0
- data/app/assets/stylesheets/decidim/extras/_meeting-registrations.scss +9 -0
- data/app/assets/stylesheets/decidim/modules/_data-picker.scss +25 -0
- data/app/assets/stylesheets/decidim/modules/_modules.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_order-by.scss +2 -0
- data/app/assets/stylesheets/decidim/modules/_versions.scss +75 -0
- data/app/cells/decidim/amendable/amend_button_card_cell.rb +1 -1
- data/app/cells/decidim/amendable/amenders_list/show.erb +3 -9
- data/app/cells/decidim/amendable/amenders_list_cell.rb +23 -1
- data/app/cells/decidim/amendable/promote_button_card/show.erb +2 -1
- data/app/cells/decidim/amendable/promote_button_card_cell.rb +6 -2
- data/app/cells/decidim/card_m_cell.rb +5 -0
- data/app/cells/decidim/content_blocks/footer_sub_hero/show.erb +1 -1
- data/app/cells/decidim/diff/attribute.erb +17 -0
- data/app/cells/decidim/diff/diff_mode_dropdown.erb +29 -0
- data/app/cells/decidim/diff/diff_split.erb +11 -0
- data/app/cells/decidim/diff/diff_unified.erb +7 -0
- data/app/cells/decidim/diff/show.erb +5 -0
- data/app/cells/decidim/diff_cell.rb +79 -0
- data/app/cells/decidim/represent_user_group/show.erb +12 -0
- data/app/cells/decidim/represent_user_group_cell.rb +46 -0
- data/app/commands/decidim/amendable/accept.rb +10 -19
- data/app/commands/decidim/amendable/create.rb +15 -38
- data/app/commands/decidim/amendable/promote.rb +20 -22
- data/app/commands/decidim/amendable/reject.rb +3 -3
- data/app/controllers/concerns/decidim/amendments_controller.rb +4 -4
- data/app/controllers/concerns/decidim/devise_controllers.rb +6 -4
- data/app/controllers/concerns/decidim/filter_resource.rb +13 -4
- data/app/controllers/concerns/decidim/needs_permission.rb +1 -0
- data/app/controllers/concerns/decidim/needs_tos_accepted.rb +2 -1
- data/app/controllers/concerns/decidim/registers_permissions.rb +27 -0
- data/app/controllers/decidim/application_controller.rb +5 -4
- data/app/events/decidim/amendable/amendment_accepted_event.rb +1 -7
- data/app/events/decidim/amendable/amendment_base_event.rb +7 -2
- data/app/events/decidim/amendable/amendment_created_event.rb +2 -8
- data/app/events/decidim/amendable/amendment_rejected_event.rb +1 -7
- data/app/events/decidim/amendable/emendation_promoted_event.rb +1 -7
- data/app/forms/decidim/amendable/create_form.rb +16 -32
- data/app/forms/decidim/amendable/form.rb +40 -4
- data/app/forms/decidim/amendable/promote_form.rb +7 -11
- data/app/forms/decidim/amendable/reject_form.rb +1 -1
- data/app/forms/decidim/amendable/review_form.rb +4 -23
- data/app/forms/decidim/invite_user_form.rb +2 -2
- data/app/helpers/decidim/amendments_helper.rb +64 -72
- data/app/helpers/decidim/application_helper.rb +18 -0
- data/app/helpers/decidim/decidim_form_helper.rb +13 -1
- data/app/helpers/decidim/scopes_helper.rb +13 -3
- data/app/helpers/decidim/traceability_helper.rb +0 -61
- data/app/helpers/decidim/translations_helper.rb +20 -1
- data/app/jobs/decidim/email_notification_generator_job.rb +2 -0
- data/app/jobs/decidim/notification_generator_job.rb +2 -0
- data/app/mailers/decidim/application_mailer.rb +15 -0
- data/app/models/decidim/amendment.rb +4 -0
- data/app/models/decidim/area.rb +18 -0
- data/app/models/decidim/follow.rb +4 -0
- data/app/models/decidim/newsletter.rb +24 -0
- data/app/models/decidim/permission_action.rb +13 -0
- data/app/models/decidim/user.rb +12 -2
- data/app/queries/decidim/metric_measure.rb +1 -1
- data/app/services/decidim/participatory_space_search.rb +54 -0
- data/app/views/decidim/account/_password_fields.html.erb +1 -1
- data/app/views/decidim/amendments/_edit_form_fields.html.erb +21 -0
- data/app/views/decidim/amendments/new.html.erb +18 -4
- data/app/views/decidim/amendments/review.html.erb +11 -5
- data/app/views/decidim/application/_photos.html.erb +1 -1
- data/app/views/decidim/devise/passwords/edit.html.erb +1 -1
- data/app/views/decidim/devise/registrations/new.html.erb +1 -1
- data/app/views/decidim/notifications_settings/show.html.erb +6 -6
- data/app/views/decidim/scopes/_scopes_picker_input.html.erb +6 -1
- data/app/views/decidim/shared/participatory_space_filters/_filters.html.erb +13 -0
- data/app/views/decidim/shared/participatory_space_filters/_filters_small_view.html.erb +19 -0
- data/app/views/decidim/shared/participatory_space_filters/_show.html.erb +7 -0
- data/app/views/decidim/user_interests/_areas.html.erb +2 -2
- data/app/views/decidim/user_interests/_scopes.html.erb +2 -2
- data/app/views/decidim/user_interests/show.html.erb +3 -1
- data/config/locales/ar-SA.yml +24 -21
- data/config/locales/ar.yml +1282 -0
- data/config/locales/ca.yml +38 -22
- data/config/locales/cs.yml +25 -19
- data/config/locales/de.yml +24 -18
- data/config/locales/en.yml +39 -23
- data/config/locales/es-MX.yml +35 -19
- data/config/locales/es-PY.yml +35 -19
- data/config/locales/es.yml +38 -22
- data/config/locales/eu.yml +24 -18
- data/config/locales/fi-plain.yml +34 -18
- data/config/locales/fi.yml +39 -23
- data/config/locales/fr.yml +24 -18
- data/config/locales/gl.yml +24 -18
- data/config/locales/hu.yml +30 -21
- data/config/locales/id-ID.yml +25 -19
- data/config/locales/it.yml +37 -21
- data/config/locales/nl.yml +24 -18
- data/config/locales/pl.yml +25 -19
- data/config/locales/pt-BR.yml +25 -19
- data/config/locales/pt.yml +25 -19
- data/config/locales/sv.yml +37 -21
- data/config/locales/tr-TR.yml +35 -19
- data/db/migrate/20181219130325_add_smtp_settings_to_decidim_organizations.rb +7 -0
- data/db/migrate/20190325145349_add_extended_data_to_newsletters.rb +7 -0
- data/db/migrate/20190412105836_add_missing_indexes.rb +11 -0
- data/db/migrate/20190412131728_fix_user_names.rb +24 -0
- data/db/seeds.rb +7 -0
- data/lib/decidim/amendable.rb +41 -29
- data/lib/decidim/attribute_encryptor.rb +20 -0
- data/lib/decidim/component_manifest.rb +4 -0
- data/lib/decidim/core.rb +20 -1
- data/lib/decidim/core/engine.rb +1 -0
- data/lib/decidim/core/test/factories.rb +9 -0
- data/lib/decidim/core/test/shared_examples/amendable/amendment_accepted_event_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/amendable/amendment_created_event_examples.rb +2 -2
- data/lib/decidim/core/test/shared_examples/amendable/amendment_form_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/amendable/amendment_promoted_event_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/amendable/amendment_rejected_event_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/amendable/create_amendment_examples.rb +3 -21
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +18 -0
- data/lib/decidim/core/test/shared_examples/has_attachments.rb +1 -1
- data/lib/decidim/core/test/shared_examples/space_cell_changes_button_text_cta.rb +31 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/exporters/csv.rb +2 -2
- data/lib/decidim/filter_form_builder.rb +8 -1
- data/lib/decidim/form_builder.rb +40 -4
- data/lib/decidim/has_component.rb +7 -0
- data/lib/decidim/has_private_users.rb +25 -8
- data/lib/decidim/jsonb_attributes.rb +45 -0
- data/lib/decidim/newsletter_participant.rb +18 -0
- data/lib/decidim/participable.rb +9 -0
- data/lib/decidim/permissions_registry.rb +39 -0
- data/lib/tasks/decidim_metrics_tasks.rake +35 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.ar.js +16 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.es-MX.js +15 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.es-PY.js +15 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.fi-pl.js +14 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.id.js +13 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.pl.js +15 -0
- data/vendor/assets/javascripts/datepicker-locales/{foundation-datepicker.pt-br.js → foundation-datepicker.pt-BR.js} +0 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.tr.js +14 -0
- metadata +42 -10
- data/app/views/decidim/amendments/_form.html.erb +0 -30
- data/app/views/decidim/amendments/_review_form.html.erb +0 -19
@@ -37,7 +37,7 @@ shared_examples "amendment accepted event" do
|
|
37
37
|
describe "notification_title" do
|
38
38
|
it "is generated correctly" do
|
39
39
|
expect(subject.notification_title)
|
40
|
-
.to
|
40
|
+
.to eq("The <a href=\"#{emendation_path}\">amendment</a> created by <a href=\"#{emendation_author_path}\">#{emendation_author_nickname}</a> has been accepted for <a href=\"#{amendable_path}\">#{amendable_title}</a>.") # rubocop:disable Metrics/LineLength
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -21,7 +21,7 @@ shared_examples "amendment created event" do
|
|
21
21
|
|
22
22
|
describe "email_subject" do
|
23
23
|
it "is generated correctly" do
|
24
|
-
expect(subject.email_subject).to eq("New amendment for #{amendable_title}
|
24
|
+
expect(subject.email_subject).to eq("New amendment for #{amendable_title}")
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -42,7 +42,7 @@ shared_examples "amendment created event" do
|
|
42
42
|
describe "notification_title" do
|
43
43
|
it "is generated correctly" do
|
44
44
|
expect(subject.notification_title)
|
45
|
-
.to
|
45
|
+
.to eq("A new amendment has been created for <a href=\"#{amendable_path}\">#{amendable_title}</a>.")
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -37,7 +37,7 @@ shared_examples "amendment promoted event" do
|
|
37
37
|
describe "notification_title" do
|
38
38
|
it "is generated correctly" do
|
39
39
|
expect(subject.notification_title)
|
40
|
-
.to
|
40
|
+
.to eq("A <a href=\"#{emendation_path}\">rejected amendment</a> for <a href=\"#{amendable_path}\">#{amendable_title}</a> has been published as a new #{amendable_type} by <a href=\"#{emendation_author_path}\">#{emendation_author_nickname}</a>.") # rubocop:disable Metrics/LineLength
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -37,7 +37,7 @@ shared_examples "amendment rejected event" do
|
|
37
37
|
describe "notification_title" do
|
38
38
|
it "is generated correctly" do
|
39
39
|
expect(subject.notification_title)
|
40
|
-
.to
|
40
|
+
.to eq("The <a href=\"#{emendation_path}\">amendment</a> created by <a href=\"#{emendation_author_path}\">#{emendation_author_nickname}</a> has been rejected for <a href=\"#{amendable_path}\">#{amendable_title}</a>.") # rubocop:disable Metrics/LineLength
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -19,7 +19,7 @@ shared_examples "create amendment" do
|
|
19
19
|
.to receive(:perform_action!)
|
20
20
|
.with(
|
21
21
|
"publish",
|
22
|
-
form.amendable_type.constantize,
|
22
|
+
form.amendable.amendable_type.constantize,
|
23
23
|
form.current_user,
|
24
24
|
kind_of(Hash)
|
25
25
|
).and_call_original
|
@@ -34,9 +34,8 @@ shared_examples "create amendment" do
|
|
34
34
|
event: "decidim.events.amendments.amendment_created",
|
35
35
|
event_class: Decidim::Amendable::AmendmentCreatedEvent,
|
36
36
|
resource: amendable,
|
37
|
-
|
38
|
-
|
39
|
-
extra: kind_of(Hash)
|
37
|
+
affected_users: [amendable.creator_author],
|
38
|
+
followers: []
|
40
39
|
)
|
41
40
|
|
42
41
|
command.call
|
@@ -58,21 +57,4 @@ shared_examples "create amendment" do
|
|
58
57
|
.by(0)
|
59
58
|
end
|
60
59
|
end
|
61
|
-
|
62
|
-
context "when the emendation doens't change the amendable" do
|
63
|
-
let(:title) { amendable.title }
|
64
|
-
let(:body) { amendable.body }
|
65
|
-
|
66
|
-
it "broadcasts invalid" do
|
67
|
-
expect { command.call }.to broadcast(:invalid)
|
68
|
-
end
|
69
|
-
|
70
|
-
it "doesn't create an amendment and the emendation" do
|
71
|
-
expect { command.call }
|
72
|
-
.to change(Decidim::Amendment, :count)
|
73
|
-
.by(0)
|
74
|
-
.and change(amendable.resource_manifest.model_class_name.constantize, :count)
|
75
|
-
.by(0)
|
76
|
-
end
|
77
|
-
end
|
78
60
|
end
|
@@ -98,6 +98,7 @@ shared_examples "comments" do
|
|
98
98
|
visit resource_path
|
99
99
|
|
100
100
|
expect(page).to have_selector(".comment__reply")
|
101
|
+
expect(page).not_to have_selector(".comment__additionalreply")
|
101
102
|
|
102
103
|
within "#comments #comment_#{comment.id}" do
|
103
104
|
click_button "Reply"
|
@@ -110,10 +111,27 @@ shared_examples "comments" do
|
|
110
111
|
end
|
111
112
|
|
112
113
|
expect(page).to have_selector(".comment-thread .comment--nested")
|
114
|
+
expect(page).to have_selector(".comment__additionalreply")
|
113
115
|
expect(page).to have_reply_to(comment, "This is a reply")
|
114
116
|
end
|
115
117
|
end
|
116
118
|
|
119
|
+
context "when a comment has been moderated" do
|
120
|
+
let!(:parent) { create(:comment, commentable: commentable) }
|
121
|
+
let!(:reply) { create(:comment, commentable: parent, root_commentable: commentable) }
|
122
|
+
|
123
|
+
it "doesn't show additional reply" do
|
124
|
+
Decidim::Moderation.create!(reportable: reply, participatory_space: reply.participatory_space, hidden_at: 1.day.ago)
|
125
|
+
|
126
|
+
visit current_path
|
127
|
+
|
128
|
+
within "#comments #comment_#{parent.id}" do
|
129
|
+
expect(page).to have_selector(".comment__reply")
|
130
|
+
expect(page).not_to have_selector(".comment__additionalreply")
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
117
135
|
describe "arguable option" do
|
118
136
|
context "when commenting with alignment" do
|
119
137
|
before do
|
@@ -39,7 +39,7 @@ shared_examples_for "has attachments" do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
within "div.wrapper .images" do
|
42
|
-
expect(strip_tags(translated(fist_image.
|
42
|
+
expect(strip_tags(translated(fist_image.title, locale: :en))).to appear_before(strip_tags(translated(last_image.title, locale: :en)))
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
shared_examples_for "space cell changes button text CTA" do
|
6
|
+
describe "within the card footer" do
|
7
|
+
context "when it has no components" do
|
8
|
+
it "renders 'More info' in the CTA button text" do
|
9
|
+
expect(subject).to have_selector(".card__footer--spaces .card__button", text: "More info")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when it has a component" do
|
14
|
+
context "and it is not published" do
|
15
|
+
let!(:component) { create(:component, :unpublished, manifest_name: "dummy", participatory_space: model) }
|
16
|
+
|
17
|
+
it "renders 'More info' in the CTA button text" do
|
18
|
+
expect(subject).to have_selector(".card__footer--spaces .card__button", text: "More info")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "and it is published" do
|
23
|
+
let!(:component) { create(:component, :published, manifest_name: "dummy", participatory_space: model) }
|
24
|
+
|
25
|
+
it "renders 'Take part' in the CTA button text" do
|
26
|
+
expect(subject).to have_selector(".card__footer--spaces .card__button", text: "Take part")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/decidim/core/version.rb
CHANGED
@@ -15,8 +15,8 @@ module Decidim
|
|
15
15
|
# provided serializer and following the previously described strategy.
|
16
16
|
#
|
17
17
|
# Returns an ExportData instance.
|
18
|
-
def export
|
19
|
-
data = ::CSV.generate(headers: headers, write_headers: true, col_sep:
|
18
|
+
def export(col_sep = Decidim.default_csv_col_sep)
|
19
|
+
data = ::CSV.generate(headers: headers, write_headers: true, col_sep: col_sep) do |csv|
|
20
20
|
processed_collection.each do |resource|
|
21
21
|
csv << headers.map { |header| resource[header] }
|
22
22
|
end
|
@@ -40,8 +40,15 @@ module Decidim
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
# Wrap the areas select in a custom fieldset.
|
44
|
+
def areas_select(method, collection, options = {})
|
45
|
+
fieldset_wrapper options[:legend_title] do
|
46
|
+
super(method, collection, options)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
43
50
|
# Wrap the scopes picker in a custom fieldset.
|
44
|
-
def scopes_picker(method, options = {})
|
51
|
+
def scopes_picker(method, options = { checkboxes_on_top: true })
|
45
52
|
fieldset_wrapper options[:legend_title] do
|
46
53
|
super(method, options)
|
47
54
|
end
|
data/lib/decidim/form_builder.rb
CHANGED
@@ -202,12 +202,44 @@ module Decidim
|
|
202
202
|
select(name, @template.options_for_select(categories, selected: selected, disabled: disabled), options, html_options)
|
203
203
|
end
|
204
204
|
|
205
|
+
# Public: Generates a select field for areas.
|
206
|
+
#
|
207
|
+
# name - The name of the field (usually area_id)
|
208
|
+
# collection - A collection of areas or area_types.
|
209
|
+
# If it's areas, we sort the selectable options alphabetically.
|
210
|
+
#
|
211
|
+
# Returns a String.
|
212
|
+
def areas_select(name, collection, options = {})
|
213
|
+
selectables = if collection.first.is_a?(Decidim::Area)
|
214
|
+
assemblies = collection
|
215
|
+
.map { |a| [a.name[I18n.locale.to_s], a.id] }
|
216
|
+
.sort_by { |arr| arr[0] }
|
217
|
+
|
218
|
+
@template.options_for_select(
|
219
|
+
assemblies,
|
220
|
+
selected: options[:selected]
|
221
|
+
)
|
222
|
+
else
|
223
|
+
@template.option_groups_from_collection_for_select(
|
224
|
+
collection,
|
225
|
+
:areas,
|
226
|
+
:translated_name,
|
227
|
+
:id,
|
228
|
+
:translated_name,
|
229
|
+
selected: options[:selected]
|
230
|
+
)
|
231
|
+
end
|
232
|
+
|
233
|
+
select(name, selectables, options)
|
234
|
+
end
|
235
|
+
|
205
236
|
# Public: Generates a picker field for scope selection.
|
206
237
|
#
|
207
238
|
# attribute - The name of the field (usually scope_id)
|
208
239
|
# options - An optional Hash with options:
|
209
240
|
# - multiple - Multiple mode, to allow multiple scopes selection.
|
210
241
|
# - label - Show label?
|
242
|
+
# - checkboxes_on_top - Show checked picker values on top (default) or below the picker prompt
|
211
243
|
#
|
212
244
|
# Also it should receive a block that returns a Hash with :url and :text for each selected scope (and for null scope for prompt)
|
213
245
|
#
|
@@ -225,7 +257,11 @@ module Decidim
|
|
225
257
|
scopes = selected_scopes(attribute).map { |scope| [scope, yield(scope)] }
|
226
258
|
template = ""
|
227
259
|
template += label(attribute, label_for(attribute) + required_for_attribute(attribute)) unless options[:label] == false
|
228
|
-
template += @template.render("decidim/scopes/scopes_picker_input",
|
260
|
+
template += @template.render("decidim/scopes/scopes_picker_input",
|
261
|
+
picker_options: picker_options,
|
262
|
+
prompt_params: prompt_params,
|
263
|
+
scopes: scopes,
|
264
|
+
checkboxes_on_top: options[:checkboxes_on_top])
|
229
265
|
template += error_and_help_text(attribute, options)
|
230
266
|
template.html_safe
|
231
267
|
end
|
@@ -366,11 +402,11 @@ module Decidim
|
|
366
402
|
end
|
367
403
|
end
|
368
404
|
|
369
|
-
def form_field_for(attribute)
|
405
|
+
def form_field_for(attribute, options = {})
|
370
406
|
if attribute == :body
|
371
|
-
text_area
|
407
|
+
text_area(attribute, options.merge(rows: 10))
|
372
408
|
else
|
373
|
-
text_field
|
409
|
+
text_field(attribute, options)
|
374
410
|
end
|
375
411
|
end
|
376
412
|
|
@@ -12,6 +12,13 @@ module Decidim
|
|
12
12
|
belongs_to :component, foreign_key: "decidim_component_id", class_name: "Decidim::Component", touch: true
|
13
13
|
delegate :organization, to: :component, allow_nil: true
|
14
14
|
delegate :participatory_space, to: :component, allow_nil: true
|
15
|
+
|
16
|
+
def can_participate_in_space?(user)
|
17
|
+
return true unless participatory_space.try(:private_space?)
|
18
|
+
return false unless user
|
19
|
+
|
20
|
+
participatory_space.users.include?(user)
|
21
|
+
end
|
15
22
|
end
|
16
23
|
|
17
24
|
class_methods do
|
@@ -9,17 +9,34 @@ module Decidim
|
|
9
9
|
extend ActiveSupport::Concern
|
10
10
|
|
11
11
|
included do
|
12
|
-
has_many :participatory_space_private_users,
|
13
|
-
|
12
|
+
has_many :participatory_space_private_users,
|
13
|
+
class_name: "Decidim::ParticipatorySpacePrivateUser",
|
14
|
+
as: :privatable_to,
|
15
|
+
dependent: :destroy
|
16
|
+
has_many :users,
|
17
|
+
through: :participatory_space_private_users,
|
18
|
+
class_name: "Decidim::User",
|
19
|
+
foreign_key: "private_user_to_id"
|
14
20
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
def self.visible_for(user)
|
22
|
+
if user
|
23
|
+
return all if user.admin?
|
24
|
+
|
25
|
+
left_outer_joins(:participatory_space_private_users).where(
|
26
|
+
%(private_space = false OR
|
27
|
+
decidim_participatory_space_private_users.decidim_user_id = ?), user.id
|
28
|
+
)
|
29
|
+
else
|
30
|
+
public_spaces
|
31
|
+
end
|
32
|
+
end
|
20
33
|
|
21
34
|
def self.public_spaces
|
22
|
-
|
35
|
+
where(private_space: false)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.private_spaces
|
39
|
+
where(private_space: true)
|
23
40
|
end
|
24
41
|
end
|
25
42
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
# A set of convenient methods to generate dynamic jsonb objects in a way is
|
7
|
+
# compatilbe with Virtus and ActiveModel thus making it easy to integrate
|
8
|
+
# into Rails forms and similar workflows.
|
9
|
+
module JsonbAttributes
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
class_methods do
|
13
|
+
# Public: Mirrors Virtus `attribute` interface to define attributes in
|
14
|
+
# custom jsonb objects.
|
15
|
+
#
|
16
|
+
# name - Attribute's name
|
17
|
+
# fields - The attribute's child fields
|
18
|
+
#
|
19
|
+
# Example:
|
20
|
+
# jsonb_attribute(:settings, [[:custom_setting, String], [:another_setting, Boolean])
|
21
|
+
# # This will generate `custom_setting`, `custom_setting=` and
|
22
|
+
# # `another_setting`, `another_setting=` and will keep them
|
23
|
+
# # syncronized with a hash in `settings`:
|
24
|
+
# # settings = { "custom_setting" => "demo", "another_setting" => "demo"}
|
25
|
+
#
|
26
|
+
# Returns nothing.
|
27
|
+
def jsonb_attribute(name, fields, *options)
|
28
|
+
attribute name, Hash, default: {}
|
29
|
+
|
30
|
+
fields.each do |f, type|
|
31
|
+
attribute f, type, *options
|
32
|
+
define_method f do
|
33
|
+
field = public_send(name) || {}
|
34
|
+
field[f.to_s] || field[f.to_sym]
|
35
|
+
end
|
36
|
+
|
37
|
+
define_method "#{f}=" do |value|
|
38
|
+
field = public_send(name) || {}
|
39
|
+
public_send("#{name}=", field.merge(f => super(value)))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
# This concern contains the logic related to newsletter participants
|
7
|
+
module NewsletterParticipant
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
# Returns a User collection Participants
|
12
|
+
# This is the default, if you want, you can overwrite in each Class to be export.
|
13
|
+
def self.newsletter_participant_ids(_component)
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/decidim/participable.rb
CHANGED
@@ -75,6 +75,15 @@ module Decidim
|
|
75
75
|
def can_participate?(_user)
|
76
76
|
true
|
77
77
|
end
|
78
|
+
|
79
|
+
def empty_published_component?
|
80
|
+
components.published.empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
def cta_button_text_key
|
84
|
+
return :more_info if empty_published_component?
|
85
|
+
:take_part
|
86
|
+
end
|
78
87
|
end
|
79
88
|
|
80
89
|
class_methods do
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
#
|
5
|
+
# Takes care of holding and accessing permissions classes for each artifact.
|
6
|
+
#
|
7
|
+
class PermissionsRegistry
|
8
|
+
def initialize
|
9
|
+
@registry = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
# Syntactic sugar for the `chain_for` instance method.
|
13
|
+
def self.chain_for(artifact)
|
14
|
+
::Decidim.permissions_registry.chain_for(artifact)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the registered array of permissions for the given `artifact`.
|
18
|
+
#
|
19
|
+
# +artifact+ is expected to be the class or module that declares `NeedsPermission.permission_class_chain`.
|
20
|
+
def chain_for(artifact)
|
21
|
+
@registry[artifact_to_key(artifact)]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Registers the of `Permissions` for the given `artifact`.
|
25
|
+
#
|
26
|
+
# +artifact+ is expected to be the class or module that declares `NeedsPermission.permission_class_chain`.
|
27
|
+
# +permission_classes+ are subclasses of `DefaultPermissions`.
|
28
|
+
def register_permissions(artifact, *permission_classes)
|
29
|
+
@registry[artifact_to_key(artifact)] = permission_classes.dup
|
30
|
+
end
|
31
|
+
|
32
|
+
# Registry accepts the class or the class name of the artifact,
|
33
|
+
# but the registry only indexes by the name.
|
34
|
+
# Artifact name normalization is done here.
|
35
|
+
def artifact_to_key(artifact)
|
36
|
+
artifact.respond_to?(:name) ? artifact.name : artifact
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|