decidim-core 0.32.1 → 0.32.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 (149) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/content_blocks/participatory_space_main_data/title.erb +1 -14
  3. data/app/cells/decidim/following_cell.rb +1 -1
  4. data/app/cells/decidim/member/show.erb +1 -1
  5. data/app/cells/decidim/nav_links/show.erb +3 -1
  6. data/app/cells/decidim/share_text_widget/modal.erb +1 -0
  7. data/app/cells/decidim/share_widget/modal.erb +1 -0
  8. data/app/cells/decidim/share_widget/qr_code_modal.erb +2 -4
  9. data/app/commands/decidim/create_omniauth_registration.rb +17 -2
  10. data/app/controllers/concerns/decidim/devise_authentication_methods.rb +4 -0
  11. data/app/controllers/concerns/decidim/devise_controllers.rb +2 -0
  12. data/app/controllers/concerns/decidim/disable_redirection_to_external_host.rb +2 -0
  13. data/app/controllers/concerns/decidim/filter_resource.rb +2 -0
  14. data/app/controllers/concerns/decidim/impersonate_users.rb +2 -2
  15. data/app/controllers/concerns/decidim/locale_switcher.rb +12 -10
  16. data/app/controllers/concerns/decidim/needs_permission.rb +22 -10
  17. data/app/controllers/concerns/decidim/onboarding_action_methods.rb +2 -0
  18. data/app/controllers/concerns/decidim/paginable.rb +7 -3
  19. data/app/controllers/concerns/decidim/payload_info.rb +2 -0
  20. data/app/controllers/concerns/decidim/resource_versions_concern.rb +14 -0
  21. data/app/controllers/decidim/application_controller.rb +0 -6
  22. data/app/controllers/decidim/authorization_modals_controller.rb +2 -0
  23. data/app/controllers/decidim/components/base_controller.rb +2 -0
  24. data/app/controllers/decidim/devise/passwords_controller.rb +8 -0
  25. data/app/controllers/decidim/favicon_controller.rb +9 -0
  26. data/app/controllers/decidim/free_resource_authorization_modals_controller.rb +2 -0
  27. data/app/controllers/decidim/gamification/badges_controller.rb +2 -0
  28. data/app/controllers/decidim/homepage_controller.rb +4 -1
  29. data/app/controllers/decidim/likes_controller.rb +1 -1
  30. data/app/controllers/decidim/links_controller.rb +2 -0
  31. data/app/controllers/decidim/manifests_controller.rb +2 -0
  32. data/app/controllers/decidim/messaging/conversations_controller.rb +10 -4
  33. data/app/controllers/decidim/newsletters_controller.rb +4 -0
  34. data/app/controllers/decidim/notifications_subscriptions_controller.rb +4 -0
  35. data/app/controllers/decidim/offline_controller.rb +5 -1
  36. data/app/controllers/decidim/open_data_controller.rb +5 -1
  37. data/app/controllers/decidim/pages_controller.rb +31 -3
  38. data/app/controllers/decidim/private_downloads_controller.rb +2 -0
  39. data/app/controllers/decidim/profiles_controller.rb +19 -1
  40. data/app/controllers/decidim/qr_controller.rb +3 -1
  41. data/app/controllers/decidim/resource_autocomplete_controller.rb +2 -0
  42. data/app/controllers/decidim/searches_controller.rb +2 -0
  43. data/app/controllers/decidim/short_links_controller.rb +4 -0
  44. data/app/controllers/decidim/static_map_controller.rb +2 -0
  45. data/app/controllers/decidim/timeouts_controller.rb +4 -0
  46. data/app/controllers/decidim/tos_controller.rb +2 -0
  47. data/app/controllers/decidim/upload_validations_controller.rb +4 -2
  48. data/app/controllers/decidim/user_activities_controller.rb +3 -0
  49. data/app/forms/decidim/upload_validation_form.rb +16 -10
  50. data/app/helpers/concerns/decidim/user_role_checker.rb +35 -10
  51. data/app/helpers/decidim/decidim_form_helper.rb +1 -1
  52. data/app/helpers/decidim/sanitize_helper.rb +11 -1
  53. data/app/jobs/decidim/application_job.rb +4 -0
  54. data/app/models/decidim/authorization.rb +24 -0
  55. data/app/models/decidim/oauth_application.rb +1 -0
  56. data/app/models/decidim/user.rb +1 -0
  57. data/app/models/decidim/user_base_entity.rb +1 -1
  58. data/app/packs/src/decidim/callout.js +10 -0
  59. data/app/packs/src/decidim/callout.test.js +32 -0
  60. data/app/packs/src/decidim/controllers/accordion/accordion.test.js +64 -0
  61. data/app/packs/src/decidim/controllers/accordion/controller.js +43 -0
  62. data/app/packs/src/decidim/controllers/autofocus/controller.js +30 -0
  63. data/app/packs/src/decidim/controllers/language_change/controller.js +21 -8
  64. data/app/packs/src/decidim/controllers/language_change/language_change.test.js +0 -1
  65. data/app/packs/src/decidim/controllers/mention/controller.js +32 -3
  66. data/app/packs/src/decidim/controllers/mention/input_mentions.test.js +8 -5
  67. data/app/packs/src/decidim/controllers/multiple_mentions/input_multiple_mentions.test.js +1 -1
  68. data/app/packs/src/decidim/datepicker/datepicker_functions.js +41 -25
  69. data/app/packs/src/decidim/datepicker/generate_datepicker.js +4 -4
  70. data/app/packs/src/decidim/datepicker/test/datepicker_functions_adjust_picker_position.test.js +64 -0
  71. data/app/packs/src/decidim/datepicker/test/time.test.js +39 -24
  72. data/app/packs/src/decidim/editor/common/suggestion.js +32 -22
  73. data/app/packs/src/decidim/editor/extensions/mention/index.js +14 -3
  74. data/app/packs/src/decidim/editor/index.js +4 -0
  75. data/app/packs/src/decidim/editor/test/extensions/mention.test.js +32 -9
  76. data/app/packs/src/decidim/refactor/implementation/autofocus.js +22 -0
  77. data/app/packs/src/decidim/refactor/implementation/autofocus.test.js +171 -0
  78. data/app/packs/src/decidim/utilities/dom.js +2 -2
  79. data/app/packs/stylesheets/decidim/_content_blocks.scss +4 -10
  80. data/app/packs/stylesheets/decidim/_conversations.scss +0 -8
  81. data/app/packs/stylesheets/decidim/_modal.scss +16 -8
  82. data/app/packs/stylesheets/decidim/_modal_share.scss +0 -22
  83. data/app/packs/stylesheets/decidim/_participatory_spaces.scss +11 -1
  84. data/app/packs/stylesheets/decidim/_rich_text.scss +12 -9
  85. data/app/packs/stylesheets/decidim/_typography.scss +5 -2
  86. data/app/packs/stylesheets/decidim/application.scss +1 -0
  87. data/app/packs/stylesheets/decidim/legacy/email.scss +0 -5
  88. data/app/permissions/decidim/permissions.rb +20 -0
  89. data/app/presenters/decidim/admin_log/component_presenter.rb +1 -1
  90. data/app/presenters/decidim/log/base_presenter.rb +10 -1
  91. data/app/presenters/decidim/log/user_presenter.rb +2 -2
  92. data/app/presenters/decidim/menu_item_presenter.rb +1 -5
  93. data/app/presenters/decidim/resource_presenter.rb +11 -0
  94. data/app/resolvers/decidim/meta_image_url_resolver.rb +7 -1
  95. data/app/serializers/decidim/exporters/open_data_blocked_user_serializer.rb +11 -2
  96. data/app/serializers/decidim/exporters/open_data_moderation_serializer.rb +25 -1
  97. data/app/services/decidim/svg_content_validator.rb +554 -0
  98. data/app/uploaders/decidim/application_uploader.rb +2 -2
  99. data/app/validators/uploader_image_content_validator.rb +276 -0
  100. data/app/views/decidim/application/_radio_accordion.html.erb +1 -5
  101. data/app/views/decidim/messaging/conversations/_add_conversation_users.html.erb +1 -1
  102. data/app/views/decidim/messaging/conversations/create.js.erb +1 -3
  103. data/app/views/decidim/shared/_login_modal.html.erb +12 -14
  104. data/app/views/layouts/decidim/_mailer_logo.html.erb +1 -1
  105. data/app/views/layouts/decidim/header/_menu_breadcrumb_desktop.html.erb +3 -2
  106. data/config/initializers/rack_attack.rb +10 -0
  107. data/config/locales/bg.yml +0 -1
  108. data/config/locales/ca-IT.yml +3 -1
  109. data/config/locales/ca.yml +10 -6
  110. data/config/locales/cs.yml +15 -1
  111. data/config/locales/de.yml +99 -3
  112. data/config/locales/en.yml +5 -1
  113. data/config/locales/es-MX.yml +5 -1
  114. data/config/locales/es-PY.yml +5 -1
  115. data/config/locales/es.yml +9 -5
  116. data/config/locales/eu.yml +161 -160
  117. data/config/locales/fi-plain.yml +3 -1
  118. data/config/locales/fi.yml +3 -1
  119. data/config/locales/fr-CA.yml +5 -1
  120. data/config/locales/fr.yml +5 -1
  121. data/config/locales/gl.yml +1485 -33
  122. data/config/locales/hu.yml +0 -1
  123. data/config/locales/ja.yml +3 -1
  124. data/config/locales/pl.yml +0 -1
  125. data/config/locales/pt-BR.yml +0 -1
  126. data/config/locales/ro-RO.yml +0 -1
  127. data/config/locales/sk.yml +2 -1
  128. data/config/locales/sv.yml +68 -12
  129. data/config/locales/tr-TR.yml +0 -2
  130. data/config/routes.rb +11 -2
  131. data/db/migrate/20260909000000_add_failed_attempts_and_locked_at_to_decidim_authorizations.rb +8 -0
  132. data/decidim-core.gemspec +1 -1
  133. data/lib/decidim/api/functions/user_entity_list.rb +1 -0
  134. data/lib/decidim/api/types/user_moderation_type.rb +2 -2
  135. data/lib/decidim/content_parsers/user_parser.rb +1 -1
  136. data/lib/decidim/content_parsers.rb +0 -1
  137. data/lib/decidim/content_renderers/mention_resource_renderer.rb +18 -4
  138. data/lib/decidim/content_renderers/user_renderer.rb +15 -4
  139. data/lib/decidim/core/test/shared_examples/participatory_space_members_page_examples.rb +77 -0
  140. data/lib/decidim/core/test/shared_examples/participatory_space_members_shared_examples.rb +58 -0
  141. data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +23 -1
  142. data/lib/decidim/core/version.rb +1 -1
  143. data/lib/decidim/core.rb +9 -0
  144. data/lib/decidim/form_builder.rb +9 -1
  145. data/lib/decidim/has_upload_validations.rb +1 -0
  146. data/lib/decidim/legacy_form_builder.rb +4 -0
  147. metadata +12 -7
  148. data/lib/decidim/content_parsers/inline_images_parser.rb +0 -68
  149. data/lib/tasks/upgrade/decidim_active_storage_migration_tasks.rake +0 -79
