decidim-core 0.29.4 → 0.30.0.rc1

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 (562) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/address/show.erb +3 -3
  3. data/app/cells/decidim/amendable/amend_button_card/show.erb +6 -4
  4. data/app/cells/decidim/amendable/amend_button_card_cell.rb +8 -0
  5. data/app/cells/decidim/amendable/amendments/show.erb +1 -1
  6. data/app/cells/decidim/amendable/promote_button_card/show.erb +2 -0
  7. data/app/cells/decidim/author/flag.erb +6 -0
  8. data/app/cells/decidim/author/flag_user.erb +14 -0
  9. data/app/cells/decidim/author/show.erb +4 -2
  10. data/app/cells/decidim/author_cell.rb +1 -1
  11. data/app/cells/decidim/card_l/extra_data.erb +1 -0
  12. data/app/cells/decidim/card_metadata_cell.rb +9 -16
  13. data/app/cells/decidim/comments_button_cell.rb +14 -2
  14. data/app/cells/decidim/content_blocks/highlighted_elements_cell.rb +2 -0
  15. data/app/cells/decidim/content_blocks/highlighted_elements_with_cell_for_list_cell.rb +1 -1
  16. data/app/cells/decidim/content_blocks/participatory_space_extra_data/extra_data.erb +2 -2
  17. data/app/cells/decidim/endorsement_block/show.erb +0 -1
  18. data/app/cells/decidim/endorsement_block_cell.rb +6 -0
  19. data/app/cells/decidim/endorsement_buttons/button_content.erb +1 -1
  20. data/app/cells/decidim/endorsement_buttons/select_identity_button.erb +1 -1
  21. data/app/cells/decidim/endorsement_buttons/show.erb +7 -7
  22. data/app/cells/decidim/endorsement_buttons/verification_modal.erb +4 -2
  23. data/app/cells/decidim/endorsers_list/empty.erb +3 -0
  24. data/app/cells/decidim/endorsers_list/full.erb +17 -5
  25. data/app/cells/decidim/endorsers_list/show.erb +19 -10
  26. data/app/cells/decidim/endorsers_list_cell.rb +19 -6
  27. data/app/cells/decidim/flag_modal/flag_user.erb +34 -0
  28. data/app/cells/decidim/flag_modal/show.erb +52 -0
  29. data/app/cells/decidim/flag_modal_cell.rb +56 -0
  30. data/app/cells/decidim/follow_button/show.erb +1 -2
  31. data/app/cells/decidim/follow_button_cell.rb +5 -0
  32. data/app/cells/decidim/map/show.erb +3 -0
  33. data/app/cells/decidim/map/template.erb +14 -0
  34. data/app/cells/decidim/map_cell.rb +39 -0
  35. data/app/cells/decidim/notification_actions/buttons_cell.rb +1 -1
  36. data/app/cells/decidim/onboarding_action_message/show.erb +15 -0
  37. data/app/cells/decidim/onboarding_action_message_cell.rb +81 -0
  38. data/app/cells/decidim/participatory_space_dropdown_metadata/metadata.erb +4 -4
  39. data/app/cells/decidim/participatory_space_dropdown_metadata/show.erb +3 -5
  40. data/app/cells/decidim/participatory_space_private_user/show.erb +23 -0
  41. data/app/cells/decidim/participatory_space_private_user_cell.rb +21 -0
  42. data/app/cells/decidim/profile_actions/show.erb +1 -1
  43. data/app/cells/decidim/profile_sidebar/show.erb +167 -0
  44. data/app/cells/decidim/profile_sidebar_cell.rb +68 -0
  45. data/app/cells/decidim/progress_bar/show.erb +2 -2
  46. data/app/cells/decidim/report_button/already_reported_modal.erb +2 -2
  47. data/app/cells/decidim/report_button/flag_modal.erb +27 -13
  48. data/app/cells/decidim/report_button_cell.rb +9 -2
  49. data/app/cells/decidim/resource_history/show.erb +20 -0
  50. data/app/cells/decidim/resource_history_cell.rb +66 -0
  51. data/app/cells/decidim/resource_types_filter/show.erb +1 -1
  52. data/app/cells/decidim/resource_types_filter_cell.rb +6 -6
  53. data/app/cells/decidim/share_button_cell.rb +0 -4
  54. data/app/cells/decidim/share_widget/modal.erb +26 -0
  55. data/app/cells/decidim/share_widget/show.erb +2 -0
  56. data/app/cells/decidim/share_widget_cell.rb +20 -0
  57. data/app/cells/decidim/tags/show.erb +7 -4
  58. data/app/cells/decidim/tags_cell.rb +11 -72
  59. data/app/cells/decidim/user_activity/show.erb +1 -1
  60. data/app/commands/decidim/amendable/create_draft.rb +2 -2
  61. data/app/commands/decidim/create_ephemeral_user.rb +52 -0
  62. data/app/commands/decidim/create_omniauth_registration.rb +21 -17
  63. data/app/commands/decidim/create_report.rb +8 -11
  64. data/app/commands/decidim/create_user_group.rb +6 -2
  65. data/app/commands/decidim/destroy_ephemeral_user.rb +47 -0
  66. data/app/commands/decidim/invite_user.rb +1 -1
  67. data/app/commands/decidim/search.rb +0 -14
  68. data/app/commands/decidim/update_account.rb +11 -3
  69. data/app/commands/decidim/update_notifications_settings.rb +1 -0
  70. data/app/commands/decidim/update_resources_taxonomies.rb +67 -0
  71. data/app/commands/decidim/update_user_group.rb +7 -1
  72. data/app/constraints/decidim/current_component.rb +1 -1
  73. data/app/controllers/concerns/decidim/ajax_permission_handler.rb +21 -0
  74. data/app/controllers/concerns/decidim/devise_authentication_methods.rb +3 -6
  75. data/app/controllers/concerns/decidim/devise_controllers.rb +2 -0
  76. data/app/controllers/concerns/decidim/disable_redirection_to_external_host.rb +1 -1
  77. data/app/controllers/concerns/decidim/ephemeral_session_checker.rb +87 -0
  78. data/app/controllers/concerns/decidim/filter_resource.rb +4 -2
  79. data/app/controllers/concerns/decidim/has_members_page.rb +25 -0
  80. data/app/controllers/concerns/decidim/headers/browser_feature_permissions.rb +50 -0
  81. data/app/controllers/concerns/decidim/locale_switcher.rb +2 -2
  82. data/app/controllers/concerns/decidim/needs_password_change.rb +0 -1
  83. data/app/controllers/concerns/decidim/needs_permission.rb +2 -1
  84. data/app/controllers/concerns/decidim/needs_tos_accepted.rb +4 -5
  85. data/app/controllers/concerns/decidim/onboarding_action_methods.rb +52 -0
  86. data/app/controllers/concerns/decidim/participatory_space_context.rb +1 -4
  87. data/app/controllers/decidim/application_controller.rb +10 -0
  88. data/app/controllers/decidim/authorization_modals_controller.rb +8 -2
  89. data/app/controllers/decidim/components/base_controller.rb +3 -7
  90. data/app/controllers/decidim/devise/confirmations_controller.rb +4 -0
  91. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +8 -1
  92. data/app/controllers/decidim/devise/registrations_controller.rb +1 -1
  93. data/app/controllers/decidim/devise/sessions_controller.rb +2 -0
  94. data/app/controllers/decidim/download_your_data_controller.rb +33 -2
  95. data/app/controllers/decidim/editor_images_controller.rb +1 -11
  96. data/app/controllers/decidim/follows_controller.rb +1 -1
  97. data/app/controllers/decidim/geolocation_controller.rb +19 -0
  98. data/app/controllers/decidim/homepage_controller.rb +0 -1
  99. data/app/controllers/decidim/open_data_controller.rb +33 -8
  100. data/app/controllers/decidim/profiles_controller.rb +2 -2
  101. data/app/controllers/decidim/reports_controller.rb +2 -7
  102. data/app/controllers/decidim/user_activities_controller.rb +1 -1
  103. data/app/controllers/decidim/user_conversations_controller.rb +1 -11
  104. data/app/events/decidim/soft_delete_resource_event.rb +15 -0
  105. data/app/forms/decidim/account_form.rb +2 -5
  106. data/app/forms/decidim/amendable/form.rb +4 -2
  107. data/app/forms/decidim/ephemeral_user_form.rb +22 -0
  108. data/app/forms/decidim/notifications_settings_form.rb +1 -0
  109. data/app/forms/decidim/omniauth_registration_form.rb +15 -2
  110. data/app/forms/decidim/registration_form.rb +1 -1
  111. data/app/helpers/concerns/decidim/flash_helper_extensions.rb +17 -2
  112. data/app/helpers/decidim/action_authorization_helper.rb +75 -14
  113. data/app/helpers/decidim/amendments_helper.rb +0 -9
  114. data/app/helpers/decidim/application_helper.rb +6 -2
  115. data/app/helpers/decidim/breadcrumb_helper.rb +6 -0
  116. data/app/helpers/decidim/cache_helper.rb +1 -1
  117. data/app/helpers/decidim/check_boxes_tree_helper.rb +25 -53
  118. data/app/helpers/decidim/decidim_form_helper.rb +0 -44
  119. data/app/helpers/decidim/endorsable_helper.rb +0 -10
  120. data/app/helpers/decidim/layout_helper.rb +6 -0
  121. data/app/helpers/decidim/menu_helper.rb +2 -2
  122. data/app/helpers/decidim/messaging/conversation_helper.rb +2 -3
  123. data/app/helpers/decidim/meta_tags_helper.rb +32 -23
  124. data/app/helpers/decidim/modal_helper.rb +23 -0
  125. data/app/helpers/decidim/omniauth_helper.rb +5 -5
  126. data/app/helpers/decidim/onboarding_action_helper.rb +13 -0
  127. data/app/helpers/decidim/orders_helper.rb +1 -2
  128. data/app/helpers/decidim/paginate_helper.rb +1 -1
  129. data/app/helpers/decidim/participatory_space_helpers.rb +1 -1
  130. data/app/helpers/decidim/passwords_helper.rb +2 -2
  131. data/app/helpers/decidim/taxonomies_helper.rb +40 -0
  132. data/app/helpers/decidim/tooltip_helper.rb +1 -4
  133. data/app/jobs/decidim/download_your_data_export_job.rb +2 -19
  134. data/app/jobs/decidim/event_publisher_job.rb +18 -9
  135. data/app/jobs/decidim/export_job.rb +5 -1
  136. data/app/jobs/decidim/export_participatory_space_job.rb +4 -1
  137. data/app/jobs/decidim/open_data_job.rb +4 -4
  138. data/app/mailers/decidim/export_mailer.rb +7 -12
  139. data/app/mailers/decidim/notifications_digest_mailer.rb +1 -7
  140. data/app/mailers/decidim/reported_mailer.rb +2 -18
  141. data/app/models/decidim/action_log.rb +20 -1
  142. data/app/models/decidim/category.rb +4 -0
  143. data/app/models/decidim/component.rb +25 -3
  144. data/app/models/decidim/metric.rb +2 -1
  145. data/app/models/decidim/moderation.rb +16 -0
  146. data/app/models/decidim/newsletter.rb +12 -8
  147. data/app/models/decidim/organization.rb +7 -3
  148. data/app/models/decidim/participatory_space_private_user.rb +20 -0
  149. data/app/models/decidim/private_export.rb +24 -0
  150. data/app/models/decidim/push_notification_message.rb +1 -1
  151. data/app/models/decidim/report.rb +1 -1
  152. data/app/models/decidim/scope.rb +4 -0
  153. data/app/models/decidim/share_token.rb +36 -10
  154. data/app/models/decidim/taxonomization.rb +23 -0
  155. data/app/models/decidim/taxonomy.rb +139 -0
  156. data/app/models/decidim/taxonomy_filter.rb +130 -0
  157. data/app/models/decidim/taxonomy_filter_item.rb +33 -0
  158. data/app/models/decidim/user.rb +13 -23
  159. data/app/models/decidim/user_base_entity.rb +12 -4
  160. data/app/models/decidim/user_moderation.rb +9 -0
  161. data/app/models/decidim/user_report.rb +4 -0
  162. data/app/packs/entrypoints/decidim_core.js +1 -0
  163. data/app/packs/entrypoints/decidim_geocoding.js +2 -0
  164. data/app/packs/images/decidim/brands/facebook.svg +10 -0
  165. data/app/packs/images/decidim/brands/google.svg +7 -1
  166. data/app/packs/images/decidim/brands/twitter-x.svg +3 -0
  167. data/app/packs/src/decidim/check_boxes_tree.js +0 -1
  168. data/app/packs/src/decidim/clipboard.js +18 -9
  169. data/app/packs/src/decidim/confirm.js +79 -59
  170. data/app/packs/src/decidim/datepicker/datepicker_functions.js +3 -3
  171. data/app/packs/src/decidim/decidim_application.js +1 -0
  172. data/app/packs/src/decidim/form_remote.js +1 -1
  173. data/app/packs/src/decidim/geocoding/reverse_geocoding.js +60 -0
  174. data/app/packs/src/decidim/impersonation.js +1 -1
  175. data/app/packs/src/decidim/index.js +13 -5
  176. data/app/packs/src/decidim/input_character_counter.js +1 -1
  177. data/app/packs/src/decidim/map/provider/here.js +1 -1
  178. data/app/packs/src/decidim/onboarding_pending_action.js +24 -0
  179. data/app/packs/src/decidim/session_timeouter.js +1 -1
  180. data/app/packs/src/decidim/sticky_footer.js +29 -0
  181. data/app/packs/src/decidim/sticky_header.js +6 -31
  182. data/app/packs/src/decidim/user_registrations.js +13 -0
  183. data/app/packs/src/decidim/utilities/dom.js +148 -0
  184. data/app/packs/src/decidim/vendor/leaflet-tilelayer-here.js +212 -0
  185. data/app/packs/stylesheets/decidim/_accordion.scss +30 -0
  186. data/app/packs/stylesheets/decidim/_buttons.scss +19 -0
  187. data/app/packs/stylesheets/decidim/_cards.scss +1 -1
  188. data/app/packs/stylesheets/decidim/_content_blocks.scss +0 -4
  189. data/app/packs/stylesheets/decidim/_dropdown.scss +1 -1
  190. data/app/packs/stylesheets/decidim/_endorsers_list.scss +26 -20
  191. data/app/packs/stylesheets/decidim/_forms.scss +2 -2
  192. data/app/packs/stylesheets/decidim/_header.scss +37 -60
  193. data/app/packs/stylesheets/decidim/_layout.scss +32 -2
  194. data/app/packs/stylesheets/decidim/_login.scss +53 -6
  195. data/app/packs/stylesheets/decidim/_modal.scss +42 -0
  196. data/app/packs/stylesheets/decidim/_modal_tos_refuse.scss +4 -0
  197. data/app/packs/stylesheets/decidim/_participatory_spaces.scss +46 -0
  198. data/app/packs/stylesheets/decidim/_profile.scss +1 -1
  199. data/app/packs/stylesheets/decidim/_success_image.scss +64 -0
  200. data/app/packs/stylesheets/decidim/_tribute.scss +36 -0
  201. data/app/packs/stylesheets/decidim/application.scss +1 -1
  202. data/app/packs/stylesheets/decidim/geocoding_addons.scss +5 -0
  203. data/app/packs/stylesheets/decidim/map.scss +7 -10
  204. data/app/packs/stylesheets/decidim/resource_history.scss +31 -0
  205. data/app/permissions/decidim/default_permissions.rb +0 -2
  206. data/app/permissions/decidim/permissions.rb +8 -2
  207. data/app/presenters/decidim/admin_log/base_user_presenter.rb +67 -0
  208. data/app/presenters/decidim/admin_log/component_presenter.rb +32 -3
  209. data/app/presenters/decidim/admin_log/moderation_presenter.rb +30 -3
  210. data/app/presenters/decidim/admin_log/share_token_presenter.rb +39 -0
  211. data/app/presenters/decidim/admin_log/taxonomy_filter_presenter.rb +57 -0
  212. data/app/presenters/decidim/admin_log/taxonomy_presenter.rb +48 -0
  213. data/app/presenters/decidim/admin_log/user_group_presenter.rb +6 -6
  214. data/app/presenters/decidim/admin_log/user_presenter.rb +4 -18
  215. data/app/presenters/decidim/log/user_presenter.rb +0 -1
  216. data/app/presenters/decidim/log/value_types/date_presenter.rb +1 -0
  217. data/app/presenters/decidim/log/value_types/taxonomy_presenter.rb +29 -0
  218. data/app/presenters/decidim/notification_to_mailer_presenter.rb +3 -7
  219. data/app/presenters/decidim/participatory_space_private_user_presenter.rb +50 -0
  220. data/app/presenters/decidim/taxonomy_filter_presenter.rb +19 -0
  221. data/app/presenters/decidim/taxonomy_presenter.rb +14 -0
  222. data/app/presenters/decidim/user_presenter.rb +1 -1
  223. data/app/queries/decidim/last_activity.rb +0 -25
  224. data/app/queries/decidim/metrics/blocked_users_metric_manage.rb +2 -2
  225. data/app/queries/decidim/metrics/users_metric_manage.rb +2 -2
  226. data/app/queries/decidim/public_activities.rb +1 -12
  227. data/app/queries/decidim/stats_users_count.rb +2 -2
  228. data/app/resolvers/decidim/meta_image_url_resolver.rb +128 -0
  229. data/app/serializers/decidim/exporters/open_data_blocked_user_serializer.rb +25 -0
  230. data/app/serializers/decidim/exporters/open_data_metric_serializer.rb +22 -0
  231. data/app/serializers/decidim/exporters/open_data_moderation_serializer.rb +30 -0
  232. data/app/serializers/decidim/exporters/open_data_taxonomy_serializer.rb +30 -0
  233. data/app/serializers/decidim/exporters/open_data_user_group_serializer.rb +38 -0
  234. data/app/serializers/decidim/exporters/open_data_user_serializer.rb +39 -0
  235. data/app/serializers/decidim/exporters/participatory_space_serializer.rb +104 -0
  236. data/app/serializers/decidim/exporters/serializer.rb +25 -0
  237. data/app/serializers/decidim/schema_org_breadcrumb_list_serializer.rb +52 -0
  238. data/app/services/decidim/action_authorizer.rb +32 -3
  239. data/app/services/decidim/base_diff_renderer.rb +1 -3
  240. data/app/services/decidim/download_your_data_exporter.rb +58 -24
  241. data/app/services/decidim/onboarding_manager.rb +272 -0
  242. data/app/services/decidim/open_data_exporter.rb +139 -13
  243. data/app/services/decidim/static_map_generator.rb +1 -1
  244. data/app/services/decidim/traceability.rb +13 -0
  245. data/app/uploaders/decidim/application_uploader.rb +1 -1
  246. data/app/validators/etiquette_validator.rb +9 -2
  247. data/app/validators/passthru_validator.rb +1 -1
  248. data/app/validators/translated_etiquette_validator.rb +32 -0
  249. data/app/views/decidim/account/_password_fields.html.erb +2 -2
  250. data/app/views/decidim/application/_accordion_section.html.erb +14 -0
  251. data/app/views/decidim/application/_collection.html.erb +30 -18
  252. data/app/views/decidim/devise/omniauth_registrations/new.html.erb +5 -1
  253. data/app/views/decidim/devise/omniauth_registrations/new_tos_fields.html.erb +29 -0
  254. data/app/views/decidim/devise/registrations/new.html.erb +10 -22
  255. data/app/views/decidim/devise/sessions/new.html.erb +24 -29
  256. data/app/views/decidim/devise/shared/_omniauth_buttons.html.erb +2 -4
  257. data/app/views/decidim/devise/shared/_tos_fields.html.erb +16 -0
  258. data/app/views/decidim/download_your_data/_export.html.erb +15 -0
  259. data/app/views/decidim/download_your_data/show.html.erb +51 -5
  260. data/app/views/decidim/endorsements/update_buttons_and_counters.js.erb +16 -19
  261. data/app/views/decidim/export_mailer/download_your_data_export.html.erb +2 -2
  262. data/app/views/decidim/export_mailer/export.html.erb +5 -1
  263. data/app/views/decidim/last_activities/index.html.erb +1 -1
  264. data/app/views/decidim/messaging/conversations/_reply_form.html.erb +2 -1
  265. data/app/views/decidim/messaging/conversations/_start.html.erb +1 -1
  266. data/app/views/decidim/notifications_settings/show.html.erb +22 -0
  267. data/app/views/decidim/open_data/_how_to_open_accordion_section.html.erb +15 -0
  268. data/app/views/decidim/open_data/index.html.erb +108 -0
  269. data/app/views/decidim/pages/show.html.erb +2 -1
  270. data/app/views/decidim/participatory_space_private_users/_participatory_space_private_user.html.erb +1 -0
  271. data/app/views/decidim/reported_mailer/hide.html.erb +9 -0
  272. data/app/views/decidim/reported_mailer/report.html.erb +1 -1
  273. data/app/views/decidim/searches/_count.html.erb +1 -1
  274. data/app/views/decidim/searches/_filters.html.erb +38 -40
  275. data/app/views/decidim/shared/_login_modal.html.erb +26 -20
  276. data/app/views/decidim/shared/_orders.html.erb +2 -2
  277. data/app/views/decidim/shared/_resource_actions.html.erb +21 -0
  278. data/app/views/decidim/shared/_results_per_page.html.erb +1 -1
  279. data/app/views/decidim/shared/filters/_check_boxes_tree.html.erb +1 -2
  280. data/app/views/decidim/shared/filters/_collection.html.erb +1 -1
  281. data/app/views/decidim/shared/filters/_dropdown_label.html.erb +7 -4
  282. data/app/views/kaminari/decidim/_page.html.erb +1 -1
  283. data/app/views/kaminari/decidim/_paginator.html.erb +1 -1
  284. data/app/views/layouts/decidim/_application.html.erb +0 -1
  285. data/app/views/layouts/decidim/_js_configuration.html.erb +1 -0
  286. data/app/views/layouts/decidim/_logo.html.erb +2 -2
  287. data/app/views/layouts/decidim/_logo_mobile.html.erb +1 -1
  288. data/app/views/layouts/decidim/_meta_tags_config.html.erb +6 -11
  289. data/app/views/layouts/decidim/_schema_org_breadcrumb_list.html.erb +3 -0
  290. data/app/views/layouts/decidim/_wrapper.html.erb +15 -9
  291. data/app/views/layouts/decidim/footer/_main_legal.html.erb +1 -1
  292. data/app/views/layouts/decidim/footer/_main_links.html.erb +1 -1
  293. data/app/views/layouts/decidim/header/_close_ephemeral_session.html.erb +25 -0
  294. data/app/views/layouts/decidim/header/_main.html.erb +14 -10
  295. data/app/views/layouts/decidim/header/_menu_breadcrumb_items.html.erb +2 -0
  296. data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_desktop.html.erb +11 -5
  297. data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile_tablet.html.erb +5 -5
  298. data/app/views/layouts/decidim/shared/_layout_item.html.erb +1 -1
  299. data/config/assets.rb +2 -1
  300. data/config/locales/ar.yml +35 -74
  301. data/config/locales/bg.yml +33 -74
  302. data/config/locales/bs-BA.yml +0 -2
  303. data/config/locales/ca.yml +370 -102
  304. data/config/locales/cs.yml +374 -102
  305. data/config/locales/de.yml +350 -88
  306. data/config/locales/el.yml +22 -58
  307. data/config/locales/en.yml +350 -82
  308. data/config/locales/eo.yml +0 -4
  309. data/config/locales/es-MX.yml +364 -99
  310. data/config/locales/es-PY.yml +369 -104
  311. data/config/locales/es.yml +370 -102
  312. data/config/locales/eu.yml +426 -156
  313. data/config/locales/fi-plain.yml +366 -76
  314. data/config/locales/fi.yml +370 -77
  315. data/config/locales/fr-CA.yml +176 -97
  316. data/config/locales/fr.yml +176 -94
  317. data/config/locales/ga-IE.yml +4 -25
  318. data/config/locales/gl.yml +20 -58
  319. data/config/locales/hu.yml +30 -62
  320. data/config/locales/id-ID.yml +21 -57
  321. data/config/locales/is-IS.yml +5 -25
  322. data/config/locales/it.yml +36 -94
  323. data/config/locales/ja.yml +231 -112
  324. data/config/locales/lb.yml +28 -76
  325. data/config/locales/lt.yml +24 -64
  326. data/config/locales/lv.yml +21 -58
  327. data/config/locales/nl.yml +23 -75
  328. data/config/locales/no.yml +23 -70
  329. data/config/locales/pl.yml +30 -72
  330. data/config/locales/pt-BR.yml +41 -63
  331. data/config/locales/pt.yml +23 -70
  332. data/config/locales/ro-RO.yml +115 -184
  333. data/config/locales/ru.yml +13 -43
  334. data/config/locales/sk.yml +24 -70
  335. data/config/locales/sl.yml +0 -4
  336. data/config/locales/sr-CS.yml +0 -2
  337. data/config/locales/sv.yml +138 -106
  338. data/config/locales/tr-TR.yml +29 -75
  339. data/config/locales/uk.yml +6 -29
  340. data/config/locales/zh-CN.yml +21 -68
  341. data/config/locales/zh-TW.yml +23 -62
  342. data/config/routes.rb +4 -10
  343. data/db/migrate/20171212103803_create_unique_nicknames.rb +1 -1
  344. data/db/migrate/20180221101934_fix_nickname_index.rb +1 -1
  345. data/db/migrate/20180706104107_add_nickname_to_managed_users.rb +1 -1
  346. data/db/migrate/20181001124950_move_users_groups_to_users_table.rb +1 -1
  347. data/db/migrate/20181025082245_add_timestamps_to_components.rb +2 -0
  348. data/db/migrate/20190412131728_fix_user_names.rb +1 -1
  349. data/db/migrate/20240628111905_add_visible_to_components.rb +7 -0
  350. data/db/migrate/20240704115429_create_decidim_taxonomies.rb +23 -0
  351. data/db/migrate/20240717093514_add_registered_only_to_decidim_share_tokens.rb +7 -0
  352. data/db/migrate/20240722215500_change_object_changes_on_versions.rb +39 -0
  353. data/db/migrate/20240806065417_create_decidim_taxonomy_filters.rb +23 -0
  354. data/db/migrate/20240822161348_add_deleted_at_to_decidim_components.rb +8 -0
  355. data/db/migrate/20240906162524_add_part_of_to_taxonomies.rb +26 -0
  356. data/db/migrate/20241001135825_add_role_to_participatory_space_private_users.rb +7 -0
  357. data/db/migrate/20241001140408_add_published_to_participatory_space_private_users.rb +7 -0
  358. data/db/migrate/20241022002600_create_private_exports.rb +18 -0
  359. data/db/migrate/20241028114430_add_component_counter_to_taxonomy_filters.rb +7 -0
  360. data/db/migrate/20241111104357_add_names_and_space_boolean_to_taxonomy_filters.rb +9 -0
  361. data/db/migrate/20241127093708_add_taxonomy_to_metrics.rb +7 -0
  362. data/db/migrate/20241204121445_add_participatory_space_manifests_from_taxonomy_filters.rb +9 -0
  363. data/decidim-core.gemspec +14 -17
  364. data/lib/decidim/action_authorization.rb +3 -2
  365. data/lib/decidim/amendable.rb +1 -1
  366. data/lib/decidim/api/input_filters/category_input_filter.rb +5 -3
  367. data/lib/decidim/api/input_filters/component_input_filter.rb +33 -20
  368. data/lib/decidim/api/input_filters/user_entity_input_filter.rb +53 -44
  369. data/lib/decidim/api/input_sorts/component_input_sort.rb +15 -13
  370. data/lib/decidim/api/input_sorts/user_entity_input_sort.rb +4 -4
  371. data/lib/decidim/api/interfaces/author_interface.rb +3 -2
  372. data/lib/decidim/api/interfaces/coauthorable_interface.rb +5 -5
  373. data/lib/decidim/api/interfaces/endorsable_interface.rb +2 -2
  374. data/lib/decidim/api/interfaces/participatory_space_interface.rb +5 -10
  375. data/lib/decidim/api/interfaces/taxonomizable_interface.rb +13 -0
  376. data/lib/decidim/api/types/amendment_type.rb +5 -7
  377. data/lib/decidim/api/types/area_api_type.rb +3 -3
  378. data/lib/decidim/api/types/attachment_type.rb +3 -3
  379. data/lib/decidim/api/types/category_type.rb +2 -2
  380. data/lib/decidim/api/types/decidim_type.rb +5 -1
  381. data/lib/decidim/api/types/fingerprint_type.rb +1 -1
  382. data/lib/decidim/api/types/localized_string_type.rb +1 -1
  383. data/lib/decidim/api/types/metric_history_type.rb +2 -0
  384. data/lib/decidim/api/types/metric_type.rb +1 -1
  385. data/lib/decidim/api/types/organization_type.rb +5 -0
  386. data/lib/decidim/api/types/participatory_space_link_type.rb +2 -2
  387. data/lib/decidim/api/types/participatory_space_manifest_type.rb +1 -1
  388. data/lib/decidim/api/types/quantifiable_translated_field_type.rb +1 -1
  389. data/lib/decidim/api/types/scope_api_type.rb +2 -3
  390. data/lib/decidim/api/types/session_type.rb +1 -2
  391. data/lib/decidim/api/types/taxonomy_type.rb +15 -0
  392. data/lib/decidim/api/types/trace_version_type.rb +2 -2
  393. data/lib/decidim/api/types/translated_field_type.rb +3 -5
  394. data/lib/decidim/api/types/user_group_type.rb +7 -20
  395. data/lib/decidim/api/types/user_type.rb +7 -20
  396. data/lib/decidim/asset_router/storage.rb +6 -11
  397. data/lib/decidim/assets/tailwind/tailwind.config.js.erb +2 -1
  398. data/lib/decidim/attachment_attributes.rb +1 -1
  399. data/lib/decidim/attribute_encryptor.rb +1 -1
  400. data/lib/decidim/attribute_object/nested_validator.rb +1 -1
  401. data/lib/decidim/attributes/integer_with_units.rb +27 -0
  402. data/lib/decidim/attributes/time_with_zone.rb +1 -5
  403. data/lib/decidim/attributes.rb +2 -0
  404. data/lib/decidim/authorization_form_builder.rb +0 -7
  405. data/lib/decidim/coauthorable.rb +1 -1
  406. data/lib/decidim/command.rb +3 -3
  407. data/lib/decidim/commands/destroy_resource.rb +5 -1
  408. data/lib/decidim/commands/resource_handler.rb +2 -2
  409. data/lib/decidim/commands/restore_resource.rb +45 -0
  410. data/lib/decidim/commands/soft_delete_resource.rb +63 -0
  411. data/lib/decidim/component_manifest.rb +7 -0
  412. data/lib/decidim/content_parsers/blob_parser.rb +8 -10
  413. data/lib/decidim/content_parsers/user_parser.rb +1 -1
  414. data/lib/decidim/core/api.rb +2 -0
  415. data/lib/decidim/core/engine.rb +21 -7
  416. data/lib/decidim/core/menu.rb +0 -5
  417. data/lib/decidim/core/seeds.rb +42 -2
  418. data/lib/decidim/core/test/factories.rb +105 -2
  419. data/lib/decidim/core/test/shared_examples/admin_resource_gallery_examples.rb +85 -0
  420. data/lib/decidim/core/test/shared_examples/comments_examples.rb +393 -38
  421. data/lib/decidim/core/test/shared_examples/components_controller_hide_shared_examples.rb +11 -0
  422. data/lib/decidim/core/test/shared_examples/components_controller_reorder_shared_examples.rb +21 -0
  423. data/lib/decidim/core/test/shared_examples/download_open_data_shared_context.rb +36 -0
  424. data/lib/decidim/core/test/shared_examples/download_open_data_shared_examples.rb +45 -0
  425. data/lib/decidim/core/test/shared_examples/download_your_data_shared_examples.rb +17 -0
  426. data/lib/decidim/core/test/shared_examples/etiquette_validator_examples.rb +25 -0
  427. data/lib/decidim/core/test/shared_examples/follows_examples.rb +43 -0
  428. data/lib/decidim/core/test/shared_examples/has_taxonomies.rb +94 -0
  429. data/lib/decidim/core/test/shared_examples/manage_share_tokens_examples.rb +237 -0
  430. data/lib/decidim/core/test/shared_examples/map_examples.rb +2 -0
  431. data/lib/decidim/core/test/shared_examples/open_data_exporter_examples.rb +102 -0
  432. data/lib/decidim/core/test/shared_examples/participatory_space_members_page_examples.rb +46 -0
  433. data/lib/decidim/core/test/shared_examples/participatory_space_search_examples.rb +98 -0
  434. data/lib/decidim/core/test/shared_examples/permissions.rb +7 -7
  435. data/lib/decidim/core/test/shared_examples/preview_with_share_token_examples.rb +94 -0
  436. data/lib/decidim/core/test/shared_examples/reports_examples.rb +15 -53
  437. data/lib/decidim/core/test/shared_examples/resource_endorsed_event_examples.rb +2 -2
  438. data/lib/decidim/core/test/shared_examples/resource_search_examples.rb +75 -69
  439. data/lib/decidim/core/test/shared_examples/searchable_resources_shared_context.rb +1 -1
  440. data/lib/decidim/core/test/shared_examples/simple_event.rb +33 -19
  441. data/lib/decidim/core/test/shared_examples/social_share_examples.rb +7 -14
  442. data/lib/decidim/core/test/shared_examples/softdeleteable_components_examples.rb +173 -0
  443. data/lib/decidim/core/test/shared_examples/system_endorse_resource_examples.rb +54 -8
  444. data/lib/decidim/core/test/shared_examples/taxonomizable_interface_examples.rb +20 -0
  445. data/lib/decidim/core/test/shared_examples/taxonomizable_resource_examples.rb +37 -0
  446. data/lib/decidim/core/test/shared_examples/taxonomy_settings.rb +49 -0
  447. data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +1 -1
  448. data/lib/decidim/core/test/shared_examples/uncommentable_component_examples.rb +0 -26
  449. data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +2 -28
  450. data/lib/decidim/core/test/shared_examples/with_endorsable_permissions_examples.rb +1 -1
  451. data/lib/decidim/core/test.rb +9 -5
  452. data/lib/decidim/core/version.rb +1 -1
  453. data/lib/decidim/core.rb +58 -0
  454. data/lib/decidim/download_your_data_serializers/download_your_data_identity_serializer.rb +0 -4
  455. data/lib/decidim/download_your_data_serializers/download_your_data_participatory_space_private_user_serializer.rb +3 -1
  456. data/lib/decidim/download_your_data_serializers/download_your_data_report_serializer.rb +2 -1
  457. data/lib/decidim/download_your_data_serializers/download_your_data_user_serializer.rb +6 -7
  458. data/lib/decidim/download_your_data_serializers.rb +19 -0
  459. data/lib/decidim/exporters/csv.rb +6 -0
  460. data/lib/decidim/exporters/export_manifest.rb +14 -0
  461. data/lib/decidim/exporters/pdf.rb +26 -22
  462. data/lib/decidim/filter_form_builder.rb +12 -15
  463. data/lib/decidim/form_builder.rb +6 -129
  464. data/lib/decidim/has_category.rb +5 -1
  465. data/lib/decidim/has_private_users.rb +4 -0
  466. data/lib/decidim/has_taxonomy_settings.rb +47 -0
  467. data/lib/decidim/has_upload_validations.rb +1 -1
  468. data/lib/decidim/legacy_form_builder.rb +118 -0
  469. data/lib/decidim/maintenance/import_models/application_record.rb +93 -0
  470. data/lib/decidim/maintenance/import_models/area.rb +82 -0
  471. data/lib/decidim/maintenance/import_models/area_type.rb +12 -0
  472. data/lib/decidim/maintenance/import_models/assembly_type.rb +49 -0
  473. data/lib/decidim/maintenance/import_models/categorization.rb +14 -0
  474. data/lib/decidim/maintenance/import_models/category.rb +107 -0
  475. data/lib/decidim/maintenance/import_models/participatory_process_type.rb +21 -0
  476. data/lib/decidim/maintenance/import_models/scope.rb +163 -0
  477. data/lib/decidim/maintenance/import_models.rb +19 -0
  478. data/lib/decidim/maintenance/taxonomy_importer.rb +132 -0
  479. data/lib/decidim/maintenance/taxonomy_plan.rb +78 -0
  480. data/lib/decidim/maintenance.rb +12 -0
  481. data/lib/decidim/map/autocomplete.rb +52 -8
  482. data/lib/decidim/map/dynamic_map.rb +1 -1
  483. data/lib/decidim/map/provider/dynamic_map/here.rb +40 -1
  484. data/lib/decidim/map/provider/geocoding/here.rb +9 -3
  485. data/lib/decidim/map/provider/static_map/here.rb +0 -34
  486. data/lib/decidim/map.rb +3 -6
  487. data/lib/decidim/moderation_tools.rb +16 -19
  488. data/lib/decidim/newsletter_encryptor.rb +1 -1
  489. data/lib/decidim/nicknamizable.rb +9 -6
  490. data/lib/decidim/paddable.rb +1 -1
  491. data/lib/decidim/participable.rb +10 -10
  492. data/lib/decidim/participatory_space_user.rb +10 -0
  493. data/lib/decidim/private_download_helper.rb +15 -0
  494. data/lib/decidim/record_encryptor.rb +51 -46
  495. data/lib/decidim/reportable.rb +2 -6
  496. data/lib/decidim/resourceable.rb +16 -0
  497. data/lib/decidim/seeds.rb +18 -20
  498. data/lib/decidim/settings_manifest.rb +34 -1
  499. data/lib/decidim/soft_deletable.rb +17 -0
  500. data/lib/decidim/taxonomizable.rb +72 -0
  501. data/lib/decidim/translatable_attributes.rb +1 -5
  502. data/lib/decidim/view_model.rb +0 -1
  503. data/lib/tasks/decidim_download_your_data_tasks.rake +2 -4
  504. data/lib/tasks/decidim_procfile.rake +6 -0
  505. data/lib/tasks/decidim_tasks.rake +1 -0
  506. data/lib/tasks/decidim_taxonomies.rake +155 -0
  507. data/lib/tasks/upgrade/{decidim_fix_categorization.rake → clean.rake} +25 -18
  508. data/lib/tasks/upgrade/decidim_active_storage_migration_tasks.rake +1 -1
  509. data/lib/tasks/upgrade/decidim_fix_nickname_uniqueness.rake +20 -23
  510. data/lib/tasks/upgrade/migrations.rake +91 -0
  511. metadata +203 -112
  512. data/app/cells/decidim/amendable/amenders_list/show.erb +0 -0
  513. data/app/cells/decidim/content_blocks/base/content.erb +0 -0
  514. data/app/cells/decidim/endorsers_list/full_endorsers_list.erb +0 -3
  515. data/app/cells/decidim/endorsers_list_button/content.erb +0 -1
  516. data/app/cells/decidim/endorsers_list_button_cell.rb +0 -15
  517. data/app/cells/decidim/report_user_button/already_reported_modal.erb +0 -11
  518. data/app/cells/decidim/report_user_button/flag_modal.erb +0 -46
  519. data/app/cells/decidim/report_user_button/show.erb +0 -2
  520. data/app/cells/decidim/report_user_button_cell.rb +0 -59
  521. data/app/cells/decidim/scopes_picker/scope_picker_prompt.erb +0 -3
  522. data/app/cells/decidim/scopes_picker/scope_picker_values.erb +0 -5
  523. data/app/cells/decidim/scopes_picker/show.erb +0 -14
  524. data/app/cells/decidim/scopes_picker_cell.rb +0 -92
  525. data/app/commands/decidim/update_user_interests.rb +0 -41
  526. data/app/controllers/decidim/scopes_controller.rb +0 -84
  527. data/app/controllers/decidim/user_interests_controller.rb +0 -30
  528. data/app/forms/decidim/user_interest_scope_form.rb +0 -25
  529. data/app/forms/decidim/user_interests_form.rb +0 -17
  530. data/app/helpers/decidim/categories_helper.rb +0 -26
  531. data/app/helpers/decidim/scopes_helper.rb +0 -105
  532. data/app/jobs/decidim/hide_child_resources_job.rb +0 -24
  533. data/app/packs/images/decidim/vendor/leaflet/layers-2x.png +0 -0
  534. data/app/packs/images/decidim/vendor/leaflet/layers.png +0 -0
  535. data/app/packs/images/decidim/vendor/leaflet/marker-icon-2x.png +0 -0
  536. data/app/packs/images/decidim/vendor/leaflet/marker-icon.png +0 -0
  537. data/app/packs/images/decidim/vendor/leaflet/marker-shadow.png +0 -0
  538. data/app/packs/stylesheets/decidim/_hashtags.scss +0 -5
  539. data/app/packs/stylesheets/decidim/legacy/MarkerCluster.Default.scss +0 -67
  540. data/app/packs/stylesheets/decidim/legacy/MarkerCluster.scss +0 -18
  541. data/app/packs/stylesheets/decidim/legacy/leaflet.scss +0 -705
  542. data/app/validators/scope_belongs_to_component_validator.rb +0 -16
  543. data/app/views/decidim/account/_user_groups.html.erb +0 -0
  544. data/app/views/decidim/reported_mailer/hidden_automatically.html.erb +0 -25
  545. data/app/views/decidim/reported_mailer/hidden_manually.html.erb +0 -25
  546. data/app/views/decidim/scopes/_scopes_picker_input.html.erb +0 -19
  547. data/app/views/decidim/scopes/picker.html.erb +0 -53
  548. data/app/views/decidim/shared/_comments.html.erb +0 -0
  549. data/app/views/decidim/shared/_share_modal.html.erb +0 -26
  550. data/app/views/decidim/shared/_tags.html.erb +0 -1
  551. data/app/views/decidim/user_interests/_areas.html.erb +0 -14
  552. data/app/views/decidim/user_interests/_scopes.html.erb +0 -22
  553. data/app/views/decidim/user_interests/show.html.erb +0 -22
  554. data/config/initializers/foundation_rails_helper.rb +0 -4
  555. data/config/locales/ca-IT.yml +0 -2122
  556. data/lib/decidim/core/test/shared_examples/has_category.rb +0 -38
  557. data/lib/decidim/core/test/shared_examples/has_scope.rb +0 -11
  558. data/lib/decidim/core/test/shared_examples/manage_component_share_tokens.rb +0 -83
  559. data/lib/decidim/core/test/shared_examples/preview_component_with_share_token_examples.rb +0 -49
  560. data/lib/decidim/core/test/shared_examples/scope_helper_examples.rb +0 -93
  561. data/lib/decidim/seven_zip_wrapper.rb +0 -29
  562. data/lib/tasks/upgrade/clean_hidden_resources.rake +0 -33
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # Represents a hierarchical classification used to organize various entities within the system.
5
+ # Taxonomies are primarily used to categorize and manage different aspects of participatory spaces,
6
+ # such as proposals, assemblies, and other components, within an organization.
7
+ class Taxonomy < ApplicationRecord
8
+ include Decidim::TranslatableResource
9
+ include Decidim::FilterableResource
10
+ include Decidim::Traceable
11
+
12
+ before_create :set_default_weight
13
+ before_validation :update_part_of, on: [:update, :create]
14
+ after_create_commit :create_part_of
15
+
16
+ translatable_fields :name
17
+
18
+ belongs_to :organization,
19
+ foreign_key: "decidim_organization_id",
20
+ class_name: "Decidim::Organization",
21
+ inverse_of: :taxonomies
22
+
23
+ belongs_to :parent,
24
+ class_name: "Decidim::Taxonomy",
25
+ counter_cache: :children_count,
26
+ inverse_of: :children,
27
+ optional: true
28
+
29
+ has_many :children,
30
+ foreign_key: "parent_id",
31
+ class_name: "Decidim::Taxonomy",
32
+ inverse_of: :parent,
33
+ dependent: :destroy
34
+
35
+ has_many :taxonomizations, class_name: "Decidim::Taxonomization", dependent: :destroy
36
+ has_many :taxonomy_filters, foreign_key: "root_taxonomy_id", class_name: "Decidim::TaxonomyFilter", dependent: :destroy
37
+ has_many :taxonomy_filter_items, foreign_key: "taxonomy_item_id", class_name: "Decidim::TaxonomyFilterItem", dependent: :destroy
38
+
39
+ validates :name, presence: true
40
+ validates :weight, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
41
+ validate :validate_max_children_levels
42
+ validate :forbid_cycles
43
+
44
+ default_scope { order(:weight) }
45
+ scope :for, ->(organization) { where(organization:) }
46
+ scope :roots, -> { where(parent_id: nil) }
47
+ scope :non_roots, -> { where.not(parent_id: nil) }
48
+
49
+ ransacker_i18n :name
50
+
51
+ scope :search_by_name, lambda { |name|
52
+ where("name ->> ? ILIKE ?", I18n.locale.to_s, "%#{name}%")
53
+ }
54
+
55
+ scope :part_of, lambda { |id|
56
+ where("part_of @> ARRAY[?]", id.to_i)
57
+ }
58
+
59
+ def self.log_presenter_class_for(_log)
60
+ Decidim::AdminLog::TaxonomyPresenter
61
+ end
62
+
63
+ def self.ransackable_scopes(_auth_object = nil)
64
+ [:search_by_name, :part_of]
65
+ end
66
+
67
+ def self.ransackable_attributes(_auth_object = nil)
68
+ %w(id name parent_id part_of)
69
+ end
70
+
71
+ def self.ransackable_associations(_auth_object = nil)
72
+ %w(children)
73
+ end
74
+
75
+ def translated_name
76
+ Decidim::TaxonomyPresenter.new(self).translated_name
77
+ end
78
+
79
+ def root_taxonomy
80
+ @root_taxonomy ||= root? ? self : parent.root_taxonomy
81
+ end
82
+
83
+ def parent_ids
84
+ @parent_ids ||= part_of.excluding(id)
85
+ end
86
+
87
+ def root? = parent_id.nil?
88
+
89
+ # this might change in the future if we want to prevent the deletion of taxonomies with associated resources
90
+ def removable?
91
+ true
92
+ end
93
+
94
+ def all_children
95
+ @all_children ||= Decidim::Taxonomy.non_roots.part_of(id).reorder(Arel.sql("array_length(part_of, 1) ASC"), "parent_id ASC", "weight ASC")
96
+ end
97
+
98
+ def reset_all_counters
99
+ Taxonomy.reset_counters(id, :children_count, :taxonomizations_count, :taxonomy_filters_count, :taxonomy_filter_items_count)
100
+ end
101
+
102
+ private
103
+
104
+ def set_default_weight
105
+ return if weight.present?
106
+
107
+ self.weight = Taxonomy.where(parent_id:).count
108
+ end
109
+
110
+ def forbid_cycles
111
+ return unless parent_id
112
+
113
+ errors.add(:parent_id, :invalid) if parent.part_of.include?(id)
114
+ end
115
+
116
+ def create_part_of
117
+ build_part_of
118
+ save if changed?
119
+ end
120
+
121
+ def update_part_of
122
+ build_part_of
123
+ end
124
+
125
+ def build_part_of
126
+ if parent
127
+ part_of.clear.append(id).concat(parent.reload.part_of)
128
+ else
129
+ part_of.clear.append(id)
130
+ end
131
+ end
132
+
133
+ def validate_max_children_levels
134
+ return unless parent_id
135
+
136
+ errors.add(:base, :invalid) if parent_ids.size > 3
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # Represents the association between a taxonomy and a filterable entity within the system.
5
+ class TaxonomyFilter < ApplicationRecord
6
+ include Decidim::TranslatableResource
7
+ include Decidim::Traceable
8
+
9
+ translatable_fields :name, :internal_name
10
+
11
+ belongs_to :root_taxonomy,
12
+ class_name: "Decidim::Taxonomy",
13
+ counter_cache: :filters_count,
14
+ inverse_of: :taxonomy_filters
15
+
16
+ has_many :filter_items,
17
+ class_name: "Decidim::TaxonomyFilterItem",
18
+ inverse_of: :taxonomy_filter,
19
+ dependent: :destroy
20
+
21
+ validate :root_taxonomy_is_root
22
+ validate :space_manifest_is_registered
23
+
24
+ scope :for_manifest, ->(space_manifest) { where("? = ANY(participatory_space_manifests)", space_manifest) }
25
+ scope :space_filters, -> { where.not(participatory_space_manifests: []) }
26
+ # filters for the organization
27
+ scope :for, ->(organization) { joins(:root_taxonomy).where(decidim_taxonomies: { decidim_organization_id: organization.id }) }
28
+
29
+ delegate :organization, to: :root_taxonomy
30
+ delegate :translated_name, :translated_internal_name, to: :presenter
31
+
32
+ def presenter
33
+ Decidim::TaxonomyFilterPresenter.new(self)
34
+ end
35
+
36
+ # Returns the presenter class for this log.
37
+ #
38
+ # log - A Decidim::Log instance.
39
+ #
40
+ # Returns a Decidim::AdminLog::TaxonomyFilterPresenter class
41
+ def self.log_presenter_class_for(_log)
42
+ Decidim::AdminLog::TaxonomyFilterPresenter
43
+ end
44
+
45
+ # Public name for this filter, defaults to the root taxonomy name.
46
+ def name
47
+ return root_taxonomy&.name if super&.compact_blank.blank?
48
+
49
+ super
50
+ end
51
+
52
+ # Internal name for this filter, defaults to the root taxonomy name.
53
+ def internal_name
54
+ return root_taxonomy&.name if super&.compact_blank.blank?
55
+
56
+ super
57
+ end
58
+
59
+ # Components that have this taxonomy filter enabled.
60
+ def components
61
+ @components ||= Decidim::Component.where("(settings->'global'->'taxonomy_filters') @> ?", "\"#{id}\"")
62
+ end
63
+
64
+ def filter_taxonomy_ids
65
+ @filter_taxonomy_ids ||= filter_items.map(&:taxonomy_item_id)
66
+ end
67
+
68
+ # A memoized taxonomy tree hash filtered according to the filter_items
69
+
70
+ # that respects the order given by the taxonomies table.
71
+ # The returned hash structure is:
72
+ # {
73
+ # _object_id_ => {
74
+ # taxonomy: _object_,
75
+ # children: {
76
+ # _sub_object_id_: {
77
+ # taxonomy: _sub_object_,
78
+ # children: {
79
+ # ...
80
+ # }
81
+ # @returns [Hash] a hash with the taxonomy tree structure.
82
+ def taxonomies
83
+ @taxonomies ||= root_taxonomy
84
+ .all_children
85
+ .where(id: filter_taxonomy_ids)
86
+ .each_with_object({}) do |taxonomy, tree|
87
+ insert_child(taxonomy, tree)
88
+ end
89
+ end
90
+
91
+ def update_components_count
92
+ update(components_count: components.count)
93
+ end
94
+
95
+ def reset_all_counters
96
+ Decidim::TaxonomyFilter.reset_counters(id, :filter_items_count)
97
+ update_components_count
98
+ end
99
+
100
+ private
101
+
102
+ def insert_child(taxonomy, tree)
103
+ return if tree[taxonomy.id]
104
+
105
+ if (parent = find_parent(taxonomy, tree))
106
+ insert_child(taxonomy, parent[:children])
107
+ else
108
+ tree[taxonomy.id] = { taxonomy:, children: {} }
109
+ end
110
+ end
111
+
112
+ def find_parent(taxonomy, tree)
113
+ tree[taxonomy.parent_id].presence ||
114
+ tree.values.detect { |v| find_parent(taxonomy, v[:children]) }
115
+ end
116
+
117
+ def root_taxonomy_is_root
118
+ return if root_taxonomy&.root?
119
+
120
+ errors.add(:root_taxonomy, :invalid)
121
+ end
122
+
123
+ def space_manifest_is_registered
124
+ available_manifests = Decidim.participatory_space_manifests.map(&:name)
125
+ return if (participatory_space_manifests.map(&:to_sym) - available_manifests).empty?
126
+
127
+ errors.add(:participatory_space_manifests, :invalid)
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # Represents the association between a taxonomy and a filterable entity within the system.
5
+ class TaxonomyFilterItem < ApplicationRecord
6
+ belongs_to :taxonomy_filter,
7
+ class_name: "Decidim::TaxonomyFilter",
8
+ counter_cache: :filter_items_count,
9
+ inverse_of: :filter_items
10
+
11
+ belongs_to :taxonomy_item,
12
+ class_name: "Decidim::Taxonomy",
13
+ counter_cache: :filter_items_count,
14
+ inverse_of: :taxonomy_filter_items
15
+
16
+ validate :taxonomy_item_is_not_root
17
+ validate :taxonomy_item_is_child_of_taxonomy_filter_root
18
+
19
+ private
20
+
21
+ def taxonomy_item_is_not_root
22
+ return unless taxonomy_item&.root?
23
+
24
+ errors.add(:taxonomy_item, :invalid)
25
+ end
26
+
27
+ def taxonomy_item_is_child_of_taxonomy_filter_root
28
+ return if taxonomy_item&.root_taxonomy == taxonomy_filter&.root_taxonomy
29
+
30
+ errors.add(:taxonomy_item, :invalid)
31
+ end
32
+ end
33
+ end
@@ -13,6 +13,8 @@ module Decidim
13
13
  include Decidim::UserReportable
