decidim-core 0.26.2 → 0.27.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 (543) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/cells/decidim/amendable/announcement_cell.rb +3 -8
  4. data/app/cells/decidim/announcement_cell.rb +1 -1
  5. data/app/cells/decidim/author_cell.rb +1 -1
  6. data/app/cells/decidim/content_blocks/footer_sub_hero/show.erb +1 -1
  7. data/app/cells/decidim/content_blocks/hero/show.erb +1 -1
  8. data/app/cells/decidim/content_blocks/highlighted_content_banner/show.erb +3 -3
  9. data/app/cells/decidim/content_blocks/highlighted_elements_cell.rb +1 -1
  10. data/app/cells/decidim/content_blocks/how_to_participate/show.erb +1 -1
  11. data/app/cells/decidim/content_blocks/last_activity/show.erb +1 -1
  12. data/app/cells/decidim/content_blocks/last_activity_cell.rb +3 -3
  13. data/app/cells/decidim/content_blocks/stats_cell.rb +4 -4
  14. data/app/cells/decidim/content_blocks/sub_hero/show.erb +1 -1
  15. data/app/cells/decidim/data_consent/category.erb +64 -0
  16. data/app/cells/decidim/data_consent/dialog.erb +29 -0
  17. data/app/cells/decidim/data_consent/modal.erb +39 -0
  18. data/app/cells/decidim/data_consent/show.erb +3 -0
  19. data/app/cells/decidim/data_consent_cell.rb +21 -0
  20. data/app/cells/decidim/follow_button_cell.rb +5 -7
  21. data/app/cells/decidim/profile_sidebar_cell.rb +1 -1
  22. data/app/cells/decidim/search_results_cell.rb +1 -1
  23. data/app/cells/decidim/tos_page/refuse_btn_modal.erb +1 -1
  24. data/app/cells/decidim/upload_modal/files.erb +52 -0
  25. data/app/cells/decidim/upload_modal/modal.erb +49 -0
  26. data/app/cells/decidim/upload_modal/show.erb +3 -0
  27. data/app/cells/decidim/upload_modal_cell.rb +205 -0
  28. data/app/cells/decidim/user_conversation/reply.erb +1 -1
  29. data/app/cells/decidim/user_conversations/add_conversation_users.erb +5 -3
  30. data/app/cells/decidim/version_cell.rb +2 -13
  31. data/app/cells/decidim/versions_list_cell.rb +2 -13
  32. data/app/cells/decidim/versions_list_item_cell.rb +2 -13
  33. data/app/commands/decidim/accept_group_invitation.rb +1 -1
  34. data/app/commands/decidim/accept_user_group_join_request.rb +1 -1
  35. data/app/commands/decidim/amendable/accept.rb +1 -1
  36. data/app/commands/decidim/amendable/create_draft.rb +1 -1
  37. data/app/commands/decidim/amendable/destroy_draft.rb +1 -1
  38. data/app/commands/decidim/amendable/promote.rb +1 -1
  39. data/app/commands/decidim/amendable/publish_draft.rb +1 -1
  40. data/app/commands/decidim/amendable/reject.rb +1 -1
  41. data/app/commands/decidim/amendable/update_draft.rb +1 -1
  42. data/app/commands/decidim/amendable/withdraw.rb +1 -1
  43. data/app/commands/decidim/attachment_methods.rb +3 -2
  44. data/app/commands/decidim/create_editor_image.rb +1 -1
  45. data/app/commands/decidim/create_follow.rb +1 -1
  46. data/app/commands/decidim/create_omniauth_registration.rb +2 -3
  47. data/app/commands/decidim/create_registration.rb +1 -2
  48. data/app/commands/decidim/create_report.rb +1 -1
  49. data/app/commands/decidim/create_user_group.rb +2 -2
  50. data/app/commands/decidim/create_user_report.rb +5 -3
  51. data/app/commands/decidim/delete_follow.rb +1 -1
  52. data/app/commands/decidim/demote_membership.rb +1 -1
  53. data/app/commands/decidim/destroy_account.rb +1 -1
  54. data/app/commands/decidim/endorse_resource.rb +1 -1
  55. data/app/commands/decidim/gallery_methods.rb +45 -10
  56. data/app/commands/decidim/invite_user.rb +1 -3
  57. data/app/commands/decidim/invite_user_again.rb +1 -1
  58. data/app/commands/decidim/invite_user_to_group.rb +1 -1
  59. data/app/commands/decidim/join_user_group.rb +1 -1
  60. data/app/commands/decidim/leave_user_group.rb +8 -2
  61. data/app/commands/decidim/messaging/reply_to_conversation.rb +2 -2
  62. data/app/commands/decidim/messaging/start_conversation.rb +2 -2
  63. data/app/commands/decidim/multiple_attachments_methods.rb +44 -5
  64. data/app/commands/decidim/promote_membership.rb +1 -1
  65. data/app/commands/decidim/reject_group_invitation.rb +1 -1
  66. data/app/commands/decidim/reject_user_group_join_request.rb +1 -1
  67. data/app/commands/decidim/remove_user_from_group.rb +1 -1
  68. data/app/commands/decidim/resend_confirmation_instructions.rb +18 -0
  69. data/app/commands/decidim/search.rb +10 -9
  70. data/app/commands/decidim/unendorse_resource.rb +1 -1
  71. data/app/commands/decidim/unsubscribe_settings.rb +1 -1
  72. data/app/commands/decidim/update_account.rb +2 -2
  73. data/app/commands/decidim/update_notifications_settings.rb +3 -2
  74. data/app/commands/decidim/update_password.rb +31 -0
  75. data/app/commands/decidim/update_user_group.rb +2 -2
  76. data/app/commands/decidim/update_user_interests.rb +1 -1
  77. data/app/commands/decidim/validate_upload.rb +15 -0
  78. data/app/controllers/concerns/decidim/devise_controllers.rb +0 -1
  79. data/app/controllers/concerns/decidim/filter_resource.rb +23 -24
  80. data/app/controllers/concerns/decidim/force_authentication.rb +1 -2
  81. data/app/controllers/concerns/decidim/http_caching_disabler.rb +1 -1
  82. data/app/controllers/concerns/decidim/needs_password_change.rb +43 -0
  83. data/app/controllers/concerns/decidim/needs_tos_accepted.rb +3 -3
  84. data/app/controllers/concerns/decidim/orderable.rb +1 -1
  85. data/app/controllers/concerns/decidim/participatory_space_context.rb +2 -2
  86. data/app/controllers/decidim/account_controller.rb +45 -0
  87. data/app/controllers/decidim/application_controller.rb +1 -1
  88. data/app/controllers/decidim/devise/invitations_controller.rb +2 -0
  89. data/app/controllers/decidim/devise/passwords_controller.rb +33 -0
  90. data/app/controllers/decidim/devise/registrations_controller.rb +2 -0
  91. data/app/controllers/decidim/devise/sessions_controller.rb +2 -0
  92. data/app/controllers/decidim/{data_portability_controller.rb → download_your_data_controller.rb} +8 -8
  93. data/app/controllers/decidim/groups_controller.rb +5 -0
  94. data/app/controllers/decidim/last_activities_controller.rb +7 -9
  95. data/app/controllers/decidim/manifests_controller.rb +11 -0
  96. data/app/controllers/decidim/newsletters_controller.rb +1 -1
  97. data/app/controllers/decidim/notifications_subscriptions_controller.rb +16 -0
  98. data/app/controllers/decidim/offline_controller.rb +7 -0
  99. data/app/controllers/decidim/profiles_controller.rb +1 -1
  100. data/app/controllers/decidim/searches_controller.rb +4 -3
  101. data/app/controllers/decidim/short_links_controller.rb +35 -0
  102. data/app/controllers/decidim/upload_validations_controller.rb +44 -0
  103. data/app/controllers/decidim/user_activities_controller.rb +32 -16
  104. data/app/controllers/decidim/user_interests_controller.rb +0 -2
  105. data/app/controllers/decidim/user_timeline_controller.rb +6 -8
  106. data/app/events/decidim/change_nickname_event.rb +21 -0
  107. data/app/forms/decidim/account_form.rb +7 -6
  108. data/app/forms/decidim/form.rb +1 -1
  109. data/app/forms/decidim/messaging/conversation_form.rb +1 -1
  110. data/app/forms/decidim/notifications_settings_form.rb +8 -2
  111. data/app/forms/decidim/password_form.rb +10 -0
  112. data/app/forms/decidim/registration_form.rb +10 -4
  113. data/app/forms/decidim/upload_validation_form.rb +54 -0
  114. data/app/forms/decidim/user_group_form.rb +1 -1
  115. data/app/forms/decidim/user_interest_scope_form.rb +1 -1
  116. data/app/forms/decidim/user_interests_form.rb +1 -1
  117. data/app/forms/translatable_presence_validator.rb +2 -2
  118. data/app/forms/url_validator.rb +1 -1
  119. data/app/helpers/decidim/application_helper.rb +2 -2
  120. data/app/helpers/decidim/attachments_helper.rb +1 -1
  121. data/app/helpers/decidim/cells_paginate_helper.rb +1 -1
  122. data/app/helpers/decidim/datalist_select_helper.rb +40 -0
  123. data/app/helpers/decidim/decidim_form_helper.rb +1 -1
  124. data/app/helpers/decidim/followable_helper.rb +1 -1
  125. data/app/helpers/decidim/icon_helper.rb +1 -1
  126. data/app/helpers/decidim/layout_helper.rb +15 -1
  127. data/app/helpers/decidim/map_helper.rb +12 -8
  128. data/app/helpers/decidim/meta_tags_helper.rb +0 -2
  129. data/app/helpers/decidim/notifications_settings_helper.rb +15 -0
  130. data/app/helpers/decidim/passwords_helper.rb +41 -0
  131. data/app/helpers/decidim/sanitize_helper.rb +1 -0
  132. data/app/helpers/decidim/searches_helper.rb +6 -6
  133. data/app/helpers/decidim/short_link_helper.rb +28 -0
  134. data/app/helpers/decidim/translations_helper.rb +2 -2
  135. data/app/jobs/decidim/{data_portability_export_job.rb → download_your_data_export_job.rb} +5 -5
  136. data/app/jobs/decidim/email_notifications_digest_generator_job.rb +21 -0
  137. data/app/jobs/decidim/notification_generator_for_recipient_job.rb +5 -3
  138. data/app/jobs/decidim/reminder_generator_job.rb +12 -0
  139. data/app/jobs/decidim/resend_confirmation_instructions_job.rb +11 -0
  140. data/app/jobs/decidim/user_report_job.rb +2 -2
  141. data/app/mailers/concerns/decidim/multitenant_asset_host.rb +11 -3
  142. data/app/mailers/decidim/application_mailer.rb +1 -1
  143. data/app/mailers/decidim/block_user_mailer.rb +8 -7
  144. data/app/mailers/decidim/export_mailer.rb +2 -2
  145. data/app/mailers/decidim/newsletter_mailer.rb +2 -2
  146. data/app/mailers/decidim/newsletters_opt_in_mailer.rb +7 -5
  147. data/app/mailers/decidim/notifications_digest_mailer.rb +23 -0
  148. data/app/mailers/decidim/user_report_mailer.rb +10 -11
  149. data/app/models/decidim/action_log.rb +86 -2
  150. data/app/models/decidim/amendment.rb +0 -1
  151. data/app/models/decidim/area.rb +1 -2
  152. data/app/models/decidim/area_type.rb +5 -0
  153. data/app/models/decidim/attachment.rb +6 -0
  154. data/app/models/decidim/attachment_collection.rb +5 -0
  155. data/app/models/decidim/category.rb +9 -4
  156. data/app/models/decidim/coauthorship.rb +0 -2
  157. data/app/models/decidim/contextual_help_section.rb +5 -1
  158. data/app/models/decidim/follow.rb +2 -2
  159. data/app/models/decidim/gamification/badge_score.rb +0 -1
  160. data/app/models/decidim/identity.rb +2 -2
  161. data/app/models/decidim/messaging/conversation.rb +4 -4
  162. data/app/models/decidim/messaging/message.rb +1 -2
  163. data/app/models/decidim/messaging/participation.rb +0 -2
  164. data/app/models/decidim/messaging/receipt.rb +0 -2
  165. data/app/models/decidim/notification.rb +5 -2
  166. data/app/models/decidim/oauth_application.rb +12 -1
  167. data/app/models/decidim/organization.rb +7 -7
  168. data/app/models/decidim/participatory_space_private_user.rb +4 -2
  169. data/app/models/decidim/permission_action.rb +1 -0
  170. data/app/models/decidim/reminder.rb +10 -0
  171. data/app/models/decidim/reminder_delivery.rb +7 -0
  172. data/app/models/decidim/reminder_record.rb +29 -0
  173. data/app/models/decidim/report.rb +2 -2
  174. data/app/models/decidim/scope.rb +3 -4
  175. data/app/models/decidim/scope_type.rb +5 -0
  176. data/app/models/decidim/share_token.rb +0 -2
  177. data/app/models/decidim/short_link.rb +162 -0
  178. data/app/models/decidim/user.rb +34 -6
  179. data/app/models/decidim/user_base_entity.rb +1 -1
  180. data/app/models/decidim/user_group.rb +3 -3
  181. data/app/models/decidim/user_moderation.rb +0 -2
  182. data/app/models/decidim/user_report.rb +2 -2
  183. data/app/packs/entrypoints/decidim_core.js +2 -2
  184. data/app/packs/entrypoints/decidim_sw.js +1 -0
  185. data/app/packs/src/decidim/autocomplete.js +298 -0
  186. data/app/packs/src/decidim/cookie_consent/consent_manager.js +133 -0
  187. data/app/packs/src/decidim/cookie_consent/cookie_consent.js +103 -0
  188. data/app/packs/src/decidim/datalist_select.js +36 -0
  189. data/app/packs/src/decidim/direct_uploads/upload_field.js +117 -0
  190. data/app/packs/src/decidim/direct_uploads/upload_modal.js +264 -0
  191. data/app/packs/src/decidim/direct_uploads/upload_utility.js +49 -0
  192. data/app/packs/src/decidim/direct_uploads/uploader.js +89 -0
  193. data/app/packs/src/decidim/external_domain_warning.js +1 -1
  194. data/app/packs/src/decidim/external_link.js +14 -3
  195. data/app/packs/src/decidim/external_link.test.js +64 -0
  196. data/app/packs/src/decidim/geocoding.js +10 -35
  197. data/app/packs/src/decidim/identity_selector_dialog.js +1 -1
  198. data/app/packs/src/decidim/impersonation.js +3 -3
  199. data/app/packs/src/decidim/input_character_counter.js +177 -7
  200. data/app/packs/src/decidim/input_multiple_mentions.js +87 -187
  201. data/app/packs/src/decidim/map/factory.js +3 -1
  202. data/app/packs/src/decidim/map/icon.js +2 -1
  203. data/app/packs/src/decidim/map/legacy.js +2 -2
  204. data/app/packs/src/decidim/map/svg-icon.js +248 -0
  205. data/app/packs/src/decidim/map.js +2 -2
  206. data/app/packs/src/decidim/security/selfxss_warning.js +5 -1
  207. data/app/packs/src/decidim/session_timeouter.js +15 -15
  208. data/app/packs/src/decidim/sw/a2hs.js +28 -0
  209. data/app/packs/src/decidim/sw/index.js +3 -0
  210. data/app/packs/src/decidim/sw/loader.js +18 -0
  211. data/app/packs/src/decidim/sw/push-permissions.js +87 -0
  212. data/app/packs/src/decidim/sw/sw.js +80 -0
  213. data/app/packs/src/decidim/vizzs/areachart.js +33 -28
  214. data/app/packs/src/decidim/vizzs/{metrics.js → index.js} +0 -0
  215. data/app/packs/src/decidim/vizzs/linechart.js +23 -18
  216. data/app/packs/src/decidim/vizzs/rowchart.js +15 -11
  217. data/app/packs/stylesheets/decidim/email.scss +66 -0
  218. data/app/packs/stylesheets/decidim/layouts/_user.scss +8 -0
  219. data/app/packs/stylesheets/decidim/modules/_autocomplete.scss +99 -0
  220. data/app/packs/stylesheets/decidim/modules/_cookie-consent.scss +115 -0
  221. data/app/packs/stylesheets/decidim/modules/_footer.scss +4 -0
  222. data/app/packs/stylesheets/decidim/modules/_input-multiple-mentions.scss +29 -2
  223. data/app/packs/stylesheets/decidim/modules/_modules.scss +3 -1
  224. data/app/packs/stylesheets/decidim/modules/_reveal.scss +15 -0
  225. data/app/packs/stylesheets/decidim/modules/_upload_modal.scss +143 -0
  226. data/app/packs/stylesheets/decidim/utils/_fontface.scss +3 -0
  227. data/app/permissions/decidim/permissions.rb +2 -4
  228. data/app/presenters/decidim/admin_log/area_type_presenter.rb +34 -0
  229. data/app/presenters/decidim/admin_log/attachment_collection_presenter.rb +35 -0
  230. data/app/presenters/decidim/admin_log/attachment_presenter.rb +27 -0
  231. data/app/presenters/decidim/admin_log/category_presenter.rb +36 -0
  232. data/app/presenters/decidim/admin_log/component_presenter.rb +35 -3
  233. data/app/presenters/decidim/admin_log/contextual_help_section_presenter.rb +33 -0
  234. data/app/presenters/decidim/admin_log/organization_presenter.rb +9 -4
  235. data/app/presenters/decidim/admin_log/scope_type_presenter.rb +34 -0
  236. data/app/presenters/decidim/home_stats_presenter.rb +4 -2
  237. data/app/presenters/decidim/log/base_presenter.rb +1 -1
  238. data/app/presenters/decidim/menu_item_presenter.rb +1 -1
  239. data/app/presenters/decidim/metric_charts_presenter.rb +7 -1
  240. data/app/presenters/decidim/nil_presenter.rb +3 -1
  241. data/app/presenters/decidim/notification_to_mailer_presenter.rb +39 -0
  242. data/app/presenters/decidim/notifications_digest_presenter.rb +42 -0
  243. data/app/presenters/decidim/official_author_presenter.rb +4 -0
  244. data/app/presenters/decidim/organization_presenter.rb +22 -0
  245. data/app/presenters/decidim/push_notification_presenter.rb +24 -0
  246. data/app/presenters/decidim/stats_presenter.rb +1 -1
  247. data/app/presenters/decidim/validation_errors_presenter.rb +1 -1
  248. data/app/queries/decidim/messaging/user_conversations.rb +1 -1
  249. data/app/queries/decidim/metric_manage.rb +1 -1
  250. data/app/queries/decidim/own_activities.rb +11 -0
  251. data/app/queries/decidim/participatory_processes_with_user_role.rb +1 -1
  252. data/app/{services/decidim/activity_search.rb → queries/decidim/public_activities.rb} +35 -77
  253. data/app/queries/decidim/public_components.rb +1 -1
  254. data/app/queries/decidim/similar_emendations.rb +1 -1
  255. data/app/queries/decidim/stats_users_count.rb +1 -1
  256. data/app/queries/decidim/user_groups/accepted_memberships.rb +1 -1
  257. data/app/queries/decidim/user_groups/accepted_user_groups.rb +1 -1
  258. data/app/queries/decidim/user_groups/accepted_users.rb +1 -1
  259. data/app/queries/decidim/user_groups/admin_memberships.rb +1 -1
  260. data/app/queries/decidim/user_groups/invited_memberships.rb +1 -1
  261. data/app/queries/decidim/user_groups/manageable_user_groups.rb +1 -1
  262. data/app/queries/decidim/user_groups/member_memberships.rb +1 -1
  263. data/app/services/decidim/{data_portability_exporter.rb → download_your_data_exporter.rb} +6 -6
  264. data/app/services/decidim/email_notification_generator.rb +2 -2
  265. data/app/services/decidim/engine_resolver.rb +66 -0
  266. data/app/services/decidim/events_manager.rb +1 -1
  267. data/app/services/decidim/iframe_disabler.rb +31 -0
  268. data/app/services/decidim/notification_generator_for_recipient.rb +1 -1
  269. data/app/services/decidim/notifications_digest_sending_decider.rb +18 -0
  270. data/app/services/decidim/notifications_subscriptions_persistor.rb +37 -0
  271. data/app/services/decidim/open_data_exporter.rb +1 -1
  272. data/app/services/decidim/resource_search.rb +17 -164
  273. data/app/services/decidim/send_push_notification.rb +59 -0
  274. data/app/services/decidim/traceability.rb +1 -1
  275. data/app/uploaders/decidim/application_uploader.rb +2 -12
  276. data/app/uploaders/decidim/cw/attachment_uploader.rb +1 -1
  277. data/app/uploaders/decidim/cw/{data_portability_uploader.rb → download_your_data_uploader.rb} +3 -3
  278. data/app/uploaders/decidim/cw/image_uploader.rb +2 -2
  279. data/app/uploaders/decidim/organization_favicon_uploader.rb +3 -2
  280. data/app/validators/passthru_validator.rb +29 -21
  281. data/app/validators/password_validator.rb +25 -4
  282. data/app/validators/uploader_image_dimensions_validator.rb +1 -1
  283. data/app/views/decidim/account/_account_notification.js.erb +20 -0
  284. data/app/views/decidim/account/_password_fields.html.erb +2 -2
  285. data/app/views/decidim/account/cancel_email_change.js.erb +6 -0
  286. data/app/views/decidim/account/resend_confirmation_instructions.erb +1 -0
  287. data/app/views/decidim/account/show.html.erb +19 -6
  288. data/app/views/decidim/application/{_attachments.html.erb → _attachments.erb} +2 -2
  289. data/app/views/decidim/application/_collection.html.erb +1 -1
  290. data/app/views/decidim/application/{_document.html.erb → _document.erb} +0 -0
  291. data/app/views/decidim/application/{_documents.html.erb → _documents.erb} +2 -2
  292. data/app/views/decidim/application/{_photos.html.erb → _photos.erb} +0 -0
  293. data/app/views/decidim/devise/confirmations/new.html.erb +1 -1
  294. data/app/views/decidim/devise/invitations/edit.html.erb +3 -4
  295. data/app/views/decidim/devise/omniauth_registrations/new.html.erb +3 -3
  296. data/app/views/decidim/devise/passwords/edit.html.erb +7 -5
  297. data/app/views/decidim/devise/passwords/new.html.erb +1 -1
  298. data/app/views/decidim/devise/registrations/edit.html.erb +5 -5
  299. data/app/views/decidim/devise/registrations/new.html.erb +5 -5
  300. data/app/views/decidim/devise/sessions/new.html.erb +2 -2
  301. data/app/views/decidim/{data_portability → download_your_data}/export.html.erb +0 -0
  302. data/app/views/decidim/{data_portability → download_your_data}/show.html.erb +2 -2
  303. data/app/views/decidim/export_mailer/download_your_data_export.html.erb +7 -0
  304. data/app/views/decidim/last_activities/index.html.erb +1 -1
  305. data/app/views/decidim/manifests/show.json.erb +31 -0
  306. data/app/views/decidim/messaging/conversations/_add_conversation_users.html.erb +5 -3
  307. data/app/views/decidim/messaging/conversations/_reply.html.erb +1 -1
  308. data/app/views/decidim/messaging/conversations/_start.html.erb +1 -3
  309. data/app/views/decidim/messaging/conversations/create.js.erb +1 -0
  310. data/app/views/decidim/notifications_digest_mailer/_email_content.html.erb +11 -0
  311. data/app/views/decidim/notifications_digest_mailer/digest_mail.erb +27 -0
  312. data/app/views/decidim/notifications_settings/show.html.erb +34 -9
  313. data/app/views/decidim/offline/show.html.erb +9 -0
  314. data/app/views/decidim/pages/_standalone.html.erb +1 -1
  315. data/app/views/decidim/reported_mailer/hide.html.erb +1 -1
  316. data/app/views/decidim/reported_mailer/report.html.erb +1 -1
  317. data/app/views/decidim/scopes/picker.html.erb +1 -1
  318. data/app/views/decidim/searches/_filters.html.erb +2 -2
  319. data/app/views/decidim/shared/participatory_space_filters/_filters.html.erb +3 -3
  320. data/app/views/decidim/user_report_mailer/notify.html.erb +10 -3
  321. data/app/views/devise/mailer/confirmation_instructions.html.erb +3 -1
  322. data/app/views/layouts/decidim/_application.html.erb +6 -3
  323. data/app/views/layouts/decidim/_cookie_warning.html.erb +8 -8
  324. data/app/views/layouts/decidim/_decidim_javascript.html.erb +12 -0
  325. data/app/views/layouts/decidim/_head.html.erb +4 -2
  326. data/app/views/layouts/decidim/_js_configuration.html.erb +5 -1
  327. data/app/views/layouts/decidim/_main_footer.html.erb +1 -0
  328. data/app/views/layouts/decidim/_offline_banner.html.erb +11 -0
  329. data/app/views/layouts/decidim/widget.html.erb +2 -2
  330. data/config/assets.rb +1 -0
  331. data/config/locales/am-ET.yml +1 -0
  332. data/config/locales/ar.yml +48 -36
  333. data/config/locales/bg.yml +15 -30
  334. data/config/locales/ca.yml +186 -35
  335. data/config/locales/cs.yml +186 -33
  336. data/config/locales/da.yml +1 -0
  337. data/config/locales/de.yml +25 -36
  338. data/config/locales/el.yml +15 -30
  339. data/config/locales/en.yml +183 -32
  340. data/config/locales/eo.yml +4 -6
  341. data/config/locales/es-MX.yml +185 -34
  342. data/config/locales/es-PY.yml +185 -34
  343. data/config/locales/es.yml +185 -34
  344. data/config/locales/et.yml +1 -0
  345. data/config/locales/eu.yml +15 -36
  346. data/config/locales/fi-plain.yml +184 -33
  347. data/config/locales/fi.yml +184 -33
  348. data/config/locales/fr-CA.yml +170 -33
  349. data/config/locales/fr.yml +170 -33
  350. data/config/locales/ga-IE.yml +5 -7
  351. data/config/locales/gl.yml +47 -30
  352. data/config/locales/hr.yml +1 -0
  353. data/config/locales/hu.yml +65 -35
  354. data/config/locales/id-ID.yml +15 -29
  355. data/config/locales/is-IS.yml +6 -15
  356. data/config/locales/it.yml +22 -38
  357. data/config/locales/ja.yml +173 -34
  358. data/config/locales/ko.yml +1 -0
  359. data/config/locales/lb.yml +16 -32
  360. data/config/locales/lt.yml +1 -0
  361. data/config/locales/lv.yml +15 -28
  362. data/config/locales/mt.yml +1 -0
  363. data/config/locales/nl.yml +25 -33
  364. data/config/locales/no.yml +24 -35
  365. data/config/locales/om-ET.yml +1 -0
  366. data/config/locales/pl.yml +113 -32
  367. data/config/locales/pt-BR.yml +17 -32
  368. data/config/locales/pt.yml +16 -32
  369. data/config/locales/ro-RO.yml +20 -36
  370. data/config/locales/ru.yml +15 -27
  371. data/config/locales/si-LK.yml +1 -0
  372. data/config/locales/sk.yml +15 -30
  373. data/config/locales/sl.yml +1 -0
  374. data/config/locales/so-SO.yml +1 -0
  375. data/config/locales/sr-CS.yml +1 -0
  376. data/config/locales/sv.yml +69 -34
  377. data/config/locales/sw-KE.yml +1 -0
  378. data/config/locales/ti-ER.yml +1 -0
  379. data/config/locales/tr-TR.yml +15 -29
  380. data/config/locales/uk.yml +15 -26
  381. data/config/locales/val-ES.yml +1 -0
  382. data/config/locales/vi.yml +1 -0
  383. data/config/locales/zh-CN.yml +15 -28
  384. data/config/locales/zh-TW.yml +1 -0
  385. data/config/routes.rb +17 -2
  386. data/db/migrate/20180508111710_add_accepted_tos_version_field_to_users.rb +1 -0
  387. data/db/migrate/20181030090144_destroy_deleted_users_follows.rb +1 -0
  388. data/db/migrate/20190412131728_fix_user_names.rb +4 -4
  389. data/db/migrate/20210831181634_add_service_name_to_active_storage_blobs.active_storage.rb +22 -0
  390. data/db/migrate/20210831181635_create_active_storage_variant_records.active_storage.rb +14 -0
  391. data/db/migrate/20211208155453_create_decidim_reminders.rb +11 -0
  392. data/db/migrate/20211209121025_create_decidim_reminder_records.rb +11 -0
  393. data/db/migrate/20211209121040_create_decidim_reminder_deliveries.rb +10 -0
  394. data/db/migrate/20220118121921_change_required_description_categories.rb +7 -0
  395. data/db/migrate/20220127113419_add_notification_settings_to_users.rb +7 -0
  396. data/db/migrate/20220203121137_add_notifications_sending_frequency_to_users.rb +7 -0
  397. data/db/migrate/20220215172439_add_digest_sent_at_to_users.rb +7 -0
  398. data/db/migrate/20220323195258_add_index_to_decidim_users_notifications_sending_frequency.rb +7 -0
  399. data/db/migrate/20220427142214_drop_emails_on_notifications_flag_from_user.rb +15 -0
  400. data/db/migrate/20220518094535_add_previous_passwords_to_users.rb +20 -0
  401. data/db/migrate/20220524195530_create_decidim_short_links.rb +23 -0
  402. data/db/seeds.rb +17 -18
  403. data/lib/decidim/acts_as_tree.rb +47 -0
  404. data/lib/decidim/api/input_sorts/component_input_sort.rb +2 -1
  405. data/lib/decidim/api/interfaces/authorable_interface.rb +6 -5
  406. data/lib/decidim/asset_router.rb +80 -0
  407. data/lib/decidim/attachment_attributes.rb +8 -8
  408. data/lib/decidim/attribute_object/form.rb +174 -0
  409. data/lib/decidim/attribute_object/model.rb +148 -0
  410. data/lib/decidim/attribute_object/nested_validator.rb +22 -0
  411. data/lib/decidim/attribute_object/type_map.rb +14 -0
  412. data/lib/decidim/attribute_object/type_resolver.rb +91 -0
  413. data/lib/decidim/attribute_object.rb +26 -0
  414. data/lib/decidim/attributes/array.rb +62 -0
  415. data/lib/decidim/attributes/blob.rb +20 -0
  416. data/lib/decidim/attributes/clean_string.rb +12 -6
  417. data/lib/decidim/attributes/hash.rb +36 -0
  418. data/lib/decidim/attributes/integer.rb +17 -0
  419. data/lib/decidim/attributes/localized_date.rb +9 -7
  420. data/lib/decidim/attributes/model.rb +24 -0
  421. data/lib/decidim/attributes/object.rb +28 -0
  422. data/lib/decidim/attributes/symbol.rb +23 -0
  423. data/lib/decidim/attributes/time_with_zone.rb +9 -7
  424. data/lib/decidim/attributes.rb +29 -0
  425. data/lib/decidim/authorable.rb +21 -6
  426. data/lib/decidim/authorization_form_builder.rb +9 -11
  427. data/lib/decidim/carrier_wave_migrator_service.rb +15 -15
  428. data/lib/decidim/coauthorable.rb +22 -4
  429. data/lib/decidim/command.rb +44 -0
  430. data/lib/decidim/common_passwords.rb +1 -1
  431. data/lib/decidim/component_manifest.rb +5 -5
  432. data/lib/decidim/component_validator.rb +2 -2
  433. data/lib/decidim/content_block_manifest.rb +1 -1
  434. data/lib/decidim/content_parsers/hashtag_parser.rb +2 -2
  435. data/lib/decidim/content_parsers/resource_parser.rb +1 -1
  436. data/lib/decidim/content_parsers/user_group_parser.rb +1 -1
  437. data/lib/decidim/content_parsers/user_parser.rb +4 -4
  438. data/lib/decidim/content_renderers/hashtag_renderer.rb +1 -1
  439. data/lib/decidim/content_renderers/link_renderer.rb +2 -2
  440. data/lib/decidim/content_renderers/user_group_renderer.rb +1 -1
  441. data/lib/decidim/content_renderers/user_renderer.rb +1 -1
  442. data/lib/decidim/controller_helpers.rb +41 -0
  443. data/lib/decidim/core/engine.rb +29 -18
  444. data/lib/decidim/core/test/factories.rb +48 -8
  445. data/lib/decidim/core/test/shared_examples/admin_resource_gallery_examples.rb +16 -4
  446. data/lib/decidim/core/test/shared_examples/amendable/amendment_form_examples.rb +1 -1
  447. data/lib/decidim/core/test/shared_examples/authorable_interface_examples.rb +15 -2
  448. data/lib/decidim/core/test/shared_examples/coauthorable_interface_examples.rb +2 -2
  449. data/lib/decidim/core/test/shared_examples/comments_examples.rb +203 -0
  450. data/lib/decidim/core/test/shared_examples/localised_email.rb +1 -1
  451. data/lib/decidim/core/test/shared_examples/logo_email.rb +1 -1
  452. data/lib/decidim/core/test/shared_examples/map_examples.rb +2 -2
  453. data/lib/decidim/core/test/shared_examples/preview_component_with_share_token_examples.rb +0 -6
  454. data/lib/decidim/core/test/shared_examples/resource_search_examples.rb +120 -40
  455. data/lib/decidim/core/test/shared_examples/resourceable.rb +0 -6
  456. data/lib/decidim/core/test/shared_examples/searchable_participatory_space_examples.rb +1 -1
  457. data/lib/decidim/core/test/shared_examples/searchable_resources_shared_context.rb +1 -1
  458. data/lib/decidim/core/test/shared_examples/system_endorse_resource_examples.rb +3 -3
  459. data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +2 -2
  460. data/lib/decidim/core/version.rb +1 -1
  461. data/lib/decidim/core.rb +108 -14
  462. data/lib/decidim/{data_portability.rb → download_your_data.rb} +3 -3
  463. data/lib/decidim/{data_portability_serializers/data_portability_conversation_serializer.rb → download_your_data_serializers/download_your_data_conversation_serializer.rb} +2 -2
  464. data/lib/decidim/{data_portability_serializers/data_portability_follow_serializer.rb → download_your_data_serializers/download_your_data_follow_serializer.rb} +2 -2
  465. data/lib/decidim/{data_portability_serializers/data_portability_identity_serializer.rb → download_your_data_serializers/download_your_data_identity_serializer.rb} +2 -2
  466. data/lib/decidim/{data_portability_serializers/data_portability_notification_serializer.rb → download_your_data_serializers/download_your_data_notification_serializer.rb} +2 -2
  467. data/lib/decidim/{data_portability_serializers/data_portability_participatory_space_private_user_serializer.rb → download_your_data_serializers/download_your_data_participatory_space_private_user_serializer.rb} +2 -2
  468. data/lib/decidim/{data_portability_serializers/data_portability_report_serializer.rb → download_your_data_serializers/download_your_data_report_serializer.rb} +2 -2
  469. data/lib/decidim/{data_portability_serializers/data_portability_user_group_serializer.rb → download_your_data_serializers/download_your_data_user_group_serializer.rb} +2 -2
  470. data/lib/decidim/{data_portability_serializers/data_portability_user_serializer.rb → download_your_data_serializers/download_your_data_user_serializer.rb} +3 -3
  471. data/lib/decidim/download_your_data_serializers.rb +23 -0
  472. data/lib/decidim/engine_router.rb +7 -1
  473. data/lib/decidim/env.rb +56 -0
  474. data/lib/decidim/event_recorder.rb +25 -0
  475. data/lib/decidim/events/base_event.rb +10 -14
  476. data/lib/decidim/events/simple_event.rb +12 -4
  477. data/lib/decidim/exporters/export_data.rb +1 -1
  478. data/lib/decidim/exporters/export_manifest.rb +2 -1
  479. data/lib/decidim/file_validator_humanizer.rb +24 -1
  480. data/lib/decidim/filterable_resource.rb +55 -0
  481. data/lib/decidim/fingerprint_calculator.rb +2 -4
  482. data/lib/decidim/form_builder.rb +158 -130
  483. data/lib/decidim/gamification/badge.rb +2 -3
  484. data/lib/decidim/gamification/badge_scorer.rb +1 -0
  485. data/lib/decidim/has_area.rb +27 -0
  486. data/lib/decidim/has_attachments.rb +2 -2
  487. data/lib/decidim/has_category.rb +36 -0
  488. data/lib/decidim/importers/import_manifest.rb +3 -21
  489. data/lib/decidim/jsonb_attributes.rb +6 -4
  490. data/lib/decidim/manifest_messages.rb +23 -0
  491. data/lib/decidim/map/autocomplete.rb +6 -4
  492. data/lib/decidim/map/frontend.rb +2 -2
  493. data/lib/decidim/map/provider/geocoding/here.rb +5 -5
  494. data/lib/decidim/map/provider/here.rb +3 -0
  495. data/lib/decidim/map/provider/osm.rb +3 -0
  496. data/lib/decidim/map.rb +4 -4
  497. data/lib/decidim/menu.rb +1 -1
  498. data/lib/decidim/metric_manifest.rb +2 -2
  499. data/lib/decidim/nicknamizable.rb +1 -1
  500. data/lib/decidim/notification_setting_manifest.rb +19 -0
  501. data/lib/decidim/organization_settings.rb +8 -7
  502. data/lib/decidim/participatory_space_context_manifest.rb +2 -2
  503. data/lib/decidim/participatory_space_manifest.rb +2 -2
  504. data/lib/decidim/processes_file_locally.rb +31 -0
  505. data/lib/decidim/query.rb +84 -0
  506. data/lib/decidim/record_encryptor.rb +29 -8
  507. data/lib/decidim/reminder_manifest.rb +75 -0
  508. data/lib/decidim/reminder_registry.rb +67 -0
  509. data/lib/decidim/resource_manifest.rb +1 -1
  510. data/lib/decidim/resourceable.rb +11 -0
  511. data/lib/decidim/scopable.rb +15 -0
  512. data/lib/decidim/settings_manifest.rb +4 -4
  513. data/lib/decidim/spring.rb +16 -0
  514. data/lib/decidim/translatable_attributes.rb +12 -8
  515. data/lib/decidim/url_option_resolver.rb +50 -0
  516. data/lib/decidim/view_hooks.rb +1 -1
  517. data/lib/decidim/view_model.rb +5 -1
  518. data/lib/decidim/webpacker/thread_safe_compiler.rb +30 -0
  519. data/lib/decidim/webpacker/webpack/custom.js +15 -3
  520. data/lib/decidim/webpacker/webpacker.yml +1 -1
  521. data/lib/decidim/webpacker.rb +2 -0
  522. data/lib/devise/models/decidim_validatable.rb +1 -1
  523. data/lib/tasks/decidim_active_storage_migration_tasks.rake +1 -3
  524. data/lib/tasks/{decidim_data_portability_tasks.rake → decidim_download_your_data_tasks.rake} +9 -9
  525. data/lib/tasks/decidim_mailers_tasks.rake +23 -0
  526. data/lib/tasks/decidim_metrics_tasks.rake +1 -1
  527. data/lib/tasks/decidim_pwa_tasks.rake +18 -0
  528. data/lib/tasks/decidim_reminders_tasks.rake +17 -0
  529. data/lib/tasks/decidim_tasks.rake +6 -1
  530. data/lib/tasks/decidim_webpacker_tasks.rake +1 -1
  531. data/lib/tasks/upgrade/decidim_fix_nickname_uniqueness.rake +51 -0
  532. metadata +184 -83
  533. data/app/controllers/decidim/cookie_policy_controller.rb +0 -24
  534. data/app/helpers/decidim/cookies_helper.rb +0 -11
  535. data/app/packs/src/decidim/vizzs/renders.js +0 -9
  536. data/app/packs/src/decidim/vizzs.js +0 -1
  537. data/app/packs/stylesheets/decidim/modules/_cookie-bar.scss +0 -26
  538. data/app/services/decidim/home_activity_search.rb +0 -80
  539. data/app/services/decidim/participatory_space_search.rb +0 -54
  540. data/app/views/decidim/cookie_policy/accept.js.erb +0 -3
  541. data/app/views/decidim/export_mailer/data_portability_export.html.erb +0 -7
  542. data/lib/decidim/data_portability_serializers.rb +0 -23
  543. data/lib/decidim/middleware/rails_cookies.rb +0 -23
