decidim-core 0.27.4 → 0.27.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/activity_cell.rb +2 -2
  3. data/app/cells/decidim/card_cell.rb +2 -2
  4. data/app/cells/decidim/card_m/top.erb +1 -1
  5. data/app/cells/decidim/card_m_cell.rb +1 -1
  6. data/app/cells/decidim/scopes_picker/scope_picker_values.erb +1 -1
  7. data/app/cells/decidim/tags_cell.rb +3 -1
  8. data/app/cells/decidim/upload_modal/modal.erb +4 -1
  9. data/app/cells/decidim/upload_modal_cell.rb +8 -4
  10. data/app/cells/decidim/user_profile_cell.rb +1 -1
  11. data/app/cells/decidim/version_cell.rb +1 -1
  12. data/app/cells/decidim/versions_list_cell.rb +1 -1
  13. data/app/commands/decidim/create_omniauth_registration.rb +2 -4
  14. data/app/commands/decidim/endorse_resource.rb +2 -0
  15. data/app/commands/decidim/messaging/reply_to_conversation.rb +3 -0
  16. data/app/commands/decidim/messaging/start_conversation.rb +3 -0
  17. data/app/commands/decidim/search.rb +1 -1
  18. data/app/commands/decidim/unendorse_resource.rb +1 -1
  19. data/app/controllers/concerns/decidim/devise_authentication_methods.rb +36 -0
  20. data/app/controllers/concerns/decidim/force_authentication.rb +6 -2
  21. data/app/controllers/concerns/decidim/paginable.rb +1 -1
  22. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +1 -22
  23. data/app/controllers/decidim/devise/registrations_controller.rb +1 -1
  24. data/app/controllers/decidim/devise/sessions_controller.rb +1 -24
  25. data/app/controllers/decidim/links_controller.rb +1 -1
  26. data/app/controllers/decidim/searches_controller.rb +1 -1
  27. data/app/controllers/decidim/user_timeline_controller.rb +1 -1
  28. data/app/controllers/decidim/widgets_controller.rb +6 -0
  29. data/app/events/decidim/welcome_notification_event.rb +6 -9
  30. data/app/forms/decidim/account_form.rb +1 -1
  31. data/app/forms/decidim/notifications_settings_form.rb +0 -8
  32. data/app/forms/decidim/registration_form.rb +1 -1
  33. data/app/helpers/decidim/cells_paginate_helper.rb +1 -1
  34. data/app/helpers/decidim/check_boxes_tree_helper.rb +4 -4
  35. data/app/helpers/decidim/decidim_form_helper.rb +1 -0
  36. data/app/helpers/decidim/newsletters_helper.rb +83 -16
  37. data/app/helpers/decidim/omniauth_helper.rb +2 -0
  38. data/app/helpers/decidim/resource_helper.rb +3 -1
  39. data/app/helpers/decidim/sanitize_helper.rb +9 -0
  40. data/app/helpers/decidim/short_link_helper.rb +1 -1
  41. data/app/helpers/decidim/user_profile_helper.rb +7 -2
  42. data/app/jobs/decidim/download_your_data_export_job.rb +2 -1
  43. data/app/jobs/decidim/open_data_job.rb +2 -0
  44. data/app/mailers/decidim/messaging/conversation_mailer.rb +3 -72
  45. data/app/models/decidim/push_notification_message.rb +39 -0
  46. data/app/models/decidim/user.rb +9 -1
  47. data/app/packs/images/decidim/icons.svg +1 -1
  48. data/app/packs/images/decidim/vendor/social-share-button/x.svg +6 -0
  49. data/app/packs/src/decidim/autocomplete.js +11 -2
  50. data/app/packs/src/decidim/data_picker.js +1 -0
  51. data/app/packs/src/decidim/direct_uploads/upload_field.js +6 -4
  52. data/app/packs/src/decidim/direct_uploads/upload_modal.js +10 -8
  53. data/app/packs/src/decidim/direct_uploads/uploader.js +4 -1
  54. data/app/packs/src/decidim/geocoding/attach_input.js +4 -1
  55. data/app/packs/src/decidim/geocoding/provider/here.js +17 -21
  56. data/app/packs/src/decidim/geocoding/provider/photon.js +1 -1
  57. data/app/packs/src/decidim/input_hashtags.js +1 -1
  58. data/app/packs/src/decidim/input_mentions.js +1 -1
  59. data/app/packs/src/decidim/input_multiple_mentions.js +1 -1
  60. data/app/packs/src/decidim/utilities/text.js +17 -0
  61. data/app/packs/src/decidim/vizzs/index.js +1 -1
  62. data/app/packs/stylesheets/decidim/_variables.scss +1 -1
  63. data/app/packs/stylesheets/decidim/plugins/leaflet.scss +118 -114
  64. data/app/packs/stylesheets/decidim/vendor/_social_share_button.scss +4 -0
  65. data/app/presenters/decidim/admin_log/oauth_application_resource_presenter.rb +1 -1
  66. data/app/presenters/decidim/notification_to_mailer_presenter.rb +9 -0
  67. data/app/services/decidim/events_manager.rb +6 -0
  68. data/app/services/decidim/push_notification_message_sender.rb +36 -0
  69. data/app/services/decidim/send_push_notification.rb +22 -8
  70. data/app/views/decidim/devise/registrations/new.html.erb +2 -2
  71. data/app/views/decidim/notifications_digest_mailer/_email_content.html.erb +7 -0
  72. data/app/views/decidim/notifications_settings/show.html.erb +1 -1
  73. data/app/views/decidim/scopes/_scopes_picker_input.html.erb +1 -1
  74. data/app/views/decidim/searches/_filters.html.erb +3 -1
  75. data/app/views/decidim/shared/_address_details.html.erb +2 -2
  76. data/app/views/decidim/shared/_share_modal.html.erb +1 -1
  77. data/app/views/decidim/shared/participatory_space_filters/_filters.html.erb +1 -1
  78. data/app/views/layouts/decidim/_js_configuration.html.erb +1 -0
  79. data/app/views/layouts/decidim/_social_media_links.html.erb +2 -2
  80. data/config/locales/ar.yml +12 -16
  81. data/config/locales/bg.yml +77 -15
  82. data/config/locales/ca.yml +34 -30
  83. data/config/locales/cs.yml +18 -14
  84. data/config/locales/de.yml +62 -58
  85. data/config/locales/el.yml +11 -16
  86. data/config/locales/en.yml +5 -1
  87. data/config/locales/eo.yml +2 -3
  88. data/config/locales/es-MX.yml +15 -11
  89. data/config/locales/es-PY.yml +15 -11
  90. data/config/locales/es.yml +30 -26
  91. data/config/locales/eu.yml +500 -342
  92. data/config/locales/fi-plain.yml +7 -3
  93. data/config/locales/fi.yml +21 -17
  94. data/config/locales/fr-CA.yml +17 -13
  95. data/config/locales/fr.yml +12 -8
  96. data/config/locales/ga-IE.yml +5 -5
  97. data/config/locales/gl.yml +5 -19
  98. data/config/locales/he-IL.yml +1 -0
  99. data/config/locales/hu.yml +63 -23
  100. data/config/locales/id-ID.yml +4 -19
  101. data/config/locales/is-IS.yml +4 -2
  102. data/config/locales/it.yml +15 -17
  103. data/config/locales/ja.yml +26 -22
  104. data/config/locales/lb.yml +15 -17
  105. data/config/locales/lt.yml +55 -10
  106. data/config/locales/lv.yml +4 -16
  107. data/config/locales/nl.yml +12 -12
  108. data/config/locales/no.yml +8 -10
  109. data/config/locales/pl.yml +151 -1
  110. data/config/locales/pt-BR.yml +267 -22
  111. data/config/locales/pt.yml +8 -10
  112. data/config/locales/ro-RO.yml +4 -10
  113. data/config/locales/ru.yml +13 -17
  114. data/config/locales/sk.yml +7 -17
  115. data/config/locales/sl.yml +0 -5
  116. data/config/locales/sq-AL.yml +1 -0
  117. data/config/locales/sv.yml +55 -17
  118. data/config/locales/th-TH.yml +1 -0
  119. data/config/locales/tr-TR.yml +18 -15
  120. data/config/locales/uk.yml +17 -14
  121. data/config/locales/zh-CN.yml +6 -10
  122. data/config/locales/zh-TW.yml +0 -9
  123. data/db/migrate/20231027142329_change_default_value_for_decidim_endorsements.rb +11 -0
  124. data/db/seeds.rb +1 -0
  125. data/decidim-core.gemspec +78 -0
  126. data/lib/decidim/acts_as_tree.rb +14 -1
  127. data/lib/decidim/asset_router/storage.rb +4 -0
  128. data/lib/decidim/attribute_encryptor.rb +6 -4
  129. data/lib/decidim/core/engine.rb +7 -3
  130. data/lib/decidim/core/test/factories.rb +309 -95
  131. data/lib/decidim/core/test/shared_examples/amendable/amendment_created_event_examples.rb +6 -26
  132. data/lib/decidim/core/test/shared_examples/amendable/amendment_promoted_event_examples.rb +8 -26
  133. data/lib/decidim/core/test/shared_examples/comments_examples.rb +56 -0
  134. data/lib/decidim/core/test/shared_examples/embed_resource_examples.rb +187 -11
  135. data/lib/decidim/core/test/shared_examples/errors.rb +2 -0
  136. data/lib/decidim/core/test/shared_examples/has_attachment_collections.rb +8 -6
  137. data/lib/decidim/core/test/shared_examples/has_attachments.rb +4 -4
  138. data/lib/decidim/core/test/shared_examples/has_category.rb +27 -0
  139. data/lib/decidim/core/test/shared_examples/has_reference.rb +1 -1
  140. data/lib/decidim/core/test/shared_examples/has_space_in_mcell_examples.rb +1 -2
  141. data/lib/decidim/core/test/shared_examples/resource_endorsed_event_examples.rb +6 -3
  142. data/lib/decidim/core/test/shared_examples/resource_locator_presenter_examples.rb +134 -0
  143. data/lib/decidim/core/test/shared_examples/searchable_results_examples.rb +1 -1
  144. data/lib/decidim/core/test/shared_examples/simple_event.rb +50 -2
  145. data/lib/decidim/core/test.rb +1 -0
  146. data/lib/decidim/core/version.rb +1 -1
  147. data/lib/decidim/core.rb +2 -1
  148. data/lib/decidim/endorsable.rb +1 -1
  149. data/lib/decidim/engine_router.rb +17 -4
  150. data/lib/decidim/events/base_event.rb +5 -2
  151. data/lib/decidim/events/simple_event.rb +3 -17
  152. data/lib/decidim/exporters.rb +10 -1
  153. data/lib/decidim/form_builder.rb +1 -0
  154. data/lib/decidim/has_category.rb +3 -3
  155. data/lib/decidim/has_conversations.rb +91 -0
  156. data/lib/decidim/participable.rb +17 -0
  157. data/lib/decidim/view_model.rb +1 -0
  158. data/lib/decidim/webpacker/webpack/.modernizrrc +9 -0
  159. data/lib/premailer/adapter/decidim.rb +5 -4
  160. data/lib/tasks/decidim_reminders_tasks.rake +1 -0
  161. data/lib/tasks/upgrade/decidim_deduplicate_endorsements.rake +53 -0
  162. data/lib/tasks/upgrade/decidim_fix_categorization.rake +15 -0
  163. data/lib/tasks/upgrade/decidim_fix_short_url_resolver.rake +22 -0
  164. metadata +37 -32
  165. data/app/helpers/decidim/layout_helper.rb.orig +0 -225
  166. data/app/packs/stylesheets/decidim/modules/_dropdown_menu.scss +0 -9
  167. data/app/views/decidim/devise/registrations/new.html.erb.orig +0 -231
  168. /data/{config/environment.rb → app/packs/images/decidim/.keep} +0 -0
