decidim-core 0.30.0 → 0.30.2

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 (142) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/activity/show.erb +6 -6
  3. data/app/cells/decidim/address/show.erb +3 -3
  4. data/app/cells/decidim/author/show.erb +1 -1
  5. data/app/cells/decidim/content_blocks/participatory_space_extra_data/extra_data.erb +2 -2
  6. data/app/cells/decidim/content_blocks/participatory_space_main_data/title.erb +11 -2
  7. data/app/cells/decidim/footer_topics/show.erb +2 -2
  8. data/app/cells/decidim/group_admins/show.erb +3 -1
  9. data/app/cells/decidim/group_members/show.erb +6 -2
  10. data/app/cells/decidim/images_panel/show.erb +5 -2
  11. data/app/cells/decidim/participatory_space_dropdown_metadata/metadata.erb +4 -4
  12. data/app/cells/decidim/report_button/flag_modal.erb +11 -9
  13. data/app/cells/decidim/report_user_button/flag_modal.erb +11 -10
  14. data/app/cells/decidim/upload_modal/files.erb +4 -4
  15. data/app/cells/decidim/upload_modal_cell.rb +5 -3
  16. data/app/commands/decidim/amendable/accept.rb +2 -1
  17. data/app/commands/decidim/create_omniauth_registration.rb +1 -1
  18. data/app/commands/decidim/create_report.rb +5 -1
  19. data/app/commands/decidim/invite_user.rb +1 -1
  20. data/app/controllers/concerns/decidim/participatory_space_context.rb +4 -1
  21. data/app/controllers/decidim/amendments_controller.rb +3 -3
  22. data/app/controllers/decidim/reports_controller.rb +6 -1
  23. data/app/forms/decidim/ephemeral_user_form.rb +1 -1
  24. data/app/forms/decidim/omniauth_registration_form.rb +1 -1
  25. data/app/forms/decidim/registration_form.rb +1 -1
  26. data/app/helpers/decidim/amendments_helper.rb +2 -1
  27. data/app/helpers/decidim/filters_helper.rb +25 -0
  28. data/app/helpers/decidim/layout_helper.rb +6 -0
  29. data/app/helpers/decidim/menu_helper.rb +2 -2
  30. data/app/helpers/decidim/paginate_helper.rb +1 -1
  31. data/app/helpers/decidim/tooltip_helper.rb +4 -1
  32. data/app/mailers/decidim/notifications_digest_mailer.rb +7 -1
  33. data/app/mailers/decidim/reported_mailer.rb +17 -2
  34. data/app/packs/images/decidim/default-avatar.svg +1 -1
  35. data/app/packs/src/decidim/callout.js +13 -8
  36. data/app/packs/src/decidim/confirm.js +15 -3
  37. data/app/packs/src/decidim/datepicker/generate_datepicker.js +2 -0
  38. data/app/packs/src/decidim/datepicker/generate_timepicker.js +2 -0
  39. data/app/packs/src/decidim/direct_uploads/upload_field.js +3 -4
  40. data/app/packs/src/decidim/direct_uploads/upload_modal.js +8 -9
  41. data/app/packs/src/decidim/dropdown_menu.js +18 -0
  42. data/app/packs/src/decidim/editor/common/suggestion.js +11 -1
  43. data/app/packs/src/decidim/index.js +1 -0
  44. data/app/packs/src/decidim/input_character_counter.js +1 -1
  45. data/app/packs/stylesheets/decidim/_activity.scss +4 -4
  46. data/app/packs/stylesheets/decidim/_cards.scss +4 -0
  47. data/app/packs/stylesheets/decidim/_filters.scss +1 -1
  48. data/app/packs/stylesheets/decidim/_header.scss +64 -37
  49. data/app/packs/stylesheets/decidim/_layout.scss +2 -2
  50. data/app/packs/stylesheets/decidim/_modal.scss +1 -5
  51. data/app/packs/stylesheets/decidim/_modal_update.scss +5 -1
  52. data/app/packs/stylesheets/decidim/resource_history.scss +14 -4
  53. data/app/permissions/decidim/default_permissions.rb +2 -0
  54. data/app/permissions/decidim/permissions.rb +13 -1
  55. data/app/presenters/decidim/notification_to_mailer_presenter.rb +7 -3
  56. data/app/queries/decidim/last_activity.rb +25 -0
  57. data/app/validators/translated_etiquette_validator.rb +2 -0
  58. data/app/views/decidim/errors/internal_server_error.html.erb +1 -1
  59. data/app/views/decidim/errors/not_found.html.erb +1 -1
  60. data/app/views/decidim/messaging/conversations/_reply_form.html.erb +1 -2
  61. data/app/views/decidim/messaging/conversations/_start.html.erb +1 -1
  62. data/app/views/decidim/newsletters/unsubscribe.html.erb +16 -4
  63. data/app/views/decidim/reported_mailer/hidden_manually.html.erb +25 -0
  64. data/app/views/decidim/searches/_filters.html.erb +48 -13
  65. data/app/views/decidim/shared/_component_announcement.html.erb +1 -1
  66. data/app/views/decidim/shared/_confirm_modal.html.erb +3 -5
  67. data/app/views/decidim/shared/_filters.html.erb +6 -4
  68. data/app/views/decidim/shared/_results_per_page.html.erb +1 -1
  69. data/app/views/kaminari/decidim/_page.html.erb +1 -1
  70. data/app/views/kaminari/decidim/_paginator.html.erb +1 -1
  71. data/app/views/layouts/decidim/_logo.html.erb +2 -2
  72. data/app/views/layouts/decidim/footer/_main.html.erb +1 -1
  73. data/app/views/layouts/decidim/footer/_main_intro.html.erb +1 -1
  74. data/app/views/layouts/decidim/footer/_mini.html.erb +2 -2
  75. data/app/views/layouts/decidim/header/_main.html.erb +2 -2
  76. data/app/views/layouts/decidim/header/_main_links_desktop.html.erb +6 -0
  77. data/app/views/layouts/decidim/header/_main_links_dropdown.html.erb +2 -0
  78. data/app/views/layouts/decidim/header/_main_links_mobile_account.html.erb +1 -1
  79. data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_desktop.html.erb +5 -11
  80. data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile_tablet.html.erb +5 -5
  81. data/app/views/layouts/decidim/header/_mobile_language_choose.html.erb +1 -1
  82. data/config/locales/ar.yml +0 -10
  83. data/config/locales/bg-BG.yml +2 -2
  84. data/config/locales/bg.yml +0 -12
  85. data/config/locales/ca-IT.yml +40 -6
  86. data/config/locales/ca.yml +40 -6
  87. data/config/locales/cs.yml +37 -17
  88. data/config/locales/de.yml +76 -29
  89. data/config/locales/el.yml +0 -11
  90. data/config/locales/en.yml +40 -6
  91. data/config/locales/es-MX.yml +41 -7
  92. data/config/locales/es-PY.yml +41 -7
  93. data/config/locales/es.yml +40 -6
  94. data/config/locales/eu.yml +82 -47
  95. data/config/locales/fi-plain.yml +65 -9
  96. data/config/locales/fi.yml +66 -10
  97. data/config/locales/fr-CA.yml +42 -13
  98. data/config/locales/fr-LU.yml +3 -3
  99. data/config/locales/fr.yml +42 -13
  100. data/config/locales/gl.yml +0 -8
  101. data/config/locales/hu.yml +0 -12
  102. data/config/locales/id-ID.yml +0 -8
  103. data/config/locales/is-IS.yml +0 -6
  104. data/config/locales/it.yml +165 -8
  105. data/config/locales/ja.yml +47 -14
  106. data/config/locales/lb-LU.yml +2 -2
  107. data/config/locales/lb.yml +0 -8
  108. data/config/locales/lt.yml +0 -12
  109. data/config/locales/lv.yml +0 -8
  110. data/config/locales/nl.yml +0 -8
  111. data/config/locales/no.yml +0 -8
  112. data/config/locales/pl.yml +0 -12
  113. data/config/locales/pt-BR.yml +0 -11
  114. data/config/locales/pt.yml +0 -8
  115. data/config/locales/ro-RO.yml +0 -18
  116. data/config/locales/ru.yml +0 -8
  117. data/config/locales/sk-SK.yml +3 -3
  118. data/config/locales/sk.yml +2 -8
  119. data/config/locales/sv.yml +63 -16
  120. data/config/locales/tr-TR.yml +0 -8
  121. data/config/locales/uk.yml +0 -7
  122. data/config/locales/zh-CN.yml +0 -8
  123. data/config/locales/zh-TW.yml +0 -12
  124. data/db/migrate/20171212103803_create_unique_nicknames.rb +1 -1
  125. data/db/migrate/20180221101934_fix_nickname_index.rb +1 -1
  126. data/db/migrate/20180706104107_add_nickname_to_managed_users.rb +1 -1
  127. data/db/migrate/20181001124950_move_users_groups_to_users_table.rb +1 -1
  128. data/db/migrate/20190412131728_fix_user_names.rb +1 -1
  129. data/lib/decidim/assets/tailwind/tailwind.config.js.erb +2 -1
  130. data/lib/decidim/core/test/factories.rb +14 -2
  131. data/lib/decidim/core/test/shared_examples/announcements_examples.rb +4 -0
  132. data/lib/decidim/core/test/shared_examples/comments_examples.rb +7 -5
  133. data/lib/decidim/core/test/shared_examples/map_examples.rb +2 -2
  134. data/lib/decidim/core/version.rb +1 -1
  135. data/lib/decidim/form_builder.rb +14 -0
  136. data/lib/decidim/nicknamizable.rb +6 -9
  137. data/lib/decidim/private_download_helper.rb +3 -3
  138. data/lib/tasks/upgrade/clean.rake +9 -1
  139. data/lib/tasks/upgrade/decidim_fix_nickname_uniqueness.rake +1 -1
  140. data/lib/tasks/upgrade/migrations.rake +2 -0
  141. metadata +9 -7
  142. /data/app/views/decidim/reported_mailer/{hide.html.erb → hidden_automatically.html.erb} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cfb327cabebd03ca7eb5e5327c4c10f0e8f1509552e959206bf19c75032a4152