@@ -121,6 +121,209 @@ shared_examples "comments" do
121
121
  end
122
122
  end
123
123
 
124
+ it "updates the numbers of characters left correctly" do
125
+ within ".add-comment form" do
126
+ fill_in "add-comment-#{commentable.commentable_type.demodulize}-#{commentable.id}", with: "This is a new comment."
127
+ expect(page).to have_content("1978 characters left")
128
+ end
129
+ end
130
+
131
+ context "when working with the screen reader character counter" do
132
+ let(:field_id) { "add-comment-#{commentable.commentable_type.demodulize}-#{commentable.id}" }
133
+ let(:field) { page.find("##{field_id}") }
134
+
135
+ before do
136
+ # Make sure the focus stays in the comment form during these tests
137
+ # because only then the screen reader
138
+ page.execute_script("document.getElementById('#{field_id}').focus()")
139
+ end
140
+
141
+ it "updates the numbers of characters left correctly for screen reader" do
142
+ within ".add-comment form" do
143
+ fill_in field_id, with: "This is a new comment."
144
+
145
+ # The screen reader character counter should update only when the user
146
+ # reaches 10% interval of the total characters available not to
147
+ # announce the remaining characters after every keystroke.
148
+ field.native.send_keys " Sending some new text."
149
+ within ".remaining-character-count" do
150
+ expect(page).to have_content("1955 characters left") # Normal
151
+ end
152
+ within ".remaining-character-count-sr" do
153
+ expect(page).to have_content("2000 characters left") # Screen reader
154
+ end
155
+
156
+ # After 10% of the total characters is reached, it should be updated
157
+ # to the screen reader section to announce it.
158
+ field.native.send_keys "a" * 155
159
+ within ".remaining-character-count" do
160
+ expect(page).to have_content("1800 characters left") # Normal
161
+ end
162
+ within ".remaining-character-count-sr" do
163
+ expect(page).to have_content("1800 characters left") # Screen reader
164
+ end
165
+
166
+ # After continuing typing after the announcement, the screen reader
167
+ # characters should stay the same (announced on the next 10%
168
+ # interval).
169
+ field.native.send_keys "b"
170
+ within ".remaining-character-count" do
171
+ expect(page).to have_content("1799 characters left") # Normal
172
+ end
173
+ within ".remaining-character-count-sr" do
174
+ expect(page).to have_content("1800 characters left") # Screen reader
175
+ end
176
+
177
+ # When text is removed at the interval, the screen reader should
178
+ # update back to the previous interval.
179
+ field.native.send_keys [:backspace, :backspace, :backspace, :backspace]
180
+ within ".remaining-character-count" do
181
+ expect(page).to have_content("1803 characters left") # Normal
182
+ end
183
+ within ".remaining-character-count-sr" do
184
+ expect(page).to have_content("1800 characters left") # Screen reader
185
+ end
186
+
187
+ # After continuing typing after the removal of characters, we should
188
+ # stay in the "latest announcement" not to confuse the user as
189
+ # - "1800 characters left" (actual 1803)
190
+ # - Type in one character
191
+ # - "1900 characters left" (actual 1802)
192
+ field.native.send_keys "b"
193
+ within ".remaining-character-count" do
194
+ expect(page).to have_content("1802 characters left") # Normal
195
+ end
196
+ within ".remaining-character-count-sr" do
197
+ expect(page).to have_content("1800 characters left") # Screen reader
198
+ end
199
+
200
+ # After the input is blurred, the screen reader character counter
201
+ # should show the actual amount of characters left.
202
+ page.execute_script("document.getElementById('#{field_id}').blur()")
203
+ within ".remaining-character-count" do
204
+ expect(page).to have_content("1802 characters left") # Normal
205
+ end
206
+ within ".remaining-character-count-sr" do
207
+ expect(page).to have_content("1802 characters left") # Screen reader
208
+ end
209
+ end
210
+ end
211
+
212
+ context "when reaching the announce after every threshold" do
213
+ it "updates the numbers of characters left correctly for screen reader" do
214
+ within ".add-comment form" do
215
+ # Test that when reaching the "announce after every" threshold, the
216
+ # characters are announced after every keystroke.
217
+ fill_in field_id, with: "a" * 1989
218
+ within ".remaining-character-count" do
219
+ expect(page).to have_content("11 characters left") # Normal
220
+ end
221
+ within ".remaining-character-count-sr" do
222
+ expect(page).to have_content("200 characters left") # Screen reader
223
+ end
224
+
225
+ (2..10).reverse_each do |remaining|
226
+ field.native.send_keys "b"
227
+ within ".remaining-character-count-sr" do
228
+ expect(page).to have_content("#{remaining} characters left")
229
+ end
230
+ end
231
+
232
+ field.native.send_keys "b"
233
+ within ".remaining-character-count-sr" do
234
+ expect(page).to have_content("1 character left")
235
+ end
236
+
237
+ field.native.send_keys "c"
238
+ within ".remaining-character-count-sr" do
239
+ expect(page).to have_content("0 characters left")
240
+ end
241
+
242
+ # Test that the SR counter will stick at the last announced
243
+ # threshold if the next threshold is not hit and text is removed.
244
+ # This prevents weird announcements such as:
245
+ # - 0 characters left
246
+ # - Remove 10 characters
247
+ # - 10 characters left
248
+ # - Remove 1 character
249
+ # - 200 characters left
250
+ page.execute_script("document.getElementById('#{field_id}').setSelectionRange(1850, 2000)")
251
+ field.native.send_keys [:backspace]
252
+ within ".remaining-character-count" do
253
+ expect(page).to have_content("150 characters left") # Normal
254
+ end
255
+ within ".remaining-character-count-sr" do
256
+ expect(page).to have_content("0 characters left") # Screen reader
257
+ end
258
+
259
+ field.native.send_keys "d"
260
+ within ".remaining-character-count-sr" do
261
+ expect(page).to have_content("0 characters left")
262
+ end
263
+ end
264
+ end
265
+ end
266
+
267
+ context "when deleting text the announce after every threshold" do
268
+ it "updates the numbers of characters left correctly for screen reader" do
269
+ within ".add-comment form" do
270
+ fill_in field_id, with: "a" * 2000
271
+ within ".remaining-character-count" do
272
+ expect(page).to have_content("0 characters left") # Normal
273
+ end
274
+ within ".remaining-character-count-sr" do
275
+ expect(page).to have_content("0 characters left") # Screen reader
276
+ end
277
+
278
+ # Test that the SR counter updates correctly after hitting the
279
+ # next threshold.
280
+ page.execute_script("document.getElementById('#{field_id}').setSelectionRange(1800, 2000)")
281
+ field.native.send_keys [:backspace]
282
+ within ".remaining-character-count" do
283
+ expect(page).to have_content("200 characters left") # Normal
284
+ end
285
+ within ".remaining-character-count-sr" do
286
+ expect(page).to have_content("200 characters left") # Screen reader
287
+ end
288
+
289
+ # The SR counter should stay at the correct boundary.
290
+ field.native.send_keys [:backspace, :backspace]
291
+ within ".remaining-character-count" do
292
+ expect(page).to have_content("202 characters left") # Normal
293
+ end
294
+ within ".remaining-character-count-sr" do
295
+ expect(page).to have_content("200 characters left") # Screen reader
296
+ end
297
+
298
+ # It stays at the correct boundary when starting to type again.
299
+ field.native.send_keys "b"
300
+ within ".remaining-character-count" do
301
+ expect(page).to have_content("201 characters left") # Normal
302
+ end
303
+ within ".remaining-character-count-sr" do
304
+ expect(page).to have_content("200 characters left") # Screen reader
305
+ end
306
+
307
+ field.native.send_keys "c"
308
+ within ".remaining-character-count" do
309
+ expect(page).to have_content("200 characters left") # Normal
310
+ end
311
+ within ".remaining-character-count-sr" do
312
+ expect(page).to have_content("200 characters left") # Screen reader
313
+ end
314
+
315
+ field.native.send_keys "d"
316
+ within ".remaining-character-count" do
317
+ expect(page).to have_content("199 characters left") # Normal
318
+ end
319
+ within ".remaining-character-count-sr" do
320
+ expect(page).to have_content("200 characters left") # Screen reader
321
+ end
322
+ end
323
+ end
324
+ end
325
+ end
326
+
124
327
  context "when component is present and has a default comments length params" do