@@ -81,7 +81,7 @@ shared_examples "searchable results" do
81
81
  find("input#term").native.send_keys :enter
82
82
 
83
83
  expect(page).to have_current_path decidim.search_path, ignore_query: true
84
- expect(page).to have_content(/results for the search: "#{term}"/i)
84
+ expect(page).to have_content(/results for the search: "#{term.upcase}"/i)
85
85
  expect(page).to have_selector(".filters__section")
86
86
  expect(page.find("#search-count .section-heading").text.to_i).not_to be_positive
87
87
  end
@@ -28,10 +28,10 @@ shared_context "when a simple event" do
28
28
  let(:extra) { {} }
29
29
  let(:resource_path) { resource_locator(resource).path }
30
30
  let(:resource_url) { resource_locator(resource).url }
31
- let(:resource_title) { resource.title["en"] }
31
+ let(:resource_title) { decidim_sanitize_translated(resource.title) }
32
32
  # to be used when resource is a component resource, not a participatory space, in which case should be overriden
33
33
  let(:participatory_space) { resource.participatory_space }
34
- let(:participatory_space_title) { participatory_space.title["en"] }
34
+ let(:participatory_space_title) { decidim_sanitize_translated(participatory_space.title) }
35
35
  let(:participatory_space_path) { Decidim::ResourceLocatorPresenter.new(participatory_space).path }
