decidim-core 0.29.5 → 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 (595) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/activity/show.erb +6 -6
  3. data/app/cells/decidim/address/show.erb +3 -3
  4. data/app/cells/decidim/amendable/amend_button_card/show.erb +6 -4
  5. data/app/cells/decidim/amendable/amend_button_card_cell.rb +8 -0
  6. data/app/cells/decidim/amendable/amendments/show.erb +1 -1
  7. data/app/cells/decidim/amendable/promote_button_card/show.erb +2 -0
  8. data/app/cells/decidim/author/flag.erb +6 -0
  9. data/app/cells/decidim/author/flag_user.erb +14 -0
  10. data/app/cells/decidim/author/show.erb +4 -2
  11. data/app/cells/decidim/author_cell.rb +1 -1
  12. data/app/cells/decidim/card_l/extra_data.erb +1 -0
  13. data/app/cells/decidim/card_metadata_cell.rb +9 -16
  14. data/app/cells/decidim/comments_button_cell.rb +14 -2
  15. data/app/cells/decidim/content_blocks/highlighted_elements_cell.rb +2 -0
  16. data/app/cells/decidim/content_blocks/highlighted_elements_with_cell_for_list_cell.rb +1 -1
  17. data/app/cells/decidim/content_blocks/participatory_space_extra_data/extra_data.erb +2 -2
  18. data/app/cells/decidim/content_blocks/participatory_space_main_data/title.erb +2 -11
  19. data/app/cells/decidim/endorsement_block/show.erb +0 -1
  20. data/app/cells/decidim/endorsement_block_cell.rb +6 -0
  21. data/app/cells/decidim/endorsement_buttons/button_content.erb +1 -1
  22. data/app/cells/decidim/endorsement_buttons/select_identity_button.erb +1 -1
  23. data/app/cells/decidim/endorsement_buttons/show.erb +7 -7
  24. data/app/cells/decidim/endorsement_buttons/verification_modal.erb +4 -2
  25. data/app/cells/decidim/endorsers_list/empty.erb +3 -0
  26. data/app/cells/decidim/endorsers_list/full.erb +17 -5
  27. data/app/cells/decidim/endorsers_list/show.erb +19 -10
  28. data/app/cells/decidim/endorsers_list_cell.rb +19 -6
  29. data/app/cells/decidim/flag_modal/flag_user.erb +34 -0
  30. data/app/cells/decidim/flag_modal/show.erb +52 -0
  31. data/app/cells/decidim/flag_modal_cell.rb +56 -0
  32. data/app/cells/decidim/follow_button/show.erb +1 -2
  33. data/app/cells/decidim/follow_button_cell.rb +5 -0
  34. data/app/cells/decidim/footer_topics/show.erb +2 -2
  35. data/app/cells/decidim/group_admins/show.erb +1 -3
  36. data/app/cells/decidim/group_members/show.erb +2 -6
  37. data/app/cells/decidim/images_panel/show.erb +2 -5
  38. data/app/cells/decidim/map/show.erb +3 -0
  39. data/app/cells/decidim/map/template.erb +14 -0
  40. data/app/cells/decidim/map_cell.rb +39 -0
  41. data/app/cells/decidim/notification_actions/buttons_cell.rb +1 -1
  42. data/app/cells/decidim/onboarding_action_message/show.erb +15 -0
  43. data/app/cells/decidim/onboarding_action_message_cell.rb +81 -0
  44. data/app/cells/decidim/participatory_space_dropdown_metadata/metadata.erb +4 -4
  45. data/app/cells/decidim/participatory_space_dropdown_metadata/show.erb +3 -5
  46. data/app/cells/decidim/participatory_space_private_user/show.erb +23 -0
  47. data/app/cells/decidim/participatory_space_private_user_cell.rb +21 -0
  48. data/app/cells/decidim/profile_actions/show.erb +1 -1
  49. data/app/cells/decidim/profile_sidebar/show.erb +167 -0
  50. data/app/cells/decidim/profile_sidebar_cell.rb +68 -0
  51. data/app/cells/decidim/progress_bar/show.erb +2 -2
  52. data/app/cells/decidim/report_button/already_reported_modal.erb +2 -2
  53. data/app/cells/decidim/report_button/flag_modal.erb +36 -24
  54. data/app/cells/decidim/report_button_cell.rb +9 -2
  55. data/app/cells/decidim/resource_history/show.erb +20 -0
  56. data/app/cells/decidim/resource_history_cell.rb +66 -0
  57. data/app/cells/decidim/resource_types_filter/show.erb +1 -1
  58. data/app/cells/decidim/resource_types_filter_cell.rb +6 -6
  59. data/app/cells/decidim/share_button_cell.rb +0 -4
  60. data/app/cells/decidim/share_widget/modal.erb +26 -0
  61. data/app/cells/decidim/share_widget/show.erb +2 -0
  62. data/app/cells/decidim/share_widget_cell.rb +20 -0
  63. data/app/cells/decidim/tags/show.erb +7 -4
  64. data/app/cells/decidim/tags_cell.rb +11 -72
  65. data/app/cells/decidim/upload_modal/files.erb +4 -4
  66. data/app/cells/decidim/upload_modal_cell.rb +3 -5
  67. data/app/cells/decidim/user_activity/show.erb +1 -1
  68. data/app/commands/decidim/amendable/accept.rb +1 -2
  69. data/app/commands/decidim/amendable/create_draft.rb +2 -2
  70. data/app/commands/decidim/create_ephemeral_user.rb +52 -0
  71. data/app/commands/decidim/create_omniauth_registration.rb +21 -17
  72. data/app/commands/decidim/create_report.rb +8 -11
  73. data/app/commands/decidim/create_user_group.rb +6 -2
  74. data/app/commands/decidim/destroy_ephemeral_user.rb +47 -0
  75. data/app/commands/decidim/invite_user.rb +1 -1
  76. data/app/commands/decidim/search.rb +0 -14
  77. data/app/commands/decidim/update_account.rb +11 -3
  78. data/app/commands/decidim/update_notifications_settings.rb +1 -0
  79. data/app/commands/decidim/update_resources_taxonomies.rb +67 -0
  80. data/app/commands/decidim/update_user_group.rb +7 -1
  81. data/app/constraints/decidim/current_component.rb +1 -1
  82. data/app/controllers/concerns/decidim/ajax_permission_handler.rb +21 -0
  83. data/app/controllers/concerns/decidim/devise_authentication_methods.rb +3 -6
  84. data/app/controllers/concerns/decidim/devise_controllers.rb +2 -0
  85. data/app/controllers/concerns/decidim/disable_redirection_to_external_host.rb +1 -1
  86. data/app/controllers/concerns/decidim/ephemeral_session_checker.rb +87 -0
  87. data/app/controllers/concerns/decidim/filter_resource.rb +4 -2
  88. data/app/controllers/concerns/decidim/has_members_page.rb +25 -0
  89. data/app/controllers/concerns/decidim/locale_switcher.rb +2 -2
  90. data/app/controllers/concerns/decidim/needs_password_change.rb +0 -1
  91. data/app/controllers/concerns/decidim/needs_permission.rb +2 -1
  92. data/app/controllers/concerns/decidim/needs_tos_accepted.rb +4 -5
  93. data/app/controllers/concerns/decidim/onboarding_action_methods.rb +52 -0
  94. data/app/controllers/concerns/decidim/participatory_space_context.rb +1 -4
  95. data/app/controllers/decidim/amendments_controller.rb +3 -3
  96. data/app/controllers/decidim/application_controller.rb +9 -0
  97. data/app/controllers/decidim/authorization_modals_controller.rb +8 -2
  98. data/app/controllers/decidim/components/base_controller.rb +3 -7
  99. data/app/controllers/decidim/devise/confirmations_controller.rb +4 -0
  100. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +8 -1
  101. data/app/controllers/decidim/devise/registrations_controller.rb +1 -1
  102. data/app/controllers/decidim/devise/sessions_controller.rb +2 -0
  103. data/app/controllers/decidim/download_your_data_controller.rb +33 -2
  104. data/app/controllers/decidim/editor_images_controller.rb +1 -11
  105. data/app/controllers/decidim/follows_controller.rb +1 -1
  106. data/app/controllers/decidim/geolocation_controller.rb +19 -0
  107. data/app/controllers/decidim/homepage_controller.rb +0 -1
  108. data/app/controllers/decidim/open_data_controller.rb +33 -8
  109. data/app/controllers/decidim/profiles_controller.rb +2 -2
  110. data/app/controllers/decidim/reports_controller.rb +2 -7
  111. data/app/controllers/decidim/user_activities_controller.rb +1 -1
  112. data/app/controllers/decidim/user_conversations_controller.rb +1 -11
  113. data/app/events/decidim/soft_delete_resource_event.rb +15 -0
  114. data/app/forms/decidim/account_form.rb +2 -5
  115. data/app/forms/decidim/amendable/form.rb +4 -2
  116. data/app/forms/decidim/ephemeral_user_form.rb +22 -0
  117. data/app/forms/decidim/notifications_settings_form.rb +1 -0
  118. data/app/forms/decidim/omniauth_registration_form.rb +15 -2
  119. data/app/forms/decidim/registration_form.rb +1 -1
  120. data/app/helpers/concerns/decidim/flash_helper_extensions.rb +17 -2
  121. data/app/helpers/decidim/action_authorization_helper.rb +75 -14
  122. data/app/helpers/decidim/amendments_helper.rb +1 -11
  123. data/app/helpers/decidim/application_helper.rb +6 -2
  124. data/app/helpers/decidim/breadcrumb_helper.rb +6 -0
  125. data/app/helpers/decidim/cache_helper.rb +1 -1
  126. data/app/helpers/decidim/check_boxes_tree_helper.rb +25 -53
  127. data/app/helpers/decidim/decidim_form_helper.rb +0 -44
  128. data/app/helpers/decidim/endorsable_helper.rb +0 -10
  129. data/app/helpers/decidim/filters_helper.rb +0 -25
  130. data/app/helpers/decidim/layout_helper.rb +6 -6
  131. data/app/helpers/decidim/menu_helper.rb +2 -2
  132. data/app/helpers/decidim/messaging/conversation_helper.rb +2 -3
  133. data/app/helpers/decidim/meta_tags_helper.rb +32 -23
  134. data/app/helpers/decidim/modal_helper.rb +23 -0
  135. data/app/helpers/decidim/omniauth_helper.rb +5 -5
  136. data/app/helpers/decidim/onboarding_action_helper.rb +13 -0
  137. data/app/helpers/decidim/orders_helper.rb +1 -2
  138. data/app/helpers/decidim/paginate_helper.rb +1 -1
  139. data/app/helpers/decidim/participatory_space_helpers.rb +1 -1
  140. data/app/helpers/decidim/passwords_helper.rb +2 -2
  141. data/app/helpers/decidim/taxonomies_helper.rb +40 -0
  142. data/app/helpers/decidim/tooltip_helper.rb +1 -4
  143. data/app/jobs/decidim/download_your_data_export_job.rb +2 -19
  144. data/app/jobs/decidim/event_publisher_job.rb +18 -9
  145. data/app/jobs/decidim/export_job.rb +5 -1
  146. data/app/jobs/decidim/export_participatory_space_job.rb +4 -1
  147. data/app/jobs/decidim/open_data_job.rb +4 -4
  148. data/app/mailers/decidim/export_mailer.rb +7 -12
  149. data/app/mailers/decidim/notifications_digest_mailer.rb +1 -7
  150. data/app/mailers/decidim/reported_mailer.rb +2 -18
  151. data/app/models/decidim/action_log.rb +20 -1
  152. data/app/models/decidim/category.rb +4 -0
  153. data/app/models/decidim/component.rb +25 -3
  154. data/app/models/decidim/metric.rb +2 -1
  155. data/app/models/decidim/moderation.rb +16 -0
  156. data/app/models/decidim/newsletter.rb +12 -8
  157. data/app/models/decidim/organization.rb +7 -3
  158. data/app/models/decidim/participatory_space_private_user.rb +20 -0
  159. data/app/models/decidim/private_export.rb +24 -0
  160. data/app/models/decidim/push_notification_message.rb +1 -1
  161. data/app/models/decidim/report.rb +1 -1
  162. data/app/models/decidim/scope.rb +4 -0
  163. data/app/models/decidim/share_token.rb +36 -10
  164. data/app/models/decidim/taxonomization.rb +23 -0
  165. data/app/models/decidim/taxonomy.rb +139 -0
  166. data/app/models/decidim/taxonomy_filter.rb +130 -0
  167. data/app/models/decidim/taxonomy_filter_item.rb +33 -0
  168. data/app/models/decidim/user.rb +13 -23
  169. data/app/models/decidim/user_base_entity.rb +12 -4
  170. data/app/models/decidim/user_moderation.rb +9 -0
  171. data/app/models/decidim/user_report.rb +4 -0
  172. data/app/packs/entrypoints/decidim_core.js +1 -0
  173. data/app/packs/entrypoints/decidim_geocoding.js +2 -0
  174. data/app/packs/images/decidim/brands/facebook.svg +10 -0
  175. data/app/packs/images/decidim/brands/google.svg +7 -1
  176. data/app/packs/images/decidim/brands/twitter-x.svg +3 -0
  177. data/app/packs/images/decidim/default-avatar.svg +1 -1
  178. data/app/packs/src/decidim/callout.js +8 -13
  179. data/app/packs/src/decidim/check_boxes_tree.js +0 -1
  180. data/app/packs/src/decidim/clipboard.js +18 -9
  181. data/app/packs/src/decidim/datepicker/datepicker_functions.js +3 -3
  182. data/app/packs/src/decidim/datepicker/generate_datepicker.js +0 -2
  183. data/app/packs/src/decidim/datepicker/generate_timepicker.js +0 -2
  184. data/app/packs/src/decidim/decidim_application.js +1 -0
  185. data/app/packs/src/decidim/direct_uploads/upload_field.js +4 -3
  186. data/app/packs/src/decidim/direct_uploads/upload_modal.js +9 -8
  187. data/app/packs/src/decidim/editor/common/suggestion.js +1 -11
  188. data/app/packs/src/decidim/geocoding/reverse_geocoding.js +60 -0
  189. data/app/packs/src/decidim/index.js +9 -5
  190. data/app/packs/src/decidim/input_character_counter.js +1 -1
  191. data/app/packs/src/decidim/map/provider/here.js +1 -1
  192. data/app/packs/src/decidim/onboarding_pending_action.js +24 -0
  193. data/app/packs/src/decidim/sticky_footer.js +29 -0
  194. data/app/packs/src/decidim/sticky_header.js +6 -31
  195. data/app/packs/src/decidim/user_registrations.js +13 -0
  196. data/app/packs/src/decidim/vendor/leaflet-tilelayer-here.js +212 -0
  197. data/app/packs/stylesheets/decidim/_accordion.scss +30 -0
  198. data/app/packs/stylesheets/decidim/_activity.scss +4 -4
  199. data/app/packs/stylesheets/decidim/_buttons.scss +19 -0
  200. data/app/packs/stylesheets/decidim/_cards.scss +0 -4
  201. data/app/packs/stylesheets/decidim/_content_blocks.scss +0 -4
  202. data/app/packs/stylesheets/decidim/_dropdown.scss +1 -1
  203. data/app/packs/stylesheets/decidim/_endorsers_list.scss +26 -20
  204. data/app/packs/stylesheets/decidim/_filters.scss +1 -1
  205. data/app/packs/stylesheets/decidim/_forms.scss +2 -2
  206. data/app/packs/stylesheets/decidim/_header.scss +39 -70
  207. data/app/packs/stylesheets/decidim/_layout.scss +34 -4
  208. data/app/packs/stylesheets/decidim/_login.scss +53 -6
  209. data/app/packs/stylesheets/decidim/_modal.scss +47 -1
  210. data/app/packs/stylesheets/decidim/_modal_tos_refuse.scss +4 -0
  211. data/app/packs/stylesheets/decidim/_modal_update.scss +1 -5
  212. data/app/packs/stylesheets/decidim/_participatory_spaces.scss +46 -0
  213. data/app/packs/stylesheets/decidim/_profile.scss +1 -1
  214. data/app/packs/stylesheets/decidim/_success_image.scss +64 -0
  215. data/app/packs/stylesheets/decidim/_tribute.scss +36 -0
  216. data/app/packs/stylesheets/decidim/application.scss +1 -1
  217. data/app/packs/stylesheets/decidim/geocoding_addons.scss +5 -0
  218. data/app/packs/stylesheets/decidim/map.scss +7 -10
  219. data/app/packs/stylesheets/decidim/resource_history.scss +31 -0
  220. data/app/permissions/decidim/default_permissions.rb +0 -2
  221. data/app/permissions/decidim/permissions.rb +9 -15
  222. data/app/presenters/decidim/admin_log/base_user_presenter.rb +67 -0
  223. data/app/presenters/decidim/admin_log/component_presenter.rb +32 -3
  224. data/app/presenters/decidim/admin_log/moderation_presenter.rb +30 -3
  225. data/app/presenters/decidim/admin_log/share_token_presenter.rb +39 -0
  226. data/app/presenters/decidim/admin_log/taxonomy_filter_presenter.rb +57 -0
  227. data/app/presenters/decidim/admin_log/taxonomy_presenter.rb +48 -0
  228. data/app/presenters/decidim/admin_log/user_group_presenter.rb +6 -6
  229. data/app/presenters/decidim/admin_log/user_presenter.rb +4 -18
  230. data/app/presenters/decidim/log/user_presenter.rb +0 -1
  231. data/app/presenters/decidim/log/value_types/date_presenter.rb +1 -0
  232. data/app/presenters/decidim/log/value_types/taxonomy_presenter.rb +29 -0
  233. data/app/presenters/decidim/notification_to_mailer_presenter.rb +3 -7
  234. data/app/presenters/decidim/participatory_space_private_user_presenter.rb +50 -0
  235. data/app/presenters/decidim/taxonomy_filter_presenter.rb +19 -0
  236. data/app/presenters/decidim/taxonomy_presenter.rb +14 -0
  237. data/app/presenters/decidim/user_presenter.rb +1 -1
  238. data/app/queries/decidim/last_activity.rb +0 -25
  239. data/app/queries/decidim/metrics/blocked_users_metric_manage.rb +2 -2
  240. data/app/queries/decidim/metrics/users_metric_manage.rb +2 -2
  241. data/app/queries/decidim/public_activities.rb +1 -12
  242. data/app/queries/decidim/stats_users_count.rb +2 -2
  243. data/app/resolvers/decidim/meta_image_url_resolver.rb +128 -0
  244. data/app/serializers/decidim/exporters/open_data_blocked_user_serializer.rb +25 -0
  245. data/app/serializers/decidim/exporters/open_data_metric_serializer.rb +22 -0
  246. data/app/serializers/decidim/exporters/open_data_moderation_serializer.rb +30 -0
  247. data/app/serializers/decidim/exporters/open_data_taxonomy_serializer.rb +30 -0
  248. data/app/serializers/decidim/exporters/open_data_user_group_serializer.rb +38 -0
  249. data/app/serializers/decidim/exporters/open_data_user_serializer.rb +39 -0
  250. data/app/serializers/decidim/exporters/participatory_space_serializer.rb +104 -0
  251. data/app/serializers/decidim/exporters/serializer.rb +25 -0
  252. data/app/serializers/decidim/schema_org_breadcrumb_list_serializer.rb +52 -0
  253. data/app/services/decidim/action_authorizer.rb +32 -3
  254. data/app/services/decidim/base_diff_renderer.rb +1 -3
  255. data/app/services/decidim/download_your_data_exporter.rb +58 -24
  256. data/app/services/decidim/onboarding_manager.rb +272 -0
  257. data/app/services/decidim/open_data_exporter.rb +139 -13
  258. data/app/services/decidim/static_map_generator.rb +1 -1
  259. data/app/services/decidim/traceability.rb +13 -0
  260. data/app/uploaders/decidim/application_uploader.rb +1 -1
  261. data/app/validators/etiquette_validator.rb +9 -2
  262. data/app/validators/passthru_validator.rb +1 -1
  263. data/app/validators/translated_etiquette_validator.rb +32 -0
  264. data/app/views/decidim/account/_password_fields.html.erb +2 -2
  265. data/app/views/decidim/application/_accordion_section.html.erb +14 -0
  266. data/app/views/decidim/application/_collection.html.erb +30 -18
  267. data/app/views/decidim/devise/omniauth_registrations/new.html.erb +5 -1
  268. data/app/views/decidim/devise/omniauth_registrations/new_tos_fields.html.erb +29 -0
  269. data/app/views/decidim/devise/registrations/new.html.erb +10 -22
  270. data/app/views/decidim/devise/sessions/new.html.erb +24 -29
  271. data/app/views/decidim/devise/shared/_omniauth_buttons.html.erb +2 -4
  272. data/app/views/decidim/devise/shared/_tos_fields.html.erb +16 -0
  273. data/app/views/decidim/download_your_data/_export.html.erb +15 -0
  274. data/app/views/decidim/download_your_data/show.html.erb +51 -5
  275. data/app/views/decidim/endorsements/update_buttons_and_counters.js.erb +16 -19
  276. data/app/views/decidim/errors/internal_server_error.html.erb +1 -1
  277. data/app/views/decidim/errors/not_found.html.erb +1 -1
  278. data/app/views/decidim/export_mailer/download_your_data_export.html.erb +2 -2
  279. data/app/views/decidim/export_mailer/export.html.erb +5 -1
  280. data/app/views/decidim/last_activities/index.html.erb +1 -1
  281. data/app/views/decidim/messaging/conversations/_reply_form.html.erb +2 -1
  282. data/app/views/decidim/messaging/conversations/_start.html.erb +1 -1
  283. data/app/views/decidim/newsletters/unsubscribe.html.erb +4 -16
  284. data/app/views/decidim/notifications_settings/show.html.erb +22 -0
  285. data/app/views/decidim/open_data/_how_to_open_accordion_section.html.erb +15 -0
  286. data/app/views/decidim/open_data/index.html.erb +108 -0
  287. data/app/views/decidim/pages/show.html.erb +2 -1
  288. data/app/views/decidim/participatory_space_private_users/_participatory_space_private_user.html.erb +1 -0
  289. data/app/views/decidim/reported_mailer/hide.html.erb +9 -0
  290. data/app/views/decidim/reported_mailer/report.html.erb +1 -1
  291. data/app/views/decidim/searches/_count.html.erb +1 -1
  292. data/app/views/decidim/searches/_filters.html.erb +39 -76
  293. data/app/views/decidim/shared/_component_announcement.html.erb +1 -1
  294. data/app/views/decidim/shared/_confirm_modal.html.erb +5 -3
  295. data/app/views/decidim/shared/_filters.html.erb +4 -6
  296. data/app/views/decidim/shared/_login_modal.html.erb +26 -20
  297. data/app/views/decidim/shared/_orders.html.erb +2 -2
  298. data/app/views/decidim/shared/_resource_actions.html.erb +21 -0
  299. data/app/views/decidim/shared/_results_per_page.html.erb +1 -1
  300. data/app/views/decidim/shared/filters/_check_boxes_tree.html.erb +1 -2
  301. data/app/views/decidim/shared/filters/_collection.html.erb +1 -1
  302. data/app/views/decidim/shared/filters/_dropdown_label.html.erb +7 -4
  303. data/app/views/kaminari/decidim/_page.html.erb +1 -1
  304. data/app/views/kaminari/decidim/_paginator.html.erb +1 -1
  305. data/app/views/layouts/decidim/_application.html.erb +0 -1
  306. data/app/views/layouts/decidim/_logo.html.erb +2 -2
  307. data/app/views/layouts/decidim/_logo_mobile.html.erb +1 -1
  308. data/app/views/layouts/decidim/_meta_tags_config.html.erb +6 -11
  309. data/app/views/layouts/decidim/_schema_org_breadcrumb_list.html.erb +3 -0
  310. data/app/views/layouts/decidim/_wrapper.html.erb +15 -9
  311. data/app/views/layouts/decidim/footer/_main.html.erb +1 -1
  312. data/app/views/layouts/decidim/footer/_main_intro.html.erb +1 -1
  313. data/app/views/layouts/decidim/footer/_main_legal.html.erb +1 -1
  314. data/app/views/layouts/decidim/footer/_main_links.html.erb +1 -1
  315. data/app/views/layouts/decidim/footer/_mini.html.erb +2 -2
  316. data/app/views/layouts/decidim/header/_close_ephemeral_session.html.erb +25 -0
  317. data/app/views/layouts/decidim/header/_main.html.erb +14 -10
  318. data/app/views/layouts/decidim/header/_main_links_desktop.html.erb +0 -6
  319. data/app/views/layouts/decidim/header/_main_links_dropdown.html.erb +0 -2
  320. data/app/views/layouts/decidim/header/_main_links_mobile_account.html.erb +1 -1
  321. data/app/views/layouts/decidim/header/_menu_breadcrumb_items.html.erb +2 -0
  322. data/app/views/layouts/decidim/header/_menu_breadcrumb_main_dropdown_desktop.html.erb +11 -5
  323. data/app/views/layouts/decidim/header/_menu_breadcrumb_mobile_tablet.html.erb +5 -5
  324. data/app/views/layouts/decidim/header/_mobile_language_choose.html.erb +1 -1
  325. data/app/views/layouts/decidim/shared/_layout_item.html.erb +1 -1
  326. data/config/assets.rb +2 -1
  327. data/config/locales/ar.yml +38 -74
  328. data/config/locales/bg-BG.yml +2 -2
  329. data/config/locales/bg.yml +38 -74
  330. data/config/locales/bs-BA.yml +0 -2
  331. data/config/locales/ca.yml +374 -130
  332. data/config/locales/cs.yml +379 -116
  333. data/config/locales/de.yml +370 -132
  334. data/config/locales/el.yml +26 -58
  335. data/config/locales/en.yml +354 -110
  336. data/config/locales/eo.yml +0 -4
  337. data/config/locales/es-MX.yml +368 -127
  338. data/config/locales/es-PY.yml +373 -132
  339. data/config/locales/es.yml +374 -130
  340. data/config/locales/eu.yml +461 -215
  341. data/config/locales/fi-plain.yml +367 -130
  342. data/config/locales/fi.yml +372 -132
  343. data/config/locales/fr-CA.yml +180 -125
  344. data/config/locales/fr-LU.yml +3 -3
  345. data/config/locales/fr.yml +180 -122
  346. data/config/locales/ga-IE.yml +4 -25
  347. data/config/locales/gl.yml +23 -58
  348. data/config/locales/hu.yml +35 -62
  349. data/config/locales/id-ID.yml +24 -57
  350. data/config/locales/is-IS.yml +6 -25
  351. data/config/locales/it.yml +39 -218
  352. data/config/locales/ja.yml +235 -140
  353. data/config/locales/lb-LU.yml +2 -2
  354. data/config/locales/lb.yml +31 -76
  355. data/config/locales/lt.yml +29 -64
  356. data/config/locales/lv.yml +24 -58
  357. data/config/locales/nl.yml +26 -75
  358. data/config/locales/no.yml +26 -70
  359. data/config/locales/pl.yml +35 -72
  360. data/config/locales/pt-BR.yml +44 -63
  361. data/config/locales/pt.yml +26 -70
  362. data/config/locales/ro-RO.yml +118 -183
  363. data/config/locales/ru.yml +16 -43
  364. data/config/locales/sk-SK.yml +3 -3
  365. data/config/locales/sk.yml +27 -72
  366. data/config/locales/sl.yml +0 -4
  367. data/config/locales/sr-CS.yml +0 -2
  368. data/config/locales/sv.yml +141 -133
  369. data/config/locales/tr-TR.yml +32 -75
  370. data/config/locales/uk.yml +8 -29
  371. data/config/locales/zh-CN.yml +24 -68
  372. data/config/locales/zh-TW.yml +28 -62
  373. data/config/routes.rb +4 -10
  374. data/db/migrate/20171212103803_create_unique_nicknames.rb +1 -1
  375. data/db/migrate/20180221101934_fix_nickname_index.rb +1 -1
  376. data/db/migrate/20180706104107_add_nickname_to_managed_users.rb +1 -1
  377. data/db/migrate/20181001124950_move_users_groups_to_users_table.rb +1 -1
  378. data/db/migrate/20181025082245_add_timestamps_to_components.rb +2 -0
  379. data/db/migrate/20190412131728_fix_user_names.rb +1 -1
  380. data/db/migrate/20240628111905_add_visible_to_components.rb +7 -0
  381. data/db/migrate/20240704115429_create_decidim_taxonomies.rb +23 -0
  382. data/db/migrate/20240717093514_add_registered_only_to_decidim_share_tokens.rb +7 -0
  383. data/db/migrate/20240722215500_change_object_changes_on_versions.rb +39 -0
  384. data/db/migrate/20240806065417_create_decidim_taxonomy_filters.rb +23 -0
  385. data/db/migrate/20240822161348_add_deleted_at_to_decidim_components.rb +8 -0
  386. data/db/migrate/20240906162524_add_part_of_to_taxonomies.rb +26 -0
  387. data/db/migrate/20241001135825_add_role_to_participatory_space_private_users.rb +7 -0
  388. data/db/migrate/20241001140408_add_published_to_participatory_space_private_users.rb +7 -0
  389. data/db/migrate/20241022002600_create_private_exports.rb +18 -0
  390. data/db/migrate/20241028114430_add_component_counter_to_taxonomy_filters.rb +7 -0
  391. data/db/migrate/20241111104357_add_names_and_space_boolean_to_taxonomy_filters.rb +9 -0
  392. data/db/migrate/20241127093708_add_taxonomy_to_metrics.rb +7 -0
  393. data/db/migrate/20241204121445_add_participatory_space_manifests_from_taxonomy_filters.rb +9 -0
  394. data/decidim-core.gemspec +14 -17
  395. data/lib/decidim/action_authorization.rb +3 -2
  396. data/lib/decidim/amendable.rb +1 -1
  397. data/lib/decidim/api/input_filters/category_input_filter.rb +5 -3
  398. data/lib/decidim/api/input_filters/component_input_filter.rb +33 -20
  399. data/lib/decidim/api/input_filters/user_entity_input_filter.rb +53 -44
  400. data/lib/decidim/api/input_sorts/component_input_sort.rb +15 -13
  401. data/lib/decidim/api/input_sorts/user_entity_input_sort.rb +4 -4
  402. data/lib/decidim/api/interfaces/author_interface.rb +3 -2
  403. data/lib/decidim/api/interfaces/coauthorable_interface.rb +5 -5
  404. data/lib/decidim/api/interfaces/endorsable_interface.rb +2 -2
  405. data/lib/decidim/api/interfaces/participatory_space_interface.rb +5 -10
  406. data/lib/decidim/api/interfaces/taxonomizable_interface.rb +13 -0
  407. data/lib/decidim/api/types/amendment_type.rb +5 -7
  408. data/lib/decidim/api/types/area_api_type.rb +3 -3
  409. data/lib/decidim/api/types/attachment_type.rb +3 -3
  410. data/lib/decidim/api/types/category_type.rb +2 -2
  411. data/lib/decidim/api/types/decidim_type.rb +5 -1
  412. data/lib/decidim/api/types/fingerprint_type.rb +1 -1
  413. data/lib/decidim/api/types/localized_string_type.rb +1 -1
  414. data/lib/decidim/api/types/metric_history_type.rb +2 -0
  415. data/lib/decidim/api/types/metric_type.rb +1 -1
  416. data/lib/decidim/api/types/organization_type.rb +5 -0
  417. data/lib/decidim/api/types/participatory_space_link_type.rb +2 -2
  418. data/lib/decidim/api/types/participatory_space_manifest_type.rb +1 -1
  419. data/lib/decidim/api/types/quantifiable_translated_field_type.rb +1 -1
  420. data/lib/decidim/api/types/scope_api_type.rb +2 -3
  421. data/lib/decidim/api/types/session_type.rb +1 -2
  422. data/lib/decidim/api/types/taxonomy_type.rb +15 -0
  423. data/lib/decidim/api/types/trace_version_type.rb +2 -2
  424. data/lib/decidim/api/types/translated_field_type.rb +3 -5
  425. data/lib/decidim/api/types/user_group_type.rb +7 -20
  426. data/lib/decidim/api/types/user_type.rb +7 -20
  427. data/lib/decidim/asset_router/storage.rb +6 -11
  428. data/lib/decidim/assets/tailwind/tailwind.config.js.erb +3 -3
  429. data/lib/decidim/attachment_attributes.rb +1 -1
  430. data/lib/decidim/attribute_encryptor.rb +1 -1
  431. data/lib/decidim/attribute_object/nested_validator.rb +1 -1
  432. data/lib/decidim/attributes/integer_with_units.rb +27 -0
  433. data/lib/decidim/attributes/time_with_zone.rb +1 -5
  434. data/lib/decidim/attributes.rb +2 -0
  435. data/lib/decidim/authorization_form_builder.rb +0 -7
  436. data/lib/decidim/coauthorable.rb +1 -1
  437. data/lib/decidim/command.rb +3 -3
  438. data/lib/decidim/commands/destroy_resource.rb +5 -1
  439. data/lib/decidim/commands/resource_handler.rb +2 -2
  440. data/lib/decidim/commands/restore_resource.rb +45 -0
  441. data/lib/decidim/commands/soft_delete_resource.rb +63 -0
  442. data/lib/decidim/component_manifest.rb +7 -0
  443. data/lib/decidim/content_parsers/blob_parser.rb +8 -10
  444. data/lib/decidim/content_parsers/user_parser.rb +1 -1
  445. data/lib/decidim/core/api.rb +2 -0
  446. data/lib/decidim/core/engine.rb +21 -7
  447. data/lib/decidim/core/menu.rb +0 -5
  448. data/lib/decidim/core/seeds.rb +42 -2
  449. data/lib/decidim/core/test/factories.rb +107 -4
  450. data/lib/decidim/core/test/shared_examples/admin_resource_gallery_examples.rb +85 -0
  451. data/lib/decidim/core/test/shared_examples/announcements_examples.rb +0 -4
  452. data/lib/decidim/core/test/shared_examples/comments_examples.rb +393 -38
  453. data/lib/decidim/core/test/shared_examples/components_controller_hide_shared_examples.rb +11 -0
  454. data/lib/decidim/core/test/shared_examples/components_controller_reorder_shared_examples.rb +21 -0
  455. data/lib/decidim/core/test/shared_examples/download_open_data_shared_context.rb +36 -0
  456. data/lib/decidim/core/test/shared_examples/download_open_data_shared_examples.rb +45 -0
  457. data/lib/decidim/core/test/shared_examples/download_your_data_shared_examples.rb +17 -0
  458. data/lib/decidim/core/test/shared_examples/etiquette_validator_examples.rb +25 -0
  459. data/lib/decidim/core/test/shared_examples/follows_examples.rb +43 -0
  460. data/lib/decidim/core/test/shared_examples/has_taxonomies.rb +94 -0
  461. data/lib/decidim/core/test/shared_examples/manage_share_tokens_examples.rb +237 -0
  462. data/lib/decidim/core/test/shared_examples/map_examples.rb +2 -0
  463. data/lib/decidim/core/test/shared_examples/open_data_exporter_examples.rb +102 -0
  464. data/lib/decidim/core/test/shared_examples/participatory_space_members_page_examples.rb +46 -0
  465. data/lib/decidim/core/test/shared_examples/participatory_space_search_examples.rb +98 -0
  466. data/lib/decidim/core/test/shared_examples/permissions.rb +7 -7
  467. data/lib/decidim/core/test/shared_examples/preview_with_share_token_examples.rb +94 -0
  468. data/lib/decidim/core/test/shared_examples/reports_examples.rb +15 -53
  469. data/lib/decidim/core/test/shared_examples/resource_endorsed_event_examples.rb +2 -2
  470. data/lib/decidim/core/test/shared_examples/resource_search_examples.rb +75 -69
  471. data/lib/decidim/core/test/shared_examples/searchable_resources_shared_context.rb +1 -1
  472. data/lib/decidim/core/test/shared_examples/simple_event.rb +33 -19
  473. data/lib/decidim/core/test/shared_examples/social_share_examples.rb +7 -14
  474. data/lib/decidim/core/test/shared_examples/softdeleteable_components_examples.rb +173 -0
  475. data/lib/decidim/core/test/shared_examples/system_endorse_resource_examples.rb +54 -8
  476. data/lib/decidim/core/test/shared_examples/taxonomizable_interface_examples.rb +20 -0
  477. data/lib/decidim/core/test/shared_examples/taxonomizable_resource_examples.rb +37 -0
  478. data/lib/decidim/core/test/shared_examples/taxonomy_settings.rb +49 -0
  479. data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +1 -1
  480. data/lib/decidim/core/test/shared_examples/uncommentable_component_examples.rb +0 -26
  481. data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +2 -28
  482. data/lib/decidim/core/test/shared_examples/with_endorsable_permissions_examples.rb +1 -1
  483. data/lib/decidim/core/test.rb +9 -5
  484. data/lib/decidim/core/version.rb +1 -1
  485. data/lib/decidim/core.rb +58 -0
  486. data/lib/decidim/download_your_data_serializers/download_your_data_identity_serializer.rb +0 -4
  487. data/lib/decidim/download_your_data_serializers/download_your_data_participatory_space_private_user_serializer.rb +3 -1
  488. data/lib/decidim/download_your_data_serializers/download_your_data_report_serializer.rb +2 -1
  489. data/lib/decidim/download_your_data_serializers/download_your_data_user_serializer.rb +6 -7
  490. data/lib/decidim/download_your_data_serializers.rb +19 -0
  491. data/lib/decidim/exporters/csv.rb +6 -0
  492. data/lib/decidim/exporters/export_manifest.rb +14 -0
  493. data/lib/decidim/exporters/pdf.rb +26 -22
  494. data/lib/decidim/filter_form_builder.rb +12 -15
  495. data/lib/decidim/form_builder.rb +6 -143
  496. data/lib/decidim/has_category.rb +5 -1
  497. data/lib/decidim/has_private_users.rb +4 -0
  498. data/lib/decidim/has_taxonomy_settings.rb +47 -0
  499. data/lib/decidim/has_upload_validations.rb +1 -1
  500. data/lib/decidim/legacy_form_builder.rb +118 -0
  501. data/lib/decidim/maintenance/import_models/application_record.rb +93 -0
  502. data/lib/decidim/maintenance/import_models/area.rb +82 -0
  503. data/lib/decidim/maintenance/import_models/area_type.rb +12 -0
  504. data/lib/decidim/maintenance/import_models/assembly_type.rb +49 -0
  505. data/lib/decidim/maintenance/import_models/categorization.rb +14 -0
  506. data/lib/decidim/maintenance/import_models/category.rb +107 -0
  507. data/lib/decidim/maintenance/import_models/participatory_process_type.rb +21 -0
  508. data/lib/decidim/maintenance/import_models/scope.rb +163 -0
  509. data/lib/decidim/maintenance/import_models.rb +19 -0
  510. data/lib/decidim/maintenance/taxonomy_importer.rb +132 -0
  511. data/lib/decidim/maintenance/taxonomy_plan.rb +78 -0
  512. data/lib/decidim/maintenance.rb +12 -0
  513. data/lib/decidim/map/autocomplete.rb +52 -8
  514. data/lib/decidim/map/dynamic_map.rb +1 -1
  515. data/lib/decidim/map/provider/dynamic_map/here.rb +40 -1
  516. data/lib/decidim/map/provider/geocoding/here.rb +9 -3
  517. data/lib/decidim/map/provider/static_map/here.rb +0 -34
  518. data/lib/decidim/map.rb +3 -6
  519. data/lib/decidim/moderation_tools.rb +16 -19
  520. data/lib/decidim/newsletter_encryptor.rb +1 -1
  521. data/lib/decidim/nicknamizable.rb +9 -6
  522. data/lib/decidim/paddable.rb +1 -1
  523. data/lib/decidim/participable.rb +10 -10
  524. data/lib/decidim/participatory_space_user.rb +10 -0
  525. data/lib/decidim/private_download_helper.rb +15 -0
  526. data/lib/decidim/record_encryptor.rb +51 -46
  527. data/lib/decidim/reportable.rb +2 -6
  528. data/lib/decidim/resourceable.rb +16 -0
  529. data/lib/decidim/seeds.rb +18 -20
  530. data/lib/decidim/settings_manifest.rb +34 -1
  531. data/lib/decidim/soft_deletable.rb +17 -0
  532. data/lib/decidim/taxonomizable.rb +72 -0
  533. data/lib/decidim/translatable_attributes.rb +1 -5
  534. data/lib/decidim/view_model.rb +0 -1
  535. data/lib/tasks/decidim_download_your_data_tasks.rake +2 -4
  536. data/lib/tasks/decidim_procfile.rake +6 -0
  537. data/lib/tasks/decidim_tasks.rake +1 -0
  538. data/lib/tasks/decidim_taxonomies.rake +155 -0
  539. data/lib/tasks/upgrade/{decidim_fix_categorization.rake → clean.rake} +25 -18
  540. data/lib/tasks/upgrade/decidim_active_storage_migration_tasks.rake +1 -1
  541. data/lib/tasks/upgrade/decidim_fix_nickname_uniqueness.rake +20 -23
  542. data/lib/tasks/upgrade/migrations.rake +91 -0
  543. metadata +201 -113
  544. data/app/cells/decidim/amendable/amenders_list/show.erb +0 -0
  545. data/app/cells/decidim/content_blocks/base/content.erb +0 -0
  546. data/app/cells/decidim/endorsers_list/full_endorsers_list.erb +0 -3
  547. data/app/cells/decidim/endorsers_list_button/content.erb +0 -1
  548. data/app/cells/decidim/endorsers_list_button_cell.rb +0 -15
  549. data/app/cells/decidim/report_user_button/already_reported_modal.erb +0 -11
  550. data/app/cells/decidim/report_user_button/flag_modal.erb +0 -47
  551. data/app/cells/decidim/report_user_button/show.erb +0 -2
  552. data/app/cells/decidim/report_user_button_cell.rb +0 -59
  553. data/app/cells/decidim/scopes_picker/scope_picker_prompt.erb +0 -3
  554. data/app/cells/decidim/scopes_picker/scope_picker_values.erb +0 -5
  555. data/app/cells/decidim/scopes_picker/show.erb +0 -14
  556. data/app/cells/decidim/scopes_picker_cell.rb +0 -92
  557. data/app/commands/decidim/update_user_interests.rb +0 -41
  558. data/app/controllers/decidim/scopes_controller.rb +0 -84
  559. data/app/controllers/decidim/user_interests_controller.rb +0 -30
  560. data/app/forms/decidim/user_interest_scope_form.rb +0 -25
  561. data/app/forms/decidim/user_interests_form.rb +0 -17
  562. data/app/helpers/decidim/categories_helper.rb +0 -26
  563. data/app/helpers/decidim/scopes_helper.rb +0 -105
  564. data/app/jobs/decidim/hide_child_resources_job.rb +0 -24
  565. data/app/packs/images/decidim/vendor/leaflet/layers-2x.png +0 -0
  566. data/app/packs/images/decidim/vendor/leaflet/layers.png +0 -0
  567. data/app/packs/images/decidim/vendor/leaflet/marker-icon-2x.png +0 -0
  568. data/app/packs/images/decidim/vendor/leaflet/marker-icon.png +0 -0
  569. data/app/packs/images/decidim/vendor/leaflet/marker-shadow.png +0 -0
  570. data/app/packs/src/decidim/dropdown_menu.js +0 -18
  571. data/app/packs/stylesheets/decidim/_hashtags.scss +0 -5
  572. data/app/packs/stylesheets/decidim/legacy/MarkerCluster.Default.scss +0 -67
  573. data/app/packs/stylesheets/decidim/legacy/MarkerCluster.scss +0 -18
  574. data/app/packs/stylesheets/decidim/legacy/leaflet.scss +0 -705
  575. data/app/validators/scope_belongs_to_component_validator.rb +0 -16
  576. data/app/views/decidim/account/_user_groups.html.erb +0 -0
  577. data/app/views/decidim/reported_mailer/hidden_automatically.html.erb +0 -25
  578. data/app/views/decidim/reported_mailer/hidden_manually.html.erb +0 -25
  579. data/app/views/decidim/scopes/_scopes_picker_input.html.erb +0 -19
  580. data/app/views/decidim/scopes/picker.html.erb +0 -53
  581. data/app/views/decidim/shared/_comments.html.erb +0 -0
  582. data/app/views/decidim/shared/_share_modal.html.erb +0 -26
  583. data/app/views/decidim/shared/_tags.html.erb +0 -1
  584. data/app/views/decidim/user_interests/_areas.html.erb +0 -14
  585. data/app/views/decidim/user_interests/_scopes.html.erb +0 -22
  586. data/app/views/decidim/user_interests/show.html.erb +0 -22
  587. data/config/initializers/foundation_rails_helper.rb +0 -4
  588. data/config/locales/ca-IT.yml +0 -2146
  589. data/lib/decidim/core/test/shared_examples/has_category.rb +0 -38
  590. data/lib/decidim/core/test/shared_examples/has_scope.rb +0 -11
  591. data/lib/decidim/core/test/shared_examples/manage_component_share_tokens.rb +0 -83
  592. data/lib/decidim/core/test/shared_examples/preview_component_with_share_token_examples.rb +0 -49
  593. data/lib/decidim/core/test/shared_examples/scope_helper_examples.rb +0 -93
  594. data/lib/decidim/seven_zip_wrapper.rb +0 -29
  595. data/lib/tasks/upgrade/clean_hidden_resources.rake +0 -33
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ class PrivateExport < ApplicationRecord
5
+ belongs_to :attached_to, polymorphic: true
6
+
7
+ has_one_attached :file
8
+ validates :content_type, presence: true
9
+
10
+ before_validation :set_content_type_and_size, if: :attached?
11
+ delegate :attached?, to: :file
12
+
13
+ default_scope { order(created_at: :desc) }
14
+
15
+ def expired?
16
+ expires_at < Time.zone.now
17
+ end
18
+
19
+ def set_content_type_and_size
20
+ self.content_type = file.content_type
21
+ self.file_size = file.byte_size
22
+ end
23
+ end
24
+ end
@@ -26,7 +26,7 @@ module Decidim
26
26
  end