@@ -1379,7 +1379,6 @@ hu:
1379
1379
  layouts:
1380
1380
  decidim:
1381
1381
  announcements:
1382
- view_less: Kevesebb mutatása
1383
1382
  view_more: További információk
1384
1383
  data_consent:
1385
1384
  details:
@@ -239,6 +239,7 @@ ja:
239
239
  create: "%{user_name} は、 %{resource_name} コンポーネントを %{space_name} スペースに追加しました"
240
240
  delete: "%{user_name} が %{resource_name} スペースから %{space_name} コンポーネントを削除しました"
241
241
  export_component: "%{user_name} は%{space_name} の %{resource_name} %{component_name} を %{format_name} としてエクスポートしました"
242
+ menu_hidden: "%{user_name} がコンポーネント %{resource_name} をスペース %{space_name} のメニューから非表示にしました"
242
243
  publish: "%{user_name} が %{resource_name} スペースで %{space_name} コンポーネントを公開しました"
243
244
  restore: "%{user_name} がコンポーネント %{resource_name} をスコープ %{space_name} に復元しました。"
244
245
  soft_delete: "%{user_name} が %{space_name} スペースの %{resource_name} コンポーネントをゴミ箱に移動しました"
@@ -1692,6 +1693,8 @@ ja:
1692
1693
  login_modal:
1693
1694
  please_log_in: ログインしてください
1694
1695
  sign_up: アカウントを作成
1696
+ mentions:
1697
+ search_prompt: 参加者を検索するには入力してください
1695
1698
  mentions_modal:
1696
1699
  remove_recipient: 受信者 %{name} を削除
1697
1700
  progress: 進捗状況
@@ -2071,7 +2074,6 @@ ja:
2071
2074
  layouts:
2072
2075
  decidim:
2073
2076
  announcements:
2074
- view_less: 一部のみ表示
2075
2077
  view_more: 詳しい情報
2076
2078
  data_consent:
2077
2079
  details:
@@ -1514,7 +1514,6 @@ pl:
1514
1514
  layouts:
1515
1515
  decidim:
1516
1516
  announcements:
1517
- view_less: Pokaż mniej
1518
1517
  view_more: Więcej informacji
1519
1518
  data_consent:
1520
1519
  details:
@@ -2018,7 +2018,6 @@ pt-BR:
2018
2018
  layouts:
2019
2019
  decidim:
2020
2020
  announcements:
2021
- view_less: Exibir menos
2022
2021
  view_more: Mais informações
2023
2022
  data_consent:
2024
2023
  details:
@@ -1842,7 +1842,6 @@ ro:
1842
1842
  layouts:
1843
1843
  decidim:
1844
1844
  announcements:
1845
- view_less: Afișați mai puțin
1846
1845
  view_more: Mai multe informații
1847
1846
  data_consent:
1848
1847
  details:
@@ -883,6 +883,8 @@ sk:
883
883
  errors:
884
884
  files:
885
885
  file_cannot_be_processed: Súbor nie je možné spracovať
886
+ file_contains_unsafe_content: Potenciálny nebezpečný obsah
887
+ file_is_not_a_valid_image: Nie je v platnom formáte obrázka
886
888
  file_resolution_too_large: Rozlíšenie súboru je príliš veľké
887
889
  not_inside_organization: Súbor nie je pripojený k žiadnej organizácii.
888
890
  internal_server_error:
@@ -2087,7 +2089,6 @@ sk:
2087
2089
  layouts:
2088
2090
  decidim:
2089
2091
  announcements:
2090
- view_less: Zobraziť menej
2091
2092
  view_more: Viac informácií
2092
2093
  data_consent:
2093
2094
  details:
@@ -252,6 +252,7 @@ sv:
252
252
  create: "%{user_name} lade till komponenten %{resource_name} till utrymmet %{space_name}"
253
253
  delete: "%{user_name} tog bort komponenten %{resource_name} från utrymmet %{space_name}"
254
254
  export_component: "%{user_name} exporterade %{resource_name} %{component_name} i %{space_name} som %{format_name}"
255
+ menu_hidden: "%{user_name} dolde komponenten %{resource_name} i menyn i utrymmet %{space_name}"
255
256
  publish: "%{user_name} publicerade komponenten %{resource_name} i utrymmet %{space_name}"
256
257
  restore: "%{user_name} återställde komponenten %{resource_name} i utrymmet %{space_name}"
257
258
  soft_delete: "%{user_name} tog bort komponenten %{resource_name} från utrymmet %{space_name}"
@@ -421,8 +422,8 @@ sv:
421
422
  success: Ändringsförslaget har dragits tillbaka.
422
423
  wizard_step_form:
423
424
  steps:
424
- '1': Skapa din korrigering
425
- '2': Publicera din korrigering
425
+ '1': Skapa ändringsförslag
426
+ '2': Publicera ditt ändringsförslag
426
427
  anonymous_user: Anonym
427
428
  application:
428
429
  document:
@@ -555,6 +556,7 @@ sv:
555
556
  global:
556
557
  amendments_enabled: Aktivera ändringsförslag
557
558
  comments_enabled: Aktivera kommentarer
559
+ comments_max_length: Max antal tecken per kommentar
558
560
  define_taxonomy_filters: Ställ in filter innan du använder den här inställningen.
559
561
  dummy_global_attribute1: Dummy Attribut 1
560
562
  dummy_global_attribute2: Dummy Attribut 2
@@ -660,6 +662,13 @@ sv:
660
662
  all: Alla
661
663
  filter_taxonomy_values:
662
664
  all: Alla
665
+ delete_user_mailer:
666
+ delete:
667
+ body_1: Ditt konto har inaktiverats och är inte längre tillgängligt. Dina personuppgifter kommer att raderas permanent i enlighet med våra rutiner för datalagring.
668
+ body_2: Av säkerhetsskäl behålls vissa uppgifter som rör behörigheter. Om du skapar ett nytt konto och godkänner behörigheter igen kan uppgifterna kopplas till ditt nya konto.
669
+ greetings_html: Vänliga hälsningar,<br/><a href="%{organization_url}">%{organization_name}</a>
670
+ hello: Hej %{username},
671
+ subject: Ditt konto har raderats
663
672
  devise:
664
673
  omniauth_registrations:
665
674
  create:
@@ -873,13 +882,13 @@ sv:
873
882
  affected_user:
874
883
  email_intro: 'Ett ändringsförslag har godkänts för %{amendable_title}. Visa det från den här sidan:'
875
884
  email_outro: Du har fått det här meddelandet eftersom du är en författare av %{amendable_title}.
876
- email_subject: Accepterad förbättring av %{amendable_title} från %{emendation_author_name}
877
- notification_title: <a href="%{emendation_path}">Förbättringen</a> gjord av <a href="%{emendation_author_path}">%{emendation_author_name}</a> accepterades för <a href="%{amendable_path}">%{amendable_title}</a>.
885
+ email_subject: Godkänd ändring av %{amendable_title} från %{emendation_author_nickname}
886
+ notification_title: <a href="%{emendation_path}">Ändringsförslaget</a> från av <a href="%{emendation_author_path}">%{emendation_author_name}</a> till <a href="%{amendable_path}">%{amendable_title}</a> har godkänts.
878
887
  follower:
879
888
  email_intro: 'Ett ändringsförslag har bifallits för %{amendable_title}. Läs det på den här sidan:'
880
889
  email_outro: Du har fått det här meddelandet eftersom du följer %{amendable_title}. Du kan sluta att ta emot meddelanden genom att följa föregående länk.
881
- email_subject: Accepterad förbättring av %{amendable_title} från %{emendation_author_name}
882
- notification_title: <a href="%{emendation_path}">Förbättringen</a> gjord av <a href="%{emendation_author_path}">%{emendation_author_name}</a> accepterades för <a href="%{amendable_path}">%{amendable_title}</a>.
890
+ email_subject: Godkänd ändring av %{amendable_title} från %{emendation_author_nickname}
891
+ notification_title: <a href="%{emendation_path}">Ändringsförslaget</a> av <a href="%{emendation_author_path}">%{emendation_author_name}</a> till <a href="%{amendable_path}">%{amendable_title}</a> har godkänts.
883
892
  amendment_created:
884
893
  affected_user:
885
894
  email_intro: 'Ett nytt ändringsförslag har skapats för %{amendable_title}. Du kan se det från den här sidan:'
@@ -895,20 +904,29 @@ sv:
895
904
  affected_user:
896
905
  email_intro: 'Ett avslaget ändringsförslag till %{amendable_title} har publicerats som en ny %{amendable_type}. Du kan se det på den här sidan:'
897
906
  email_outro: Du har fått det här meddelandet eftersom du är en författare av %{amendable_title}.
907
+ email_subject: Ett ändringsförslag från %{emendation_author_name} har publicerats som en ny %{amendable_type}
908
+ notification_title: Ett <a href="%{emendation_path}">avslaget ändringsförslag</a> till <a href="%{amendable_path}">%{amendable_title}</a> har publicerats som en ny %{amendable_type} av <a href="%{emendation_author_path}">%{emendation_author_name}</a>.
898
909
  follower:
899
910
  email_intro: 'En avslaget ändringsförslag till %{amendable_title} har lagts fram som ett nytt %{amendable_type}. Du kan se det på den här sidan:'
900
911
  email_outro: Du har fått det här meddelandet eftersom du följer %{amendable_title}. Du kan sluta att ta emot meddelanden via föregående länk.
912
+ email_subject: Ett ändringsförslag från %{emendation_author_name} har publicerats som en ny %{amendable_type}
913
+ notification_title: Ett <a href="%{emendation_path}">avslaget ändringsförslag</a> till <a href="%{amendable_path}">%{amendable_title}</a> har publicerats som en ny %{amendable_type} av <a href="%{emendation_author_path}">%{emendation_author_name}</a>.
901
914
  amendment_rejected:
902
915
  affected_user:
903
916
  email_intro: 'En ändringsförslag till %{amendable_title} har avslagits. Du kan se det från den här sidan:'
904
917
  email_outro: Du har fått det här meddelandet eftersom du är en författare till %{amendable_title}.
918
+ email_subject: Ändringsförslag till %{amendable_title} från %{emendation_author_name} avslogs
919
+ notification_title: <a href="%{emendation_path}">Ändringsförslaget</a> till <a href="%{amendable_path}">%{amendable_title}</a> som skapades av <a href="%{emendation_author_path}">%{emendation_author_name}</a> har avslagits.
905
920
  follower:
906
921
  email_intro: 'Ett ändringsförslag till %{amendable_title} har avslagits. Du kan se det från den här sidan:'
907
922
  email_outro: Du har fått det här meddelandet eftersom du följer %{amendable_title}. Du kan sluta ta emot meddelanden via föregående länk.
923
+ email_subject: Ändringsförslag till %{amendable_title} från %{emendation_author_name} avslogs
924
+ notification_title: <a href="%{emendation_path}">Ändringsförslaget</a> till <a href="%{amendable_path}">%{amendable_title}</a> som skapades av <a href="%{emendation_author_path}">%{emendation_author_name}</a> har avslagits.
908
925
  emendation_promoted:
909
926
  follower:
910
927
  email_intro: 'Ett ändringsförslag till %{amendable_title} har avslagits. Du kan se det från den här sidan:'
911
928
  email_outro: Du har fått det här meddelandet eftersom du är en författare till %{amendable_title}.
929
+ email_subject: Ett ändringsförslag från %{emendation_author_name} har publicerats som en ny %{amendable_type}
912
930
  attachments:
913
931
  attachment_created:
914
932
  email_intro: 'Ett nytt dokument har lagts till i %{resource_title}. Du kan se det från den här sidan:'
@@ -941,6 +959,18 @@ sv:
941
959
  notification_body: Vi har ändrat reglerna för användarnamn för att undvika dubbletter och har tagit bort regeln om skriftlägeskänsliga namn. <br/> Ditt användarnamn skapades efter ett annat med samma namn, så vi har automatiskt bytt namn på det. Du kan ändra det i <a href="%{link_to_account_settings}">dina kontoinställningar</a>.
942
960
  notification_event:
943
961
  notification_title: Något inträffade i <a href="%{resource_path}">%{resource_title}</a>.
962
+ participatory_space:
963
+ member_added:
964
+ published:
965
+ email_intro: Du har lagts till som medlem i ett deltagarutrymme.
966
+ email_outro: Du har fått det här meddelandet eftersom en administratör har lagt till dig i <a href="%{resource_url}">%{resource_title}</a>. Om åtkomsten till utrymmet är begränsad kan du komma åt det med ditt konto.<br> Din profil visas i utrymmets <a href="%{members_page}">medlemslista</a>.
967
+ email_subject: Du har nu åtkomst till %{resource_title}.
968
+ notification_title: Du har nu åtkomst till <a href="%{resource_url}">%{resource_title}</a>.
969
+ unpublished:
970
+ email_intro: Du har lagts till som medlem i ett deltagarutrymme.
971
+ email_outro: Du har fått det här meddelandet eftersom en administratör har lagt till dig i <a href="%{resource_url}">%{resource_title}</a>. Om åtkomsten till utrymmet är begränsad kan du komma åt det med ditt konto.
972
+ email_subject: Du har nu åtkomst till %{resource_title}.
973
+ notification_title: Du har nu åtkomst till <a href="%{resource_url}">%{resource_title}</a>.
944
974
  reports:
945
975
  parent_hidden:
946
976
  email_intro: |-
@@ -960,13 +990,25 @@ sv:
960
990
  En administratör tog bort din %{resource_type} eftersom den har rapporterats som %{report_reasons}.
961
991
  </br>
962
992
  <i>%{resource_content}</i>
993
+ resource_liked:
994
+ email_intro: '%{liker_name}, som du följer, har precis gillat ”%{resource_title}” och vi tror att det kan intressera dig. Ta en titt och bidra:'
995
+ email_outro: Du har fått det här meddelandet eftersom du följer %{liker_name}. Du kan sluta ta emot meddelandena genom att följa länken ovan.
996
+ email_subject: "%{liker_name} har gillat något"
997
+ notification_title: <a href="%{liker_path}">%{liker_name} </a> gillar %{resource_type} <a href="%{resource_path}">%{resource_title}</a>.
963
998
  resources:
964
999
  soft_deleted:
965
1000
  notification_title: En administratör har tagit bort ditt "%{resource_type}" "%{resource_title}".
966
1001
  users:
1002
+ profile_updated:
1003
+ email_intro: <a href="%{resource_url}">Profilsidan</a> för %{name}, som du följer, har uppdaterats.
1004
+ email_outro: Du har fått det här meddelandet eftersom du följer %{name}. Du kan sluta ta emot meddelandena genom att följa länken ovan.
1005
+ email_subject: "%{name} uppdaterade sin profil"
1006
+ notification_title: <a href="%{resource_path}">Profilsidan</a> för %{name}, som du följer, har uppdaterats.
967
1007
  user_officialized:
1008
+ email_intro: Deltagaren %{name} har fått officiell status.
968
1009
  email_outro: Du har fått detta meddelande eftersom du är administratör i organisationen.
969
1010
  email_subject: "%{name} har fått officiell status"
1011
+ notification_title: Deltagaren %{name} har fått officiell status.
970
1012
  export_mailer:
971
1013
  download_your_data_export:
972
1014
  click_button_html: Klicka på nästa länk för att ladda ner dina data.<br/>Filen kommer att finnas tillgänglig för nedladdning fram till %{date}.
@@ -1146,7 +1188,7 @@ sv:
1146
1188
  access_mode_presenter:
1147
1189
  access_modes:
1148
1190
  open: Öppen
1149
- restricted: Begränsad
1191
+ restricted: Privat
1150
1192
  transparent: Transparent
1151
1193
  not_found: Åtkomstläge %{id} hittades inte
1152
1194
  area_presenter:
@@ -1167,6 +1209,8 @@ sv:
1167
1209
  dynamic:
1168
1210
  screen_reader_explanation: Följande element är en karta som presenterar objekten på denna sida som kartpunkter. Elementet kan användas med en skärmläsare men det kan vara svårt att förstå.
1169
1211
  skip_button: Hoppa över karta
1212
+ zoom_in: Zooma in
1213
+ zoom_out: Zooma ut
1170
1214
  static:
1171
1215
  latlng_text: 'latitud: %{latitude}, longitud: %{longitude}'
1172
1216
  map_service_brand: OpenStreetMap
@@ -1508,13 +1552,21 @@ sv:
1508
1552
  never_logged_in: har aldrig loggat in
1509
1553
  subject: Varning om inaktivt konto
1510
1554
  participatory_space:
1555
+ labels:
1556
+ reference: Utrymmets referens
1557
+ restricted: Privat utrymme
1558
+ transparent: Transparent utrymme
1511
1559
  pages:
1512
1560
  user_profile:
1513
1561
  member_of:
1514
- member_of: Medlem av
1562
+ member_of: Medlem i
1515
1563
  participatory_space_members:
1516
1564
  index:
1517
1565
  members: Medlemmar