4
- data.tar.gz: 8062e844f6cfa3e3777d0684e4f9e2e071b68355e9008639d7dbb06803b792ac
3
+ metadata.gz: 42ebd59c0047d75695c9819c2bb0482423b4f5022f31258703b0d0ee476ca793
4
+ data.tar.gz: bb3a77b79383688f58f120b1ce7824282061b503e1a11553f2c883360b8b8fb4
5
5
  SHA512:
6
- metadata.gz: 9c7420aa2cb261ced54ea359fdaa3b4ef515b573ff6ef5eb2665df5f1d41858e4e1f5c08381d07e9fda401671be922dd9585dbcef14ada0cb3af197aea7cd66d
7
- data.tar.gz: beeb21d36c097492f708b4de337e040bef8940e0d872b5e8d0d319c5ec6ad6f416d2f8ca225f8569a8e241d2b1140a17e6b9834ea4321343398ee38a074116c9
6
+ metadata.gz: c12dc0996382e5ad172ae4b70008bcd2df5d1181e9938f0815ef004efe353b210fa78ed7ab8ab7ba8068542c08cb1e431a011e1f6e5401a1aae0c987cd4c330e
7
+ data.tar.gz: 2a641e595999e29a1a68285315d35e5312842c6b997929df48d2fd53bf6cff51ef3279e92ed11dc5c43364238a6486aebc5f07715d49119b611806c103fc2ce7
@@ -1,19 +1,19 @@
1
1
  <div class="activity" data-activity>
