decidim-core 0.27.3 → 0.27.4
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/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
|