decidim-core 0.27.3 → 0.27.4

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.

Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/activities_cell.rb +1 -7
  3. data/app/cells/decidim/collapsible_list/show.erb +1 -1
  4. data/app/cells/decidim/content_blocks/last_activity_cell.rb +1 -4
  5. data/app/cells/decidim/tags_cell.rb +13 -2
  6. data/app/commands/decidim/create_omniauth_registration.rb +2 -2
  7. data/app/controllers/decidim/authorization_modals_controller.rb +1 -1
  8. data/app/controllers/decidim/last_activities_controller.rb +1 -7
  9. data/app/controllers/decidim/short_links_controller.rb +1 -1
  10. data/app/forms/decidim/notifications_settings_form.rb +1 -1
  11. data/app/forms/url_validator.rb +1 -1
  12. data/app/helpers/decidim/layout_helper.rb +4 -1
  13. data/app/helpers/decidim/layout_helper.rb.orig +225 -0
  14. data/app/models/decidim/organization.rb +6 -0
  15. data/app/models/decidim/user.rb +4 -2
  16. data/app/packs/src/decidim/input_character_counter.js +1 -1
  17. data/app/packs/src/decidim/map/controller/drag_marker.js +0 -2
  18. data/app/packs/src/decidim/map/controller/markers.js +0 -1
  19. data/app/packs/src/decidim/map/controller/static.js +0 -1
  20. data/app/packs/src/decidim/map/controller.js +0 -2
  21. data/app/packs/src/decidim/map/factory.js +4 -1
  22. data/app/packs/src/decidim/map/icon.js +0 -1
  23. data/app/packs/src/decidim/map/legacy.js +0 -1
  24. data/app/packs/src/decidim/map/provider/default.js +2 -0
  25. data/app/packs/src/decidim/map/provider/here.js +2 -1
  26. data/app/packs/stylesheets/decidim/modules/_dropdown_menu.scss +9 -0
  27. data/app/queries/decidim/last_activity.rb +96 -0
  28. data/app/queries/decidim/metrics/users_metric_manage.rb +6 -6
  29. data/app/queries/decidim/public_activities.rb +5 -57
  30. data/app/services/decidim/email_notification_generator.rb +7 -1
  31. data/app/services/decidim/send_push_notification.rb +1 -1
  32. data/app/uploaders/decidim/application_uploader.rb +2 -0
  33. data/app/views/decidim/devise/registrations/new.html.erb.orig +231 -0
  34. data/config/environment.rb +0 -0
  35. data/config/locales/ar.yml +3 -3
  36. data/config/locales/bg.yml +4 -0
  37. data/config/locales/ca.yml +7 -6
  38. data/config/locales/cs.yml +23 -7
  39. data/config/locales/de.yml +74 -11
  40. data/config/locales/el.yml +147 -0
  41. data/config/locales/en.yml +1 -0
  42. data/config/locales/eo.yml +3 -0
  43. data/config/locales/es-MX.yml +2 -1
  44. data/config/locales/es-PY.yml +4 -3
  45. data/config/locales/es.yml +7 -6
  46. data/config/locales/eu.yml +5 -5
  47. data/config/locales/fi-plain.yml +22 -0
  48. data/config/locales/fi.yml +1 -0
  49. data/config/locales/fr-CA.yml +6 -5
  50. data/config/locales/fr.yml +7 -6
  51. data/config/locales/ga-IE.yml +4 -0
  52. data/config/locales/gl.yml +8 -1
  53. data/config/locales/hu.yml +23 -2
  54. data/config/locales/id-ID.yml +8 -0
  55. data/config/locales/is-IS.yml +3 -1
  56. data/config/locales/it.yml +10 -6
  57. data/config/locales/ja.yml +16 -1
  58. data/config/locales/kaa.yml +10 -0
  59. data/config/locales/lb.yml +12 -8
  60. data/config/locales/lt.yml +1 -1
  61. data/config/locales/lv.yml +4 -0
  62. data/config/locales/nl.yml +6 -6
  63. data/config/locales/no.yml +8 -4
  64. data/config/locales/pl.yml +4 -0
  65. data/config/locales/pt-BR.yml +5 -1
  66. data/config/locales/pt.yml +5 -1
  67. data/config/locales/ro-RO.yml +4 -0
  68. data/config/locales/ru.yml +2 -0
  69. data/config/locales/sk.yml +21 -7
  70. data/config/locales/sr-CS.yml +8 -0
  71. data/config/locales/sv.yml +11 -11
  72. data/config/locales/tr-TR.yml +4 -0
  73. data/config/locales/uk.yml +2 -0
  74. data/config/locales/zh-CN.yml +4 -0
  75. data/config/locales/zh-TW.yml +17 -3
  76. data/db/migrate/20181030090144_destroy_deleted_users_follows.rb +1 -1
  77. data/db/migrate/20181204110723_remove_following_users_count_from_users.rb +11 -2
  78. data/db/migrate/20181214101250_add_notification_types_to_users.rb +6 -1
  79. data/db/migrate/20190412131728_fix_user_names.rb +9 -2
  80. data/db/migrate/20200211173227_add_direct_message_types_to_users.rb +6 -1
  81. data/db/migrate/20210302150803_invalidate_all_sessions_for_deleted_users.rb +10 -3
  82. data/db/migrate/20210310120640_add_followable_counter_cache_to_users.rb +13 -3
  83. data/db/seeds.rb +4 -3
  84. data/lib/decidim/core/test/shared_examples/map_examples.rb +4 -1
  85. data/lib/decidim/core/version.rb +1 -1
  86. data/lib/decidim/core.rb +17 -0
  87. data/lib/decidim/form_builder.rb +6 -13
  88. data/lib/tasks/upgrade/decidim_user_moderation.rake +14 -0
  89. metadata +17 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d6577740d87b562e24f541c4723480ec774239f69a389d4434536ab72be3b116