2
- <div class="activity__time">
2
+ <p class="activity__time">
3
3
  <%= created_at %>
4
- </div>
4
+ </p>
5
5
  <div class="activity__content">
6
- <span>
6
+ <div>
7
7
  <% if title.present? %>
8
- <span>
8
+ <p>
9
9
  <%= title_icon %>
10
10
  <%= title %>
11
- </span>
11
+ </p>
12
12
  <% end %>
13
13
  <a href="<%= resource_link_path %>">
14
14
  <%= html_truncate decidim_sanitize(resource_link_text, strip_tags: true), length: 80 %>
15
15
  </a>
16
- </span>
16
+ </div>
17
17
  <% unless hide_participatory_space? %>
18
18
  <span>
19
19
  <%= participatory_space_link %>
@@ -4,13 +4,13 @@
4
4
  <%= icon "map-pin-line" %>
5
5
  <div class="address">
6
6
  <% if has_location? %>
7
- <div class="address__location"><%= location %></div>
7
+ <p class="address__location"><%= location %></p>
8
8
  <% end %>
9
9
 
10
- <div class="address__address"><%= address %></div>
10
+ <p class="address__address"><%= address %></p>
11
11
 
12
12
  <% if has_location_hints? %>
13
- <div class="address__hints"><%= location_hints %></div>
13
+ <p class="address__hints"><%= location_hints %></p>
14
14
  <% end %>
15
15
  </div>
16
16
  </div>
@@ -1,6 +1,6 @@
1
1
  <%# If the options hash has the demo key it means we are in the decidim-design engine, so it is not a real-world scenario with actual users %>
2
2
  <% tooltip = options.has_key?(:demo) ? { tooltip: render(:profile_minicard).html_safe } : nil %>
3
- <%= content_tag(:span, class: :author, data: ) do %>
3
+ <%= content_tag(:p, class: :author, data: ) do %>
4
4
  <%= content_tag :span, class: "author__container#{" is-compact" if layout == :compact}", data: tooltip do %>
5
5
  <% if layout == :compact %>
6
6
  <%= render :avatar %>
@@ -2,10 +2,10 @@
2
2
  <div class="participatory-space__metadata-item">
3
3
  <div class="participatory-space__metadata-item-title">
4
4
  <%= icon item[:icon] %>
5
- <span><%= item[:title] %></span>
5
+ <h2><%= item[:title] %></h2>
6
6
  </div>
7
7
  <% if item[:text].present? %>
8
- <%= content_tag :span, item[:text] %>
8
+ <%= content_tag :p, item[:text] %>
9
9
  <% elsif item[:partial].present? %>
10
10
  <%= render item[:partial] %>
11
11
  <% end %>
@@ -11,11 +11,11 @@
11
11
  <div class="content-block__description editor-content" <%= "data-component='accordion'" if should_truncate %>>
12
12
  <% if should_truncate %>
13
13
  <% seed = SecureRandom.hex(4) %>
14
- <div id="panel-view-more-<%= seed %>" aria-hidden="true">
14
+ <div id="panel-view-more-<%= seed %>" aria-hidden="true" inert>
15
15
  <%= description_text %>
16
16
  </div>
17
17
 
18
- <button class="button button__sm button__text-secondary mt-2" data-controls="panel-view-more-<%= seed %>" aria-expanded="false">
18
+ <button class="button button__sm button__text-secondary mt-2" data-controls="panel-view-more-<%= seed %>" aria-expanded="false" onclick="document.querySelector('div[id^=panel-view-more]').toggleAttribute('inert')">
19
19
  <span>
20
20
  <%= t("view_more", scope: "layouts.decidim.announcements") %>
21
21
  </span>
@@ -30,3 +30,12 @@
30
30
  <% end %>
31
31
  </div>
32
32
  <% end %>
33
+ <script>
34
+ const button = document.querySelector('button[data-controls^="panel-view-more"]')
35
+ button.addEventListener('keydown', function(e){
36
+ // press space or enter
37
+ if (e.keyCode === 32 || e.keyCode === 13){
38
+ document.querySelector('div[id^=panel-view-more]').toggleAttribute('inert')
39
+ }
40
+ })
41
+ </script>
@@ -1,5 +1,5 @@
1
- <nav role="navigation" aria-label="Help">
2
- <h2 class="h4 mb-4">Help</h2>
1
+ <nav role="navigation" aria-label="<%= t("layouts.decidim.footer.help") %>">
2
+ <h2 class="h4 mb-4"><%= t("layouts.decidim.footer.help") %></h2>
3
3
  <ul class="space-y-4 break-inside-avoid">