1566
+ participatory_spaces:
1567
+ show:
1568
+ restricted_space: Det här är ett privat utrymme. Endast medlemmar och administratörer kan se det och delta.
1569
+ transparent_space: Det här är ett transparent utrymme. Alla kan se innehållet, men endast medlemmar och administratörer kan delta.
1518
1570
  passwords:
1519
1571
  update:
1520
1572
  error: Det gick inte att uppdatera lösenordet.
@@ -1662,6 +1714,8 @@ sv:
1662
1714
  login_modal:
1663
1715
  please_log_in: Logga in
1664
1716
  sign_up: Skapa ett konto
1717
+ mentions:
1718
+ search_prompt: Skriv för att söka efter deltagare
1665
1719
  mentions_modal:
1666
1720
  remove_recipient: Ta bort mottagare %{name}
1667
1721
  progress: Framsteg
@@ -1703,6 +1757,9 @@ sv:
1703
1757
  help_text: "<strong>Obs:</strong> Innehåll kan ha översatts automatiskt och inte vara 100% korrekt."
1704
1758
  show_original: Visa originaltexten
1705
1759
  show_translated: Visa maskinöversatt text
1760
+ user_activity:
1761
+ index:
1762
+ no_activities_warning: Den här deltagaren har ingen aktivitet ännu.
1706
1763
  user_contact_disabled: Deltagaren tar inte emot inte direktmeddelanden.
1707
1764
  user_conversations:
1708
1765
  index:
@@ -1801,7 +1858,7 @@ sv:
1801
1858
  nickname_help: Ditt användarnamn i %{organization}. Kan bara innehålla små bokstäver a-z, siffror, '-' och '_'.
1802
1859
  submit_button: Spara
1803
1860
  subtitle: Om du godkänner inbjudan väljer du ditt användarnamn och lösenord.
1804
- subtitle_no_password: Om du accepterar inbjudan var vänlig ange ditt alias.
1861
+ subtitle_no_password: Om du accepterar inbjudan var vänlig ange ditt användarnamn.
1805
1862
  invitation_removed: Din inbjudan har tagits bort.
1806
1863
  invitation_token_invalid: Ogiltig token för inbjudan!
1807
1864
  new:
@@ -1809,8 +1866,8 @@ sv:
1809
1866
  submit_button: Skicka en inbjudan
1810
1867
  no_invitations_remaining: Inga inbjudningar kvar
1811
1868
  send_instructions: Ett e-brev med inbjudan har skickats till %{email}.
1812
- updated: Inbjudan godtogs. Du är nu inloggad.
1813
- updated_not_active: Inbjudan godtogs.
1869
+ updated: Inbjudan accepterades. Du är nu inloggad.
1870
+ updated_not_active: Inbjudan accepterades.
1814
1871
  mailer:
1815
1872
  confirmation_instructions:
1816
1873
  action: Bekräfta mitt konto
@@ -2042,7 +2099,6 @@ sv:
2042
2099
  layouts:
2043
2100
  decidim:
2044
2101
  announcements:
2045
- view_less: Visa mindre
2046
2102
  view_more: Mer information
2047
2103
  data_consent:
2048
2104
  details:
@@ -964,8 +964,6 @@ tr:
964
964
  timestamp_error_message: Üzgünüm, bu çok hızlıydı! Lütfen yeniden gönderin.
965
965
  layouts:
966
966
  decidim:
967
- announcements:
968
- view_less: Daha Az Göster
969
967
  data_consent:
970
968
  details:
971
969
  columns:
data/config/routes.rb CHANGED
@@ -23,8 +23,17 @@ Decidim::Core::Engine.routes.draw do
23
23
 
24
24
  post :locate, to: "geolocation#locate"
25
25
 
26
- Decidim.global_engines.each do |name, engine_data|
27
- mount engine_data[:engine], at: engine_data[:at], as: name
26
+ scope "/:locale", **locale_scope_options do
27
+ Decidim.global_engines.each do |name, engine_data|
28
+ mount engine_data[:engine], at: engine_data[:at], as: name
29
+ end
30
+ end
31
+
32
+ Decidim.global_engines.each do |_name, engine_data|
33
+ path = engine_data[:at]
34
+
35
+ get path, to: redirect(&locale_redirector(path))
36
+ get "#{path}/*rest", to: redirect { |params, request| locale_redirector("#{path}/#{params[:rest]}").call(params, request) }
28
37
  end
29
38
 
30
39
  authenticate(:user) do
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddFailedAttemptsAndLockedAtToDecidimAuthorizations < ActiveRecord::Migration[7.0]
4
+ def change
5
+ add_column :decidim_authorizations, :failed_attempts, :integer, default: 0, null: false
6
+ add_column :decidim_authorizations, :locked_at, :datetime
7
+ end
8
+ end
data/decidim-core.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.push File.expand_path("lib", __dir__)
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "decidim-core"
7
- version = "0.32.1"
7
+ version = "0.32.2"
8
8
  s.version = version
9
9
  s.authors = ["Josep Jaume Rey Peroy", "Marc Riera Casals", "Oriol Gual Oliva"]
10
10
  s.email = ["josepjaume@gmail.com", "mrc2407@gmail.com", "oriolgual@gmail.com"]
@@ -21,6 +21,7 @@ module Decidim
21
21
  @query = Decidim::UserBaseEntity
22
22
  .where(organization: ctx[:current_organization])
23
23
  .confirmed
24
+ .not_deleted
24
25
  .not_blocked
25
26
  add_filter_keys(args[:filter])
26
27
  add_order_keys(args[:order].to_h)
@@ -21,7 +21,7 @@ module Decidim
21
21
  end
22
22
 
23
23
  def block_reasons
24
- object.blocking.justification
24
+ object.blocking&.justification
25
25
  end
26
26
 
27
27
  def blocked_at
