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.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/card_g/show.erb +1 -1
  3. data/app/cells/decidim/notification/deleted.erb +12 -0
  4. data/app/cells/decidim/notification/not_available.erb +12 -0
  5. data/app/cells/decidim/notification_cell.rb +5 -1
  6. data/app/cells/decidim/share_widget/modal.erb +1 -1
  7. data/app/commands/decidim/destroy_account.rb +49 -4
  8. data/app/events/decidim/welcome_notification_event.rb +1 -1
  9. data/app/jobs/decidim/remove_search_indexes_job.rb +18 -0
  10. data/app/mailers/decidim/notifications_digest_mailer.rb +18 -1
  11. data/app/models/decidim/component.rb +3 -0
  12. data/app/models/decidim/notification.rb +12 -0
  13. data/app/models/decidim/user.rb +4 -0
  14. data/app/models/decidim/user_base_entity.rb +1 -1
  15. data/app/packs/src/decidim/controllers/multiple_mentions/controller.js +25 -2
  16. data/app/packs/src/decidim/editor/extensions/link/index.js +0 -1
  17. data/app/packs/src/decidim/editor/index.js +5 -1
  18. data/app/packs/src/decidim/editor/test/extensions/link.test.js +2 -2
  19. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_link.js +1 -1
  20. data/app/packs/stylesheets/decidim/_conversations.scss +1 -1
  21. data/app/packs/stylesheets/decidim/_modal.scss +5 -1
  22. data/app/packs/stylesheets/decidim/_modal_fingerprint.scss +1 -1
  23. data/app/presenters/decidim/log/user_presenter.rb +2 -1
  24. data/app/presenters/decidim/organization_presenter.rb +4 -0
  25. data/app/presenters/decidim/user_presenter.rb +6 -1
  26. data/app/views/decidim/manifests/show.json.erb +1 -0
  27. data/app/views/decidim/pages/_tabbed.html.erb +1 -1
  28. data/app/views/decidim/shared/_orders.html.erb +1 -1
  29. data/app/views/layouts/decidim/header/_main_links_mobile_account.html.erb +15 -1
  30. data/config/locales/ar.yml +0 -4
  31. data/config/locales/bg.yml +0 -8
  32. data/config/locales/ca-IT.yml +13 -11
  33. data/config/locales/ca.yml +13 -11
  34. data/config/locales/cs.yml +19 -19
  35. data/config/locales/de.yml +9 -20
  36. data/config/locales/el.yml +0 -3
  37. data/config/locales/en.yml +19 -17
  38. data/config/locales/es-MX.yml +12 -10
  39. data/config/locales/es-PY.yml +12 -10
  40. data/config/locales/es.yml +11 -9
  41. data/config/locales/eu.yml +41 -40
  42. data/config/locales/fa-IR.yml +3 -0
  43. data/config/locales/fi-plain.yml +11 -8
  44. data/config/locales/fi.yml +11 -8
  45. data/config/locales/fr-CA.yml +20 -11
  46. data/config/locales/fr.yml +20 -11
  47. data/config/locales/ga-IE.yml +0 -4
  48. data/config/locales/gl.yml +0 -3
  49. data/config/locales/hu.yml +0 -6
  50. data/config/locales/id-ID.yml +0 -3
  51. data/config/locales/it.yml +0 -3
  52. data/config/locales/ja.yml +24 -22
  53. data/config/locales/ko.yml +3 -0
  54. data/config/locales/lb.yml +0 -3
  55. data/config/locales/lt.yml +0 -5
  56. data/config/locales/lv.yml +0 -3
  57. data/config/locales/mt.yml +3 -0
  58. data/config/locales/nl.yml +0 -3
  59. data/config/locales/no.yml +0 -3
  60. data/config/locales/pl.yml +11 -7
  61. data/config/locales/pt-BR.yml +626 -5
  62. data/config/locales/pt.yml +0 -3
  63. data/config/locales/ro-RO.yml +480 -121
  64. data/config/locales/ru.yml +0 -3
  65. data/config/locales/sk.yml +0 -3
  66. data/config/locales/sv.yml +28 -13
  67. data/config/locales/tr-TR.yml +0 -5
  68. data/config/locales/uk.yml +0 -3
  69. data/config/locales/vi.yml +3 -0
  70. data/config/locales/zh-CN.yml +0 -3
  71. data/config/locales/zh-TW.yml +0 -5
  72. data/db/data/20251125144141_add_short_name_to_organizations.rb +35 -0
  73. data/db/migrate/20251031150928_add_short_name_to_organization.rb +7 -0
  74. data/decidim-core.gemspec +1 -0
  75. data/lib/decidim/core/seeds.rb +2 -2
  76. data/lib/decidim/core/test/factories.rb +25 -0
  77. data/lib/decidim/core/test/shared_examples/comments_examples.rb +27 -1
  78. data/lib/decidim/core/test/shared_examples/fingerprint_examples.rb +13 -0
  79. data/lib/decidim/core/version.rb +1 -1
  80. data/lib/decidim/events/base_event.rb +4 -0
  81. data/lib/decidim/has_private_users.rb +1 -0
  82. data/lib/decidim/seeds.rb +1 -1
  83. data/lib/tasks/decidim_procfile.rake +1 -1
  84. data/lib/tasks/upgrade/decidim_remove_deleted_users_left_data_tasks.rake +30 -0
  85. data/lib/tasks/upgrade/fix_deleted_private_follows.rake +26 -0
  86. metadata +27 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 644720c93a8b08cdb4aa839557a74298774aef2719321671ca3bee677d8e93a6