27
27
 
28
28
  def url
29
- EngineRouter.new("decidim", {}).public_send(:conversation_path, host: organization.host, id: @conversation)
29
+ EngineRouter.new("decidim", {}).conversation_path(host: organization.host, id: @conversation)
30
30
  end
31
31
 
32
32
  private
@@ -5,7 +5,7 @@ module Decidim
5
5
  class Report < ApplicationRecord
6
6
  include Decidim::DownloadYourData
7
7
 
8
- REASONS = %w(spam offensive does_not_belong hidden_during_block parent_hidden).freeze
8
+ REASONS = %w(spam offensive does_not_belong hidden_during_block).freeze
9
9
 
10
10
  belongs_to :moderation, foreign_key: "decidim_moderation_id", class_name: "Decidim::Moderation"
11
11
  belongs_to :user, foreign_key: "decidim_user_id", class_name: "Decidim::User"
@@ -76,6 +76,10 @@ module Decidim
76
76
  # Allow ransacker to search for a key in a hstore column (`name`.`en`)
77
77
  ransacker_i18n :name
78
78
 
79
+ def self.ransackable_attributes(_auth_object = nil)
80
+ %w(name id)
81
+ end
82
+
79
83
  private
80
84
 
81
85
  def forbid_cycles
@@ -2,33 +2,63 @@
2
2
 
3
3
  module Decidim
4
4
  class ShareToken < ApplicationRecord
5
- validates :token, presence: true, uniqueness: { scope: [:decidim_organization_id, :token_for_type, :token_for_id] }
5
+ include Decidim::Traceable
6
6
 
7
7
  belongs_to :organization, foreign_key: "decidim_organization_id", class_name: "Decidim::Organization"
8
8
  belongs_to :user, foreign_key: "decidim_user_id", class_name: "Decidim::User"
9
9
  belongs_to :token_for, foreign_type: "token_for_type", polymorphic: true
10
10
 
11
- after_initialize :generate, :set_default_expiration
11
+ validates :token, presence: true, uniqueness: { scope: [:decidim_organization_id, :token_for_type, :token_for_id] }
12
+ # validates token no spaces or strange characters
13
+ validates :token, format: { with: /\A[a-zA-Z0-9_-]+\z/ }
14
+
15
+ after_initialize :generate
16
+
17
+ def self.log_presenter_class_for(_log)
18
+ Decidim::AdminLog::ShareTokenPresenter
19
+ end
12
20
 
13
- def self.use!(token_for:, token:)
21
+ def self.use!(token_for:, token:, user: nil)
14
22
  record = find_by!(token_for:, token:)
15
- record.use!
23
+ record.use!(user:)
16
24
  end
17
25
 
18
- def use!
26
+ def use!(user: nil)
19
27
  return raise StandardError, "Share token '#{token}' for '#{token_for_type}' with id = #{token_for_id} has expired." if expired?
28
+ return raise StandardError, "Share token '#{token}' for '#{token_for_type}' with id = #{token_for_id} requires a registered user." if registered_only? && user.nil?
20
29
 
21
30
  update!(times_used: times_used + 1, last_used_at: Time.zone.now)
22
31
  end
23
32
 
24
33
  def expired?
25
- expires_at.past?
34
+ expires_at.past? unless expires_at.nil?
26
35
  end
27
36
 
28
37
  def url
29
38
  token_for.shareable_url(self)
30
39
  end
31
40
 
41
+ def participatory_space
42
+ return token_for if token_for.try(:manifest).is_a?(Decidim::ParticipatorySpaceManifest)
43
+ return token_for.participatory_space if token_for.respond_to?(:participatory_space)
44
+
45
+ component&.participatory_space
46
+ end
47
+
48
+ def component
49
+ return token_for if token_for.is_a?(Decidim::Component)
50
+
51
+ token_for.component if token_for.respond_to?(:component)
52
+ end
53
+
54
+ def self.ransackable_attributes(_auth_object = nil)
55
+ %w(token expires_at last_used_at registered_only times_used)
56
+ end
57
+
58
+ def self.ransackable_associations(_auth_object = nil)
59
+ %w(organization token_for user)
60
+ end
61
+
32
62
  private
33
63
 
34
64
  def generate
@@ -39,9 +69,5 @@ module Decidim
39
69
  break if ShareToken.find_by(token:).blank?
40
70
  end
41
71
  end
42
-
43
- def set_default_expiration
44
- self.expires_at ||= 1.day.from_now
45
- end
46
72
  end
47
73
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # Represents the link between a taxonomy and any taxonomizable entity.
5
+ class Taxonomization < ApplicationRecord
6
+ belongs_to :taxonomy,
7
+ class_name: "Decidim::Taxonomy",
8
+ counter_cache: :taxonomizations_count,
9
+ inverse_of: :taxonomizations
10
+
11
+ belongs_to :taxonomizable, polymorphic: true
12
+
13
+ validate :prevent_root_taxonomization
14
+
15
+ private
16
+
17
+ def prevent_root_taxonomization
18
+ return unless taxonomy.root?
19
+
20
+ errors.add(:taxonomy, :invalid)
21
+ end
22
+ end
23
+ end
@@ -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>