decidim-core 0.22.0 → 0.23.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of decidim-core might be problematic. Click here for more details.

Files changed (334) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/decidim_core_manifest.js +5 -0
  3. data/app/assets/javascripts/decidim.js.es6 +2 -0
  4. data/app/assets/javascripts/decidim/ajax_modals.js.es6 +3 -3
  5. data/app/assets/javascripts/decidim/confirm.js.es6 +3 -2
  6. data/app/assets/javascripts/decidim/core/bundle.js +1 -1
  7. data/app/assets/javascripts/decidim/core/bundle.js.map +1 -1
  8. data/app/assets/javascripts/decidim/diff_mode_dropdown.js.es6 +18 -4
  9. data/app/assets/javascripts/decidim/editor.js.es6 +4 -4
  10. data/app/assets/javascripts/decidim/geocoding.js.es6 +60 -0
  11. data/app/assets/javascripts/decidim/geocoding/attach_input.js.es6 +106 -0
  12. data/app/assets/javascripts/decidim/geocoding/format_address.js.es6 +29 -0
  13. data/app/assets/javascripts/decidim/geocoding/provider/here.js.es6 +107 -0
  14. data/app/assets/javascripts/decidim/geocoding/provider/photon.js.es6 +77 -0
  15. data/app/assets/javascripts/decidim/map.js.es6 +34 -124
  16. data/app/assets/javascripts/decidim/map/controller.js.es6 +92 -0
  17. data/app/assets/javascripts/decidim/map/controller/markers.js.es6 +65 -0
  18. data/app/assets/javascripts/decidim/map/controller/static.es6 +48 -0
  19. data/app/assets/javascripts/decidim/map/factory.js.es6 +51 -0
  20. data/app/assets/javascripts/decidim/map/icon.js.es6 +31 -0
  21. data/app/assets/javascripts/decidim/map/legacy.js.es6 +87 -0
  22. data/app/assets/javascripts/decidim/map/provider/default.js.es6 +22 -0
  23. data/app/assets/javascripts/decidim/map/provider/here.js.es6 +22 -0
  24. data/app/assets/javascripts/decidim/security/selfxss_warning.js.es6 +19 -0
  25. data/app/assets/stylesheets/decidim/_decidim.scss +2 -0
  26. data/app/assets/stylesheets/decidim/layouts/_home.scss +5 -0
  27. data/app/assets/stylesheets/decidim/modules/_cards.scss +15 -0
  28. data/app/assets/stylesheets/decidim/modules/_forms.scss +14 -0
  29. data/app/assets/stylesheets/decidim/modules/_layout.scss +11 -3
  30. data/app/assets/stylesheets/decidim/modules/_map.scss +35 -0
  31. data/app/assets/stylesheets/decidim/modules/_progress-bar.scss +4 -0
  32. data/app/assets/stylesheets/decidim/modules/_reveal.scss +5 -0
  33. data/app/assets/stylesheets/decidim/modules/_status-labels.scss +2 -1
  34. data/app/cells/decidim/author/flag.erb +1 -1
  35. data/app/cells/decidim/author/profile_inline.erb +2 -2
  36. data/app/cells/decidim/author_cell.rb +5 -2
  37. data/app/cells/decidim/card_cell.rb +21 -7
  38. data/app/cells/decidim/card_m/show.erb +1 -1
  39. data/app/cells/decidim/card_m_cell.rb +6 -4
  40. data/app/cells/decidim/collapsible_authors_cell.rb +1 -1
  41. data/app/cells/decidim/content_blocks/sub_hero/show.erb +3 -1
  42. data/app/cells/decidim/diff/diff_mode_html.erb +5 -5
  43. data/app/cells/decidim/follow_button/show.erb +6 -6
  44. data/app/cells/decidim/follow_button_cell.rb +8 -0
  45. data/app/cells/decidim/progress_bar/show.erb +11 -4
  46. data/app/cells/decidim/progress_bar_cell.rb +20 -1
  47. data/app/cells/decidim/tos_page/announcement.erb +0 -1
  48. data/app/cells/decidim/tos_page/form.erb +17 -0
  49. data/app/cells/decidim/translation_bar/show.erb +6 -0
  50. data/app/cells/decidim/translation_bar_cell.rb +52 -0
  51. data/app/cells/decidim/version_cell.rb +1 -1
  52. data/app/cells/decidim/versions_list_cell.rb +1 -1
  53. data/app/commands/decidim/amendable/accept.rb +9 -3
  54. data/app/commands/decidim/amendable/create_draft.rb +2 -0
  55. data/app/commands/decidim/amendable/update_draft.rb +2 -0
  56. data/app/commands/decidim/attachment_methods.rb +20 -5
  57. data/app/commands/decidim/destroy_account.rb +1 -0
  58. data/app/commands/decidim/gallery_methods.rb +16 -9
  59. data/app/commands/decidim/messaging/reply_to_conversation.rb +1 -1
  60. data/app/commands/decidim/multiple_attachments_methods.rb +56 -0
  61. data/app/controllers/concerns/decidim/devise_controllers.rb +1 -0
  62. data/app/controllers/concerns/decidim/filter_resource.rb +24 -6
  63. data/app/controllers/concerns/decidim/flaggable.rb +20 -0
  64. data/app/controllers/concerns/decidim/force_authentication.rb +1 -0
  65. data/app/controllers/concerns/decidim/impersonate_users.rb +1 -1
  66. data/app/controllers/concerns/decidim/needs_snippets.rb +20 -0
  67. data/app/controllers/concerns/decidim/paginable.rb +5 -1
  68. data/app/controllers/concerns/decidim/withdrawable.rb +20 -0
  69. data/app/controllers/decidim/application_controller.rb +16 -0
  70. data/app/controllers/decidim/components/base_controller.rb +6 -1
  71. data/app/controllers/decidim/cookie_policy_controller.rb +6 -3
  72. data/app/controllers/decidim/messaging/conversations_controller.rb +5 -2
  73. data/app/forms/decidim/account_form.rb +5 -1
  74. data/app/forms/decidim/amendable/create_form.rb +1 -1
  75. data/app/forms/decidim/amendable/form.rb +44 -3
  76. data/app/forms/decidim/attachment_form.rb +6 -1
  77. data/app/forms/decidim/user_group_form.rb +5 -1
  78. data/app/helpers/decidim/cells_helper.rb +3 -15
  79. data/app/helpers/decidim/check_boxes_tree_helper.rb +21 -12
  80. data/app/helpers/decidim/cookies_helper.rb +1 -1
  81. data/app/helpers/decidim/decidim_form_helper.rb +1 -1
  82. data/app/helpers/decidim/filter_params_helper.rb +30 -0
  83. data/app/helpers/decidim/map_helper.rb +86 -23
  84. data/app/helpers/decidim/orders_helper.rb +6 -1
  85. data/app/helpers/decidim/paginate_helper.rb +1 -8
  86. data/app/helpers/decidim/sanitize_helper.rb +8 -0
  87. data/app/helpers/decidim/scopes_helper.rb +5 -5
  88. data/app/helpers/decidim/translations_helper.rb +7 -1
  89. data/app/jobs/decidim/data_portability_export_job.rb +3 -3
  90. data/app/jobs/decidim/machine_translation_fields_job.rb +30 -0
  91. data/app/jobs/decidim/machine_translation_resource_job.rb +113 -0
  92. data/app/jobs/decidim/machine_translation_save_job.rb +33 -0
  93. data/app/jobs/decidim/open_data_job.rb +1 -1
  94. data/app/mailers/decidim/application_mailer.rb +1 -0
  95. data/app/mailers/decidim/reported_mailer.rb +8 -1
  96. data/app/models/decidim/action_log.rb +1 -1
  97. data/app/models/decidim/area.rb +3 -0
  98. data/app/models/decidim/area_type.rb +4 -0
  99. data/app/models/decidim/attachment.rb +30 -2
  100. data/app/models/decidim/attachment_collection.rb +3 -0
  101. data/app/models/decidim/authorization.rb +3 -0
  102. data/app/models/decidim/category.rb +4 -0
  103. data/app/models/decidim/component.rb +7 -0
  104. data/app/models/decidim/content_block.rb +11 -1
  105. data/app/models/decidim/contextual_help_section.rb +4 -0
  106. data/app/models/decidim/follow.rb +3 -1
  107. data/app/models/decidim/messaging/message.rb +1 -1
  108. data/app/models/decidim/moderation.rb +1 -1
  109. data/app/models/decidim/newsletter.rb +3 -0
  110. data/app/models/decidim/oauth_application.rb +2 -0
  111. data/app/models/decidim/organization.rb +54 -10
  112. data/app/models/decidim/scope.rb +4 -1
  113. data/app/models/decidim/scope_type.rb +3 -0
  114. data/app/models/decidim/share_token.rb +49 -0
  115. data/app/models/decidim/static_page.rb +4 -1
  116. data/app/models/decidim/static_page_topic.rb +3 -0
  117. data/app/models/decidim/user.rb +11 -3
  118. data/app/models/decidim/user_base_entity.rb +6 -2
  119. data/app/permissions/decidim/permissions.rb +9 -0
  120. data/app/presenters/decidim/admin_log/component_presenter.rb +2 -2
  121. data/app/presenters/decidim/admin_log/moderation_presenter.rb +2 -2
  122. data/app/presenters/decidim/admin_log/organization_presenter.rb +2 -2
  123. data/app/presenters/decidim/admin_log/user_presenter.rb +2 -2
  124. data/app/presenters/decidim/log/base_presenter.rb +10 -2
  125. data/app/presenters/decidim/log/value_types/default_presenter.rb +1 -1
  126. data/app/presenters/decidim/official_author_presenter.rb +36 -0
  127. data/app/presenters/decidim/resource_locator_presenter.rb +63 -12
  128. data/app/queries/decidim/similar_emendations.rb +4 -4
  129. data/app/scrubbers/decidim/newsletter_scrubber.rb +31 -0
  130. data/app/scrubbers/decidim/user_input_scrubber.rb +1 -1
  131. data/app/serializers/decidim/importers/participatory_space_components_importer.rb +1 -1
  132. data/app/services/decidim/base_diff_renderer.rb +17 -0
  133. data/app/services/decidim/open_data_exporter.rb +2 -0
  134. data/app/services/decidim/resource_search.rb +95 -6
  135. data/app/services/decidim/static_map_generator.rb +10 -26
  136. data/app/services/decidim/tokenizer.rb +38 -0
  137. data/app/services/decidim/traceability.rb +3 -0
  138. data/app/uploaders/decidim/application_uploader.rb +19 -1
  139. data/app/uploaders/decidim/attachment_uploader.rb +23 -17
  140. data/app/uploaders/decidim/banner_image_uploader.rb +1 -1
  141. data/app/uploaders/decidim/hero_image_uploader.rb +1 -1
  142. data/app/uploaders/decidim/homepage_image_uploader.rb +1 -1
  143. data/app/uploaders/decidim/image_uploader.rb +6 -2
  144. data/app/uploaders/decidim/oauth_application_logo_uploader.rb +1 -1
  145. data/app/uploaders/decidim/official_image_footer_uploader.rb +1 -1
  146. data/app/uploaders/decidim/official_image_header_uploader.rb +1 -1
  147. data/app/uploaders/decidim/organization_logo_uploader.rb +1 -1
  148. data/app/uploaders/decidim/record_image_uploader.rb +15 -0
  149. data/app/validators/etiquette_validator.rb +0 -7
  150. data/app/validators/geocoding_validator.rb +9 -4
  151. data/app/validators/passthru_validator.rb +111 -0
  152. data/app/validators/scope_belongs_to_component_validator.rb +16 -0
  153. data/app/validators/uploader_content_type_validator.rb +44 -0
  154. data/app/views/decidim/authorization_modals/_content.html.erb +2 -2
  155. data/app/views/decidim/devise/registrations/new.html.erb +3 -1
  156. data/app/views/decidim/devise/sessions/new.html.erb +3 -1
  157. data/app/views/decidim/messaging/conversations/_error_modal.html.erb +21 -0
  158. data/app/views/decidim/messaging/conversations/error.js.erb +10 -0
  159. data/app/views/decidim/newsletter_mailer/newsletter.html.erb +1 -1
  160. data/app/views/decidim/notification_mailer/event_received.html.erb +2 -2
  161. data/app/views/decidim/pages/_standalone.html.erb +1 -1
  162. data/app/views/decidim/pages/_tabbed.html.erb +1 -1
  163. data/app/views/decidim/reported_mailer/report.html.erb +49 -3
  164. data/app/views/decidim/scopes/_scopes_picker_input.html.erb +15 -14
  165. data/app/views/decidim/searches/_filters.html.erb +1 -0
  166. data/app/views/decidim/shared/_login_modal.html.erb +14 -3
  167. data/app/views/decidim/shared/_static_map.html.erb +1 -1
  168. data/app/views/layouts/decidim/_head.html.erb +2 -0
  169. data/app/views/layouts/decidim/_js_configuration.html.erb +7 -1
  170. data/config/locales/am-ET.yml +1 -0
  171. data/config/locales/ar.yml +3 -4
  172. data/config/locales/bg.yml +1508 -0
  173. data/config/locales/ca.yml +36 -9
  174. data/config/locales/cs.yml +54 -27
  175. data/config/locales/da.yml +1 -0
  176. data/config/locales/de.yml +156 -128
  177. data/config/locales/el.yml +0 -4
  178. data/config/locales/en.yml +30 -3
  179. data/config/locales/eo.yml +92 -0
  180. data/config/locales/es-MX.yml +29 -2
  181. data/config/locales/es-PY.yml +28 -1
  182. data/config/locales/es.yml +44 -17
  183. data/config/locales/et.yml +1 -0
  184. data/config/locales/eu.yml +9 -4
  185. data/config/locales/fi-plain.yml +28 -1
  186. data/config/locales/fi.yml +34 -7
  187. data/config/locales/fr-CA.yml +32 -4
  188. data/config/locales/fr.yml +65 -37
  189. data/config/locales/ga-IE.yml +0 -8
  190. data/config/locales/gl.yml +10 -5
  191. data/config/locales/hr.yml +1 -0
  192. data/config/locales/hu.yml +7 -5
  193. data/config/locales/id-ID.yml +3 -4
  194. data/config/locales/is-IS.yml +3 -9
  195. data/config/locales/is.yml +463 -0
  196. data/config/locales/it.yml +37 -9
  197. data/config/locales/ja-JP.yml +25 -16
  198. data/config/locales/ja.yml +1605 -0
  199. data/config/locales/ko-KR.yml +1 -0
  200. data/config/locales/ko.yml +1 -0
  201. data/config/locales/lt.yml +1 -0
  202. data/config/locales/{lv-LV.yml → lv.yml} +2 -5
  203. data/config/locales/mt.yml +1 -0
  204. data/config/locales/nl.yml +34 -12
  205. data/config/locales/no.yml +150 -8
  206. data/config/locales/om-ET.yml +1 -0
  207. data/config/locales/pl.yml +89 -72
  208. data/config/locales/pt-BR.yml +4 -5
  209. data/config/locales/pt.yml +10 -4
  210. data/config/locales/ro-RO.yml +10 -4
  211. data/config/locales/ru.yml +3 -10
  212. data/config/locales/si-LK.yml +1 -0
  213. data/config/locales/sk.yml +3 -5
  214. data/config/locales/sl.yml +8 -7
  215. data/config/locales/so-SO.yml +1 -0
  216. data/config/locales/sr-CS.yml +0 -9
  217. data/config/locales/sv.yml +19 -8
  218. data/config/locales/sw-KE.yml +1 -0
  219. data/config/locales/ti-ER.yml +1 -0
  220. data/config/locales/tr-TR.yml +588 -247
  221. data/config/locales/uk.yml +3 -11
  222. data/config/locales/vi-VN.yml +1 -0
  223. data/config/locales/vi.yml +1 -0
  224. data/config/locales/zh-CN.yml +1584 -0
  225. data/config/locales/zh-TW.yml +1 -0
  226. data/db/migrate/20200525184143_add_enable_machine_translation_to_decidim_organizations.rb +7 -0
  227. data/db/migrate/20200702073419_create_decidim_share_tokens.rb +16 -0
  228. data/db/migrate/20200707132401_add_comments_max_length_to_decidim_organization.rb +7 -0
  229. data/db/migrate/20200730142511_add_file_upload_settings_to_decidim_organizations.rb +36 -0
  230. data/db/migrate/20200806092109_add_machine_translation_display_priority_to_organizations.rb +17 -0
  231. data/db/migrate/20201004160335_remove_notifications_with_continuity_badge.rb +9 -0
  232. data/db/seeds.rb +12 -6
  233. data/lib/decidim/authorable.rb +22 -1
  234. data/lib/decidim/authorization_form_builder.rb +7 -0
  235. data/lib/decidim/coauthorable.rb +22 -0
  236. data/lib/decidim/component_manifest.rb +1 -1
  237. data/lib/decidim/content_processor.rb +52 -29
  238. data/lib/decidim/content_renderers/base_renderer.rb +1 -1
  239. data/lib/decidim/content_renderers/hashtag_renderer.rb +2 -0
  240. data/lib/decidim/content_renderers/link_renderer.rb +4 -1
  241. data/lib/decidim/content_renderers/user_group_renderer.rb +3 -1
  242. data/lib/decidim/content_renderers/user_renderer.rb +3 -1
  243. data/lib/decidim/core.rb +67 -12
  244. data/lib/decidim/core/engine.rb +65 -21
  245. data/lib/decidim/core/test.rb +8 -0
  246. data/lib/decidim/core/test/factories.rb +34 -8
  247. data/lib/decidim/core/test/shared_examples/admin_log_presenter_examples.rb +34 -0
  248. data/lib/decidim/core/test/shared_examples/amendable/accept_amendment_examples.rb +4 -4
  249. data/lib/decidim/core/test/shared_examples/amendable_proposals_interface_examples.rb +8 -8
  250. data/lib/decidim/core/test/shared_examples/comments_examples.rb +52 -1
  251. data/lib/decidim/core/test/shared_examples/counts_commentators_as_newsletter_participants.rb +31 -0
  252. data/lib/decidim/core/test/shared_examples/embed_resource_examples.rb +49 -0
  253. data/lib/decidim/core/test/shared_examples/follows_examples.rb +3 -3
  254. data/lib/decidim/core/test/shared_examples/manage_component_share_tokens.rb +83 -0
  255. data/lib/decidim/core/test/shared_examples/map_examples.rb +186 -0
  256. data/lib/decidim/core/test/shared_examples/preview_component_with_share_token_examples.rb +55 -0
  257. data/lib/decidim/core/test/shared_examples/resource_search_examples.rb +200 -0
  258. data/lib/decidim/core/test/shared_examples/scopable_resource_examples.rb +43 -0
  259. data/lib/decidim/core/test/shared_examples/scope_helper_examples.rb +12 -1
  260. data/lib/decidim/core/test/shared_examples/searchable_participatory_space_examples.rb +2 -2
  261. data/lib/decidim/core/test/shared_examples/searchable_results_examples.rb +15 -2
  262. data/lib/decidim/core/test/shared_examples/simple_event.rb +7 -0
  263. data/lib/decidim/core/test/shared_examples/system_endorse_resource_examples.rb +1 -0
  264. data/lib/decidim/core/test/shared_examples/traceable_interface_examples.rb +1 -1
  265. data/lib/decidim/core/test/shared_examples/uncommentable_component_examples.rb +1 -1
  266. data/lib/decidim/core/version.rb +1 -1
  267. data/lib/decidim/diffy_extension.rb +21 -0
  268. data/lib/decidim/events/base_event.rb +29 -11
  269. data/lib/decidim/exporters.rb +7 -0
  270. data/lib/decidim/exporters/csv.rb +15 -1
  271. data/lib/decidim/exporters/excel.rb +1 -1
  272. data/lib/decidim/exporters/export_manifest.rb +29 -0
  273. data/lib/decidim/exporters/pdf.rb +56 -0
  274. data/lib/decidim/file_validator_humanizer.rb +98 -0
  275. data/lib/decidim/form_builder.rb +68 -56
  276. data/lib/decidim/geocodable.rb +79 -0
  277. data/lib/decidim/has_attachments.rb +10 -0
  278. data/lib/decidim/has_private_users.rb +1 -1
  279. data/lib/decidim/has_upload_validations.rb +36 -0
  280. data/lib/decidim/map.rb +214 -0
  281. data/lib/decidim/map/autocomplete.rb +67 -0
  282. data/lib/decidim/map/dynamic_map.rb +89 -0
  283. data/lib/decidim/map/frontend.rb +97 -0
  284. data/lib/decidim/map/geocoding.rb +115 -0
  285. data/lib/decidim/map/provider.rb +12 -0
  286. data/lib/decidim/map/provider/autocomplete/here.rb +20 -0
  287. data/lib/decidim/map/provider/autocomplete/osm.rb +20 -0
  288. data/lib/decidim/map/provider/dynamic_map/here.rb +51 -0
  289. data/lib/decidim/map/provider/dynamic_map/osm.rb +13 -0
  290. data/lib/decidim/map/provider/geocoding/here.rb +58 -0
  291. data/lib/decidim/map/provider/geocoding/osm.rb +30 -0
  292. data/lib/decidim/map/provider/here.rb +21 -0
  293. data/lib/decidim/map/provider/osm.rb +22 -0
  294. data/lib/decidim/map/provider/static_map/here.rb +35 -0
  295. data/lib/decidim/map/provider/static_map/osm.rb +29 -0
  296. data/lib/decidim/map/static_map.rb +133 -0
  297. data/lib/decidim/map/utility.rb +38 -0
  298. data/lib/decidim/newsletter_participant.rb +2 -4
  299. data/lib/decidim/organization_settings.rb +267 -0
  300. data/lib/decidim/paddable.rb +11 -4
  301. data/lib/decidim/resource_manifest.rb +1 -1
  302. data/lib/decidim/scopable.rb +9 -6
  303. data/lib/decidim/scopable_component.rb +29 -1
  304. data/lib/decidim/scopable_participatory_space.rb +19 -0
  305. data/lib/decidim/scopable_resource.rb +21 -0
  306. data/lib/decidim/search_resource_fields_mapper.rb +17 -4
  307. data/lib/decidim/searchable.rb +6 -0
  308. data/lib/decidim/settings_manifest.rb +2 -1
  309. data/lib/decidim/shareable_with_token.rb +27 -0
  310. data/lib/decidim/snippets.rb +30 -0
  311. data/lib/decidim/translatable_attributes.rb +42 -4
  312. data/lib/decidim/translatable_resource.rb +78 -0
  313. data/lib/decidim/view_model.rb +1 -0
  314. data/lib/premailer/adapter/decidim.rb +33 -0
  315. data/lib/tasks/decidim_locales_tasks.rake +35 -0
  316. data/lib/tasks/decidim_tasks.rake +1 -0
  317. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.bg.js +14 -0
  318. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.da.js +14 -0
  319. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.eo.js +17 -0
  320. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.et.js +18 -0
  321. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.fr-CA.js +16 -0
  322. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.ga.js +15 -0
  323. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.hr.js +13 -0
  324. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.is.js +14 -0
  325. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.ja.js +16 -0
  326. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.lt.js +16 -0
  327. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.lv.js +17 -0
  328. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.mt.js +15 -0
  329. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.sl.js +14 -0
  330. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.sr.js +16 -0
  331. metadata +149 -30
  332. data/app/cells/decidim/tos_page/sticky_form.erb +0 -29
  333. data/app/helpers/decidim/multi_translation_helper.rb +0 -0
  334. data/lib/decidim/hashtaggable.rb +0 -24
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples_for "an embed resource" do |options|
4
+ if options.is_a?(Hash) && options[:skip_space_checks]
5
+ let(:organization) { resource.organization }
6
+
7
+ before do
8
+ switch_to_host(organization.host)
9
+ end
10
+ else
11
+ include_context "with a component"
12
+ end
13
+
14
+ context "when visiting the embed page for a resource" do
15
+ before do
16
+ visit resource_locator(resource).path
17
+ visit "#{current_path}/embed"
18
+ end
19
+
20
+ it "renders the page correctly" do
21
+ if resource.title.is_a?(Hash)
22
+ expect(page).to have_i18n_content(resource.title)
23
+ else
24
+ expect(page).to have_content(resource.title)
25
+ end
26
+
27
+ expect(page).to have_content(organization.name)
28
+ end
29
+
30
+ unless options.is_a?(Hash) && options[:skip_space_checks]
31
+ context "when the participatory_space is a process" do
32
+ it "shows the process name" do
33
+ expect(page).to have_i18n_content(participatory_process.title)
34
+ end
35
+ end
36
+
37
+ context "when the participatory_space is an assembly" do
38
+ let(:assembly) do
39
+ create(:assembly, organization: organization)
40
+ end
41
+ let(:participatory_space) { assembly }
42
+
43
+ it "shows the assembly name" do
44
+ expect(page).to have_i18n_content(assembly.title)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -10,7 +10,7 @@ shared_examples "follows" do
10
10
  context "when not following the followable" do
