decidim-core 0.29.2 → 0.30.0.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/amendable/amend_button_card/show.erb +6 -4
  3. data/app/cells/decidim/amendable/amend_button_card_cell.rb +8 -0
  4. data/app/cells/decidim/amendable/amendments/show.erb +1 -1
  5. data/app/cells/decidim/amendable/promote_button_card/show.erb +2 -0
  6. data/app/cells/decidim/author_cell.rb +1 -1
  7. data/app/cells/decidim/card_l/extra_data.erb +1 -0
  8. data/app/cells/decidim/card_metadata_cell.rb +9 -16
  9. data/app/cells/decidim/comments_button_cell.rb +14 -2
  10. data/app/cells/decidim/content_blocks/highlighted_elements_cell.rb +2 -0
  11. data/app/cells/decidim/content_blocks/highlighted_elements_with_cell_for_list_cell.rb +1 -1
  12. data/app/cells/decidim/endorsement_block/show.erb +0 -1
  13. data/app/cells/decidim/endorsement_block_cell.rb +6 -0
  14. data/app/cells/decidim/endorsement_buttons/button_content.erb +1 -1
  15. data/app/cells/decidim/endorsement_buttons/select_identity_button.erb +1 -1
  16. data/app/cells/decidim/endorsement_buttons/show.erb +7 -7
  17. data/app/cells/decidim/endorsement_buttons/verification_modal.erb +4 -2
  18. data/app/cells/decidim/endorsers_list/empty.erb +3 -0
  19. data/app/cells/decidim/endorsers_list/full.erb +17 -5
  20. data/app/cells/decidim/endorsers_list/show.erb +19 -10
  21. data/app/cells/decidim/endorsers_list_cell.rb +19 -6
  22. data/app/cells/decidim/follow_button/show.erb +1 -2
  23. data/app/cells/decidim/follow_button_cell.rb +5 -0
  24. data/app/cells/decidim/map/show.erb +3 -0
  25. data/app/cells/decidim/map/template.erb +14 -0
  26. data/app/cells/decidim/map_cell.rb +39 -0
  27. data/app/cells/decidim/notification_actions/buttons_cell.rb +1 -1
  28. data/app/cells/decidim/onboarding_action_message/show.erb +15 -0
  29. data/app/cells/decidim/onboarding_action_message_cell.rb +81 -0
  30. data/app/cells/decidim/participatory_space_private_user/show.erb +23 -0
  31. data/app/cells/decidim/participatory_space_private_user_cell.rb +21 -0
  32. data/app/cells/decidim/progress_bar/show.erb +2 -2
  33. data/app/cells/decidim/report_button_cell.rb +1 -0
  34. data/app/cells/decidim/resource_history/show.erb +20 -0
  35. data/app/cells/decidim/resource_history_cell.rb +66 -0
  36. data/app/cells/decidim/share_button_cell.rb +0 -4
  37. data/app/cells/decidim/share_widget/modal.erb +26 -0
  38. data/app/cells/decidim/share_widget/show.erb +2 -0
  39. data/app/cells/decidim/share_widget_cell.rb +20 -0
  40. data/app/cells/decidim/tags/show.erb +7 -4
  41. data/app/cells/decidim/tags_cell.rb +11 -72
  42. data/app/commands/decidim/amendable/create_draft.rb +2 -2
  43. data/app/commands/decidim/create_ephemeral_user.rb +52 -0
  44. data/app/commands/decidim/create_omniauth_registration.rb +13 -3
  45. data/app/commands/decidim/create_report.rb +1 -5
  46. data/app/commands/decidim/create_user_group.rb +6 -2
  47. data/app/commands/decidim/destroy_ephemeral_user.rb +47 -0
  48. data/app/commands/decidim/update_account.rb +11 -3
  49. data/app/commands/decidim/update_notifications_settings.rb +1 -0
  50. data/app/commands/decidim/update_resources_taxonomies.rb +67 -0
  51. data/app/commands/decidim/update_user_group.rb +7 -1
  52. data/app/constraints/decidim/current_component.rb +1 -1
  53. data/app/controllers/concerns/decidim/ajax_permission_handler.rb +21 -0
  54. data/app/controllers/concerns/decidim/devise_authentication_methods.rb +3 -6
  55. data/app/controllers/concerns/decidim/devise_controllers.rb +2 -0
  56. data/app/controllers/concerns/decidim/disable_redirection_to_external_host.rb +1 -1
  57. data/app/controllers/concerns/decidim/ephemeral_session_checker.rb +87 -0
  58. data/app/controllers/concerns/decidim/filter_resource.rb +4 -2
  59. data/app/controllers/concerns/decidim/has_members_page.rb +25 -0
  60. data/app/controllers/concerns/decidim/headers/browser_feature_permissions.rb +50 -0
  61. data/app/controllers/concerns/decidim/locale_switcher.rb +2 -2
  62. data/app/controllers/concerns/decidim/needs_password_change.rb +0 -1
  63. data/app/controllers/concerns/decidim/needs_permission.rb +2 -1
  64. data/app/controllers/concerns/decidim/needs_tos_accepted.rb +4 -5
  65. data/app/controllers/concerns/decidim/onboarding_action_methods.rb +52 -0
  66. data/app/controllers/decidim/application_controller.rb +10 -0
  67. data/app/controllers/decidim/authorization_modals_controller.rb +8 -2
  68. data/app/controllers/decidim/components/base_controller.rb +3 -7
  69. data/app/controllers/decidim/devise/confirmations_controller.rb +4 -0
  70. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +8 -1
  71. data/app/controllers/decidim/devise/registrations_controller.rb +1 -1
  72. data/app/controllers/decidim/devise/sessions_controller.rb +2 -0
  73. data/app/controllers/decidim/download_your_data_controller.rb +33 -2
  74. data/app/controllers/decidim/editor_images_controller.rb +1 -11
  75. data/app/controllers/decidim/follows_controller.rb +1 -1
  76. data/app/controllers/decidim/geolocation_controller.rb +19 -0
  77. data/app/controllers/decidim/homepage_controller.rb +0 -1
  78. data/app/controllers/decidim/open_data_controller.rb +33 -8
  79. data/app/controllers/decidim/user_conversations_controller.rb +1 -11
  80. data/app/events/decidim/soft_delete_resource_event.rb +15 -0
  81. data/app/forms/decidim/amendable/form.rb +4 -2
  82. data/app/forms/decidim/ephemeral_user_form.rb +22 -0
  83. data/app/forms/decidim/notifications_settings_form.rb +1 -0
  84. data/app/forms/decidim/omniauth_registration_form.rb +14 -1
  85. data/app/helpers/concerns/decidim/flash_helper_extensions.rb +17 -2
  86. data/app/helpers/decidim/action_authorization_helper.rb +75 -14
  87. data/app/helpers/decidim/amendments_helper.rb +0 -9
  88. data/app/helpers/decidim/application_helper.rb +6 -2
  89. data/app/helpers/decidim/breadcrumb_helper.rb +6 -0
  90. data/app/helpers/decidim/cache_helper.rb +1 -1
  91. data/app/helpers/decidim/check_boxes_tree_helper.rb +25 -53
  92. data/app/helpers/decidim/decidim_form_helper.rb +0 -44
  93. data/app/helpers/decidim/endorsable_helper.rb +0 -10
  94. data/app/helpers/decidim/layout_helper.rb +6 -0
  95. data/app/helpers/decidim/messaging/conversation_helper.rb +2 -3
  96. data/app/helpers/decidim/meta_tags_helper.rb +32 -23
  97. data/app/helpers/decidim/modal_helper.rb +23 -0
  98. data/app/helpers/decidim/omniauth_helper.rb +5 -5
  99. data/app/helpers/decidim/onboarding_action_helper.rb +13 -0
  100. data/app/helpers/decidim/orders_helper.rb +2 -1
  101. data/app/helpers/decidim/participatory_space_helpers.rb +1 -1
  102. data/app/helpers/decidim/passwords_helper.rb +2 -2
  103. data/app/helpers/decidim/taxonomies_helper.rb +40 -0
  104. data/app/jobs/decidim/download_your_data_export_job.rb +2 -19
  105. data/app/jobs/decidim/event_publisher_job.rb +18 -9
  106. data/app/jobs/decidim/export_job.rb +5 -1
  107. data/app/jobs/decidim/export_participatory_space_job.rb +4 -1
  108. data/app/jobs/decidim/hide_child_resources_job.rb +24 -0
  109. data/app/jobs/decidim/open_data_job.rb +4 -4
  110. data/app/mailers/decidim/export_mailer.rb +7 -12
  111. data/app/models/decidim/action_log.rb +11 -0
  112. data/app/models/decidim/category.rb +4 -0
  113. data/app/models/decidim/component.rb +25 -3
  114. data/app/models/decidim/metric.rb +2 -1
  115. data/app/models/decidim/moderation.rb +16 -0
  116. data/app/models/decidim/newsletter.rb +12 -8
  117. data/app/models/decidim/organization.rb +7 -3
  118. data/app/models/decidim/participatory_space_private_user.rb +20 -0
  119. data/app/models/decidim/private_export.rb +24 -0
  120. data/app/models/decidim/push_notification_message.rb +1 -1
  121. data/app/models/decidim/report.rb +1 -1
  122. data/app/models/decidim/scope.rb +4 -0
  123. data/app/models/decidim/share_token.rb +36 -10
  124. data/app/models/decidim/taxonomization.rb +23 -0
  125. data/app/models/decidim/taxonomy.rb +139 -0
  126. data/app/models/decidim/taxonomy_filter.rb +130 -0
  127. data/app/models/decidim/taxonomy_filter_item.rb +33 -0
  128. data/app/models/decidim/user.rb +9 -23
  129. data/app/models/decidim/user_base_entity.rb +12 -0
  130. data/app/models/decidim/user_moderation.rb +9 -0
  131. data/app/models/decidim/user_report.rb +4 -0
  132. data/app/packs/entrypoints/decidim_core.js +1 -0
  133. data/app/packs/entrypoints/decidim_geocoding.js +2 -0
  134. data/app/packs/images/decidim/brands/facebook.svg +10 -0
  135. data/app/packs/images/decidim/brands/google.svg +7 -1
  136. data/app/packs/images/decidim/brands/twitter-x.svg +3 -0
  137. data/app/packs/src/decidim/check_boxes_tree.js +0 -1
  138. data/app/packs/src/decidim/clipboard.js +18 -9
  139. data/app/packs/src/decidim/confirm.js +79 -59
  140. data/app/packs/src/decidim/decidim_application.js +1 -0
  141. data/app/packs/src/decidim/form_remote.js +1 -1
  142. data/app/packs/src/decidim/geocoding/reverse_geocoding.js +60 -0
  143. data/app/packs/src/decidim/impersonation.js +1 -1
  144. data/app/packs/src/decidim/index.js +11 -1
  145. data/app/packs/src/decidim/map/provider/here.js +1 -1
  146. data/app/packs/src/decidim/onboarding_pending_action.js +24 -0
  147. data/app/packs/src/decidim/session_timeouter.js +1 -1
  148. data/app/packs/src/decidim/sticky_footer.js +29 -0
  149. data/app/packs/src/decidim/sticky_header.js +6 -31
  150. data/app/packs/src/decidim/user_registrations.js +13 -0
  151. data/app/packs/src/decidim/utilities/dom.js +148 -0
  152. data/app/packs/stylesheets/decidim/_accordion.scss +30 -0
  153. data/app/packs/stylesheets/decidim/_buttons.scss +19 -0
  154. data/app/packs/stylesheets/decidim/_dropdown.scss +1 -1
  155. data/app/packs/stylesheets/decidim/_endorsers_list.scss +26 -20
  156. data/app/packs/stylesheets/decidim/_forms.scss +2 -2
  157. data/app/packs/stylesheets/decidim/_hashtags.scss +5 -0
  158. data/app/packs/stylesheets/decidim/_header.scss +5 -3
  159. data/app/packs/stylesheets/decidim/_layout.scss +32 -2
  160. data/app/packs/stylesheets/decidim/_login.scss +53 -6
  161. data/app/packs/stylesheets/decidim/_modal.scss +42 -0
  162. data/app/packs/stylesheets/decidim/_modal_tos_refuse.scss +4 -0
  163. data/app/packs/stylesheets/decidim/_participatory_spaces.scss +46 -0
  164. data/app/packs/stylesheets/decidim/_profile.scss +1 -1
  165. data/app/packs/stylesheets/decidim/_success_image.scss +64 -0
  166. data/app/packs/stylesheets/decidim/_tribute.scss +36 -0
  167. data/app/packs/stylesheets/decidim/application.scss +2 -0
  168. data/app/packs/stylesheets/decidim/geocoding_addons.scss +5 -0
  169. data/app/packs/stylesheets/decidim/map.scss +7 -10
  170. data/app/packs/stylesheets/decidim/resource_history.scss +31 -0
  171. data/app/permissions/decidim/permissions.rb +8 -2
  172. data/app/presenters/decidim/admin_log/base_user_presenter.rb +67 -0
  173. data/app/presenters/decidim/admin_log/component_presenter.rb +32 -3
  174. data/app/presenters/decidim/admin_log/moderation_presenter.rb +30 -3
  175. data/app/presenters/decidim/admin_log/share_token_presenter.rb +39 -0
  176. data/app/presenters/decidim/admin_log/taxonomy_filter_presenter.rb +57 -0
  177. data/app/presenters/decidim/admin_log/taxonomy_presenter.rb +48 -0
  178. data/app/presenters/decidim/admin_log/user_group_presenter.rb +6 -6
  179. data/app/presenters/decidim/admin_log/user_presenter.rb +4 -18
  180. data/app/presenters/decidim/log/value_types/date_presenter.rb +1 -0
  181. data/app/presenters/decidim/log/value_types/taxonomy_presenter.rb +29 -0
  182. data/app/presenters/decidim/participatory_space_private_user_presenter.rb +50 -0
  183. data/app/presenters/decidim/taxonomy_filter_presenter.rb +19 -0
  184. data/app/presenters/decidim/taxonomy_presenter.rb +14 -0
  185. data/app/queries/decidim/metrics/blocked_users_metric_manage.rb +2 -2
  186. data/app/queries/decidim/metrics/users_metric_manage.rb +2 -2
  187. data/app/queries/decidim/public_activities.rb +1 -12
  188. data/app/queries/decidim/stats_users_count.rb +2 -2
  189. data/app/resolvers/decidim/meta_image_url_resolver.rb +128 -0
  190. data/app/serializers/decidim/exporters/open_data_blocked_user_serializer.rb +25 -0
  191. data/app/serializers/decidim/exporters/open_data_metric_serializer.rb +22 -0
  192. data/app/serializers/decidim/exporters/open_data_moderation_serializer.rb +30 -0
  193. data/app/serializers/decidim/exporters/open_data_taxonomy_serializer.rb +30 -0
  194. data/app/serializers/decidim/exporters/open_data_user_group_serializer.rb +38 -0
  195. data/app/serializers/decidim/exporters/open_data_user_serializer.rb +39 -0
  196. data/app/serializers/decidim/exporters/participatory_space_serializer.rb +104 -0
  197. data/app/serializers/decidim/exporters/serializer.rb +25 -0
  198. data/app/serializers/decidim/schema_org_breadcrumb_list_serializer.rb +52 -0
  199. data/app/services/decidim/action_authorizer.rb +32 -3
  200. data/app/services/decidim/base_diff_renderer.rb +1 -1
  201. data/app/services/decidim/download_your_data_exporter.rb +58 -24
  202. data/app/services/decidim/onboarding_manager.rb +272 -0
  203. data/app/services/decidim/open_data_exporter.rb +139 -13
  204. data/app/services/decidim/traceability.rb +13 -0
  205. data/app/uploaders/decidim/application_uploader.rb +1 -1
  206. data/app/validators/etiquette_validator.rb +9 -2
  207. data/app/validators/passthru_validator.rb +1 -1
  208. data/app/validators/translated_etiquette_validator.rb +32 -0
  209. data/app/views/decidim/account/_password_fields.html.erb +2 -2
  210. data/app/views/decidim/application/_accordion_section.html.erb +14 -0
  211. data/app/views/decidim/application/_collection.html.erb +30 -18
  212. data/app/views/decidim/devise/omniauth_registrations/new.html.erb +5 -1
  213. data/app/views/decidim/devise/omniauth_registrations/new_tos_fields.html.erb +29 -0
  214. data/app/views/decidim/devise/registrations/new.html.erb +10 -22
  215. data/app/views/decidim/devise/sessions/new.html.erb +24 -29
  216. data/app/views/decidim/devise/shared/_omniauth_buttons.html.erb +2 -4
  217. data/app/views/decidim/devise/shared/_tos_fields.html.erb +16 -0
  218. data/app/views/decidim/download_your_data/_export.html.erb +15 -0
  219. data/app/views/decidim/download_your_data/show.html.erb +51 -5
  220. data/app/views/decidim/endorsements/update_buttons_and_counters.js.erb +16 -19
  221. data/app/views/decidim/export_mailer/download_your_data_export.html.erb +2 -2
  222. data/app/views/decidim/export_mailer/export.html.erb +5 -1
  223. data/app/views/decidim/notifications_settings/show.html.erb +22 -0
  224. data/app/views/decidim/open_data/_how_to_open_accordion_section.html.erb +15 -0
  225. data/app/views/decidim/open_data/index.html.erb +108 -0
  226. data/app/views/decidim/pages/show.html.erb +2 -1
  227. data/app/views/decidim/participatory_space_private_users/_participatory_space_private_user.html.erb +1 -0
  228. data/app/views/decidim/shared/_login_modal.html.erb +26 -20
  229. data/app/views/decidim/shared/_orders.html.erb +2 -2
  230. data/app/views/decidim/shared/_resource_actions.html.erb +21 -0
  231. data/app/views/decidim/shared/filters/_check_boxes_tree.html.erb +1 -2
  232. data/app/views/decidim/shared/filters/_collection.html.erb +1 -1
  233. data/app/views/decidim/shared/filters/_dropdown_label.html.erb +7 -4
  234. data/app/views/layouts/decidim/_application.html.erb +0 -1
  235. data/app/views/layouts/decidim/_js_configuration.html.erb +1 -0
  236. data/app/views/layouts/decidim/_logo.html.erb +1 -1
  237. data/app/views/layouts/decidim/_logo_mobile.html.erb +1 -1
  238. data/app/views/layouts/decidim/_meta_tags_config.html.erb +6 -11
  239. data/app/views/layouts/decidim/_schema_org_breadcrumb_list.html.erb +3 -0
  240. data/app/views/layouts/decidim/_wrapper.html.erb +15 -9
  241. data/app/views/layouts/decidim/footer/_main_links.html.erb +1 -1
  242. data/app/views/layouts/decidim/header/_close_ephemeral_session.html.erb +25 -0
  243. data/app/views/layouts/decidim/header/_main.html.erb +14 -10
  244. data/app/views/layouts/decidim/header/_menu_breadcrumb_items.html.erb +2 -0
  245. data/app/views/layouts/decidim/shared/_layout_item.html.erb +1 -1
  246. data/config/assets.rb +2 -1
  247. data/config/locales/ar.yml +27 -59
  248. data/config/locales/bg.yml +3 -64
  249. data/config/locales/ca.yml +370 -61
  250. data/config/locales/cs.yml +371 -54
  251. data/config/locales/de.yml +365 -54
  252. data/config/locales/el.yml +1 -48
  253. data/config/locales/en.yml +363 -54
  254. data/config/locales/eo.yml +0 -2
  255. data/config/locales/es-MX.yml +363 -57
  256. data/config/locales/es-PY.yml +363 -57
  257. data/config/locales/es.yml +367 -58
  258. data/config/locales/eu.yml +373 -65
  259. data/config/locales/fi-plain.yml +365 -57
  260. data/config/locales/fi.yml +370 -59
  261. data/config/locales/fr-CA.yml +178 -54
  262. data/config/locales/fr.yml +179 -52
  263. data/config/locales/ga-IE.yml +0 -21
  264. data/config/locales/gl.yml +1 -34
  265. data/config/locales/hu.yml +1 -53
  266. data/config/locales/id-ID.yml +1 -34
  267. data/config/locales/is-IS.yml +0 -16
  268. data/config/locales/it.yml +5 -60
  269. data/config/locales/ja.yml +215 -56
  270. data/config/locales/lb.yml +1 -52
  271. data/config/locales/lt.yml +1 -59
  272. data/config/locales/lv.yml +1 -40
  273. data/config/locales/nl.yml +1 -53
  274. data/config/locales/no.yml +2 -52
  275. data/config/locales/pl.yml +4 -66
  276. data/config/locales/pt-BR.yml +11 -52
  277. data/config/locales/pt.yml +2 -52
  278. data/config/locales/ro-RO.yml +219 -117
  279. data/config/locales/ru.yml +0 -20
  280. data/config/locales/sk.yml +1 -41
  281. data/config/locales/sv.yml +138 -59
  282. data/config/locales/tr-TR.yml +1 -50
  283. data/config/locales/uk.yml +0 -18
  284. data/config/locales/zh-CN.yml +1 -50
  285. data/config/locales/zh-TW.yml +1 -54
  286. data/config/routes.rb +4 -10
  287. data/db/migrate/20181025082245_add_timestamps_to_components.rb +2 -0
  288. data/db/migrate/20240628111905_add_visible_to_components.rb +7 -0
  289. data/db/migrate/20240704115429_create_decidim_taxonomies.rb +23 -0
  290. data/db/migrate/20240717093514_add_registered_only_to_decidim_share_tokens.rb +7 -0
  291. data/db/migrate/20240722215500_change_object_changes_on_versions.rb +39 -0
  292. data/db/migrate/20240806065417_create_decidim_taxonomy_filters.rb +23 -0
  293. data/db/migrate/20240822161348_add_deleted_at_to_decidim_components.rb +8 -0
  294. data/db/migrate/20240906162524_add_part_of_to_taxonomies.rb +26 -0
  295. data/db/migrate/20241001135825_add_role_to_participatory_space_private_users.rb +7 -0
  296. data/db/migrate/20241001140408_add_published_to_participatory_space_private_users.rb +7 -0
  297. data/db/migrate/20241022002600_create_private_exports.rb +18 -0
  298. data/db/migrate/20241028114430_add_component_counter_to_taxonomy_filters.rb +7 -0
  299. data/db/migrate/20241111104357_add_names_and_space_boolean_to_taxonomy_filters.rb +9 -0
  300. data/db/migrate/20241127093708_add_taxonomy_to_metrics.rb +7 -0
  301. data/db/migrate/20241204121445_add_participatory_space_manifests_from_taxonomy_filters.rb +9 -0
  302. data/decidim-core.gemspec +14 -17
  303. data/lib/decidim/action_authorization.rb +3 -2
  304. data/lib/decidim/amendable.rb +1 -1
  305. data/lib/decidim/api/input_filters/category_input_filter.rb +5 -3
  306. data/lib/decidim/api/input_filters/component_input_filter.rb +33 -20
  307. data/lib/decidim/api/input_filters/user_entity_input_filter.rb +53 -44
  308. data/lib/decidim/api/input_sorts/component_input_sort.rb +15 -13
  309. data/lib/decidim/api/input_sorts/user_entity_input_sort.rb +4 -4
  310. data/lib/decidim/api/interfaces/author_interface.rb +3 -2
  311. data/lib/decidim/api/interfaces/coauthorable_interface.rb +5 -5
  312. data/lib/decidim/api/interfaces/endorsable_interface.rb +2 -2
  313. data/lib/decidim/api/interfaces/participatory_space_interface.rb +5 -10
  314. data/lib/decidim/api/interfaces/taxonomizable_interface.rb +13 -0
  315. data/lib/decidim/api/types/amendment_type.rb +5 -7
  316. data/lib/decidim/api/types/area_api_type.rb +3 -3
  317. data/lib/decidim/api/types/attachment_type.rb +3 -3
  318. data/lib/decidim/api/types/category_type.rb +2 -2
  319. data/lib/decidim/api/types/decidim_type.rb +5 -1
  320. data/lib/decidim/api/types/fingerprint_type.rb +1 -1
  321. data/lib/decidim/api/types/localized_string_type.rb +1 -1
  322. data/lib/decidim/api/types/metric_history_type.rb +2 -0
  323. data/lib/decidim/api/types/metric_type.rb +1 -1
  324. data/lib/decidim/api/types/organization_type.rb +5 -0
  325. data/lib/decidim/api/types/participatory_space_link_type.rb +2 -2
  326. data/lib/decidim/api/types/participatory_space_manifest_type.rb +1 -1
  327. data/lib/decidim/api/types/quantifiable_translated_field_type.rb +1 -1
  328. data/lib/decidim/api/types/scope_api_type.rb +2 -3
  329. data/lib/decidim/api/types/session_type.rb +1 -2
  330. data/lib/decidim/api/types/taxonomy_type.rb +15 -0
  331. data/lib/decidim/api/types/trace_version_type.rb +2 -2
  332. data/lib/decidim/api/types/translated_field_type.rb +3 -5
  333. data/lib/decidim/api/types/user_group_type.rb +7 -20
  334. data/lib/decidim/api/types/user_type.rb +7 -20
  335. data/lib/decidim/asset_router/storage.rb +4 -4
  336. data/lib/decidim/assets/tailwind/tailwind.config.js.erb +2 -1
  337. data/lib/decidim/attachment_attributes.rb +1 -1
  338. data/lib/decidim/attribute_encryptor.rb +1 -1
  339. data/lib/decidim/attribute_object/nested_validator.rb +1 -1
  340. data/lib/decidim/attributes/integer_with_units.rb +27 -0
  341. data/lib/decidim/attributes.rb +2 -0
  342. data/lib/decidim/authorization_form_builder.rb +0 -7
  343. data/lib/decidim/coauthorable.rb +1 -1
  344. data/lib/decidim/command.rb +3 -3
  345. data/lib/decidim/commands/destroy_resource.rb +5 -1
  346. data/lib/decidim/commands/resource_handler.rb +2 -2
  347. data/lib/decidim/commands/restore_resource.rb +45 -0
  348. data/lib/decidim/commands/soft_delete_resource.rb +63 -0
  349. data/lib/decidim/component_manifest.rb +7 -0
  350. data/lib/decidim/core/api.rb +2 -0
  351. data/lib/decidim/core/engine.rb +21 -7
  352. data/lib/decidim/core/menu.rb +0 -5
  353. data/lib/decidim/core/seeds.rb +42 -2
  354. data/lib/decidim/core/test/factories.rb +105 -2
  355. data/lib/decidim/core/test/shared_examples/admin_resource_gallery_examples.rb +85 -0
  356. data/lib/decidim/core/test/shared_examples/comments_examples.rb +393 -38
  357. data/lib/decidim/core/test/shared_examples/components_controller_hide_shared_examples.rb +11 -0
  358. data/lib/decidim/core/test/shared_examples/components_controller_reorder_shared_examples.rb +21 -0
  359. data/lib/decidim/core/test/shared_examples/download_open_data_shared_context.rb +36 -0
  360. data/lib/decidim/core/test/shared_examples/download_open_data_shared_examples.rb +45 -0
  361. data/lib/decidim/core/test/shared_examples/download_your_data_shared_examples.rb +17 -0
  362. data/lib/decidim/core/test/shared_examples/etiquette_validator_examples.rb +25 -0
  363. data/lib/decidim/core/test/shared_examples/follows_examples.rb +43 -0
  364. data/lib/decidim/core/test/shared_examples/has_taxonomies.rb +94 -0
  365. data/lib/decidim/core/test/shared_examples/manage_share_tokens_examples.rb +237 -0
  366. data/lib/decidim/core/test/shared_examples/map_examples.rb +2 -0
  367. data/lib/decidim/core/test/shared_examples/open_data_exporter_examples.rb +102 -0
  368. data/lib/decidim/core/test/shared_examples/participatory_space_members_page_examples.rb +46 -0
  369. data/lib/decidim/core/test/shared_examples/participatory_space_search_examples.rb +98 -0
  370. data/lib/decidim/core/test/shared_examples/permissions.rb +7 -7
  371. data/lib/decidim/core/test/shared_examples/preview_with_share_token_examples.rb +94 -0
  372. data/lib/decidim/core/test/shared_examples/reports_examples.rb +60 -5
  373. data/lib/decidim/core/test/shared_examples/resource_endorsed_event_examples.rb +2 -2
  374. data/lib/decidim/core/test/shared_examples/resource_search_examples.rb +75 -69
  375. data/lib/decidim/core/test/shared_examples/searchable_resources_shared_context.rb +1 -1
  376. data/lib/decidim/core/test/shared_examples/simple_event.rb +33 -19
  377. data/lib/decidim/core/test/shared_examples/social_share_examples.rb +46 -0
  378. data/lib/decidim/core/test/shared_examples/softdeleteable_components_examples.rb +173 -0
  379. data/lib/decidim/core/test/shared_examples/system_endorse_resource_examples.rb +54 -8
  380. data/lib/decidim/core/test/shared_examples/taxonomizable_interface_examples.rb +20 -0
  381. data/lib/decidim/core/test/shared_examples/taxonomizable_resource_examples.rb +37 -0
  382. data/lib/decidim/core/test/shared_examples/taxonomy_settings.rb +49 -0
  383. data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +1 -1
  384. data/lib/decidim/core/test/shared_examples/versions_controller_examples.rb +2 -2
  385. data/lib/decidim/core/test/shared_examples/with_endorsable_permissions_examples.rb +1 -1
  386. data/lib/decidim/core/test.rb +9 -5
  387. data/lib/decidim/core/version.rb +1 -1
  388. data/lib/decidim/core.rb +58 -0
  389. data/lib/decidim/download_your_data_serializers/download_your_data_identity_serializer.rb +0 -4
  390. data/lib/decidim/download_your_data_serializers/download_your_data_participatory_space_private_user_serializer.rb +3 -1
  391. data/lib/decidim/download_your_data_serializers/download_your_data_report_serializer.rb +2 -1
  392. data/lib/decidim/download_your_data_serializers/download_your_data_user_serializer.rb +6 -7
  393. data/lib/decidim/download_your_data_serializers.rb +19 -0
  394. data/lib/decidim/exporters/csv.rb +6 -0
  395. data/lib/decidim/exporters/export_manifest.rb +14 -0
  396. data/lib/decidim/exporters/pdf.rb +26 -22
  397. data/lib/decidim/filter_form_builder.rb +12 -15
  398. data/lib/decidim/form_builder.rb +6 -129
  399. data/lib/decidim/has_category.rb +5 -1
  400. data/lib/decidim/has_private_users.rb +4 -0
  401. data/lib/decidim/has_taxonomy_settings.rb +47 -0
  402. data/lib/decidim/has_upload_validations.rb +1 -1
  403. data/lib/decidim/legacy_form_builder.rb +118 -0
  404. data/lib/decidim/maintenance/import_models/application_record.rb +93 -0
  405. data/lib/decidim/maintenance/import_models/area.rb +82 -0
  406. data/lib/decidim/maintenance/import_models/area_type.rb +12 -0
  407. data/lib/decidim/maintenance/import_models/assembly_type.rb +49 -0
  408. data/lib/decidim/maintenance/import_models/categorization.rb +14 -0
  409. data/lib/decidim/maintenance/import_models/category.rb +139 -0
  410. data/lib/decidim/maintenance/import_models/participatory_process_type.rb +21 -0
  411. data/lib/decidim/maintenance/import_models/scope.rb +163 -0
  412. data/lib/decidim/maintenance/import_models.rb +19 -0
  413. data/lib/decidim/maintenance/taxonomy_importer.rb +142 -0
  414. data/lib/decidim/maintenance/taxonomy_plan.rb +78 -0
  415. data/lib/decidim/maintenance.rb +12 -0
  416. data/lib/decidim/map/autocomplete.rb +52 -8
  417. data/lib/decidim/map/dynamic_map.rb +1 -1
  418. data/lib/decidim/map/provider/dynamic_map/here.rb +1 -40
  419. data/lib/decidim/map/provider/geocoding/here.rb +9 -3
  420. data/lib/decidim/map.rb +3 -6
  421. data/lib/decidim/moderation_tools.rb +29 -5
  422. data/lib/decidim/newsletter_encryptor.rb +1 -1
  423. data/lib/decidim/paddable.rb +1 -1
  424. data/lib/decidim/participable.rb +10 -10
  425. data/lib/decidim/participatory_space_user.rb +10 -0
  426. data/lib/decidim/private_download_helper.rb +15 -0
  427. data/lib/decidim/record_encryptor.rb +51 -46
  428. data/lib/decidim/resourceable.rb +16 -0
  429. data/lib/decidim/seeds.rb +18 -20
  430. data/lib/decidim/settings_manifest.rb +34 -1
  431. data/lib/decidim/soft_deletable.rb +17 -0
  432. data/lib/decidim/taxonomizable.rb +72 -0
  433. data/lib/decidim/view_model.rb +0 -1
  434. data/lib/tasks/decidim_download_your_data_tasks.rake +2 -4
  435. data/lib/tasks/decidim_procfile.rake +6 -0
  436. data/lib/tasks/decidim_tasks.rake +1 -0
  437. data/lib/tasks/decidim_taxonomies.rake +160 -0
  438. data/lib/tasks/upgrade/{decidim_fix_categorization.rake → clean.rake} +25 -18
  439. data/lib/tasks/upgrade/clean_hidden_resources.rake +33 -0
  440. data/lib/tasks/upgrade/decidim_active_storage_migration_tasks.rake +1 -1
  441. data/lib/tasks/upgrade/migrations.rake +94 -0
  442. metadata +198 -103
  443. data/app/cells/decidim/amendable/amenders_list/show.erb +0 -0
  444. data/app/cells/decidim/content_blocks/base/content.erb +0 -0
  445. data/app/cells/decidim/endorsers_list/full_endorsers_list.erb +0 -3
  446. data/app/cells/decidim/endorsers_list_button/content.erb +0 -1
  447. data/app/cells/decidim/endorsers_list_button_cell.rb +0 -15
  448. data/app/cells/decidim/scopes_picker/scope_picker_prompt.erb +0 -3
  449. data/app/cells/decidim/scopes_picker/scope_picker_values.erb +0 -5
  450. data/app/cells/decidim/scopes_picker/show.erb +0 -14
  451. data/app/cells/decidim/scopes_picker_cell.rb +0 -92
  452. data/app/commands/decidim/update_user_interests.rb +0 -41
  453. data/app/controllers/decidim/scopes_controller.rb +0 -84
  454. data/app/controllers/decidim/user_interests_controller.rb +0 -30
  455. data/app/forms/decidim/user_interest_scope_form.rb +0 -25
  456. data/app/forms/decidim/user_interests_form.rb +0 -17
  457. data/app/helpers/decidim/categories_helper.rb +0 -26
  458. data/app/helpers/decidim/scopes_helper.rb +0 -105
  459. data/app/packs/images/decidim/vendor/leaflet/layers-2x.png +0 -0
  460. data/app/packs/images/decidim/vendor/leaflet/layers.png +0 -0
  461. data/app/packs/images/decidim/vendor/leaflet/marker-icon-2x.png +0 -0
  462. data/app/packs/images/decidim/vendor/leaflet/marker-icon.png +0 -0
  463. data/app/packs/images/decidim/vendor/leaflet/marker-shadow.png +0 -0
  464. data/app/packs/src/decidim/vendor/leaflet-tilelayer-here.js +0 -212
  465. data/app/packs/stylesheets/decidim/legacy/MarkerCluster.Default.scss +0 -67
  466. data/app/packs/stylesheets/decidim/legacy/MarkerCluster.scss +0 -18
  467. data/app/packs/stylesheets/decidim/legacy/leaflet.scss +0 -705
  468. data/app/validators/scope_belongs_to_component_validator.rb +0 -16
  469. data/app/views/decidim/account/_user_groups.html.erb +0 -0
  470. data/app/views/decidim/scopes/_scopes_picker_input.html.erb +0 -19
  471. data/app/views/decidim/scopes/picker.html.erb +0 -53
  472. data/app/views/decidim/shared/_comments.html.erb +0 -0
  473. data/app/views/decidim/shared/_share_modal.html.erb +0 -26
  474. data/app/views/decidim/shared/_tags.html.erb +0 -1
  475. data/app/views/decidim/user_interests/_areas.html.erb +0 -14
  476. data/app/views/decidim/user_interests/_scopes.html.erb +0 -22
  477. data/app/views/decidim/user_interests/show.html.erb +0 -22
  478. data/config/initializers/foundation_rails_helper.rb +0 -4
  479. data/lib/decidim/core/test/shared_examples/has_category.rb +0 -38
  480. data/lib/decidim/core/test/shared_examples/has_scope.rb +0 -11
  481. data/lib/decidim/core/test/shared_examples/manage_component_share_tokens.rb +0 -83
  482. data/lib/decidim/core/test/shared_examples/preview_component_with_share_token_examples.rb +0 -49
  483. data/lib/decidim/core/test/shared_examples/scope_helper_examples.rb +0 -93
  484. data/lib/decidim/seven_zip_wrapper.rb +0 -29
@@ -4,8 +4,8 @@ require "spec_helper"
4
4
 
5
5
  shared_examples_for "general conversation permissions" do
6
6
  let(:context) { { conversation: } }
7
- let(:another_user) { create :user }
8
- let(:group) { create :user_group }
7
+ let(:another_user) { create(:user) }
8
+ let(:group) { create(:user_group) }
9
9
 
10
10
  context "when the originator of the conversation is the user" do
11
11
  let!(:conversation) do
@@ -46,7 +46,7 @@ shared_examples_for "general conversation permissions" do
46
46
  context "when the interlocutor is specified in the context" do
47
47
  let(:context) { { conversation:, interlocutor: } }
48
48
  let(:originator) { interlocutor }
49
- let(:interlocutor) { create :user }
49
+ let(:interlocutor) { create(:user) }
50
50
 
51
51
  let!(:conversation) do
52
52
  Decidim::Messaging::Conversation.start!(
@@ -113,8 +113,8 @@ end
113
113
 
114
114
  shared_examples_for "restricted conversation permissions" do
115
115
  let(:context) { { conversation: } }
116
- let(:user) { create :user }
117
- let(:interlocutor) { create :user, organization: user.organization }
116
+ let(:user) { create(:user) }
117
+ let(:interlocutor) { create(:user, organization: user.organization) }
118
118
  let!(:conversation) do
119
119
  Decidim::Messaging::Conversation.start(
120
120
  originator: user,
@@ -128,14 +128,14 @@ shared_examples_for "restricted conversation permissions" do
128
128
  end
129
129
 
130
130
  context "when interlocutor restricts communications" do
131
- let(:interlocutor) { create :user, direct_message_types: "followed-only" }
131
+ let(:interlocutor) { create(:user, direct_message_types: "followed-only") }
132
132
 
133
133
  context "and does not follow the user" do
134
134
  it { is_expected.to eq false }
135
135
  end
136
136
 
137
137
  context "and follows the user" do
138
- let!(:follow) { create :follow, user: interlocutor, followable: user }
138
+ let!(:follow) { create(:follow, user: interlocutor, followable: user) }
139
139
 
140
140
  it { is_expected.to eq true }
141
141
  end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples "visit unpublished resource with a share token" do
4
+ context "when no share_token is provided" do
5
+ before do
6
+ visit_resource_page
7
+ end
8
+
9
+ it "does not allow visiting resource" do
10
+ expect(page).to have_content "You are not authorized"
11
+ expect(page).to have_no_current_path(resource_path, ignore_query: true)
12
+ end
13
+ end
14
+
15
+ context "when a share_token is provided" do
16
+ let(:share_token) { create(:share_token, token: "VALID_TOKEN", token_for: resource) }
17
+ let(:params) { { share_token: share_token.token } }
18
+
19
+ before do
20
+ uri = URI(resource_path)
21
+ uri.query = URI.encode_www_form(params.to_a)
22
+ visit uri
23
+ end
24
+
25
+ context "when a valid share_token is provided" do
26
+ it "allows visiting the resource" do
27
+ expect(page).to have_no_content "You are not authorized"
28
+ expect(current_url).to include(params[:share_token])
29
+ expect(page).to have_current_path(resource_path, ignore_query: true)
30
+
31
+ # repeat visit without the token in the params to check for the session
32
+ visit resource_path
33
+ expect(page).to have_no_content "You are not authorized"
34
+ expect(current_url).not_to include(params[:share_token])
35
+ expect(page).to have_current_path(resource_path, ignore_query: true)
36
+ end
37
+ end
38
+
39
+ context "when an invalid share_token is provided" do
40
+ let(:share_token) { create(:share_token, :expired, token: "INVALID_TOKEN_FOR_UNREGISTERED", token_for: resource) }
41
+
42
+ it "does not allow visiting resource" do
43
+ expect(page).to have_content "You are not authorized"
44
+ expect(page).to have_no_current_path(resource_path, ignore_query: true)
45
+ end
46
+ end
47
+
48
+ context "when the token requires the user to be registered" do
49
+ let!(:share_token) { create(:share_token, token: "VALID_TOKEN_FOR_REGISTERED", token_for: resource, registered_only: true) }
50
+ let!(:user) { create(:user, :confirmed, organization:) }
51
+
52
+ it "does not allow visiting resource" do
53
+ expect(page).to have_content "You are not authorized"
54
+ expect(page).to have_no_current_path(resource_path, ignore_query: true)
55
+ end
56
+
57
+ it "allows visiting resource to logged users" do
58
+ login_as user, scope: :user
59
+ sleep 0.5 # add a delay to ensure the user session cookie is set
60
+ uri = URI(resource_path)
61
+ uri.query = URI.encode_www_form(params.to_a)
62
+ visit uri
63
+ expect(page).to have_no_content "You are not authorized"
64
+ expect(page).to have_current_path(resource_path, ignore_query: true)
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ shared_examples "preview component with a share_token" do
71
+ let!(:component) { create(:component, manifest_name:, participatory_space:, published_at: nil) }
72
+ let(:resource) { component }
73
+ let(:resource_path) { main_component_path(component) }
74
+
75
+ def visit_resource_page
76
+ visit_component
77
+ end
78
+
79
+ it_behaves_like "visit unpublished resource with a share token"
80
+ end
81
+
82
+ shared_examples "preview participatory space with a share_token" do
83
+ let(:resource) { participatory_space }
84
+
85
+ before do
86
+ switch_to_host(organization.host)
87
+ end
88
+
89
+ def visit_resource_page
90
+ visit resource_path
91
+ end
92
+
93
+ it_behaves_like "visit unpublished resource with a share token"
94
+ end
@@ -9,7 +9,7 @@ shared_examples "logged in user reports content" do
9
9
  context "and the user has not reported the resource yet" do
10
10
  it "reports the resource" do
11
11
  visit reportable_path
12
-
12
+ find("#dropdown-trigger-resource-#{reportable.id}").click
13
13
  expect(page).to have_css(%(button[data-dialog-open="flagModal"]))
14
14
  find(%(button[data-dialog-open="flagModal"])).click
15
15
  expect(page).to have_css(".flag-modal", visible: :visible)
@@ -44,6 +44,7 @@ shared_examples "higher user role hides" do
44
44
  it "reports the resource" do
45
45
  visit reportable_path
46
46
 
47
+ find("#dropdown-trigger-resource-#{reportable.id}").click
47
48
  expect(page).to have_css(%(button[data-dialog-open="flagModal"]))
48
49
  find(%(button[data-dialog-open="flagModal"])).click
49
50
  expect(page).to have_css(".flag-modal", visible: :visible)
@@ -58,6 +59,56 @@ shared_examples "higher user role hides" do
58
59
  end
59
60
  end
60
61
 
62
+ shared_examples "higher user role hides resource with comments" do
63
+ context "and the admin hides a resource with comments" do
64
+ let!(:comments) { create_list(:comment, 2, body: "Dummy comment", commentable: reportable, author: user) }
65
+
66
+ before do
67
+ login_as user, scope: :user
68
+ Decidim::Ai::SpamDetection.create_reporting_user!
69
+ end
70
+ around do |example|
71
+ previous = Capybara.raise_server_errors
72
+
73
+ # Disabling server errors to that we can test page not found error.
74
+ Capybara.raise_server_errors = false
75
+ example.run
76
+ Capybara.raise_server_errors = previous
77
+ end
78
+
79
+ it "hides the resource" do
80
+ visit decidim.search_path
81
+ expect(page).to have_content(translated(comments.first.body))
82
+ expect(page).to have_content(translated(comments.second.body))
83
+
84
+ visit reportable_path
85
+
86
+ expect(page).to have_content(translated(comments.first.body))
87
+ expect(page).to have_content(translated(comments.second.body))
88
+
89
+ find("#dropdown-trigger-resource-#{reportable.id}").click
90
+ expect(page).to have_css(%(button[data-dialog-open="flagModal"]))
91
+ find(%(button[data-dialog-open="flagModal"])).click
92
+ expect(page).to have_css(".flag-modal", visible: :visible)
93
+
94
+ within ".flag-modal" do
95
+ find(:css, "input[name='report[hide]']").set(true)
96
+ click_on "Hide"
97
+ end
98
+
99
+ perform_enqueued_jobs
100
+
101
+ expect(reportable.reload).to be_hidden
102
+ expect(comments.first.reload).to be_hidden
103
+ expect(comments.second.reload).to be_hidden
104
+
105
+ visit decidim.search_path
106
+ expect(page).to have_no_content(translated(comments.first.body))
107
+ expect(page).to have_no_content(translated(comments.second.body))
108
+ end
109
+ end
110
+ end
111
+
61
112
  shared_examples "higher user role does not have hide" do
62
113
  context "and the admin reports" do
63
114
  before do
@@ -67,6 +118,7 @@ shared_examples "higher user role does not have hide" do
67
118
  it "reports the resource" do
68
119
  visit reportable_path
69
120
 
121
+ find("#dropdown-trigger-resource-#{reportable.id}").click
70
122
  expect(page).to have_css(%(button[data-dialog-open="flagModal"]))
71
123
  find(%(button[data-dialog-open="flagModal"])).click
72
124
  expect(page).to have_css(".flag-modal", visible: :visible)
@@ -85,6 +137,7 @@ shared_examples "reports" do
85
137
 
86
138
  expect(page).to have_no_css("html.is-disabled")
87
139
 
140
+ find("#dropdown-trigger-resource-#{reportable.id}").click
88
141
  click_on "Report"
89
142
 
90
143
  expect(page).to have_css("html.is-disabled")
@@ -103,6 +156,7 @@ shared_examples "reports" do
103
156
  it "cannot report it twice" do
104
157
  visit reportable_path
105
158
 
159
+ find("#dropdown-trigger-resource-#{reportable.id}").click
106
160
  expect(page).to have_css(%(button[data-dialog-open="flagModal"]))
107
161
  find(%(button[data-dialog-open="flagModal"])).click
108
162
  expect(page).to have_css(".flag-modal", visible: :visible)
@@ -120,25 +174,26 @@ shared_examples "reports by user type" do
120
174
  let!(:user) { create(:user, :admin, :confirmed, organization:) }
121
175
  include_examples "higher user role reports"
122
176
  include_examples "higher user role hides"
177
+ include_examples "higher user role hides resource with comments"
123
178
  end
124
179
  context "When reporting user is process admin" do
125
- let!(:user) { create :process_admin, :confirmed, participatory_process: }
180
+ let!(:user) { create(:process_admin, :confirmed, participatory_process:) }
126
181
 
127
182
  include_examples "higher user role reports"
128
183
  include_examples "higher user role hides"
129
184
  end
130
185
  context "When reporting user is process collaborator" do
131
- let!(:user) { create :process_collaborator, :confirmed, participatory_process: }
186
+ let!(:user) { create(:process_collaborator, :confirmed, participatory_process:) }
132
187
  include_examples "higher user role reports"
133
188
  include_examples "higher user role does not have hide"
134
189
  end
135
190
  context "When reporting user is process moderator" do
136
- let!(:user) { create :process_moderator, :confirmed, participatory_process: }
191
+ let!(:user) { create(:process_moderator, :confirmed, participatory_process:) }
137
192
  include_examples "higher user role reports"
138
193
  include_examples "higher user role hides"
139
194
  end
140
195
  context "When reporting user is process valuator" do
141
- let!(:user) { create :process_valuator, :confirmed, participatory_process: }
196
+ let!(:user) { create(:process_valuator, :confirmed, participatory_process:) }
142
197
  include_examples "higher user role reports"
143
198
  include_examples "higher user role does not have hide"
144
199
  end
@@ -6,10 +6,10 @@ shared_examples_for "resource endorsed event" do
6
6
  include_context "when a simple event"
7
7
 
8
8
  let(:event_name) { "decidim.events.resource_endorsed" }
9
- let(:author) { create :user, organization: resource.organization }
9
+ let(:author) { create(:user, organization: resource.organization) }
10
10
 
11
11
  let(:extra) { { endorser_id: author.id } }
12
- let(:endorsement) { create :endorsement, resource:, author: }
12
+ let(:endorsement) { create(:endorsement, resource:, author:) }
13
13
  let(:resource_path) { resource_locator(resource).path }
14
14
  let(:follower) { create(:user, organization: resource.organization) }
15
15
  let(:follow) { create(:follow, followable: author, user: follower) }
@@ -29,9 +29,9 @@ shared_examples_for "a resource search with scopes" do |factory_name|
29
29
  describe "scope_id filter" do
30
30
  let(:filter_params) { { with_any_scope: scope_ids } }
31
31
 
32
- let(:scope1) { create :scope, organization: component.organization }
33
- let(:scope2) { create :scope, organization: component.organization }
34
- let(:subscope1) { create :scope, organization: component.organization, parent: scope1 }
32
+ let(:scope1) { create(:scope, organization: component.organization) }
33
+ let(:scope2) { create(:scope, organization: component.organization) }
34
+ let(:subscope1) { create(:scope, organization: component.organization, parent: scope1) }
35
35
 
36
36
  let!(:resource) { create(factory_name, { component:, scope: scope1 }.merge(factory_params)) }
37
37
  let!(:resource2) { create(factory_name, { component:, scope: scope2 }.merge(factory_params)) }
@@ -117,94 +117,100 @@ shared_examples_for "a resource search with scopes" do |factory_name|
117
117
  end
118
118
  end
119
119
 
120
- shared_examples_for "a resource search with categories" do |factory_name, category_mode = :multi|
121
- let(:participatory_space) { component.participatory_space }
122
- let(:filter_params) do
123
- case category_mode
124
- when :single
125
- { with_category: category_ids }
126
- else
127
- { with_any_category: category_ids }
128
- end
129
- end
120
+ shared_examples_for "a resource search with taxonomies" do |factory_name|
130
121
  let(:factory_params) do
131
122
  resource_params
132
123
  rescue StandardError
133
124
  {}
134
125
  end
135
126
 
136
- describe "results" do
137
- let(:category1) { create :category, participatory_space: }
138
- let(:category2) { create :category, participatory_space: }
139
- let(:child_category) { create :category, participatory_space:, parent: category2 }
140
- let!(:resource) { create(factory_name, { component: }.merge(factory_params)) }
141
- let!(:resource2) { create(factory_name, { component:, category: category1 }.merge(factory_params)) }
142
- let!(:resource3) { create(factory_name, { component:, category: category2 }.merge(factory_params)) }
143
- let!(:resource4) { create(factory_name, { component:, category: child_category }.merge(factory_params)) }
127
+ let(:participatory_space) { component.participatory_space }
128
+ let(:filter_params) do
129
+ { with_any_taxonomies: { "#{root_taxonomy.id}": taxonomy_ids } }
130
+ end
144
131
 
145
- before do
146
- get(
147
- request_path,
148
- params: { filter: filter_params },
149
- headers: { "HOST" => component.organization.host }
150
- )
132
+ let(:root_taxonomy) { create(:taxonomy, organization:) }
133
+ let(:taxonomy1) { create(:taxonomy, parent: root_taxonomy, organization:) }
134
+ let(:taxonomy2) { create(:taxonomy, parent: root_taxonomy, organization:) }
135
+ let(:child_taxonomy) { create(:taxonomy, organization:, parent: taxonomy2) }
136
+ let!(:resource) { create(factory_name, { component: }.merge(factory_params)) }
137
+ let!(:resource2) { create(factory_name, { component:, taxonomies: [taxonomy1] }.merge(factory_params)) }
138
+ let!(:resource3) { create(factory_name, { component:, taxonomies: [taxonomy2] }.merge(factory_params)) }
139
+ let!(:resource4) { create(factory_name, { component:, taxonomies: [child_taxonomy] }.merge(factory_params)) }
140
+
141
+ before do
142
+ get(
143
+ request_path,
144
+ params: { filter: filter_params },
145
+ headers: { "HOST" => component.organization.host }
146
+ )
147
+ end
148
+
149
+ context "when no taxonomy filter is present" do
150
+ let(:filter_params) do
151
+ { with_any_taxonomies: [] }
151
152
  end
152
153
 
153
- context "when no category filter is present" do
154
- let(:category_ids) { nil }
154
+ it "includes all resources" do
155
+ expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
156
+ expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
157
+ expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
158
+ expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
159
+ end
160
+ end
155
161
 
156
- it "includes all resources" do
157
- expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
158
- expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
159
- expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
160
- expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
161
- end
162
+ context "when no ids are specified" do
163
+ let(:taxonomy_ids) { [] }
164
+
165
+ it "includes all resources" do
166
+ expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
167
+ expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
168
+ expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
169
+ expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
162
170
  end
171
+ end
163
172
 
164
- context "when a category is selected" do
165
- let(:category_ids) { [category2.id] }
173
+ context "when `all` is being sent" do
174
+ let(:taxonomy_ids) { ["all"] }
166
175
 
167
- it "includes only resources for that category and its children" do
168
- expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
169
- expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
170
- expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
171
- expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
172
- end
176
+ it "includes all resources with the root taxonomy" do
177
+ expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
178
+ expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
179
+ expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
180
+ expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
173
181
  end
182
+ end
174
183
 
175
- context "when a subcategory is selected" do
176
- let(:category_ids) { [child_category.id] }
184
+ context "when a taxonomy is selected" do
185
+ let(:taxonomy_ids) { [taxonomy2.id] }
177
186
 
178
- it "includes only resources for that category" do
179
- expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
180
- expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
181
- expect(subject).not_to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
182
- expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
183
- end
187
+ it "includes only resources for that taxonomy and its children" do
188
+ expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
189
+ expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
190
+ expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
191
+ expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
184
192
  end
193
+ end
185
194
 
186
- context "when `without` is being sent" do
187
- let(:category_ids) { ["without"] }
195
+ context "when multiple taxonomies are selected" do
196
+ let(:taxonomy_ids) { [taxonomy1.id, taxonomy2.id] }
188
197
 
189
- it "returns resources without a category" do
190
- expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
191
- expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
192
- expect(subject).not_to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
193
- expect(subject).not_to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
194
- end
198
+ it "includes only resources for those taxonomies" do
199
+ expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
200
+ expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
201
+ expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
202
+ expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
195
203
  end
204
+ end
196
205
 
197
- if category_mode == :multi
198
- context "when `without` and some category id is being sent" do
199
- let(:category_ids) { ["without", category1.id] }
206
+ context "when a sub_taxonomy is selected" do
207
+ let(:taxonomy_ids) { [child_taxonomy.id] }
200
208
 
201
- it "returns resources without a category and with the selected category" do
202
- expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
203
- expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
204
- expect(subject).not_to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
205
- expect(subject).not_to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
206
- end
207
- end
209
+ it "includes only resources for that taxonomy" do
210
+ expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
211
+ expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
212
+ expect(subject).not_to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
213
+ expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
208
214
  end
209
215
  end
210
216
  end
@@ -3,7 +3,7 @@
3
3
  RSpec.shared_context "when a resource is ready for global search" do
4
4
  let!(:organization) { create(:organization) }
5
5
  let!(:author) { create(:user, :admin, organization:) }
6
- let!(:scope1) { create :scope, organization: }
6
+ let!(:scope1) { create(:scope, organization:) }
7
7
 
8
8
  let(:test_locales) { [:ca, :en, :es] }
9
9
  let(:description1) do
@@ -105,25 +105,6 @@ shared_examples_for "a simple event" do |skip_space_checks|
105
105
  end
106
106
  end
107
107
 
108
- describe "resource_path" do
109
- it "is generated correctly" do
110
- expect(subject.resource_path).to be_kind_of(String)
111
- end
112
- end
113
-
114
- describe "resource_url" do
115
- it "is generated correctly" do
116
- expect(subject.resource_url).to be_kind_of(String)
117
- expect(subject.resource_url).to start_with("http")
118
- end
119
- end
120
-
121
- describe "resource_title" do
122
- it "responds to the method" do
123
- expect(subject).to respond_to(:resource_title)
124
- end
125
- end
126
-
127
108
  unless skip_space_checks
128
109
  describe "participatory_space_url" do
129
110
  it "is generated correctly" do
@@ -197,3 +178,36 @@ shared_examples_for "a simple event notification" do
197
178
  end
198
179
  end
199
180
  end
181
+
182
+ shared_examples_for "a notification event only" do
183
+ describe "types" do
184
+ subject { described_class }
185
+
186
+ it "supports notifications" do
187
+ expect(subject.types).to include :notification
188
+ end
189
+
190
+ it "does not support emails" do
191
+ expect(subject.types).not_to include :email
192
+ end
193
+ end
194
+
195
+ describe "resource_path" do
196
+ it "is generated correctly" do
197
+ expect(subject.resource_path).to be_kind_of(String)
198
+ end
199
+ end
200
+
201
+ describe "resource_url" do
202
+ it "is generated correctly" do
203
+ expect(subject.resource_url).to be_kind_of(String)
204
+ expect(subject.resource_url).to start_with("http")
205
+ end
206
+ end
207
+
208
+ describe "resource_title" do
209
+ it "responds to the method" do
210
+ expect(subject).to respond_to(:resource_title)
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ def visit_resource
6
+ return visit resource if resource.is_a?(String)
7
+
8
+ return visit decidim.root_path if resource.is_a?(Decidim::Organization)
9
+
10
+ visit resource_locator(resource).path
11
+ end
12
+
13
+ shared_examples "a empty social share meta tag" do
14
+ it "has no meta tag" do
15
+ visit_resource
16
+ expect(find('meta[property="og:image"]', visible: false)[:content]).to be_blank
17
+ end
18
+ end
19
+
20
+ shared_examples "a social share meta tag" do |image|
21
+ it "has meta tag for #{image}" do
22
+ visit_resource
23
+ expect(find('meta[property="og:image"]', visible: false)[:content]).to end_with(image)
24
+ end
25
+ end
26
+
27
+ shared_examples "a social share widget" do
28
+ it "has the social share button" do
29
+ visit_resource
30
+
31
+ expect(page).to have_css('button[data-dialog-open="socialShare"]')
32
+ end
33
+
34
+ it "lists all the expected social share providers" do
35
+ visit_resource
36
+ click_on "Share"
37
+
38
+ within "#socialShare" do
39
+ expect(page).to have_css('a[title="Share to X"]')
40
+ expect(page).to have_css('a[title="Share to Facebook"]')
41
+ expect(page).to have_css('a[title="Share to WhatsApp"]')
42
+ expect(page).to have_css('a[title="Share to Telegram"]')
43
+ expect(page).to have_css(".share-modal__input")
44
+ end
45
+ end
46
+ end