125
328
  it "displays the numbers of characters left" do
126
329
  if component.present?
@@ -9,7 +9,7 @@ shared_examples "localised email" do
9
9
  let(:locale) { "ca" }
10
10
 
11
11
  it "uses the user's locale" do
12
- expect(mail.subject).to eq(subject)
12
+ expect(mail.subject).to eq(mail_subject)
13
13
  expect(mail.body.encoded).to match(body)
14
14
  end
15
15
  end
@@ -15,7 +15,7 @@ shared_examples "email with logo" do
15
15
 
16
16
  it "includes organization logo with full link" do
17
17
  expect(mail.body).to include("alt=\"#{organization.name}\"")
18
- expect(mail.body).to match(%r{https{0,1}://#{organization.host}#{logo_path}})
18
+ expect(mail.body).to match(%r{https{0,1}://#{organization.host}:#{Capybara.server_port}#{logo_path}})
19
19
  end
20
20
  end
21
21
  end
@@ -24,7 +24,7 @@ shared_context "with frontend map builder" do
24
24
  end
25
25
  end
26
26
  let(:organization) { create(:organization) }
27
- let(:template) { template_class.new(ActionView::LookupContext.new(nil)) }
27
+ let(:template) { template_class.new(ActionView::LookupContext.new(ActionController::Base.view_paths), {}, []) }
28
28
  let(:options) { {} }
29
29
  let(:js_options) { options.transform_keys { |k| k.to_s.camelize(:lower) }.to_h }
30
30
 
@@ -103,6 +103,7 @@ shared_context "with frontend map elements" do
103
103
  final_html = html_document
104
104
  Rails.application.routes.draw do
105
105
  get "test_dynamic_map", to: ->(_) { [200, {}, [final_html]] }
106
+ get "offline", to: ->(_) { [200, {}, [""]] }
106
107
  end
107
108
 
108
109
  visit "/test_dynamic_map"
@@ -180,7 +181,6 @@ shared_examples "a record with front-end geocoding address field" do |geocoded_m
180
181
  it "calls the front-end geocoder when an address is written", :slow do
181
182
  within view_options[:within_selector] do
182
183
  fill_in_geocoding view_options[:address_field], with: geocoded_address_value
183
- find(".tribute-container ul#results li", match: :first).click
184
184
  find("*[type=submit]").click
185
185
  end
186
186
 
@@ -15,9 +15,7 @@ shared_examples_for "preview component with share_token" do
15
15
 
16
16
  it "does not allow visiting component" do
17
17
  expect(page).to have_content "You are not authorized"
18
- # rubocop:disable Capybara/CurrentPathExpectation
19
18
  expect(page.current_path).not_to match main_component_path(component)
20
- # rubocop:enable Capybara/CurrentPathExpectation
21
19
  end
22
20
  end
23
21
 
@@ -34,9 +32,7 @@ shared_examples_for "preview component with share_token" do
34
32
  context "when a valid share_token is provided" do
35
33
  it "allows visiting component" do
36
34
  expect(page).not_to have_content "You are not authorized"
37
- # rubocop:disable Capybara/CurrentPathExpectation
38
35
  expect(page.current_path).to match main_component_path(component)
39
- # rubocop:enable Capybara/CurrentPathExpectation
40
36
  end
41
37
  end
42
38
 
@@ -45,9 +41,7 @@ shared_examples_for "preview component with share_token" do
45
41
 
46
42
  it "does not allow visiting component" do
47
43
  expect(page).to have_content "You are not authorized"
48
- # rubocop:disable Capybara/CurrentPathExpectation
49
44
  expect(page.current_path).not_to match main_component_path(component)
50
- # rubocop:enable Capybara/CurrentPathExpectation
51
45
  end
52
46
  end
53
47
  end
@@ -3,19 +3,18 @@
3
3
  require "spec_helper"
4
4
 
5
5
  shared_examples_for "a resource search" do |factory_name|
6
- context "when no component is passed" do
7
- let(:params) { default_params.merge(component: nil) }
8
-
9
- it "raises an error" do
10
- expect { subject }.to raise_error(StandardError, "Missing component")
6
+ describe "component_id" do
7
+ before do
8
+ get(
9
+ request_path,
10
+ headers: { "HOST" => component.organization.host }
11
+ )
11
12
  end
12
- end
13
13
 
14
- describe "component_id" do
15
14
  it "only returns resources from the given component" do
16
15
  external_resource = create(factory_name)
17
16
 
18
- expect(subject).not_to include(external_resource)
17
+ expect(subject).not_to have_escaped_html(translated(external_resource.try(:title) || external_resource.try(:name)))
19
18
  end
20
19
  end
21
20
  end
@@ -28,7 +27,7 @@ shared_examples_for "a resource search with scopes" do |factory_name|
28
27
  end
29
28
 
30
29
  describe "scope_id filter" do
31
- let(:params) { default_params.merge(scope_id: scope_ids) }
30
+ let(:filter_params) { { with_any_scope: scope_ids } }
32
31
 
33
32
  let(:scope1) { create :scope, organization: component.organization }
34
33
  let(:scope2) { create :scope, organization: component.organization }
@@ -38,11 +37,21 @@ shared_examples_for "a resource search with scopes" do |factory_name|
38
37
  let!(:resource2) { create(factory_name, { component: component, scope: scope2 }.merge(factory_params)) }
39
38
  let!(:resource3) { create(factory_name, { component: component, scope: subscope1 }.merge(factory_params)) }
40
39
 
40
+ before do
41
+ get(
42
+ request_path,
43
+ params: { filter: filter_params },
44
+ headers: { "HOST" => component.organization.host }
45
+ )
46
+ end
47
+
41
48
  context "when a parent scope id is being sent" do
42
49
  let(:scope_ids) { [scope1.id] }
43
50
 
44
51
  it "filters resources by scope" do
45
- expect(subject).to match_array [resource, resource3]
52
+ expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
53
+ expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
54
+ expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
46
55
  end
47
56
  end
48
57
 
@@ -50,7 +59,9 @@ shared_examples_for "a resource search with scopes" do |factory_name|
50
59
  let(:scope_ids) { [subscope1.id] }
51
60
 
52
61
  it "filters resources by scope" do
53
- expect(subject).to eq [resource3]
62
+ expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
63
+ expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
64
+ expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
54
65
  end
55
66
  end
56
67
 
@@ -58,7 +69,9 @@ shared_examples_for "a resource search with scopes" do |factory_name|
58
69
  let(:scope_ids) { [scope2.id, scope1.id] }
59
70
 
60
71
  it "filters resources by scope" do
61
- expect(subject).to match_array [resource, resource2, resource3]
72
+ expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
73
+ expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
74
+ expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
62
75
  end
63
76
  end
64
77
 
@@ -66,8 +79,19 @@ shared_examples_for "a resource search with scopes" do |factory_name|
66
79
  let!(:resource_without_scope) { create(factory_name, { component: component, scope: nil }.merge(factory_params)) }
67
80
  let(:scope_ids) { ["global"] }
68
81
 
82
+ before do
83
+ get(
84
+ request_path,
85
+ params: { filter: filter_params },
86
+ headers: { "HOST" => component.organization.host }
87
+ )
88
+ end
89
+
69
90
  it "returns resources without a scope" do
70
- expect(subject).to match_array [resource_without_scope]
91
+ expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
92
+ expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
93
+ expect(subject).not_to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
94
+ expect(subject).to have_escaped_html(translated(resource_without_scope.try(:title) || resource_without_scope.try(:name)))
71
95
  end
72
96
  end
73
97
 
@@ -75,16 +99,34 @@ shared_examples_for "a resource search with scopes" do |factory_name|
75
99
  let!(:resource_without_scope) { create(factory_name, { component: component, scope: nil }.merge(factory_params)) }
76
100
  let(:scope_ids) { ["global", scope2.id, scope1.id] }
77
101
 
102
+ before do
103
+ get(
104
+ request_path,
105
+ params: { filter: filter_params },
106
+ headers: { "HOST" => component.organization.host }
107
+ )
108
+ end
109
+
78
110
  it "returns resources without a scope and with selected scopes" do
79
- expect(subject).to match_array [resource_without_scope, resource, resource2, resource3]
111
+ expect(subject).to have_escaped_html(translated(resource_without_scope.try(:title) || resource_without_scope.try(:name)))
112
+ expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
113
+ expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
114
+ expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
80
115
  end
81
116
  end
82
117
  end
83
118
  end
84
119
 
85
- shared_examples_for "a resource search with categories" do |factory_name|
86
- let(:participatory_process) { component.participatory_space }
87
- let(:params) { default_params.merge(category_id: category_ids) }
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
88
130
  let(:factory_params) do
89
131
  resource_params
90
132
  rescue StandardError
@@ -92,19 +134,30 @@ shared_examples_for "a resource search with categories" do |factory_name|
92
134
  end
93
135
 
94
136
  describe "results" do
95
- let(:category1) { create :category, participatory_space: participatory_process }
96
- let(:category2) { create :category, participatory_space: participatory_process }
97
- let(:child_category) { create :category, participatory_space: participatory_process, parent: category2 }
137
+ let(:category1) { create :category, participatory_space: participatory_space }
138
+ let(:category2) { create :category, participatory_space: participatory_space }
139
+ let(:child_category) { create :category, participatory_space: participatory_space, parent: category2 }
98
140
  let!(:resource) { create(factory_name, { component: component }.merge(factory_params)) }
99
141
  let!(:resource2) { create(factory_name, { component: component, category: category1 }.merge(factory_params)) }
100
142
  let!(:resource3) { create(factory_name, { component: component, category: category2 }.merge(factory_params)) }
101
143
  let!(:resource4) { create(factory_name, { component: component, category: child_category }.merge(factory_params)) }
102
144
 
145
+ before do
146
+ get(
147
+ request_path,
148
+ params: { filter: filter_params },
149
+ headers: { "HOST" => component.organization.host }
150
+ )
151
+ end
152
+
103
153
  context "when no category filter is present" do
104
154
  let(:category_ids) { nil }
105
155
 
106
156
  it "includes all resources" do
107
- expect(subject).to match_array [resource, resource2, resource3, resource4]
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)))
108
161
  end
109
162
  end
110
163
 
@@ -112,7 +165,10 @@ shared_examples_for "a resource search with categories" do |factory_name|
112
165
  let(:category_ids) { [category2.id] }
113
166
 
114
167
  it "includes only resources for that category and its children" do
115
- expect(subject).to match_array [resource3, resource4]
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)))
116
172
  end