4
4
  <% topics.each do |topic| %>
5
5
  <%= topic_item(topic, class: "font-semibold underline") %>
@@ -21,7 +21,9 @@
21
21
  <%= link_to(
22
22
  decidim.demote_group_manage_user_path(model.nickname, membership),
23
23
  method: :post,
24
- data: { confirm: t("decidim.group_admins.actions.are_you_sure") },
24
+ data: { confirm: t("decidim.group_admins.actions.confirm_remove_from_admin"),
25
+ confirm_title: t("decidim.group_admins.actions.confirm_modal.title_remove"),
26
+ confirm_button: t("decidim.group_admins.actions.confirm_modal.ok_remove") },
25
27
  class: "button button__sm button__transparent-secondary"
26
28
  ) do %>
27
29
  <span><%= t("decidim.group_admins.actions.demote_admin") %></span>
@@ -24,14 +24,18 @@
24
24
  t("decidim.group_members.actions.promote_to_admin"),
25
25
  decidim.promote_group_manage_user_path(model.nickname, membership),
26
26
  method: :post,
27
- data: { confirm: t("decidim.group_members.actions.are_you_sure") },
27
+ data: { confirm: t("decidim.group_members.actions.confirm_promote_to_admin"),
28
+ confirm_title: t("decidim.group_admins.actions.confirm_modal.title_add"),
29
+ confirm_button: t("decidim.group_admins.actions.confirm_modal.ok_add") },
28
30
  class: "button button__sm button__transparent-secondary"
29
31
  ) %>
30
32
 
31
33
  <%= link_to(
32
34
  decidim.group_manage_user_path(model.nickname, membership),
33
35
  method: :delete,
34
- data: { confirm: t("decidim.group_members.actions.are_you_sure") },
36
+ data: { confirm: t("decidim.group_members.actions.confirm_remove_from_group"),
37
+ confirm_title: t("decidim.group_members.actions.confirm_modal.title_remove"),
38
+ confirm_button: t("decidim.group_members.actions.confirm_modal.ok_remove") },
35
39
  class: "button button__sm button__transparent-secondary"
36
40
  ) do %>
37
41
  <span><%= t("decidim.group_members.actions.remove_from_group") %></span>
@@ -1,7 +1,10 @@
1
1
  <div class="grid grid-cols-1 md:grid-cols-4 gap-6">
2
- <% photos.each_with_index do |photo, index| %>
2
+ <% photos.each_with_index do |photo| %>
3
3
  <%= link_to photo.big_url, target: "_blank", rel: "noopener", class: "overflow-hidden rounded aspect-video" do %>
4
- <%= image_tag photo.thumbnail_url, class:"w-full h-full object-cover", alt: strip_tags(translated_attribute(photo.title)) %>
4
+ <%= image_tag photo.thumbnail_url,
5
+ class: "w-full h-full object-cover",
6
+ role: "presentation",
7
+ "data-filename": strip_tags(translated_attribute(photo.title)) %>
5
8
  <% end %>
6
9
  <% end %>
7
10
  </div>
@@ -1,9 +1,9 @@
1
1
  <h4 class="menu-bar__secondary-dropdown__title"><%= title %></h4>
2
- <div class="menu-bar__secondary-dropdown__metadata">
3
- <% if hashtag.present? %>
2
+ <% if hashtag.present? %>
3
+ <div class="menu-bar__secondary-dropdown__metadata">
4
4
  <span>
5
5
  <%= icon "twitter-x-line", class: "text-gray fill-current" %>
6
6
  <%= link_to "##{hashtag}", twitter_hashtag_url(hashtag), target: "_blank", class: "text-secondary underline" %>
7
7
  </span>
8
- <% end %>
9
- </div>
8
+ </div>
9
+ <% end %>
@@ -6,16 +6,18 @@
6
6
  <div>
7
7
  <div class="form__wrapper flag-modal__form">
8
8
  <p id="dialog-desc-<%= modal_id %>" class="flag-modal__form-description"><%= t("decidim.shared.flag_modal.description") %></p>
9
- <p class="flag-modal__form-reason"><%= t("decidim.shared.flag_modal.reason") %>:</p>
10
- <%= f.collection_radio_buttons :reason, [
11
- [:spam, t("decidim.shared.flag_modal.spam")],
12
- [:offensive, t("decidim.shared.flag_modal.offensive")],
13
- [:does_not_belong, t("decidim.shared.flag_modal.does_not_belong", organization_name: current_organization_name)]
14
- ], :first, :last do |builder|
15
- builder.label(for: nil, class: "form__wrapper-checkbox-label") { builder.radio_button(id: nil) + builder.text }
16
- end %>
9
+ <fieldset class="mt-6">
10
+ <legend class="flag-modal__form-reason"><%= t("decidim.shared.flag_modal.reason") %>:</legend>
11
+ <%= f.collection_radio_buttons :reason, [
12
+ [:spam, t("decidim.shared.flag_modal.spam")],
13
+ [:offensive, t("decidim.shared.flag_modal.offensive")],
14
+ [:does_not_belong, t("decidim.shared.flag_modal.does_not_belong", organization_name: current_organization_name)]
15
+ ], :first, :last do |builder|
16
+ builder.label(for: "#{builder.value.to_s}-#{modal_id}", class: "form__wrapper-checkbox-label") { builder.radio_button(id: "#{builder.value.to_s}-#{modal_id}") + builder.text }
17
+ end %>
18
+ </fieldset>
17
19
 