36
36
  let(:participatory_space_url) { Decidim::ResourceLocatorPresenter.new(participatory_space).url }
37
37
  let(:author) do
@@ -65,6 +65,7 @@ shared_examples_for "a simple event" do |skip_space_checks|
65
65
  it "is generated correctly" do
66
66
  expect(subject.email_subject).to be_kind_of(String)
67
67
  expect(subject.email_subject).not_to include("translation missing")
68
+ expect(subject.email_subject).not_to include("script")
68
69
  end
69
70
  end
70
71
 
@@ -100,6 +101,7 @@ shared_examples_for "a simple event" do |skip_space_checks|
100
101
  it "is generated correctly" do
101
102
  expect(subject.notification_title).to be_kind_of(String)
102
103
  expect(subject.notification_title).not_to include("translation missing")
104
+ expect(subject.notification_title).not_to include("script")
103
105
  end
104
106
  end
105
107
 
@@ -129,6 +131,12 @@ shared_examples_for "a simple event" do |skip_space_checks|
129
131
  expect(subject.participatory_space_url).to start_with("http")
130
132
  end
131
133
  end
134
+
135
+ describe "participatory_space_title" do
136
+ it "is generated correctly" do
137
+ expect(translated(participatory_space.title)).to include("script")
138
+ end
139
+ end
132
140
  end