14
14
  include Decidim::Traceable
15
15
 
16
+ REGEXP_NICKNAME = /\A[\w-]+\z/
17
+
16
18
  class Roles
17
19
  def self.all
18
20
  Decidim.config.user_roles
@@ -33,6 +35,7 @@ module Decidim
33
35
  has_many :access_grants, class_name: "Doorkeeper::AccessGrant", foreign_key: :resource_owner_id, dependent: :destroy
34
36
  has_many :access_tokens, class_name: "Doorkeeper::AccessToken", foreign_key: :resource_owner_id, dependent: :destroy
35
37
  has_many :reminders, foreign_key: "decidim_user_id", class_name: "Decidim::Reminder", dependent: :destroy
38
+ has_many :private_exports, class_name: "Decidim::PrivateExport", dependent: :destroy, inverse_of: :attached_to, as: :attached_to
36
39
 
37
40
  validates :name, presence: true, unless: -> { deleted? }
38
41
  validates :nickname,
@@ -43,37 +46,28 @@ module Decidim
43
46
  validates :locale, inclusion: { in: :available_locales }, allow_blank: true
44
47
  validates :tos_agreement, acceptance: true, allow_nil: false, on: :create
45
48
  validates :tos_agreement, acceptance: true, if: :user_invited?
49
+ validates :tos_agreement, acceptance: true, if: :ephemeral?
46
50
  validates :email, :nickname, uniqueness: { scope: :organization }, unless: -> { deleted? || managed? || nickname.blank? }
