decidim-core 0.31.5 → 0.32.0.rc2

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 (361) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -13
  3. data/app/cells/decidim/amendable/amend_button_card_cell.rb +1 -1
  4. data/app/cells/decidim/content_blocks/announcement_settings_form/show.erb +5 -0
  5. data/app/cells/decidim/content_blocks/announcement_settings_form_cell.rb +17 -0
  6. data/app/cells/decidim/content_blocks/how_to_participate/show.erb +1 -1
  7. data/app/cells/decidim/content_blocks/participatory_space_announcement_cell.rb +1 -3
  8. data/app/cells/decidim/content_blocks/participatory_space_hero_cell.rb +1 -5
  9. data/app/cells/decidim/{participatory_space_private_user_cell.rb → member_cell.rb} +1 -1
  10. data/app/cells/decidim/onboarding_action_message_cell.rb +1 -0
  11. data/app/cells/decidim/profile/details.erb +1 -1
  12. data/app/cells/decidim/profile_cell.rb +1 -0
  13. data/app/cells/decidim/profile_member_of/show.erb +13 -0
  14. data/app/cells/decidim/profile_member_of_cell.rb +35 -0
  15. data/app/cells/decidim/tags_cell.rb +1 -1
  16. data/app/cells/decidim/versions_list/show.erb +25 -0
  17. data/app/commands/decidim/create_follow.rb +3 -5
  18. data/app/commands/decidim/create_user_report.rb +1 -1
  19. data/app/commands/decidim/destroy_account.rb +3 -3
  20. data/app/commands/decidim/search.rb +5 -5
  21. data/app/controllers/concerns/decidim/ajax_permission_handler.rb +1 -1
  22. data/app/controllers/concerns/decidim/direct_upload.rb +3 -2
  23. data/app/controllers/concerns/decidim/ephemeral_session_checker.rb +1 -1
  24. data/app/controllers/concerns/decidim/force_authentication.rb +10 -1
  25. data/app/controllers/concerns/decidim/impersonate_users.rb +4 -0
  26. data/app/controllers/concerns/decidim/locale_switcher.rb +52 -2
  27. data/app/controllers/concerns/decidim/needs_tos_accepted.rb +1 -1
  28. data/app/controllers/concerns/decidim/participatory_space/has_members_page.rb +27 -0
  29. data/app/controllers/concerns/decidim/participatory_space_context.rb +1 -5
  30. data/app/controllers/decidim/account_controller.rb +1 -1
  31. data/app/controllers/decidim/amendments_controller.rb +5 -4
  32. data/app/controllers/decidim/components/base_controller.rb +20 -3
  33. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +1 -1
  34. data/app/controllers/decidim/devise/passwords_controller.rb +1 -1
  35. data/app/controllers/decidim/devise/registrations_controller.rb +1 -1
  36. data/app/controllers/decidim/devise/sessions_controller.rb +1 -1
  37. data/app/controllers/decidim/download_your_data_controller.rb +1 -1
  38. data/app/controllers/decidim/editor_images_controller.rb +1 -1
  39. data/app/controllers/decidim/follows_controller.rb +4 -3
  40. data/app/controllers/decidim/geolocation_controller.rb +1 -1
  41. data/app/controllers/decidim/likes_controller.rb +2 -1
  42. data/app/controllers/decidim/locales_controller.rb +3 -11
  43. data/app/controllers/decidim/messaging/conversations_controller.rb +3 -3
  44. data/app/controllers/decidim/newsletters_controller.rb +1 -1
  45. data/app/controllers/decidim/notifications_settings_controller.rb +1 -1
  46. data/app/controllers/decidim/notifications_subscriptions_controller.rb +1 -1
  47. data/app/controllers/decidim/open_data_controller.rb +1 -1
  48. data/app/controllers/decidim/report_users_controller.rb +2 -2
  49. data/app/controllers/decidim/reports_controller.rb +1 -1
  50. data/app/controllers/decidim/user_activities_controller.rb +1 -2
  51. data/app/events/decidim/welcome_notification_event.rb +1 -1
  52. data/app/forms/decidim/upload_validation_form.rb +1 -1
  53. data/app/helpers/concerns/decidim/flash_helper_extensions.rb +1 -0
  54. data/app/helpers/decidim/active_link_to_helper.rb +136 -0
  55. data/app/helpers/decidim/amendments_helper.rb +3 -3
  56. data/app/helpers/decidim/check_boxes_tree_helper.rb +2 -2
  57. data/app/helpers/decidim/component_path_helper.rb +9 -4
  58. data/app/helpers/decidim/filters_helper.rb +0 -2
  59. data/app/helpers/decidim/menu_helper.rb +3 -3
  60. data/app/helpers/decidim/meta_tags_helper.rb +0 -2
  61. data/app/helpers/decidim/paginate_helper.rb +14 -1
  62. data/app/helpers/decidim/sanitize_helper.rb +1 -0
  63. data/app/helpers/decidim/short_link_helper.rb +5 -5
  64. data/app/helpers/decidim/translations_helper.rb +4 -4
  65. data/app/jobs/decidim/delete_inactive_participants_job.rb +2 -2
  66. data/app/mailers/decidim/application_mailer.rb +7 -2
  67. data/app/mailers/decidim/decidim_devise_mailer.rb +1 -0
  68. data/app/mailers/decidim/reported_mailer.rb +4 -1
  69. data/app/models/decidim/action_log.rb +1 -1
  70. data/app/models/decidim/attachment.rb +2 -2
  71. data/app/models/decidim/authorization_transfer.rb +1 -1
  72. data/app/models/decidim/component.rb +6 -9
  73. data/app/models/decidim/content_block.rb +3 -3
  74. data/app/models/decidim/newsletter.rb +2 -2
  75. data/app/models/decidim/participatory_space/member.rb +55 -0
  76. data/app/models/decidim/resource_link.rb +1 -1
  77. data/app/models/decidim/short_link.rb +1 -1
  78. data/app/packs/src/decidim/controllers/assign_role/assign_role.test.js +80 -0
  79. data/app/packs/src/decidim/controllers/assign_role/controller.js +27 -0
  80. data/app/packs/src/decidim/controllers/main_menu/controller.js +115 -0
  81. data/app/packs/src/decidim/controllers/main_menu/main_menu.test.js +185 -0
  82. data/app/packs/src/decidim/datepicker/generate_datepicker.js +1 -13
  83. data/app/packs/src/decidim/editor/common/suggestion.js +1 -1
  84. data/app/packs/src/decidim/editor/extensions/decidim_kit/index.js +4 -1
  85. data/app/packs/src/decidim/editor/extensions/image/index.js +8 -5
  86. data/app/packs/src/decidim/editor/extensions/link/index.js +8 -0
  87. data/app/packs/src/decidim/editor/extensions/mention/index.js +18 -5
  88. data/app/packs/src/decidim/editor/extensions/mention_resource/index.js +16 -7
  89. data/app/packs/src/decidim/editor/test/extensions/decidim_kit.test.js +13 -4
  90. data/app/packs/src/decidim/editor/test/extensions/heading.test.js +1 -1
  91. data/app/packs/src/decidim/editor/test/extensions/image.test.js +26 -28
  92. data/app/packs/src/decidim/editor/test/extensions/mention.test.js +6 -2
  93. data/app/packs/src/decidim/editor/test/extensions/video_embed.test.js +27 -15
  94. data/app/packs/src/decidim/editor/test/helpers.js +8 -10
  95. data/app/packs/src/decidim/editor/test/toolbar/full.test.js +15 -4
  96. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_block.js +8 -4
  97. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_formatting.js +5 -1
  98. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_indent.js +9 -5
  99. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_link.js +5 -1
  100. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_list.js +8 -4
  101. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_basic_styling.js +13 -9
  102. data/app/packs/src/decidim/editor/test/toolbar/shared/behaves_like_content_styling.js +6 -2
  103. data/app/packs/src/decidim/index.js +0 -1
  104. data/app/packs/stylesheets/decidim/_cards.scss +2 -1
  105. data/app/packs/stylesheets/decidim/_datepicker.scss +0 -8
  106. data/app/packs/stylesheets/decidim/_dropdown.scss +21 -31
  107. data/app/packs/stylesheets/decidim/_footer.scss +0 -36
  108. data/app/packs/stylesheets/decidim/_forms.scss +5 -1
  109. data/app/packs/stylesheets/decidim/_header.scss +148 -46
  110. data/app/packs/stylesheets/decidim/_language_chooser.scss +79 -0
  111. data/app/packs/stylesheets/decidim/application.scss +1 -0
  112. data/app/presenters/decidim/admin_log/participatory_space/member_presenter.rb +40 -0
  113. data/app/presenters/decidim/admin_log/static_page_resource_presenter.rb +1 -1
  114. data/app/presenters/decidim/authorization_transfer_presenter.rb +1 -1
  115. data/app/presenters/decidim/breadcrumb_root_menu_item_presenter.rb +3 -3
  116. data/app/presenters/decidim/log/user_presenter.rb +1 -0
  117. data/app/presenters/decidim/log/value_types/access_mode_presenter.rb +45 -0
  118. data/app/presenters/decidim/participatory_space/member_presenter.rb +48 -0
  119. data/app/presenters/decidim/resource_locator_presenter.rb +22 -3
  120. data/app/queries/decidim/last_activity.rb +1 -1
  121. data/app/serializers/decidim/exporters/participatory_space_serializer.rb +15 -1
  122. data/app/services/decidim/email_notification_generator.rb +2 -0
  123. data/app/services/decidim/notification_generator.rb +4 -0
  124. data/app/uploaders/decidim/organization_favicon_uploader.rb +4 -9
  125. data/app/validators/uploader_image_dimensions_validator.rb +13 -11
  126. data/app/views/decidim/homepage/show.html.erb +1 -1
  127. data/app/views/decidim/messaging/conversations/_new_conversation_button.html.erb +1 -1
  128. data/app/views/decidim/messaging/conversations/_reply.html.erb +1 -1
  129. data/app/views/decidim/messaging/conversations/new.html.erb +1 -1
  130. data/app/views/decidim/messaging/conversations/show.html.erb +2 -2
  131. data/app/views/decidim/participatory_space/members/_member.html.erb +1 -0
  132. data/app/views/decidim/shared/_results_per_page.html.erb +1 -1
  133. data/app/views/decidim/shared/filters/_check_boxes_tree.html.erb +1 -1
  134. data/app/views/decidim/shared/filters/_dropdown_label.html.erb +4 -3
  135. data/app/views/devise/mailer/{invite_private_user.html.erb → invite_member.html.erb} +2 -2
  136. data/app/views/devise/mailer/{invite_private_user.text.erb → invite_member.text.erb} +2 -2
  137. data/app/views/layouts/decidim/_head.html.erb +2 -2
  138. data/app/views/layouts/decidim/_wrapper.html.erb +1 -1
  139. data/app/views/layouts/decidim/footer/_focus_mode_main.html.erb +0 -1
  140. data/app/views/layouts/decidim/footer/_main.html.erb +0 -1
  141. data/app/views/layouts/decidim/header/_focus_mode_back_button.html.erb +4 -1
  142. data/app/views/layouts/decidim/header/_main.html.erb +17 -8
  143. data/app/views/layouts/decidim/header/_main_language_chooser.html.erb +24 -0
  144. data/app/views/layouts/decidim/header/_main_links_desktop.html.erb +56 -56
  145. data/app/views/layouts/decidim/header/_main_links_mobile_account.html.erb +2 -2
  146. data/app/views/layouts/decidim/header/_main_links_mobile_item_account.html.erb +3 -1
  147. data/app/views/layouts/decidim/header/_main_menu_mobile.html.erb +18 -5
  148. data/app/views/layouts/decidim/header/_main_search.html.erb +3 -3
  149. data/app/views/layouts/decidim/header/_menu.html.erb +5 -5
  150. data/app/views/layouts/decidim/header/_menu_breadcrumb_desktop.html.erb +13 -12
  151. data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile.html.erb +28 -0
  152. data/config/initializers/invisible_captcha.rb +1 -0
  153. data/config/locales/ar.yml +3 -10
  154. data/config/locales/bg.yml +3 -10
  155. data/config/locales/ca-IT.yml +33 -19
  156. data/config/locales/ca.yml +33 -19
  157. data/config/locales/cs.yml +22 -19
  158. data/config/locales/de.yml +13 -18
  159. data/config/locales/el.yml +3 -7
  160. data/config/locales/en.yml +33 -19
  161. data/config/locales/es-MX.yml +33 -19
  162. data/config/locales/es-PY.yml +33 -19
  163. data/config/locales/es.yml +33 -19
  164. data/config/locales/eu.yml +33 -19
  165. data/config/locales/fi-plain.yml +33 -19
  166. data/config/locales/fi.yml +33 -19
  167. data/config/locales/fr-CA.yml +33 -19
  168. data/config/locales/fr.yml +33 -19
  169. data/config/locales/ga-IE.yml +3 -1
  170. data/config/locales/gl.yml +3 -7
  171. data/config/locales/hu.yml +3 -10
  172. data/config/locales/id-ID.yml +3 -7
  173. data/config/locales/it.yml +3 -10
  174. data/config/locales/ja.yml +18 -19
  175. data/config/locales/lb.yml +3 -8
  176. data/config/locales/lt.yml +3 -10
  177. data/config/locales/lv.yml +3 -7
  178. data/config/locales/nl.yml +3 -8
  179. data/config/locales/no.yml +3 -8
  180. data/config/locales/pl.yml +3 -10
  181. data/config/locales/pt-BR.yml +17 -19
  182. data/config/locales/pt.yml +3 -8
  183. data/config/locales/ro-RO.yml +10 -18
  184. data/config/locales/ru.yml +0 -6
  185. data/config/locales/sk.yml +33 -19
  186. data/config/locales/sv.yml +33 -19
  187. data/config/locales/tr-TR.yml +3 -8
  188. data/config/locales/uk.yml +0 -3
  189. data/config/locales/zh-CN.yml +3 -7
  190. data/config/locales/zh-TW.yml +3 -8
  191. data/config/routes.rb +139 -76
  192. data/db/data/20251213075429_rename_members_in_action_log.rb +22 -0
  193. data/db/data/20260319145808_rename_send_to_members_in_newsletter.rb +27 -0
  194. data/db/migrate/20200730142511_add_file_upload_settings_to_decidim_organizations.rb +13 -15
  195. data/db/migrate/20250523104311_move_cta_to_hero_content_block.rb +1 -1
  196. data/db/migrate/20250527122040_move_highlighted_content_banner_settings_to_content_block.rb +1 -1
  197. data/db/migrate/20250819110800_convert_private_exports_id_to_uuid.rb +2 -2
  198. data/db/migrate/20251112132305_remove_legacy_images_from_core_module.rb +27 -0
  199. data/db/migrate/20251205122428_rename_participatory_space_private_users_to_members.rb +9 -0
  200. data/db/migrate/20251216185133_rename_privatable_to_to_participatory_space_in_members.rb +10 -0
  201. data/db/migrate/20260208201405_remove_user_group_core.rb +21 -0
  202. data/db/migrate/20260208201406_remove_user_group_memberships.rb +30 -0
  203. data/db/migrate/20260208201407_remove_user_group_organizations.rb +11 -0
  204. data/db/migrate/20260217152425_remove_enable_participatory_space_filters_from_decidim_organizations.rb +7 -0
  205. data/db/migrate/20260314081619_add_index_on_decidim_members.rb +25 -0
  206. data/decidim-core.gemspec +25 -28
  207. data/lib/decidim/acts_as_tree.rb +12 -12
  208. data/lib/decidim/admin_filters_registry.rb +1 -1
  209. data/lib/decidim/amendable.rb +5 -1
  210. data/lib/decidim/api/functions/category_list.rb +1 -0
  211. data/lib/decidim/api/functions/component_finder_base.rb +1 -1
  212. data/lib/decidim/api/functions/component_list.rb +3 -1
  213. data/lib/decidim/api/functions/component_list_base.rb +1 -0
  214. data/lib/decidim/api/functions/participatory_space_finder_base.rb +1 -1
  215. data/lib/decidim/api/functions/participatory_space_list_base.rb +1 -0
  216. data/lib/decidim/api/functions/user_entity_list.rb +0 -1
  217. data/lib/decidim/api/interfaces/amendable_entity_interface.rb +1 -0
  218. data/lib/decidim/api/interfaces/amendable_interface.rb +1 -0
  219. data/lib/decidim/api/interfaces/attachable_collection_interface.rb +1 -0
  220. data/lib/decidim/api/interfaces/attachable_interface.rb +1 -0
  221. data/lib/decidim/api/interfaces/author_interface.rb +2 -1
  222. data/lib/decidim/api/interfaces/authorable_interface.rb +1 -0
  223. data/lib/decidim/api/interfaces/categories_container_interface.rb +1 -0
  224. data/lib/decidim/api/interfaces/categorizable_interface.rb +1 -0
  225. data/lib/decidim/api/interfaces/coauthorable_interface.rb +1 -0
  226. data/lib/decidim/api/interfaces/component_interface.rb +9 -8
  227. data/lib/decidim/api/interfaces/fingerprint_interface.rb +1 -0
  228. data/lib/decidim/api/interfaces/followable_interface.rb +2 -0
  229. data/lib/decidim/api/interfaces/likeable_interface.rb +2 -2
  230. data/lib/decidim/api/interfaces/localizable_interface.rb +1 -0
  231. data/lib/decidim/api/interfaces/participatory_space_interface.rb +1 -0
  232. data/lib/decidim/api/interfaces/referable_interface.rb +1 -0
  233. data/lib/decidim/api/interfaces/scopable_interface.rb +1 -0
  234. data/lib/decidim/api/interfaces/taxonomizable_interface.rb +1 -0
  235. data/lib/decidim/api/interfaces/timestamps_interface.rb +1 -0
  236. data/lib/decidim/api/interfaces/traceable_interface.rb +1 -0
  237. data/lib/decidim/api/types/attachment_collection_type.rb +5 -3
  238. data/lib/decidim/api/types/attachment_type.rb +11 -4
  239. data/lib/decidim/api/types/badge_score_type.rb +28 -0
  240. data/lib/decidim/api/types/moderation_type.rb +25 -0
  241. data/lib/decidim/api/types/participant_details_type.rb +17 -0
  242. data/lib/decidim/api/types/reportable_type.rb +18 -0
  243. data/lib/decidim/api/types/reportable_user_type.rb +17 -0
  244. data/lib/decidim/api/types/static_page_topic_type.rb +16 -0
  245. data/lib/decidim/api/types/static_page_type.rb +22 -0
  246. data/lib/decidim/api/types/taxonomy_type.rb +2 -0
  247. data/lib/decidim/api/types/user_moderation_type.rb +36 -0
  248. data/lib/decidim/api/types/user_type.rb +13 -0
  249. data/lib/decidim/asset_router/pipeline.rb +1 -1
  250. data/lib/decidim/asset_router/storage.rb +9 -9
  251. data/lib/decidim/assets/tailwind/tailwind.config.js.erb +3 -0
  252. data/lib/decidim/attribute_encryptor.rb +51 -10
  253. data/lib/decidim/attribute_object/model.rb +0 -5
  254. data/lib/decidim/block_registry.rb +1 -1
  255. data/lib/decidim/coauthorable.rb +2 -1
  256. data/lib/decidim/command.rb +1 -0
  257. data/lib/decidim/content_processor.rb +1 -1
  258. data/lib/decidim/core/api.rb +8 -0
  259. data/lib/decidim/core/content_blocks/registry_manager.rb +0 -6
  260. data/lib/decidim/core/engine.rb +2 -34
  261. data/lib/decidim/core/menu.rb +0 -26
  262. data/lib/decidim/core/test/factories.rb +29 -18
  263. data/lib/decidim/core/test/shared_examples/access_mode_restricted_participatory_spaces.rb +172 -0
  264. data/lib/decidim/core/test/shared_examples/access_mode_transparent_participatory_spaces.rb +241 -0
  265. data/lib/decidim/core/test/shared_examples/comments_examples.rb +115 -111
  266. data/lib/decidim/core/test/shared_examples/fingerprint_examples.rb +2 -0
  267. data/lib/decidim/core/test/shared_examples/has_members.rb +63 -0
  268. data/lib/decidim/core/test/shared_examples/manage_share_tokens_examples.rb +1 -1
  269. data/lib/decidim/core/test/shared_examples/map_examples.rb +1 -1
  270. data/lib/decidim/core/test/shared_examples/participant_details_examples.rb +16 -0
  271. data/lib/decidim/core/test/shared_examples/participatory_space_members_page_examples.rb +10 -10
  272. data/lib/decidim/core/test/shared_examples/resource_liked_event_examples.rb +1 -1
  273. data/lib/decidim/core/test/shared_examples/resource_locator_presenter_examples.rb +7 -7
  274. data/lib/decidim/core/test/shared_examples/searchable_participatory_space_examples.rb +3 -3
  275. data/lib/decidim/core/test/shared_examples/searchable_results_examples.rb +2 -2
  276. data/lib/decidim/core/test/shared_examples/simple_event.rb +1 -0
  277. data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +2 -2
  278. data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +1 -1
  279. data/lib/decidim/core/test.rb +2 -1
  280. data/lib/decidim/core/version.rb +1 -1
  281. data/lib/decidim/core.rb +222 -335
  282. data/lib/decidim/download_your_data_serializers/{download_your_data_participatory_space_private_user_serializer.rb → download_your_data_member_serializer.rb} +6 -6
  283. data/lib/decidim/download_your_data_serializers.rb +2 -2
  284. data/lib/decidim/engine_router.rb +31 -6
  285. data/lib/decidim/exporters/csv.rb +1 -1
  286. data/lib/decidim/filter_form_builder.rb +1 -1
  287. data/{app/controllers/concerns → lib}/decidim/form_factory.rb +11 -1
  288. data/lib/decidim/has_settings.rb +2 -2
  289. data/lib/decidim/legacy_form_builder.rb +1 -0
  290. data/lib/decidim/locale_router_detector.rb +41 -0
  291. data/lib/decidim/maintenance/import_models/scope.rb +1 -1
  292. data/lib/decidim/maintenance/import_models.rb +0 -2
  293. data/lib/decidim/map/frontend.rb +1 -1
  294. data/lib/decidim/map/geocoding.rb +2 -2
  295. data/lib/decidim/map/static_map.rb +10 -22
  296. data/lib/decidim/map/utility.rb +3 -6
  297. data/lib/decidim/map.rb +2 -2
  298. data/lib/decidim/menu.rb +1 -1
  299. data/lib/decidim/menu_item.rb +1 -0
  300. data/lib/decidim/menu_registry.rb +1 -1
  301. data/lib/decidim/moderation_tools.rb +1 -1
  302. data/lib/decidim/newsletter_encryptor.rb +5 -8
  303. data/lib/decidim/organization_settings.rb +2 -2
  304. data/lib/decidim/participable.rb +1 -0
  305. data/lib/decidim/participatory_space/has_members.rb +61 -0
  306. data/lib/decidim/participatory_space_manifest.rb +0 -4
  307. data/lib/decidim/participatory_space_resourceable.rb +10 -1
  308. data/lib/decidim/routes/locale_redirects.rb +47 -0
  309. data/lib/decidim/routes.rb +7 -0
  310. data/lib/decidim/search_resource_fields_mapper.rb +3 -4
  311. data/lib/decidim/seeds.rb +17 -0
  312. data/lib/decidim/shakapacker/runner.rb +4 -4
  313. data/lib/decidim/shakapacker/shakapacker.yml +28 -3
  314. data/lib/decidim/taxonomizable.rb +1 -1
  315. data/lib/decidim/translatable_attributes.rb +9 -3
  316. data/lib/decidim/view_model.rb +4 -0
  317. data/lib/devise/models/decidim_newsletterable.rb +1 -1
  318. data/lib/tasks/decidim_procfile.rake +1 -1
  319. data/lib/tasks/decidim_tasks.rake +0 -1
  320. data/lib/tasks/decidim_taxonomies.rake +1 -1
  321. data/lib/tasks/upgrade/decidim_active_storage_migration_tasks.rake +0 -1
  322. data/lib/tasks/upgrade/decidim_encryption.rake +12 -0
  323. data/lib/tasks/upgrade/decidim_migrate_wysiwyg_content.rake +0 -1
  324. data/lib/tasks/upgrade/decidim_remove_deleted_users_left_data_tasks.rake +1 -1
  325. data/lib/tasks/upgrade/{fix_deleted_private_follows.rake → fix_deleted_members_follows.rake} +5 -5
  326. data/lib/tasks/upgrade/migrations.rake +0 -1
  327. data/lib/tasks/upgrade/user_groups_migration.rake +0 -1
  328. metadata +206 -130
  329. data/app/cells/decidim/content_blocks/global_menu/show.erb +0 -11
  330. data/app/cells/decidim/content_blocks/global_menu_cell.rb +0 -35
  331. data/app/cells/decidim/content_blocks/menu_breadcrumb_last_activity/show.erb +0 -10
  332. data/app/cells/decidim/content_blocks/menu_breadcrumb_last_activity_cell.rb +0 -49
  333. data/app/cells/decidim/participatory_space_dropdown_metadata/links.erb +0 -9
  334. data/app/cells/decidim/participatory_space_dropdown_metadata/metadata.erb +0 -1
  335. data/app/cells/decidim/participatory_space_dropdown_metadata/show.erb +0 -11
  336. data/app/cells/decidim/participatory_space_dropdown_metadata_cell.rb +0 -26
  337. data/app/controllers/concerns/decidim/has_members_page.rb +0 -25
  338. data/app/jobs/decidim/newsletters_opt_in_job.rb +0 -11
  339. data/app/jobs/decidim/user_report_job.rb +0 -11
  340. data/app/models/decidim/participatory_space_private_user.rb +0 -51
  341. data/app/packs/src/decidim/controllers/sticky_header/controller.js +0 -116
  342. data/app/packs/src/decidim/controllers/sticky_header/sticky_header.test.js +0 -320
  343. data/app/packs/src/decidim/dropdown_menu.js +0 -18
  344. data/app/packs/src/decidim/identity_selector_dialog.js +0 -33
  345. data/app/presenters/decidim/admin_log/participatory_space_private_user_presenter.rb +0 -38
  346. data/app/presenters/decidim/participatory_space_private_user_presenter.rb +0 -46
  347. data/app/views/decidim/participatory_space_private_users/_participatory_space_private_user.html.erb +0 -1
  348. data/app/views/layouts/decidim/footer/_main_language_chooser.html.erb +0 -26
  349. data/app/views/layouts/decidim/header/_menu_breadcrumb_items.html.erb +0 -34
  350. data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_desktop.html.erb +0 -10
  351. data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_mobile.html.erb +0 -17
  352. data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_top_left.html.erb +0 -2
  353. data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile_tablet.html.erb +0 -33
  354. data/app/views/layouts/decidim/header/_mobile_language_choose.html.erb +0 -25
  355. data/lib/decidim/core/test/shared_examples/has_private_users.rb +0 -63
  356. data/lib/decidim/core/test/shared_examples/participatory_space_dropdown_metadata_cell_examples.rb +0 -81
  357. data/lib/decidim/has_private_users.rb +0 -57
  358. data/lib/decidim/maintenance/import_models/assembly_type.rb +0 -49
  359. data/lib/decidim/maintenance/import_models/participatory_process_type.rb +0 -21
  360. data/lib/decidim/query_extensions.rb +0 -64
  361. /data/app/cells/decidim/{participatory_space_private_user → member}/show.erb +0 -0