4
- data.tar.gz: 8366df277375b9fadc5c96b4a9e647a0300057d7148eafcb672f3a57d3abd55f
3
+ metadata.gz: d976829c2218ab34a1bf7c2ad99443edd61c4f37bb56963c8bb21a3e74afddef
4
+ data.tar.gz: acbaa2ce577af7e32648ce22941616e258f48bdbfb304e754344770fafaf9ef4
5
5
  SHA512:
6
- metadata.gz: f6f4e9e7bcf14ccc5943ec41d4468338d1cf62aec7d37b296d0fa37a3c1c7bc97711b06579d10b32167ce291b8d664989f90eecfcba9a94f228ff60e7e8698e0
7
- data.tar.gz: 4fcd0dacd12572c3a4b404709ec632dcc6c5cc964dfd9dc29d92a4dd03da2b10ddc3e5df57a6ed91cb3f90e0dac70c4668ba89040f8cf5788e34d1f8e857d3b8
6
+ metadata.gz: 868d324e0f83442b37750933c39985dffdba9bfd06a2f47ad00836b7c9b89164bafff5d2083d5e24d7f01eb9c47dac46f564a375bacaa17726fe5d472bf6c86b
7
+ data.tar.gz: 1af449d8a281aa2ae5db6c0f03a7be077f7a7eeaa2a300e8bc2a2d36622cd4be5aafb4245878a24e4bd2496542d0166a84287974e72cdeb294acdcd021144b00
@@ -27,13 +27,7 @@ module Decidim
27
27
  end
28
28
 
29
29
  def activities
30
- @activities ||= last_activities.select do |activity|
31
- activity.visible_for?(current_user)
32
- end
33
- end
34
-
35
- def last_activities
36
- @last_activities ||= model.map do |activity|
30
+ @activities ||= model.map do |activity|
37
31
  activity.organization_lazy
38
32
  activity.resource_lazy
39
33
  activity.participatory_space_lazy
@@ -16,7 +16,7 @@
16
16
  </span>
17
17
  </div>
18
18
  <% else %>
19
- <div class="collapsible-list <%= list_class %>">
19
+ <div class="<%= list_class %>">
20
20
  <% list.each do |element| %>