117
173
  end
118
174
 
@@ -120,7 +176,10 @@ shared_examples_for "a resource search with categories" do |factory_name|
120
176
  let(:category_ids) { [child_category.id] }
121
177
 
122
178
  it "includes only resources for that category" do
123
- expect(subject).to eq [resource4]
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)))
124
183
  end
125
184
  end
126
185
 
@@ -128,15 +187,23 @@ shared_examples_for "a resource search with categories" do |factory_name|
128
187
  let(:category_ids) { ["without"] }
129
188
 
130
189
  it "returns resources without a category" do
131
- expect(subject).to eq [resource]
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)))
132
194
  end
133
195
  end
134
196
 
135
- context "when `without` and some category id is being sent" do
136
- let(:category_ids) { ["without", category1.id] }
197
+ if category_mode == :multi
198
+ context "when `without` and some category id is being sent" do
199
+ let(:category_ids) { ["without", category1.id] }
137
200
 
138
- it "returns resources without a category and with the selected category" do
139
- expect(subject).to match_array [resource, resource2]
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
140
207
  end
141
208
  end
142
209
  end
@@ -148,32 +215,42 @@ shared_examples_for "a resource search with origin" do |factory_name|
148
215
  rescue StandardError
149
216
  {}
150
217
  end
151
- let(:params) { default_params.merge(origin: origins) }
218
+ let(:filter_params) { { with_any_origin: origins } }
152
219
 
153
220
  describe "results" do
154
221
  let!(:official_resource) { create(factory_name, :official, { component: component }.merge(factory_params)) }
155
222
  let!(:user_group_resource) { create(factory_name, :user_group_author, { component: component }.merge(factory_params)) }
156
- let!(:citizen_resource) { create(factory_name, :citizen_author, { component: component }.merge(factory_params)) }
223
+ let!(:participant_resource) { create(factory_name, :participant_author, { component: component }.merge(factory_params)) }
157
224
 
158
225
  if FactoryBot.factory_by_name(factory_name).defined_traits.map(&:name).include?(:meeting_resource)
159
226
  let!(:meeting_resource) { create(factory_name, :official_meeting, { component: component }.merge(factory_params)) }
160
227
  end
161
228
 
229
+ before do
230
+ get(
231
+ request_path,
232
+ params: { filter: filter_params },
233
+ headers: { "HOST" => component.organization.host }
234
+ )
235
+ end
236
+
162
237
  context "when filtering official resources" do
163
238
  let(:origins) { %w(official) }
164
239
 
165
240
  it "returns only official resources" do
166
- expect(subject.size).to eq(1)
167
- expect(subject).to include(official_resource)
241
+ expect(subject).to have_escaped_html(translated(official_resource.try(:title) || official_resource.try(:name)))
242
+ expect(subject).not_to have_escaped_html(translated(participant_resource.try(:title) || participant_resource.try(:name)))
243
+ expect(subject).not_to have_escaped_html(translated(user_group_resource.try(:title) || user_group_resource.try(:name)))
168
244
  end
169
245
  end
170
246
 
171
- context "when filtering citizen resources" do
172
- let(:origins) { %w(citizens) }
247
+ context "when filtering participants resources" do
248
+ let(:origins) { %w(participants) }
173
249
 
174
250
  it "returns only citizen resources" do
175
- expect(subject.size).to eq(1)
176
- expect(subject).to include(citizen_resource)
251
+ expect(subject).not_to have_escaped_html(translated(official_resource.try(:title) || official_resource.try(:name)))
252
+ expect(subject).to have_escaped_html(translated(participant_resource.try(:title) || participant_resource.try(:name)))
253
+ expect(subject).not_to have_escaped_html(translated(user_group_resource.try(:title) || user_group_resource.try(:name)))
177
254
  end
178
255
  end
179
256
 
@@ -181,8 +258,9 @@ shared_examples_for "a resource search with origin" do |factory_name|
181
258
  let(:origins) { %w(user_group) }
182
259
 
183
260
  it "returns only user groups resources" do
184
- expect(subject.size).to eq(1)
185
- expect(subject).to include(user_group_resource)
261
+ expect(subject).not_to have_escaped_html(translated(official_resource.try(:title) || official_resource.try(:name)))
262
+ expect(subject).not_to have_escaped_html(translated(participant_resource.try(:title) || participant_resource.try(:name)))
263
+ expect(subject).to have_escaped_html(translated(user_group_resource.try(:title) || user_group_resource.try(:name)))
186
264
  end
187
265
  end
188
266
 
@@ -191,8 +269,10 @@ shared_examples_for "a resource search with origin" do |factory_name|
191
269
  let(:origins) { %w(meeting) }
192
270
 
193
271
  it "returns only meeting resources" do
194
- expect(subject.size).to eq(1)
195
- expect(subject).to include(meeting_resource)
272
+ expect(subject).not_to have_escaped_html(translated(official_resource.try(:title) || official_resource.try(:name)))
273
+ expect(subject).not_to have_escaped_html(translated(participant_resource.try(:title) || participant_resource.try(:name)))
274
+ expect(subject).not_to have_escaped_html(translated(user_group_resource.try(:title) || user_group_resource.try(:name)))
275
+ expect(subject).to have_escaped_html(translated(meeting_resource.try(:title) || meeting_resource.try(:name)))
196
276
  end
197
277
  end
198
278
  end
@@ -8,10 +8,4 @@ shared_examples_for "resourceable" do
8
8
  expect(subject.resource_title).to be_present
9
9
  end
10
10
  end
11
-
12
- describe "resource_description" do
13
- it "is defined" do
14
- expect(subject.resource_title).to be_present
15
- end
16
- end
17
11
  end
@@ -83,7 +83,7 @@ shared_examples "global search of participatory spaces" do
83
83
  describe "Search" do