4
- data.tar.gz: e603634ef33432a213f5122b5e00c11614085d95fcc35e4a3c1b180d582427d8
3
+ metadata.gz: a09ab97ba5e294cac771913b5136ad740e670befc9509ca5827cf86d215f9fa6
4
+ data.tar.gz: ad5ddc3a2ea6c21d8ed9dea42ee2a9307ba44799a8f4ca90c5253f3a75c217dd
5
5
  SHA512:
6
- metadata.gz: a98933696db00e724d2b7ae56c14e3cc718be1026234a9a36679ef3678395a3fe4308be1ff8d9fd59aa233f7c056459e2466089a2f9e21368c9df6b37c722505
7
- data.tar.gz: 2dc98284fe86eb99c409a4f418b00ec6baba661476bfa2114b518a63dfba5313b33e268099a1e90703d98ec4ec438c8e1e4a30e51717ca63c2fb2f57b20e4664
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: alt_title %>
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.event_class_instance.try(:hidden_resource?)
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.destroy_all
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).destroy_all
56
- Decidim::Follow.where(user: current_user).destroy_all
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).destroy_all
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
@@ -153,6 +153,10 @@ module Decidim
153
153
  deleted_at.present?
154
154
  end
155
155
 
156
+ def can_participate?(_user)
157
+ true
158
+ end
159
+
156
160
  # Public: whether the user has been officialized or not
157
161
  def officialized?
158
162
  !officialized_at.nil?
@@ -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.searchInput.addEventListener("selection", (event) => {
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
  /**
@@ -28,7 +28,6 @@ export default Link.extend({
28
28
  ...this.parent?.(),
29
29
  allowTargetControl: false,
30
30
  HTMLAttributes: {
31
- target: "_blank",
32
31
  class: null
33
32
  }
34
33
  }
@@ -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", () => (input.value = editor.getHTML()));
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 target="_blank" href="https://decidim.org">world</a>!</p>'
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 target="_blank" href="https://decidim.org">world</a>!</p>'
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 target="_blank" href="https://decidim.org">world</a>!</p>'
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-col md:flex-row items-start md:items-center gap-2 md:gap-6 mb-14;
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 ltr:-translate-x-1/2 rtl:translate-x-1/2 -translate-y-1/2 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)];
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;
@@ -8,7 +8,7 @@
8
8
  }
9
9
 
10
10
  &__code {
11
- @apply block max-h-24 overflow-auto border border-gray-3 bg-background p-2 break-all;
11
+ @apply block max-h-24 overflow-auto border border-gray-3 bg-background p-2 break-words whitespace-pre-wrap;
12
12
  }
13
13
 
14
14
  a {
@@ -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::TranslatableAttributes
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).to_s %>
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>
@@ -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}
@@ -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: