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.
- checksums.yaml +4 -4
- data/app/cells/decidim/activities_cell.rb +1 -7
- data/app/cells/decidim/collapsible_list/show.erb +1 -1
- data/app/cells/decidim/content_blocks/last_activity_cell.rb +1 -4
- data/app/cells/decidim/tags_cell.rb +13 -2
- data/app/commands/decidim/create_omniauth_registration.rb +2 -2
- data/app/controllers/decidim/authorization_modals_controller.rb +1 -1
- data/app/controllers/decidim/last_activities_controller.rb +1 -7
- data/app/controllers/decidim/short_links_controller.rb +1 -1
- data/app/forms/decidim/notifications_settings_form.rb +1 -1
- data/app/forms/url_validator.rb +1 -1
- data/app/helpers/decidim/layout_helper.rb +4 -1
- data/app/helpers/decidim/layout_helper.rb.orig +225 -0
- data/app/models/decidim/organization.rb +6 -0
- data/app/models/decidim/user.rb +4 -2
- data/app/packs/src/decidim/input_character_counter.js +1 -1
- data/app/packs/src/decidim/map/controller/drag_marker.js +0 -2
- data/app/packs/src/decidim/map/controller/markers.js +0 -1
- data/app/packs/src/decidim/map/controller/static.js +0 -1
- data/app/packs/src/decidim/map/controller.js +0 -2
- data/app/packs/src/decidim/map/factory.js +4 -1
- data/app/packs/src/decidim/map/icon.js +0 -1
- data/app/packs/src/decidim/map/legacy.js +0 -1
- data/app/packs/src/decidim/map/provider/default.js +2 -0
- data/app/packs/src/decidim/map/provider/here.js +2 -1
- data/app/packs/stylesheets/decidim/modules/_dropdown_menu.scss +9 -0
- data/app/queries/decidim/last_activity.rb +96 -0
- data/app/queries/decidim/metrics/users_metric_manage.rb +6 -6
- data/app/queries/decidim/public_activities.rb +5 -57
- data/app/services/decidim/email_notification_generator.rb +7 -1
- data/app/services/decidim/send_push_notification.rb +1 -1
- data/app/uploaders/decidim/application_uploader.rb +2 -0
- data/app/views/decidim/devise/registrations/new.html.erb.orig +231 -0
- data/config/environment.rb +0 -0
- data/config/locales/ar.yml +3 -3
- data/config/locales/bg.yml +4 -0
- data/config/locales/ca.yml +7 -6
- data/config/locales/cs.yml +23 -7
- data/config/locales/de.yml +74 -11
- data/config/locales/el.yml +147 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/eo.yml +3 -0
- data/config/locales/es-MX.yml +2 -1
- data/config/locales/es-PY.yml +4 -3
- data/config/locales/es.yml +7 -6
- data/config/locales/eu.yml +5 -5
- data/config/locales/fi-plain.yml +22 -0
- data/config/locales/fi.yml +1 -0
- data/config/locales/fr-CA.yml +6 -5
- data/config/locales/fr.yml +7 -6
- data/config/locales/ga-IE.yml +4 -0
- data/config/locales/gl.yml +8 -1
- data/config/locales/hu.yml +23 -2
- data/config/locales/id-ID.yml +8 -0
- data/config/locales/is-IS.yml +3 -1
- data/config/locales/it.yml +10 -6
- data/config/locales/ja.yml +16 -1
- data/config/locales/kaa.yml +10 -0
- data/config/locales/lb.yml +12 -8
- data/config/locales/lt.yml +1 -1
- data/config/locales/lv.yml +4 -0
- data/config/locales/nl.yml +6 -6
- data/config/locales/no.yml +8 -4
- data/config/locales/pl.yml +4 -0
- data/config/locales/pt-BR.yml +5 -1
- data/config/locales/pt.yml +5 -1
- data/config/locales/ro-RO.yml +4 -0
- data/config/locales/ru.yml +2 -0
- data/config/locales/sk.yml +21 -7
- data/config/locales/sr-CS.yml +8 -0
- data/config/locales/sv.yml +11 -11
- data/config/locales/tr-TR.yml +4 -0
- data/config/locales/uk.yml +2 -0
- data/config/locales/zh-CN.yml +4 -0
- data/config/locales/zh-TW.yml +17 -3
- data/db/migrate/20181030090144_destroy_deleted_users_follows.rb +1 -1
- data/db/migrate/20181204110723_remove_following_users_count_from_users.rb +11 -2
- data/db/migrate/20181214101250_add_notification_types_to_users.rb +6 -1
- data/db/migrate/20190412131728_fix_user_names.rb +9 -2
- data/db/migrate/20200211173227_add_direct_message_types_to_users.rb +6 -1
- data/db/migrate/20210302150803_invalidate_all_sessions_for_deleted_users.rb +10 -3
- data/db/migrate/20210310120640_add_followable_counter_cache_to_users.rb +13 -3
- data/db/seeds.rb +4 -3
- data/lib/decidim/core/test/shared_examples/map_examples.rb +4 -1
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/core.rb +17 -0
- data/lib/decidim/form_builder.rb +6 -13
- data/lib/tasks/upgrade/decidim_user_moderation.rake +14 -0
- metadata +17 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d976829c2218ab34a1bf7c2ad99443edd61c4f37bb56963c8bb21a3e74afddef
|
4
|
+
data.tar.gz: acbaa2ce577af7e32648ce22941616e258f48bdbfb304e754344770fafaf9ef4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 ||=
|
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
|
@@ -56,10 +56,7 @@ module Decidim
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def activities
|
59
|
-
@activities ||=
|
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: {
|
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: {
|
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
|
-
|
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
|
data/app/forms/url_validator.rb
CHANGED
@@ -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,
|
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
|
data/app/models/decidim/user.rb
CHANGED
@@ -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
|
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,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
|
*
|
@@ -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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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 ||=
|
22
|
+
@quantity ||= query.where("created_at >= ?", start_time).count
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|