decidim-core 0.28.4 → 0.28.6

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 (141) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/activity_cell.rb +1 -4
  3. data/app/cells/decidim/author/show.erb +5 -4
  4. data/app/cells/decidim/author_cell.rb +26 -0
  5. data/app/cells/decidim/card_s/show.erb +5 -3
  6. data/app/cells/decidim/diff_cell.rb +4 -0
  7. data/app/cells/decidim/newsletter_templates/image_text_cta_cell.rb +1 -1
  8. data/app/cells/decidim/participatory_space_dropdown_metadata/show.erb +5 -3
  9. data/app/cells/decidim/resource_types_filter/show.erb +1 -1
  10. data/app/cells/decidim/resource_types_filter_cell.rb +6 -6
  11. data/app/cells/decidim/translation_bar/show.erb +3 -3
  12. data/app/cells/decidim/translation_bar_cell.rb +1 -1
  13. data/app/cells/decidim/user_activity/show.erb +1 -1
  14. data/app/commands/decidim/create_omniauth_registration.rb +14 -8
  15. data/app/commands/decidim/destroy_account.rb +3 -0
  16. data/app/commands/decidim/search.rb +14 -0
  17. data/app/controllers/decidim/doorkeeper/credentials_controller.rb +1 -1
  18. data/app/controllers/decidim/links_controller.rb +1 -1
  19. data/app/controllers/decidim/profiles_controller.rb +6 -2
  20. data/app/controllers/decidim/reports_controller.rb +1 -1
  21. data/app/controllers/decidim/user_activities_controller.rb +1 -1
  22. data/app/forms/decidim/account_form.rb +5 -2
  23. data/app/helpers/concerns/decidim/user_role_checker.rb +46 -0
  24. data/app/helpers/decidim/cta_button_helper.rb +1 -1
  25. data/app/helpers/decidim/map_helper.rb +6 -1
  26. data/app/helpers/decidim/orders_helper.rb +2 -1
  27. data/app/helpers/decidim/participatory_space_helpers.rb +1 -1
  28. data/app/helpers/decidim/sanitize_helper.rb +11 -2
  29. data/app/models/decidim/attachment.rb +1 -1
  30. data/app/models/decidim/user.rb +0 -4
  31. data/app/models/decidim/user_base_entity.rb +4 -0
  32. data/app/packs/src/decidim/append_redirect_url_to_modals.js +14 -6
  33. data/app/packs/src/decidim/direct_uploads/upload_field.js +21 -8
  34. data/app/packs/src/decidim/index.js +5 -0
  35. data/app/packs/src/decidim/map/provider/here.js +1 -1
  36. data/app/packs/src/decidim/remote_tooltips.js +38 -0
  37. data/app/packs/src/decidim/toggle.js +1 -1
  38. data/app/packs/src/decidim/tooltips.js +42 -22
  39. data/app/packs/stylesheets/decidim/_hashtags.scss +5 -0
  40. data/app/packs/stylesheets/decidim/_header.scss +20 -2
  41. data/app/packs/stylesheets/decidim/_profile.scss +1 -1
  42. data/app/packs/stylesheets/decidim/_progress-bar.scss +1 -1
  43. data/app/packs/stylesheets/decidim/application.scss +1 -0
  44. data/app/packs/stylesheets/decidim/legacy/conference-diploma.scss +2 -1
  45. data/app/presenters/decidim/attachment_presenter.rb +1 -1
  46. data/app/presenters/decidim/log/user_presenter.rb +1 -0
  47. data/app/services/decidim/base_diff_renderer.rb +28 -2
  48. data/app/services/decidim/email_notification_generator.rb +14 -5
  49. data/app/services/decidim/static_map_generator.rb +1 -1
  50. data/app/views/decidim/last_activities/index.html.erb +1 -1
  51. data/app/views/decidim/pages/_tabbed.html.erb +2 -2
  52. data/app/views/decidim/reported_mailer/hide.html.erb +1 -1
  53. data/app/views/decidim/reported_mailer/report.html.erb +1 -1
  54. data/app/views/decidim/searches/_count.html.erb +1 -1
  55. data/app/views/decidim/searches/_filters.html.erb +40 -38
  56. data/app/views/decidim/shared/_orders.html.erb +2 -2
  57. data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile_tablet.html.erb +1 -1
  58. data/config/locales/ar.yml +55 -12
  59. data/config/locales/bg.yml +17 -8
  60. data/config/locales/bn-BD.yml +1 -0
  61. data/config/locales/bs-BA.yml +100 -0
  62. data/config/locales/ca-IT.yml +2115 -0
  63. data/config/locales/ca.yml +69 -22
  64. data/config/locales/cs.yml +62 -15
  65. data/config/locales/de.yml +67 -20
  66. data/config/locales/el.yml +17 -2
  67. data/config/locales/en.yml +47 -0
  68. data/config/locales/eo.yml +2 -0
  69. data/config/locales/es-MX.yml +61 -14
  70. data/config/locales/es-PY.yml +65 -18
  71. data/config/locales/es.yml +72 -25
  72. data/config/locales/eu.yml +308 -250
  73. data/config/locales/fi-plain.yml +50 -11
  74. data/config/locales/fi.yml +87 -48
  75. data/config/locales/fr-CA.yml +57 -10
  76. data/config/locales/fr.yml +55 -8
  77. data/config/locales/ga-IE.yml +11 -0
  78. data/config/locales/gl.yml +33 -2
  79. data/config/locales/hu.yml +17 -10
  80. data/config/locales/id-ID.yml +32 -3
  81. data/config/locales/is-IS.yml +18 -2
  82. data/config/locales/it.yml +84 -14
  83. data/config/locales/ja.yml +70 -23
  84. data/config/locales/lb.yml +32 -7
  85. data/config/locales/lt.yml +9 -3
  86. data/config/locales/lv.yml +26 -2
  87. data/config/locales/nl.yml +33 -6
  88. data/config/locales/no.yml +25 -0
  89. data/config/locales/pl.yml +15 -6
  90. data/config/locales/pt-BR.yml +18 -8
  91. data/config/locales/pt.yml +31 -0
  92. data/config/locales/ro-RO.yml +475 -207
  93. data/config/locales/ru.yml +33 -1
  94. data/config/locales/sk.yml +39 -7
  95. data/config/locales/sl.yml +4 -0
  96. data/config/locales/sr-CS.yml +2 -0
  97. data/config/locales/sv.yml +35 -16
  98. data/config/locales/tr-TR.yml +32 -8
  99. data/config/locales/uk.yml +20 -2
  100. data/config/locales/zh-CN.yml +27 -2
  101. data/config/locales/zh-TW.yml +14 -0
  102. data/config/routes.rb +1 -0
  103. data/decidim-core.gemspec +4 -1
  104. data/lib/decidim/api/functions/component_list.rb +1 -1
  105. data/lib/decidim/api/functions/participatory_space_finder_base.rb +11 -1
  106. data/lib/decidim/api/interfaces/participatory_space_interface.rb +1 -1
  107. data/lib/decidim/api/types/component_type.rb +7 -0
  108. data/lib/decidim/api/types/user_group_type.rb +4 -0
  109. data/lib/decidim/api/types/user_type.rb +4 -0
  110. data/lib/decidim/attributes/rich_text.rb +38 -0
  111. data/lib/decidim/attributes/time_with_zone.rb +16 -2
  112. data/lib/decidim/attributes.rb +2 -0
  113. data/lib/decidim/content_parsers/blob_parser.rb +95 -0
  114. data/lib/decidim/content_parsers/user_parser.rb +1 -1
  115. data/lib/decidim/content_parsers.rb +1 -0
  116. data/lib/decidim/content_renderers/blob_renderer.rb +90 -0
  117. data/lib/decidim/content_renderers.rb +1 -0
  118. data/lib/decidim/core/engine.rb +29 -1
  119. data/lib/decidim/core/test/factories.rb +28 -0
  120. data/lib/decidim/core/test/shared_examples/authorable_interface_examples.rb +1 -1
  121. data/lib/decidim/core/test/shared_examples/comments_examples.rb +15 -2
  122. data/lib/decidim/core/test/shared_examples/reports_examples.rb +48 -6
  123. data/lib/decidim/core/test/shared_examples/uncommentable_component_examples.rb +26 -0
  124. data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +26 -0
  125. data/lib/decidim/core/version.rb +1 -1
  126. data/lib/decidim/diffy_extension.rb +18 -0
  127. data/lib/decidim/form_builder.rb +1 -1
  128. data/lib/decidim/map/autocomplete.rb +1 -0
  129. data/lib/decidim/map/provider/dynamic_map/here.rb +1 -40
  130. data/lib/decidim/map/provider/static_map/here.rb +34 -0
  131. data/lib/decidim/nicknamizable.rb +1 -1
  132. data/lib/decidim/participatory_space_user.rb +4 -0
  133. data/lib/decidim/query_extensions.rb +0 -26
  134. data/lib/decidim/reportable.rb +6 -2
  135. data/lib/decidim/settings_manifest.rb +2 -0
  136. data/lib/decidim/translatable_attributes.rb +10 -1
  137. data/lib/decidim/view_model.rb +1 -0
  138. data/lib/tasks/upgrade/decidim_fix_categorization.rake +34 -8
  139. data/lib/tasks/upgrade/decidim_fix_nickname_uniqueness.rake +23 -20
  140. metadata +30 -8
  141. data/app/packs/src/decidim/vendor/leaflet-tilelayer-here.js +0 -212