@@ -29,7 +29,7 @@ module Decidim
29
29
  end
30
30
 
31
31
  def blocking_user
32
- object.blocking.blocking_user
32
+ object.blocking&.blocking_user
33
33
  end
34
34
  end
35
35
  end
@@ -16,7 +16,7 @@ module Decidim
16
16
  Metadata = Struct.new(:users)
17
17
 
18
18
  # Matches a nickname if contains letters, numbers or underscores.
19
- MENTION_REGEX = /\B@(\w*)\b/
19
+ MENTION_REGEX = /\B@([\w-]*)\b/
20
20
 
21
21
  # (see BaseParser#metadata)
22
22
  def metadata
@@ -20,7 +20,6 @@ module Decidim
20
20
  autoload :UserParser, "decidim/content_parsers/user_parser"
21
21
  autoload :NewlineParser, "decidim/content_parsers/newline_parser"
22
22
  autoload :LinkParser, "decidim/content_parsers/link_parser"
23
- autoload :InlineImagesParser, "decidim/content_parsers/inline_images_parser"
24
23
  autoload :ResourceParser, "decidim/content_parsers/resource_parser"
25
24
  autoload :TagParser, "decidim/content_parsers/tag_parser"
26
25
  autoload :MentionResourceParser, "decidim/content_parsers/mention_resource_parser"
@@ -20,8 +20,12 @@ module Decidim
20
20
  # a link to the resource.
21
21
  #
22
22
  # @return [String] the content ready to display (contains HTML)
23
- def render(editor: false, **_)
24
- replace_pattern(content, GLOBAL_ID_REGEX, editor:)
23
+ def render(editor: false, plain: false, **_)
24
+ if plain
25
+ replace_plain_text(content)
26
+ else
27
+ replace_pattern(content, GLOBAL_ID_REGEX, editor:)
28
+ end
25
29
  end
26
30
 
27
31
  protected
@@ -39,9 +43,19 @@ module Decidim
39
43
  end
40
44
  end
41
45
 
46
+ def replace_plain_text(text)
47
+ text.gsub(GLOBAL_ID_REGEX) do
48
+ resource = GlobalID::Locator.locate(Regexp.last_match[0])
49
+ resource ? presenter_for(resource).title : ""
50
+ end
51
+ end
52
+
42
53
  def render_editor(resource_gid, resource)
