decidim-core 0.31.2 → 0.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -13
  3. data/app/cells/decidim/amendable/amend_button_card/show.erb +2 -2
  4. data/app/cells/decidim/amendable/amend_button_card_cell.rb +1 -1
  5. data/app/cells/decidim/author_cell.rb +0 -4
  6. data/app/cells/decidim/card_metadata_cell.rb +1 -1
  7. data/app/cells/decidim/comments_button_cell.rb +9 -1
  8. data/app/cells/decidim/content_blocks/announcement_settings_form/show.erb +5 -0
  9. data/app/cells/decidim/content_blocks/announcement_settings_form_cell.rb +17 -0
  10. data/app/cells/decidim/content_blocks/cta_settings_form/show.erb +1 -1
  11. data/app/cells/decidim/content_blocks/hero_settings_form/show.erb +1 -1
  12. data/app/cells/decidim/content_blocks/highlighted_content_banner_cell.rb +1 -1
  13. data/app/cells/decidim/content_blocks/highlighted_content_banner_settings_form/show.erb +1 -1
  14. data/app/cells/decidim/content_blocks/highlighted_elements_with_cell_for_list_cell.rb +5 -1
  15. data/app/cells/decidim/content_blocks/highlighted_participatory_spaces_cell.rb +1 -1
  16. data/app/cells/decidim/content_blocks/how_to_participate/show.erb +1 -1
  17. data/app/cells/decidim/content_blocks/html_cell.rb +1 -1
  18. data/app/cells/decidim/content_blocks/participatory_space_announcement_cell.rb +1 -3
  19. data/app/cells/decidim/content_blocks/participatory_space_hero_cell.rb +1 -5
  20. data/app/cells/decidim/content_blocks/participatory_space_hero_settings_form/show.erb +1 -1
  21. data/app/cells/decidim/content_blocks/static_page/section_cell.rb +1 -1
  22. data/app/cells/decidim/content_blocks/static_page/section_settings_form/show.erb +3 -1
  23. data/app/cells/decidim/content_blocks/static_page/summary_cell.rb +1 -1
  24. data/app/cells/decidim/content_blocks/static_page/summary_settings_form/show.erb +3 -1
  25. data/app/cells/decidim/content_blocks/static_page/two_pane_section_cell.rb +2 -2
  26. data/app/cells/decidim/content_blocks/static_page/two_pane_section_settings_form/show.erb +4 -2
  27. data/app/cells/decidim/data_consent/category.erb +25 -38
  28. data/app/cells/decidim/footer_topics/show.erb +5 -8
  29. data/app/cells/decidim/{participatory_space_private_user → member}/show.erb +6 -6
  30. data/app/cells/decidim/{participatory_space_private_user_cell.rb → member_cell.rb} +1 -5
  31. data/app/cells/decidim/nav_links/show.erb +3 -3
  32. data/app/cells/decidim/onboarding_action_message_cell.rb +1 -0
  33. data/app/cells/decidim/profile/details.erb +1 -1
  34. data/app/cells/decidim/profile_cell.rb +1 -0
  35. data/app/cells/decidim/profile_member_of/show.erb +13 -0
  36. data/app/cells/decidim/profile_member_of_cell.rb +35 -0
  37. data/app/cells/decidim/report_button/already_reported_modal.erb +1 -1
  38. data/app/cells/decidim/report_button/flag_modal.erb +1 -1
  39. data/app/cells/decidim/report_user_button/already_reported_modal.erb +1 -1
  40. data/app/cells/decidim/report_user_button/flag_modal.erb +1 -1
  41. data/app/cells/decidim/resource_types_filter/show.erb +2 -2
  42. data/app/cells/decidim/share_text_widget/modal.erb +1 -1
  43. data/app/cells/decidim/share_widget/qr_code_modal.erb +1 -1
  44. data/app/cells/decidim/tags_cell.rb +1 -1
  45. data/app/cells/decidim/upload_modal/files.erb +5 -1
  46. data/app/cells/decidim/upload_modal_cell.rb +15 -1
  47. data/app/cells/decidim/versions_list/show.erb +25 -0
  48. data/app/commands/decidim/create_follow.rb +3 -5
  49. data/app/commands/decidim/create_user_report.rb +1 -1
  50. data/app/commands/decidim/destroy_account.rb +15 -4
  51. data/app/commands/decidim/multiple_attachments_methods.rb +42 -24
  52. data/app/commands/decidim/search.rb +5 -5
  53. data/app/controllers/concerns/decidim/ajax_permission_handler.rb +1 -1
  54. data/app/controllers/concerns/decidim/devise_controllers.rb +9 -0
  55. data/app/controllers/concerns/decidim/direct_upload.rb +3 -2
  56. data/app/controllers/concerns/decidim/ephemeral_session_checker.rb +1 -1
  57. data/app/controllers/concerns/decidim/force_authentication.rb +10 -1
  58. data/app/controllers/concerns/decidim/impersonate_users.rb +4 -0
  59. data/app/controllers/concerns/decidim/locale_switcher.rb +52 -2
  60. data/app/controllers/concerns/decidim/needs_tos_accepted.rb +1 -1
  61. data/app/controllers/concerns/decidim/participatory_space/has_members_page.rb +27 -0
  62. data/app/controllers/concerns/decidim/participatory_space_context.rb +1 -5
  63. data/app/controllers/decidim/account_controller.rb +1 -1
  64. data/app/controllers/decidim/amendments_controller.rb +5 -4
  65. data/app/controllers/decidim/components/base_controller.rb +20 -3
  66. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +1 -1
  67. data/app/controllers/decidim/devise/passwords_controller.rb +1 -1
  68. data/app/controllers/decidim/devise/registrations_controller.rb +1 -1
  69. data/app/controllers/decidim/devise/sessions_controller.rb +1 -1
  70. data/app/controllers/decidim/download_your_data_controller.rb +2 -2
  71. data/app/controllers/decidim/editor_images_controller.rb +1 -1
  72. data/app/controllers/decidim/follows_controller.rb +4 -3
  73. data/app/controllers/decidim/geolocation_controller.rb +1 -1
  74. data/app/controllers/decidim/likes_controller.rb +2 -1
  75. data/app/controllers/decidim/locales_controller.rb +3 -11
  76. data/app/controllers/decidim/messaging/conversations_controller.rb +3 -3
  77. data/app/controllers/decidim/newsletters_controller.rb +1 -1
  78. data/app/controllers/decidim/notifications_settings_controller.rb +1 -1
  79. data/app/controllers/decidim/notifications_subscriptions_controller.rb +8 -0
  80. data/app/controllers/decidim/open_data_controller.rb +1 -1
  81. data/app/controllers/decidim/private_downloads_controller.rb +29 -0
  82. data/app/controllers/decidim/report_users_controller.rb +2 -2
  83. data/app/controllers/decidim/reports_controller.rb +1 -1
  84. data/app/controllers/decidim/user_activities_controller.rb +1 -2
  85. data/app/events/decidim/amendable/amendment_base_event.rb +7 -1
  86. data/app/events/decidim/welcome_notification_event.rb +1 -1
  87. data/app/forms/decidim/upload_validation_form.rb +1 -1
  88. data/app/helpers/concerns/decidim/flash_helper_extensions.rb +1 -0
  89. data/app/helpers/decidim/active_link_to_helper.rb +136 -0
  90. data/app/helpers/decidim/amendments_helper.rb +3 -3
  91. data/app/helpers/decidim/check_boxes_tree_helper.rb +2 -2
  92. data/app/helpers/decidim/component_path_helper.rb +9 -4
  93. data/app/helpers/decidim/filters_helper.rb +0 -2
  94. data/app/helpers/decidim/mailer_helper.rb +36 -0
  95. data/app/helpers/decidim/menu_helper.rb +4 -5
  96. data/app/helpers/decidim/meta_tags_helper.rb +0 -2
  97. data/app/helpers/decidim/newsletters_helper.rb +4 -22
  98. data/app/helpers/decidim/paginate_helper.rb +14 -1
  99. data/app/helpers/decidim/sanitize_helper.rb +1 -0
  100. data/app/helpers/decidim/short_link_helper.rb +5 -5
  101. data/app/helpers/decidim/translations_helper.rb +4 -4
  102. data/app/jobs/decidim/delete_inactive_participants_job.rb +2 -2
  103. data/app/jobs/decidim/find_and_update_descendants_job.rb +8 -2
  104. data/app/jobs/decidim/process_inactive_participant_job.rb +0 -7
  105. data/app/jobs/decidim/update_search_indexes_job.rb +2 -2
  106. data/app/mailers/decidim/application_mailer.rb +11 -2
  107. data/app/mailers/decidim/decidim_devise_mailer.rb +1 -0
  108. data/app/mailers/decidim/delete_user_mailer.rb +14 -0
  109. data/app/mailers/decidim/participants_account_mailer.rb +0 -16
  110. data/app/mailers/decidim/reported_mailer.rb +4 -1
  111. data/app/models/decidim/action_log.rb +1 -1
  112. data/app/models/decidim/attachment.rb +20 -2
  113. data/app/models/decidim/authorization.rb +7 -0
  114. data/app/models/decidim/authorization_transfer.rb +1 -1
  115. data/app/models/decidim/component.rb +6 -9
  116. data/app/models/decidim/content_block.rb +3 -3
  117. data/app/models/decidim/moderation.rb +1 -1
  118. data/app/models/decidim/newsletter.rb +2 -2
  119. data/app/models/decidim/participatory_space/member.rb +55 -0
  120. data/app/models/decidim/private_download.rb +61 -0
  121. data/app/models/decidim/private_export.rb +6 -0
  122. data/app/models/decidim/resource_link.rb +1 -1
  123. data/app/models/decidim/short_link.rb +1 -1
  124. data/app/models/decidim/user.rb +2 -2
  125. data/app/models/decidim/user_base_entity.rb +17 -2
  126. data/app/models/decidim/user_moderation.rb +1 -1
  127. data/app/packs/src/decidim/a11y.js +29 -0
  128. data/app/packs/src/decidim/a11y.test.js +81 -0
  129. data/app/packs/src/decidim/confirm.js +8 -1
  130. data/app/packs/src/decidim/confirm.test.js +225 -0
  131. data/app/packs/src/decidim/controllers/accordion/accordion.test.js +272 -0
  132. data/app/packs/src/decidim/controllers/accordion/controller.js +117 -17
  133. data/app/packs/src/decidim/controllers/assign_role/assign_role.test.js +80 -0
  134. data/app/packs/src/decidim/controllers/assign_role/controller.js +27 -0
  135. data/app/packs/src/decidim/controllers/breadcrumb_truncate/breadcrumb_truncate.test.js +230 -0
  136. data/app/packs/src/decidim/controllers/breadcrumb_truncate/controller.js +172 -0
  137. data/app/packs/src/decidim/controllers/dropdown/controller.js +32 -0
  138. data/app/packs/src/decidim/controllers/dropdown/dropdown.test.js +215 -0
  139. data/app/packs/src/decidim/controllers/form_validator/form_validator.js +9 -8
  140. data/app/packs/src/decidim/controllers/form_validator/form_validator.test.js +28 -1
  141. data/app/packs/src/decidim/controllers/language_change/controller.js +1 -0
  142. data/app/packs/src/decidim/controllers/language_change/language_change.test.js +13 -0
  143. data/app/packs/src/decidim/controllers/main_menu/controller.js +152 -0
  144. data/app/packs/src/decidim/controllers/main_menu/main_menu.test.js +285 -0
  145. data/app/packs/src/decidim/controllers/mention/controller.js +296 -140
  146. data/app/packs/src/decidim/controllers/mention/input_mentions.test.js +120 -457
  147. data/app/packs/src/decidim/controllers/multiple_mentions/controller.js +68 -32
  148. data/app/packs/src/decidim/controllers/multiple_mentions/input_multiple_mentions.test.js +30 -23
  149. data/app/packs/src/decidim/controllers/password_toggler/controller.js +22 -1
  150. data/app/packs/src/decidim/controllers/password_toggler/password_toggler.test.js +11 -20
  151. data/app/packs/src/decidim/datepicker/datepicker_functions.js +26 -0
  152. data/app/packs/src/decidim/datepicker/generate_datepicker.js +3 -14
  153. data/app/packs/src/decidim/datepicker/generate_timepicker.js +3 -2
  154. data/app/packs/src/decidim/datepicker/test/datepicker_functions_adjust_picker_position.test.js +234 -0
  155. data/app/packs/src/decidim/direct_uploads/upload_field.js +4 -4
  156. data/app/packs/src/decidim/direct_uploads/upload_modal.js +12 -7
  157. data/app/packs/src/decidim/editor/common/suggestion.js +4 -2
  158. data/app/packs/src/decidim/editor/extensions/decidim_kit/index.js +4 -1
  159. data/app/packs/src/decidim/editor/extensions/image/index.js +57 -16
  160. data/app/packs/src/decidim/editor/extensions/image/node_view.js +9 -1
  161. data/app/packs/src/decidim/editor/extensions/indent/index.js +9 -0
  162. data/app/packs/src/decidim/editor/extensions/link/bubble_menu.js +34 -6
  163. data/app/packs/src/decidim/editor/extensions/link/index.js +53 -12
  164. data/app/packs/src/decidim/editor/extensions/mention/index.js +18 -5
  165. data/app/packs/src/decidim/editor/extensions/mention_resource/index.js +16 -7
  166. data/app/packs/src/decidim/editor/test/extensions/decidim_kit.test.js +13 -4
  167. data/app/packs/src/decidim/editor/test/extensions/heading.test.js +1 -1
  168. data/app/packs/src/decidim/editor/test/extensions/image.test.js +26 -28
  169. data/app/packs/src/decidim/editor/test/extensions/image_links.test.js +161 -0
  170. data/app/packs/src/decidim/editor/test/extensions/mention.test.js +6 -2
  171. data/app/packs/src/decidim/editor/test/extensions/video_embed.test.js +27 -15
  172. data/app/packs/src/decidim/editor/test/helpers.js +8 -10
  173. data/app/packs/src/decidim/editor/test/toolbar/full.test.js +15 -4
  174. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_block.js +8 -4
  175. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_formatting.js +5 -1
  176. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_indent.js +9 -5
  177. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_link.js +5 -1
  178. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_list.js +8 -4
  179. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_styling.js +13 -9
  180. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_content_styling.js +6 -2
  181. data/app/packs/src/decidim/geocoding/reverse_geocoding.js +15 -5
  182. data/app/packs/src/decidim/geocoding/reverse_geocoding.test.js +197 -0
  183. data/app/packs/src/decidim/index.js +4 -4
  184. data/app/packs/src/decidim/map/controller.js +10 -1
  185. data/app/packs/src/decidim/refactor/moved/focus_guard.js +16 -16
  186. data/app/packs/src/decidim/refactor/moved/focus_guard.test.js +136 -0
  187. data/app/packs/src/decidim/sw/push-permissions.js +48 -13
  188. data/app/packs/src/decidim/sw/sw.js +1 -1
  189. data/app/packs/src/decidim/utilities/text.js +6 -6
  190. data/app/packs/stylesheets/decidim/_cards.scss +15 -6
  191. data/app/packs/stylesheets/decidim/_conversations.scss +14 -0
  192. data/app/packs/stylesheets/decidim/_cookies.scss +13 -5
  193. data/app/packs/stylesheets/decidim/_datepicker.scss +0 -8
  194. data/app/packs/stylesheets/decidim/_documents.scss +1 -1
  195. data/app/packs/stylesheets/decidim/_dropdown.scss +22 -32
  196. data/app/packs/stylesheets/decidim/_editor_suggestions.scss +49 -0
  197. data/app/packs/stylesheets/decidim/_flash.scss +1 -1
  198. data/app/packs/stylesheets/decidim/_floating_help.scss +1 -1
  199. data/app/packs/stylesheets/decidim/_footer.scss +27 -31
  200. data/app/packs/stylesheets/decidim/_forms.scss +5 -1
  201. data/app/packs/stylesheets/decidim/_header.scss +183 -48
  202. data/app/packs/stylesheets/decidim/_language_chooser.scss +79 -0
  203. data/app/packs/stylesheets/decidim/_participatory_spaces.scss +1 -1
  204. data/app/packs/stylesheets/decidim/_rich_text.scss +17 -0
  205. data/app/packs/stylesheets/decidim/_tom_select.scss +23 -0
  206. data/app/packs/stylesheets/decidim/application.scss +3 -0
  207. data/app/packs/stylesheets/decidim/editor.scss +12 -33
  208. data/app/packs/stylesheets/decidim/geocoding_addons.scss +10 -2
  209. data/app/presenters/decidim/admin_log/participatory_space/member_presenter.rb +40 -0
  210. data/app/presenters/decidim/admin_log/static_page_resource_presenter.rb +1 -1
  211. data/app/presenters/decidim/authorization_transfer_presenter.rb +1 -1
  212. data/app/presenters/decidim/breadcrumb_root_menu_item_presenter.rb +3 -3
  213. data/app/presenters/decidim/footer_menu_presenter.rb +2 -4
  214. data/app/presenters/decidim/log/user_presenter.rb +1 -0
  215. data/app/presenters/decidim/log/value_types/access_mode_presenter.rb +45 -0
  216. data/app/presenters/decidim/menu_item_presenter.rb +15 -3
  217. data/app/presenters/decidim/participatory_space/member_presenter.rb +48 -0
  218. data/app/presenters/decidim/resource_locator_presenter.rb +22 -3
  219. data/app/presenters/decidim/stats_presenter.rb +1 -1
  220. data/app/queries/decidim/last_activity.rb +1 -1
  221. data/app/resolvers/decidim/meta_image_url_resolver.rb +7 -0
  222. data/app/serializers/decidim/exporters/participatory_space_serializer.rb +15 -1
  223. data/app/services/decidim/email_notification_generator.rb +2 -0
  224. data/app/services/decidim/notification_generator.rb +4 -0
  225. data/app/services/decidim/notifications_subscriptions_persistor.rb +6 -0
  226. data/app/services/decidim/push_subscription_endpoint_validator.rb +34 -0
  227. data/app/services/decidim/send_push_notification.rb +5 -1
  228. data/app/uploaders/decidim/image_uploader.rb +1 -1
  229. data/app/uploaders/decidim/organization_favicon_uploader.rb +4 -9
  230. data/app/validators/uploader_image_dimensions_validator.rb +13 -11
  231. data/app/views/decidim/delete_user_mailer/delete.html.erb +6 -0
  232. data/app/views/decidim/devise/invitations/edit.html.erb +3 -3
  233. data/app/views/decidim/devise/registrations/new.html.erb +1 -0
  234. data/app/views/decidim/devise/shared/_tos_fields.html.erb +3 -3
  235. data/app/views/decidim/gamification/badges/index.html.erb +1 -1
  236. data/app/views/decidim/homepage/show.html.erb +2 -2
  237. data/app/views/decidim/last_activities/index.html.erb +1 -1
  238. data/app/views/decidim/messaging/conversations/_error_modal.html.erb +11 -19
  239. data/app/views/decidim/messaging/conversations/_new_conversation_button.html.erb +1 -1
  240. data/app/views/decidim/messaging/conversations/_reply.html.erb +1 -1
  241. data/app/views/decidim/messaging/conversations/error.js.erb +12 -7
  242. data/app/views/decidim/messaging/conversations/new.html.erb +1 -1
  243. data/app/views/decidim/messaging/conversations/show.html.erb +2 -2
  244. data/app/views/decidim/newsletters/unsubscribe.html.erb +1 -1
  245. data/app/views/decidim/notification_mailer/event_received.html.erb +3 -3
  246. data/app/views/decidim/notifications_settings/show.html.erb +5 -5
  247. data/app/views/decidim/offline/show.html.erb +1 -1
  248. data/app/views/decidim/pages/_tabbed.html.erb +3 -3
  249. data/app/views/decidim/pages/index.html.erb +1 -1
  250. data/app/views/decidim/participatory_space/members/_member.html.erb +1 -0
  251. data/app/views/decidim/profiles/show.html.erb +1 -1
  252. data/app/views/decidim/searches/_filters.html.erb +1 -1
  253. data/app/views/decidim/shared/_filters.html.erb +5 -5
  254. data/app/views/decidim/shared/_resource_actions.html.erb +4 -4
  255. data/app/views/decidim/shared/_results_per_page.html.erb +1 -1
  256. data/app/views/decidim/shared/filters/_check_boxes_tree.html.erb +2 -2
  257. data/app/views/decidim/shared/filters/_collection.html.erb +1 -1
  258. data/app/views/decidim/shared/filters/_dropdown_label.html.erb +4 -3
  259. data/app/views/decidim/user_activities/index.html.erb +1 -1
  260. data/app/views/devise/mailer/{invite_private_user.html.erb → invite_member.html.erb} +2 -2
  261. data/app/views/devise/mailer/{invite_private_user.text.erb → invite_member.text.erb} +2 -2
  262. data/app/views/layouts/decidim/_head.html.erb +2 -2
  263. data/app/views/layouts/decidim/_wrapper.html.erb +3 -3
  264. data/app/views/layouts/decidim/footer/_focus_mode_main.html.erb +0 -1
  265. data/app/views/layouts/decidim/footer/_main.html.erb +1 -2
  266. data/app/views/layouts/decidim/footer/_main_links.html.erb +56 -28
  267. data/app/views/layouts/decidim/header/_focus_mode_back_button.html.erb +4 -1
  268. data/app/views/layouts/decidim/header/_main.html.erb +17 -8
  269. data/app/views/layouts/decidim/header/_main_language_chooser.html.erb +24 -0
  270. data/app/views/layouts/decidim/header/_main_links_desktop.html.erb +56 -56
  271. data/app/views/layouts/decidim/header/_main_links_mobile_account.html.erb +2 -2
  272. data/app/views/layouts/decidim/header/_main_links_mobile_item_account.html.erb +3 -1
  273. data/app/views/layouts/decidim/header/_main_menu_mobile.html.erb +18 -5
  274. data/app/views/layouts/decidim/header/_main_search.html.erb +3 -3
  275. data/app/views/layouts/decidim/header/_menu.html.erb +5 -5
  276. data/app/views/layouts/decidim/header/_menu_breadcrumb_desktop.html.erb +40 -12
  277. data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile.html.erb +33 -0
  278. data/app/views/layouts/decidim/shared/_layout_center.html.erb +1 -1
  279. data/app/views/layouts/decidim/shared/_layout_item.html.erb +1 -1
  280. data/app/views/layouts/decidim/shared/_layout_two_col.html.erb +1 -1
  281. data/config/initializers/decidim_locale_aware_named_route_helper.rb +16 -0
  282. data/config/initializers/devise.rb +6 -0
  283. data/config/initializers/invisible_captcha.rb +1 -0
  284. data/config/locales/ar.yml +6 -38
  285. data/config/locales/bg.yml +3 -39
  286. data/config/locales/ca-IT.yml +91 -58
  287. data/config/locales/ca.yml +91 -58
  288. data/config/locales/cs.yml +54 -58
  289. data/config/locales/de.yml +45 -68
  290. data/config/locales/el.yml +3 -31
  291. data/config/locales/en.yml +88 -55
  292. data/config/locales/es-MX.yml +93 -60
  293. data/config/locales/es-PY.yml +93 -60
  294. data/config/locales/es.yml +95 -62
  295. data/config/locales/eu.yml +124 -92
  296. data/config/locales/fi-plain.yml +93 -55
  297. data/config/locales/fi.yml +96 -58
  298. data/config/locales/fr-CA.yml +70 -52
  299. data/config/locales/fr.yml +71 -54
  300. data/config/locales/ga-IE.yml +3 -1
  301. data/config/locales/gl.yml +3 -31
  302. data/config/locales/hu.yml +7 -40
  303. data/config/locales/id-ID.yml +3 -30
  304. data/config/locales/is-IS.yml +0 -6
  305. data/config/locales/it.yml +15 -33
  306. data/config/locales/ja.yml +105 -71
  307. data/config/locales/lb.yml +3 -33
  308. data/config/locales/lt.yml +4 -37
  309. data/config/locales/lv.yml +3 -30
  310. data/config/locales/nl.yml +3 -33
  311. data/config/locales/no.yml +3 -33
  312. data/config/locales/pl.yml +7 -41
  313. data/config/locales/pt-BR.yml +24 -65
  314. data/config/locales/pt.yml +3 -33
  315. data/config/locales/ro-RO.yml +12 -55
  316. data/config/locales/ru.yml +0 -16
  317. data/config/locales/sk.yml +1417 -32
  318. data/config/locales/sv.yml +44 -62
  319. data/config/locales/tr-TR.yml +20 -37
  320. data/config/locales/uk.yml +0 -9
  321. data/config/locales/zh-CN.yml +3 -30
  322. data/config/locales/zh-TW.yml +4 -35
  323. data/config/routes.rb +140 -76
  324. data/db/data/20251213075429_rename_members_in_action_log.rb +22 -0
  325. data/db/data/20260319145808_rename_send_to_members_in_newsletter.rb +27 -0
  326. data/db/migrate/20200730142511_add_file_upload_settings_to_decidim_organizations.rb +13 -15
  327. data/db/migrate/20250217192438_convert_user_groups_into_users.rb +3 -2
  328. data/db/migrate/20250523104311_move_cta_to_hero_content_block.rb +1 -1
  329. data/db/migrate/20250527122040_move_highlighted_content_banner_settings_to_content_block.rb +1 -1
  330. data/db/migrate/20250819110800_convert_private_exports_id_to_uuid.rb +2 -2
  331. data/db/migrate/20251112132305_remove_legacy_images_from_core_module.rb +27 -0
  332. data/db/migrate/20251205122428_rename_participatory_space_private_users_to_members.rb +9 -0
  333. data/db/migrate/20251216185133_rename_privatable_to_to_participatory_space_in_members.rb +10 -0
  334. data/db/migrate/20260208201405_remove_user_group_core.rb +21 -0
  335. data/db/migrate/20260208201406_remove_user_group_memberships.rb +30 -0
  336. data/db/migrate/20260208201407_remove_user_group_organizations.rb +11 -0
  337. data/db/migrate/20260217152425_remove_enable_participatory_space_filters_from_decidim_organizations.rb +7 -0
  338. data/db/migrate/20260314081619_add_index_on_decidim_members.rb +25 -0
  339. data/decidim-core.gemspec +28 -28
  340. data/lib/decidim/acts_as_tree.rb +12 -12
  341. data/lib/decidim/admin_filters_registry.rb +1 -1
  342. data/lib/decidim/amendable.rb +5 -1
  343. data/lib/decidim/api/functions/category_list.rb +1 -0
  344. data/lib/decidim/api/functions/component_finder_base.rb +1 -1
  345. data/lib/decidim/api/functions/component_list.rb +3 -1
  346. data/lib/decidim/api/functions/component_list_base.rb +1 -0
  347. data/lib/decidim/api/functions/participatory_space_finder_base.rb +1 -1
  348. data/lib/decidim/api/functions/participatory_space_list_base.rb +1 -0
  349. data/lib/decidim/api/functions/user_entity_list.rb +2 -1
  350. data/lib/decidim/api/interfaces/amendable_entity_interface.rb +1 -0
  351. data/lib/decidim/api/interfaces/amendable_interface.rb +1 -0
  352. data/lib/decidim/api/interfaces/attachable_collection_interface.rb +1 -0
  353. data/lib/decidim/api/interfaces/attachable_interface.rb +1 -0
  354. data/lib/decidim/api/interfaces/author_interface.rb +2 -1
  355. data/lib/decidim/api/interfaces/authorable_interface.rb +1 -0
  356. data/lib/decidim/api/interfaces/categories_container_interface.rb +1 -0
  357. data/lib/decidim/api/interfaces/categorizable_interface.rb +1 -0
  358. data/lib/decidim/api/interfaces/coauthorable_interface.rb +1 -0
  359. data/lib/decidim/api/interfaces/component_interface.rb +9 -8
  360. data/lib/decidim/api/interfaces/fingerprint_interface.rb +1 -0
  361. data/lib/decidim/api/interfaces/followable_interface.rb +2 -0
  362. data/lib/decidim/api/interfaces/likeable_interface.rb +2 -2
  363. data/lib/decidim/api/interfaces/localizable_interface.rb +1 -0
  364. data/lib/decidim/api/interfaces/participatory_space_interface.rb +1 -0
  365. data/lib/decidim/api/interfaces/referable_interface.rb +1 -0
  366. data/lib/decidim/api/interfaces/scopable_interface.rb +1 -0
  367. data/lib/decidim/api/interfaces/taxonomizable_interface.rb +1 -0
  368. data/lib/decidim/api/interfaces/timestamps_interface.rb +1 -0
  369. data/lib/decidim/api/interfaces/traceable_interface.rb +1 -0
  370. data/lib/decidim/api/types/attachment_collection_type.rb +5 -3
  371. data/lib/decidim/api/types/attachment_type.rb +11 -4
  372. data/lib/decidim/api/types/badge_score_type.rb +28 -0
  373. data/lib/decidim/api/types/moderation_type.rb +25 -0
  374. data/lib/decidim/api/types/participant_details_type.rb +17 -0
  375. data/lib/decidim/api/types/reportable_type.rb +18 -0
  376. data/lib/decidim/api/types/reportable_user_type.rb +17 -0
  377. data/lib/decidim/api/types/static_page_topic_type.rb +16 -0
  378. data/lib/decidim/api/types/static_page_type.rb +22 -0
  379. data/lib/decidim/api/types/taxonomy_type.rb +2 -0
  380. data/lib/decidim/api/types/user_moderation_type.rb +36 -0
  381. data/lib/decidim/api/types/user_type.rb +13 -0
  382. data/lib/decidim/asset_router/pipeline.rb +1 -1
  383. data/lib/decidim/asset_router/storage.rb +9 -9
  384. data/lib/decidim/assets/tailwind/tailwind.config.js.erb +4 -1
  385. data/lib/decidim/attachment_attributes.rb +58 -9
  386. data/lib/decidim/attribute_encryptor.rb +51 -10
  387. data/lib/decidim/attribute_object/model.rb +0 -5
  388. data/lib/decidim/block_registry.rb +1 -1
  389. data/lib/decidim/coauthorable.rb +2 -1
  390. data/lib/decidim/command.rb +2 -1
  391. data/lib/decidim/content_parsers/blob_parser.rb +3 -3
  392. data/lib/decidim/content_processor.rb +1 -1
  393. data/lib/decidim/content_renderers/base_renderer.rb +112 -0
  394. data/lib/decidim/content_renderers/blob_renderer.rb +6 -9
  395. data/lib/decidim/content_renderers/mention_resource_renderer.rb +10 -6
  396. data/lib/decidim/content_renderers/resource_renderer.rb +16 -7
  397. data/lib/decidim/content_renderers/user_renderer.rb +11 -9
  398. data/lib/decidim/core/api.rb +8 -0
  399. data/lib/decidim/core/content_blocks/registry_manager.rb +4 -10
  400. data/lib/decidim/core/engine.rb +10 -34
  401. data/lib/decidim/core/menu.rb +0 -26
  402. data/lib/decidim/core/test/factories.rb +32 -18
  403. data/lib/decidim/core/test/shared_examples/access_mode_restricted_participatory_spaces.rb +175 -0
  404. data/lib/decidim/core/test/shared_examples/access_mode_transparent_participatory_spaces.rb +244 -0
  405. data/lib/decidim/core/test/shared_examples/admin_resource_gallery_examples.rb +10 -10
  406. data/lib/decidim/core/test/shared_examples/amendable/amendment_event_examples.rb +2 -2
  407. data/lib/decidim/core/test/shared_examples/amendable/amendment_promoted_event_examples.rb +3 -3
  408. data/lib/decidim/core/test/shared_examples/comments_examples.rb +147 -117
  409. data/lib/decidim/core/test/shared_examples/fingerprint_examples.rb +2 -0
  410. data/lib/decidim/core/test/shared_examples/has_members.rb +63 -0
  411. data/lib/decidim/core/test/shared_examples/has_space_in_mcell_examples.rb +2 -1
  412. data/lib/decidim/core/test/shared_examples/manage_share_tokens_examples.rb +1 -1
  413. data/lib/decidim/core/test/shared_examples/map_examples.rb +1 -1
  414. data/lib/decidim/core/test/shared_examples/participant_details_examples.rb +16 -0
  415. data/lib/decidim/core/test/shared_examples/participatory_space_members_page_examples.rb +10 -10
  416. data/lib/decidim/core/test/shared_examples/participatory_space_members_shared_examples.rb +121 -0
  417. data/lib/decidim/core/test/shared_examples/resource_liked_event_examples.rb +3 -3
  418. data/lib/decidim/core/test/shared_examples/resource_locator_presenter_examples.rb +7 -7
  419. data/lib/decidim/core/test/shared_examples/searchable_participatory_space_examples.rb +3 -3
  420. data/lib/decidim/core/test/shared_examples/searchable_results_examples.rb +2 -2
  421. data/lib/decidim/core/test/shared_examples/simple_event.rb +1 -0
  422. data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +2 -2
  423. data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +1 -1
  424. data/lib/decidim/core/test.rb +2 -1
  425. data/lib/decidim/core/version.rb +1 -1
  426. data/lib/decidim/core.rb +222 -335
  427. data/lib/decidim/download_your_data_serializers/{download_your_data_participatory_space_private_user_serializer.rb → download_your_data_member_serializer.rb} +6 -6
  428. data/lib/decidim/download_your_data_serializers.rb +2 -2
  429. data/lib/decidim/engine_router.rb +31 -6
  430. data/lib/decidim/exporters/csv.rb +1 -1
  431. data/lib/decidim/filter_form_builder.rb +1 -1
  432. data/lib/decidim/form_builder.rb +58 -36
  433. data/{app/controllers/concerns → lib}/decidim/form_factory.rb +11 -1
  434. data/lib/decidim/has_settings.rb +2 -2
  435. data/lib/decidim/legacy_form_builder.rb +1 -0
  436. data/lib/decidim/locale_router_detector.rb +41 -0
  437. data/lib/decidim/maintenance/import_models/scope.rb +1 -1
  438. data/lib/decidim/maintenance/import_models.rb +0 -2
  439. data/lib/decidim/maintenance/taxonomy_importer.rb +1 -1
  440. data/lib/decidim/map/autocomplete.rb +4 -3
  441. data/lib/decidim/map/dynamic_map.rb +3 -1
  442. data/lib/decidim/map/frontend.rb +1 -1
  443. data/lib/decidim/map/geocoding.rb +2 -2
  444. data/lib/decidim/map/static_map.rb +10 -22
  445. data/lib/decidim/map/utility.rb +3 -6
  446. data/lib/decidim/map.rb +2 -2
  447. data/lib/decidim/menu.rb +1 -1
  448. data/lib/decidim/menu_item.rb +1 -0
  449. data/lib/decidim/menu_registry.rb +1 -1
  450. data/lib/decidim/moderation_tools.rb +1 -1
  451. data/lib/decidim/newsletter_encryptor.rb +5 -8
  452. data/lib/decidim/organization_settings.rb +2 -2
  453. data/lib/decidim/participable.rb +1 -0
  454. data/lib/decidim/participatory_space/has_members.rb +61 -0
  455. data/lib/decidim/participatory_space_manifest.rb +0 -4
  456. data/lib/decidim/participatory_space_resourceable.rb +10 -1
  457. data/lib/decidim/participatory_space_user.rb +1 -1
  458. data/lib/decidim/routes/locale_redirects.rb +47 -0
  459. data/lib/decidim/routes.rb +7 -0
  460. data/lib/decidim/search_resource_fields_mapper.rb +3 -4
  461. data/lib/decidim/searchable.rb +9 -4
  462. data/lib/decidim/seeds.rb +17 -0
  463. data/lib/decidim/shakapacker/runner.rb +4 -4
  464. data/lib/decidim/shakapacker/shakapacker.yml +28 -3
  465. data/lib/decidim/taxonomizable.rb +1 -1
  466. data/lib/decidim/translatable_attributes.rb +9 -3
  467. data/lib/decidim/view_model.rb +5 -1
  468. data/lib/devise/models/decidim_newsletterable.rb +1 -1
  469. data/lib/tasks/decidim_mailers_tasks.rake +31 -9
  470. data/lib/tasks/decidim_procfile.rake +1 -1
  471. data/lib/tasks/decidim_tasks.rake +0 -1
  472. data/lib/tasks/decidim_taxonomies.rake +1 -1
  473. data/lib/tasks/upgrade/decidim_active_storage_migration_tasks.rake +0 -1
  474. data/lib/tasks/upgrade/decidim_encryption.rake +12 -0
  475. data/lib/tasks/upgrade/decidim_migrate_wysiwyg_content.rake +0 -1
  476. data/lib/tasks/upgrade/decidim_remove_deleted_users_left_data_tasks.rake +1 -1
  477. data/lib/tasks/upgrade/{fix_deleted_private_follows.rake → fix_deleted_members_follows.rake} +5 -5
  478. data/lib/tasks/upgrade/migrations.rake +0 -1
  479. data/lib/tasks/upgrade/user_groups_migration.rake +0 -1
  480. metadata +244 -132
  481. data/app/cells/decidim/content_blocks/global_menu/show.erb +0 -11
  482. data/app/cells/decidim/content_blocks/global_menu_cell.rb +0 -35
  483. data/app/cells/decidim/content_blocks/menu_breadcrumb_last_activity/show.erb +0 -10
  484. data/app/cells/decidim/content_blocks/menu_breadcrumb_last_activity_cell.rb +0 -49
  485. data/app/cells/decidim/participatory_space_dropdown_metadata/links.erb +0 -9
  486. data/app/cells/decidim/participatory_space_dropdown_metadata/metadata.erb +0 -1
  487. data/app/cells/decidim/participatory_space_dropdown_metadata/show.erb +0 -11
  488. data/app/cells/decidim/participatory_space_dropdown_metadata_cell.rb +0 -26
  489. data/app/commands/decidim/gallery_methods.rb +0 -107
  490. data/app/controllers/concerns/decidim/has_members_page.rb +0 -25
  491. data/app/jobs/decidim/newsletters_opt_in_job.rb +0 -11
  492. data/app/jobs/decidim/user_report_job.rb +0 -11
  493. data/app/models/decidim/participatory_space_private_user.rb +0 -51
  494. data/app/packs/src/decidim/controllers/sticky_header/controller.js +0 -116
  495. data/app/packs/src/decidim/controllers/sticky_header/sticky_header.test.js +0 -320
  496. data/app/packs/src/decidim/dropdown_menu.js +0 -18
  497. data/app/packs/src/decidim/identity_selector_dialog.js +0 -33
  498. data/app/packs/src/decidim/vendor/tribute.js +0 -1890
  499. data/app/packs/stylesheets/decidim/_tribute.scss +0 -36
  500. data/app/presenters/decidim/admin_log/participatory_space_private_user_presenter.rb +0 -38
  501. data/app/presenters/decidim/participatory_space_private_user_presenter.rb +0 -46
  502. data/app/views/decidim/participants_account_mailer/removal_notification.html.erb +0 -11
  503. data/app/views/decidim/participatory_space_private_users/_participatory_space_private_user.html.erb +0 -1
  504. data/app/views/layouts/decidim/footer/_main_language_chooser.html.erb +0 -26
  505. data/app/views/layouts/decidim/header/_menu_breadcrumb_items.html.erb +0 -34
  506. data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_desktop.html.erb +0 -10
  507. data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_mobile.html.erb +0 -17
  508. data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_top_left.html.erb +0 -2
  509. data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile_tablet.html.erb +0 -33
  510. data/app/views/layouts/decidim/header/_mobile_language_choose.html.erb +0 -25
  511. data/lib/decidim/core/test/shared_examples/has_private_users.rb +0 -63
  512. data/lib/decidim/core/test/shared_examples/participatory_space_dropdown_metadata_cell_examples.rb +0 -81
  513. data/lib/decidim/has_private_users.rb +0 -57
  514. data/lib/decidim/maintenance/import_models/assembly_type.rb +0 -49
  515. data/lib/decidim/maintenance/import_models/participatory_process_type.rb +0 -21
  516. data/lib/decidim/query_extensions.rb +0 -64
