decidim-core 0.8.4 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +1 -1
- data/app/assets/images/decidim/decidim-logo.svg +23 -23
- data/app/assets/images/decidim/default-avatar.svg +7 -7
- data/app/assets/images/decidim/icons.svg +1 -0
- data/app/assets/javascripts/decidim.js.es6 +5 -2
- data/app/assets/javascripts/decidim/append_redirect_url_to_modals.js.es6 +84 -0
- data/app/assets/javascripts/decidim/data_picker.js.es6 +177 -0
- data/app/assets/javascripts/decidim/form_filter.component.js.es6 +25 -20
- data/app/assets/javascripts/decidim/form_filter.component.test.js +24 -13
- data/app/assets/javascripts/decidim/history.js.es6 +3 -3
- data/app/assets/stylesheets/decidim/_decidim.scss +1 -4
- data/app/assets/stylesheets/decidim/_variables.scss +4 -4
- data/app/assets/stylesheets/decidim/editor.scss +13 -0
- data/app/assets/stylesheets/decidim/email.css +9 -1
- data/app/assets/stylesheets/decidim/extras/_add_comments.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_announcement.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_collection-sort-controls.scss +2 -2
- data/app/assets/stylesheets/decidim/extras/_embed.scss +6 -5
- data/app/assets/stylesheets/decidim/extras/_impersonation-bar.scss +4 -0
- data/app/assets/stylesheets/decidim/extras/_label-required.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_leaflet.scss +6 -4
- data/app/assets/stylesheets/decidim/extras/_meeting-registrations.scss +4 -4
- data/app/assets/stylesheets/decidim/extras/_process_stats.scss +11 -4
- data/app/assets/stylesheets/decidim/extras/_proposal_form.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_quill.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_reference.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_register_form.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_results-per-page.scss +10 -10
- data/app/assets/stylesheets/decidim/extras/_social_icons_mini.scss +4 -3
- data/app/assets/stylesheets/decidim/layouts/_highlighted_banner.scss +38 -0
- data/app/assets/stylesheets/decidim/layouts/_home.scss +33 -3
- data/app/assets/stylesheets/decidim/layouts/_user.scss +33 -5
- data/app/assets/stylesheets/decidim/layouts/_view.scss +1 -2
- data/app/assets/stylesheets/decidim/map.css +5 -3
- data/app/assets/stylesheets/decidim/modules/_address.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_author-avatar.scss +24 -9
- data/app/assets/stylesheets/decidim/modules/_buttons.scss +24 -10
- data/app/assets/stylesheets/decidim/modules/_callout.scss +5 -1
- data/app/assets/stylesheets/decidim/modules/_card-grid.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_cards.scss +102 -31
- data/app/assets/stylesheets/decidim/modules/_comments.scss +21 -20
- data/app/assets/stylesheets/decidim/modules/_cookie-bar.scss +4 -0
- data/app/assets/stylesheets/decidim/modules/_data-picker.scss +159 -0
- data/app/assets/stylesheets/decidim/modules/_datepicker.scss +36 -36
- data/app/assets/stylesheets/decidim/modules/_definition-data.scss +12 -9
- data/app/assets/stylesheets/decidim/modules/_extra.scss +4 -1
- data/app/assets/stylesheets/decidim/modules/_filter-tags.scss +3 -0
- data/app/assets/stylesheets/decidim/modules/_filters.scss +9 -5
- data/app/assets/stylesheets/decidim/modules/_flag.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_footer.scss +10 -0
- data/app/assets/stylesheets/decidim/modules/_forms.scss +2 -1
- data/app/assets/stylesheets/decidim/modules/_help.scss +2 -0
- data/app/assets/stylesheets/decidim/modules/_icons.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_layout.scss +4 -0
- data/app/assets/stylesheets/decidim/modules/_list-docs.scss +3 -0
- data/app/assets/stylesheets/decidim/modules/_main-container.scss +13 -7
- data/app/assets/stylesheets/decidim/modules/_map.scss +13 -1
- data/app/assets/stylesheets/decidim/modules/_margins.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_messages.scss +2 -1
- data/app/assets/stylesheets/decidim/modules/_modules.scss +3 -0
- data/app/assets/stylesheets/decidim/modules/_navbar.scss +36 -16
- data/app/assets/stylesheets/decidim/modules/_omnipresent_banner.scss +26 -0
- data/app/assets/stylesheets/decidim/modules/_opinion-toggle.scss +5 -0
- data/app/assets/stylesheets/decidim/modules/_order-by.scss +10 -10
- data/app/assets/stylesheets/decidim/modules/_pagination.scss +3 -2
- data/app/assets/stylesheets/decidim/modules/_process-header.scss +11 -2
- data/app/assets/stylesheets/decidim/modules/_process-info.scss +9 -1
- data/app/assets/stylesheets/decidim/modules/_process-nav.scss +20 -3
- data/app/assets/stylesheets/decidim/modules/_process-phase.scss +12 -3
- data/app/assets/stylesheets/decidim/modules/_progress-bar.scss +69 -0
- data/app/assets/stylesheets/decidim/modules/_reference.scss +1 -2
- data/app/assets/stylesheets/decidim/modules/_reveal.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_share.scss +2 -0
- data/app/assets/stylesheets/decidim/modules/_signup.scss +5 -1
- data/app/assets/stylesheets/decidim/modules/_static-pages.scss +6 -0
- data/app/assets/stylesheets/decidim/modules/_status-labels.scss +2 -0
- data/app/assets/stylesheets/decidim/modules/_tags.scss +3 -1
- data/app/assets/stylesheets/decidim/modules/_timeline.scss +41 -30
- data/app/assets/stylesheets/decidim/modules/_title-action.scss +2 -1
- data/app/assets/stylesheets/decidim/modules/_typography.scss +13 -4
- data/app/assets/stylesheets/decidim/modules/_user-form.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_video.scss +2 -2
- data/app/assets/stylesheets/decidim/utils/_fontface.scss +22 -20
- data/app/assets/stylesheets/decidim/utils/_helpers.scss +6 -6
- data/app/assets/stylesheets/decidim/utils/_keyframes.scss +6 -6
- data/app/assets/stylesheets/decidim/utils/_mixins.scss +24 -7
- data/app/assets/stylesheets/decidim/utils/_settings.scss +50 -52
- data/app/assets/stylesheets/decidim/utils/_toggle-expand.scss +1 -0
- data/app/commands/decidim/create_omniauth_registration.rb +3 -0
- data/app/commands/decidim/create_registration.rb +3 -1
- data/app/commands/decidim/destroy_account.rb +1 -0
- data/app/commands/decidim/invite_user_again.rb +1 -1
- data/app/commands/decidim/messaging/reply_to_conversation.rb +1 -3
- data/app/commands/decidim/unsubscribe_settings.rb +29 -0
- data/app/commands/decidim/update_account.rb +16 -3
- data/app/controllers/concerns/decidim/action_authorization.rb +1 -1
- data/app/controllers/concerns/decidim/devise_controllers.rb +10 -0
- data/app/controllers/concerns/decidim/form_factory.rb +2 -1
- data/app/controllers/concerns/decidim/impersonate_users.rb +13 -8
- data/app/controllers/concerns/decidim/participatory_space_context.rb +1 -1
- data/app/controllers/decidim/application_controller.rb +16 -0
- data/app/controllers/decidim/cookie_policy_controller.rb +2 -0
- data/app/controllers/decidim/devise/invitations_controller.rb +9 -1
- data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +10 -1
- data/app/controllers/decidim/devise/sessions_controller.rb +9 -1
- data/app/controllers/decidim/locales_controller.rb +2 -3
- data/app/controllers/decidim/messaging/conversations_controller.rb +2 -2
- data/app/controllers/decidim/newsletters_controller.rb +60 -0
- data/app/controllers/decidim/pages_controller.rb +1 -0
- data/app/controllers/decidim/profiles_controller.rb +23 -0
- data/app/controllers/decidim/scopes_controller.rb +19 -20
- data/app/events/decidim/profile_updated_event.rb +27 -0
- data/app/forms/decidim/account_form.rb +34 -0
- data/app/forms/decidim/form.rb +1 -0
- data/app/forms/decidim/messaging/conversation_form.rb +5 -2
- data/app/forms/decidim/omniauth_registration_form.rb +5 -0
- data/app/forms/decidim/registration_form.rb +8 -1
- data/app/helpers/decidim/action_authorization_helper.rb +2 -2
- data/app/helpers/decidim/application_helper.rb +8 -0
- data/app/helpers/decidim/feature_path_helper.rb +12 -2
- data/app/helpers/decidim/feature_reference_helper.rb +1 -1
- data/app/helpers/decidim/messaging/conversation_helper.rb +27 -9
- data/app/helpers/decidim/newsletters_helper.rb +49 -0
- data/app/helpers/decidim/scopes_helper.rb +43 -2
- data/app/helpers/decidim/translations_helper.rb +6 -2
- data/app/mailers/decidim/decidim_devise_mailer.rb +1 -3
- data/app/mailers/decidim/messaging/conversation_mailer.rb +1 -1
- data/app/mailers/decidim/newsletter_mailer.rb +7 -8
- data/app/models/decidim/abilities/everyone_ability.rb +1 -0
- data/app/models/decidim/authorization.rb +19 -5
- data/app/models/decidim/impersonation_log.rb +2 -1
- data/app/models/decidim/messaging/conversation.rb +2 -0
- data/app/models/decidim/messaging/message.rb +4 -0
- data/app/models/decidim/organization.rb +1 -0
- data/app/models/decidim/scope.rb +10 -2
- data/app/models/decidim/user.rb +10 -2
- data/app/presenters/decidim/home_stats_presenter.rb +10 -4
- data/app/presenters/decidim/user_group_presenter.rb +28 -0
- data/app/presenters/decidim/user_presenter.rb +42 -0
- data/app/services/decidim/action_authorizer.rb +32 -68
- data/app/services/decidim/notification_generator_for_recipient.rb +8 -3
- data/app/uploaders/decidim/avatar_uploader.rb +2 -2
- data/app/views/decidim/account/delete.html.erb +1 -1
- data/app/views/decidim/account/show.html.erb +4 -1
- data/app/views/decidim/devise/invitations/edit.html.erb +2 -0
- data/app/views/decidim/devise/omniauth_registrations/new.html.erb +7 -1
- data/app/views/decidim/devise/registrations/new.html.erb +7 -1
- data/app/views/decidim/messaging/conversations/_message.html.erb +6 -12
- data/app/views/decidim/messaging/conversations/_reply.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/index.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/update.js.erb +1 -0
- data/app/views/decidim/newsletter_mailer/newsletter.html.erb +11 -0
- data/app/views/decidim/newsletters/show.html.erb +11 -0
- data/app/views/decidim/newsletters/unsubscribe.html.erb +4 -0
- data/app/views/decidim/notifications/_notification.html.erb +1 -1
- data/app/views/decidim/profiles/show.html.erb +64 -0
- data/app/views/decidim/scopes/_scopes_picker_input.html.erb +6 -0
- data/app/views/decidim/scopes/picker.html.erb +36 -0
- data/app/views/decidim/shared/_action_authorization_modal.html.erb +25 -51
- data/app/views/decidim/shared/_author.html.erb +21 -0
- data/app/views/decidim/shared/_author_reference.html.erb +12 -0
- data/app/views/layouts/decidim/_application.html.erb +1 -0
- data/app/views/layouts/decidim/_impersonation_warning.html.erb +1 -1
- data/app/views/layouts/decidim/_mailer_logo.html.erb +6 -1
- data/app/views/layouts/decidim/_omnipresent_banner.html.erb +14 -0
- data/app/views/layouts/decidim/_user_menu.html.erb +3 -0
- data/app/views/layouts/decidim/mailer.html.erb +16 -4
- data/app/views/layouts/decidim/widget.html.erb +14 -9
- data/app/views/pages/home.html.erb +2 -0
- data/app/views/pages/home/_highlighted_content_banner.html.erb +26 -0
- data/config/initializers/devise.rb +1 -3
- data/config/locales/ca.yml +67 -9
- data/config/locales/en.yml +65 -4
- data/config/locales/es.yml +74 -14
- data/config/locales/eu.yml +66 -4
- data/config/locales/fi.yml +87 -25
- data/config/locales/fr.yml +71 -9
- data/config/locales/gl.yml +493 -0
- data/config/locales/it.yml +79 -17
- data/config/locales/nl.yml +71 -9
- data/config/locales/pl.yml +66 -4
- data/config/locales/pt-BR.yml +493 -0
- data/config/locales/pt.yml +99 -37
- data/config/locales/ru.yml +85 -13
- data/config/locales/sv.yml +493 -0
- data/config/locales/uk.yml +78 -16
- data/config/routes.rb +11 -1
- data/db/migrate/20171212103803_create_unique_nicknames.rb +29 -0
- data/db/migrate/20180115090038_extend_user_profile.rb +8 -0
- data/db/migrate/20180123125308_add_enable_omnipresent_banner_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180123125409_add_omnipresent_banner_title_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180123125432_add_omnipresent_banner_short_description_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180123125452_add_omnipresent_banner_url_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180125063433_add_highlighted_content_banner_to_decidim_organizations.rb +13 -0
- data/db/seeds.rb +8 -2
- data/lib/decidim/abilities/participatory_process_role_ability.rb +1 -3
- data/lib/decidim/content_parsers.rb +8 -0
- data/lib/decidim/content_parsers/base_parser.rb +58 -0
- data/lib/decidim/content_parsers/user_parser.rb +46 -0
- data/lib/decidim/content_processor.rb +84 -0
- data/lib/decidim/content_renderers.rb +8 -0
- data/lib/decidim/content_renderers/base_renderer.rb +37 -0
- data/lib/decidim/content_renderers/user_renderer.rb +32 -0
- data/lib/decidim/core.rb +66 -1
- data/lib/decidim/core/api/author_interface.rb +3 -3
- data/lib/decidim/core/api/user_group_type.rb +10 -8
- data/lib/decidim/core/api/user_type.rb +13 -7
- data/lib/decidim/core/engine.rb +7 -5
- data/lib/decidim/core/test.rb +1 -1
- data/lib/decidim/core/test/factories.rb +21 -45
- data/lib/decidim/core/test/shared_examples/announcements_examples.rb +3 -2
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +5 -2
- data/lib/decidim/core/test/shared_examples/scope_helper_examples.rb +40 -3
- data/lib/decidim/core/test/shared_examples/simple_event.rb +73 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/events.rb +2 -0
- data/lib/decidim/events/author_event.rb +41 -0
- data/lib/decidim/events/base_event.rb +28 -3
- data/lib/decidim/events/email_event.rb +1 -1
- data/lib/decidim/events/notification_event.rb +1 -1
- data/lib/decidim/events/simple_event.rb +79 -0
- data/lib/decidim/filter_form_builder.rb +2 -3
- data/lib/decidim/form_builder.rb +39 -27
- data/lib/decidim/friendly_dates.rb +26 -0
- data/lib/decidim/has_feature.rb +1 -0
- data/lib/decidim/has_reference.rb +1 -1
- data/lib/decidim/i18n_exceptions.rb +1 -3
- data/lib/decidim/menu.rb +1 -1
- data/lib/decidim/newsletter_encryptor.rb +22 -0
- data/lib/decidim/nicknamizable.rb +56 -0
- data/lib/decidim/participable.rb +8 -0
- data/lib/decidim/participatory_space_manifest.rb +10 -1
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.gl.js +13 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.pt-br.js +14 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.pt.js +5 -1
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.ru.js +4 -1
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.sv.js +14 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.uk.js +4 -1
- data/vendor/assets/javascripts/form_datepicker.js.es6 +4 -2
- data/vendor/assets/javascripts/foundation-datepicker.js +42 -26
- metadata +124 -84
- data/app/assets/javascripts/decidim/select2.field.js.es6 +0 -47
- data/app/assets/javascripts/decidim/select2.js.es6 +0 -11
- data/app/assets/stylesheets/decidim/editor.sass +0 -4
- data/app/assets/stylesheets/decidim/plugins/_select2.scss +0 -63
- data/app/helpers/decidim/datetime_helper.rb +0 -23
- data/app/queries/decidim/freetext_scopes.rb +0 -39
- data/lib/decidim/core/test/shared_examples/manage_moderations_examples.rb +0 -64
@@ -36,10 +36,11 @@ shared_examples "manage announcements" do
|
|
36
36
|
|
37
37
|
it "customize an announcement for the current step and it has more priority" do
|
38
38
|
visit edit_feature_path(current_feature)
|
39
|
+
step_id = current_feature.participatory_space.steps.first.id
|
39
40
|
|
40
41
|
fill_in_i18n_editor(
|
41
|
-
:
|
42
|
-
"#step-
|
42
|
+
:"feature_step_settings_#{step_id}_announcement",
|
43
|
+
"#step-#{step_id}-settings-announcement-tabs",
|
43
44
|
en: "An announcement for this step",
|
44
45
|
es: "Un aviso para esta fase",
|
45
46
|
ca: "Un avís per a aquesta fase"
|
@@ -23,12 +23,14 @@ shared_examples "comments" do
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
it "allows user to sort the comments" do
|
26
|
+
it "allows user to sort the comments", :slow do
|
27
27
|
comment = create(:comment, commentable: commentable, body: "Most Rated Comment")
|
28
28
|
create(:comment_vote, comment: comment, author: user, weight: 1)
|
29
29
|
|
30
30
|
visit resource_path
|
31
31
|
|
32
|
+
expect(page).to have_no_content("Comments are disabled at this time")
|
33
|
+
|
32
34
|
expect(page).to have_css(".comment", minimum: 1)
|
33
35
|
page.find(".order-by .dropdown.menu .is-dropdown-submenu-parent").hover
|
34
36
|
|
@@ -88,7 +90,7 @@ shared_examples "comments" do
|
|
88
90
|
end
|
89
91
|
end
|
90
92
|
|
91
|
-
context "when a user replies to a comment" do
|
93
|
+
context "when a user replies to a comment", :slow do
|
92
94
|
let!(:comment_author) { create(:user, :confirmed, organization: organization) }
|
93
95
|
let!(:comment) { create(:comment, commentable: commentable, author: comment_author) }
|
94
96
|
|
@@ -99,6 +101,7 @@ shared_examples "comments" do
|
|
99
101
|
|
100
102
|
within "#comments #comment_#{comment.id}" do
|
101
103
|
click_button "Reply"
|
104
|
+
expect(page).to have_selector(".add-comment")
|
102
105
|
fill_in "add-comment-Decidim::Comments::Comment-#{comment.id}", with: "This is a reply"
|
103
106
|
click_button "Send"
|
104
107
|
end
|
@@ -10,13 +10,19 @@ shared_examples "scope helpers" do
|
|
10
10
|
let(:scope) { create(:scope, organization: organization) }
|
11
11
|
let(:resource) { create(:dummy_resource, feature: feature, scope: scope) }
|
12
12
|
|
13
|
-
subject { helper.has_visible_scopes?(resource) }
|
14
|
-
|
15
13
|
before do
|
16
14
|
allow(helper).to receive(:current_participatory_space).and_return(participatory_space)
|
17
15
|
end
|
16
|
+
let(:helper) do
|
17
|
+
Class.new.tap do |v|
|
18
|
+
v.extend(Decidim::ScopesHelper)
|
19
|
+
v.extend(Decidim::TranslationsHelper)
|
20
|
+
end
|
21
|
+
end
|
18
22
|
|
19
23
|
describe "has_visible_scopes?" do
|
24
|
+
subject { helper.has_visible_scopes?(resource) }
|
25
|
+
|
20
26
|
context "when all conditions are met" do
|
21
27
|
it { is_expected.to be_truthy }
|
22
28
|
end
|
@@ -26,8 +32,13 @@ shared_examples "scope helpers" do
|
|
26
32
|
it { is_expected.to be_falsey }
|
27
33
|
end
|
28
34
|
|
29
|
-
context "when the process has a scope" do
|
35
|
+
context "when the process has a different scope than the organization" do
|
30
36
|
let(:participatory_space_scope) { create(:scope, organization: organization) }
|
37
|
+
it { is_expected.to be_truthy }
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when the process has the same scope as the organization" do
|
41
|
+
let(:participatory_space_scope) { scope }
|
31
42
|
it { is_expected.to be_falsey }
|
32
43
|
end
|
33
44
|
|
@@ -36,4 +47,30 @@ shared_examples "scope helpers" do
|
|
36
47
|
it { is_expected.to be_falsey }
|
37
48
|
end
|
38
49
|
end
|
50
|
+
|
51
|
+
describe "scope_name_for_picker" do
|
52
|
+
let(:global_name) { "Global name" }
|
53
|
+
subject { helper.scope_name_for_picker(scope, global_name) }
|
54
|
+
|
55
|
+
context "when a scope is given" do
|
56
|
+
context "when the scope has a scope type" do
|
57
|
+
it { is_expected.to include(scope.name["en"]) }
|
58
|
+
it { is_expected.to include(scope.scope_type.name["en"]) }
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when the scope has no type" do
|
62
|
+
before do
|
63
|
+
scope.scope_type = nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it { is_expected.to eq(scope.name["en"]) }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when no scope is given" do
|
71
|
+
let(:scope) { nil }
|
72
|
+
|
73
|
+
it { is_expected.to eq("Global name") }
|
74
|
+
end
|
75
|
+
end
|
39
76
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
shared_context "simple event" do
|
6
|
+
subject do
|
7
|
+
described_class.new(
|
8
|
+
resource: resource,
|
9
|
+
event_name: event_name,
|
10
|
+
user: user,
|
11
|
+
extra: extra
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:organization) do
|
16
|
+
if resource.respond_to?(:organization)
|
17
|
+
resource.organization
|
18
|
+
else
|
19
|
+
create :organization
|
20
|
+
end
|
21
|
+
end
|
22
|
+
let(:user) { create :user, organization: organization }
|
23
|
+
let(:extra) { {} }
|
24
|
+
let(:resource_path) { resource_locator(resource).path }
|
25
|
+
let(:resource_url) { resource_locator(resource).url }
|
26
|
+
let(:resource_title) { resource.title["en"] }
|
27
|
+
let(:author) { resource.author }
|
28
|
+
let(:author_presenter) { Decidim::UserPresenter.new(author) }
|
29
|
+
end
|
30
|
+
|
31
|
+
shared_examples_for "an simple event" do
|
32
|
+
describe "types" do
|
33
|
+
subject { described_class }
|
34
|
+
|
35
|
+
it "supports notifications" do
|
36
|
+
expect(subject.types).to include :notification
|
37
|
+
end
|
38
|
+
|
39
|
+
it "supports emails" do
|
40
|
+
expect(subject.types).to include :email
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "email_subject" do
|
45
|
+
it "is generated correctly" do
|
46
|
+
expect(subject.email_subject).to be_kind_of(String)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "email_intro" do
|
51
|
+
it "is generated correctly" do
|
52
|
+
expect(subject.email_intro).to be_kind_of(String)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "email_outro" do
|
57
|
+
it "is generated correctly" do
|
58
|
+
expect(subject.email_outro).to be_kind_of(String)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "email_greeting" do
|
63
|
+
it "is generated correctly" do
|
64
|
+
expect(subject.email_greeting).to be_kind_of(String)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "notification_title" do
|
69
|
+
it "is generated correctly" do
|
70
|
+
expect(subject.notification_title).to be_kind_of(String)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/decidim/core/version.rb
CHANGED
data/lib/decidim/events.rb
CHANGED
@@ -5,5 +5,7 @@ module Decidim
|
|
5
5
|
autoload :BaseEvent, "decidim/events/base_event"
|
6
6
|
autoload :EmailEvent, "decidim/events/email_event"
|
7
7
|
autoload :NotificationEvent, "decidim/events/notification_event"
|
8
|
+
autoload :SimpleEvent, "decidim/events/simple_event"
|
9
|
+
autoload :AuthorEvent, "decidim/events/author_event"
|
8
10
|
end
|
9
11
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Events
|
5
|
+
# This module is used to be included in event classes inheriting from SimpleEvent
|
6
|
+
# whose resource has an author.
|
7
|
+
#
|
8
|
+
# It adds the author_name, author_nickname, author_path and author_url to the i18n interpolations.
|
9
|
+
module AuthorEvent
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
i18n_attributes :author_name, :author_nickname, :author_path, :author_url
|
14
|
+
|
15
|
+
def author_nickname
|
16
|
+
author_presenter.nickname
|
17
|
+
end
|
18
|
+
|
19
|
+
def author_name
|
20
|
+
author_presenter.name
|
21
|
+
end
|
22
|
+
|
23
|
+
def author_path
|
24
|
+
author_presenter.profile_path
|
25
|
+
end
|
26
|
+
|
27
|
+
def author_url
|
28
|
+
author_presenter.profile_url
|
29
|
+
end
|
30
|
+
|
31
|
+
def author_presenter
|
32
|
+
@author ||= Decidim::UserPresenter.new(author)
|
33
|
+
end
|
34
|
+
|
35
|
+
def author
|
36
|
+
resource.author if resource.respond_to?(:author)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -6,6 +6,9 @@ module Decidim
|
|
6
6
|
# add more logic to a `Decidim::Notification` and are used to render them in the
|
7
7
|
# notifications dashboard and to generate other notifications (emails, for example).
|
8
8
|
class BaseEvent
|
9
|
+
class_attribute :types
|
10
|
+
self.types = []
|
11
|
+
|
9
12
|
# Public: Stores all the notification types this event can create. Please, do not
|
10
13
|
# overwrite this method, consider it final. Instead, add values to the array via
|
11
14
|
# modules, take the `NotificationEvent` module as an example:
|
@@ -16,7 +19,7 @@ module Decidim
|
|
16
19
|
# extend ActiveSupport::Concern
|
17
20
|
#
|
18
21
|
# included do
|
19
|
-
#
|
22
|
+
# type :web_push_notifications
|
20
23
|
# end
|
21
24
|
# end
|
22
25
|
#
|
@@ -25,8 +28,8 @@ module Decidim
|
|
25
28
|
# end
|
26
29
|
#
|
27
30
|
# MyEvent.types # => [:web_push_notifications]
|
28
|
-
def self.
|
29
|
-
|
31
|
+
def self.type(type)
|
32
|
+
self.types += Array(type)
|
30
33
|
end
|
31
34
|
|
32
35
|
# Initializes the class.
|
@@ -58,10 +61,32 @@ module Decidim
|
|
58
61
|
@resource_url ||= resource_locator.url
|
59
62
|
end
|
60
63
|
|
64
|
+
# Whether this event should be notified or not. Useful when you want the
|
65
|
+
# event to decide based on the params.
|
66
|
+
#
|
67
|
+
# It returns false when the resource or any element in the chain is a
|
68
|
+
# `Decidim::Publicable` and it isn't published.
|
69
|
+
def notifiable?
|
70
|
+
return false if resource.is_a?(Decidim::Publicable) && !resource.published?
|
71
|
+
return false if participatory_space.is_a?(Decidim::Publicable) && !participatory_space&.published?
|
72
|
+
return false unless feature&.published?
|
73
|
+
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
61
77
|
private
|
62
78
|
|
63
79
|
attr_reader :event_name, :resource, :user, :extra
|
64
80
|
|
81
|
+
def feature
|
82
|
+
return resource.feature if resource.is_a?(Decidim::HasFeature)
|
83
|
+
return resource if resource.is_a?(Decidim::Feature)
|
84
|
+
end
|
85
|
+
|
86
|
+
def participatory_space
|
87
|
+
return feature.participatory_space if feature
|
88
|
+
end
|
89
|
+
|
65
90
|
def resource_title
|
66
91
|
resource.title.is_a?(Hash) ? resource.title[I18n.locale.to_s] : resource.title
|
67
92
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Events
|
5
|
+
# Extends the BaseEvent to add common features to most events so you don't
|
6
|
+
# need to write each time the same code.
|
7
|
+
#
|
8
|
+
# The only convention you need to keep in mind is that the event name will be
|
9
|
+
# used as the i18n scope to search for the keys.
|
10
|
+
class SimpleEvent < BaseEvent
|
11
|
+
include Decidim::Events::EmailEvent
|
12
|
+
include Decidim::Events::NotificationEvent
|
13
|
+
|
14
|
+
class_attribute :i18n_interpolations
|
15
|
+
self.i18n_interpolations = []
|
16
|
+
|
17
|
+
# Public: A method to add values to pass as interpolations to the I18n.t method.
|
18
|
+
#
|
19
|
+
# By default the resource_path, resource_title and resource_url are already included.
|
20
|
+
#
|
21
|
+
# attribute - A Symbol of the method name (and interpolation value) to add.
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
#
|
25
|
+
# class MyEvent < Decidim::Events::SimpleEvent
|
26
|
+
# i18n_attributes :participatory_space_title
|
27
|
+
# end
|
28
|
+
def self.i18n_attributes(*attributes)
|
29
|
+
self.i18n_interpolations += Array(attributes)
|
30
|
+
end
|
31
|
+
|
32
|
+
def email_subject
|
33
|
+
I18n.t("email_subject", i18n_options).html_safe
|
34
|
+
end
|
35
|
+
|
36
|
+
def email_intro
|
37
|
+
I18n.t("email_intro", i18n_options).html_safe
|
38
|
+
end
|
39
|
+
|
40
|
+
def email_outro
|
41
|
+
I18n.t("email_outro", i18n_options).html_safe
|
42
|
+
end
|
43
|
+
|
44
|
+
def notification_title
|
45
|
+
I18n.t("notification_title", i18n_options).html_safe
|
46
|
+
end
|
47
|
+
|
48
|
+
# Public: The String to use as scope to search for the keys
|
49
|
+
# when using I18n.t
|
50
|
+
#
|
51
|
+
# By default is the same value as the event name.
|
52
|
+
def i18n_scope
|
53
|
+
event_name
|
54
|
+
end
|
55
|
+
|
56
|
+
# Public: The Hash of options to pass to the I18.t method.
|
57
|
+
def i18n_options
|
58
|
+
default_i18n_options.merge(event_interpolations)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def event_interpolations
|
64
|
+
Array(self.class.i18n_interpolations).inject({}) do |all, attribute|
|
65
|
+
all.update(attribute => send(attribute))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def default_i18n_options
|
70
|
+
{
|
71
|
+
resource_path: resource_path,
|
72
|
+
resource_title: resource_title,
|
73
|
+
resource_url: resource_url,
|
74
|
+
scope: i18n_scope
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# rubocop:disable Metrics/ParameterLists
|
4
3
|
require "decidim/form_builder"
|
5
4
|
|
6
5
|
module Decidim
|
@@ -41,8 +40,8 @@ module Decidim
|
|
41
40
|
end
|
42
41
|
end
|
43
42
|
|
44
|
-
# Wrap the scopes
|
45
|
-
def
|
43
|
+
# Wrap the scopes picker in a custom fieldset.
|
44
|
+
def scopes_picker(method, options = {})
|
46
45
|
fieldset_wrapper options[:legend_title] do
|
47
46
|
super(method, options)
|
48
47
|
end
|
data/lib/decidim/form_builder.rb
CHANGED
@@ -25,6 +25,7 @@ module Decidim
|
|
25
25
|
def collection_check_boxes(attribute, collection, value_attribute, text_attribute, options = {}, html_options = {})
|
26
26
|
super + error_and_help_text(attribute, options)
|
27
27
|
end
|
28
|
+
# rubocop:enable Metrics/ParameterLists
|
28
29
|
|
29
30
|
# Public: Generates an form field for each locale.
|
30
31
|
#
|
@@ -131,29 +132,28 @@ module Decidim
|
|
131
132
|
select(name, @template.options_for_select(categories, selected: selected, disabled: disabled), options, html_options)
|
132
133
|
end
|
133
134
|
|
134
|
-
# Public: Generates a
|
135
|
+
# Public: Generates a picker field for scope selection.
|
135
136
|
#
|
136
|
-
# name
|
137
|
-
#
|
138
|
-
#
|
139
|
-
# -
|
137
|
+
# name - The name of the field (usually scope_id)
|
138
|
+
# options - An optional Hash with options:
|
139
|
+
# - multiple - Multiple mode, to allow multiple scopes selection.
|
140
|
+
# - label - Show label?
|
141
|
+
#
|
142
|
+
# Also it should receive a block that returns a Hash with :url and :text for each selected scope (and for null scope for prompt)
|
140
143
|
#
|
141
144
|
# Returns a String.
|
142
|
-
def
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
selected = [selected] unless selected.is_a?(Array)
|
147
|
-
scopes = Decidim::Scope.where(id: selected.map(&:to_i)).map { |scope| [scope.name[I18n.locale.to_s], scope.id] }
|
148
|
-
else
|
149
|
-
scopes = []
|
150
|
-
end
|
151
|
-
prompt = options.delete(:prompt)
|
152
|
-
remote_path = options.delete(:remote_path) || false
|
153
|
-
multiple = options.delete(:multiple) || false
|
154
|
-
html_options = { multiple: multiple, class: "select2", "data-remote-path" => remote_path, "data-placeholder" => prompt }
|
145
|
+
def scopes_picker(attribute, options = {})
|
146
|
+
picker_options = { id: "#{@object_name}_#{attribute}", class: "picker-#{options[:multiple] ? "multiple" : "single"}",
|
147
|
+
name: "#{@object_name}[#{attribute}]" }
|
148
|
+
picker_options[:class] += " is-invalid-input" if error?(attribute)
|
155
149
|
|
156
|
-
|
150
|
+
prompt_params = yield(nil)
|
151
|
+
scopes = selected_scopes(attribute).map { |scope| [scope, yield(scope)] }
|
152
|
+
template = ""
|
153
|
+
template += label(attribute, label_for(attribute) + required_for_attribute(attribute)) unless options[:label] == false
|
154
|
+
template += @template.render("decidim/scopes/scopes_picker_input", picker_options: picker_options, prompt_params: prompt_params, scopes: scopes)
|
155
|
+
template += error_and_help_text(attribute, options)
|
156
|
+
template.html_safe
|
157
157
|
end
|
158
158
|
|
159
159
|
# Public: Override so checkboxes are rendered before the label.
|
@@ -259,6 +259,17 @@ module Decidim
|
|
259
259
|
template.html_safe
|
260
260
|
end
|
261
261
|
|
262
|
+
# Public: Returns the translated name for the given attribute.
|
263
|
+
#
|
264
|
+
# attribute - The String name of the attribute to return the name.
|
265
|
+
def label_for(attribute)
|
266
|
+
if object.class.respond_to?(:human_attribute_name)
|
267
|
+
object.class.human_attribute_name(attribute)
|
268
|
+
else
|
269
|
+
attribute.to_s.humanize
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
262
273
|
private
|
263
274
|
|
264
275
|
# Private: Override from FoundationRailsHelper in order to render
|
@@ -461,14 +472,6 @@ module Decidim
|
|
461
472
|
end
|
462
473
|
end
|
463
474
|
|
464
|
-
def label_for(attribute)
|
465
|
-
if object.class.respond_to?(:human_attribute_name)
|
466
|
-
object.class.human_attribute_name(attribute)
|
467
|
-
else
|
468
|
-
attribute.to_s.humanize
|
469
|
-
end
|
470
|
-
end
|
471
|
-
|
472
475
|
def name_with_locale(name, locale)
|
473
476
|
"#{name}_#{locale.to_s.gsub("-", "__")}"
|
474
477
|
end
|
@@ -506,5 +509,14 @@ module Decidim
|
|
506
509
|
end
|
507
510
|
"".html_safe
|
508
511
|
end
|
512
|
+
|
513
|
+
# Private: Returns an array of scopes related to object attribute
|
514
|
+
def selected_scopes(attribute)
|
515
|
+
selected = object.send(attribute) || []
|
516
|
+
selected = selected.values if selected.is_a?(Hash)
|
517
|
+
selected = [selected] unless selected.is_a?(Array)
|
518
|
+
selected = Decidim::Scope.where(id: selected.map(&:to_i)) unless selected.first.is_a?(Decidim::Scope)
|
519
|
+
selected
|
520
|
+
end
|
509
521
|
end
|
510
522
|
end
|