18
- <%= f.text_area :details, rows: 4, label_options: { class: "flag-modal__form-textarea-label", for: nil }, id: nil %>
20
+ <%= f.text_area :details, rows: 4, label_options: { class: "flag-modal__form-textarea-label", for: "additional-comments-#{modal_id}" }, id: "additional-comments-#{modal_id}" %>
19
21
 
20
22
  <% if frontend_administrable? %>
21
23
  <%= f.check_box :hide,
@@ -6,16 +6,17 @@
6
6
  <div>
7
7
  <div class="form__wrapper flag-modal__form">
8
8
  <p class="flag-modal__form-description"><%= t("decidim.shared.flag_user_modal.description") %></p>
9
- <p class="flag-modal__form-reason"><%= t("decidim.shared.flag_modal.reason") %>:</p>
10
- <%= f.collection_radio_buttons :reason, [
11
- [:spam, t("decidim.shared.flag_user_modal.spam")],
12
- [:offensive, t("decidim.shared.flag_user_modal.offensive")],
13
- [:does_not_belong, t("decidim.shared.flag_user_modal.does_not_belong", organization_name: current_organization_name)]
14
- ], :first, :last do |builder|
15
- builder.label(for: nil, class: "form__wrapper-checkbox-label") { builder.radio_button(id: nil) + builder.text }
16
- end %>
17
-
18
- <%= f.text_area :details, rows: 4, label_options: { class: "flag-modal__form-textarea-label", for: nil }, id: nil %>
9
+ <fieldset class="mt-6">
10
+ <legend class="flag-modal__form-reason"><%= t("decidim.shared.flag_modal.reason") %>:</legend>
11
+ <%= f.collection_radio_buttons :reason, [
12
+ [:spam, t("decidim.shared.flag_user_modal.spam")],
13
+ [:offensive, t("decidim.shared.flag_user_modal.offensive")],
14
+ [:does_not_belong, t("decidim.shared.flag_user_modal.does_not_belong", organization_name: current_organization_name)]
15
+ ], :first, :last do |builder|
16
+ builder.label(for: "#{builder.value.to_s}-#{modal_id}", class: "form__wrapper-checkbox-label") { builder.radio_button(id: "#{builder.value.to_s}-#{modal_id}") + builder.text }
17
+ end %>
18
+ </fieldset>
19
+ <%= f.text_area :details, rows: 4, label_options: { class: "flag-modal__form-textarea-label", for: "additional-comments-#{modal_id}" }, id: "additional-comments-#{modal_id}" %>
19
20
 
20
21
  <% if frontend_administrable? %>
21
22
  <%= f.check_box :block,
@@ -25,19 +25,19 @@
25
25
 
26
26
  <div class="attachment-details" data-attachment-id="<%= attachment.id %>" data-title="<%= title_for(attachment) %>" data-filename="<%= file_name_for(attachment) %>" data-state="uploaded">
27
27
  <% if file_attachment_path(attachment) && blob(attachment).image? %>
28
- <div><%= image_tag(file_attachment_path(attachment), alt: title_for(attachment) || file_name_for(attachment)) %></div>
28
+ <div><%= image_tag(file_attachment_path(attachment), alt: "") %></div>
29
29
  <% elsif uploader_default_image_path(attribute).present? %>
30
30
  <div><%= image_tag uploader_default_image_path(attribute) %></div>
31
31
  <% end %>
32
32
 
33
33
  <% if has_title? %>
34
- <span><%= title_for(attachment) %> (<%= truncated_file_name_for(attachment) %>)</span>
34
+ <span><%= title_for(attachment) %></span>
35
35
  <%= form.hidden_field attribute, multiple: true, value: attachment.id, id: attachment.id %>
36
36
  <% else %>
37
37
  <% if blob(attachment).image? %>
38
- <span><%= truncated_file_name_for(attachment, 15) %></span>
38
+ <span><%= title_for(attachment) %></span>
39
39
  <% else %>
40
- <%= link_to truncated_file_name_for(attachment), file_attachment_path(attachment) %>
40
+ <%= link_to title_for(attachment), file_attachment_path(attachment), class: "w-full break-all mb-2" %>
41
41
  <% end %>
42
42
  <% end %>
43
43
  </div>
@@ -132,9 +132,11 @@ module Decidim
132
132
  end
133
133
 
134
134
  def title_for(attachment)
135
- return unless has_title?
136
-
137
- decidim_html_escape(decidim_sanitize(translated_attribute(attachment.title)))
135
+ if has_title?
136
+ decidim_html_escape(decidim_sanitize(translated_attribute(attachment.title)))
137
+ else
138
+ decidim_html_escape(decidim_sanitize(determine_filename(attachment)))
139
+ end
138
140
  end
139
141
 
140
142
  def truncated_file_name_for(attachment, max_length = 31)
@@ -62,7 +62,8 @@ module Decidim
62
62
  @amendable.save!
63
63
  @amendable
64
64
  end