21
21
  <% if cell_name %>
22
22
  <%= cell cell_name, element, cell_options %>
@@ -56,10 +56,7 @@ module Decidim
56
56
  end
57
57
 
58
58
  def activities
59
- @activities ||= ActionLog.where(
60
- organization: current_organization,
61
- visibility: %w(public-only all)
62
- ).with_new_resource_type("all").order(created_at: :desc).limit(activities_to_show * 6)
59
+ @activities ||= Decidim::LastActivity.new(current_organization, current_user: current_user).query.limit(activities_to_show * 6)
63
60
  end
64
61
 
65
62
  def activities_to_show
@@ -55,7 +55,7 @@ module Decidim
55
55
  end
56
56
 
57
57
  def category_path
58
- resource_locator(model).index(filter: { category_id: [model.category.id.to_s] })
58
+ resource_locator(model).index(filter: { filter_param(:category) => [model.category.id.to_s] })
59
59
  end
60
60
 
61
61
  def scope?
@@ -86,7 +86,18 @@ module Decidim
86
86
  end
87
87
 
88
88
  def scope_path
89
- resource_locator(model).index(filter: { scope_id: [model.scope.id] })
89
+ resource_locator(model).index(filter: { filter_param(:scope) => [model.scope.id] })
90
+ end
91
+
92
+ def filter_param(name)
93
+ candidates = ["with_any_#{name}".to_sym, "with_#{name}".to_sym]
94
+ return candidates.first unless controller.respond_to?(:default_filter_params, true)
95
+
96
+ available_params = controller.send(:default_filter_params)
97
+ candidates.each do |candidate|
98
+ return candidate if available_params.has_key?(candidate)
99
+ end
100
+ candidates.first
90
101
  end
91
102
  end
92
103
  end
@@ -46,8 +46,6 @@ module Decidim
46
46
  attr_reader :form, :verified_email
47
47
 
48
48
  def create_or_find_user
