decidim-core 0.27.2 → 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/cells/decidim/upload_modal/files.erb +1 -0
- data/app/cells/decidim/upload_modal_cell.rb +14 -4
- data/app/commands/decidim/attachment_methods.rb +20 -2
- data/app/commands/decidim/create_omniauth_registration.rb +2 -2
- data/app/commands/decidim/create_registration.rb +1 -0
- data/app/commands/decidim/gallery_methods.rb +1 -1
- data/app/commands/decidim/update_account.rb +1 -0
- data/app/commands/decidim/update_password.rb +2 -0
- data/app/controllers/decidim/authorization_modals_controller.rb +1 -1
- data/app/controllers/decidim/devise/sessions_controller.rb +18 -2
- data/app/controllers/decidim/last_activities_controller.rb +1 -7
- data/app/controllers/decidim/links_controller.rb +8 -11
- 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/cells_helper.rb +1 -0
- data/app/helpers/decidim/external_domain_helper.rb +14 -3
- data/app/helpers/decidim/layout_helper.rb +4 -1
- data/app/helpers/decidim/layout_helper.rb.orig +225 -0
- data/app/helpers/decidim/sanitize_helper.rb +3 -2
- data/app/models/decidim/organization.rb +6 -0
- data/app/models/decidim/scope_type.rb +24 -0
- data/app/models/decidim/user.rb +4 -2
- data/app/packs/src/decidim/direct_uploads/upload_modal.js +0 -1
- data/app/packs/src/decidim/editor/clipboard_override.js +6 -2
- data/app/packs/src/decidim/editor.js +63 -33
- 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/_buttons.scss +10 -6
- data/app/packs/stylesheets/decidim/modules/_cards.scss +1 -1
- data/app/packs/stylesheets/decidim/modules/_comments.scss +24 -0
- data/app/packs/stylesheets/decidim/modules/_dropdown_menu.scss +9 -0
- data/app/packs/stylesheets/decidim/modules/_input-gallery.scss +2 -1
- data/app/packs/stylesheets/decidim/modules/_upload_modal.scss +0 -4
- data/app/packs/stylesheets/decidim/vizzs/_linechart.scss +2 -2
- data/app/packs/stylesheets/decidim/vizzs/_rowchart.scss +2 -2
- data/app/presenters/decidim/notification_presenter.rb +1 -1
- data/app/presenters/decidim/notification_to_mailer_presenter.rb +1 -0
- data/app/presenters/decidim/user_group_presenter.rb +1 -1
- data/app/presenters/decidim/user_presenter.rb +1 -1
- 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/scrubbers/decidim/admin_input_scrubber.rb +3 -1
- data/app/scrubbers/decidim/user_input_scrubber.rb +30 -1
- data/app/services/decidim/email_notification_generator.rb +7 -1
- data/app/services/decidim/send_push_notification.rb +1 -1
- data/app/services/decidim/traceability.rb +1 -0
- data/app/uploaders/decidim/application_uploader.rb +2 -0
- data/app/validators/uploader_image_dimensions_validator.rb +22 -2
- data/app/views/decidim/devise/registrations/new.html.erb.orig +231 -0
- data/app/views/decidim/links/_invalid_url_modal.html.erb +17 -0
- data/app/views/decidim/links/_modal.html.erb +1 -1
- data/app/views/decidim/links/invalid_url.js.erb +24 -0
- data/app/views/decidim/links/new.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/_conversation.html.erb +1 -5
- data/config/environment.rb +0 -0
- data/config/locales/ar.yml +567 -4
- data/config/locales/bg.yml +5 -4
- data/config/locales/ca.yml +27 -22
- data/config/locales/cs.yml +41 -33
- data/config/locales/da.yml +4 -0
- data/config/locales/de.yml +66 -21
- data/config/locales/el.yml +147 -2
- data/config/locales/en.yml +17 -13
- data/config/locales/eo.yml +5 -1
- data/config/locales/es-MX.yml +22 -17
- data/config/locales/es-PY.yml +24 -19
- data/config/locales/es.yml +26 -21
- data/config/locales/et.yml +4 -0
- data/config/locales/eu.yml +154 -63
- data/config/locales/fa-IR.yml +1 -0
- data/config/locales/fi-plain.yml +17 -12
- data/config/locales/fi.yml +20 -15
- data/config/locales/fr-CA.yml +29 -21
- data/config/locales/fr.yml +28 -20
- data/config/locales/ga-IE.yml +5 -0
- data/config/locales/gl.yml +8 -22
- data/config/locales/gn-PY.yml +4 -0
- data/config/locales/hr.yml +4 -0
- data/config/locales/hu.yml +82 -20
- data/config/locales/id-ID.yml +10 -4
- data/config/locales/is-IS.yml +5 -2
- data/config/locales/it.yml +9 -9
- data/config/locales/ja.yml +18 -14
- data/config/locales/ka-GE.yml +4 -0
- data/config/locales/kaa.yml +11 -0
- data/config/locales/lb.yml +12 -12
- data/config/locales/lt.yml +1 -35
- data/config/locales/lv.yml +4 -3
- data/config/locales/nl.yml +5 -27
- data/config/locales/no.yml +9 -27
- data/config/locales/oc-FR.yml +3 -0
- data/config/locales/pl.yml +4 -34
- data/config/locales/pt-BR.yml +7 -7
- data/config/locales/pt.yml +5 -5
- data/config/locales/ro-RO.yml +40 -4
- data/config/locales/ru.yml +3 -3
- data/config/locales/sk.yml +22 -10
- data/config/locales/sl.yml +1 -0
- data/config/locales/sr-CS.yml +10 -0
- data/config/locales/sv.yml +11 -33
- data/config/locales/tr-TR.yml +7 -7
- data/config/locales/uk.yml +3 -3
- data/config/locales/zh-CN.yml +4 -4
- data/config/locales/zh-TW.yml +1886 -0
- 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/asset_router/pipeline.rb +2 -0
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +36 -0
- data/lib/decidim/core/test/shared_examples/digest_mail_examples.rb +33 -0
- data/lib/decidim/core/test/shared_examples/editor_shared_examples.rb +5 -4
- data/lib/decidim/core/test/shared_examples/map_examples.rb +4 -1
- data/lib/decidim/core/test/shared_examples/rich_text_editor_examples.rb +7 -3
- data/lib/decidim/core/test.rb +1 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/core.rb +17 -0
- data/lib/decidim/form_builder.rb +10 -16
- data/lib/decidim/publicable.rb +4 -0
- data/lib/tasks/upgrade/decidim_user_moderation.rake +14 -0
- metadata +23 -12
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
|
@@ -5,6 +5,7 @@ module Decidim
|
|
5
5
|
class UploadModalCell < Decidim::ViewModel
|
6
6
|
include Cell::ViewModel::Partial
|
7
7
|
include ERB::Util
|
8
|
+
include Decidim::SanitizeHelper
|
8
9
|
|
9
10
|
alias form model
|
10
11
|
|
@@ -29,7 +30,7 @@ module Decidim
|
|
29
30
|
end
|
30
31
|
|
31
32
|
def label
|
32
|
-
options[:label]
|
33
|
+
form.send(:custom_label, attribute, options[:label], { required: required?, for: nil })
|
33
34
|
end
|
34
35
|
|
35
36
|
def button_label
|
@@ -72,8 +73,17 @@ module Decidim
|
|
72
73
|
options[:multiple] || false
|
73
74
|
end
|
74
75
|
|
76
|
+
# @deprecated Please use `required?` instead.
|
77
|
+
#
|
78
|
+
# NOTE: When this is removed, also the `optional` option should be removed.
|
75
79
|
def optional
|
76
|
-
|
80
|
+
!required?
|
81
|
+
end
|
82
|
+
|
83
|
+
def required?
|
84
|
+
return !options[:optional] if options.has_key?(:optional)
|
85
|
+
|
86
|
+
options[:required] == true
|
77
87
|
end
|
78
88
|
|
79
89
|
# By default Foundation adds form errors next to input, but since input is in the modal
|
@@ -81,7 +91,7 @@ module Decidim
|
|
81
91
|
# This should only be necessary when file is required by the form.
|
82
92
|
def input_validation_field
|
83
93
|
object_name = form.object.present? ? "#{form.object.model_name.param_key}[#{add_attribute}_validation]" : "#{add_attribute}_validation"
|
84
|
-
input = check_box_tag object_name, 1, attachments.present?, class: "hide", label: false, required:
|
94
|
+
input = check_box_tag object_name, 1, attachments.present?, class: "hide", label: false, required: required?
|
85
95
|
message = form.send(:abide_error_element, add_attribute) + form.send(:error_and_help_text, add_attribute)
|
86
96
|
input + message
|
87
97
|
end
|
@@ -142,7 +152,7 @@ module Decidim
|
|
142
152
|
def title_for(attachment)
|
143
153
|
return unless has_title?
|
144
154
|
|
145
|
-
translated_attribute(attachment.title)
|
155
|
+
decidim_html_escape(decidim_sanitize(translated_attribute(attachment.title)))
|
146
156
|
end
|
147
157
|
|
148
158
|
def truncated_file_name_for(attachment, max_length = 31)
|
@@ -12,8 +12,8 @@ module Decidim
|
|
12
12
|
@attachment = Attachment.new(
|
13
13
|
title: { I18n.locale => @form.attachment.title },
|
14
14
|
attached_to: attached_to,
|
15
|
-
file: @form.attachment.file,
|
16
|
-
content_type: @form.attachment.file
|
15
|
+
file: signed_id_for(@form.attachment.file),
|
16
|
+
content_type: content_type_for(@form.attachment.file)
|
17
17
|
)
|
18
18
|
end
|
19
19
|
|
@@ -53,5 +53,23 @@ module Decidim
|
|
53
53
|
def delete_attachment?
|
54
54
|
@form.attachment&.delete_file.present?
|
55
55
|
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
def signed_id_for(attachment)
|
60
|
+
return attachment[:file] if attachment.is_a?(Hash)
|
61
|
+
|
62
|
+
attachment
|
63
|
+
end
|
64
|
+
|
65
|
+
def content_type_for(attachment)
|
66
|
+
return attachment.content_type if attachment.instance_of?(ActionDispatch::Http::UploadedFile)
|
67
|
+
|
68
|
+
blob(signed_id_for(attachment)).content_type
|
69
|
+
end
|
70
|
+
|
71
|
+
def blob(signed_id)
|
72
|
+
ActiveStorage::Blob.find_signed(signed_id)
|
73
|
+
end
|
56
74
|
end
|
57
75
|
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
|
@@ -41,6 +41,7 @@ module Decidim
|
|
41
41
|
nickname: form.nickname,
|
42
42
|
password: form.password,
|
43
43
|
password_confirmation: form.password_confirmation,
|
44
|
+
password_updated_at: Time.current,
|
44
45
|
organization: form.current_organization,
|
45
46
|
tos_agreement: form.tos_agreement,
|
46
47
|
newsletter_notifications_at: form.newsletter_at,
|
@@ -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
|
@@ -6,9 +6,25 @@ module Decidim
|
|
6
6
|
class SessionsController < ::Devise::SessionsController
|
7
7
|
include Decidim::DeviseControllers
|
8
8
|
|
9
|
-
# rubocop: disable Rails/LexicallyScopedActionFilter
|
10
9
|
before_action :check_sign_in_enabled, only: :create
|
11
|
-
|
10
|
+
|
11
|
+
def create
|
12
|
+
super do |user|
|
13
|
+
if user.admin?
|
14
|
+
# Check that the admin password passes the validation and clear the
|
15
|
+
# `password_updated_at` field when the password is weak to force a
|
16
|
+
# password update on the user.
|
17
|
+
#
|
18
|
+
# Handles a case when the user registers through the registration
|
19
|
+
# form and they are promoted to an admin after that. In this case,
|
20
|
+
# the newly promoted admin user would otherwise have to change their
|
21
|
+
# password straight away even if they originally registered with a
|
22
|
+
# strong password.
|
23
|
+
validator = PasswordValidator.new({ attributes: :password })
|
24
|
+
user.update!(password_updated_at: nil) unless validator.validate_each(user, :password, sign_in_params[:password])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
12
28
|
|
13
29
|
def destroy
|
14
30
|
current_user.invalidate_all_sessions!
|
@@ -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
|
@@ -21,24 +21,21 @@ module Decidim
|
|
21
21
|
|
22
22
|
def invalid_url
|
23
23
|
flash[:alert] = I18n.t("decidim.links.invalid_url")
|
24
|
-
|
24
|
+
if request.xhr?
|
25
|
+
render "invalid_url"
|
26
|
+
else
|
27
|
+
redirect_to decidim.root_path
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
31
|
def parse_url
|
32
|
+
raise Decidim::InvalidUrlError if params[:external_url].blank?
|
28
33
|
raise Decidim::InvalidUrlError unless external_url
|
29
|
-
|
30
|
-
parts = external_url.match %r{\A(([a-z]+):)?//([^/]+)(/.*)?\z}
|
31
|
-
raise Decidim::InvalidUrlError unless parts
|
32
|
-
|
33
|
-
@url_parts = {
|
34
|
-
protocol: parts[1],
|
35
|
-
domain: parts[3],
|
36
|
-
path: parts[4]
|
37
|
-
}
|
34
|
+
raise Decidim::InvalidUrlError unless %w(http https).include?(external_url.scheme)
|
38
35
|
end
|
39
36
|
|
40
37
|
def external_url
|
41
|
-
@external_url ||= URI.parse(params[:external_url])
|
38
|
+
@external_url ||= URI.parse(params[:external_url])
|
42
39
|
end
|
43
40
|
end
|
44
41
|
end
|
@@ -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
|
@@ -3,10 +3,21 @@
|
|
3
3
|
module Decidim
|
4
4
|
module ExternalDomainHelper
|
5
5
|
def highlight_domain
|
6
|
+
highlighted_domain = [
|
7
|
+
external_url.host,
|
8
|
+
(external_url.port && [80, 443].include?(external_url.port) ? "" : ":#{external_url.port}")
|
9
|
+
].join
|
10
|
+
|
11
|
+
path = [
|
12
|
+
external_url.path,
|
13
|
+
(external_url.query ? "?#{external_url.query}" : ""),
|
14
|
+
(external_url.fragment ? "##{external_url.fragment}" : "")
|
15
|
+
].join
|
16
|
+
|
6
17
|
tag.div do
|
7
|
-
content_tag(:span, "#{
|
8
|
-
content_tag(:span,
|
9
|
-
content_tag(:span,
|
18
|
+
content_tag(:span, "#{external_url.scheme}://") +
|
19
|
+
content_tag(:span, highlighted_domain, class: "text-alert") +
|
20
|
+
content_tag(:span, path)
|
10
21
|
end
|
11
22
|
end
|
12
23
|
end
|
@@ -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
|
@@ -112,9 +112,10 @@ module Decidim
|
|
112
112
|
#
|
113
113
|
# @return ActiveSupport::SafeBuffer
|
114
114
|
def render_sanitized_content(resource, method)
|
115
|
-
content = present(resource).send(method, links: true, strip_tags: !safe_content?)
|
115
|
+
content = present(resource).send(method, links: true, strip_tags: !try(:safe_content?))
|
116
116
|
|
117
|
-
return decidim_sanitize(content, {}) unless safe_content?
|
117
|
+
return decidim_sanitize(content, {}) unless try(:safe_content?)
|
118
|
+
return decidim_sanitize_editor_admin(content, {}) if try(:safe_content_admin?)
|
118
119
|
|
119
120
|
decidim_sanitize_editor(content)
|
120
121
|
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
|