@@ -28,18 +28,14 @@ header {
28
28
  #flash-messages-container {
29
29
  @apply mt-40 md:mt-0;
30
30
  }
31
-
32
- #menu-bar-container {
33
- @apply mt-[140px] md:mt-0;
34
- }
35
31
  }
36
32
 
37
- #sticky-header-container {
38
- @apply fixed w-full top-0 shadow-lg z-40 bg-white md:relative transition-top duration-300;
33
+ #header-container {
34
+ @apply w-full z-40 bg-white;
39
35
  }
40
36
 
41
37
  .main-bar {
42
- @apply container grid grid-cols-4 md:grid-cols-8 lg:grid-cols-12 gap-4 items-center py-5 h-24;
38
+ @apply container flex justify-between gap-4 items-center py-5 h-20;
43
39
 
44
40
  &--focus-mode-back-button {
45
41
  @apply h-16 lg:h-24;
@@ -50,7 +46,7 @@ header {
50
46
  }
51
47
 
52
48
  &__container {
53
- @apply relative w-full;
49
+ @apply relative w-full flex justify-between;
54
50
  }
55
51
 
56
52
  &__logo {
@@ -69,15 +65,23 @@ header {
69
65
  @apply hidden md:block col-span-2 col-start-5 xl:col-start-4;
70
66
 
71
67
  form {
72
- @apply block relative rounded text-md border border-neutral-200 outline outline-1 outline-transparent rounded bg-background-2 leading-relaxed;
68
+ @apply block relative rounded text-md border border-neutral-200 outline outline-1 outline-transparent rounded bg-background-2 leading-none;
73
69
  }
74
70
 
75
71
  input[type="text"] {
76
- @apply block bg-transparent w-full px-4 py-1.5;
72
+ @apply block bg-transparent w-full pl-4 pr-10 py-2 h-full;
73
+
74
+ &::placeholder {
75
+ @apply text-neutral-500 text-sm ltr:pl-0 rtl:pr-0;
76
+ }
77
77
  }
78
78
 
79
79
  button[type="submit"] {
80
- @apply absolute ltr:right-2 rtl:left-2 inset-y-0 text-secondary px-2;
80
+ @apply absolute rtl:left-2 ltr:right-2 inset-y-0 text-secondary px-2;
81
+
82
+ svg {
83
+ @apply fill-neutral-500;
84
+ }
81
85
  }
82
86
  }
83
87
 
@@ -90,19 +94,23 @@ header {
90
94
  }
91
95
 
92
96
  &__menu-mobile {
93
- @apply lg:hidden flex flex-row-reverse items-center;
97
+ @apply lg:hidden flex flex-row-reverse items-center gap-x-3;
94
98
  }
95
99
 
96
100
  &__links-desktop,
97
101
  > *:last-child:not(.main-bar__back-button) {
98
- @apply col-span-1 md:col-start-8 lg:col-start-8 lg:col-span-5 justify-self-end;
102
+ @apply col-span-1 lg:col-start-8 lg:col-start-8 lg:col-span-5 justify-self-end;
99
103
  }
100
104
 
101
105
  &__links-desktop {
102
106
  @apply hidden lg:flex items-center justify-between text-center divide-x-2 divide-gray-3 ml-auto [&>*]:px-4 xl:[&>*]:px-6 first:[&>*]:pl-0 last:[&>*]:pr-0;
103
107
 
104
108
  &__item {
105
- @apply flex flex-col items-center text-secondary px-2 py-1 rounded hover:underline hover:bg-background;
109
+ @apply flex items-center gap-x-2 text-secondary px-2 py-1 rounded;
110
+
111
+ &:hover {
112
+ @apply bg-secondary rounded-[4px] text-white;
113
+ }
106
114
 
107
115
  &-wrapper {
108
116
  @apply flex gap-x-4 xl:gap-x-6;
@@ -113,17 +121,76 @@ header {
113
121
  }
114
122
  }
115
123
 
124
+ .card__highlight-img {
125
+ svg {
126
+ @apply w-full h-full;
127
+ }
128
+ }
129
+
130
+ &__dropdown {
131
+ @apply flex items-end absolute top-0 right-0 bg-[rgba(0,0,0,0.25)] transition duration-300 z-30 h-screen cursor-auto;
132
+
133
+ .menu-bar {
134
+ &__main-dropdown {
135
+ @apply hidden sm:flex flex-col h-full sm:p-8;
136
+
137
+ &__left {
138
+ @apply w-full;
139
+ }
140
+ }
141
+
142
+ &__dropdown-menu {
143
+ @apply w-full;
144
+
145
+ li {
146
+ @apply py-3 sm:py-3.5 border-b border-t-0 last:border-0 border-gray-3 #{!important};
147
+
148
+ a {
149
+ @apply no-underline;
150
+ }
151
+ }
152
+ }
153
+ }
154
+
155
+ #main-dropdown-summary-desktop-close {
156
+ @apply self-end;
157
+ }
158
+ }
159
+
160
+ &__trigger {
161
+ @apply text-secondary cursor-pointer py-1 px-2 text-md leading-[22px] w-fit flex items-center gap-x-2;
162
+
163
+ span {
164
+ @apply text-secondary;
165
+ }
166
+
167
+ &:hover {
168
+ @apply bg-secondary rounded-[4px] text-white;
169
+
170
+ svg,
171
+ span {
172
+ @apply text-white;
173
+ }
174
+ }
175
+
176
+ &[aria-expended="true"] {
177
+ #content {
178
+ @apply bg-[rgb(0_0_0_/_0.5)];
179
+ }
180
+ }
181
+ }
182
+
116
183
  /* overwrite default dropdown styles */
117
184
  [data-target*="dropdown"] > span:only-of-type {
118
185
  @apply gap-0;
119
186
  }
120
187
 
121
188
  svg {
122
- @apply w-5 h-5 fill-current;
189
+ @apply w-4 h-5 fill-current;
123
190
  }
124
191
 
125
192
  svg + span {
126
- @apply text-sm first-letter:uppercase;
193
+ @apply text-md leading-[22px] first-letter:uppercase font-semibold whitespace-nowrap;
127
194
  }
128
195
  }
129
196
 
@@ -131,14 +198,23 @@ header {
131
198
  @apply fixed bottom-0 left-0 z-40 bg-white w-full px-4 py-3 flex justify-between text-secondary shadow-[0_-4px_6px_rgba(198,198,198,0.25)];
132
199
 
133
200
  &__trigger {
134
- @apply flex flex-col items-center text-secondary cursor-pointer md:pl-4 md:border-l border-gray-3;
201
+ @apply flex items-center text-secondary cursor-pointer justify-evenly gap-x-1 px-2 py-1;
135
202
 
136
203
  svg {
137
204
  @apply w-6 h-6 fill-current;
138
205
  }
139
206
 
140
207
  span {
141
- @apply text-sm first-letter:uppercase;
208
+ @apply text-secondary;
209
+ }
210
+
211
+ &:hover {
212
+ @apply bg-secondary rounded-[4px] text-white;
213
+
214
+ svg,
215
+ span {
216
+ @apply text-white;
217
+ }
142
218
  }
143
219
  }
144
220
 
@@ -146,10 +222,6 @@ header {
146
222
  @apply absolute top-full left-0 z-30 bg-white;
147
223
  }
148
224
 
149
- &__dropdown-before {
150
- @apply before:block before:absolute before:-top-10 before:right-12 before:content-[""] before:bg-white before:w-24 before:h-12 before:-mt-8;
151
- }
152
-
153
225
  &__account {
154
226
  @apply fixed top-0 left-0 w-full h-full z-30 bg-white;
155
227
 
@@ -165,10 +237,6 @@ header {
165
237
  @apply text-md;
166
238
  }
167
239
 
168
- .main-bar {
169
- @apply border-b border-gray;
170
- }
171
-
172
240
  .main-bar__avatar {
173
241
  @apply w-12 h-12;
174
242
  }
@@ -198,7 +266,7 @@ header {
198
266
  }
199
267
 
200
268
  svg + span {
201
- @apply text-sm first-letter:uppercase w-auto;
269
+ @apply w-auto text-md leading-[22px] first-letter:uppercase font-semibold;
202
270
 
203
271
  flex-shrink: 0;
204
272
  }
@@ -246,23 +314,27 @@ header {
246
314
  @apply py-0 mx-0 w-full;
247
315
 
248
316
  &[aria-hidden="true"] {
249
- @apply md:hidden;
317
+ @apply sm:hidden;
250
318
  }
251
319
  }
252
320
  }
253
321
 
254
322
  .menu-bar {
255
- @apply container h-full flex justify-between items-center lg:relative last-of-type:[&>svg]:hidden;
323
+ @apply container h-full flex justify-between items-center sm:relative last-of-type:[&>svg]:hidden;
256
324
 
257
325
  &__container {
258
- @apply bg-primary relative h-14;
326
+ @apply bg-primary relative h-14 flex justify-between;
259
327
  }
260
328
 
261
329
  &__breadcrumb-desktop {
262
- @apply hidden lg:flex justify-between items-center gap-2.5 [&>*]:text-lg [&>*]:text-white;
330
+ @apply hidden lg:flex justify-between items-center [&>*]:text-md [&>*]:text-white gap-x-2;
331
+
332
+ .no-interactive {
333
+ @apply font-normal px-0;
334
+ }
263
335
 
264
336
  &__dropdown-trigger {
265
- @apply flex rounded px-2 py-1 z-20;
337
+ @apply flex rounded py-1 z-20 font-semibold;
266
338
 
267
339
  &:hover {
268
340
  @apply z-10 relative before:content-[''] before:absolute before:w-[calc(100%+3rem+1px)] before:min-w-[10rem] before:h-40 before:left-1/2 before:top-1/2 before:-translate-x-1/2 before:-translate-y-1/4 before:-z-10;
@@ -274,7 +346,7 @@ header {
274
346
  }
275
347
 
276
348
  &__dropdown-wrapper {
277
- @apply flex items-center cursor-pointer rounded hover:backdrop-brightness-75 focus:backdrop-brightness-75 focus:outline-none;
349
+ @apply flex items-center cursor-pointer underline;
278
350
  }
279
351
 
280
352
  &__dropdown-content {
@@ -355,6 +427,10 @@ header {
355
427
  }
356
428
  }
357
429
 
430
+ .menu-bar__breadcrumb-item {
431
+ @apply font-semibold underline;
432
+ }
433
+
358
434
  /* overwrite default dropdown styles */
359
435
  [id*="dropdown-menu"] {
360
436
  @apply mx-0 py-0 border-0;
@@ -381,19 +457,15 @@ header {
381
457
  }
382
458
  }
383
459
 
384
- &__language-chooser {
385
- @apply absolute top-full left-0 bg-white rounded w-full bg-gray-5;
386
- }
387
-
388
460
  &__dropdown-menu {
389
- @apply w-full md:w-1/4 bg-primary px-4 md:px-8 pt-0 pb-3 md:py-3 divide-y divide-gray-3 text-white;
461
+ @apply w-full sm:w-1/4 px-4 sm:px-0 pt-0 pb-3 sm:py-3 divide-y divide-gray-3 text-[var(--secondary)];
390
462
 
391
463
  > * {
392
- @apply py-3 md:py-3.5;
464
+ @apply py-3 sm:py-3.5 sm:px-2;
393
465
  }
394
466
 
395
467
  a {
396
- @apply flex items-center justify-start gap-1 font-semibold text-lg text-white;
468
+ @apply flex items-center justify-start gap-1 font-semibold text-xl text-[var(--secondary)] underline;
397
469
 
398
470
  span {
399
471
  @apply min-w-0 truncate;
@@ -403,13 +475,21 @@ header {
403
475
  @apply flex-none fill-current;
404
476
  }
405
477
  }
478
+
479
+ li:hover {
480
+ @apply bg-[var(--secondary)] rounded-[4px];
481
+
482
+ a {
483
+ @apply text-white;
484
+ }
485
+ }
406
486
  }
407
487
 
408
488
  &__main-dropdown {
409
- @apply bg-white flex flex-row rounded-b shadow-lg text-black w-full lg:w-[1280px] h-screen md:h-auto;
489
+ @apply bg-white flex flex-row rounded-b shadow-lg text-black w-full lg:w-[530px] h-screen lg:h-auto;
410
490
 
411
491
  &__left {
412
- @apply flex flex-col justify-between p-4 md:p-8 space-y-5 hidden md:block md:w-3/4;
492
+ @apply p-4 sm:py-8 sm:px-0 space-y-5 hidden sm:block sm:w-3/4;
413
493
 
414
494
  &-top {
415
495
  @apply border-b-4 border-gray-3 pb-3;
@@ -420,14 +500,14 @@ header {
420
500
  @apply w-full px-4;
421
501
 
422
502
  &-menu {
423
- @apply w-full md:w-[100%] mt-0 grid md:grid-cols-2 gap-x-6 text-secondary;
503
+ @apply w-full lg:w-[100%] mt-0 grid lg:grid-cols-2 gap-x-6 text-secondary;
424
504
 
425
505
  > * {
426
- @apply py-3 md:py-3.5 border-b last:border-0 border-gray-3;
506
+ @apply py-3 lg:py-3.5 border-b last:border-0 border-gray-3;
427
507
 
428
508
  /* since the grid has 2 columns, remove the border for these last 2 columns */
429
509
  &:nth-last-child(-n + 2) {
430
- @apply md:border-0;
510
+ @apply lg:border-0;
431
511
  }
432
512
  }
433
513
 
@@ -446,7 +526,7 @@ header {
446
526
  }
447
527
 
448
528
  &__bottom {
449
- @apply hidden md:flex;
529
+ @apply hidden lg:flex;
450
530
 
451
531
  &-right {
452
532
  @apply mr-2 mb-2;
@@ -466,6 +546,28 @@ header {
466
546
  }
467
547
  }
468
548
 
549
+ &__dropdown-desktop {
550
+ .card__highlight {
551
+ @apply flex-col ring-transparent rounded-lg shadow-[1px_4px_8px_3px_rgba(0,0,0,0.15)];
552
+
553
+ &-img {
554
+ @apply w-full aspect-[21/9] rounded-none rounded-tl-lg rounded-tr-lg;
555
+
556
+ svg {
557
+ @apply fill-primary;
558
+ }
559
+ }
560
+
561
+ &-text {
562
+ @apply w-full items-start text-start bg-background-2 rounded-bl-lg rounded-br-lg;
563
+
564
+ h3 {
565
+ @apply font-bold;
566
+ }
567
+ }
568
+ }
569
+ }
570
+
469
571
  &__secondary-dropdown {
470
572
  @apply absolute top-full left-0 lg:relative flex justify-between bg-white rounded-b shadow-lg text-black w-full lg:w-[1000px];
471
573
 
@@ -0,0 +1,79 @@
1
+ header {
2
+ .main-bar {
3
+ &__language-chooser {
4
+ &-desktop {
5
+ @apply hidden md:block;
6
+ }
7
+
8
+ > div[id*="dropdown-menu"] {
9
+ @apply bg-white shadow-[1px_4px_8px_3px_rgba(0,0,0,0.15)] overflow-auto max-h-[50vh] p-2 sm:w-fit z-[100];
10
+ }
11
+
12
+ &.focus-mode {
13
+ @apply border-none pr-0;
14
+ }
15
+
16
+ &-trigger {
17
+ @apply inline-flex border border-neutral-300 rounded px-4 py-[9px] gap-x-2 flex-row;
18
+
19
+ &[id*="dropdown-menu"] {
20
+ @apply py-[9px];
21
+ }
22
+
23
+ & > span,
24
+ & > svg:first-of-type {
25
+ @apply text-neutral-500;
26
+ }
27
+
28
+ & > svg:last-of-type,
29
+ & > svg:first-of-type {
30
+ @apply block;
31
+ }
32
+
33
+ & > svg:last-of-type {
34
+ @apply text-gray-2 ml-1;
35
+ }
36
+
37
+ svg + span {
38
+ @apply text-sm font-normal;
39
+ }
40
+ }
41
+
42
+ &-holder {
43
+ @apply items-center gap-x-1 flex;
44
+ }
45
+
46
+ &-list {
47
+ @apply flex flex-col space-y-2;
48
+ }
49
+
50
+ &-item {
51
+ @apply text-black text-left text-md hover:bg-secondary hover:text-white;
52
+
53
+ &:hover {
54
+ @apply rounded;
55
+ }
56
+
57
+ &-active {
58
+ @apply bg-neutral-200 rounded;
59
+
60
+ &:hover {
61
+ @apply bg-[var(--secondary)];
62
+ }
63
+ }
64
+ }
65
+
66
+ & > div {
67
+ @apply absolute;
68
+ }
69
+ }
70
+ }
71
+
72
+ .menu-bar__language-chooser-mobile {
73
+ .main-bar__language-chooser {
74
+ & > div[id*="dropdown-menu"] {
75
+ @apply w-full relative;
76
+ }
77
+ }
78
+ }
79
+ }
@@ -9,6 +9,7 @@
9
9
  // On the other hand, the following styles match with specific routes
10
10
  @use "stylesheets/decidim/header";
11
11
  @use "stylesheets/decidim/footer";
12
+ @use "stylesheets/decidim/language_chooser";
12
13
  @use "stylesheets/decidim/login";
13
14
  @use "stylesheets/decidim/pages";
14
15
  @use "stylesheets/decidim/notifications";
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module AdminLog
5
+ module ParticipatorySpace
6
+ # This class holds the logic to present a `Decidim::ParticipatorySpace::MemberPresenter`
7
+ # for the `AdminLog` log.
8
+ #
9
+ # Usage should be automatic and you should not need to call this class
10
+ # directly, but here is an example:
11
+ #
12
+ # action_log = Decidim::ActionLog.last
13
+ # view_helpers # => this comes from the views
14
+ # MemberPresenter.new(action_log, view_helpers).present
15
+ class MemberPresenter < Decidim::Log::BasePresenter
16
+ private
17
+
18
+ def diff_fields_mapping
19
+ {
20
+ name: :string,
21
+ email: :string
22
+ }
23
+ end
24
+
25
+ def action_string
26
+ case action
27
+ when "create", "create_via_csv", "delete"
28
+ "decidim.admin_log.member.#{action}"
29
+ else
30
+ super
31
+ end
32
+ end
33
+
34
+ def i18n_labels_scope
35
+ "activemodel.attributes.member"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -11,7 +11,7 @@ module Decidim
11
11
  #
12
12
  # Returns an HTML-safe String.
13
13
  def resource_path
14
- @resource_path ||= h.decidim.page_path(resource)
14
+ @resource_path ||= h.decidim.page_path(resource, locale: I18n.locale)
15
15
  end
16
16
  end
17
17
  end
@@ -20,7 +20,7 @@ module Decidim
20
20
  # "Decidim::Bar" => "Bars: 456"
21
21
  # }
22
22
  #
23
- # @return [Hash<String => String>] The translated resource counts with the
23
+ # @return [Hash{String => String}] The translated resource counts with the
24
24
  # resource type as its keys and the translated text with the record count
25
25
  # as its values.
26
26
  def translated_record_counts
@@ -9,16 +9,16 @@ module Decidim
9
9
 
10
10
  def render
11
11
  content_tag :li, class: link_wrapper_classes do
12
- output = [arrow_link(label, url, link_options)]
12
+ output = [root_link(label, url, link_options)]
13
13
  output.push(@view.send(:simple_menu, **@menu_item.submenu).render) if @menu_item.submenu
14
14
 
15
15
  safe_join(output)
16
16
  end
17
17
  end
18
18
 
19
- def arrow_link(text, url, args = {})
19
+ def root_link(text, url, args = {})
20
20
  link_to url, class: args.with_indifferent_access[:class] do
21
- "<span>#{text}</span> #{icon("arrow-right-line")}".html_safe
21
+ "<span>#{text}</span>".html_safe
22
22
  end
23
23
  end
24
24
  end
@@ -11,6 +11,7 @@ module Decidim
11
11
  # The only requirement for custom renderers is that they should respond to `present`.
12
12
  class UserPresenter
13
13
  include Decidim::SanitizeHelper
14
+
14
15
  # Public: Initializes the presenter.
15
16
  #
16
17
  # user - An instance of Decidim::User
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Log
5
+ module ValueTypes
6
+ # This class presents the given value as an access mode. Check
7
+ # the `DefaultPresenter` for more info on how value
8
+ # presenters work.
9
+ class AccessModePresenter < DefaultPresenter
10
+ # Public: Presents the value as an access mode. If the access mode can
11
+ # be found, it shows its translated label. Otherwise it shows a fallback message.
12
+ #
13
+ # Returns an HTML-safe String.
14
+ def present
15
+ return unless value
16
+ return translated_access_mode if valid_access_mode?
17
+
18
+ I18n.t("not_found", id: value, scope: "decidim.log.value_types.access_mode_presenter")
19
+ end
20
+
21
+ private
22
+
23
+ def valid_access_mode?
24
+ access_modes.has_value?(value.to_i)
25
+ end
26
+
27
+ def translated_access_mode
28
+ I18n.t(access_mode_key, scope: "decidim.log.value_types.access_mode_presenter.access_modes")
29
+ end
30
+
31
+ def access_mode_key
32
+ access_modes.key(value.to_i)
33
+ end
34
+
35
+ def access_modes
36
+ # Access modes are consistent across participatory spaces (assemblies, processes, etc.)
37
+ # open: 0 - fully visible and accessible
38
+ # transparent: 1 - visible but content restricted
39
+ # restricted: 2 - not visible, requires permission
40
+ { open: 0, transparent: 1, restricted: 2 }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module ParticipatorySpace
5
+ #
6
+ # Decorator for participatory space members
7
+ #
8
+ class MemberPresenter < SimpleDelegator
9
+ delegate :profile_url, to: :user, allow_nil: true
10
+
11
+ def name
12
+ user ? user.name : full_name
13
+ end
14
+
15
+ def nickname
16
+ user.nickname if user
17
+ end
18
+
19
+ def avatar_url(variant = nil)
20
+ return user.avatar_url(variant) if user.present?
21
+
22
+ non_user_avatar_path(variant)
23
+ end
24
+
25
+ def non_user_avatar_path(variant = nil)
26
+ return non_user_avatar.default_url(variant) unless non_user_avatar.attached?
27
+
28
+ non_user_avatar.path(variant:)
29
+ end
30
+
31
+ def non_user_avatar
32
+ attached_uploader(:non_user_avatar)
33
+ end
34
+
35
+ def deleted?
36
+ false
37
+ end
38
+
39
+ private
40
+
41
+ def user
42
+ @user ||= if (user = __getobj__.user.presence)
43
+ Decidim::UserPresenter.new(user)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -55,8 +55,9 @@ module Decidim
55
55
  # Returns a String.
56
56
  def show(options = {})
57
57
  options.merge!(options_for_polymorphic)
58
+ locale = options.delete(:locale) || I18n.locale
58
59
 
59
- admin_route_proxy.send("#{member_route_name}_path", target, options)
60
+ normalize_locale_route(admin_route_proxy.send("#{member_route_name}_path", target, options), locale)
60
61
  end
61
62
 
62
63
  # Builds the admin edit path to the resource.
@@ -66,8 +67,9 @@ module Decidim
66
67
  # Returns a String.
67
68
  def edit(options = {})
68
69
  options.merge!(options_for_polymorphic)
70
+ locale = options.delete(:locale) || I18n.locale
69
71
 
70
- admin_route_proxy.send("edit_#{member_route_name}_path", target, options)
72
+ normalize_locale_route(admin_route_proxy.send("edit_#{member_route_name}_path", target, options), locale)
71
73
  end
72
74
 
73
75
  private
@@ -112,8 +114,9 @@ module Decidim
112
114
 
113
115
  def admin_collection_route(route_type, options)
114
116
  options.merge!(options_for_polymorphic)
117
+ locale = options.delete(:locale) || I18n.locale
115
118
 
116
- admin_route_proxy.send("#{collection_route_name}_#{route_type}", options)
119
+ normalize_locale_route(admin_route_proxy.send("#{collection_route_name}_#{route_type}", options), locale)
117
120
  end
118
121
 
119
122
  def manifest_for(record)
@@ -172,5 +175,21 @@ module Decidim
172
175
  def admin_route_proxy
173
176
  @admin_route_proxy ||= EngineRouter.admin_proxy(component || target)
174
177
  end
178
+
179
+ def normalize_locale_route(path, locale)
180
+ path = path.sub(/([?&])locale=[^&]*(?=&|\z)/, "\\1")
181
+ path = path.delete_suffix("?")
182
+ path = path.delete_suffix("&")
183
+ path = path.sub("?&", "?")
184
+
185
+ path = "/#{path}" unless path.start_with?("/")
186
+
187
+ locale_candidates = Regexp.union(I18n.available_locales.map(&:to_s).sort_by(&:length).reverse)
188
+ path = path.sub(%r{\A/#{locale_candidates}(?=/|\z)}, "")
189
+
190
+ path = "/" if path.empty?
191
+
192
+ "/#{locale}#{path}"
193
+ end
175
194
  end
176
195
  end