49
- generated_password = SecureRandom.hex
50
-
51
49
  @user = User.find_or_initialize_by(
52
50
  email: verified_email,
53
51
  organization: organization
@@ -59,6 +57,8 @@ module Decidim
59
57
  # to be marked confirmed.
60
58
  @user.skip_confirmation! if !@user.confirmed? && @user.email == verified_email
61
59
  else
60
+ generated_password = SecureRandom.hex
61
+
62
62
  @user.email = (verified_email || form.email)
63
63
  @user.name = form.name
64
64
  @user.nickname = form.normalized_nickname
@@ -17,7 +17,7 @@ module Decidim
17
17
  end
18
18
 
19
19
  def current_component
20
- @current_component ||= Decidim::Component.find(params[:component_id])
20
+ @current_component ||= Decidim::Component.where(participatory_space: current_organization.participatory_spaces).find(params[:component_id])
21
21
  end
22
22
 
23
23
  def authorization_action
@@ -32,13 +32,7 @@ module Decidim
32
32
  end
33
33
 
34
34
  def search_collection
35
- ActionLog
36
- .where(
37
- organization: current_organization,
38
- visibility: %w(public-only all)
39
- )
40
- .with_new_resource_type("all")
41
- .order(created_at: :desc)
35
+ LastActivity.new(current_organization, current_user: current_user).query
42
36
  end
43
37
 
44
38
  def default_filter_params
@@ -29,7 +29,7 @@ module Decidim
29
29
  #
30
30
  # @return [Decidim::ShortLink] The short link matching the identifier
31
31
  def link
32
- @link ||= Decidim::ShortLink.find_by(identifier: params[:id])
32
+ @link ||= Decidim::ShortLink.find_by(identifier: params[:id], organization: current_organization)
33
33
  end
34
34
  end
35
35
  end
@@ -53,7 +53,7 @@ module Decidim
53
53
  end
54
54
 
55
55
  def meet_push_notifications_requirements?
56
- Rails.application.secrets.vapid[:enabled]
56
+ Rails.application.secrets.dig(:vapid, :enabled) || false
57
57
  end
58
58
  end
59
59
  end
@@ -6,7 +6,7 @@
6
6
  #
7
7
  class UrlValidator < ActiveModel::EachValidator
8
8
  def validate_each(record, attribute, value)
9
- record.errors.add attribute, (options[:message] || "must be a valid URL") unless url_valid?(value)
9
+ record.errors.add attribute, :url_format, **options unless url_valid?(value)
10
10
  end
11
11
 
12
12
  # a URL may be technically well-formed but may
@@ -105,7 +105,10 @@ module Decidim
105
105
  # non-nil because otherwise it will be set to the asset host at
106
106
  # ActionView::Helpers::AssetUrlHelper#compute_asset_host.
107
107
  img_path = asset_pack_path(path, host: "", protocol: :relative)
108
- Rails.public_path.join(img_path.sub(%r{^/}, ""))
108
+ path = Rails.public_path.join(img_path.sub(%r{^/}, ""))
109
+ return unless File.exist?(path)
110
+
111
+ path
109
112
  rescue ::Webpacker::Manifest::MissingEntryError
110
113
  nil
111
114
  end
@@ -0,0 +1,225 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # View helpers related to the layout.
5
+ module LayoutHelper
6
+ include Decidim::ModalHelper
7
+ include Decidim::TooltipHelper
8
+
9
+ # Public: Generates a set of meta tags that generate the different favicon
10
+ # versions for an organization.
11
+ #
12
+ # Returns a safe String with the versions.
13
+ def favicon
14
+ return if current_organization.favicon.blank?
15
+
16
+ safe_join(Decidim::OrganizationFaviconUploader::SIZES.map do |version, size|
17
+ favicon_link_tag(current_organization.attached_uploader(:favicon).variant_url(version, host: current_organization.host), sizes: "#{size}x#{size}")
18
+ end)
19
+ end
20
+
21
+ def apple_favicon
22
+ icon_image = current_organization.attached_uploader(:favicon).variant_url(:medium, host: current_organization.host)
23
+ return unless icon_image
24
+
25
+ favicon_link_tag(icon_image, rel: "apple-touch-icon", type: "image/png")
26
+ end
27
+
28
+ def legacy_favicon
29
+ variant = :favicon if current_organization.favicon.content_type != "image/vnd.microsoft.icon"
30
+ icon_image = current_organization.attached_uploader(:favicon).variant_url(variant, host: current_organization.host)
31
+ return unless icon_image
32
+
33
+ favicon_link_tag(icon_image, rel: "icon", sizes: "any", type: nil)
34
+ end
35
+
36
+ # Outputs an SVG-based icon.
37
+ #
38
+ # name - The String with the icon name.
39
+ # options - The Hash options used to customize the icon (default {}):
40
+ # :width - The Number of width in pixels (optional).
41
+ # :height - The Number of height in pixels (optional).
42
+ # :title - The title for the SVG element (optional, similar to alt for img)
43
+ # :aria_label - The String to set as aria label (optional).
44
+ # :aria_hidden - The Truthy value to enable aria_hidden (optional).
45
+ # :role - The String to set as the role (optional).
46
+ # :class - The String to add as a CSS class (optional).
47
+ #
48
+ # Returns a String.
49
+ def redesigned_icon(name, options = {})
50
+ default_html_properties = {
51
+ "width" => "1em",
52
+ "height" => "1em",
53
+ "role" => "img",
54
+ "aria-hidden" => "true"
55
+ }
56
+
57
+ html_properties = options.with_indifferent_access.transform_keys(&:dasherize).slice("width", "height", "aria-label", "role", "aria-hidden", "class", "style")
58
+ html_properties = default_html_properties.merge(html_properties)
59
+
60
+ href = Decidim.cors_enabled ? "" : asset_pack_path("media/images/remixicon.symbol.svg")
61
+
62
+ content_tag :svg, html_properties do
63
+ content_tag :use, nil, "href" => "#{href}#ri-#{name}", tabindex: -1
64
+ end
65
+ end
66
+
67
+ def legacy_icon(name, options = {})
68
+ options = options.with_indifferent_access
69
+ html_properties = {}
70
+
71
+ html_properties["width"] = options[:width]
72
+ html_properties["height"] = options[:height]
73
+ html_properties["aria-label"] = options[:aria_label] || options[:"aria-label"]
74
+ html_properties["role"] = options[:role] || "img"
75
+ html_properties["aria-hidden"] = options[:aria_hidden] || options[:"aria-hidden"]
76
+
77
+ html_properties["class"] = (["icon--#{name}"] + _icon_classes(options)).join(" ")
78
+
79
+ title = options["title"] || html_properties["aria-label"]
80
+ if title.blank? && html_properties["role"] == "img"
81
+ # This will make the accessibility audit tools happy as with the "img"
82
+ # role, the alternative text (aria-label) and title are required for the
83
+ # element. This will also force the SVG to be hidden because otherwise
84
+ # the screen reader would announce the icon name which can be in
85
+ # different language (English) than the page language which is not
86
+ # allowed.
87
+ title = name
88
+ html_properties["aria-label"] = title
89
+ html_properties["aria-hidden"] = true
90
+ end
91
+
92
+ href = Decidim.cors_enabled ? "" : asset_pack_path("media/images/icons.svg")
93
+
94
+ content_tag :svg, html_properties do
95
+ inner = content_tag :title, title
96
+ inner += content_tag :use, nil, "href" => "#{href}#icon-#{name}"
97
+
98
+ inner
99
+ end
100
+ end
101
+
102
+ def icon(*args)
103
+ redesign_enabled? ? redesigned_icon(*args) : legacy_icon(*args)
104
+ end
105
+
106
+ # Outputs a SVG icon from an external file. It apparently renders an image
107
+ # tag, but then a JS script kicks in and replaces it with an inlined SVG
108
+ # version.
109
+ #
110
+ # path - The asset's path
111
+ #
112
+ # Returns an <img /> tag with the SVG icon.
113
+ def external_icon(path, options = {})
114
+ classes = _icon_classes(options) + ["external-icon"]
115
+
116
+ if path.split(".").last == "svg"
117
+ icon_path = application_path(path)
118
+ return unless icon_path
119
+
120
+ attributes = { class: classes.join(" ") }.merge(options)
121
+ asset = File.read(icon_path)
122
+ asset.gsub("<svg ", "<svg#{tag_builder.tag_options(attributes)} ").html_safe
123
+ else
124
+ image_pack_tag(path, class: classes.join(" "), style: "display: none")
125
+ end
126
+ end
127
+
128
+ def application_path(path)
129
+ # Force the path to be returned without the protocol and host even when a
130
+ # custom asset host has been defined. The host parameter needs to be a
131
+ # non-nil because otherwise it will be set to the asset host at
132
+ # ActionView::Helpers::AssetUrlHelper#compute_asset_host.
133
+ img_path = asset_pack_path(path, host: "", protocol: :relative)
134
+ path = Rails.public_path.join(img_path.sub(%r{^/}, ""))
135
+ return unless File.exist?(path)
136
+
137
+ path
138
+ rescue ::Webpacker::Manifest::MissingEntryError
139
+ nil
140
+ end
141
+
142
+ # Allows to create role attribute according to accessibility rules
143
+ #
144
+ # Returns role attribute string if role option is specified
145
+ def role(options = {})
146
+ "role=\"#{options[:role]}\" " if options[:role]
147
+ end
148
+
149
+ def _icon_classes(options = {})
150
+ classes = options[:remove_icon_class] ? [] : ["icon"]
151
+ classes += [options[:class]]
152
+ classes.compact
153
+ end
154
+
155
+ def extended_navigation_bar(items, max_items: 5)
156
+ return unless items.any?
157
+
158
+ extra_items = items.slice((max_items + 1)..-1) || []
159
+ active_item = items.find { |item| item[:active] }
160
+
161
+ controller.view_context.render partial: "decidim/shared/extended_navigation_bar", locals: {
162
+ items:,
163
+ extra_items:,
164
+ active_item:,
165
+ max_items:
166
+ }
167
+ end
168
+
169
+ # Renders a view with the customizable CSS variables in two flavours:
170
+ # 1. as a hexadecimal valid CSS color (ie: #ff0000)
171
+ # 2. as a disassembled RGB components (ie: 255 0 0)
172
+ #
173
+ # Example:
174
+ #
175
+ # --primary: #ff0000;
176
+ # --primary-rgb: 255,0,0
177
+ #
178
+ # Hexadecimal variables can be used as a normal CSS color:
179
+ #
180
+ # color: var(--primary)
181
+ #
182
+ # While the disassembled variant can be used where you need to manipulate
183
+ # the color somehow (ie: adding a background transparency):
184
+ #
185
+ # background-color: rgba(var(--primary-rgb), 0.5)
186
+ def organization_colors
187
+ css = current_organization.colors.each.map { |k, v| "--#{k}: #{v};--#{k}-rgb: #{v[1..2].hex} #{v[3..4].hex} #{v[5..6].hex};" }.join
188
+ render partial: "layouts/decidim/organization_colors", locals: { css: }
189
+ end
190
+
191
+ <<<<<<< HEAD
192
+ def current_user_unread_data
193
+ return {} if current_user.blank?
194
+
195
+ {}.tap do |d|
196
+ d.merge!(unread_notifications: true) if current_user.notifications.any?
197
+ d.merge!(unread_conversations: true) if current_user.unread_conversations.any?
198
+ d.merge!(unread_items: d.present?)
199
+ end
200
+ end
201
+
202
+ ||||||| parent of 53b6893e5c (Use local emojibase data instead of CDN)
203
+ =======
204
+ # Public: Gets the name of the webpacker entrypoint that will be used
205
+ # for the locale of the Emojibase NPM package, used with @picmo/popup-picker
206
+ #
207
+ # Returns a string with the entrypoint name
208
+ def emojibase_entrypoint_locale
209
+ entrypoint = Decidim::Webpacker.configuration.entrypoints.keys.select do |entry|
210
+ entry == "decidim_emojibase_#{I18n.locale}"
211
+ end
212
+
213
+ return "decidim_emojibase_en" if entrypoint.empty?
214
+
215
+ entrypoint.first
216
+ end
217
+
218
+ >>>>>>> 53b6893e5c (Use local emojibase data instead of CDN)
219
+ private
220
+
221
+ def tag_builder
222
+ @tag_builder ||= ActionView::Helpers::TagHelper::TagBuilder.new(self)
223
+ end
224
+ end
225
+ end
@@ -87,6 +87,12 @@ module Decidim
87
87
  @top_scopes ||= scopes.top_level
88
88
  end
89
89
 
90
+ def participatory_spaces
91
+ @participatory_spaces ||= Decidim.participatory_space_manifests.flat_map do |manifest|
92
+ manifest.participatory_spaces.call(self)
93
+ end
94
+ end
95
+
90
96
  def public_participatory_spaces
91
97
  @public_participatory_spaces ||= Decidim.participatory_space_manifests.flat_map do |manifest|
92
98
  manifest.participatory_spaces.call(self).public_spaces
@@ -261,9 +261,10 @@ module Decidim
261
261
  end
262
262
 
263
263
  def needs_password_update?
264
+ return false if organization.users_registration_mode == "disabled"
264
265
  return false unless admin?
265
266
  return false unless Decidim.config.admin_password_strong
266
- return true if password_updated_at.blank?
267
+ return identities.none? if password_updated_at.blank?
267
268
 
268
269
  password_updated_at < Decidim.config.admin_password_expiration_days.days.ago
269
270
  end
@@ -293,7 +294,8 @@ module Decidim
293
294
  event: "decidim.events.core.welcome_notification",
294
295
  event_class: WelcomeNotificationEvent,
295
296
  resource: self,
296
- affected_users: [self]
297
+ affected_users: [self],
298
+ extra: { force_email: true }
297
299
  )
