decidim-core 0.27.5 → 0.27.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/cells/decidim/activity_cell.rb +2 -2
- data/app/cells/decidim/card_cell.rb +2 -2
- data/app/cells/decidim/card_m/top.erb +1 -1
- data/app/cells/decidim/card_m_cell.rb +1 -1
- data/app/cells/decidim/scopes_picker/scope_picker_values.erb +1 -1
- data/app/cells/decidim/tags_cell.rb +3 -1
- data/app/cells/decidim/user_profile_cell.rb +1 -1
- data/app/commands/decidim/create_omniauth_registration.rb +2 -4
- data/app/commands/decidim/messaging/reply_to_conversation.rb +3 -0
- data/app/commands/decidim/messaging/start_conversation.rb +3 -0
- data/app/controllers/concerns/decidim/devise_authentication_methods.rb +36 -0
- data/app/controllers/concerns/decidim/paginable.rb +1 -1
- data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +1 -22
- data/app/controllers/decidim/devise/sessions_controller.rb +1 -24
- data/app/controllers/decidim/widgets_controller.rb +6 -0
- data/app/events/decidim/welcome_notification_event.rb +6 -9
- data/app/helpers/decidim/cells_paginate_helper.rb +1 -1
- data/app/helpers/decidim/check_boxes_tree_helper.rb +4 -4
- data/app/helpers/decidim/newsletters_helper.rb +83 -16
- data/app/helpers/decidim/resource_helper.rb +1 -1
- data/app/helpers/decidim/sanitize_helper.rb +9 -0
- data/app/helpers/decidim/user_profile_helper.rb +7 -2
- data/app/mailers/decidim/messaging/conversation_mailer.rb +3 -72
- data/app/models/decidim/push_notification_message.rb +39 -0
- data/app/packs/images/decidim/.keep +0 -0
- data/app/packs/src/decidim/input_hashtags.js +1 -1
- data/app/packs/src/decidim/input_mentions.js +1 -1
- data/app/packs/src/decidim/input_multiple_mentions.js +1 -1
- data/app/packs/src/decidim/vizzs/index.js +1 -1
- data/app/packs/stylesheets/decidim/plugins/leaflet.scss +118 -114
- data/app/presenters/decidim/admin_log/oauth_application_resource_presenter.rb +1 -1
- data/app/presenters/decidim/notification_to_mailer_presenter.rb +9 -0
- data/app/services/decidim/events_manager.rb +6 -0
- data/app/services/decidim/push_notification_message_sender.rb +36 -0
- data/app/services/decidim/send_push_notification.rb +22 -8
- data/app/views/decidim/devise/registrations/new.html.erb +2 -2
- data/app/views/decidim/notifications_digest_mailer/_email_content.html.erb +7 -0
- data/app/views/decidim/shared/_address_details.html.erb +2 -2
- data/app/views/layouts/decidim/_js_configuration.html.erb +1 -0
- data/config/locales/ar.yml +4 -2
- data/config/locales/bg.yml +74 -0
- data/config/locales/ca.yml +22 -22
- data/config/locales/de.yml +25 -25
- data/config/locales/el.yml +1 -3
- data/config/locales/es-MX.yml +1 -1
- data/config/locales/es-PY.yml +1 -1
- data/config/locales/es.yml +20 -20
- data/config/locales/eu.yml +11 -2
- data/config/locales/fi.yml +3 -3
- data/config/locales/fr-CA.yml +2 -2
- data/config/locales/fr.yml +2 -2
- data/config/locales/gl.yml +3 -0
- data/config/locales/he-IL.yml +1 -0
- data/config/locales/hu.yml +41 -8
- data/config/locales/it.yml +1 -3
- data/config/locales/ja.yml +3 -2
- data/config/locales/lb.yml +1 -3
- data/config/locales/lt.yml +0 -3
- data/config/locales/no.yml +1 -3
- data/config/locales/pl.yml +137 -1
- data/config/locales/pt-BR.yml +113 -21
- data/config/locales/pt.yml +1 -3
- data/config/locales/ro-RO.yml +0 -3
- data/config/locales/ru.yml +9 -0
- data/config/locales/sk.yml +2 -0
- data/config/locales/sv.yml +22 -2
- data/config/locales/tr-TR.yml +1 -3
- data/config/locales/uk.yml +14 -0
- data/config/locales/zh-CN.yml +0 -3
- data/config/locales/zh-TW.yml +0 -3
- data/decidim-core.gemspec +78 -0
- data/lib/decidim/acts_as_tree.rb +14 -1
- data/lib/decidim/asset_router/storage.rb +4 -0
- data/lib/decidim/attribute_encryptor.rb +6 -4
- data/lib/decidim/core/engine.rb +7 -3
- data/lib/decidim/core/test/factories.rb +308 -95
- data/lib/decidim/core/test/shared_examples/amendable/amendment_created_event_examples.rb +6 -26
- data/lib/decidim/core/test/shared_examples/amendable/amendment_promoted_event_examples.rb +8 -26
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +32 -0
- data/lib/decidim/core/test/shared_examples/embed_resource_examples.rb +187 -11
- data/lib/decidim/core/test/shared_examples/has_attachment_collections.rb +8 -6
- data/lib/decidim/core/test/shared_examples/has_attachments.rb +4 -4
- data/lib/decidim/core/test/shared_examples/has_category.rb +27 -0
- data/lib/decidim/core/test/shared_examples/has_reference.rb +1 -1
- data/lib/decidim/core/test/shared_examples/has_space_in_mcell_examples.rb +1 -2
- data/lib/decidim/core/test/shared_examples/resource_endorsed_event_examples.rb +6 -3
- data/lib/decidim/core/test/shared_examples/resource_locator_presenter_examples.rb +134 -0
- data/lib/decidim/core/test/shared_examples/searchable_results_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/simple_event.rb +50 -2
- data/lib/decidim/core/test.rb +1 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/core.rb +1 -0
- data/lib/decidim/engine_router.rb +17 -4
- data/lib/decidim/events/base_event.rb +5 -2
- data/lib/decidim/events/simple_event.rb +3 -17
- data/lib/decidim/has_category.rb +1 -1
- data/lib/decidim/has_conversations.rb +91 -0
- data/lib/decidim/participable.rb +17 -0
- data/lib/decidim/view_model.rb +1 -0
- data/lib/decidim/webpacker/webpack/.modernizrrc +9 -0
- data/lib/premailer/adapter/decidim.rb +5 -4
- data/lib/tasks/decidim_reminders_tasks.rake +1 -0
- data/lib/tasks/upgrade/decidim_fix_categorization.rake +15 -0
- metadata +31 -30
- data/config/environment.rb +0 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 99119ce695e1aa34d4a744deca10b822209b52253058e77548a6399cd78f0069
|
|
4
|
+
data.tar.gz: '052746495077e884e4cb8e5bc33c8bcb6af257efbee57b385b39f62404530fd5'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e5b7a3d7779697415e7ec9badd7d4d00bd408a1f42e7c667f01b797558ba22524231273b94f3f6beeb644f7aee8692bd5d2d580a7493c84dfaa5eb563241bc58
|
|
7
|
+
data.tar.gz: 193b200909cc1fa784ccad5583b3c9593b8e6a9be31c10ab03c90ee9153075ac0d168566e7fe275bb9140c1bc53a8a42e58f84ffc9b852fe91269deef496d5a3
|
|
@@ -28,11 +28,11 @@ module Decidim
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def title
|
|
31
|
-
model.try(:title) || model.try(:name) || ""
|
|
31
|
+
decidim_escape_translated(model.try(:title) || model.try(:name) || "")
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def body
|
|
35
|
-
model.try(:body) || model.try(:about) || ""
|
|
35
|
+
decidim_escape_translated(model.try(:body) || model.try(:about) || "")
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def resource_manifest
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div class="card__top">
|
|
2
2
|
<% if render_space? %>
|
|
3
3
|
<div class="card__content text-small">
|
|
4
|
-
<span class="muted"><%= searchable_resource_human_name(model.participatory_space.class, count: 1) %>:</span> <%= link_to
|
|
4
|
+
<span class="muted"><%= searchable_resource_human_name(model.participatory_space.class, count: 1) %>:</span> <%= link_to decidim_escape_translated(model.participatory_space.title), Decidim::ResourceLocatorPresenter.new(model.participatory_space).path, class: "card__link text-ellipsis" %>
|
|
5
5
|
</div>
|
|
6
6
|
<% end %>
|
|
7
7
|
</div>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div class="picker-values">
|
|
2
2
|
<%- scopes.each do |scope, params| %>
|
|
3
|
-
<div><%= link_to params[:text], params[:url], data: { picker_value: scope.id } %></div>
|
|
3
|
+
<div><%= link_to decidim_html_escape(params[:text]), params[:url], data: { picker_value: scope.id } %></div>
|
|
4
4
|
<% end %>
|
|
5
5
|
</div>
|
|
@@ -9,6 +9,8 @@ module Decidim
|
|
|
9
9
|
# <%= cell("decidim/category", model.category, context: {resource: model}) %>
|
|
10
10
|
#
|
|
11
11
|
class TagsCell < Decidim::ViewModel
|
|
12
|
+
include Decidim::SanitizeHelper
|
|
13
|
+
|
|
12
14
|
def show
|
|
13
15
|
render if category? || scope?
|
|
14
16
|
end
|
|
@@ -51,7 +53,7 @@ module Decidim
|
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
def category_name
|
|
54
|
-
model.category.translated_name
|
|
56
|
+
decidim_html_escape model.category.translated_name
|
|
55
57
|
end
|
|
56
58
|
|
|
57
59
|
def category_path
|
|
@@ -57,14 +57,12 @@ module Decidim
|
|
|
57
57
|
# to be marked confirmed.
|
|
58
58
|
@user.skip_confirmation! if !@user.confirmed? && @user.email == verified_email
|
|
59
59
|
else
|
|
60
|
-
generated_password = SecureRandom.hex
|
|
61
|
-
|
|
62
60
|
@user.email = (verified_email || form.email)
|
|
63
61
|
@user.name = form.name
|
|
64
62
|
@user.nickname = form.normalized_nickname
|
|
65
63
|
@user.newsletter_notifications_at = nil
|
|
66
|
-
@user.password =
|
|
67
|
-
@user.password_confirmation =
|
|
64
|
+
@user.password = SecureRandom.hex
|
|
65
|
+
@user.password_confirmation = @user.password
|
|
68
66
|
if form.avatar_url.present?
|
|
69
67
|
url = URI.parse(form.avatar_url)
|
|
70
68
|
filename = File.basename(url.path)
|
|
@@ -54,11 +54,13 @@ module Decidim
|
|
|
54
54
|
notify(manager) do
|
|
55
55
|
ConversationMailer.new_group_message(sender, manager, conversation, message, recipient).deliver_later
|
|
56
56
|
end
|
|
57
|
+
Decidim::PushNotificationMessageSender.new.new_group_message(sender, manager, conversation, message, recipient).deliver
|
|
57
58
|
end
|
|
58
59
|
else
|
|
59
60
|
notify(recipient) do
|
|
60
61
|
ConversationMailer.new_message(sender, recipient, conversation, message).deliver_later
|
|
61
62
|
end
|
|
63
|
+
Decidim::PushNotificationMessageSender.new.new_message(sender, recipient, conversation, message).deliver
|
|
62
64
|
end
|
|
63
65
|
end
|
|
64
66
|
end
|
|
@@ -68,6 +70,7 @@ module Decidim
|
|
|
68
70
|
notify(recipient) do
|
|
69
71
|
ConversationMailer.comanagers_new_message(sender, recipient, conversation, message, form.context.current_user).deliver_later
|
|
70
72
|
end
|
|
73
|
+
Decidim::PushNotificationMessageSender.new.comanagers_new_message(sender, recipient, conversation, message, form.context.current_user).deliver
|
|
71
74
|
end
|
|
72
75
|
end
|
|
73
76
|
|
|
@@ -54,11 +54,13 @@ module Decidim
|
|
|
54
54
|
notify(manager) do
|
|
55
55
|
ConversationMailer.new_group_conversation(originator, manager, conversation, recipient).deliver_later
|
|
56
56
|
end
|
|
57
|
+
Decidim::PushNotificationMessageSender.new.new_group_conversation(originator, manager, conversation, recipient).deliver
|
|
57
58
|
end
|
|
58
59
|
else
|
|
59
60
|
notify(recipient) do
|
|
60
61
|
ConversationMailer.new_conversation(originator, recipient, conversation).deliver_later
|
|
61
62
|
end
|
|
63
|
+
Decidim::PushNotificationMessageSender.new.new_conversation(originator, recipient, conversation).deliver
|
|
62
64
|
end
|
|
63
65
|
end
|
|
64
66
|
end
|
|
@@ -68,6 +70,7 @@ module Decidim
|
|
|
68
70
|
notify(recipient) do
|
|
69
71
|
ConversationMailer.comanagers_new_conversation(originator, recipient, conversation, form.context.current_user).deliver_later
|
|
70
72
|
end
|
|
73
|
+
Decidim::PushNotificationMessageSender.new.comanagers_new_conversation(originator, recipient, conversation, form.context.current_user).deliver
|
|
71
74
|
end
|
|
72
75
|
end
|
|
73
76
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/concern"
|
|
4
|
+
|
|
5
|
+
module Decidim
|
|
6
|
+
module DeviseAuthenticationMethods
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
include Decidim::UserBlockedChecker
|
|
9
|
+
|
|
10
|
+
included do
|
|
11
|
+
def after_sign_in_path_for(user)
|
|
12
|
+
if user.present? && user.blocked?
|
|
13
|
+
check_user_block_status(user)
|
|
14
|
+
elsif user.needs_password_update?
|
|
15
|
+
change_password_path
|
|
16
|
+
elsif first_login_and_not_authorized?(user) && !user.admin? && !pending_redirect?(user)
|
|
17
|
+
decidim_verifications.first_login_authorizations_path
|
|
18
|
+
else
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Calling the `stored_location_for` method removes the key, so in order
|
|
24
|
+
# to check if there is any pending redirect after login I need to call
|
|
25
|
+
# this method and use the value to set a pending redirect. This is the
|
|
26
|
+
# only way to do this without checking the session directly.
|
|
27
|
+
def pending_redirect?(user)
|
|
28
|
+
store_location_for(user, stored_location_for(user))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def first_login_and_not_authorized?(user)
|
|
32
|
+
user.is_a?(User) && user.sign_in_count == 1 && current_organization.available_authorizations.any? && user.verifiable?
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -6,6 +6,7 @@ module Decidim
|
|
|
6
6
|
class OmniauthRegistrationsController < ::Devise::OmniauthCallbacksController
|
|
7
7
|
include FormFactory
|
|
8
8
|
include Decidim::DeviseControllers
|
|
9
|
+
include Decidim::DeviseAuthenticationMethods
|
|
9
10
|
|
|
10
11
|
def new
|
|
11
12
|
@form = form(OmniauthRegistrationForm).from_params(params[:user])
|
|
@@ -45,28 +46,6 @@ module Decidim
|
|
|
45
46
|
end
|
|
46
47
|
end
|
|
47
48
|
|
|
48
|
-
def after_sign_in_path_for(user)
|
|
49
|
-
if user.present? && user.blocked?
|
|
50
|
-
check_user_block_status(user)
|
|
51
|
-
elsif !pending_redirect?(user) && first_login_and_not_authorized?(user)
|
|
52
|
-
decidim_verifications.authorizations_path
|
|
53
|
-
else
|
|
54
|
-
super
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Calling the `stored_location_for` method removes the key, so in order
|
|
59
|
-
# to check if there's any pending redirect after login I need to call
|
|
60
|
-
# this method and use the value to set a pending redirect. This is the
|
|
61
|
-
# only way to do this without checking the session directly.
|
|
62
|
-
def pending_redirect?(user)
|
|
63
|
-
store_location_for(user, stored_location_for(user))
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def first_login_and_not_authorized?(user)
|
|
67
|
-
user.is_a?(User) && user.sign_in_count == 1 && Decidim::Verifications.workflows.any? && user.verifiable?
|
|
68
|
-
end
|
|
69
|
-
|
|
70
49
|
def action_missing(action_name)
|
|
71
50
|
return send(:create) if devise_mapping.omniauthable? && current_organization.enabled_omniauth_providers.keys.include?(action_name.to_sym)
|
|
72
51
|
|
|
@@ -5,6 +5,7 @@ module Decidim
|
|
|
5
5
|
# Custom Devise SessionsController to avoid namespace problems.
|
|
6
6
|
class SessionsController < ::Devise::SessionsController
|
|
7
7
|
include Decidim::DeviseControllers
|
|
8
|
+
include Decidim::DeviseAuthenticationMethods
|
|
8
9
|
|
|
9
10
|
before_action :check_sign_in_enabled, only: :create
|
|
10
11
|
|
|
@@ -35,30 +36,6 @@ module Decidim
|
|
|
35
36
|
end
|
|
36
37
|
end
|
|
37
38
|
|
|
38
|
-
def after_sign_in_path_for(user)
|
|
39
|
-
if user.present? && user.blocked?
|
|
40
|
-
check_user_block_status(user)
|
|
41
|
-
elsif user.needs_password_update?
|
|
42
|
-
change_password_path
|
|
43
|
-
elsif first_login_and_not_authorized?(user) && !user.admin? && !pending_redirect?(user)
|
|
44
|
-
decidim_verifications.first_login_authorizations_path
|
|
45
|
-
else
|
|
46
|
-
super
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# Calling the `stored_location_for` method removes the key, so in order
|
|
51
|
-
# to check if there's any pending redirect after login I need to call
|
|
52
|
-
# this method and use the value to set a pending redirect. This is the
|
|
53
|
-
# only way to do this without checking the session directly.
|
|
54
|
-
def pending_redirect?(user)
|
|
55
|
-
store_location_for(user, stored_location_for(user))
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def first_login_and_not_authorized?(user)
|
|
59
|
-
user.is_a?(User) && user.sign_in_count == 1 && current_organization.available_authorizations.any? && user.verifiable?
|
|
60
|
-
end
|
|
61
|
-
|
|
62
39
|
def after_sign_out_path_for(user)
|
|
63
40
|
request.referer || super
|
|
64
41
|
end
|
|
@@ -11,6 +11,8 @@ module Decidim
|
|
|
11
11
|
helper_method :model, :iframe_url, :current_participatory_space
|
|
12
12
|
|
|
13
13
|
def show
|
|
14
|
+
raise ActionController::RoutingError, "Not Found" if model.nil?
|
|
15
|
+
|
|
14
16
|
respond_to do |format|
|
|
15
17
|
format.js { render "decidim/widgets/show" }
|
|
16
18
|
format.html
|
|
@@ -19,6 +21,10 @@ module Decidim
|
|
|
19
21
|
|
|
20
22
|
private
|
|
21
23
|
|
|
24
|
+
def current_component
|
|
25
|
+
@current_component ||= request.env["decidim.current_component"]
|
|
26
|
+
end
|
|
27
|
+
|
|
22
28
|
def current_participatory_space
|
|
23
29
|
@current_participatory_space ||= model.component.participatory_space
|
|
24
30
|
end
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "mustache"
|
|
4
|
-
|
|
5
3
|
module Decidim
|
|
6
4
|
class WelcomeNotificationEvent < Decidim::Events::BaseEvent
|
|
7
5
|
include Decidim::Events::EmailEvent
|
|
@@ -46,13 +44,12 @@ module Decidim
|
|
|
46
44
|
private
|
|
47
45
|
|
|
48
46
|
def interpolate(template)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
organization
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
).html_safe
|
|
47
|
+
template
|
|
48
|
+
.gsub("{{name}}", user.name)
|
|
49
|
+
.gsub("{{organization}}", organization.name)
|
|
50
|
+
.gsub("{{help_url}}", url_helpers.pages_url(host: organization.host))
|
|
51
|
+
.gsub("{{badges_url}}", url_helpers.gamification_badges_url(host: organization.host))
|
|
52
|
+
.html_safe
|
|
56
53
|
end
|
|
57
54
|
end
|
|
58
55
|
end
|
|
@@ -50,20 +50,20 @@ module Decidim
|
|
|
50
50
|
organization = current_participatory_space.organization
|
|
51
51
|
|
|
52
52
|
sorted_main_categories = current_participatory_space.categories.first_class.includes(:subcategories).sort_by do |category|
|
|
53
|
-
[category.weight, translated_attribute(category.name, organization)]
|
|
53
|
+
[category.weight, decidim_html_escape(translated_attribute(category.name, organization))]
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
categories_values = sorted_main_categories.flat_map do |category|
|
|
57
57
|
sorted_descendant_categories = category.descendants.includes(:subcategories).sort_by do |subcategory|
|
|
58
|
-
[subcategory.weight, translated_attribute(subcategory.name, organization)]
|
|
58
|
+
[subcategory.weight, decidim_html_escape(translated_attribute(subcategory.name, organization))]
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
subcategories = sorted_descendant_categories.flat_map do |subcategory|
|
|
62
|
-
TreePoint.new(subcategory.id.to_s, translated_attribute(subcategory.name, organization))
|
|
62
|
+
TreePoint.new(subcategory.id.to_s, decidim_html_escape(translated_attribute(subcategory.name, organization)))
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
TreeNode.new(
|
|
66
|
-
TreePoint.new(category.id.to_s, translated_attribute(category.name, organization)),
|
|
66
|
+
TreePoint.new(category.id.to_s, decidim_html_escape(translated_attribute(category.name, organization))),
|
|
67
67
|
subcategories
|
|
68
68
|
)
|
|
69
69
|
end
|
|
@@ -8,28 +8,28 @@ module Decidim
|
|
|
8
8
|
# for example transform "https://es.lipsum.com/" to "https://es.lipsum.com/?utm_source=localhost&utm_campaign=newsletter_11"
|
|
9
9
|
# And replace "%{name}" on the subject or content of newsletter to the user Name
|
|
10
10
|
# for example transform "%{name}" to "User Name"
|
|
11
|
+
#
|
|
12
|
+
# @param content [String] - the string to convert
|
|
13
|
+
# @param user [Decidim::User] - the user to replace
|
|
14
|
+
# @param id [Integer] - the id of the newsletter to change
|
|
15
|
+
#
|
|
16
|
+
# @return [String] - the content converted
|
|
11
17
|
def parse_interpolations(content, user = nil, id = nil)
|
|
12
|
-
|
|
13
|
-
host = user.organization.host.to_s
|
|
14
|
-
campaign = "newsletter_#{id}"
|
|
18
|
+
host = user&.organization&.host&.to_s
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
link_replaced = link.first + utm_codes(host, campaign)
|
|
20
|
-
content = content.gsub(/href\s*=\s*"([^"]*#{link.first})"/, %(href="#{link_replaced}"))
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
if user.present?
|
|
25
|
-
content.gsub("%{name}", user.name)
|
|
26
|
-
else
|
|
27
|
-
content.gsub("%{name}", "")
|
|
28
|
-
end
|
|
20
|
+
content = interpret_name(content, user)
|
|
21
|
+
content = track_newsletter_links(content, id, host)
|
|
22
|
+
transform_image_urls(content, host)
|
|
29
23
|
end
|
|
30
24
|
|
|
31
25
|
# this method is used to generate the root link on mail with the utm_codes
|
|
32
26
|
# If the newsletter_id is nil, it returns the root_url
|
|
27
|
+
#
|
|
28
|
+
# @param organization [Decidim::Organization] - the Organization of this newsletter
|
|
29
|
+
# @param newsletter_id [Integer] - the id of the newsletter
|
|
30
|
+
#
|
|
31
|
+
# @return [String] - the root_url converted
|
|
32
|
+
#
|
|
33
33
|
def custom_url_for_mail_root(organization, newsletter_id = nil)
|
|
34
34
|
decidim = EngineRouter.new("decidim", {})
|
|
35
35
|
if newsletter_id.present?
|
|
@@ -39,10 +39,77 @@ module Decidim
|
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
private
|
|
43
|
+
|
|
42
44
|
# Method to specify the utm_codes.
|
|
43
45
|
# You can change or add utm_codes for track
|
|
46
|
+
#
|
|
47
|
+
# @param host [String] - the Decidim::Organization host add to the URL
|
|
48
|
+
# @param newsletter_id [String] - the ID of the newsletter
|
|
49
|
+
#
|
|
50
|
+
# @return [String] - the UTM codes to be added
|
|
51
|
+
#
|
|
44
52
|
def utm_codes(host, newsletter_id)
|
|
45
53
|
"?utm_source=#{host}&utm_campaign=#{newsletter_id}"
|
|
46
54
|
end
|
|
55
|
+
|
|
56
|
+
# Interpret placeholder '%{name}' and replace by the user name
|
|
57
|
+
# If user is not define, it returns content with blank instead of the placeholder
|
|
58
|
+
#
|
|
59
|
+
# @param content [String] - the string to convert
|
|
60
|
+
# @param user [Decidim::User] - the user to replace
|
|
61
|
+
#
|
|
62
|
+
# @return [String] - the content converted
|
|
63
|
+
#
|
|
64
|
+
def interpret_name(content, user)
|
|
65
|
+
return content.gsub("%{name}", "") if user.blank?
|
|
66
|
+
|
|
67
|
+
content.gsub("%{name}", user.name)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Find each img HTML tag with relative path in src attribute
|
|
71
|
+
# For each URL, prepends the decidim.root_url
|
|
72
|
+
# If host is not defined it returns full content
|
|
73
|
+
#
|
|
74
|
+
# @param content [String] - the string to convert
|
|
75
|
+
# @param host [String] - the Decidim::Organization host to replace
|
|
76
|
+
#
|
|
77
|
+
# @return [String] - the content converted
|
|
78
|
+
#
|
|
79
|
+
def transform_image_urls(content, host)
|
|
80
|
+
return content if host.blank?
|
|
81
|
+
|
|
82
|
+
content.scan(/src\s*=\s*"([^"]*)"/).each do |src|
|
|
83
|
+
root_url = decidim.root_url(host: host)[0..-2]
|
|
84
|
+
src_replaced = "#{root_url}#{src.first}"
|
|
85
|
+
content = content.gsub(/src\s*=\s*"([^"]*#{src.first})"/, %(src="#{src_replaced}"))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
content
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Add tracking query params to each links
|
|
92
|
+
#
|
|
93
|
+
# @param content [String] - the string to convert
|
|
94
|
+
# @param id [Integer] - the id of the newsletter
|
|
95
|
+
# @param host [String] - the Decidim::Organization host
|
|
96
|
+
#
|
|
97
|
+
# @return [String] - the content converted
|
|
98
|
+
#
|
|
99
|
+
def track_newsletter_links(content, id, host)
|
|
100
|
+
return content unless Decidim.config.track_newsletter_links
|
|
101
|
+
return content if id.blank?
|
|
102
|
+
return content if host.blank?
|
|
103
|
+
|
|
104
|
+
campaign = "newsletter_#{id}"
|
|
105
|
+
links = content.scan(/href\s*=\s*"([^"]*)"/)
|
|
106
|
+
|
|
107
|
+
links.each do |link|
|
|
108
|
+
link_replaced = link.first + utm_codes(host, campaign)
|
|
109
|
+
content = content.gsub(/href\s*=\s*"([^"]*#{link.first})"/, %(href="#{link_replaced}"))
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
content
|
|
113
|
+
end
|
|
47
114
|
end
|
|
48
115
|
end
|
|
@@ -75,7 +75,7 @@ module Decidim
|
|
|
75
75
|
# Returns a descriptive title for the resource
|
|
76
76
|
def resource_title(resource)
|
|
77
77
|
title = resource.try(:title) || resource.try(:name) || resource.try(:subject) || "#{resource.model_name.human} ##{resource.id}"
|
|
78
|
-
title =
|
|
78
|
+
title = decidim_escape_translated(title) if title.is_a?(Hash)
|
|
79
79
|
title
|
|
80
80
|
end
|
|
81
81
|
end
|
|
@@ -6,6 +6,7 @@ module Decidim
|
|
|
6
6
|
def self.included(base)
|
|
7
7
|
base.include ActionView::Helpers::SanitizeHelper
|
|
8
8
|
base.include ActionView::Helpers::TagHelper
|
|
9
|
+
base.include Decidim::TranslatableAttributes
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
# Public: It sanitizes a user-inputted string with the
|
|
@@ -53,6 +54,14 @@ module Decidim
|
|
|
53
54
|
decidim_html_escape(text).sub(/^javascript:/, "")
|
|
54
55
|
end
|
|
55
56
|
|
|
57
|
+
def decidim_sanitize_translated(text)
|
|
58
|
+
decidim_sanitize(translated_attribute(text))
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def decidim_escape_translated(text)
|
|
62
|
+
decidim_html_escape(translated_attribute(text))
|
|
63
|
+
end
|
|
64
|
+
|
|
56
65
|
private
|
|
57
66
|
|
|
58
67
|
# Maintains the paragraphs and lists separations with their bullet points and
|
|
@@ -14,9 +14,14 @@ module Decidim
|
|
|
14
14
|
#
|
|
15
15
|
# Returns a String with the menu tab.
|
|
16
16
|
def user_profile_tab(text, link, options = {})
|
|
17
|
-
|
|
17
|
+
aria = {}
|
|
18
|
+
cls = %w(tabs-title)
|
|
19
|
+
if is_active_link?(link, (options[:aria_link_type] || :inclusive))
|
|
20
|
+
cls << "is-active"
|
|
21
|
+
aria[:current] = "page"
|
|
22
|
+
end
|
|
18
23
|
|
|
19
|
-
content_tag(:li, class: "
|
|
24
|
+
content_tag(:li, class: cls.join(" "), aria: aria) do
|
|
20
25
|
link_to(text, link, options)
|
|
21
26
|
end
|
|
22
27
|
end
|
|
@@ -5,74 +5,12 @@ module Decidim
|
|
|
5
5
|
# A custom mailer for sending notifications to users when they receive
|
|
6
6
|
# private messages
|
|
7
7
|
class ConversationMailer < Decidim::ApplicationMailer
|
|
8
|
-
|
|
9
|
-
notification_mail(
|
|
10
|
-
from: originator,
|
|
11
|
-
to: user,
|
|
12
|
-
conversation: conversation,
|
|
13
|
-
message: conversation.messages.first.body,
|
|
14
|
-
action: "new_conversation"
|
|
15
|
-
)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def new_group_conversation(originator, manager, conversation, group)
|
|
19
|
-
notification_mail(
|
|
20
|
-
from: originator,
|
|
21
|
-
to: manager,
|
|
22
|
-
conversation: conversation,
|
|
23
|
-
message: conversation.messages.first.body,
|
|
24
|
-
action: "new_group_conversation",
|
|
25
|
-
third_party: group
|
|
26
|
-
)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def comanagers_new_conversation(group, user, conversation, manager)
|
|
30
|
-
notification_mail(
|
|
31
|
-
from: group,
|
|
32
|
-
to: user,
|
|
33
|
-
conversation: conversation,
|
|
34
|
-
message: conversation.messages.first.body,
|
|
35
|
-
action: "comanagers_new_conversation",
|
|
36
|
-
third_party: manager
|
|
37
|
-
)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def new_message(sender, user, conversation, message)
|
|
41
|
-
notification_mail(
|
|
42
|
-
from: sender,
|
|
43
|
-
to: user,
|
|
44
|
-
conversation: conversation,
|
|
45
|
-
message: message.body,
|
|
46
|
-
action: "new_message"
|
|
47
|
-
)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def new_group_message(sender, user, conversation, message, group)
|
|
51
|
-
notification_mail(
|
|
52
|
-
from: sender,
|
|
53
|
-
to: user,
|
|
54
|
-
conversation: conversation,
|
|
55
|
-
message: message.body,
|
|
56
|
-
action: "new_group_message",
|
|
57
|
-
third_party: group
|
|
58
|
-
)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def comanagers_new_message(sender, user, conversation, message, manager)
|
|
62
|
-
notification_mail(
|
|
63
|
-
from: sender,
|
|
64
|
-
to: user,
|
|
65
|
-
conversation: conversation,
|
|
66
|
-
message: message.body,
|
|
67
|
-
action: "comanagers_new_message",
|
|
68
|
-
third_party: manager
|
|
69
|
-
)
|
|
70
|
-
end
|
|
8
|
+
include HasConversations
|
|
71
9
|
|
|
72
10
|
private
|
|
73
11
|
|
|
74
12
|
# rubocop:disable Metrics/ParameterLists
|
|
75
|
-
def
|
|
13
|
+
def send_notification(from:, to:, conversation:, action:, message: nil, third_party: nil)
|
|
76
14
|
with_user(to) do
|
|
77
15
|
@organization = to.organization
|
|
78
16
|
@conversation = conversation
|
|
@@ -81,14 +19,7 @@ module Decidim
|
|
|
81
19
|
@third_party = third_party
|
|
82
20
|
@message = message
|
|
83
21
|
@host = @organization.host
|
|
84
|
-
|
|
85
|
-
subject = I18n.t(
|
|
86
|
-
"conversation_mailer.#{action}.subject",
|
|
87
|
-
scope: "decidim.messaging",
|
|
88
|
-
sender: @sender.name,
|
|
89
|
-
manager: @third_party&.name,
|
|
90
|
-
group: @third_party&.name
|
|
91
|
-
)
|
|
22
|
+
subject = get_subject(action: action, sender: @sender, third_party: @third_party)
|
|
92
23
|
|
|
93
24
|
mail(to: to.email, subject: subject)
|
|
94
25
|
end
|