84
84
  # trick to force creating participatory_space2 declared in users of this shared_examples
85
85
  let!(:spaces) { [participatory_space, participatory_space2] }
86
- let(:description_2) do
86
+ let(:description2) do
87
87
  msg = "Chewie, I'll be waiting for your signal. Take care, you two. May the Force be with you. Ow!"
88
88
  { ca: "CA:#{msg}", en: "EN:#{msg}", es: "ES:#{msg}" }
89
89
  end
@@ -6,7 +6,7 @@ RSpec.shared_context "when a resource is ready for global search" do
6
6
  let!(:scope1) { create :scope, organization: organization }
7
7
 
8
8
  let(:test_locales) { [:ca, :en, :es] }
9
- let(:description_1) do
9
+ let(:description1) do
10
10
  Decidim::Faker::Localized.prefixed("Poemes als terrats de l'Empordà, Ow!", test_locales)
11
11
  end
12
12
  end
@@ -6,11 +6,11 @@ shared_context "with resources to be endorsed or not" do
6
6
  include_context "with a component"
7
7
 
8
8
  # Should be overriden and create one main resource
9
- let!(:resource) {}
9
+ let!(:resource) { nil }
10
10
  # the name of the resource to be clicked from the component view
11
- let(:resource_name) {}
11
+ let(:resource_name) { nil }
12
12
  # Should be overriden and create 3 extra resources in the current component
13
- let!(:resources) {}
13
+ let!(:resources) { nil }
14
14
  end
15
15
 
16
16
  shared_examples "Endorse resource system specs" do
@@ -56,7 +56,7 @@ shared_examples_for "a translated event" do
56
56
  end
57
57
 
58
58
  context "when translation is not available" do
59
- let(:body) { { "en": en_body } }
59
+ let(:body) { { en: en_body } }
60
60
 
61
61
  it "does perform translation" do
62
62
  expect(subject.perform_translation?).to eq(translatable)
@@ -104,7 +104,7 @@ shared_examples_for "a translated event" do
104
104
  end
105
105
 
106
106
  context "when translation is not available" do
107
- let(:body) { { "en": en_body } }
107
+ let(:body) { { en: en_body } }
108
108
 
109
109
  it "does perform translation" do
110
110
  expect(subject.perform_translation?).to eq(translatable)
@@ -4,7 +4,7 @@ module Decidim
4
4
  # This holds the decidim-core version.
5
5
  module Core
6
6
  def self.version
7
- "0.26.2"
7
+ "0.27.0.rc1"
8
8
  end
9
9
  end
10
10
  end