47
51
 
48
52
  validate :all_roles_are_valid
49
53
 
50
54
  has_one_attached :download_your_data_file
51
55
 
56
+ scope :not_deleted, -> { where(deleted_at: nil) }
57
+
52
58
  scope :managed, -> { where(managed: true) }
53
59
  scope :not_managed, -> { where(managed: false) }
54
60
 
55
61
  scope :officialized, -> { where.not(officialized_at: nil) }
56
62
  scope :not_officialized, -> { where(officialized_at: nil) }
57
63
 
58
- scope :interested_in_scopes, lambda { |scope_ids|
59
- actual_ids = scope_ids.select(&:presence)
60
- if actual_ids.count.positive?
61
- ids = actual_ids.map(&:to_i).join(",")
62
- where(Arel.sql("extended_data->'interested_scopes' @> ANY('{#{ids}}')").to_s)
63
- else
64
- # Do not apply the scope filter when there are scope ids available. Note
65
- # that the active record scope must always return an active record
66
- # collection.
67
- self
68
- end
69
- }
70
-
71
64
  scope :org_admins_except_me, ->(user) { where(organization: user.organization, admin: true).where.not(id: user.id) }
72
65
 
66
+ scope :ephemeral, -> { where("extended_data @> ?", Arel.sql({ ephemeral: true }.to_json)) }
67
+
73
68
  attr_accessor :newsletter_notifications