298
300
  end
299
301
 
@@ -33,7 +33,7 @@ export default class InputCharacterCounter {
33
33
  this.$target = $(this.$input.data("remaining-characters"));
34
34
  this.minCharacters = parseInt(this.$input.attr("minlength"), 10);
35
35
  this.maxCharacters = parseInt(this.$input.attr("maxlength"), 10);
36
- this.describeByCounter = typeof this.$input.attr("aria-describedby") === "undefined";
36
+ this.describeByCounter = this.$input.attr("type") !== "hidden" && typeof this.$input.attr("aria-describedby") === "undefined";
37
37
 
38
38
  // Define the closest length for the input "gaps" defined by the threshold.
39
39
  if (this.maxCharacters > 10) {
@@ -1,6 +1,4 @@
1
- import * as L from "leaflet";
2
1
  import MapController from "src/decidim/map/controller"
3
- import "src/decidim/vendor/leaflet-tilelayer-here"
4
2
 
5
3
  export default class MapDragMarkerController extends MapController {
6
4
  start() {
@@ -1,5 +1,4 @@
1
1
  import "src/decidim/vendor/jquery-tmpl"
2
- import * as L from "leaflet";
3
2
  import MapController from "src/decidim/map/controller"
4
3
  import "leaflet.markercluster";
5
4
 
@@ -1,4 +1,3 @@
1
- import * as L from "leaflet";
2
1
  import MapController from "src/decidim/map/controller"
3
2
 
4
3
  const openLink = window.open;
@@ -1,5 +1,3 @@
1
- import * as L from "leaflet";
2
- import "src/decidim/map/icon"
3
1
  import MapControllerRegistry from "src/decidim/map/controller_registry"
4
2
 
5
3
  export default class MapController {
@@ -1,3 +1,5 @@
1
+ import "src/decidim/map/icon"
2
+
1
3
  import MapMarkersController from "src/decidim/map/controller/markers"
2
4
  import MapStaticController from "src/decidim/map/controller/static"
3
5
  import MapDragMarkerController from "src/decidim/map/controller/drag_marker"
@@ -22,7 +24,8 @@ import MapDragMarkerController from "src/decidim/map/controller/drag_marker"
22
24
  * window.Decidim.createMapController = (mapId, config) => {
23
25
  * if (config.type === "custom") {
24
26
  * // Obviously you need to implement CustomMapController for this to
25
- * // work.
27
+ * // work. You can find an example at:
28
+ * // decidim-dev/app/packs/src/decidim/dev/test/custom_map_factory.js
26
29
  * return new window.Decidim.CustomMapController(mapId, config);
27
30
  * }
28
31
  *
@@ -1,4 +1,3 @@
1
- import * as L from "leaflet";
2
1
  import { SVGIcon } from "src/decidim/map/svg-icon";
3
2
 
4
3
  L.DivIcon.SVGIcon = SVGIcon;
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable require-jsdoc */
2
2
 
3
- import * as L from "leaflet";
4
3
  import "src/decidim/map/factory"
5
4
 
6
5
  /**
@@ -1,3 +1,5 @@
1
+ import "leaflet"
2
+
1
3
  /**
2
4
  * NOTE:
3
5
  * This has to load before decidim/map in order for it to apply correctly when
@@ -1,4 +1,5 @@
1
- import * as L from "leaflet"
1
+ import "leaflet"
2
+ import "src/decidim/vendor/leaflet-tilelayer-here"
2
3
 
3
4
  /**
4
5
  * NOTE:
@@ -0,0 +1,9 @@
1
+ .dropdown.menu > li {
2
+ &.is-active > a {
3
+ color: var(--secondary);
4
+ }
5
+
6
+ &.is-dropdown-submenu-parent > a::after {
7
+ border-color: var(--secondary) transparent transparent;
8
+ }
9
+ }
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # This query finds the public ActionLog entries that can be shown in the
5
+ # activities views of the application within a Decidim Organization. It is
6
+ # intended to be used in the "Last activities" content block in the homepage,
7
+ # and also in the "Last activities" page, to retrieve public activity of this
8
+ # organization.
9
+ class LastActivity < Decidim::Query
10
+ def initialize(organization, options = {})
11
+ @organization = organization
12
+ @current_user = options[:current_user]
13
+ end
14
+
15
+ def query
16
+ @query ||= begin
17
+ query = base_query
18
+ query = filter_moderated(query)
19
+ query = filter_spaces(query)
20
+ query = filter_deleted(query)
21
+ query.with_new_resource_type("all")
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :organization, :current_user
28
+
29
+ def base_query
30
+ ActionLog
31
+ .where(organization: organization, visibility: visibility)
32
+ .order(created_at: :desc)
33
+ end
34
+
35
+ def visibility
36
+ %w(public-only all)
37
+ end
38
+
39
+ def filter_moderated(query)
40
+ # Filter out the items that have been moderated.
41
+ query.joins(
42
+ <<~SQL.squish
43
+ LEFT JOIN decidim_moderations
44
+ ON decidim_moderations.decidim_reportable_type = decidim_action_logs.resource_type
45
+ AND decidim_moderations.decidim_reportable_id = decidim_action_logs.resource_id
46
+ AND decidim_moderations.hidden_at IS NOT NULL
47
+ SQL
48
+ ).where(decidim_moderations: { id: nil })
49
+ end
50
+
51
+ def filter_spaces(query)
52
+ conditions = []
53
+
54
+ Decidim.participatory_space_manifests.map do |manifest|
55
+ klass = manifest.model_class_name.constantize
56
+
57
+ condition = if klass.include?(Decidim::HasPrivateUsers)
58
+ Arel.sql(
59
+ [
60
+ "decidim_action_logs.participatory_space_type = '#{manifest.model_class_name}'",
61
+ "decidim_action_logs.participatory_space_id IN (#{Arel.sql(klass.visible_for(current_user).select(:id).to_sql)})"
62
+ ].join(" AND ")
63
+ ).to_s
64
+ else
65
+ Arel.sql("decidim_action_logs.participatory_space_type = '#{manifest.model_class_name}'").to_s
66
+ end
67
+
68
+ conditions << "(#{condition})"
69
+ end
70
+ query.where(Arel.sql(conditions.join(" OR ")).to_s)
71
+ end
72
+
73
+ def filter_deleted(query)
74
+ conditions = []
75
+
76
+ ActionLog.public_resource_types.each do |resource_type|
77
+ klass = resource_type.constantize
78
+
79
+ condition = if klass.respond_to?(:not_deleted)
80
+ Arel.sql(
81
+ [
82
+ "decidim_action_logs.resource_type = '#{resource_type}'",
83
+ "decidim_action_logs.resource_id IN (#{Arel.sql(klass.not_deleted.select(:id).to_sql)})"
84
+ ].join(" AND ")
85
+ ).to_s
86
+ else
87
+ Arel.sql("decidim_action_logs.resource_type = '#{resource_type}'").to_s
88
+ end
89
+
90
+ conditions << "(#{condition})"
91
+ end
92
+
93
+ query.where(Arel.sql(conditions.join(" OR ")).to_s)
94
+ end
95
+ end
96
+ end
@@ -11,15 +11,15 @@ module Decidim
11
11
  private
12
12
 
13
13
  def query
14
- return @query if @query
15
-
16
- @query = Decidim::User.where(organization: @organization)
17
- @query = @query.where("created_at <= ?", end_time)
18
- @query
14
+ @query ||= Decidim::User.where(organization: @organization)
15
+ .where("deleted_at IS NULL OR deleted_at > ?", end_time)
16
+ .where("blocked_at IS NULL OR blocked_at > ?", end_time)
17
+ .confirmed
18
+ .where("created_at <= ?", end_time)
19
19
  end
20
20
 
21
21
  def quantity
22
- @quantity ||= @query.where("created_at >= ?", start_time).count
22
+ @quantity ||= query.where("created_at >= ?", start_time).count
23
23
  end
24
24
  end
25
25
  end