11
11
  context "when user clicks the Follow button" do
12
12
  it "makes the user follow the followable" do
13
- visit resource_locator(followable).path
13
+ visit followable_path
14
14
  expect do
15
15
  click_button "Follow"
16
16
  expect(page).to have_content "Stop following"
@@ -26,7 +26,7 @@ shared_examples "follows" do
26
26
 
27
27
  context "when user clicks the Follow button" do
28
28
  it "makes the user follow the followable" do
29
- visit resource_locator(followable).path
29
+ visit followable_path
30
30
  expect do
31
31
  click_button "Stop following"
32
32
  expect(page).to have_content "Follow"
@@ -42,7 +42,7 @@ shared_examples "follows" do
42
42
 
43
43
  context "when user clicks the Follow button" do
44
44
  it "makes the user follow the followable" do
45
- visit resource_locator(followable).path
45
+ visit followable_path
46
46
  expect do
47
47
  click_button "Already following #{translated(followable.participatory_space.title)}"
48
48
  expect(page).to have_content "Stop following"
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.shared_examples "manage component share tokens" do
4
+ let!(:components_path) { participatory_space_components_path(participatory_space) }
5
+
6
+ context "when visiting the components page for the participatory space" do
7
+ before do
8
+ visit components_path
9
+ end
10
+
11
+ it "has a share button that opens the share url for the component" do
12
+ share_window = window_opened_by { click_link "Share", wait: 2 }
13
+
14
+ within_window share_window do
15
+ expect(page).to have_current_path(component.share_tokens.reload.last.url)
16
+ end
17
+ end
18
+ end
19
+
20
+ context "when visiting the component configuration page" do
21
+ context "when there are tokens" do
22
+ let!(:share_tokens) { create_list(:share_token, 3, token_for: component, organization: component.organization) }
23
+ let!(:share_token) { share_tokens.last }
24
+
25
+ before do
26
+ visit components_path
27
+
28
+ within find("tr", text: component.name["en"]) do
29
+ click_link "Configure"
30
+ end
31
+ end
32
+
33
+ it "displays all tokens" do
34
+ within ".share_tokens" do
35
+ expect(page).to have_selector("tbody tr", count: 3)
36
+ end
37
+ end
38
+
39
+ it "displays relevant attributes for each token" do
40
+ share_tokens.each do |share_token|
41
+ within ".share_tokens tbody" do
42
+ expect(page).to have_content share_token.token
43
+ expect(page).to have_content share_token.user.name
44
+ end
45
+ end
46
+ end
47
+
48
+ it "has a share link for each token" do
49
+ urls = share_tokens.map(&:url).map { |url| url.split("?").first }
50
+ within ".share_tokens tbody tr:first-child" do
51
+ share_window = window_opened_by { click_link "Share" }
52
+
53
+ within_window share_window do
54
+ expect(urls).to include(page.current_path)
55
+ end
56
+ end
57
+ end
58
+
59
+ it "has a link to delete tokens" do
60
+ within ".share_tokens tbody tr:first-child" do
61
+ accept_confirm { click_link "Delete" }
62
+ end
63
+
64
+ expect(page).to have_admin_callout("successfully")
65
+ expect(page).to have_selector("tbody tr", count: 2)
66
+ end
67
+ end
68
+
69
+ context "when there are no tokens" do
70
+ before do
71
+ visit components_path
72
+
73
+ within find("tr", text: component.name["en"]) do
74
+ click_link "Configure"
75
+ end
76
+ end
77
+
78
+ it "displays empty message" do
79
+ expect(page).to have_content "There are no active tokens"
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_context "with map utility" do
4
+ let(:organization) { create(:organization) }
5
+ let(:locale) { "en" }
6
+ let(:config) { {} }
7
+
8
+ let(:utility_class) { described_class }
9
+ let(:utility) { utility_class.new(organization: organization, config: config, locale: locale) }
10
+ end
11
+
12
+ shared_context "with frontend map builder" do
13
+ subject { described_class.new(template, options) }
14
+
15
+ let(:template_class) do
16
+ Class.new(ActionView::Base) do
17
+ def protect_against_forgery?
18
+ false
19
+ end
20
+
21
+ def snippets
22
+ @snippets ||= Decidim::Snippets.new
23
+ end
24
+ end
25
+ end
26
+ let(:organization) { create(:organization) }
27
+ let(:template) { template_class.new }
28
+ let(:options) { {} }
29
+ let(:js_options) { options.map { |k, v| [k.to_s.camelize(:lower), v] }.to_h }
30
+
31
+ before do
32
+ allow(template).to receive(:current_organization).and_return(organization)
33
+ end
34
+ end
35
+
36
+ shared_context "with dynamic map builder" do
37
+ include_context "with frontend map builder"
38
+
39
+ let(:options) do
40
+ {
41
+ tile_layer: {
42
+ url: "https://tiles.example.org",
43
+ options: {
44
+ foo: "bar",
45
+ attribution: "Test Attribution"
46
+ }
47
+ }
48
+ }
49
+ end
50
+ end
51
+
52
+ shared_context "with map autocomplete builder" do
53
+ include_context "with frontend map builder"
54
+
55
+ let(:options) { { url: "https://photon.example.org/api/" } }
56
+ end
57
+
58
+ shared_context "with frontend map elements" do
59
+ let(:html_head) { "" }
60
+ let(:html_document) do
61
+ builder = subject
62
+ document_inner = html_body
63
+ head_extra = html_head
64
+ template.instance_eval do
65
+ <<~HTML.strip
66
+ <!doctype html>
67
+ <html lang="en">
68
+ <head>
69
+ <title>Map Test</title>
70
+ #{stylesheet_link_tag "application"}
71
+ #{javascript_include_tag "application"}
72
+ #{builder.stylesheet_snippets}
73
+ #{builder.javascript_snippets}
74
+ #{head_extra}
75
+ </head>
76
+ <body>
77
+ #{document_inner}
78
+ <script type="text/javascript">
79
+ // This is just to indicate to Capybara that the page has fully
80
+ // finished loading.
81
+ $(document).ready(function() {
82
+ setTimeout(function() {
83
+ $("body").append('<div id="ready_indicator">Document ready</div>');
84
+ }, 1000);
85
+ });
86
+ </script>
87
+ </body>
88
+ </html>
89
+ HTML
90
+ end
91
+ end
92
+ let(:html_body) { "" }
93
+
94
+ before do
95
+ # Create a temporary route to display the generated HTML in a correct site
96
+ # context.
97
+ final_html = html_document
98
+ Rails.application.routes.draw do
99
+ get "test_dynamic_map", to: ->(_) { [200, {}, [final_html]] }
100
+ end
101
+
102
+ visit "/test_dynamic_map"
103
+ end
104
+
105
+ after do
106
+ expect(page).to have_selector("#ready_indicator", text: "Document ready")
107
+
108
+ expect_no_js_errors
109
+
110
+ # Reset the routes back to original
111
+ Rails.application.reload_routes!
112
+ end
113
+ end
114
+
115
+ shared_examples "a page with dynamic map" do
116
+ include_context "with dynamic map builder"
117
+
118
+ include_context "with frontend map elements" do
119
+ let(:html_body) do
120
+ builder = subject
121
+ template.instance_eval do
122
+ builder.map_element(id: "map", class: "google-map") do
123
+ content_tag(:span, "", id: "map_inner")
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ it "displays the map" do
130
+ expect(page).to have_selector("#map.google-map", visible: :all)
131
+ expect(page).to have_selector("#map_inner", visible: :all)
132
+ end
133
+ end
134
+
135
+ shared_examples "a page with geocoding input" do
136
+ include_context "with map autocomplete builder"
137
+
138
+ include_context "with frontend map elements" do
139
+ let(:html_body) do
140
+ builder = subject
141
+ template.instance_eval do
142
+ builder.geocoding_field(:test, :address)
143
+ end
144
+ end
145
+ end
146
+
147
+ it "displays the geocoding field element" do
148
+ config = ERB::Util.html_escape(js_options.to_json)
149
+ expect(subject.geocoding_field(:test, :address)).to eq(
150
+ %(<input autocomplete="off" data-decidim-geocoding="#{config}" type="text" name="test[address]" id="test_address" />)
151
+ )
152
+ end
153
+ end
154
+
155
+ # Use this shared example to test that the front-end geocoded address field is
156
+ # working correctly. Fill in the other fields in the view in the before block so
157
+ # that the saving will proceed successfully.
158
+ shared_examples "a record with front-end geocoding address field" do |geocoded_model, view_options|
159
+ let(:geocoded_record) { nil }
160
+ let(:geocoded_address_value) { "Street2" }
161
+ let(:geocoded_address_coordinates) { [3.345, 4.456] }
162
+
163
+ it "calls the front-end geocoder when an address is written", :slow do
164
+ within view_options[:within_selector] do
165
+ fill_in_geocoding view_options[:address_field], with: geocoded_address_value
166
+ find(".tribute-container ul#results li", match: :first).click
167
+ find("*[type=submit]").click
168
+ end
169
+
170
+ # Check that the latitude and longitude are according to the front-end
171
+ # geocoder as one of the autocompleted addresses were selected. The back-end
172
+ # geocoding should be bypassed in this situation which is why these match
173
+ # what was returned by the front-end geocoding. These values are returned by
174
+ # the dummy test geocoding API defined at
175
+ # `decidim-dev/lib/decidim/dev/test/rspec_support/geocoder.rb`. Search for
176
+ # `:serves_geocoding_autocomplete`.
177
+ expect(page).to have_content("successfully")
178
+ final = if geocoded_record
179
+ geocoded_model.find(geocoded_record.id)
180
+ else
181
+ geocoded_model.last
182
+ end
183
+ expect(final.latitude).to eq(geocoded_address_coordinates[0])
184
+ expect(final.longitude).to eq(geocoded_address_coordinates[1])
185
+ end
186
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ shared_examples_for "preview component with share_token" do
6
+ context "when component is unpublished" do
7
+ before do
8
+ component.unpublish!
9
+ end
10
+
11
+ context "when no share_token is provided" do
12
+ before do
13
+ visit_component
14
+ end
15
+
16
+ it "does not allow visiting component" do
17
+ expect(page).to have_content "You are not authorized"
18
+ # rubocop:disable Capybara/CurrentPathExpectation
19
+ expect(page.current_path).not_to match main_component_path(component)
20
+ # rubocop:enable Capybara/CurrentPathExpectation
21
+ end
22
+ end
23
+
24
+ context "when a share_token is provided" do
25
+ let(:share_token) { create(:share_token, token_for: component) }
26
+ let(:params) { { share_token: share_token.token } }
27
+
28
+ before do
29
+ uri = URI(main_component_path(component))
30
+ uri.query = URI.encode_www_form(params.to_a)
31
+ visit uri
32
+ end
33
+
34
+ context "when a valid share_token is provided" do
35
+ it "allows visiting component" do
36
+ expect(page).not_to have_content "You are not authorized"
37
+ # rubocop:disable Capybara/CurrentPathExpectation
38
+ expect(page.current_path).to match main_component_path(component)
39
+ # rubocop:enable Capybara/CurrentPathExpectation
40
+ end
41
+ end
42
+
43
+ context "when an invalid share_token is provided" do
44
+ let(:share_token) { create(:share_token, :expired, token_for: component) }
45
+
46
+ it "does not allow visiting component" do
47
+ expect(page).to have_content "You are not authorized"
48
+ # rubocop:disable Capybara/CurrentPathExpectation
49
+ expect(page.current_path).not_to match main_component_path(component)
50
+ # rubocop:enable Capybara/CurrentPathExpectation
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,200 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
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")
11
+ end
12
+ end
13
+
14
+ describe "component_id" do
15
+ it "only returns resources from the given component" do
16
+ external_resource = create(factory_name)
17
+
18
+ expect(subject).not_to include(external_resource)
19
+ end
20
+ end
21
+ end
22
+
23
+ shared_examples_for "a resource search with scopes" do |factory_name|
24
+ let(:factory_params) do
25
+ resource_params
26
+ rescue StandardError
27
+ {}
28
+ end
29
+
30
+ describe "scope_id filter" do
31
+ let(:params) { default_params.merge(scope_id: scope_ids) }
32
+
33
+ let(:scope1) { create :scope, organization: component.organization }
34
+ let(:scope2) { create :scope, organization: component.organization }
35
+ let(:subscope1) { create :scope, organization: component.organization, parent: scope1 }
36
+
37
+ let!(:resource) { create(factory_name, { component: component, scope: scope1 }.merge(factory_params)) }
38
+ let!(:resource2) { create(factory_name, { component: component, scope: scope2 }.merge(factory_params)) }
39
+ let!(:resource3) { create(factory_name, { component: component, scope: subscope1 }.merge(factory_params)) }
40
+
41
+ context "when a parent scope id is being sent" do
42
+ let(:scope_ids) { [scope1.id] }
43
+
44
+ it "filters resources by scope" do
45
+ expect(subject).to match_array [resource, resource3]
46
+ end
47
+ end
48
+
49
+ context "when a subscope id is being sent" do
50
+ let(:scope_ids) { [subscope1.id] }
51
+
52
+ it "filters resources by scope" do
53
+ expect(subject).to eq [resource3]
54
+ end
55
+ end
56
+
57
+ context "when multiple ids are sent" do
58
+ let(:scope_ids) { [scope2.id, scope1.id] }
59
+
60
+ it "filters resources by scope" do
61
+ expect(subject).to match_array [resource, resource2, resource3]
62
+ end
63
+ end
64
+
65
+ context "when `global` is being sent" do
66
+ let!(:resource_without_scope) { create(factory_name, { component: component, scope: nil }.merge(factory_params)) }
67
+ let(:scope_ids) { ["global"] }
68
+
69
+ it "returns resources without a scope" do
70
+ expect(subject).to match_array [resource_without_scope]
71
+ end
72
+ end
73
+
74
+ context "when `global` and some ids is being sent" do
75
+ let!(:resource_without_scope) { create(factory_name, { component: component, scope: nil }.merge(factory_params)) }
76
+ let(:scope_ids) { ["global", scope2.id, scope1.id] }
77
+
78
+ it "returns resources without a scope and with selected scopes" do
79
+ expect(subject).to match_array [resource_without_scope, resource, resource2, resource3]
80
+ end
81
+ end
82
+ end
83
+ end
84
+
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) }
88
+ let(:factory_params) do
89
+ resource_params
90
+ rescue StandardError
91
+ {}
92
+ end
93
+
94
+ 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 }
98
+ let!(:resource) { create(factory_name, { component: component }.merge(factory_params)) }
99
+ let!(:resource2) { create(factory_name, { component: component, category: category1 }.merge(factory_params)) }
100
+ let!(:resource3) { create(factory_name, { component: component, category: category2 }.merge(factory_params)) }
101
+ let!(:resource4) { create(factory_name, { component: component, category: child_category }.merge(factory_params)) }
102
+
103
+ context "when no category filter is present" do
104
+ let(:category_ids) { nil }
105
+
106
+ it "includes all resources" do
107
+ expect(subject).to match_array [resource, resource2, resource3, resource4]
108
+ end
109
+ end
110
+
111
+ context "when a category is selected" do
112
+ let(:category_ids) { [category2.id] }
113
+
114
+ it "includes only resources for that category and its children" do
115
+ expect(subject).to match_array [resource3, resource4]
116
+ end
117
+ end
118
+
119
+ context "when a subcategory is selected" do
120
+ let(:category_ids) { [child_category.id] }
121
+
122
+ it "includes only resources for that category" do
123
+ expect(subject).to eq [resource4]
124
+ end
125
+ end
126
+
127
+ context "when `without` is being sent" do
128
+ let(:category_ids) { ["without"] }
129
+
130
+ it "returns resources without a category" do
131
+ expect(subject).to eq [resource]
132
+ end
133
+ end
134
+
135
+ context "when `without` and some category id is being sent" do
136
+ let(:category_ids) { ["without", category1.id] }
137
+
138
+ it "returns resources without a category and with the selected category" do
139
+ expect(subject).to match_array [resource, resource2]
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ shared_examples_for "a resource search with origin" do |factory_name|
146
+ let(:factory_params) do
147
+ resource_params
148
+ rescue StandardError
149
+ {}
150
+ end
151
+ let(:params) { default_params.merge(origin: origins) }
152
+
153
+ describe "results" do
154
+ let!(:official_resource) { create(factory_name, :official, { component: component }.merge(factory_params)) }
155
+ 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)) }
157
+
158
+ if FactoryBot.factory_by_name(factory_name).defined_traits.map(&:name).include?(:meeting_resource)
159
+ let!(:meeting_resource) { create(factory_name, :official_meeting, { component: component }.merge(factory_params)) }
160
+ end
161
+
162
+ context "when filtering official resources" do
163
+ let(:origins) { %w(official) }
164
+
165
+ it "returns only official resources" do
166
+ expect(subject.size).to eq(1)
167
+ expect(subject).to include(official_resource)
168
+ end
169
+ end
170
+
171
+ context "when filtering citizen resources" do
172
+ let(:origins) { %w(citizens) }
173
+
174
+ it "returns only citizen resources" do
175
+ expect(subject.size).to eq(1)
176
+ expect(subject).to include(citizen_resource)
177
+ end
178
+ end
179
+
180
+ context "when filtering user groups resources" do
181
+ let(:origins) { %w(user_group) }
182
+
183
+ it "returns only user groups resources" do
184
+ expect(subject.size).to eq(1)
185
+ expect(subject).to include(user_group_resource)
186
+ end
187
+ end
188
+
189
+ if respond_to?(:meeting_resource)
190
+ context "when filtering meetings resources" do
191
+ let(:origins) { %w(meeting) }
192
+
193
+ it "returns only meeting resources" do
194
+ expect(subject.size).to eq(1)
195
+ expect(subject).to include(meeting_resource)
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end