65
- @amendable.add_coauthor(@amender, user_group: @user_group)
65
+
66
+ @amendable.add_coauthor(@amender, user_group: @user_group) if @amendable.is_a?(Decidim::Coauthorable)
66
67
  end
67
68
 
68
69
  def notify_emendation_state_change!
@@ -69,7 +69,7 @@ module Decidim
69
69
  @user.email = (verified_email || form.email)
70
70
  @user.name = form.name.gsub(REGEXP_SANITIZER, "")
71
71
  @user.nickname = form.normalized_nickname
72
- @user.newsletter_notifications_at = nil
72
+ @user.newsletter_notifications_at = form.newsletter_at
73
73
  @user.password = SecureRandom.hex
74
74
  attach_avatar(form.avatar_url) if form.avatar_url.present?
75
75
  @user.tos_agreement = form.tos_agreement
@@ -76,7 +76,11 @@ module Decidim
76
76
  participatory_space_moderators.each do |moderator|
77
77
  next unless moderator.email_on_moderations
78
78
 
79
- ReportedMailer.hide(moderator, @report).deliver_later
79
+ if hidden_by_admin?
80
+ ReportedMailer.hidden_manually(moderator, @report, current_user).deliver_later
81
+ else
82
+ ReportedMailer.hidden_automatically(moderator, @report).deliver_later
83
+ end
80
84
  end
81
85
  end
82
86
  end
