decidim-core 0.31.0 → 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/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/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/user.rb +4 -0
- data/app/models/decidim/user_base_entity.rb +1 -1
- data/app/packs/src/decidim/controllers/multiple_mentions/controller.js +25 -2
- 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/stylesheets/decidim/_conversations.scss +1 -1
- 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/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 +13 -11
- data/config/locales/ca.yml +13 -11
- data/config/locales/cs.yml +19 -19
- data/config/locales/de.yml +9 -20
- data/config/locales/el.yml +0 -3
- data/config/locales/en.yml +19 -17
- data/config/locales/es-MX.yml +12 -10
- data/config/locales/es-PY.yml +12 -10
- data/config/locales/es.yml +11 -9
- data/config/locales/eu.yml +41 -40
- data/config/locales/fa-IR.yml +3 -0
- data/config/locales/fi-plain.yml +11 -8
- data/config/locales/fi.yml +11 -8
- data/config/locales/fr-CA.yml +20 -11
- data/config/locales/fr.yml +20 -11
- 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 +0 -3
- data/config/locales/ja.yml +24 -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 -3
- data/config/locales/sk.yml +0 -3
- 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/20251125144141_add_short_name_to_organizations.rb +35 -0
- data/db/migrate/20251031150928_add_short_name_to_organization.rb +7 -0
- data/decidim-core.gemspec +1 -0
- data/lib/decidim/core/seeds.rb +2 -2
- data/lib/decidim/core/test/factories.rb +25 -0
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +27 -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/tasks/decidim_procfile.rake +1 -1
- 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 +27 -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
|
|
@@ -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,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
|
|
@@ -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
|
/**
|
|
@@ -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
|
});
|
|
@@ -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 {
|
|
@@ -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
|
|
@@ -6,7 +6,12 @@ module Decidim
|
|
|
6
6
|
#
|
|
7
7
|
class UserPresenter < SimpleDelegator
|
|
8
8
|
include ActionView::Helpers::UrlHelper
|
|
9
|
-
include Decidim::
|
|
9
|
+
include Decidim::SanitizeHelper
|
|
10
|
+
|
|
11
|
+
# name sanitized
|
|
12
|
+
def name
|
|
13
|
+
decidim_sanitize_translated(__getobj__.name)
|
|
14
|
+
end
|
|
10
15
|
|
|
11
16
|
#
|
|
12
17
|
# nickname presented in a twitter-like style
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "<%= organization_params.html_name %>",
|
|
3
|
+
"short_name": "<%= organization_params.html_short_name %>",
|
|
3
4
|
"lang": "<%= organization_params.default_locale %>",
|
|
4
5
|
"description": "<%= organization_params.translated_description %>",
|
|
5
6
|
"display": "<%= organization_params.pwa_display %>",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
<ul id="dropdown-menu-pages" class="vertical-tabs__list" role="menu">
|
|
22
22
|
<% pages.each do |sibling| %>
|
|
23
23
|
<li class="<%= "is-active" if page == sibling %>" role="menuitem">
|
|
24
|
-
<%= link_to translated_attribute(sibling.title), page_path(sibling.slug), "aria-current": (page == sibling)
|
|
24
|
+
<%= link_to translated_attribute(sibling.title), page_path(sibling.slug), "aria-current": ("page" if page == sibling) %>
|
|
25
25
|
</li>
|
|
26
26
|
<% end %>
|
|
27
27
|
</ul>
|
|
@@ -9,6 +9,6 @@
|
|
|
9
9
|
i18n_scope:,
|
|
10
10
|
title: t("#{i18n_scope}.label"),
|
|
11
11
|
role: :menuitem,
|
|
12
|
-
class: "button button__sm button__text-secondary #{order_name == order ? "underline font-bold" : "font-normal"}" %>
|
|
12
|
+
class: "button button__sm button__text-secondary #{order_name == order ? "underline font-bold" : "font-normal"}", "aria-current": order_name == order ? "true" : "" %>
|
|
13
13
|
<% end %>
|
|
14
14
|
</div>
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
</div>
|
|
11
11
|
|
|
12
12
|
<div>
|
|
13
|
-
<div class="main-bar__links-mobile__trigger" onclick="document.querySelector('#dropdown-trigger-links-mobile').click();document.querySelector('#dropdown-menu-account-mobile').removeAttribute('aria-modal')">
|
|
13
|
+
<div class="main-bar__links-mobile__trigger" tabindex="0" onclick="document.querySelector('#dropdown-trigger-links-mobile').click();document.querySelector('#dropdown-menu-account-mobile').removeAttribute('aria-modal')">
|
|
14
14
|
<%= icon "close-line" %>
|
|
15
|
+
<p class="sr-only"><%= t("close", scope: "decidim.shared.flag_modal") %></p>
|
|
15
16
|
</div>
|
|
16
17
|
</div>
|
|
17
18
|
</div>
|
|
@@ -37,3 +38,16 @@
|
|
|
37
38
|
</ul>
|
|
38
39
|
</div>
|
|
39
40
|
</div>
|
|
41
|
+
<script type="text/javascript">
|
|
42
|
+
const closeDiv = document.querySelector('div.main-bar__links-mobile__trigger');
|
|
43
|
+
const menuDropdown = document.querySelector('#dropdown-menu-account-mobile');
|
|
44
|
+
const dropdownTrigger = document.querySelector('#dropdown-trigger-links-mobile');
|
|
45
|
+
// 32 is code for space bar and 13 is code for enter
|
|
46
|
+
closeDiv.addEventListener('keydown', function(e){
|
|
47
|
+
if (e.keyCode === 13 || e.keyCode === 32) {
|
|
48
|
+
menuDropdown.removeAttribute('aria-modal');
|
|
49
|
+
menuDropdown.setAttribute('aria-hidden', "true");
|
|
50
|
+
dropdownTrigger.focus();
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
</script>
|
data/config/locales/ar.yml
CHANGED
|
@@ -885,7 +885,6 @@ ar:
|
|
|
885
885
|
hello: مرحبا %{name}،
|
|
886
886
|
intro:
|
|
887
887
|
daily: 'هذه هي إخطارات اليوم الأخير بناءً على النشاط الذي تتابعه:'
|
|
888
|
-
real_time: 'هذا تنبيه عن النشاط الذي تتبعّه:'
|
|
889
888
|
weekly: 'هذه هي إخطارات الأسبوع الأخير بناءً على النشاط الذي تتابعه:'
|
|
890
889
|
outro: لقد تلقيت هذه الإشعارات لأنك تتبع هذا المحتوى أو مؤلفيه. يمكنك إلغاء متابعتها من صفحات كل منهم.
|
|
891
890
|
see_more: عرض المزيد من الإشعارات
|
|
@@ -934,13 +933,10 @@ ar:
|
|
|
934
933
|
proposals_explanation: تقديم مقترحات ، ودعم المقترحات الحالية وتعزيز التغييرات التي تريد رؤيتها.
|
|
935
934
|
footer_sub_hero:
|
|
936
935
|
footer_sub_hero_headline: مرحبًا بكم على المنصة التشاركية لـ %{organization}.
|
|
937
|
-
register: تسجيل
|
|
938
936
|
hero:
|
|
939
937
|
participate: مشاركة
|
|
940
938
|
participate_title: المشاركة في مسارات المنصة
|
|
941
939
|
welcome: مرحبًا بكم على %{organization}!
|
|
942
|
-
sub_hero:
|
|
943
|
-
register: تسجيل
|
|
944
940
|
index:
|
|
945
941
|
standalone_pages: صفحات
|
|
946
942
|
subheading: انتقل من خلال صفحات المساعدة من %{name}
|
data/config/locales/bg.yml
CHANGED
|
@@ -626,7 +626,6 @@ bg:
|
|
|
626
626
|
files:
|
|
627
627
|
file_cannot_be_processed: Файлът не може да бъде обработен
|
|
628
628
|
file_resolution_too_large: Разделителната способност на файла е твърде голяма
|
|
629
|
-
not_inside_organization: Файлът не е прикачен към никоя организация.
|
|
630
629
|
internal_server_error:
|
|
631
630
|
copied: Текстът е копиран!
|
|
632
631
|
copy_error_message_clarification: Копирайте съобщението за грешка в клипборда
|
|
@@ -1014,11 +1013,9 @@ bg:
|
|
|
1014
1013
|
same_language: Съдържанието е публикувано на предпочитания от вас език (%{language}), поради което в този имейл не се показва автоматичен превод.
|
|
1015
1014
|
translated_text: 'Автоматично преведен текст:'
|
|
1016
1015
|
notifications:
|
|
1017
|
-
action_error: Възникна проблем при актуализирането на известията.
|
|
1018
1016
|
no_notifications: Още няма известия.
|
|
1019
1017
|
show:
|
|
1020
1018
|
missing_event: Упс, това известие принадлежи на съдържание, което вече не е налично. Можете да го подминете.
|
|
1021
|
-
moderated: Съдържанието е модерирано
|
|
1022
1019
|
notifications_digest_mailer:
|
|
1023
1020
|
header:
|
|
1024
1021
|
daily: Ежедневно обобщение на известията
|
|
@@ -1082,13 +1079,10 @@ bg:
|
|
|
1082
1079
|
footer_sub_hero:
|
|
1083
1080
|
footer_sub_hero_body_html: Нека изградим по-отворено, прозрачно и задружно общество.<br /> Присъединете се, участвайте и решавайте.
|
|
1084
1081
|
footer_sub_hero_headline: Добре дошли в платформата за сътрудничество %{organization}!
|
|
1085
|
-
register: Регистрация
|
|
1086
1082
|
hero:
|
|
1087
1083
|
participate: Участвайте
|
|
1088
1084
|
participate_title: Участвайте в процесите на платформата
|
|
1089
1085
|
welcome: Добре дошли в %{organization}!
|
|
1090
|
-
sub_hero:
|
|
1091
|
-
register: Регистрация
|
|
1092
1086
|
index:
|
|
1093
1087
|
standalone_pages: Страници
|
|
1094
1088
|
subheading: Придвижвайте се в помощта на %{name}
|
|
@@ -1350,8 +1344,6 @@ bg:
|
|
|
1350
1344
|
subject: Получихте покана да управлявате %{organization}
|
|
1351
1345
|
invite_collaborator:
|
|
1352
1346
|
subject: Получихте покана да сътрудничите на %{organization}
|
|
1353
|
-
invite_private_user:
|
|
1354
|
-
subject: Поканени сте в частен процес на сътрудничество в %{organization}
|
|
1355
1347
|
organization_admin_invitation_instructions:
|
|
1356
1348
|
subject: Получихте покана да управлявате %{organization}
|
|
1357
1349
|
password_change:
|