43
- title = presenter_for(resource).title
44
- %(<span data-type="mentionResource" data-id="#{resource_gid}" data-label="#{title}">#{title}</span>)
54
+ title = presenter_for(resource).title.to_s
55
+ escaped_gid = CGI.escapeHTML(resource_gid.to_s)
56
+ escaped_title = CGI.escapeHTML(title)
57
+
58
+ %(<span data-type="mentionResource" data-id="#{escaped_gid}" data-label="#{escaped_title}">#{escaped_title}</span>)
45
59
  end
46
60
 
47
61
  def render_resource_link(resource)
@@ -17,8 +17,12 @@ module Decidim
17
17
  # invalid Decidim::User are replaced with an empty string.
18
18
  #
19
19
  # @return [String] the content ready to display (contains HTML)
20
- def render(editor: false, **_)
21
- replace_pattern(content, GLOBAL_ID_REGEX, editor:)
20
+ def render(editor: false, plain: false, **_)
21
+ if plain
22
+ replace_plain_text(content)
23
+ else
24
+ replace_pattern(content, GLOBAL_ID_REGEX, editor:)
25
+ end
22
26
  end
23
27
 
24
28
  protected
@@ -36,10 +40,17 @@ module Decidim
36
40
  end
37
41
  end
38
42
 
43
+ def replace_plain_text(text)
44
+ text.gsub(GLOBAL_ID_REGEX) do
45
+ user = GlobalID::Locator.locate(Regexp.last_match[0])
46
+ user ? presenter_for(user).nickname : ""
47
+ end
48
+ end
49
+
39
50
  def render_editor(mentionable)
40
51
  mention = render_text(mentionable, editor: true)
41
- label = CGI.escapeHTML("#{mention} (#{mentionable.name})")
42
- %(<span data-type="mention" data-id="#{mention}" data-label="#{label}">#{label}</span>)
52
+ label = CGI.escapeHTML(mention)
53
+ %(<span data-type="mention" data-id="#{label}" data-label="#{label}">#{label}</span>)
43
54
  end
44
55
 
45
56
  def presenter_for(mentionable)
@@ -42,5 +42,82 @@ shared_examples "participatory space members page examples" do
42
42
  end
43
43
  end
44
44
  end
45
+
46
+ context "when participatory space has paginated members" do
47
+ let(:users) { create_list(:user, 30, organization: participatory_space.organization) }
48
+ let!(:members) do
49
+ users.map do |user|
50
+ create(:member, participatory_space:, user:, published: true)
51
+ end
52
+ end
53
+
54
+ context "with default pagination" do
55
+ it "returns first page with 25 members" do
56
+ get :index, params: { slug_param => slug, :locale => I18n.locale }
57
+
58
+ expect(assigns(:members).count).to eq(25)
59
+ expect(assigns(:members).current_page).to eq(1)
60
+ expect(assigns(:members).total_count).to eq(30)
61
+ end
62
+ end
63
+
64
+ context "with page parameter" do
65
+ it "returns second page with remaining members" do
66
+ get :index, params: { slug_param => slug, :locale => I18n.locale, :page => 2 }
67
+
68
+ expect(assigns(:members).count).to eq(5)
69
+ expect(assigns(:members).current_page).to eq(2)
70
+ expect(assigns(:members).total_count).to eq(30)
71
+ end
72
+
73
+ it "returns empty collection for out-of-range page" do
74
+ get :index, params: { slug_param => slug, :locale => I18n.locale, :page => 999 }
75
+
76
+ expect(assigns(:members).count).to eq(0)
77
+ expect(assigns(:members).current_page).to eq(999)
78
+ expect(assigns(:members).total_count).to eq(30)
79
+ end
80
+ end
81
+
82
+ context "with per_page parameter" do
83
+ it "returns all members when per_page is 50" do
84
+ get :index, params: { slug_param => slug, :locale => I18n.locale, :per_page => 50 }
85
+
86
+ expect(assigns(:members).count).to eq(30)
87
+ expect(assigns(:members).current_page).to eq(1)
88
+ expect(assigns(:members).limit_value).to eq(50)
89
+ expect(assigns(:members).total_count).to eq(30)
90
+ end
91
+
92
+ it "returns first 25 members when per_page is 25" do
93
+ get :index, params: { slug_param => slug, :locale => I18n.locale, :per_page => 25 }
94
+
95
+ expect(assigns(:members).count).to eq(25)
96
+ expect(assigns(:members).limit_value).to eq(25)
97
+ end
98
+
99
+ it "limits per_page to maximum allowed value" do
100
+ get :index, params: { slug_param => slug, :locale => I18n.locale, :per_page => 200 }
101
+
102
+ expect(assigns(:members).limit_value).to eq(100)
103
+ end
104
+
105
+ it "limit per_page to minimum allowed value" do
106
+ get :index, params: { slug_param => slug, :locale => I18n.locale, :per_page => 5 }
107
+
108
+ expect(assigns(:members).limit_value).to eq(25)
109
+ end
110
+ end
111
+
112
+ context "with both page and per_page parameters" do
113
+ it "returns correct page with custom per_page" do
114
+ get :index, params: { slug_param => slug, :locale => I18n.locale, :page => 2, :per_page => 50 }
115
+
116
+ expect(assigns(:members).count).to eq(0)
117
+ expect(assigns(:members).current_page).to eq(2)
118
+ expect(assigns(:members).limit_value).to eq(50)
119
+ end
120
+ end
121
+ end
45
122
  end
46
123
  end
@@ -117,5 +117,63 @@ shared_examples "participatory space members" do
117
117
  expect(page).to have_content("Profile")
118
118
  end
119
119
  end
120
+
121
+ context "when there are more members than the pagination per_page limit" do
122
+ let(:per_page) { Decidim::Paginable::OPTIONS.first }
123
+ let(:users) { create_list(:user, per_page + 5, organization: participatory_space.organization) }
124
+ let!(:extra_members) do
125
+ users.map do |user|
126
+ create(:member, participatory_space:, user:, published: true)
127
+ end
128
+ end
129
+
130
+ before do
131
+ visit members_path
132
+ end
133
+
134
+ it "paginates the members list" do
135
+ within ".layout-main__section" do
136
+ expect(page).to have_css(".profile__user", count: per_page)
137
+ end
138
+ end
139
+
140
+ it "shows pagination controls" do
141
+ within("div[data-pagination]") do
142
+ expect(page).to have_css('nav[aria-label="Pagination"]')
143
+ end
144
+ end
145
+
146
+ it "navigates to the next page" do
147
+ within "nav[aria-label=\"Pagination\"]" do
148
+ click_on "Next"
149
+ end
150
+
151
+ within ".layout-main__section" do
152
+ expect(page).to have_css(".profile__user", count: 6)
153
+ end
154
+ end
155
+
156
+ it "maintains pagination when navigating back" do
157
+ within "nav[aria-label=\"Pagination\"]" do
158
+ click_on "Next"
159
+ end
160
+
161
+ within "nav[aria-label=\"Pagination\"]" do
162
+ click_on "Prev"
163
+ end
164
+
165
+ within ".layout-main__section" do
166
+ expect(page).to have_css(".profile__user", count: per_page)
167
+ end
168
+ end
169
+
170
+ it "shows the correct page number in the URL" do
171
+ within "nav[aria-label=\"Pagination\"]" do
172
+ click_on "Next"
173
+ end
174
+
175
+ expect(page).to have_current_path(/page=2/)
176
+ end
177
+ end
120
178
  end
121
179
  end
@@ -28,7 +28,7 @@ shared_examples "a version of a hidden object" do
28
28
  end
29
29
  end
30
30
 
31
- shared_examples "versions controller" do
31
+ shared_context "versions controller resource" do
32
32
  let(:base_params) do
33
33
  if resource.is_a?(Decidim::Participable)
34
34
  { :"#{resource.model_name.singular_route_key}_slug" => resource.slug, :locale => I18n.locale }
@@ -45,6 +45,10 @@ shared_examples "versions controller" do
45
45
  request.env["decidim.current_component"] = resource.component
46
46
  end
47
47
  end
48
+ end
49
+
50
+ shared_examples "versions controller" do
51
+ include_context "versions controller resource"
48
52
 
49
53
  describe "GET show" do
50
54
  context "with an existing version" do
@@ -64,3 +68,21 @@ shared_examples "versions controller" do
64
68
  end
65
69
  end
66
70
  end
71
+
72
+ # The versions of a resource must be readable with the same `:read` permission
73
+ # as the resource itself. This ensures that a resource that is hidden, private,
74
+ # deleted or unpublished cannot be reached through its versions.
75
+ #
76
+ # Requires a `resource` that is not readable through its public `:read`
77
+ # permission.
78
+ shared_examples "versions controller denying unreadable resources" do
79
+ include_context "versions controller resource"
80
+
81
+ it "does not expose the versions" do
82
+ get :show, params: base_params.merge(id: 1)
83
+
84
+ expect(response).not_to have_http_status(:ok)
85
+ rescue ActiveRecord::RecordNotFound
86
+ # The resource is filtered out before the permission is evaluated.
87
+ end
88
+ end