@@ -68,6 +68,8 @@ import markAsReadNotifications from "src/decidim/notifications"
68
68
  import RemoteModal from "src/decidim/remote_modal"
69
69
  import selectActiveIdentity from "src/decidim/identity_selector_dialog"
70
70
  import createTooltip from "src/decidim/tooltips"
71
+ // Temporary disabling this feature because we have a poor performance. See https://github.com/decidim/decidim/issues/14431
72
+ // import fetchRemoteTooltip from "src/decidim/remote_tooltips"
71
73
  import createToggle from "src/decidim/toggle"
72
74
  import {
73
75
  createAccordion,
@@ -189,6 +191,9 @@ const initializer = (element = document) => {
189
191
  // Initialize data-toggles
190
192
  element.querySelectorAll("[data-toggle]").forEach((elem) => createToggle(elem))
191
193
 
194
+ // Temporary disabling this feature because we have a poor performance. See https://github.com/decidim/decidim/issues/14431
195
+ // element.querySelectorAll("[data-remote-tooltip]").forEach((elem) => fetchRemoteTooltip(elem))
196
+
192
197
  element.querySelectorAll(".new_report").forEach((elem) => changeReportFormBehavior(elem))
193
198
  }
194
199
 
@@ -1,5 +1,5 @@
1
1
  import "leaflet"
2
- import "src/decidim/vendor/leaflet-tilelayer-here"
2
+ import "leaflet-tilelayer-here"
3
3
 
4
4
  /**
5
5
  * NOTE:
@@ -0,0 +1,38 @@
1
+ import createTooltip from "src/decidim/tooltips"
2
+
3
+ /**
4
+ * Given the following HTML structure,
5
+ * <span data-remote-tooltip="true" tooltip-url="some url" data-author="true">
6
+ * <span></span>
7
+ * </span>
8
+ *
9
+ * This function will check if the HTMLElement where is attached to has a child, and will add a data tooltip attribute
10
+ * to the respective child in order to attach the fetched HTML content fetched under a json key as the content of the
11
+ * HTML tooltip. The DOM structure is expected to be like follows:
12
+ *
13
+ * <span data-remote-tooltip="true" tooltip-url="some url" data-author="true">
14
+ * <span data-tooltip="HTML content from json data field"></span>
15
+ * </span>
16
+ *
17
+ * @param {HTMLElement} node The element holding the initialization data
18
+ * @returns {void}
19
+ */
20
+ export default async function(node) {
21
+ const container = node.firstElementChild;
22
+
23
+ if (container) {
24
+ const response = await fetch(node.dataset.tooltipUrl, {
25
+ headers: {
26
+ "Content-Type": "application/json"
27
+ }
28
+ });
29
+ if (response.ok) {
30
+ const json = await response.json();
31
+
32
+ container.dataset.tooltip = json.data;
33
+ createTooltip(container);
34
+ } else {
35
+ console.error(response.status, response.statusText);
36
+ }
37
+ }
38
+ }
@@ -9,7 +9,7 @@ export default function createToggle(component) {
9
9
  const { toggle } = component.dataset
10
10
 
11
11
  if (!component.id) {
12
- // when component has no id, we enforce to have it one
12
+ // when component has no id, we enforce it to have one
13
13
  component.id = `toggle-${Math.random().toString(36).substring(7)}`
14
14
  }
15
15
 
@@ -63,9 +63,32 @@ export default function(node) {
63
63
  // append to dom hidden, to apply css transitions
64
64
  tooltip.setAttribute("aria-hidden", true)
65
65
 
66
- const append = () => {
67
- // do nothing if the tooltip is already present at the DOM
66
+ // used to detect if the user is on a mobile device by checking the user agent
67
+ const useMobile = (/Mobi|Android/i).test(navigator.userAgent);
68
+
69
+ // used not to collapse tooltip
70
+ let removeTooltip = () => {
71
+ tooltip.setAttribute("aria-hidden", "true");
72
+ }
73
+
74
+ // used to allow clicks outside the tooltip to take place on the page or device
75
+ const OutsideClick = (event) => {
76
+ if (!tooltip.contains(event.target) && event.target !== node) {
77
+ removeTooltip();
78
+ }
79
+ }
80
+
81
+ // function called again to allow clicks outside the tooltip to collapse the tooltip
82
+ removeTooltip = () => {
83
+ tooltip.setAttribute("aria-hidden", "true");
84
+ document.removeEventListener("click", OutsideClick)
85
+ }
86
+
87
+ const toggleTooltip = (event) => {
88
+ event.preventDefault();
89
+ // if the tooltip is visible in the DOM, hide it otherwise display
68
90
  if (tooltip.getAttribute("aria-hidden") === "false") {
91
+ tooltip.setAttribute("aria-hidden", "true");
69
92
  return
70
93
  }
71
94
 
@@ -106,27 +129,24 @@ export default function(node) {
106
129
  tooltip.style.left = `${positionX}px`
107
130
 
108
131
  tooltip.setAttribute("aria-hidden", false)
109
- }
110
-
111
- // in order to revoke the remove event when the mouse is over the trigger/tooltip
112
- let cancelRemove = false
113
132
 
114
- const remove = () => {
115
- cancelRemove = false
116
- // give some sleep time before hiding the element from the DOM
117
- setTimeout(() => !cancelRemove && tooltip.setAttribute("aria-hidden", true), 500);
133
+ // sleep time before hiding the element from the DOM
134
+ setTimeout(() => document.addEventListener("click", OutsideClick))
118
135
  }
119
136
 
120
- // keyboard listener is at root-level
121
- window.addEventListener("keydown", (event) => event.key === "Escape" && remove())
122
-
123
- node.addEventListener("mouseenter", append)
124
- node.addEventListener("mouseleave", remove)
125
- node.addEventListener("focus", append)
126
- node.addEventListener("blur", remove)
127
- tooltip.addEventListener("mouseenter", () => tooltip.setAttribute("aria-hidden", false))
128
- tooltip.addEventListener("mouseleave", remove)
129
-
130
- node.addEventListener("mouseover", () => (cancelRemove = true))
131
- tooltip.addEventListener("mouseover", () => (cancelRemove = true))
137
+ if (useMobile) {
138
+ // mobile use to click and toggle the tooltip
139
+ node.addEventListener("click", toggleTooltip);
140
+ window.addEventListener("keydown", (event) => event.key === "Escape" && removeTooltip())
141
+ } else {
142
+ // desktop use for hover and blur over tooltip
143
+ node.addEventListener("mouseenter", toggleTooltip)
144
+ node.addEventListener("mouseleave", removeTooltip)
145
+ node.addEventListener("focus", toggleTooltip)
146
+ node.addEventListener("blur", removeTooltip)
147
+
148
+ // tooltip hover listeners to prevent hiding when hovered
149
+ tooltip.addEventListener("mouseenter", () => tooltip.setAttribute("aria-hidden", false))
150
+ tooltip.addEventListener("mouseleave", removeTooltip)
151
+ }
132
152
  }
@@ -0,0 +1,5 @@
1
+ .hashtags {
2
+ > label {
3
+ @apply ml-4;
4
+ }
5
+ }
@@ -81,7 +81,7 @@ header {
81
81
  @apply fixed bottom-0 left-0 z-40 bg-white w-full px-4 py-3 flex justify-between text-secondary shadow-[0_-4px_6px_rgba(198,198,198,0.25)];
82
82
 
83
83
  &__trigger {
84
- @apply flex flex-col items-center text-secondary cursor-pointer p-2;
84
+ @apply flex flex-col items-center text-secondary cursor-pointer md:pl-4 md:border-l border-gray-3;
85
85
 
86
86
  svg {
87
87
  @apply w-5 h-5 fill-current;
@@ -140,6 +140,20 @@ header {
140
140
  }
141
141
  }
142
142
 
143
+ &__login {
144
+ @apply w-auto h-full flex flex-row items-center relative text-secondary gap-1 pl-2 pr-2;
145
+
146
+ svg {
147
+ @apply w-8 h-8 fill-current;
148
+ }
149
+
150
+ svg + span {
151
+ @apply text-sm first-letter:uppercase w-auto;
152
+
153
+ flex-shrink: 0;
154
+ }
155
+ }
156
+
143
157
  &__item {
144
158
  @apply w-1/4 flex flex-col items-center relative;
145
159
 
@@ -412,8 +426,12 @@ header {
412
426
  @apply h4 md:h3;
413
427
  }
414
428
 
429
+ nav {
430
+ @apply w-full md:w-1/4;
431
+ }
432
+
415
433
  &__menu {
416
- @apply w-full md:w-1/4 bg-primary px-4 md:px-8 pt-0 pb-3 md:py-3 divide-y divide-gray-3 text-white;
434
+ @apply w-full bg-primary px-4 md:px-8 pt-0 pb-3 md:py-3 divide-y divide-gray-3 text-white;
417
435
 
418
436
  > * {
419
437
  @apply py-3 md:py-3.5;
@@ -45,7 +45,7 @@
45
45
 
46
46
  &__actions {
47
47
  &-main {
48
- @apply w-fit grid grid-cols-2 md:grid-cols-1 mx-auto gap-x-4 gap-y-6 md:gap-4;
48
+ @apply w-fit mx-auto gap-x-4 gap-y-6 md:gap-4;
49
49
 
50
50
  &__dropdown {
51
51
  @apply divide-y divide-gray-3 z-20 w-64;
@@ -29,7 +29,7 @@
29
29
  }
30
30
 
31
31
  &__sm {
32
- @apply w-16;
32
+ @apply w-16 pt-2;
33
33
  }
34
34
 
35
35
  &__sm &__number {
@@ -57,6 +57,7 @@
57
57
  @import "stylesheets/decidim/_toggle_switch.scss";
58
58
  @import "stylesheets/decidim/_hero.scss";
59
59
  @import "stylesheets/decidim/_actions.scss";
60
+ @import "stylesheets/decidim/_hashtags.scss";
60
61
  }
61
62
 
62
63
  // On the other hand, the following styles match with specific routes
@@ -37,7 +37,6 @@
37
37
  }
38
38
 
39
39
  .conference-diploma .diploma__logo {
40
- border: 1px solid #333;
41
40
  padding: 2rem;
42
41
  }
43
42
 
@@ -47,10 +46,12 @@
47
46
  max-height: 100%;
48
47
  max-width: 100%;
49
48
  margin: 0;
49
+ padding-top: 10%;
50
50
  }
51
51
 
52
52
  .conference-diploma .diploma__border {
53
53
  margin: 0;
54
+ margin-top: 15%;
54
55
  -moz-border-image: url("../images/decidim/pattern.png") 20 repeat;
55
56
  -webkit-border-image: url("../images/decidim/pattern.png") 20 repeat;
56
57
  -o-border-image: url("../images/decidim/pattern.png") 20 repeat;
@@ -6,7 +6,7 @@ module Decidim
6
6
  #
7
7
  class AttachmentPresenter < SimpleDelegator
8
8
  def attachment_file_url
9
- attachment.attached_uploader(:file).url(host: attached_to.organization.host)
9
+ attachment.attached_uploader(:file).url
10
10
  end
11
11
 
12
12
  def attachment
@@ -46,6 +46,7 @@ module Decidim
46
46
  # Returns an HTML-safe String.
47
47
  def present_user
48
48
  return h.content_tag(:span, present_user_name, class: "logs__log__author") if user.blank?
49
+ return I18n.t("decidim.profile.deleted") if user.respond_to?(:deleted?) && user.deleted?
49
50
 
50
51
  h.link_to(
51
52
  present_user_name,
@@ -41,7 +41,9 @@ module Decidim
41
41
  end
42
42
 
43
43
  def parse_i18n_changeset(attribute, values, type, diff)
44
- values.last.keys.each do |locale, _value|
44
+ return diff unless values.last.is_a?(Hash)
45
+
46
+ (values.last.keys - ["machine_translations"]).each do |locale, _value|
45
47
  first_value = values.first.try(:[], locale)
46
48
  last_value = values.last.try(:[], locale)
47
49
  next if first_value == last_value
@@ -56,6 +58,27 @@ module Decidim
56
58
  }
57
59
  )
58
60
  end
61
+
62
+ return diff unless values.last.has_key?("machine_translations")
63
+
64
+ values.last.fetch("machine_translations").each_key do |locale, _value|
65
+ next unless I18n.available_locales.include?(locale.to_sym)
66
+
67
+ first_value = values.first.try(:[], "machine_translations").try(:[], locale)
68
+ last_value = values.last.try(:[], "machine_translations").try(:[], locale)
69
+
70
+ attribute_locale = :"#{attribute}_machine_translations_#{locale}"
71
+
72
+ diff.update(
73
+ attribute_locale => {
74
+ type:,
75
+ label: generate_i18n_label(attribute, locale, "decidim.machine_translations.automatic"),
76
+ old_value: first_value,
77
+ new_value: last_value
78
+ }
79
+ )
80
+ end
81
+
59
82
  diff
60
83
  end
61
84
 
@@ -108,7 +131,8 @@ module Decidim
108
131
  end
109
132
 
110
133
  # Returns a String.
111
- def generate_i18n_label(attribute, locale)
134
+ # i18n-tasks-use t("decidim.machine_translations.automatic")
135
+ def generate_i18n_label(attribute, locale, postfix = "")
112
136
  label = I18n.t(attribute, scope: i18n_scope)
113
137
  locale_name = if I18n.available_locales.include?(locale.to_sym)
114
138
  I18n.t("locale.name", locale:)
@@ -116,6 +140,8 @@ module Decidim
116
140
  locale
117
141
  end
118
142
 
143
+ locale_name = I18n.t(postfix, locale_name:, locale:) if postfix.present?
144
+
119
145
  "#{label} (#{locale_name})"
120
146
  end
121
147
 
@@ -36,20 +36,29 @@ module Decidim
36
36
  return unless resource
37
37
  return unless event_class.types.include?(:email)
38
38
 
39
- followers.each do |recipient|
40
- next unless ["all", "followed-only"].include?(recipient.notification_types)
39
+ send_to_followers
40
+ send_to_affected_users
41
+ end
41
42
 
42
- send_email_to(recipient, user_role: :follower)
43
- end
43
+ private
44
44
 
45
+ def send_to_affected_users
45
46
  affected_users.each do |recipient|
46
47
  next unless ["all", "own-only"].include?(recipient.notification_types)
48
+ next if recipient.deleted? || recipient.blocked?
47
49
 
48
50
  send_email_to(recipient, user_role: :affected_user)
49
51
  end
50
52
  end
51
53
 
52
- private
54
+ def send_to_followers
55
+ followers.each do |recipient|
56
+ next unless ["all", "followed-only"].include?(recipient.notification_types)
57
+ next if recipient.deleted? || recipient.blocked?
58
+
59
+ send_email_to(recipient, user_role: :follower)
60
+ end
61
+ end
53
62
 
54
63
  attr_reader :event, :event_class, :resource, :followers, :affected_users, :extra
55
64
 
@@ -15,7 +15,7 @@ module Decidim
15
15
  def data
16
16
  return if @resource.blank? || map_utility.nil?
17
17
 
18
- Rails.cache.fetch(@resource.cache_key) do
18
+ Rails.cache.fetch(@resource.cache_key_with_version) do
19
19
  map_utility.image_data(
20
20
  latitude: @resource.latitude,
21
21
  longitude: @resource.longitude,
@@ -5,7 +5,7 @@
5
5
  <h1 class="title-decorator my-12"><%= t("last_activity", scope: "decidim.last_activities.index") %></h1>
6
6
 
7
7
  <div class="profile__activity pb-16">
8
- <%= cell "decidim/resource_types_filter", resource_types, form_path: last_activities_path, filter_param_key: :with_resource_type, filter: %>
8
+ <%= cell "decidim/resource_types_filter", resource_types, source: :last_activities, filter_param_key: :with_resource_type %>
9
9
  <div id="activities">
10
10
  <%= render partial: "activities" %>
11
11
  </div>
@@ -10,7 +10,7 @@
10
10
  </header>
11
11
 
12
12
  <div class="vertical-tabs">
13
- <nav>
13
+ <nav role="navigation" aria-label="<%= I18n.t("layouts.decidim.navigation.aria_label", title: translated_attribute(page.title)) %>">
14
14
  <button id="dropdown-trigger-pages" data-component="dropdown" data-target="dropdown-menu-pages" data-open-md="true" data-auto-close="true">
15
15
  <span>
16
16
  <%= translated_attribute(page.title) %>
@@ -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) %>
24
+ <%= link_to translated_attribute(sibling.title), page_path(sibling.slug), "aria-current": (page == sibling).to_s %>
25
25
  </li>
26
26
  <% end %>
27
27
  </ul>
@@ -1,7 +1,7 @@
1
1
  <p class="email-greeting"><%= t(".hello", name: @user.name) %></p>
2
2
 
3
3
  <p class="email-instructions">
4
- <%= t(".report_html", url: reported_content_url ) %>
4
+ <%= t(".report_html", url: report_url ) %>
5
5
  </p>
6
6
 
7
7
  <p class="email-button email-button__cta">
@@ -1,7 +1,7 @@
1
1
  <p class="email-greeting"><%= t(".hello", name: @user.name) %></p>
2
2
 
3
3
  <p class="email-instructions">
4
- <%= t(".report_html", url: reported_content_url) %>
4
+ <%= t(".report_html", url: report_url) %>
5
5
  </p>
6
6
 
7
7
  <br>
@@ -15,6 +15,6 @@
15
15
  <% end %>
16
16
  </div>
17
17
 
18
- <h1 class="h3 decorator mb-10 md:my-10">
18
+ <h1 id="search-results-title" class="h3 decorator mb-10 md:my-10">
19
19
  <%= t("decidim.search.results_found_for_term", count: @results_count, term:) %>
20
20
  </h1>
@@ -1,44 +1,46 @@
1
- <div class="filter-container search__filter">
2
- <button id="dropdown-trigger-search" data-component="dropdown" data-target="dropdown-menu-search" data-auto-close="true">
3
- <%= content_tag :span, t("decidim.searches.filters_small_view.filter_by"), class: "#{"is-active" if params.dig(:filter, :with_resource_type) == nil}" %>
4
- <% @blocks.each do |elements| %>
5
- <% elements.each do |type, results| %>
6
- <%= content_tag :span, class: "#{"is-active" if params.dig(:filter, :with_resource_type) == type}" do %>
7
- <span><%= searchable_resource_human_name(type) %></span>
1
+ <nav role="navigation" aria-labelledby="search-results-title">
2
+ <div class="filter-container search__filter">
3
+ <button id="dropdown-trigger-search" data-component="dropdown" data-target="dropdown-menu-search" data-auto-close="true">
4
+ <%= content_tag :span, t("decidim.searches.filters_small_view.filter_by"), class: "#{"is-active" if params.dig(:filter, :with_resource_type) == nil}" %>
5
+ <% @blocks.each do |elements| %>
6
+ <% elements.each do |type, results| %>
7
+ <%= content_tag :span, class: "#{"is-active" if params.dig(:filter, :with_resource_type) == type}" do %>
8
+ <span><%= searchable_resource_human_name(type) %></span>
9
+ <% end %>
8
10
  <% end %>
9
11
  <% end %>
10
- <% end %>
11
- <%= icon "arrow-down-s-line", class: "w-8 h-8 flex-none text-secondary fill-current" %>
12
- <%= icon "arrow-up-s-line", class: "w-8 h-8 flex-none text-secondary fill-current" %>
13
- </button>
14
- <div id="dropdown-menu-search" aria-hidden="true">
15
- <div>
16
- <%= link_to main_search_path, class: "filter#{" is-active" if params.dig(:filter, :with_resource_type) == nil}" do %>
17
- <%= resource_type_icon("all") %>
18
- <span><%= t("all", scope: "decidim.searches.filters.state") %></span>
19
- <span class="label ml-auto"><%= @results_count %></span>
20
- <% end %>
21
- </div>
22
- <% @blocks.each do |elements| %>
12
+ <%= icon "arrow-down-s-line", class: "w-8 h-8 flex-none text-secondary fill-current" %>
13
+ <%= icon "arrow-up-s-line", class: "w-8 h-8 flex-none text-secondary fill-current" %>
14
+ </button>
15
+ <div id="dropdown-menu-search" aria-hidden="true">
23
16
  <div>
24
- <% elements.each do |type, results| %>
25
- <div>
26
- <% if results[:count].positive? %>
27
- <%= link_to search_path_by_resource_type(type), class: "filter#{" is-active" if params.dig(:filter, :with_resource_type) == type}" do %>
28
- <%= resource_type_icon(type) %>
29
- <span><%= searchable_resource_human_name(type) %></span>
30
- <span class="label ml-auto"><%= results[:count] %></span>
31
- <% end %>
32
- <% else %>
33
- <%= content_tag :div, class: "filter#{" is-empty" if results[:count].zero?}" do %>
34
- <%= resource_type_icon(type) %>
35
- <span><%= searchable_resource_human_name(type) %></span>
36
- <span class="label ml-auto"><%= results[:count] %></span>
37
- <% end %>
38
- <% end %>
39
- </div>
17
+ <%= link_to main_search_path, class: "filter#{" is-active" if params.dig(:filter, :with_resource_type) == nil}" do %>
18
+ <%= resource_type_icon("all") %>
19
+ <span><%= t("all", scope: "decidim.searches.filters.state") %></span>
20
+ <span class="label ml-auto"><%= @results_count %></span>
40
21
  <% end %>
41
22
  </div>
42
- <% end %>
23
+ <% @blocks.each do |elements| %>
24
+ <div>
25
+ <% elements.each do |type, results| %>
26
+ <div>
27
+ <% if results[:count].positive? %>
28
+ <%= link_to search_path_by_resource_type(type), class: "filter#{" is-active" if params.dig(:filter, :with_resource_type) == type}" do %>
29
+ <%= resource_type_icon(type) %>
30
+ <span><%= searchable_resource_human_name(type) %></span>
31
+ <span class="label ml-auto"><%= results[:count] %></span>
32
+ <% end %>
33
+ <% else %>
34
+ <%= content_tag :div, class: "filter#{" is-empty" if results[:count].zero?}" do %>
35
+ <%= resource_type_icon(type) %>
36
+ <span><%= searchable_resource_human_name(type) %></span>
37
+ <span class="label ml-auto"><%= results[:count] %></span>
38
+ <% end %>
39
+ <% end %>
40
+ </div>
41
+ <% end %>
42
+ </div>
43
+ <% end %>
44
+ </div>
43
45
  </div>
44
- </div>
46
+ </nav>
@@ -1,9 +1,9 @@
1
- <button class="order-by__button" id="dropdown-trigger-order" data-component="dropdown" data-target="dropdown-menu-order" data-open-md="true">
1
+ <button class="order-by__button <%= b_css_class if defined?(b_css_class) %>" id="dropdown-trigger-order" data-component="dropdown" data-target="dropdown-menu-order" data-open-md="true">
2
2
  <%= icon "arrow-down-s-line" %>
3
3
  <%= icon "arrow-up-s-line" %>
4
4
  <span><%= t("#{i18n_scope}.label") %></span>
5
5
  </button>
6
- <div id="dropdown-menu-order" class="order-by">
6
+ <div id="dropdown-menu-order" class="order-by <%= css_class if defined?(css_class) %>">
7
7
  <% orders.each do |order_name| %>
8
8
  <%= order_link order_name,
9
9
  i18n_scope:,
@@ -2,7 +2,7 @@
2
2
  <div class="menu-bar__breadcrumb-mobile__dropdown-trigger">
3
3
  <span>
4
4
  <% breadcrumb_items.last(2).each_with_index do |item, i| %>
5
- <% item_label = decidim_html_escape(translated_attribute(item[:label])) %>
5
+ <% item_label = decidim_escape_translated(item[:label]).html_safe %>
6
6
  <% if i.positive? %>
7
7
  <span>/</span>
8
8
  <% end %>