133
141
 
134
142
  describe "i18n_options" do
@@ -152,3 +160,43 @@ shared_examples_for "a simple event" do |skip_space_checks|
152
160
  end
153
161
  end
154
162
  end
163
+
164
+ shared_examples_for "a simple event email" do
165
+ describe "email_subject" do
166
+ it "is generated correctly" do
167
+ expect(subject.email_subject).to eq(email_subject)
168
+ end
169
+
170
+ # it "is html safe" do
171
+ # # pending "Enable after #12547 is merged"
172
+ # expect(subject.email_subject).not_to include("script")
173
+ # end
174
+ end
175
+
176
+ describe "email_intro" do
177
+ it "is generated correctly" do
178
+ expect(subject.email_intro).to eq(email_intro)
179
+ end
180
+ end
181
+
182
+ describe "email_outro" do
183
+ it "is generated correctly" do
184
+ expect(subject.email_outro).to eq(email_outro)
185
+ end
186
+ end
187
+ end
188
+
189
+ shared_examples_for "a simple event notification" do
190
+ describe "notification_title" do
191
+ it "is generated correctly" do
192
+ expect(subject.notification_title)
193
+ .to eq(notification_title)
194
+ end
195
+ #
196
+ # it "is html safe" do
197
+ # pp subject.notification_title
198
+ # pending "Enable after #12547 is merged"
199
+ # expect(subject.notification_title).not_to include("script")
200
+ # end
201
+ end
202
+ end
@@ -76,3 +76,4 @@ require "decidim/core/test/shared_examples/resource_endorsed_event_examples"
76
76
  require "decidim/core/test/shared_examples/versions_controller_examples"
77
77
  require "decidim/core/test/shared_examples/mcell_examples"
78
78
  require "decidim/core/test/shared_examples/digest_mail_examples"
79
+ require "decidim/core/test/shared_examples/resource_locator_presenter_examples"
@@ -4,7 +4,7 @@ module Decidim
4
4
  # This holds the decidim-core version.
5
5
  module Core
6
6
  def self.version
7
- "0.27.4"
7
+ "0.27.6"
8
8
  end
9
9
  end
10
10
  end
data/lib/decidim/core.rb CHANGED
@@ -114,6 +114,7 @@ module Decidim
114
114
  autoload :ControllerHelpers, "decidim/controller_helpers"
115
115
  autoload :ProcessesFileLocally, "decidim/processes_file_locally"
116
116
  autoload :DependencyResolver, "decidim/dependency_resolver"
117
+ autoload :HasConversations, "decidim/has_conversations"
117
118
 
118
119
  include ActiveSupport::Configurable
119
120
  # Loads seeds from all engines.
@@ -585,7 +586,7 @@ module Decidim
585
586
  #
586
587
  # Returns an Array[ComponentManifest].
587
588
  def self.component_manifests
588
- component_registry.manifests
589
+ component_registry.manifests.sort_by(&:name)
589
590
  end
590
591
 
591
592
  # Public: Finds all registered participatory space manifest's via the
@@ -21,7 +21,7 @@ module Decidim
21
21
  if user_group
22
22
  endorsements.where(user_group: user_group).any?
23
23
  else
24
- endorsements.where(author: user, user_group: nil).any?
24
+ endorsements.where(author: user, user_group: 0).any?
25
25
  end
26
26
  end
27
27
  end
@@ -16,7 +16,7 @@ module Decidim
16
16
  #
17
17
  # @return [EngineRouter] The new engine router
18
18
  def self.main_proxy(target)
19
- new(target.mounted_engine, target.mounted_params)
19
+ new(target.mounted_engine, target.mounted_params, target)
20
20
  end
21
21
 
22
22
  # Instantiates a router to the backend engine for an object.
@@ -25,12 +25,13 @@ module Decidim
25
25
  #
26
26
  # @return [EngineRouter] The new engine router
27
27
  def self.admin_proxy(target)
28
- new(target.mounted_admin_engine, target.mounted_params)
28
+ new(target.mounted_admin_engine, target.mounted_params, target)
29
29
  end
30
30
 
31
- def initialize(engine, default_url_options)
31
+ def initialize(engine, default_url_options, target = nil)
32
32
  @engine = engine
33
33
  @default_url_options = default_url_options
34
+ @target = target
34
35
  end
35
36
 
36
37
  def default_url_options
@@ -44,11 +45,23 @@ module Decidim
44
45
  def method_missing(method_name, *args)
45
46
  return super unless route_helper?(method_name)
46
47
 
47
- send(@engine).send(method_name, *args)
48
+ filter_slug_params!(method_name)
49
+
50
+ send(engine).send(method_name, *args)
48
51
  end
49
52
 
50
53
  private
51
54
 
55
+ attr_reader :engine, :target
56
+
57
+ def filter_slug_params!(method_name)
58
+ return if target.nil?
59
+ return unless target.respond_to?(:mounted_params)
60
+
61
+ skip_space_slug = target.respond_to?(:slug_param_name) && target.respond_to?(:skip_space_slug?) && target.skip_space_slug?(method_name)
62
+ @default_url_options.except!(target.slug_param_name) if skip_space_slug == true
63
+ end
64
+
52
65
  def route_helper?(method_name)
53
66
  method_name.to_s.match?(/_(url|path)$/)
54
67
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../../../app/helpers/decidim/sanitize_helper"
4
+
3
5
  module Decidim
4
6
  module Events
5
7
  # This class serves as a base for all event classes. Event classes are intended to
@@ -8,6 +10,7 @@ module Decidim
8
10
  class BaseEvent
9
11
  extend ActiveModel::Translation
10
12
  include Decidim::TranslatableAttributes
13
+ include Decidim::SanitizeHelper
11
14
 
12
15
  class_attribute :types
13
16
  self.types = []
@@ -103,9 +106,9 @@ module Decidim
103
106
  return unless resource
104
107
 
105
108
  title = if resource.respond_to?(:title)
106
- translated_attribute(resource.title)
109
+ decidim_sanitize_translated(resource.title)
107
110
  elsif resource.respond_to?(:name)
108
- translated_attribute(resource.name)
111
+ decidim_sanitize_translated(resource.name)
109
112
  end
110
113
 
111
114
  Decidim::ContentProcessor.render_without_format(title, links: false).html_safe
@@ -11,7 +11,6 @@ module Decidim
11
11
  include Decidim::Events::EmailEvent
12
12
  include Decidim::Events::NotificationEvent
13
13
  include Decidim::ComponentPathHelper
14
- include Decidim::SanitizeHelper
15
14
 
16
15
  delegate :created_at, to: :resource
17
16
 
@@ -34,14 +33,7 @@ module Decidim
34
33
  end
35
34
 
36
35
  def email_subject
37
- I18n.t("email_subject", **email_subject_i18n_options).html_safe
38
- end
39
-
40
- def email_subject_i18n_options
41
- sanitized_values = { resource_title: decidim_sanitize(resource_title) }
42
- sanitized_values[:mentioned_proposal_title] = decidim_sanitize(mentioned_proposal_title) if i18n_options.has_key?(:mentioned_proposal_title)
43
- sanitized_values[:participatory_space_title] = decidim_sanitize(participatory_space_title) if i18n_options.has_key?(:participatory_space_title)
44
- i18n_options.merge(sanitized_values)
36
+ I18n.t("email_subject", **i18n_options).html_safe
45
37
  end
46
38
 
47
39
  def email_intro
@@ -77,13 +69,7 @@ module Decidim
77
69
 
78
70
  # Public: The Hash of options to pass to the I18.t method.
79
71
  def i18n_options
80
- default_i18n_options.merge(event_interpolations).transform_values do |value|
81
- if value.is_a?(String)
82
- decidim_html_escape(value)
83
- else
84
- value
85
- end
86
- end
72
+ default_i18n_options.merge(event_interpolations)
87
73
  end
88
74
 
89
75
  # Caches the path for the given resource when it's a Decidim::Component.
@@ -136,7 +122,7 @@ module Decidim
136
122
  end
137
123
 
138
124
  def participatory_space_title
139
- translated_attribute(participatory_space.try(:title))
125
+ decidim_sanitize_translated(participatory_space.try(:title))
140
126
  end
141
127
  end
142
128
  end
@@ -9,6 +9,11 @@ module Decidim
9
9
  autoload :PDF, "decidim/exporters/pdf"
10
10
  autoload :ExportData, "decidim/exporters/export_data"
11
11
 
12
+ # Lock the export formats to one of the available exporters
13
+ EXPORT_FORMATS = [:JSON, :CSV, :Excel, :PDF, :FormPDF].freeze
14
+
15
+ class UnknownFormatError < StandardError; end
16
+
12
17
  # Necessary for the i18n normalizer to locate strings not directly invoked in views:
13
18
 
14
19
  # i18n-tasks-use t('decidim.admin.exports.formats.JSON')
@@ -19,7 +24,11 @@ module Decidim
19
24
  #
20
25
  # format - The exporter format as a string. i.e "CSV"
21
26
  def self.find_exporter(format)
22
- const_get(format)
27
+ raise UnknownFormatError unless format.respond_to?(:to_sym)
28
+ raise UnknownFormatError unless EXPORT_FORMATS.include?(format.to_sym)
29
+ raise UnknownFormatError unless const_defined?(format.to_sym)
30
+
31
+ const_get(format.to_sym)
23
32
  end
24
33
  end
25
34
  end
@@ -317,6 +317,7 @@ module Decidim
317
317
  template = ""
318
318
  template += "<label>#{label_for(attribute) + required_for_attribute(attribute)}</label>" unless options[:label] == false