@@ -8,6 +8,7 @@
8
8
  module Decidim
9
9
  class Command
10
10
  include ::Wisper::Publisher
11
+
11
12
  delegate :locale, to: :I18n
12
13
 
13
14
  def self.call(*, **, &)
@@ -53,7 +54,7 @@ module Decidim
53
54
  protected
54
55
 
55
56
  def event_arguments
56
- raise "#{self.class} must implement #event_arguments"
57
+ raise "#{self.class} must implement #event_arguments (passed to #{event_namespace})"
57
58
  end
58
59
 
59
60
  def event_namespace
@@ -34,8 +34,8 @@ module Decidim
34
34
  # Group 6: Variation key for representations
35
35
  /(?<variation_part>[\w.=-]+)
36
36
  )?
37
- # Group 7: Filename
38
- /([\w.=-]+)
37
+ # Group 7: Filename (supports apostrophes inside names but not as HTML quote delimiters)
38
+ /((?:[^\s/"<>']|'(?=[^\s/"<>']))+)
39
39
  }x
40
40
 
41
41
  def rewrite
@@ -55,7 +55,7 @@ module Decidim
55
55
  blob =
56
56
  if type_part == "disk"
57
57
  # Disk service URL
58
- decoded = ActiveStorage.verifier.verified(key_part, purpose: :blob_key).with_indifferent_access
58
+ decoded = ActiveStorage.verifier.verified(key_part, purpose: :blob_key)&.with_indifferent_access
59
59
  ActiveStorage::Blob.find_by(key: decoded[:key]) if decoded
60
60
  else
61
61
  # Representation or blob
@@ -39,7 +39,7 @@ module Decidim
39
39
  # @!attribute rewrite
40
40
  # @return [String] the rewritten content
41
41
  # @!attribute metadata
42
- # @return [Hash<Symbol, Metadata>] a hash where the keys are the parsers
42
+ # @return [Hash{Symbol => Metadata}] a hash where the keys are the parsers
43
43
  # names, and the values are the Metadata object returned by the parser
44
44
  Result = Struct.new(:rewrite, :metadata)
45
45
 
@@ -12,6 +12,16 @@ module Decidim
12
12
  class BaseRenderer
13
13
  include Decidim::ContentProcessor::Common
14
14
 
15
+ ReplacementContext = Struct.new(:placement, :node_name, :attribute_name, :ancestor_names) do
16
+ def text?
17
+ placement == :text
18
+ end
19
+
20
+ def attribute?
21
+ placement == :attribute
22
+ end
23
+ end
24
+
15
25
  # @return [String] the content to be formatted
16
26
  attr_reader :content
17
27
 
@@ -34,6 +44,108 @@ module Decidim
34
44
  def render(_options = nil)
35
45
  content
36
46
  end
47
+
48
+ protected
49
+
50
+ def replace_pattern_by_context(text, pattern, skip_ancestor_tags: %w(code pre script style), on_missing: "")
51
+ return text unless text.respond_to?(:gsub)
52
+
53
+ skip_ancestor_tags = Array(skip_ancestor_tags).map(&:to_s)
54
+
55
+ has_match = pattern.is_a?(String) ? text.include?(pattern) : pattern.match?(text)
56
+ return text unless has_match
57
+
58
+ fragment = html_fragment(text)
59
+ attr_modified = replace_pattern_in_attributes(fragment, pattern, skip_ancestor_tags:, on_missing:) do |match, context|
60
+ yield(match, context)
61
+ end
62
+ text_modified = replace_pattern_in_text_nodes(fragment, pattern, skip_ancestor_tags:, on_missing:) do |match, context|
63
+ yield(match, context)
64
+ end
65
+
66
+ return text unless attr_modified || text_modified
67
+
68
+ fragment.to_s
69
+ end
70
+
71
+ private
72
+
73
+ def replace_pattern_in_attributes(fragment, pattern, skip_ancestor_tags:, on_missing:)
74
+ modified = false
75
+ fragment.xpath(".//*").each do |node|
76
+ next if skip_replacement_for_node?(node, skip_ancestor_tags)
77
+
78
+ node.attribute_nodes.each do |attribute|
79
+ replaced_value = attribute.value.gsub(pattern) do |match|
80
+ replace_match(match, replacement_context(node, placement: :attribute, attribute_name: attribute.name), on_missing:) do |resolved_match, context|
81
+ yield(resolved_match, context)
82
+ end
83
+ end
84
+ unless replaced_value == attribute.value
85
+ attribute.value = replaced_value
86
+ modified = true
87
+ end
88
+ end
89
+ end
90
+ modified
91
+ end
92
+
93
+ def replace_pattern_in_text_nodes(fragment, pattern, skip_ancestor_tags:, on_missing:)
94
+ modified = false
95
+ fragment.xpath(".//text()").each do |node|
96
+ parent = node.parent
97
+ next if skip_replacement_for_node?(parent, skip_ancestor_tags)
98
+
99
+ original_text = node.text
100
+ has_node_match = pattern.is_a?(String) ? original_text.include?(pattern) : pattern.match?(original_text)
101
+ next unless has_node_match
102
+
103
+ doc = node.document
104
+ context = replacement_context(parent, placement: :text)
105
+ last_pos = 0
106
+
107
+ original_text.scan(pattern) do
108
+ m = Regexp.last_match
109
+ node.add_previous_sibling(Nokogiri::XML::Text.new(original_text[last_pos...m.begin(0)], doc)) if m.begin(0) > last_pos
110
+
111
+ replacement = replace_match(m[0], context, on_missing:) do |resolved_match, ctx|
112
+ yield(resolved_match, ctx)
113
+ end
114
+
115
+ Loofah.fragment(replacement.to_s).children.to_a.each do |child|
116
+ node.add_previous_sibling(child)
117
+ end
118
+
119
+ last_pos = m.end(0)
120
+ end
121
+
122
+ node.add_previous_sibling(Nokogiri::XML::Text.new(original_text[last_pos..], doc)) if last_pos < original_text.length
123
+ node.remove
124
+ modified = true
125
+ end
126
+ modified
127
+ end
128
+
129
+ def replace_match(match, context, on_missing:)
130
+ yield(match, context)
131
+ rescue ActiveRecord::RecordNotFound
132
+ on_missing.respond_to?(:call) ? on_missing.call(match, context) : on_missing
133
+ end
134
+
135
+ def replacement_context(node, placement:, attribute_name: nil)
136
+ ReplacementContext.new(
137
+ placement:,
138
+ node_name: node&.name,
139
+ attribute_name:,
140
+ ancestor_names: node ? node.ancestors.map(&:name) : []
141
+ )
142
+ end
143
+
144
+ def skip_replacement_for_node?(node, skip_ancestor_tags)
145
+ return false unless node
146
+
147
+ ([node.name] + node.ancestors.map(&:name)).any? { |name| skip_ancestor_tags.include?(name) }
148
+ end
37
149
  end
38
150
  end
39
151
  end
@@ -18,8 +18,8 @@ module Decidim
18
18
  #
19
19
  # @see BaseRenderer Examples of how to use a content renderer
20
20
  class BlobRenderer < BaseRenderer
21
- # Matches a global id representing a Decidim::User
22
- GLOBAL_ID_REGEX = %r{(gid://[\w-]+/ActiveStorage::Blob/\d+)(/([\w=-]+))?}
21
+ # Matches a global id representing an ActiveStorage::Blob (optionally with a variant key)
22
+ GLOBAL_ID_REGEX = %r{(gid://[\w-]+/ActiveStorage::Blob/\d+)(/([\w=-]+))?(?:[^\s"'<>]*)}
23
23
 
24
24
  # Replaces found Global IDs matching an existing blob with a URL to
25
25
  # that blob. The Global IDs representing an invalid ActiveStorage::Blob
@@ -33,11 +33,10 @@ module Decidim
33
33
  protected
34
34
 
35
35
  def replace_pattern(text, pattern)
36
- return text unless text.respond_to?(:gsub)
37
-
38
- text.gsub(pattern) do
39
- blob_gid = Regexp.last_match(1)
40
- variation_key = Regexp.last_match(3)
36
+ replace_pattern_by_context(text, pattern) do |match, _context|
37
+ match_data = match.match(GLOBAL_ID_REGEX)
38
+ blob_gid = match_data[1]
39
+ variation_key = match_data[3]
41
40
 
42
41
  blob = GlobalID::Locator.locate(blob_gid)
43
42
  if variation_key
@@ -50,8 +49,6 @@ module Decidim
50
49
  else
51
50
  blob_url(blob)
52
51
  end
53
- rescue ActiveRecord::RecordNotFound => _e
54
- ""
55
52
  end
56
53
  end
57
54
 
@@ -27,17 +27,15 @@ module Decidim
27
27
  protected
28
28
 
29
29
  def replace_pattern(text, pattern, editor:)
30
- return text unless text.respond_to?(:gsub)
31
-
32
- text.gsub(pattern) do |resource_gid|
30
+ replace_pattern_by_context(text, pattern) do |resource_gid, context|
33
31
  resource = GlobalID::Locator.locate(resource_gid)
34
- if editor
32
+ if context.attribute?
33
+ render_resource_url(resource, editor:)
34
+ elsif editor
35
35
  render_editor(resource_gid, resource)
36
36
  else
37
37
  render_resource_link(resource)
38
38
  end
39
- rescue ActiveRecord::RecordNotFound => _e
40
- ""
41
39
  end
42
40
  end
43
41
 
@@ -50,6 +48,12 @@ module Decidim
50
48
  link_to mention_title(resource), resource_path(resource)
51
49
  end
52
50
 
51
+ def render_resource_url(resource, editor:)
52
+ return resource_path(resource) if editor
53
+
54
+ Decidim::ResourceLocatorPresenter.new(resource).url
55
+ end
56
+
53
57
  def mention_title(resource)
54
58
  title = presenter_for(resource).title
55
59
 
@@ -11,17 +11,26 @@ module Decidim
11
11
  #
12
12
  # @return [String] the content ready to display (contains HTML)
13
13
  def render(_options = nil)
14
- return content unless content.respond_to?(:gsub)
15
-
16
- content.gsub(regex) do |resource_gid|
14
+ replace_pattern_by_context(content, regex, on_missing: proc { |match, _| "~#{match.split("/").last}" }) do |resource_gid, context|
17
15
  resource = GlobalID::Locator.locate(resource_gid)
18
- resource.presenter.display_mention
19
- rescue ActiveRecord::RecordNotFound
20
- resource_id = resource_gid.split("/").last
21
- "~#{resource_id}"
16
+
17
+ if context.attribute?
18
+ resource_attribute_value(resource)
19
+ else
20
+ resource.presenter.display_mention
21
+ end
22
22
  end
23
23
  end
24
24
 
25
+ protected
26
+
27
+ def resource_attribute_value(resource)
28
+ presenter = resource.presenter
29
+ return presenter.profile_path if presenter.respond_to?(:profile_path)
30
+
31
+ Decidim::ResourceLocatorPresenter.new(resource).path
32
+ end
33
+
25
34
  def regex
26
35
  raise "Not implemented"
27
36
  end
@@ -24,17 +24,15 @@ module Decidim
24
24
  protected
25
25
 
26
26
  def replace_pattern(text, pattern, editor:)
27
- return text unless text.respond_to?(:gsub)
28
-
29
- text.gsub(pattern) do |mentionable_gid|
30
- mentionable = GlobalID::Locator.locate(mentionable_gid)
31
- if editor
32
- render_editor(mentionable)
27
+ replace_pattern_by_context(text, pattern) do |user_gid, context|
28
+ user = GlobalID::Locator.locate(user_gid)
29
+ if context.attribute?
30
+ render_profile_path(user)
31
+ elsif editor
32
+ render_editor(user)
33
33
  else
34
- render_text(mentionable)
34
+ render_text(user)
35
35
  end
36
- rescue ActiveRecord::RecordNotFound => _e
37
- ""
38
36
  end
39
37
  end
40
38
 
@@ -55,6 +53,10 @@ module Decidim
55
53
  presenter_for(user).display_mention
56
54
  end
57
55
  end
56
+
57
+ def render_profile_path(user)
58
+ presenter_for(user).profile_path
59
+ end
58
60
  end
59
61
  end
60
62
  end
@@ -18,6 +18,7 @@ module Decidim
18
18
  autoload :AreaTypeType, "decidim/api/types/area_type_type"
19
19
  autoload :AttachmentType, "decidim/api/types/attachment_type"
20
20
  autoload :AttachmentCollectionType, "decidim/api/types/attachment_collection_type"
21
+ autoload :BadgeScoreType, "decidim/api/types/badge_score_type"
21
22
  autoload :CategoryType, "decidim/api/types/category_type"
22
23
  autoload :TaxonomyType, "decidim/api/types/taxonomy_type"
23
24
  autoload :ComponentType, "decidim/api/types/component_type"
@@ -26,6 +27,7 @@ module Decidim
26
27
  autoload :FingerprintType, "decidim/api/types/fingerprint_type"
27
28
  autoload :LocalizedStringType, "decidim/api/types/localized_string_type"
28
29
  autoload :OrganizationType, "decidim/api/types/organization_type"
30
+ autoload :ParticipantDetailsType, "decidim/api/types/participant_details_type"
29
31
  autoload :ParticipatorySpaceType, "decidim/api/types/participatory_space_type"
30
32
  autoload :ParticipatorySpaceLinkType, "decidim/api/types/participatory_space_link_type"
31
33
  autoload :ParticipatorySpaceManifestType, "decidim/api/types/participatory_space_manifest_type"
@@ -36,6 +38,12 @@ module Decidim
36
38
  autoload :TraceVersionType, "decidim/api/types/trace_version_type"
37
39
  autoload :TranslatedFieldType, "decidim/api/types/translated_field_type"
38
40
  autoload :UserType, "decidim/api/types/user_type"
41
+ autoload :UserModerationType, "decidim/api/types/user_moderation_type"
42
+ autoload :ModerationType, "decidim/api/types/moderation_type"
43
+ autoload :ReportableUserType, "decidim/api/types/reportable_user_type"
44
+ autoload :ReportableType, "decidim/api/types/reportable_type"
45
+ autoload :StaticPageType, "decidim/api/types/static_page_type"
46
+ autoload :StaticPageTopicType, "decidim/api/types/static_page_topic_type"
39
47
 
40
48
  autoload :BaseInputFilter, "decidim/api/input_filters/base_input_filter"
41
49
  autoload :CategoryInputFilter, "decidim/api/input_filters/category_input_filter"
@@ -26,12 +26,6 @@ module Decidim
26
26
  content_block.default!
27
27
  end
28
28
 
29
- Decidim.content_blocks.register(:homepage, :global_menu) do |content_block|
30
- content_block.cell = "decidim/content_blocks/global_menu"
31
- content_block.public_name_key = "decidim.content_blocks.global_menu.name"
32
- content_block.default!
33
- end
34
-
35
29
  Decidim.content_blocks.register(:homepage, :sub_hero) do |content_block|
36
30
  content_block.cell = "decidim/content_blocks/sub_hero"
37
31
  content_block.public_name_key = "decidim.content_blocks.sub_hero.name"
@@ -51,11 +45,11 @@ module Decidim
51
45
  ]
52
46
 
53
47
  content_block.settings do |settings|
54
- settings.attribute :title, type: :text, translated: true
48
+ settings.attribute :title, type: :text, translated: true, required: true
55
49
  settings.attribute :short_description, type: :text, translated: true
56
- settings.attribute :action_button_title, type: :text, translated: true
57
- settings.attribute :action_button_subtitle, type: :text, translated: true
58
- settings.attribute :action_button_url, type: :text
50
+ settings.attribute :action_button_title, type: :text, translated: true, required: true
51
+ settings.attribute :action_button_subtitle, type: :text, translated: true, required: true
52
+ settings.attribute :action_button_url, type: :text, required: true
59
53
  end
60
54
 
61
55
  content_block.default!
@@ -241,31 +241,11 @@ module Decidim
241
241
  ENV["SHAKAPACKER_CONFIG"] = Decidim::Shakapacker.configuration.configuration_file
242
242
  end
243
243
 
244
- # Rails 7.0 default is vips, but
245
- # The `:mini_magick` option is not deprecated; it is fine to keep using it.
246
- # And we are going to use it while migrating rails application
247
- initializer "decidim_core.active_storage_variant_processor" do |app|
248
- app.config.active_storage.variant_processor = :mini_magick
249
- end
250
-
251
244
  initializer "decidim_core.setup_i18n" do |app|
252
245
  app.config.i18n.available_locales = Decidim.available_locales
253
246
  app.config.i18n.default_locale = Decidim.default_locale
254
- end
255
-
256
- initializer "decidim_core.active_storage_method_patch" do |_app|
257
- if Rails::VERSION::MAJOR < 8
258
- # This is a manual bugfix of https://github.com/rails/rails/pull/51931
259
- module Attachment
260
- def named_variants
261
- record.attachment_reflections[name]&.named_variants || {}
262
- end
263
- end
264
-
265
- ActiveSupport.on_load(:active_storage_attachment) { prepend Attachment }
266
- else
267
- Decidim.deprecator.warn("Remove decidim_core.active_storage_method_patch initializer from #{__FILE__}")
268
- end
247
+ app.config.i18n.fallbacks = true
248
+ app.config.i18n.raise_on_missing_translations = Rails.env.local?
269
249
  end
270
250
 
271
251
  initializer "decidim_core.action_controller" do |_app|
@@ -362,13 +342,7 @@ module Decidim
362
342
  end
363
343
  end
364
344
 
365
- initializer "decidim_core.locales" do |app|
366
- app.config.i18n.fallbacks = true
367
- end
368
-
369
345
  initializer "decidim_core.graphql_api" do
370
- Decidim::Api::QueryType.include Decidim::QueryExtensions
371
-
372
346
  Decidim::Api.add_orphan_type Decidim::Core::UserType
373
347
  end
374
348
 
@@ -396,10 +370,6 @@ module Decidim
396
370
  end
397
371
  end
398
372
 
399
- initializer "decidim_core.i18n_exceptions" do |app|
400
- app.config.i18n.raise_on_missing_translations = true unless Rails.env.production?
401
- end
402
-
403
373
  initializer "decidim_core.geocoding", after: :load_config_initializers do
404
374
  Geocoder.configure(Decidim.geocoder) if Decidim.geocoder.present?
405
375
  end
@@ -471,8 +441,6 @@ module Decidim
471
441
  end
472
442
 
473
443
  initializer "decidim_core.menu" do
474
- Decidim::Core::Menu.register_menu!
475
- Decidim::Core::Menu.register_mobile_menu!
476
444
  Decidim::Core::Menu.register_user_menu!
477
445
  end
478
446
 
@@ -495,6 +463,14 @@ module Decidim
495
463
  end
496
464
  end
497
465
 
466
+ initializer "decidim_core.delete_account" do
467
+ config.to_prepare do
468
+ ActiveSupport::Notifications.subscribe("decidim.destroy_account:after") do |_event_name, data|
469
+ Decidim::DeleteUserMailer.delete(user_email: data[:user_email], user_name: data[:user_name], locale: data[:locale], organization: data[:organization]).deliver_later
470
+ end
471
+ end
472
+ end
473
+
498
474
  initializer "decidim_core.add_cells_view_paths" do
499
475
  Cell::ViewModel.view_paths << Rails.root.join("app/views") # for partials
500
476
  Cell::ViewModel.view_paths << File.expand_path("#{Decidim::Core::Engine.root}/app/cells")
@@ -3,32 +3,6 @@
3
3
  module Decidim
4
4
  module Core
5
5
  class Menu
6
- def self.register_menu!
7
- Decidim.menu :menu do |menu|
8
- menu.add_item :root,
9
- I18n.t("menu.home", scope: "decidim"),
10
- decidim.root_path,
11
- position: 1,
12
- active: :exclusive
13
- end
14
- end
15
-
16
- def self.register_mobile_menu!
17
- Decidim.menu :mobile_menu do |menu|
18
- menu.add_item :root,
19
- I18n.t("menu.home", scope: "decidim"),
20
- decidim.root_path,
21
- position: 1,
22
- active: :exclusive
23
-
24
- menu.add_item :help,
25
- I18n.t("menu.help", scope: "decidim"),
26
- decidim.pages_path,
27
- position: 10,
28
- active: :exclusive
29
- end
30
- end
31
-
32
6
  def self.register_user_menu!
33
7
  Decidim.menu :user_menu do |menu|
34
8
  menu.add_item :account,
@@ -85,6 +85,8 @@ FactoryBot.define do
85
85
  "#{Faker::Lorem.sentence(word_count: 1, supplemental: true, random_words_to_add: 3)} #{n}"
86
86
  end
87
87
 
88
+ sequence(:component_position)
89
+
88
90
  factory :category, class: "Decidim::Category" do
89
91
  transient do
90
92
  skip_injection { false }
@@ -155,7 +157,6 @@ FactoryBot.define do
155
157
  }
156
158
  end
157
159
  file_upload_settings { Decidim::OrganizationSettings.default(:upload) }
158
- enable_participatory_space_filters { true }
159
160
  content_security_policy do
160
161
  {
161
162
  "default-src" => "localhost:* #{host}:*",
@@ -200,7 +201,7 @@ FactoryBot.define do
200
201
  tos_agreement { "1" }
201
202
  avatar { Decidim::Dev.test_file("avatar.jpg", "image/jpeg") }
202
203
  personal_url { Faker::Internet.url }
203
- about { generate_localized_title(:user_about, skip_injection:) }
204
+ about { generate_title(:user_about, skip_injection:) }
204
205
  confirmation_sent_at { Time.current }
205
206
  accepted_tos_version { organization.tos_version }
206
207
  notifications_sending_frequency { "real_time" }
@@ -284,12 +285,18 @@ FactoryBot.define do
284
285
  end
285
286
  end
286
287
 
287
- factory :participatory_space_private_user, class: "Decidim::ParticipatorySpacePrivateUser" do
288
+ factory :badge_score, class: "Decidim::Gamification::BadgeScore" do
289
+ user
290
+ badge_name { "followers" }
291
+ value { 1 }
292
+ end
293
+
294
+ factory :member, class: "Decidim::ParticipatorySpace::Member" do
288
295
  transient do
289
296
  skip_injection { false }
290
297
  end
291
298
  user
292
- privatable_to { create(:participatory_process, organization: user.organization, skip_injection:) }
299
+ participatory_space { create(:participatory_process, organization: user.organization, skip_injection:) }
293
300
 
294
301
  role { generate_localized_title(:role, skip_injection:) }
295
302
 
@@ -302,12 +309,13 @@ FactoryBot.define do
302
309
  end
303
310
  end
304
311
 
305
- factory :assembly_private_user, class: "Decidim::ParticipatorySpacePrivateUser" do
312
+ factory :assembly_member, class: "Decidim::ParticipatorySpace::Member" do
306
313
  transient do
307
314
  skip_injection { false }
315
+ organization { create(:organization, skip_injection:) }
308
316
  end
309
- user
310
- privatable_to { create(:assembly, organization: user.organization, skip_injection:) }
317
+ user { create(:user, :confirmed, organization:, skip_injection:) }
318
+ participatory_space { create(:assembly, organization:, skip_injection:) }
311
319
  end
312
320
 
313
321
  factory :identity, class: "Decidim::Identity" do
@@ -463,6 +471,7 @@ FactoryBot.define do
463
471
  manifest_name { "dummy" }
464
472
  published_at { Time.current }
465
473
  deleted_at { nil }
474
+ weight { generate(:component_position) }
466
475
  settings do
467
476
  {
468
477
  dummy_global_translatable_text: generate_localized_title(:dummy_global_translatable_text, skip_injection:),
@@ -630,8 +639,11 @@ FactoryBot.define do
630
639
  end
631
640
 
632
641
  factory :taxonomization, class: "Decidim::Taxonomization" do
642
+ transient do
643
+ skip_injection { false }
644
+ end
633
645
  taxonomy { association(:taxonomy, :with_parent) }
634
- taxonomizable { association(:dummy_resource) }
646
+ taxonomizable { association(:dummy_resource, organization: taxonomy.organization, skip_injection:) }
635
647
  end
636
648
 
637
649
  factory :taxonomy_filter, class: "Decidim::TaxonomyFilter" do
@@ -651,7 +663,7 @@ FactoryBot.define do
651
663
 
652
664
  factory :taxonomy_filter_item, class: "Decidim::TaxonomyFilterItem" do
653
665
  taxonomy_filter
654
- taxonomy_item { association(:taxonomy, parent: taxonomy_filter.root_taxonomy) }
666
+ taxonomy_item { association(:taxonomy, organization: taxonomy_filter.root_taxonomy.organization, parent: taxonomy_filter.root_taxonomy) }
655
667
  end
656
668
 
657
669
  factory :coauthorship, class: "Decidim::Coauthorship" do
@@ -719,7 +731,7 @@ FactoryBot.define do
719
731
  skip_injection { false }
720
732
  end
721
733
  moderation
722
- user { build(:user, organization: moderation.reportable.organization, skip_injection:) }
734
+ user { build(:user, :confirmed, organization: moderation.reportable.organization, skip_injection:) }
723
735
  reason { "spam" }
724
736
  end
725
737
 
@@ -739,6 +751,7 @@ FactoryBot.define do
739
751
  user do
740
752
  build(
741
753
  :user,
754
+ :confirmed,
742
755
  organization: followable.try(:organization) || build(:organization, skip_injection:)
743
756
  )
744
757
  end
@@ -775,8 +788,8 @@ FactoryBot.define do
775
788
  skip_injection { false }
776
789
  end
777
790
 
778
- originator { build(:user, skip_injection:) }
779
- interlocutors { [build(:user, skip_injection:)] }
791
+ originator { build(:user, organization: user.organization, skip_injection:) }
792
+ interlocutors { [build(:user, organization: originator.organization, skip_injection:)] }
780
793
  body { Faker::Lorem.sentence }
781
794
  user
782
795
 
@@ -821,8 +834,8 @@ FactoryBot.define do
821
834
 
822
835
  user { create(:user) }
823
836
  organization { user.organization }
824
- user_id { user.id }
825
- user_type { user.class.name }
837
+ user_id { user.try(:id) }
838
+ user_type { user.try(:class).try(:name) }
826
839
  participatory_space { build(:participatory_process, organization:, skip_injection:) }
827
840
  component { build(:component, participatory_space:, skip_injection:) }
828
841
  resource { build(:dummy_resource, component:, skip_injection:) }
@@ -939,9 +952,10 @@ FactoryBot.define do
939
952
  factory :amendment, class: "Decidim::Amendment" do
940
953
  transient do
941
954
  skip_injection { false }
955
+ organization { create(:organization, skip_injection:) }
942
956
  end
943
- amendable { build(:dummy_resource, skip_injection:) }
944
- emendation { build(:dummy_resource, skip_injection:) }
957
+ amendable { build(:dummy_resource, organization:, skip_injection:) }
958
+ emendation { build(:dummy_resource, organization:, skip_injection:) }
945
959
  amender { emendation.try(:creator_author) || emendation.try(:author) }
946
960
  state { "evaluating" }
947
961
 
@@ -974,7 +988,7 @@ FactoryBot.define do
974
988
  end
975
989
  reason { "spam" }
976
990
  moderation { create(:user_moderation, user:, skip_injection:) }
977
- user { build(:user) }
991
+ user { build(:user, :confirmed) }
978
992
  end
979
993
 
980
994
  factory :user_moderation, class: "Decidim::UserModeration" do
@@ -1039,7 +1053,7 @@ FactoryBot.define do
1039
1053
  skip_injection { false }
1040
1054
  end
1041
1055
  reminder { create(:reminder, skip_injection:) }
1042
- remindable { build(:dummy_resource, skip_injection:) }
1056
+ remindable { build(:dummy_resource, organization: reminder.user.organization, skip_injection:) }
1043
1057
 
1044
1058
  Decidim::ReminderRecord::STATES.keys.each do |defined_state|
1045
1059
  trait defined_state do