74
69
 
75
70
  searchable_fields({
76
- # scope_id: :decidim_scope_id,
77
71
  organization_id: :decidim_organization_id,
78
72
  A: :name,
79
73
  B: :nickname,
@@ -191,7 +185,7 @@ module Decidim
191
185
  end
192
186
 
193
187
  def tos_accepted?
194
- return true if managed
188
+ return true if managed && !ephemeral?
195
189
  return false if accepted_tos_version.nil?
196
190
 
197
191
  # For some reason, if we do not use `#to_i` here we get some
@@ -213,14 +207,6 @@ module Decidim
213
207
  ImpersonationLog.active.exists?(user: self)
214
208
  end
215
209
 
216
- def interested_scopes_ids
217
- extended_data["interested_scopes"] || []
218
- end
219
-
220
- def interested_scopes
221
- @interested_scopes ||= organization.scopes.where(id: interested_scopes_ids)
222
- end
223
-
224
210
  def user_name
225
211
  extended_data["user_name"] || name
226
212
  end
@@ -274,6 +260,10 @@ module Decidim
274
260
  false
275
261
  end
276
262
 
263
+ def ephemeral?
264
+ extended_data["ephemeral"]
265
+ end
266
+
277
267
  def after_confirmation
278
268
  return unless organization.send_welcome_notification?
279
269
 
@@ -21,13 +21,11 @@ module Decidim
21
21
 
22
22
  # Regex for name & nickname format validations
23
23
  REGEXP_NAME = /\A(?!.*[<>?%&\^*#@()\[\]=+:;"{}\\|])/
24
- REGEXP_NICKNAME = /\A[a-z0-9_-]+\z/
25
24
 
26
25
  has_one_attached :avatar
27
26
  validates_avatar :avatar, uploader: Decidim::AvatarUploader
28
27
 
29
28
  validates :name, format: { with: REGEXP_NAME }
30
- validates :nickname, format: { with: REGEXP_NICKNAME }, unless: -> { deleted? || managed? }
31
29
 
32
30
  scope :confirmed, -> { where.not(confirmed_at: nil) }
33
31
  scope :not_confirmed, -> { where(confirmed_at: nil) }
@@ -36,8 +34,6 @@ module Decidim
36
34
  scope :not_blocked, -> { where(blocked: false) }
37
35
  scope :available, -> { where(deleted_at: nil, blocked: false, managed: false) }
38
36
 
39
- scope :not_deleted, -> { where(deleted_at: nil) }
40
-
41
37
  # Public: Returns a collection with all the public entities this user is following.
42
38
  #
43
39
  # This cannot be done as with a `has_many :following, through: :following_follows`
@@ -69,6 +65,18 @@ module Decidim
69
65
  Decidim::UserBaseEntity.joins(:follows).where(decidim_follows: { user: self }).blocked.exists?
70
66
  end
71
67
 
68
+ def self.ransackable_attributes(auth_object = nil)
69
+ base = %w(name email nickname last_sign_in_at)
70
+
71
+ return base unless auth_object&.admin?
72
+
73
+ base + %w(invitation_sent_at invitation_accepted_at officialized_at)
74
+ end
75
+
76
+ def self.ransackable_associations(_auth_object = nil)
77
+ []
78
+ end
79
+
72
80
  private
73
81
 
74
82
  def only_public(klass, ids)
@@ -6,6 +6,7 @@ module Decidim
6
6
  include Loggable
7
7
 
8
8
  belongs_to :user, foreign_key: :decidim_user_id, class_name: "Decidim::UserBaseEntity"
9
+ has_one :blocking, through: :user
9
10
  has_many :reports, class_name: "Decidim::UserReport", dependent: :destroy
10
11
 
11
12
  scope :blocked, -> { joins(:user).where(decidim_users: { blocked: true }) }
@@ -16,5 +17,13 @@ module Decidim
16
17
  def self.log_presenter_class_for(_log)
17
18
  Decidim::AdminLog::UserModerationPresenter
18
19
  end
20
+
21
+ def self.ransackable_attributes(_auth_object = nil)
22
+ []
23
+ end
24
+
25
+ def self.ransackable_associations(_auth_object = nil)
26
+ %w(reports user)
27
+ end
19
28
  end
20
29
  end
@@ -19,6 +19,10 @@ module Decidim
19
19
  # Decidim::DownloadYourDataSerializers::DownloadYourDataReportSerializer
20
20
  end
21
21
 
22
+ def self.ransackable_attributes(_auth_object = nil)
23
+ %w(reason)
24
+ end
25
+
22
26
  private
23
27
 
24
28
  # Private: check if the moderation and the user have the same organization
@@ -6,6 +6,7 @@ import "src/decidim/decidim_application"
6
6
 
7
7
  // CSS
8
8
  import "entrypoints/decidim_core.scss"
9
+ import "stylesheets/decidim/resource_history.scss"
9
10
 
10
11
  // Images
11
12
  require.context("../images", true)
@@ -0,0 +1,2 @@
1
+ import "src/decidim/geocoding/reverse_geocoding.js"
2
+ import "stylesheets/decidim/geocoding_addons.scss";
@@ -0,0 +1,10 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#clip0_29214_25190)">
3
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M24 12.0707C24 5.40424 18.6274 0 12 0C5.37258 0 0 5.40424 0 12.0707C0 18.0956 4.38823 23.0893 10.125 23.9948V15.5599H7.07812V12.0707H10.125V9.41139C10.125 6.38617 11.9165 4.71513 14.6576 4.71513C15.9705 4.71513 17.3438 4.95088 17.3438 4.95088V7.92141H15.8306C14.3399 7.92141 13.875 8.85187 13.875 9.80645V12.0707H17.2031L16.6711 15.5599H13.875V23.9948C19.6118 23.0893 24 18.0956 24 12.0707Z" fill="white"/>
4
+ </g>
5
+ <defs>
6
+ <clipPath id="clip0_29214_25190">
7
+ <rect width="24" height="24" fill="white"/>
8
+ </clipPath>
9
+ </defs>
10
+ </svg>
@@ -1 +1,7 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42" height="42" viewBox="2 -2 42 42"><defs><filter id="b" width="2" height="2" x="-.5" y="-.5" filterUnits="objectBoundingBox"><feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation=".5"/><feColorMatrix in="shadowBlurOuter1" result="shadowMatrixOuter1" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.168 0"/><feOffset in="SourceAlpha" result="shadowOffsetOuter2"/><feGaussianBlur in="shadowOffsetOuter2" result="shadowBlurOuter2" stdDeviation=".5"/><feColorMatrix in="shadowBlurOuter2" result="shadowMatrixOuter2" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.084 0"/><feMerge><feMergeNode in="shadowMatrixOuter1"/><feMergeNode in="shadowMatrixOuter2"/><feMergeNode in="SourceGraphic"/></feMerge></filter><rect id="a" width="40" height="40" x="0" y="0" rx="2"/></defs><use width="100%" height="100%" fill="#fff" fill-rule="evenodd" filter="url(#b)" transform="translate(3 -1)" xlink:href="#a"/><use width="100%" height="100%" fill="none" fill-rule="evenodd" filter="url(#b)" transform="translate(3 -1)" xlink:href="#a"/><use width="100%" height="100%" fill="none" fill-rule="evenodd" filter="url(#b)" transform="translate(3 -1)" xlink:href="#a"/><use width="100%" height="100%" fill="none" fill-rule="evenodd" filter="url(#b)" transform="translate(3 -1)" xlink:href="#a"/><path fill="#4285f4" fill-rule="evenodd" d="M31.64 19.205c0-.639-.057-1.252-.164-1.841H23v3.481h4.844a4.14 4.14 0 01-1.796 2.716v2.259h2.908c1.702-1.567 2.684-3.875 2.684-6.615z"/><path fill="#34a853" fill-rule="evenodd" d="M23 28c2.43 0 4.467-.806 5.956-2.18l-2.908-2.259c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711h-3.007v2.332A8.997 8.997 0 0023 28z"/><path fill="#fbbc05" fill-rule="evenodd" d="M17.964 20.71a5.41 5.41 0 01-.282-1.71c0-.593.102-1.17.282-1.71v-2.332h-3.007A8.996 8.996 0 0014 19c0 1.452.348 2.827.957 4.042z"/><path fill="#ea4335" fill-rule="evenodd" d="M23 13.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C27.463 10.891 25.426 10 23 10a8.997 8.997 0 00-8.043 4.958l3.007 2.332c.708-2.127 2.692-3.71 5.036-3.71z"/><path fill="none" d="M14 10h18v18H14z"/></svg>
1
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: block;">
2
+ <path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"></path>
3
+ <path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"></path>
4
+ <path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"></path>
5
+ <path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"></path>
6
+ <path fill="none" d="M0 0h48v48H0z"></path>
7
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-twitter-x" viewBox="0 0 16 16">
2
+ <path d="M12.6.75h2.454l-5.36 6.142L16 15.25h-4.937l-3.867-5.07-4.425 5.07H.316l5.733-6.57L0 .75h5.063l3.495 4.633L12.601.75Zm-.86 13.028h1.36L4.323 2.145H2.865z"/>
3
+ </svg>
@@ -101,7 +101,6 @@ export default class CheckBoxesTree {
101
101
  const indeterminateSiblings = totalCheckSiblings.filter((checkbox) => checkbox.indeterminate)
102
102
 
103
103
  if (checkedSiblings.length === 0 && indeterminateSiblings.length === 0) {
104
- parentCheck.checked = false;
105
104
  parentCheck.indeterminate = false;
106
105
  } else if (checkedSiblings.length === totalCheckSiblings.length && indeterminateSiblings.length === 0) {
107
106
  parentCheck.checked = true;
@@ -21,7 +21,9 @@ import select from "select";
21
21
  *
22
22
  * Options through data attributes:
23
23
  * - `data-clipboard-copy` = The jQuery selector for the target input element
24
- * where text will be copied from.
24
+ * where text will be copied from. If this element does not contain any visible text (for instance is an image),
25
+ * the selector indicated in here will be used to place the confirmation message.
26
+ * - `data-clipboard-content` = The text that will be copied. If empty or not present, the target input element will be used.
25
27
  * - `data-clipboard-copy-label` = The label that will be shown in the button
26
28
  * after a succesful copy.
27
29
  * - `data-clipboard-copy-message` = The text that will be announced to screen
@@ -40,12 +42,17 @@ $(() => {
40
42
  }
41
43
 
42
44
  const $input = $($el.data("clipboard-copy"));
43
- if ($input.length < 1 || !$input.is("input, textarea, select")) {
44
- return;
45
+
46
+ let selectedText = $el.data("clipboard-content") || "";
47
+ if (selectedText === "" && $input.is("input, textarea, select")) {
48
+ selectedText = select($input[0]);
45
49
  }
46
50
 
51
+ let $msgEl = $el;
52
+ if ($msgEl.text() === "") {
53
+ $msgEl = $input;
54
+ }
47
55
  // Get the available text to clipboard.
48
- const selectedText = select($input[0]);
49
56
  if (!selectedText || selectedText.length < 1) {
50
57
  return;
51
58
  }
@@ -83,16 +90,18 @@ $(() => {
83
90
  }
84
91
 
85
92
  if (!$el.data("clipboard-copy-label-original")) {
86
- $el.data("clipboard-copy-label-original", $el.html());
93
+ $el.data("clipboard-copy-label-original", $msgEl.html());
87
94
  }
88
95
 
89
- $el.html(label);
96
+ $msgEl.html(label);
97
+
90
98
  to = setTimeout(() => {
91
- $el.html($el.data("clipboard-copy-label-original"));
99
+ $msgEl.html($el.data("clipboard-copy-label-original"));
92
100
  $el.removeData("clipboard-copy-label-original");
93
101
  $el.removeData("clipboard-copy-label-timeout");
94
102
  }, CLIPBOARD_COPY_TIMEOUT);
95
- $el.data("clipboard-copy-label-timeout", to)
103
+
104
+ $el.data("clipboard-copy-label-timeout", to);
96
105
  }
97
106
 
98
107
  // Alert the screen reader what just happened (the link was copied).
@@ -107,7 +116,7 @@ $(() => {
107
116
  }
108
117
  } else {
109
118
  $msg = $('<div aria-role="alert" aria-live="assertive" aria-atomic="true" class="sr-only"></div>');
110
- $el.after($msg);
119
+ $msgEl.append($msg);
111
120
  $el.data("clipboard-message-element", $msg);
112
121
  }
113
122