319
319
  template += @template.render("decidim/scopes/scopes_picker_input",
320
+ values_options: { delete_button: true, class: "label primary" },
320
321
  picker_options: picker_options,
321
322
  prompt_params: prompt_params,
322
323
  scopes: scopes,
@@ -8,7 +8,7 @@ module Decidim
8
8
  extend ActiveSupport::Concern
9
9
 
10
10
  included do
11
- has_one :categorization, as: :categorizable
11
+ has_one :categorization, as: :categorizable, class_name: "Decidim::Categorization", dependent: :destroy
12
12
  has_one :category, through: :categorization
13
13
 
14
14
  scope :with_category, lambda { |category|
@@ -26,11 +26,11 @@ module Decidim
26
26
  cat_ids = parent_ids.dup
27
27
  cat_ids.prepend(nil) if categories.include?("without")
28
28
 
29
- subquery = includes(:category).where(decidim_categories: { id: cat_ids })
29
+ subquery = left_outer_joins(:category).where(decidim_categories: { id: cat_ids })
30
30
  return subquery if parent_ids.none?
31
31
 
32
32
  subquery.or(
33
- includes(:category).where(decidim_categories: { parent_id: parent_ids })
33
+ left_outer_joins(:category).where(decidim_categories: { parent_id: parent_ids })
34
34
  )
35
35
  }
36
36
 
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ module HasConversations
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ def new_conversation(originator, user, conversation)
11
+ send_notification(
12
+ from: originator,
13
+ to: user,
14
+ conversation: conversation,
15
+ message: conversation.messages.first.body,
16
+ action: "new_conversation"
17
+ )
18
+ end
19
+
20
+ def new_group_conversation(originator, manager, conversation, group)
21
+ send_notification(
22
+ from: originator,
23
+ to: manager,
24
+ conversation: conversation,
25
+ message: conversation.messages.first.body,
26
+ action: "new_group_conversation",
27
+ third_party: group
28
+ )
29
+ end
30
+
31
+ def comanagers_new_conversation(group, user, conversation, manager)
32
+ send_notification(
33
+ from: group,
34
+ to: user,
35
+ conversation: conversation,
36
+ message: conversation.messages.first.body,
37
+ action: "comanagers_new_conversation",
38
+ third_party: manager
39
+ )
40
+ end
41
+
42
+ def new_message(sender, user, conversation, message)
43
+ send_notification(
44
+ from: sender,
45
+ to: user,
46
+ conversation: conversation,
47
+ message: message.body,
48
+ action: "new_message"
49
+ )
50
+ end
51
+
52
+ def new_group_message(sender, user, conversation, message, group)
53
+ send_notification(
54
+ from: sender,
55
+ to: user,
56
+ conversation: conversation,
57
+ message: message.body,
58
+ action: "new_group_message",
59
+ third_party: group
60
+ )
61
+ end
62
+
63
+ def comanagers_new_message(sender, user, conversation, message, manager)
64
+ send_notification(
65
+ from: sender,
66
+ to: user,
67
+ conversation: conversation,
68
+ message: message.body,
69
+ action: "comanagers_new_message",
70
+ third_party: manager
71
+ )
72
+ end
73
+
74
+ private
75
+
76
+ def get_subject(action:, sender:, third_party:)
77
+ I18n.t(
78
+ "conversation_mailer.#{action}.subject",
79
+ scope: "decidim.messaging",
80
+ sender: sender.name,
81
+ manager: third_party&.name,
82
+ group: third_party&.name
83
+ )
84
+ end
85
+
86
+ def send_notification
87
+ raise NotImplementedError, "You must define a send_notification method"
88
+ end
89
+ end
90
+ end
91
+ end
@@ -12,6 +12,23 @@ module Decidim
12
12
  :mounted_engine, :mounted_admin_engine, :admin_extension_module, :admins_query,
13
13
  to: :class
14
14
 
15
+ def skip_space_slug?(method_name)
16
+ [
17
+ "edit_#{underscored_name}_path".to_sym,
18
+ "edit_#{underscored_name}_url".to_sym,
19
+ "new_#{underscored_name}_path".to_sym,
20
+ "new_#{underscored_name}_url".to_sym,
21
+ "#{underscored_name}_path".to_sym,
22
+ "#{underscored_name}_url".to_sym,
23
+ "#{underscored_name.pluralize}_path".to_sym,
24
+ "#{underscored_name.pluralize}_url".to_sym
25
+ ].include?(method_name)
26
+ end
27
+
28
+ def slug_param_name
29
+ "#{underscored_name}_slug".to_sym
30
+ end
31
+
15
32
  def mounted_params
16
33
  {
17
34
  host: organization.host,
@@ -16,6 +16,7 @@ module Decidim
16
16
  include Cell::Caching::Notifications
17
17
  include Decidim::MarkupHelper
18
18
  include ::Webpacker::Helper
19
+ include Decidim::SanitizeHelper
19
20
 
20
21
  delegate :current_organization, to: :controller
21
22
 
@@ -0,0 +1,9 @@
1
+ {
2
+ "minify": true,
3
+ "options": [
4
+ "setClasses"
5
+ ],
6
+ "feature-detects": [
7
+ "css/transitions"
8
+ ]
9
+ }
@@ -16,15 +16,16 @@ class Premailer
16
16
  # @return [String] a plain text.
17
17
  def to_plain_text
18
18
  html_src = begin
19
+ @doc.css("style").remove
19
20
  @doc.at("body").inner_html
20
21
  rescue StandardError
21
22
  ""
22
23
  end
23
24
 
24
- html_src = @doc.to_html unless html_src && html_src.present?
25
-
26
- # remove style tags and content
27
- html_src.gsub!(%r{<style.*?/style>}m, "")
25
+ unless html_src && html_src.present?
26
+ @doc.css("style").remove
27
+ html_src = @doc.to_html
28
+ end
28
29
 
29
30
  convert_to_text(html_src, @options[:line_length], @html_encoding)
30
31
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  namespace :decidim do
4
4
  namespace :reminders do
5
+ desc "Sends all the email reminders defined in the manifests"
5
6
  task :all, [] => :environment do
6
7
  Decidim.reminders_registry.all.each do |reminder_manifest|
7
8
  call_reminder_job(reminder_manifest)
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :decidim do
4
+ namespace :upgrade do
5
+ desc "Remove duplicated endorsements"
6
+ task fix_duplicate_endorsements: :environment do
7
+ logger = Logger.new($stdout)
8
+ logger.info("Removing duplicate endorsements...")
9
+ has_count = 0
10
+
11
+ columns = [:resource_type, :resource_id, :decidim_author_type, :decidim_author_id, :decidim_user_group_id]
12
+
13
+ get_duplicates(columns).each do |issue|
14
+ while row_count(issue) > 1
15
+ find_next(issue)&.destroy
16
+ has_count += 1
17
+ logger.info("Removed duplicate endorsement for #{issue.resource_type} #{issue.resource_id}")
18
+ end
19
+ end
20
+
21
+ logger.info("Patch remaining endorsements.")
22
+ Decidim::Endorsement.where(decidim_user_group_id: nil).update(decidim_user_group_id: 0)
23
+ logger.info("Process terminated, #{has_count} endorsements have been removed.")
24
+ logger.info("Done")
25
+ end
26
+
27
+ private
28
+
29
+ def get_duplicates(*columns)
30
+ Decidim::Endorsement.select("#{columns.join(",")}, COUNT(*)").group(columns).having("COUNT(*) > 1")
31
+ end
32
+
33
+ def row_count(issue)
34
+ Decidim::Endorsement.where(
35
+ resource_type: issue.resource_type,
36
+ resource_id: issue.resource_id,
37
+ decidim_author_type: issue.decidim_author_type,
38
+ decidim_author_id: issue.decidim_author_id,
39
+ decidim_user_group_id: issue.decidim_user_group_id
40
+ ).count
41
+ end
42
+
43
+ def find_next(issue)
44
+ Decidim::Endorsement.find_by(
45
+ resource_type: issue.resource_type,
46
+ resource_id: issue.resource_id,
47
+ decidim_author_type: issue.decidim_author_type,
48
+ decidim_author_id: issue.decidim_author_id,
49
+ decidim_user_group_id: issue.decidim_user_group_id
50
+ )
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :decidim do
4
+ namespace :upgrade do
5
+ desc "Remove orphan categorizations"
6
+ task fix_orphan_categorizations: :environment do
7
+ logger = Logger.new($stdout)
8
+ logger.info("Removing orphan categorizations...")
9
+
10
+ Decidim::Categorization.find_each do |categorization|
11
+ categorization.destroy if categorization.categorizable.nil?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :decidim do
4
+ namespace :upgrade do
5
+ desc "Fix wrongly mapped short links components"
6
+ task fix_short_urls: :environment do
7
+ logger = Logger.new($stdout)
8
+ logger.info("Fixing wrongly mapped short links...")
9
+
10
+ Decidim::ShortLink.where(target_type: "Decidim::Component").find_each do |short_url|
11
+ real_component = Decidim::Component.find_by(id: short_url.target_id)
12
+
13
+ next if real_component.nil?
14
+ next if short_url.mounted_engine_name == real_component.mounted_engine
15
+
16
+ logger.info("Fixing #{short_url.identifier}: #{short_url.mounted_engine_name} to #{real_component.mounted_engine}")
17
+ short_url.update(mounted_engine_name: real_component.mounted_engine)
18
+ end
19
+ logger.info("Done fixing wrongly mapped short links.")
20
+ end
21
+ end
22
+ end