@@ -41,7 +41,7 @@ module Decidim
41
41
  @user = Decidim::User.new(
42
42
  name: form.name,
43
43
  email: form.email.downcase,
44
- nickname: UserBaseEntity.nicknamize(form.name, organization: form.organization),
44
+ nickname: UserBaseEntity.nicknamize(form.name, form.organization.id),
45
45
  organization: form.organization,
46
46
  admin: form.role == "admin",
47
47
  roles: form.role == "admin" ? [] : [form.role].compact
@@ -9,6 +9,7 @@ module Decidim
9
9
 
10
10
  included do
11
11
  include Decidim::NeedsOrganization
12
+ include Decidim::UserRoleChecker
12
13
 
13
14
  helper ParticipatorySpaceHelpers, IconHelper, ContextualHelpHelper
14
15
  helper_method :current_participatory_space
@@ -81,8 +82,10 @@ module Decidim
81
82
  return true unless current_participatory_space.try(:private_space?) &&
82
83
  !current_participatory_space.try(:is_transparent?)
83
84
  return false unless current_user
85
+ return true if current_user.admin?
86
+ return true if user_has_any_role?(current_user, current_participatory_space, broad_check: true)
84
87
 
85
- current_user.admin || current_participatory_space.users.include?(current_user)
88
+ current_participatory_space.users.include?(current_user)
86
89
  end
87
90
 
88
91
  def help_section
@@ -107,7 +107,7 @@ module Decidim
107
107
  end
108
108
 
109
109
  def reject
110
- enforce_permission_to :reject, :amendment, current_component: amendable.component
110
+ enforce_permission_to :reject, :amendment, amendable:, current_component: amendable.component
111
111
 
112
112
  @form = form(Decidim::Amendable::RejectForm).from_model(amendment)
113
113
 
@@ -143,13 +143,13 @@ module Decidim
143
143
  end
144
144
 
145
145
  def review
146
- enforce_permission_to :accept, :amendment, current_component: amendable.component
146
+ enforce_permission_to :accept, :amendment, amendable:, current_component: amendable.component
147
147
 
148
148
  @form = form(Decidim::Amendable::ReviewForm).from_params(params)
149
149
  end
150
150
 
151
151
  def accept
152
- enforce_permission_to :accept, :amendment, current_component: amendable.component
152
+ enforce_permission_to :accept, :amendment, amendable:, current_component: amendable.component
153
153
 
154
154
  @form = form(Decidim::Amendable::ReviewForm).from_params(params)
155
155
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Decidim
4
4
  # Exposes the report resource so users can report a reportable.
5
+ # Unless the reportable is marked as hideable, the resource notice will change accordingly.
5
6
  class ReportsController < Decidim::ApplicationController
6
7
  include FormFactory
7
8
  include NeedsPermission
@@ -15,7 +16,11 @@ module Decidim
15
16
 
16
17
  CreateReport.call(@form, reportable) do
17
18
  on(:ok) do
18
- flash[:notice] = I18n.t("decidim.reports.create.success")
19
+ flash[:notice] = if hideable?
20
+ I18n.t("decidim.reports.hide.success")
21
+ else
22
+ I18n.t("decidim.reports.create.success")
23
+ end
19
24
  redirect_to reportable.reload.reported_content_url
20
25
  end
21
26
 
@@ -16,7 +16,7 @@ module Decidim
16
16
  end
17
17
 
18
18
  def nickname
19
- super || User.nicknamize(name)
19
+ super || User.nicknamize("#{name}_#{SecureRandom.alphanumeric(8)}", organization.id)
20
20
  end
21
21
  end
22
22
  end
@@ -26,7 +26,7 @@ module Decidim
26
26
  end
27
27
 
28
28
  def normalized_nickname
29
- UserBaseEntity.nicknamize(nickname || name, organization: current_organization)
29
+ UserBaseEntity.nicknamize(nickname || name, current_organization.id)
30
30
  end
31
31
 
32
32
  def newsletter_at
@@ -37,7 +37,7 @@ module Decidim
37
37
  end
38
38
 
39
39
  def generate_nickname(name, organization)
40
- Decidim::UserBaseEntity.nicknamize(name, organization:)
40
+ Decidim::UserBaseEntity.nicknamize(name, organization.id)
41
41
  end
42
42
 
43
43
  def valid_users
@@ -61,8 +61,9 @@ module Decidim
61
61
  # Checks if the user can accept and reject the emendation
62
62
  def allowed_to_accept_and_reject?(emendation)
63
63
  return unless emendation.amendment.evaluating?
64
+ return current_user.admin? if emendation.amendable.respond_to?(:official?) && emendation.amendable.official?
64
65
 
65
- emendation.amendable.created_by?(current_user) || current_user.admin?
66
+ emendation.amendable.created_by?(current_user)
66
67
  end
67
68
 
68
69
  # Checks if the user can promote the emendation
@@ -32,6 +32,31 @@ module Decidim
32
32
  end
33
33
  end
34
34
 
35
+ def filter_search_label(label, id)
36
+ I18n.t("decidim.searches.filters.resource", label:, collection: filter_for_resource(id))
37
+ end
38
+
39
+ def filter_for_resource(skip_to_id)
40
+ case skip_to_id
41
+ when "proposals"
42
+ I18n.t("decidim/proposals/proposal.other", scope: "activerecord.models")
43
+ when "meetings"
44
+ I18n.t("decidim/meetings/meeting.other", scope: "activerecord.models")
45
+ when "debates"
46
+ I18n.t("decidim/debates/debate.other", scope: "activerecord.models")
47
+ when "sortitions"
48
+ I18n.t("decidim/sortitions/sortition.other", scope: "activerecord.models")
49
+ when "surveys"
50
+ I18n.t("decidim/surveys/survey.other", scope: "activerecord.models")
51
+ when "projects"
52
+ I18n.t("decidim/budgets/project.other", scope: "activerecord.models")
53
+ when "initiatives"
54
+ I18n.t("decidim/initiative.other", scope: "activerecord.models")
55
+ else
56
+ ""
57
+ end
58
+ end
59
+
35
60
  private
36
61
 
37
62
  # Creates a unique namespace for a filter form to prevent duplicate IDs in
@@ -60,6 +60,12 @@ module Decidim
60
60
  html_properties = options.with_indifferent_access.transform_keys(&:dasherize).slice("width", "height", "aria-label", "role", "aria-hidden", "class", "style")
61
61
  html_properties = default_html_properties.merge(html_properties)
62
62
 
63
+ if name == "wechat-line"
64
+ html_properties = html_properties.merge({ "aria-label" => I18n.t("decidim.author.comments.other") }).except("aria-hidden")
65
+ elsif name == "heart-line"
66
+ html_properties = html_properties.merge({ "aria-label" => I18n.t("decidim.author.endorsements.other") }).except("aria-hidden")
67
+ end
68
+
63
69
  href = Decidim.cors_enabled ? "" : asset_pack_path("media/images/remixicon.symbol.svg")
64
70
 
65
71
  content_tag :svg, html_properties do
@@ -39,7 +39,7 @@ module Decidim
39
39
  @breadcrumb_root_menu ||= ::Decidim::BreadcrumbRootMenuPresenter.new(
40
40
  :menu,
41
41
  self,
42
- container_options: { class: "menu-bar__main-dropdown__menu" }
42
+ container_options: { class: "menu-bar__dropdown-menu" }
43
43
  )
44
44
  end
45
45
 
@@ -47,7 +47,7 @@ module Decidim
47
47
  @mobile_breadcrumb_root_menu ||= ::Decidim::BreadcrumbRootMenuPresenter.new(
48
48
  :mobile_menu,
49
49
  self,
50
- container_options: { class: "menu-bar__main-dropdown__menu" }
50
+ container_options: { class: "menu-bar__main-dropdown__top-menu" }
51
51
  )
52
52
  end
53
53
 
@@ -13,7 +13,7 @@ module Decidim
13
13
 
14
14
  per_page = (params[:per_page] || paginate_params[:per_page] || Decidim::Paginable::OPTIONS.first).to_i
15
15
 
16
- content_tag :div, class: "flex flex-col-reverse md:flex-row items-center justify-between gap-1 py-8 md:py-16", data: { pagination: "" } do
16
+ content_tag :div, class: "flex flex-col-reverse md:flex-row items-center justify-between gap-1 py-8 md:py-16 md:flex-wrap", data: { pagination: "" } do
17
17
  template = ""
18
18
  template += render(partial: "decidim/shared/results_per_page", locals: { per_page: }, formats: [:html]) if collection.total_pages.positive?
19
19
  template += paginate collection, window: 2, outer_window: 1, theme: "decidim", params: paginate_params
@@ -5,7 +5,10 @@ module Decidim
5
5
  # on the layout.
6
6
  module TooltipHelper
7
7
  def with_tooltip(title, opts = {}, &)
8
- content_tag(:span, title:, data: { tooltip: content_tag(:div, title, id: opts[:id], class: opts[:class] || "bottom", role: "tooltip", "aria-hidden": "true") }) do
8
+ content_tag(:p,
9
+ title:,
10
+ class: "inline-block",
11
+ data: { tooltip: content_tag(:p, title, id: opts[:id], class: opts[:class] || "bottom", role: "tooltip", "aria-hidden": "true") }) do
9
12
  capture(&).html_safe
10
13
  end
11
14
  end
@@ -14,7 +14,13 @@ module Decidim
14
14
  @organization = user.organization
15
15
  @notifications_digest = Decidim::NotificationsDigestPresenter.new(user)
16
16
  @display_see_more_message = notifications.size > SIZE_LIMIT
17
- @notifications = notifications[0...SIZE_LIMIT].map { |notification| Decidim::NotificationToMailerPresenter.new(notification) }
17
+ # Note that this could be improved by adding a "type" column to the notifications table
18
+ # This fix can generate lists of notifications that are below the SIZE_LIMIT
19
+ @notifications = notifications[0...SIZE_LIMIT].filter_map do |notification|
20
+ next unless notification.event_class_instance.respond_to?(:email_intro)
21
+
22
+ Decidim::NotificationToMailerPresenter.new(notification)
23
+ end
18
24
 
19
25
  mail(to: user.email, subject: @notifications_digest.subject)
20
26
  end
@@ -21,14 +21,29 @@ module Decidim
21
21
  end
22
22
  end
23
23
 
24
- def hide(user, report)
24
+ # This is used when a user with special rights (like an administrator, a space administrator or a moderator) hides a resource
25
+ def hidden_manually(user, report, current_user)
25
26
  with_user(user) do
26
27
  @report = report
27
28
  @participatory_space = @report.moderation.participatory_space
28
29
  @reportable = @report.moderation.reportable
29
30
  @organization = user.organization
30
31
  @user = user
31
- subject = I18n.t("hide.subject", scope: "decidim.reported_mailer")
32
+ @moderator = current_user
33
+ subject = I18n.t("hidden_manually.subject", scope: "decidim.reported_mailer", moderator: @moderator.name)
34
+ mail(to: user.email, subject:)
35
+ end
36
+ end
37
+
38
+ # This is meant to be used when a resource is hidden by an algorithm, such as the `decidim-ai` module, or the `Decidim.max_reports_before_hiding` feature.
39
+ def hidden_automatically(user, report)
40
+ with_user(user) do
41
+ @report = report
42
+ @participatory_space = @report.moderation.participatory_space
43
+ @reportable = @report.moderation.reportable
44
+ @organization = user.organization
45
+ @user = user
46
+ subject = I18n.t("hidden_automatically.subject", scope: "decidim.reported_mailer")
32
47
  mail(to: user.email, subject:)
33
48
  end
34
49
  end
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" width="200" height="200" x="0" y="0" enable-background="new 0 0 200 200" version="1.1" viewBox="0 0 200 200" xml:space="preserve"><g><path fill="#C5C5C5" d="M200-0.5H0v200h26.099c2.885-35.293,24.07-64.381,52.419-74.319C64.372,117.596,54.75,102.674,54.75,85.5 c0-24.853,20.146-45,45-45c24.853,0,45,20.147,45,45c0,17.095-9.533,31.963-23.572,39.58c28.5,9.837,49.828,39.002,52.724,74.42 H200V-0.5z"/><path fill="#FFF" d="M121.178,125.08c14.039-7.617,23.572-22.485,23.572-39.58c0-24.853-20.147-45-45-45 c-24.854,0-45,20.147-45,45c0,17.174,9.622,32.096,23.768,39.681c-28.349,9.938-49.534,39.026-52.419,74.319h147.803 C171.006,164.082,149.678,134.917,121.178,125.08z"/></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" width="200" height="200" x="0" y="0" enable-background="new 0 0 200 200" version="1.1" viewBox="0 0 200 200" xml:space="preserve"><g><path fill="#908e8e" d="M200-0.5H0v200h26.099c2.885-35.293,24.07-64.381,52.419-74.319C64.372,117.596,54.75,102.674,54.75,85.5 c0-24.853,20.146-45,45-45c24.853,0,45,20.147,45,45c0,17.095-9.533,31.963-23.572,39.58c28.5,9.837,49.828,39.002,52.724,74.42 H200V-0.5z"/><path fill="#FFF" d="M121.178,125.08c14.039-7.617,23.572-22.485,23.572-39.58c0-24.853-20.147-45-45-45 c-24.854,0-45,20.147-45,45c0,17.174,9.622,32.096,23.768,39.681c-28.349,9.938-49.534,39.026-52.419,74.319h147.803 C171.006,164.082,149.678,134.917,121.178,125.08z"/></g></svg>
@@ -4,13 +4,18 @@
4
4
  * reload without this.
5
5
  */
6
6
 
7
- $(() => {
8
- const $callout = $('.callout[role="alert"]:first');
9
- if ($callout.length > 0) {
10
- setTimeout(() => {
11
- // The content insertion is to try to hint some of the screen readers
12
- // that the alert content has changed and needs to be announced.
13
- $callout.attr("tabindex", "0").focus().html(`${$callout.html()}&nbsp;`);
14
- }, 500);
7
+ document.addEventListener("turbo:load", () => {
8
+ const callout = document.querySelector(".flash[role='alert']");
9
+ if (!callout) {
10
+ return;
15
11
  }
12
+
13
+ setTimeout(() => {
14
+ callout.setAttribute("tabindex", "0");
15
+ callout.focus();
16
+
17
+ // The content insertion is to try to hint some of the screen readers
18
+ // that the alert content has changed and needs to be announced.
19
+ callout.innerHTML += "&nbsp;";
20
+ }, 500);
16
21
  });