decidim-core 0.31.0.rc2 → 0.31.1
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/activity_cell.rb +6 -0
- data/app/cells/decidim/card_g/show.erb +1 -1
- data/app/cells/decidim/notification/deleted.erb +12 -0
- data/app/cells/decidim/notification/not_available.erb +12 -0
- data/app/cells/decidim/notification_cell.rb +5 -1
- data/app/cells/decidim/share_widget/modal.erb +1 -1
- data/app/commands/decidim/destroy_account.rb +49 -4
- data/app/controllers/decidim/download_your_data_controller.rb +5 -2
- data/app/events/decidim/welcome_notification_event.rb +1 -1
- data/app/jobs/decidim/remove_search_indexes_job.rb +18 -0
- data/app/mailers/decidim/notifications_digest_mailer.rb +18 -1
- data/app/models/decidim/component.rb +3 -0
- data/app/models/decidim/notification.rb +12 -0
- data/app/models/decidim/private_export.rb +4 -0
- data/app/models/decidim/user.rb +4 -0
- data/app/models/decidim/user_base_entity.rb +1 -1
- data/app/packs/src/decidim/controllers/dropdown/controller.js +2 -2
- data/app/packs/src/decidim/controllers/multiple_mentions/controller.js +25 -2
- data/app/packs/src/decidim/datepicker/generate_datepicker.js +6 -0
- data/app/packs/src/decidim/datepicker/generate_timepicker.js +9 -0
- data/app/packs/src/decidim/editor/extensions/link/index.js +0 -1
- data/app/packs/src/decidim/editor/index.js +5 -1
- data/app/packs/src/decidim/editor/test/extensions/link.test.js +2 -2
- data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_link.js +1 -1
- data/app/packs/src/decidim/index.js +10 -5
- data/app/packs/src/decidim/map/controller/markers.js +3 -1
- data/app/packs/stylesheets/decidim/_conversations.scss +1 -1
- data/app/packs/stylesheets/decidim/_dropdown.scss +22 -5
- data/app/packs/stylesheets/decidim/_filters.scss +1 -1
- data/app/packs/stylesheets/decidim/_footer.scss +5 -0
- data/app/packs/stylesheets/decidim/_modal.scss +5 -1
- data/app/packs/stylesheets/decidim/_modal_fingerprint.scss +1 -1
- data/app/presenters/decidim/log/user_presenter.rb +2 -1
- data/app/presenters/decidim/organization_presenter.rb +4 -0
- data/app/presenters/decidim/user_presenter.rb +6 -1
- data/app/services/decidim/download_your_data_exporter.rb +15 -4
- data/app/services/decidim/open_data_exporter.rb +2 -1
- data/app/views/decidim/download_your_data/_export.html.erb +1 -1
- data/app/views/decidim/export_mailer/download_your_data_export.html.erb +1 -1
- data/app/views/decidim/export_mailer/export.html.erb +1 -1
- data/app/views/decidim/manifests/show.json.erb +1 -0
- data/app/views/decidim/pages/_tabbed.html.erb +1 -1
- data/app/views/decidim/shared/_orders.html.erb +1 -1
- data/app/views/layouts/decidim/header/_main_links_mobile_account.html.erb +15 -1
- data/config/locales/ar.yml +0 -4
- data/config/locales/bg.yml +0 -8
- data/config/locales/ca-IT.yml +17 -13
- data/config/locales/ca.yml +15 -11
- data/config/locales/cs.yml +19 -19
- data/config/locales/de.yml +10 -21
- data/config/locales/el.yml +0 -3
- data/config/locales/en.yml +21 -17
- data/config/locales/es-MX.yml +14 -10
- data/config/locales/es-PY.yml +14 -10
- data/config/locales/es.yml +13 -9
- data/config/locales/eu.yml +67 -55
- data/config/locales/fa-IR.yml +3 -0
- data/config/locales/fi-plain.yml +22 -8
- data/config/locales/fi.yml +22 -8
- data/config/locales/fr-CA.yml +33 -12
- data/config/locales/fr.yml +33 -12
- data/config/locales/ga-IE.yml +0 -4
- data/config/locales/gl.yml +0 -3
- data/config/locales/hu.yml +0 -6
- data/config/locales/id-ID.yml +0 -3
- data/config/locales/it.yml +2 -3
- data/config/locales/ja.yml +46 -22
- data/config/locales/ko.yml +3 -0
- data/config/locales/lb.yml +0 -3
- data/config/locales/lt.yml +0 -5
- data/config/locales/lv.yml +0 -3
- data/config/locales/mt.yml +3 -0
- data/config/locales/nl.yml +0 -3
- data/config/locales/no.yml +0 -3
- data/config/locales/pl.yml +11 -7
- data/config/locales/pt-BR.yml +626 -5
- data/config/locales/pt.yml +0 -3
- data/config/locales/ro-RO.yml +480 -121
- data/config/locales/ru.yml +0 -4
- data/config/locales/sk.yml +0 -3
- data/config/locales/sl.yml +0 -1
- data/config/locales/sv.yml +28 -13
- data/config/locales/tr-TR.yml +0 -5
- data/config/locales/uk.yml +0 -3
- data/config/locales/vi.yml +3 -0
- data/config/locales/zh-CN.yml +0 -3
- data/config/locales/zh-TW.yml +0 -5
- data/db/data/20251108232118_add_dummy_migration.rb +11 -0
- data/db/data/20251125144141_add_short_name_to_organizations.rb +35 -0
- data/db/migrate/20250819110800_convert_private_exports_id_to_uuid.rb +55 -0
- data/db/migrate/20251031150928_add_short_name_to_organization.rb +7 -0
- data/decidim-core.gemspec +2 -0
- data/lib/decidim/core/engine.rb +9 -0
- data/lib/decidim/core/seeds.rb +2 -2
- data/lib/decidim/core/test/factories.rb +32 -2
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +51 -1
- data/lib/decidim/core/test/shared_examples/fingerprint_examples.rb +13 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/events/base_event.rb +4 -0
- data/lib/decidim/has_private_users.rb +1 -0
- data/lib/decidim/seeds.rb +1 -1
- data/lib/decidim/shakapacker/configuration.rb +5 -1
- data/lib/tasks/decidim_procfile.rake +1 -1
- data/lib/tasks/upgrade/clean.rake +11 -0
- data/lib/tasks/upgrade/decidim_fix_action_log.rake +28 -0
- data/lib/tasks/upgrade/decidim_remove_deleted_users_left_data_tasks.rake +30 -0
- data/lib/tasks/upgrade/fix_deleted_private_follows.rake +26 -0
- metadata +44 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a09ab97ba5e294cac771913b5136ad740e670befc9509ca5827cf86d215f9fa6
|
|
4
|
+
data.tar.gz: ad5ddc3a2ea6c21d8ed9dea42ee2a9307ba44799a8f4ca90c5253f3a75c217dd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0cbb0319b8de1e90e2f6d3f4eb52d81ff023c9849d902a6569084065b8e9ec2ef76b48d811d23ada7731f48a2defa940764c6846bf1ae59797d83ab78afb351b
|
|
7
|
+
data.tar.gz: 34ef4ee5189225382525aa6c01c09f7b1a4bc39c1edbec9a7beff9408acacb8766ece1cf6688962d70d4695e2be708b48f74f9fe69d023d675ffe2e10ebf51e3
|
|
@@ -12,6 +12,12 @@ module Decidim
|
|
|
12
12
|
return unless renderable?
|
|
13
13
|
|
|
14
14
|
render
|
|
15
|
+
rescue NoMethodError => e
|
|
16
|
+
# Soft-deleted components or participatory spaces could cause errors
|
|
17
|
+
# when rendering activities. We log them for further inspection but
|
|
18
|
+
# avoid breaking the entire activity feed.
|
|
19
|
+
Rails.logger.error("Error rendering activity cell for #{model.id}: #{e.message}")
|
|
20
|
+
nil
|
|
15
21
|
end
|
|
16
22
|
|
|
17
23
|
# Since activity logs could be linked to resource no longer available
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<%= link_to resource_path, class: classes[:default], id: resource_id do %>
|
|
2
2
|
<div class="<%= classes[:img] %>">
|
|
3
3
|
<% if has_image? %>
|
|
4
|
-
<%= image_tag resource_image_url, alt:
|
|
4
|
+
<%= image_tag resource_image_url, alt: "" %>
|
|
5
5
|
<% else %>
|
|
6
6
|
<%= external_icon "media/images/placeholder-card-g.svg", class: "card__placeholder-g" %>
|
|
7
7
|
<% end %>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<div class="notification" data-notification>
|
|
2
|
+
<div class="notification__wrapper">
|
|
3
|
+
<div class="notification__time" title="<%= l(notification.created_at) %>"> <%= notification.created_at_in_words %></div>
|
|
4
|
+
<div class="notification__snippet">
|
|
5
|
+
<span class="notification__snippet-title text-gray"><%= t("decidim.notifications.show.deleted") %></span>
|
|
6
|
+
</div>
|
|
7
|
+
</div>
|
|
8
|
+
<%= link_to model, remote: true, method: :delete, class: "notification__button", data: { "notification-read": "" } do %>
|
|
9
|
+
<span class="sr-only md:not-sr-only"><%= t("mark_as_read", scope: "layouts.decidim.notifications_dashboard") %></span>
|
|
10
|
+
<%= icon "check-line", class: "fill-current" %>
|
|
11
|
+
<% end %>
|
|
12
|
+
</div>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<div class="notification" data-notification>
|
|
2
|
+
<div class="notification__wrapper">
|
|
3
|
+
<div class="notification__time" title="<%= l(notification.created_at) %>"> <%= notification.created_at_in_words %></div>
|
|
4
|
+
<div class="notification__snippet">
|
|
5
|
+
<span class="notification__snippet-title text-gray"><%= t("decidim.notifications.show.not_available") %></span>
|
|
6
|
+
</div>
|
|
7
|
+
</div>
|
|
8
|
+
<%= link_to model, remote: true, method: :delete, class: "notification__button", data: { "notification-read": "" } do %>
|
|
9
|
+
<span class="sr-only md:not-sr-only"><%= t("mark_as_read", scope: "layouts.decidim.notifications_dashboard") %></span>
|
|
10
|
+
<%= icon "check-line", class: "fill-current" %>
|
|
11
|
+
<% end %>
|
|
12
|
+
</div>
|
|
@@ -7,7 +7,11 @@ module Decidim
|
|
|
7
7
|
include Decidim::Core::Engine.routes.url_helpers
|
|
8
8
|
|
|
9
9
|
def show
|
|
10
|
-
if notification.
|
|
10
|
+
if !notification.can_participate?(current_user)
|
|
11
|
+
render :not_available
|
|
12
|
+
elsif notification.deleted_resource?
|
|
13
|
+
render :deleted
|
|
14
|
+
elsif notification.hidden_resource?
|
|
11
15
|
render :moderated
|
|
12
16
|
else
|
|
13
17
|
render :show
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<%= decidim_modal id: "socialShare", class: "share-modal" do %>
|
|
2
2
|
<div data-dialog-container>
|
|
3
|
-
<h2 tabindex="-1" data-dialog-title><%= t("share", scope: "decidim.shared.share_modal") %></h2>
|
|
3
|
+
<h2 id="dialog-title-social-share-modal" tabindex="-1" data-dialog-title><%= t("share", scope: "decidim.shared.share_modal") %></h2>
|
|
4
4
|
|
|
5
5
|
<div>
|
|
6
6
|
|
|
@@ -19,6 +19,15 @@ module Decidim
|
|
|
19
19
|
destroy_user_account!
|
|
20
20
|
destroy_user_identities
|
|
21
21
|
destroy_follows
|
|
22
|
+
destroy_user_versions
|
|
23
|
+
destroy_user_private_exports
|
|
24
|
+
destroy_user_access_grants
|
|
25
|
+
destroy_user_access_tokens
|
|
26
|
+
destroy_user_reminders
|
|
27
|
+
destroy_user_notifications
|
|
28
|
+
destroy_user_badges
|
|
29
|
+
destroy_user_likes
|
|
30
|
+
destroy_user_reports
|
|
22
31
|
destroy_participatory_space_private_user
|
|
23
32
|
delegate_destroy_to_participatory_spaces
|
|
24
33
|
end
|
|
@@ -47,17 +56,53 @@ module Decidim
|
|
|
47
56
|
current_user.save!
|
|
48
57
|
end
|
|
49
58
|
|
|
59
|
+
def destroy_user_badges
|
|
60
|
+
Decidim::Gamification::BadgeScore.where(user: current_user).find_each(&:destroy)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def destroy_user_reports
|
|
64
|
+
Decidim::UserModeration.where(user: current_user).find_each(&:destroy)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def destroy_user_likes
|
|
68
|
+
Decidim::Like.where(author: current_user).find_each(&:destroy)
|
|
69
|
+
end
|
|
70
|
+
|
|
50
71
|
def destroy_user_identities
|
|
51
|
-
current_user.identities.
|
|
72
|
+
current_user.identities.find_each(&:destroy)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def destroy_user_versions
|
|
76
|
+
current_user.versions.find_each(&:destroy)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def destroy_user_private_exports
|
|
80
|
+
current_user.private_exports.find_each(&:destroy)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def destroy_user_access_grants
|
|
84
|
+
current_user.access_grants.find_each(&:destroy)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def destroy_user_access_tokens
|
|
88
|
+
current_user.access_tokens.find_each(&:destroy)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def destroy_user_reminders
|
|
92
|
+
current_user.reminders.find_each(&:destroy)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def destroy_user_notifications
|
|
96
|
+
current_user.notifications.find_each(&:destroy)
|
|
52
97
|
end
|
|
53
98
|
|
|
54
99
|
def destroy_follows
|
|
55
|
-
Decidim::Follow.where(followable: current_user).
|
|
56
|
-
Decidim::Follow.where(user: current_user).
|
|
100
|
+
Decidim::Follow.where(followable: current_user).find_each(&:destroy)
|
|
101
|
+
Decidim::Follow.where(user: current_user).find_each(&:destroy)
|
|
57
102
|
end
|
|
58
103
|
|
|
59
104
|
def destroy_participatory_space_private_user
|
|
60
|
-
Decidim::ParticipatorySpacePrivateUser.where(user: current_user).
|
|
105
|
+
Decidim::ParticipatorySpacePrivateUser.where(user: current_user).find_each(&:destroy)
|
|
61
106
|
end
|
|
62
107
|
|
|
63
108
|
def delegate_destroy_to_participatory_spaces
|
|
@@ -43,7 +43,10 @@ module Decidim
|
|
|
43
43
|
def download_file
|
|
44
44
|
enforce_permission_to(:download, :user, current_user:)
|
|
45
45
|
|
|
46
|
-
if private_export.
|
|
46
|
+
if private_export.blank?
|
|
47
|
+
flash[:error] = t("decidim.account.download_your_data_export.export_not_found")
|
|
48
|
+
redirect_to download_your_data_path
|
|
49
|
+
elsif private_export.expired?
|
|
47
50
|
flash[:error] = t("decidim.account.download_your_data_export.export_expired")
|
|
48
51
|
redirect_to download_your_data_path
|
|
49
52
|
elsif private_export.file.attached?
|
|
@@ -57,7 +60,7 @@ module Decidim
|
|
|
57
60
|
private
|
|
58
61
|
|
|
59
62
|
def private_export
|
|
60
|
-
@private_export ||= current_user.private_exports.
|
|
63
|
+
@private_export ||= current_user.private_exports.where(uuid: params[:uuid]).first
|
|
61
64
|
end
|
|
62
65
|
|
|
63
66
|
def help_definitions
|
|
@@ -43,7 +43,7 @@ module Decidim
|
|
|
43
43
|
|
|
44
44
|
def interpolate(template)
|
|
45
45
|
template
|
|
46
|
-
.gsub("{{name}}", user.name)
|
|
46
|
+
.gsub("{{name}}", user.presenter.name)
|
|
47
47
|
.gsub("{{organization}}", organization_name(organization))
|
|
48
48
|
.gsub("{{help_url}}", url_helpers.pages_url(host: organization.host))
|
|
49
49
|
.gsub("{{badges_url}}", url_helpers.gamification_badges_url(host: organization.host))
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
class RemoveSearchIndexesJob < ApplicationJob
|
|
5
|
+
queue_as :default
|
|
6
|
+
|
|
7
|
+
def perform(elements)
|
|
8
|
+
elements.each do |element|
|
|
9
|
+
element.remove_from_index(element)
|
|
10
|
+
next unless element.respond_to?(:comments)
|
|
11
|
+
|
|
12
|
+
element.comments.each do |comment|
|
|
13
|
+
Decidim::RemoveSearchIndexesJob.perform_later([comment])
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -17,13 +17,30 @@ module Decidim
|
|
|
17
17
|
# Note that this could be improved by adding a "type" column to the notifications table
|
|
18
18
|
# This fix can generate lists of notifications that are below the SIZE_LIMIT
|
|
19
19
|
@notifications = notifications[0...SIZE_LIMIT].filter_map do |notification|
|
|
20
|
+
# Check if is a notification that can be sent on email
|
|
20
21
|
next unless notification.event_class_instance.respond_to?(:email_intro)
|
|
22
|
+
# checks if the resource exists, as we have implemented the possibility of soft deleting resources
|
|
23
|
+
next unless resource_is_present?(notification)
|
|
24
|
+
# checks if the resource is visible
|
|
25
|
+
next unless notification.can_participate?(@user)
|
|
26
|
+
# It usually checks if the resource is reportable and is not hidden, however, there are some exceptions
|
|
27
|
+
# like in the comments, where we check if the resource and intended comment is visible.
|
|
28
|
+
next if notification.hidden_resource?
|
|
29
|
+
# It usually checks if the resource is deletable and is not deleted, however, there are some exceptions
|
|
30
|
+
# like in the comments, where we check if the resource and intended comment is visible.
|
|
31
|
+
next if notification.deleted_resource?
|
|
21
32
|
|
|
22
33
|
Decidim::NotificationToMailerPresenter.new(notification)
|
|
23
34
|
end
|
|
24
35
|
|
|
25
|
-
mail(to: user.email, subject: @notifications_digest.subject)
|
|
36
|
+
mail(to: user.email, subject: @notifications_digest.subject) if @notifications.any?
|
|
26
37
|
end
|
|
27
38
|
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def resource_is_present?(notification)
|
|
43
|
+
notification.resource
|
|
44
|
+
end
|
|
28
45
|
end
|
|
29
46
|
end
|
|
@@ -100,11 +100,14 @@ module Decidim
|
|
|
100
100
|
def resource_description; end
|
|
101
101
|
|
|
102
102
|
def can_participate_in_space?(user)
|
|
103
|
+
return false unless published?
|
|
104
|
+
return false unless participatory_space.published?
|
|
103
105
|
return true unless participatory_space.try(:private_space?)
|
|
104
106
|
return false unless user
|
|
105
107
|
|
|
106
108
|
participatory_space.can_participate?(user)
|
|
107
109
|
end
|
|
110
|
+
alias can_participate? can_participate_in_space?
|
|
108
111
|
|
|
109
112
|
def private_non_transparent_space?
|
|
110
113
|
return false unless participatory_space.respond_to?(:private_space?)
|
|
@@ -37,8 +37,20 @@ module Decidim
|
|
|
37
37
|
where(decidim_user_id: user.id)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
def can_participate?(user)
|
|
41
|
+
resource.can_participate?(user)
|
|
42
|
+
end
|
|
43
|
+
|
|
40
44
|
def self.export_serializer
|
|
41
45
|
Decidim::DownloadYourDataSerializers::DownloadYourDataNotificationSerializer
|
|
42
46
|
end
|
|
47
|
+
|
|
48
|
+
def hidden_resource?
|
|
49
|
+
event_class_instance.respond_to?(:hidden_resource?) && event_class_instance.hidden_resource?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def deleted_resource?
|
|
53
|
+
event_class_instance.respond_to?(:deleted_resource?) && event_class_instance.deleted_resource?
|
|
54
|
+
end
|
|
43
55
|
end
|
|
44
56
|
end
|
data/app/models/decidim/user.rb
CHANGED
|
@@ -20,7 +20,7 @@ module Decidim
|
|
|
20
20
|
has_one :blocking, class_name: "Decidim::UserBlock", foreign_key: :id, primary_key: :block_id, dependent: :destroy
|
|
21
21
|
|
|
22
22
|
# Regex for name & nickname format validations
|
|
23
|
-
REGEXP_NAME = /\A(?!.*[<>?%&\^*#@()\[\]=+:;"{}
|
|
23
|
+
REGEXP_NAME = /\A(?!.*[<>?%&\^*#@()\[\]=+:;"{}\\|\n\r])/m
|
|
24
24
|
REGEXP_NICKNAME = /\A[a-z0-9_-]+\z/
|
|
25
25
|
|
|
26
26
|
has_one_attached :avatar
|
|
@@ -116,10 +116,10 @@ export default class extends Controller {
|
|
|
116
116
|
changeStyleOfSelectedElement() {
|
|
117
117
|
this.element.addEventListener("click", function(event) {
|
|
118
118
|
event.target.parentNode.parentNode.querySelectorAll("a").forEach((link) => {
|
|
119
|
-
link.parentNode.classList.remove("dropdown__item-
|
|
119
|
+
link.parentNode.classList.remove("dropdown__item-opened");
|
|
120
120
|
})
|
|
121
121
|
|
|
122
|
-
event.target.parentNode.classList.add("dropdown__item-
|
|
122
|
+
event.target.parentNode.classList.add("dropdown__item-opened")
|
|
123
123
|
})
|
|
124
124
|
}
|
|
125
125
|
}
|
|
@@ -16,11 +16,30 @@ export default class extends Controller {
|
|
|
16
16
|
|
|
17
17
|
this.initializeEmptyFocusElement();
|
|
18
18
|
this.initializeAutoComplete();
|
|
19
|
-
this.
|
|
19
|
+
this.setupSelectionListener();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Setup the selection event listener
|
|
24
|
+
* @returns {void}
|
|
25
|
+
*/
|
|
26
|
+
setupSelectionListener() {
|
|
27
|
+
this.selectionHandler = (event) => {
|
|
20
28
|
const feedback = event.detail;
|
|
21
29
|
const selection = feedback.selection;
|
|
22
30
|
this.handleSelection(selection);
|
|
23
|
-
}
|
|
31
|
+
};
|
|
32
|
+
this.searchInput.addEventListener("selection", this.selectionHandler);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/*
|
|
36
|
+
* Remove event listener to prevent duplicates
|
|
37
|
+
* @returns {void}
|
|
38
|
+
*/
|
|
39
|
+
disconnect() {
|
|
40
|
+
if (this.searchInput && this.selectionHandler) {
|
|
41
|
+
this.searchInput.removeEventListener("selection", this.selectionHandler);
|
|
42
|
+
}
|
|
24
43
|
}
|
|
25
44
|
|
|
26
45
|
/**
|
|
@@ -150,6 +169,10 @@ export default class extends Controller {
|
|
|
150
169
|
this.addSelectedUser(selection, id);
|
|
151
170
|
this.autoComplete.setInput("");
|
|
152
171
|
this.selected.push(id);
|
|
172
|
+
|
|
173
|
+
if (this.autoComplete && this.autoComplete.autocomplete) {
|
|
174
|
+
this.autoComplete.autocomplete.close();
|
|
175
|
+
}
|
|
153
176
|
}
|
|
154
177
|
|
|
155
178
|
/**
|
|
@@ -14,12 +14,18 @@ export default function generateDatePicker(input, row, formats) {
|
|
|
14
14
|
date.setAttribute("id", `${input.id}_date`);
|
|
15
15
|
date.setAttribute("type", "text");
|
|
16
16
|
date.setAttribute("aria-label", input.dataset.dateLabel);
|
|
17
|
+
if (input.attributes.disabled) {
|
|
18
|
+
date.setAttribute("disabled", input.attributes.disabled);
|
|
19
|
+
};
|
|
17
20
|
|
|
18
21
|
const calendar = document.createElement("button");
|
|
19
22
|
calendar.innerHTML = icon("calendar-line");
|
|
20
23
|
calendar.setAttribute("class", "datepicker__calendar-button");
|
|
21
24
|
calendar.setAttribute("type", "button");
|
|
22
25
|
calendar.setAttribute("aria-label", input.dataset.buttonDateLabel);
|
|
26
|
+
if (input.attributes.disabled) {
|
|
27
|
+
calendar.setAttribute("disabled", input.attributes.disabled);
|
|
28
|
+
};
|
|
23
29
|
|
|
24
30
|
dateColumn.appendChild(date);
|
|
25
31
|
dateColumn.appendChild(calendar);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/* eslint-disable require-jsdoc */
|
|
2
|
+
/* eslint max-lines: ["error", 310] */
|
|
3
|
+
|
|
2
4
|
import icon from "src/decidim/refactor/moved/icon"
|
|
3
5
|
import { changeHourDisplay, changeMinuteDisplay, formatDate, hourDisplay, minuteDisplay, formatTime, setHour, setMinute, updateTimeValue, updateInputValue } from "src/decidim/datepicker/datepicker_functions"
|
|
4
6
|
import { timeKeyDownListener, timeBeforeInputListener } from "src/decidim/datepicker/datepicker_listeners";
|
|
@@ -14,12 +16,19 @@ export default function generateTimePicker(input, row, formats) {
|
|
|
14
16
|
time.setAttribute("id", `${input.id}_time`);
|
|
15
17
|
time.setAttribute("type", "text");
|
|
16
18
|
time.setAttribute("aria-label", input.dataset.timeLabel);
|
|
19
|
+
if (input.attributes.disabled) {
|
|
20
|
+
time.setAttribute("disabled", input.attributes.disabled);
|
|
21
|
+
};
|
|
17
22
|
|
|
18
23
|
const clock = document.createElement("button");
|
|
19
24
|
clock.innerHTML = icon("time-line")
|
|
20
25
|
clock.setAttribute("class", "datepicker__clock-button");
|
|
21
26
|
clock.setAttribute("type", "button");
|
|
22
27
|
clock.setAttribute("aria-label", input.dataset.buttonTimeLabel);
|
|
28
|
+
if (input.attributes.disabled) {
|
|
29
|
+
clock.setAttribute("disabled", input.attributes.disabled);
|
|
30
|
+
};
|
|
31
|
+
|
|
23
32
|
|
|
24
33
|
timeColumn.appendChild(time);
|
|
25
34
|
timeColumn.appendChild(clock);
|
|
@@ -81,7 +81,11 @@ export default function createEditor(container) {
|
|
|
81
81
|
const toolbar = createEditorToolbar(editor);
|
|
82
82
|
container.insertBefore(toolbar, editorContainer);
|
|
83
83
|
|
|
84
|
-
editor.on("update", () =>
|
|
84
|
+
editor.on("update", () => {
|
|
85
|
+
input.value = editor.isEmpty
|
|
86
|
+
? ""
|
|
87
|
+
: editor.getHTML();
|
|
88
|
+
});
|
|
85
89
|
|
|
86
90
|
return editor;
|
|
87
91
|
}
|
|
@@ -37,14 +37,14 @@ describe("Link", () => {
|
|
|
37
37
|
await sleep(50);
|
|
38
38
|
|
|
39
39
|
expect(editor.getHTML()).toEqual(
|
|
40
|
-
'<p>Hello, <a
|
|
40
|
+
'<p>Hello, <a href="https://decidim.org" target="_blank">world</a>!</p>'
|
|
41
41
|
);
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
it("allows editing the link through the dialog", async () => {
|
|
45
45
|
editorElement.focus();
|
|
46
46
|
await updateContent(editorElement,
|
|
47
|
-
'<p>Hello, <a
|
|
47
|
+
'<p>Hello, <a href="https://decidim.org" target="_blank" >world</a>!</p>'
|
|
48
48
|
);
|
|
49
49
|
|
|
50
50
|
// Set the editor cursor inside the link
|
|
@@ -26,7 +26,7 @@ export default (ctx) => {
|
|
|
26
26
|
await sleep(0);
|
|
27
27
|
|
|
28
28
|
expect(ctx.prosemirror.innerHTML).toEqual(
|
|
29
|
-
'<p>Hello, <a
|
|
29
|
+
'<p>Hello, <a href="https://decidim.org" target="_blank">world</a>!</p>'
|
|
30
30
|
);
|
|
31
31
|
});
|
|
32
32
|
});
|
|
@@ -70,16 +70,21 @@ const deprecate = (element, targetController, oldSyntax) => {
|
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
console.warn(element)
|
|
74
73
|
console.warn(`[Decidim] ${oldSyntax} is deprecated. Please use the new version of this component - data-controller="${targetController}" - ${window.location.href}`)
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
|
|
75
|
+
if (typeof window.Decidim.dev !== "undefined" && window.Decidim.dev === true) {
|
|
76
|
+
// eslint-disable-next-line no-alert
|
|
77
|
+
alert(`[Decidim] ${oldSyntax} is deprecated. Please use the new version of this component - data-controller="${targetController}"`)
|
|
78
|
+
}
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
const deprecationMessage = (element, oldSyntax, newSyntax) => {
|
|
80
82
|
console.warn(`[Decidim] ${oldSyntax} is deprecated. Please use the new version of this component - ${newSyntax}`)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
|
|
84
|
+
if (typeof window.Decidim.dev !== "undefined" && window.Decidim.dev === true) {
|
|
85
|
+
// eslint-disable-next-line no-alert
|
|
86
|
+
alert(`[Decidim] ${oldSyntax} is deprecated. Please use the new version of this component - ${newSyntax}`)
|
|
87
|
+
}
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
window.deprecate = deprecate;
|
|
@@ -67,7 +67,9 @@ export default class MapMarkersController extends MapController {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
clearMarkers() {
|
|
70
|
-
|
|
70
|
+
if (this.markerClusters !== null) {
|
|
71
|
+
this.map.removeLayer(this.markerClusters);
|
|
72
|
+
}
|
|
71
73
|
this.markerClusters = new L.MarkerClusterGroup();
|
|
72
74
|
this.map.addLayer(this.markerClusters);
|
|
73
75
|
}
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
&__participants {
|
|
59
|
-
@apply bg-background rounded px-4 py-2 flex flex-
|
|
59
|
+
@apply bg-background rounded px-4 py-2 flex flex-wrap items-start md:items-center gap-2 md:gap-6 mb-14;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
&__message {
|
|
@@ -106,12 +106,9 @@
|
|
|
106
106
|
@apply text-gray-2 mr-1;
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
-
}
|
|
110
109
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
> .dropdown__button {
|
|
114
|
-
@apply text-white no-underline;
|
|
110
|
+
&:hover {
|
|
111
|
+
@apply text-white no-underline !bg-secondary;
|
|
115
112
|
|
|
116
113
|
span {
|
|
117
114
|
@apply text-white;
|
|
@@ -122,6 +119,26 @@
|
|
|
122
119
|
}
|
|
123
120
|
}
|
|
124
121
|
}
|
|
122
|
+
|
|
123
|
+
&-opened {
|
|
124
|
+
> .dropdown__button {
|
|
125
|
+
@apply text-secondary no-underline;
|
|
126
|
+
|
|
127
|
+
span {
|
|
128
|
+
@apply text-secondary;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
svg {
|
|
132
|
+
fill: rgb(var(--secondary-rgb) / var(--tw-bg-opacity)) !important;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
&:hover {
|
|
136
|
+
svg {
|
|
137
|
+
fill: white !important;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
125
142
|
}
|
|
126
143
|
|
|
127
144
|
&__bottom {
|
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
@apply invisible opacity-0 fixed z-50 inset-0 bg-[rgba(0,0,0,0.25)] transition duration-300;
|
|
3
3
|
|
|
4
4
|
& > * {
|
|
5
|
-
@apply absolute inset-1/2
|
|
5
|
+
@apply absolute inset-1/2 translate-x-[-50%] translate-y-[-50%] w-[90%] lg:max-w-[900px] max-h-[95vh] h-fit overflow-y-auto p-6 bg-white z-50 rounded shadow-[0_4px_6px_rgba(211,211,211,0.25)];
|
|
6
|
+
|
|
7
|
+
[dir="rtl"] & {
|
|
8
|
+
@apply translate-x-[50%];
|
|
9
|
+
}
|
|
6
10
|
|
|
7
11
|
& > svg:only-child {
|
|
8
12
|
@apply w-8 h-8 mx-auto text-gray-2 fill-current animate-spin;
|
|
@@ -10,6 +10,7 @@ module Decidim
|
|
|
10
10
|
# overwrite `BasePresenter#user_presenter` to return your custom user presenter.
|
|
11
11
|
# The only requirement for custom renderers is that they should respond to `present`.
|
|
12
12
|
class UserPresenter
|
|
13
|
+
include Decidim::SanitizeHelper
|
|
13
14
|
# Public: Initializes the presenter.
|
|
14
15
|
#
|
|
15
16
|
# user - An instance of Decidim::User
|
|
@@ -60,7 +61,7 @@ module Decidim
|
|
|
60
61
|
#
|
|
61
62
|
# Returns an HTML-safe String.
|
|
62
63
|
def present_user_name
|
|
63
|
-
extra["name"].html_safe
|
|
64
|
+
decidim_sanitize_translated(extra["name"]).html_safe
|
|
64
65
|
end
|
|
65
66
|
|
|
66
67
|
# Private: Presents the nickname of the user performing the action.
|
|
@@ -7,6 +7,10 @@ module Decidim
|
|
|
7
7
|
translated_attribute(name).html_safe
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
def html_short_name
|
|
11
|
+
translated_attribute(short_name).html_safe
|
|
12
|
+
end
|
|
13
|
+
|
|
10
14
|
def translated_description
|
|
11
15
|
ActionView::Base.full_sanitizer.sanitize(translated_attribute(description)).html_safe
|
|
12
16
|
end
|