decidim 0.0.5 → 0.0.6

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

Potentially problematic release.


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

Files changed (360) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.json +2 -1
  3. data/Gemfile.lock +121 -112
  4. data/README.md +28 -10
  5. data/Rakefile +1 -1
  6. data/decidim-admin/README.md +1 -1
  7. data/decidim-admin/app/assets/stylesheets/decidim/admin/_sidebar.scss +30 -1
  8. data/decidim-admin/app/assets/stylesheets/decidim/admin/_tables.scss +3 -0
  9. data/decidim-admin/app/assets/stylesheets/decidim/admin/application.scss +3 -0
  10. data/decidim-admin/app/commands/decidim/admin/create_participatory_process.rb +4 -1
  11. data/decidim-admin/app/commands/decidim/admin/create_participatory_process_admin.rb +26 -7
  12. data/decidim-admin/app/commands/decidim/admin/create_participatory_process_group.rb +54 -0
  13. data/decidim-admin/app/commands/decidim/admin/create_participatory_process_step.rb +0 -1
  14. data/decidim-admin/app/commands/decidim/admin/destroy_participatory_process_step.rb +3 -1
  15. data/decidim-admin/app/commands/decidim/admin/hide_resource.rb +37 -0
  16. data/decidim-admin/app/commands/decidim/admin/reorder_participatory_process_steps.rb +1 -0
  17. data/decidim-admin/app/commands/decidim/admin/unreport_resource.rb +33 -0
  18. data/decidim-admin/app/commands/decidim/admin/update_participatory_process.rb +4 -2
  19. data/decidim-admin/app/commands/decidim/admin/update_participatory_process_group.rb +57 -0
  20. data/decidim-admin/app/commands/decidim/admin/update_participatory_process_step.rb +1 -2
  21. data/decidim-admin/app/controllers/decidim/admin/application_controller.rb +4 -0
  22. data/decidim-admin/app/controllers/decidim/admin/categories_controller.rb +1 -1
  23. data/decidim-admin/app/controllers/decidim/admin/feature_permissions_controller.rb +2 -2
  24. data/decidim-admin/{lib → app/controllers}/decidim/admin/features/base_controller.rb +0 -0
  25. data/decidim-admin/app/controllers/decidim/admin/moderations_controller.rb +64 -0
  26. data/decidim-admin/app/controllers/decidim/admin/newsletters_controller.rb +1 -1
  27. data/decidim-admin/app/controllers/decidim/admin/participatory_process_groups_controller.rb +86 -0
  28. data/decidim-admin/app/controllers/decidim/admin/participatory_process_publications_controller.rb +1 -1
  29. data/decidim-admin/app/controllers/decidim/admin/participatory_process_step_activations_controller.rb +1 -1
  30. data/decidim-admin/app/controllers/decidim/admin/participatory_process_step_ordering_controller.rb +1 -1
  31. data/decidim-admin/app/controllers/decidim/admin/participatory_process_steps_controller.rb +1 -1
  32. data/decidim-admin/app/controllers/decidim/admin/participatory_process_user_roles_controller.rb +3 -3
  33. data/decidim-admin/app/controllers/decidim/admin/participatory_processes_controller.rb +3 -2
  34. data/decidim-admin/app/forms/decidim/admin/organization_form.rb +1 -0
  35. data/decidim-admin/app/forms/decidim/admin/participatory_process_form.rb +12 -1
  36. data/decidim-admin/app/forms/decidim/admin/participatory_process_group_form.rb +23 -0
  37. data/decidim-admin/app/forms/decidim/admin/participatory_process_step_form.rb +0 -1
  38. data/decidim-admin/app/forms/decidim/admin/participatory_process_user_role_form.rb +5 -1
  39. data/decidim-admin/app/helpers/decidim/admin/application_helper.rb +1 -0
  40. data/decidim-admin/app/helpers/decidim/admin/process_groups_for_select_helper.rb +20 -0
  41. data/decidim-admin/app/helpers/decidim/admin/processes_for_select_helper.rb +22 -0
  42. data/decidim-admin/app/models/decidim/admin/abilities/admin_user.rb +2 -0
  43. data/decidim-admin/app/models/decidim/admin/abilities/participatory_process_admin.rb +4 -0
  44. data/decidim-admin/app/models/decidim/admin/participatory_process_user_role.rb +1 -1
  45. data/decidim-admin/app/queries/decidim/admin/process_admins.rb +43 -0
  46. data/decidim-admin/app/views/decidim/admin/moderations/index.html.erb +65 -0
  47. data/decidim-admin/app/views/decidim/admin/organization/_form.html.erb +4 -0
  48. data/decidim-admin/app/views/decidim/admin/participatory_process_groups/_form.html.erb +17 -0
  49. data/decidim-admin/app/views/decidim/admin/participatory_process_groups/edit.html.erb +13 -0
  50. data/decidim-admin/app/views/decidim/admin/participatory_process_groups/index.html.erb +38 -0
  51. data/decidim-admin/app/views/decidim/admin/participatory_process_groups/new.html.erb +11 -0
  52. data/decidim-admin/app/views/decidim/admin/participatory_process_groups/show.html.erb +23 -0
  53. data/decidim-admin/app/views/decidim/admin/participatory_process_steps/_form.html.erb +0 -4
  54. data/decidim-admin/app/views/decidim/admin/participatory_process_steps/show.html.erb +4 -5
  55. data/decidim-admin/app/views/decidim/admin/participatory_process_user_roles/index.html.erb +27 -24
  56. data/decidim-admin/app/views/decidim/admin/participatory_processes/_form.html.erb +10 -1
  57. data/decidim-admin/app/views/decidim/admin/participatory_processes/show.html.erb +15 -1
  58. data/decidim-admin/app/views/layouts/decidim/admin/_header.html.erb +1 -0
  59. data/decidim-admin/app/views/layouts/decidim/admin/_language_chooser.html.erb +14 -0
  60. data/decidim-admin/app/views/layouts/decidim/admin/_sidebar.html.erb +2 -0
  61. data/decidim-admin/app/views/layouts/decidim/admin/participatory_process.html.erb +5 -0
  62. data/decidim-admin/config/i18n-tasks.yml +3 -1
  63. data/decidim-admin/config/locales/ca.yml +83 -3
  64. data/decidim-admin/config/locales/en.yml +81 -1
  65. data/decidim-admin/config/locales/es.yml +81 -1
  66. data/decidim-admin/config/locales/eu.yml +340 -1
  67. data/decidim-admin/config/locales/fi.yml +464 -0
  68. data/decidim-admin/config/routes.rb +8 -0
  69. data/decidim-admin/db/seeds.rb +1 -1
  70. data/decidim-admin/lib/decidim/admin/engine.rb +1 -0
  71. data/decidim-admin/spec/commands/create_participatory_process_admin_spec.rb +10 -4
  72. data/decidim-admin/spec/commands/create_participatory_process_spec.rb +6 -1
  73. data/decidim-admin/spec/commands/hide_resource_spec.rb +41 -0
  74. data/decidim-admin/spec/commands/unreport_resource_spec.rb +42 -0
  75. data/decidim-admin/spec/commands/update_organization_spec.rb +1 -0
  76. data/decidim-admin/spec/features/admin_invite_spec.rb +1 -0
  77. data/decidim-admin/spec/features/admin_manages_feature_permissions_spec.rb +1 -1
  78. data/decidim-admin/spec/features/admin_manages_organization_admins_spec.rb +1 -1
  79. data/decidim-admin/spec/features/admin_manages_participatory_process_groups_spec.rb +107 -0
  80. data/decidim-admin/spec/features/admin_manages_participatory_processes_spec.rb +5 -0
  81. data/decidim-admin/spec/features/admin_manages_user_groups_spec.rb +11 -4
  82. data/decidim-admin/spec/forms/organization_form_spec.rb +2 -0
  83. data/decidim-admin/spec/forms/participatory_process_group_form_spec.rb +86 -0
  84. data/decidim-admin/spec/forms/participatory_process_step_form_spec.rb +0 -10
  85. data/decidim-admin/spec/forms/participatory_process_user_role_form_spec.rb +4 -0
  86. data/decidim-admin/spec/models/abilities/admin_user_spec.rb +3 -2
  87. data/decidim-admin/spec/models/abilities/participatory_process_admin_spec.rb +7 -0
  88. data/decidim-admin/spec/queries/process_admins_spec.rb +23 -0
  89. data/decidim-admin/spec/shared/manage_process_admins_examples.rb +2 -0
  90. data/decidim-admin/spec/shared/manage_process_steps_examples.rb +0 -10
  91. data/decidim-api/decidim-api.gemspec +1 -1
  92. data/decidim-budgets/app/commands/decidim/budgets/add_line_item.rb +9 -1
  93. data/decidim-budgets/app/controllers/decidim/budgets/admin/projects_controller.rb +13 -1
  94. data/decidim-budgets/app/forms/decidim/budgets/admin/project_form.rb +5 -1
  95. data/decidim-budgets/app/models/decidim/budgets/order.rb +3 -0
  96. data/decidim-budgets/app/models/decidim/budgets/project.rb +9 -1
  97. data/decidim-budgets/app/services/decidim/budgets/project_search.rb +0 -5
  98. data/decidim-budgets/app/views/decidim/budgets/admin/projects/_form.html.erb +5 -3
  99. data/decidim-budgets/app/views/decidim/budgets/admin/projects/index.html.erb +9 -0
  100. data/decidim-budgets/app/views/decidim/budgets/line_items/update_budget.js.erb +1 -0
  101. data/decidim-budgets/app/views/decidim/budgets/projects/_filters.html.erb +2 -2
  102. data/decidim-budgets/app/views/decidim/budgets/projects/_filters_small_view.html.erb +18 -0
  103. data/decidim-budgets/app/views/decidim/budgets/projects/_project.html.erb +17 -2
  104. data/decidim-budgets/app/views/decidim/budgets/projects/_project_budget_button.html.erb +2 -2
  105. data/decidim-budgets/app/views/decidim/budgets/projects/_tags.html.erb +1 -1
  106. data/decidim-budgets/app/views/decidim/budgets/projects/index.html.erb +2 -1
  107. data/decidim-budgets/app/views/decidim/budgets/projects/show.html.erb +7 -1
  108. data/decidim-budgets/config/i18n-tasks.yml +1 -0
  109. data/decidim-budgets/config/locales/ca.yml +18 -3
  110. data/decidim-budgets/config/locales/en.yml +15 -0
  111. data/decidim-budgets/config/locales/es.yml +17 -2
  112. data/decidim-budgets/config/locales/eu.yml +97 -1
  113. data/decidim-budgets/config/locales/fi.yml +123 -0
  114. data/decidim-budgets/db/migrate/20170215132708_add_reference_to_projects.rb +7 -0
  115. data/decidim-budgets/lib/decidim/budgets/feature.rb +4 -2
  116. data/decidim-budgets/lib/decidim/budgets/seeds/Exampledocument.pdf +0 -0
  117. data/decidim-budgets/lib/decidim/budgets/seeds/city.jpeg +0 -0
  118. data/decidim-budgets/lib/decidim/budgets/test/factories.rb +21 -1
  119. data/decidim-budgets/spec/commands/add_line_item_spec.rb +10 -1
  120. data/decidim-budgets/spec/features/comments_spec.rb +10 -0
  121. data/decidim-budgets/spec/features/orders_spec.rb +47 -3
  122. data/decidim-budgets/spec/models/project_spec.rb +16 -1
  123. data/decidim-budgets/spec/services/project_search_spec.rb +9 -0
  124. data/decidim-budgets/spec/shared/admin_shared_context.rb +1 -1
  125. data/decidim-budgets/spec/shared/manage_projects_examples.rb +22 -0
  126. data/decidim-comments/app/assets/javascripts/decidim/comments/bundle.js +0 -0
  127. data/decidim-comments/app/commands/decidim/comments/create_comment.rb +9 -1
  128. data/decidim-comments/app/frontend/application/icon.component.jsx +1 -1
  129. data/decidim-comments/app/frontend/comments/add_comment_form.component.jsx +11 -10
  130. data/decidim-comments/app/frontend/comments/add_comment_form.component.test.jsx +5 -5
  131. data/decidim-comments/app/frontend/comments/comment.component.jsx +91 -1
  132. data/decidim-comments/app/frontend/comments/comment.component.test.jsx +18 -0
  133. data/decidim-comments/app/frontend/comments/comment_data.fragment.graphql +2 -0
  134. data/decidim-comments/app/frontend/comments/comment_order_selector.component.jsx +4 -5
  135. data/decidim-comments/app/frontend/comments/comments.query.graphql +1 -0
  136. data/decidim-comments/app/mailers/decidim/comments/comment_notification_mailer.rb +8 -0
  137. data/decidim-comments/app/models/decidim/comments/abilities/admin_user.rb +25 -0
  138. data/decidim-comments/app/models/decidim/comments/abilities/process_admin_user.rb +33 -0
  139. data/decidim-comments/app/models/decidim/comments/comment.rb +7 -1
  140. data/decidim-comments/app/models/decidim/comments/comment_vote.rb +3 -1
  141. data/decidim-comments/app/queries/decidim/comments/sorted_comments.rb +1 -0
  142. data/decidim-comments/app/views/decidim/comments/comment_notification_mailer/comment_created.html.erb +1 -1
  143. data/decidim-comments/app/views/decidim/comments/comment_notification_mailer/reply_created.html.erb +1 -1
  144. data/decidim-comments/config/locales/ca.yml +11 -0
  145. data/decidim-comments/config/locales/en.yml +12 -2
  146. data/decidim-comments/config/locales/es.yml +11 -0
  147. data/decidim-comments/config/locales/eu.yml +38 -1
  148. data/decidim-comments/config/locales/fi.yml +66 -0
  149. data/decidim-comments/lib/decidim/comments.rb +2 -0
  150. data/decidim-comments/lib/decidim/comments/admin.rb +9 -0
  151. data/decidim-comments/lib/decidim/comments/admin_engine.rb +22 -0
  152. data/decidim-comments/lib/decidim/comments/api/comment_type.rb +12 -0
  153. data/decidim-comments/lib/decidim/comments/commentable.rb +0 -2
  154. data/decidim-comments/lib/decidim/comments/engine.rb +1 -0
  155. data/decidim-comments/lib/decidim/comments/test/factories.rb +3 -0
  156. data/decidim-comments/spec/commands/create_comment_spec.rb +11 -0
  157. data/decidim-comments/spec/features/admin_manages_comments_spec.rb +23 -0
  158. data/decidim-comments/spec/features/comments_spec.rb +5 -173
  159. data/decidim-comments/spec/features/process_admin_manages_comments_spec.rb +24 -0
  160. data/decidim-comments/spec/features/report_comment_spec.rb +20 -0
  161. data/decidim-comments/spec/models/abilities/admin_user_spec.rb +20 -0
  162. data/decidim-comments/spec/models/abilities/process_admin_user_spec.rb +21 -0
  163. data/decidim-comments/spec/models/comment_spec.rb +1 -0
  164. data/decidim-comments/spec/queries/sorted_comments_spec.rb +11 -0
  165. data/decidim-comments/spec/shared/admin_shared_context.rb +11 -0
  166. data/decidim-comments/spec/types/comment_type_spec.rb +19 -0
  167. data/decidim-dev/config/locales/ca.yml +1 -1
  168. data/decidim-dev/config/locales/en.yml +1 -1
  169. data/decidim-dev/config/locales/es.yml +1 -1
  170. data/decidim-dev/config/locales/eu.yml +1 -1
  171. data/decidim-dev/config/locales/fi.yml +5 -0
  172. data/decidim-dev/decidim-dev.gemspec +3 -1
  173. data/decidim-dev/lib/decidim/dev/test/base_spec_helper.rb +1 -28
  174. data/decidim-dev/lib/decidim/dev/test/rspec_support/feature.rb +11 -0
  175. data/{decidim-meetings/spec/support → decidim-dev/lib/decidim/dev/test/rspec_support}/geocoder.rb +5 -1
  176. data/decidim-dev/lib/decidim/dev/test/rspec_support/html_matchers.rb +6 -0
  177. data/decidim-dev/lib/decidim/dev/test/rspec_support/i18n.rb +3 -0
  178. data/decidim-dev/lib/decidim/dev/test/rspec_support/webmock.rb +2 -0
  179. data/decidim-dev/lib/decidim/dev/test/spec_helper.rb +37 -0
  180. data/decidim-dev/lib/generators/decidim/dummy_generator.rb +5 -0
  181. data/decidim-dev/lib/generators/decidim/templates/autoprefixer.yml +8 -0
  182. data/decidim-dev/lib/generators/decidim/templates/autoprefixer_initializer.rb +16 -0
  183. data/decidim-meetings/app/commands/decidim/meetings/admin/create_meeting.rb +6 -17
  184. data/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb +6 -7
  185. data/decidim-meetings/app/controllers/decidim/meetings/application_controller.rb +1 -0
  186. data/decidim-meetings/app/controllers/decidim/meetings/meetings_controller.rb +14 -9
  187. data/decidim-meetings/app/forms/decidim/meetings/admin/meeting_form.rb +12 -1
  188. data/decidim-meetings/app/helpers/decidim/meetings/admin/application_helper.rb +1 -1
  189. data/decidim-meetings/app/helpers/decidim/meetings/application_helper.rb +2 -1
  190. data/decidim-meetings/app/helpers/decidim/meetings/map_helper.rb +10 -32
  191. data/decidim-meetings/app/models/decidim/meetings/meeting.rb +2 -1
  192. data/decidim-meetings/app/services/decidim/meetings/meeting_search.rb +0 -5
  193. data/decidim-meetings/app/views/decidim/meetings/admin/meetings/_form.html.erb +5 -3
  194. data/decidim-meetings/app/views/decidim/meetings/meetings/_filters.html.erb +5 -3
  195. data/decidim-meetings/app/views/decidim/meetings/meetings/_filters_small_view.html.erb +1 -1
  196. data/decidim-meetings/app/views/decidim/meetings/meetings/_meetings.html.erb +11 -1
  197. data/decidim-meetings/app/views/decidim/meetings/meetings/_tags.html.erb +1 -1
  198. data/decidim-meetings/app/views/decidim/meetings/meetings/index.html.erb +27 -32
  199. data/decidim-meetings/app/views/decidim/meetings/meetings/index.js.erb +2 -2
  200. data/decidim-meetings/app/views/decidim/meetings/meetings/show.html.erb +2 -15
  201. data/decidim-meetings/config/i18n-tasks.yml +1 -1
  202. data/decidim-meetings/config/locales/ca.yml +18 -3
  203. data/decidim-meetings/config/locales/en.yml +20 -3
  204. data/decidim-meetings/config/locales/es.yml +18 -3
  205. data/decidim-meetings/config/locales/eu.yml +75 -1
  206. data/decidim-meetings/config/locales/fi.yml +98 -0
  207. data/decidim-meetings/db/migrate/20170215132546_add_reference_to_meetings.rb +7 -0
  208. data/decidim-meetings/decidim-meetings.gemspec +0 -2
  209. data/decidim-meetings/lib/decidim/meetings/admin_engine.rb +0 -26
  210. data/decidim-meetings/lib/decidim/meetings/list_engine.rb +1 -9
  211. data/decidim-meetings/spec/commands/create_meeting_spec.rb +6 -14
  212. data/decidim-meetings/spec/commands/update_meeting_spec.rb +10 -29
  213. data/decidim-meetings/spec/features/explore_meetings_spec.rb +37 -13
  214. data/decidim-meetings/spec/forms/meeting_form_spec.rb +15 -1
  215. data/decidim-meetings/spec/models/meeting_spec.rb +1 -0
  216. data/decidim-meetings/spec/services/meeting_search_spec.rb +9 -0
  217. data/decidim-meetings/spec/shared/admin_shared_context.rb +1 -1
  218. data/decidim-meetings/spec/shared/manage_meetings_examples.rb +97 -1
  219. data/decidim-meetings/spec/spec_helper.rb +0 -5
  220. data/decidim-pages/app/commands/decidim/pages/admin/update_page.rb +1 -4
  221. data/decidim-pages/app/commands/decidim/pages/create_page.rb +1 -4
  222. data/decidim-pages/app/forms/decidim/pages/admin/page_form.rb +0 -3
  223. data/decidim-pages/app/models/decidim/pages/page.rb +8 -12
  224. data/decidim-pages/app/views/decidim/pages/admin/pages/_form.html.erb +0 -1
  225. data/decidim-pages/app/views/decidim/pages/application/show.html.erb +0 -1
  226. data/decidim-pages/config/locales/ca.yml +0 -1
  227. data/decidim-pages/config/locales/en.yml +0 -1
  228. data/decidim-pages/config/locales/es.yml +0 -1
  229. data/decidim-pages/config/locales/eu.yml +14 -1
  230. data/decidim-pages/config/locales/fi.yml +22 -0
  231. data/decidim-pages/db/migrate/20170220091402_remove_page_feature_titles.rb +5 -0
  232. data/decidim-pages/lib/decidim/pages/engine.rb +1 -0
  233. data/decidim-pages/lib/decidim/pages/feature.rb +4 -1
  234. data/decidim-pages/spec/commands/create_page_spec.rb +1 -2
  235. data/decidim-pages/spec/commands/update_page_spec.rb +0 -1
  236. data/decidim-pages/spec/factories.rb +6 -1
  237. data/decidim-pages/spec/features/admin_spec.rb +1 -17
  238. data/decidim-pages/spec/features/comments_spec.rb +10 -0
  239. data/decidim-pages/spec/features/page_show_spec.rb +1 -10
  240. data/decidim-pages/spec/forms/page_form_spec.rb +0 -21
  241. data/decidim-pages/spec/models/page_spec.rb +2 -4
  242. data/decidim-proposals/app/commands/decidim/proposals/admin/create_proposal.rb +4 -1
  243. data/decidim-proposals/app/commands/decidim/proposals/create_proposal.rb +4 -1
  244. data/decidim-proposals/app/controllers/decidim/proposals/admin/proposals_controller.rb +4 -0
  245. data/decidim-proposals/app/controllers/decidim/proposals/proposals_controller.rb +12 -6
  246. data/decidim-proposals/app/forms/decidim/proposals/admin/proposal_form.rb +13 -2
  247. data/decidim-proposals/app/forms/decidim/proposals/proposal_form.rb +13 -2
  248. data/decidim-proposals/app/helpers/decidim/proposals/application_helper.rb +3 -0
  249. data/decidim-proposals/app/helpers/decidim/proposals/map_helper.rb +19 -0
  250. data/decidim-proposals/app/helpers/decidim/proposals/proposal_order_helper.rb +16 -0
  251. data/decidim-proposals/app/models/decidim/proposals/abilities/admin_user.rb +2 -0
  252. data/decidim-proposals/app/models/decidim/proposals/abilities/current_user.rb +3 -0
  253. data/decidim-proposals/app/models/decidim/proposals/abilities/process_admin_user.rb +2 -1
  254. data/decidim-proposals/app/models/decidim/proposals/proposal.rb +12 -3
  255. data/decidim-proposals/app/services/decidim/proposals/proposal_search.rb +0 -5
  256. data/decidim-proposals/app/views/decidim/proposals/admin/proposal_answers/edit.html.erb +1 -1
  257. data/decidim-proposals/app/views/decidim/proposals/admin/proposals/_form.html.erb +8 -2
  258. data/decidim-proposals/app/views/decidim/proposals/admin/proposals/index.html.erb +12 -14
  259. data/decidim-proposals/app/views/decidim/proposals/proposals/_filters.html.erb +2 -2
  260. data/decidim-proposals/app/views/decidim/proposals/proposals/_filters_small_view.html.erb +1 -1
  261. data/decidim-proposals/app/views/decidim/proposals/proposals/_proposals.html.erb +1 -1
  262. data/decidim-proposals/app/views/decidim/proposals/proposals/_tags.html.erb +1 -1
  263. data/decidim-proposals/app/views/decidim/proposals/proposals/index.html.erb +27 -0
  264. data/decidim-proposals/app/views/decidim/proposals/proposals/new.html.erb +8 -2
  265. data/decidim-proposals/app/views/decidim/proposals/proposals/show.html.erb +18 -1
  266. data/decidim-proposals/config/i18n-tasks.yml +3 -1
  267. data/decidim-proposals/config/locales/ca.yml +11 -8
  268. data/decidim-proposals/config/locales/en.yml +9 -6
  269. data/decidim-proposals/config/locales/es.yml +14 -11
  270. data/decidim-proposals/config/locales/eu.yml +119 -1
  271. data/decidim-proposals/config/locales/fi.yml +143 -0
  272. data/decidim-proposals/db/migrate/20170215113152_create_proposal_reports.rb +14 -0
  273. data/decidim-proposals/db/migrate/20170215131720_add_report_count_to_proposals.rb +5 -0
  274. data/decidim-proposals/db/migrate/20170215132030_add_reference_to_proposals.rb +7 -0
  275. data/decidim-proposals/db/migrate/20170220152416_add_hidden_at_to_proposals.rb +5 -0
  276. data/decidim-proposals/db/migrate/20170228105156_add_geolocalization_fields_to_proposals.rb +7 -0
  277. data/decidim-proposals/db/migrate/20170307085300_migrate_proposal_reports_data_to_reports.rb +26 -0
  278. data/decidim-proposals/decidim-proposals.gemspec +1 -1
  279. data/decidim-proposals/lib/decidim/proposals/feature.rb +4 -3
  280. data/decidim-proposals/lib/decidim/proposals/test/factories.rb +8 -0
  281. data/decidim-proposals/spec/features/admin_manages_proposals_spec.rb +3 -0
  282. data/decidim-proposals/spec/features/comments_spec.rb +11 -0
  283. data/decidim-proposals/spec/features/process_admin_manages_proposals_spec.rb +3 -0
  284. data/decidim-proposals/spec/features/proposals_spec.rb +98 -15
  285. data/decidim-proposals/spec/features/report_proposal_spec.rb +19 -0
  286. data/decidim-proposals/spec/helpers/proposal_order_helper_spec.rb +30 -0
  287. data/decidim-proposals/spec/models/decidim/proposals/proposal_spec.rb +2 -0
  288. data/decidim-proposals/spec/services/decidim/proposals/proposal_search_spec.rb +9 -0
  289. data/decidim-proposals/spec/shared/create_proposal_examples.rb +29 -2
  290. data/decidim-proposals/spec/shared/manage_proposals_examples.rb +95 -26
  291. data/decidim-proposals/spec/shared/proposal_form_examples.rb +29 -1
  292. data/decidim-results/app/forms/decidim/results/admin/result_form.rb +9 -1
  293. data/decidim-results/app/models/decidim/results/result.rb +2 -1
  294. data/decidim-results/app/services/decidim/results/result_search.rb +0 -5
  295. data/decidim-results/app/views/decidim/results/admin/results/_form.html.erb +5 -3
  296. data/decidim-results/app/views/decidim/results/results/_filters.html.erb +2 -2
  297. data/decidim-results/app/views/decidim/results/results/_filters_small_view.html.erb +18 -0
  298. data/decidim-results/app/views/decidim/results/results/_tags.html.erb +1 -1
  299. data/decidim-results/app/views/decidim/results/results/index.html.erb +1 -0
  300. data/decidim-results/app/views/decidim/results/results/show.html.erb +1 -0
  301. data/decidim-results/config/i18n-tasks.yml +2 -0
  302. data/decidim-results/config/locales/ca.yml +15 -2
  303. data/decidim-results/config/locales/en.yml +15 -2
  304. data/decidim-results/config/locales/es.yml +15 -2
  305. data/decidim-results/config/locales/eu.yml +57 -1
  306. data/decidim-results/config/locales/fi.yml +77 -0
  307. data/decidim-results/db/migrate/20170215132624_add_reference_to_results.rb +7 -0
  308. data/decidim-results/lib/decidim/results/test/factories.rb +6 -0
  309. data/decidim-results/spec/features/comments_spec.rb +10 -0
  310. data/decidim-results/spec/features/explore_results_spec.rb +27 -0
  311. data/decidim-results/spec/models/result_spec.rb +1 -0
  312. data/decidim-results/spec/services/result_search_spec.rb +9 -0
  313. data/decidim-results/spec/shared/admin_shared_context.rb +1 -1
  314. data/decidim-system/README.md +45 -8
  315. data/decidim-system/app/commands/decidim/system/register_organization.rb +3 -0
  316. data/decidim-system/app/commands/decidim/system/update_organization.rb +2 -0
  317. data/decidim-system/app/controllers/decidim/system/application_controller.rb +2 -0
  318. data/decidim-system/app/forms/decidim/system/register_organization_form.rb +1 -0
  319. data/decidim-system/app/forms/decidim/system/update_organization_form.rb +18 -0
  320. data/decidim-system/app/views/decidim/system/organizations/edit.html.erb +10 -0
  321. data/decidim-system/app/views/decidim/system/organizations/new.html.erb +33 -19
  322. data/decidim-system/config/locales/ca.yml +3 -0
  323. data/decidim-system/config/locales/en.yml +3 -0
  324. data/decidim-system/config/locales/es.yml +3 -0
  325. data/decidim-system/config/locales/eu.yml +3 -0
  326. data/decidim-system/config/locales/fi.yml +68 -0
  327. data/decidim-system/db/seeds.rb +1 -1
  328. data/decidim-system/decidim-system.gemspec +1 -1
  329. data/decidim-system/lib/decidim/system/engine.rb +1 -0
  330. data/decidim-system/spec/commands/decidim/system/register_organization_spec.rb +3 -0
  331. data/decidim-system/spec/commands/decidim/system/update_organization_spec.rb +53 -0
  332. data/decidim-system/spec/features/organizations_spec.rb +5 -0
  333. data/docs/analytics.md +23 -0
  334. data/docs/how_to_create_a_plugin.md +3 -1
  335. data/lib/generators/decidim/app_generator.rb +4 -0
  336. data/lib/generators/decidim/demo_generator.rb +1 -1
  337. data/lib/generators/decidim/install_generator.rb +8 -1
  338. data/lib/generators/decidim/review_app_generator.rb +53 -0
  339. data/lib/generators/decidim/templates/Gemfile.erb +1 -5
  340. data/lib/generators/decidim/templates/app.json.erb +1 -1
  341. data/lib/generators/decidim/templates/carrierwave.rb +2 -2
  342. data/lib/generators/decidim/templates/decidim_controller.rb.erb +5 -0
  343. data/lib/generators/decidim/templates/initializer.rb +4 -0
  344. data/package.json +4 -4
  345. data/yarn.lock +106 -165
  346. metadata +100 -54
  347. data/decidim-meetings/app/assets/config/decidim_meetings_manifest.js +0 -2
  348. data/decidim-meetings/app/assets/javascripts/decidim/meetings/map.js.es6.erb +0 -97
  349. data/decidim-meetings/app/assets/stylesheets/decidim/meetings/map.css +0 -3
  350. data/decidim-meetings/app/services/decidim/meetings/static_map_generator.rb +0 -50
  351. data/decidim-meetings/app/views/decidim/meetings/meetings/_address_details.html.erb +0 -5
  352. data/decidim-meetings/spec/controllers/meetings_controller_spec.rb +0 -41
  353. data/decidim-meetings/spec/services/static_map_generator_spec.rb +0 -33
  354. data/decidim-meetings/vendor/assets/javascripts/leaflet-svg-icon.js +0 -179
  355. data/decidim-meetings/vendor/assets/javascripts/leaflet-tilelayer-here.js +0 -166
  356. data/decidim-meetings/vendor/assets/javascripts/leaflet.js +0 -9
  357. data/decidim-meetings/vendor/assets/javascripts/leaflet.markercluster.js +0 -7
  358. data/decidim-meetings/vendor/assets/stylesheets/MarkerCluster.Default.css +0 -60
  359. data/decidim-meetings/vendor/assets/stylesheets/MarkerCluster.css +0 -14
  360. data/decidim-meetings/vendor/assets/stylesheets/leaflet.css +0 -624
@@ -0,0 +1,7 @@
1
+ class AddReferenceToProjects < ActiveRecord::Migration[5.0]
2
+ def change
3
+ add_column :decidim_budgets_projects, :reference, :string
4
+ Decidim::Budgets::Project.find_each(&:save)
5
+ change_column_null :decidim_budgets_projects, :reference, false
6
+ end
7
+ end
@@ -27,6 +27,8 @@ Decidim.register_feature(:budgets) do |feature|
27
27
 
28
28
  feature.settings(:step) do |settings|
29
29
  settings.attribute :comments_blocked, type: :boolean, default: false
30
+ settings.attribute :votes_enabled, type: :boolean, default: true
31
+ settings.attribute :show_votes, type: :boolean, default: false
30
32
  end
31
33
 
32
34
  feature.seeds do
@@ -54,13 +56,13 @@ Decidim.register_feature(:budgets) do |feature|
54
56
  Decidim::Attachment.create!(
55
57
  title: Decidim::Faker::Localized.sentence(2),
56
58
  description: Decidim::Faker::Localized.sentence(5),
57
- file: File.new(Decidim::Dev.asset("city.jpeg")),
59
+ file: File.new(File.join(File.dirname(__FILE__), "seeds", "city.jpeg")),
58
60
  attached_to: project
59
61
  )
60
62
  Decidim::Attachment.create!(
61
63
  title: Decidim::Faker::Localized.sentence(2),
62
64
  description: Decidim::Faker::Localized.sentence(5),
63
- file: File.new(Decidim::Dev.asset("Exampledocument.pdf")),
65
+ file: File.new(File.join(File.dirname(__FILE__), "seeds", "Exampledocument.pdf")),
64
66
  attached_to: project
65
67
  )
66
68
  Decidim::Comments::Seed.comments_for(project)
@@ -6,7 +6,7 @@ FactoryGirl.define do
6
6
  factory :budget_feature, parent: :feature do
7
7
  name { Decidim::Features::Namer.new(participatory_process.organization.available_locales, :budgets).i18n_name }
8
8
  manifest_name :budgets
9
- participatory_process
9
+ participatory_process { create(:participatory_process, :with_steps) }
10
10
 
11
11
  trait :with_total_budget_and_vote_threshold_percent do
12
12
  transient do
@@ -21,6 +21,26 @@ FactoryGirl.define do
21
21
  }
22
22
  end
23
23
  end
24
+
25
+ trait :with_votes_disabled do
26
+ step_settings do
27
+ {
28
+ participatory_process.active_step.id => {
29
+ votes_enabled: false
30
+ }
31
+ }
32
+ end
33
+ end
34
+
35
+ trait :with_show_votes_enabled do
36
+ step_settings do
37
+ {
38
+ participatory_process.active_step.id => {
39
+ show_votes: true
40
+ }
41
+ }
42
+ end
43
+ end
24
44
  end
25
45
 
26
46
  factory :project, class: Decidim::Budgets::Project do
@@ -2,7 +2,8 @@ require "spec_helper"
2
2
 
3
3
  describe Decidim::Budgets::AddLineItem do
4
4
  let(:user) { create(:user) }
5
- let(:feature) { create(:budget_feature, organization: user.organization, settings: settings) }
5
+ let(:participatory_process) { create :participatory_process, :with_steps, organization: user.organization }
6
+ let(:feature) { create(:budget_feature, participatory_process: participatory_process, settings: settings) }
6
7
  let(:project) { create(:project, feature: feature, budget: 60_000) }
7
8
  let(:settings) { { "total_budget" => 100_000, vote_threshold_percent: 50 }}
8
9
  let(:order) { nil }
@@ -58,4 +59,12 @@ describe Decidim::Budgets::AddLineItem do
58
59
  expect { subject.call }.to broadcast(:invalid)
59
60
  end
60
61
  end
62
+
63
+ context "when the votes are not enabled" do
64
+ let(:feature) { create(:budget_feature, :with_votes_disabled, participatory_process: participatory_process, settings: settings) }
65
+
66
+ it "broadcasts invalid" do
67
+ expect { subject.call }.to broadcast(:invalid)
68
+ end
69
+ end
61
70
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ describe "Comments", type: :feature, perform_enqueued: true do
5
+ let!(:feature) { create(:budget_feature, organization: organization) }
6
+ let!(:commentable) { create(:project, feature: feature) }
7
+
8
+ let(:resource_path) { decidim_budgets.project_path(commentable, feature_id: feature, participatory_process_id: feature.participatory_process) }
9
+ include_examples "comments"
10
+ end
@@ -32,11 +32,12 @@ describe "Orders", type: :feature do
32
32
  context "when the user is logged in" do
33
33
  before do
34
34
  login_as user, scope: :user
35
- visit_feature
36
35
  end
37
36
 
38
37
  context "and has not a pending order" do
39
38
  it "adds a project to the current order" do
39
+ visit_feature
40
+
40
41
  within "#project-#{project.id}-item" do
41
42
  page.find('.budget--list__action').click
42
43
  end
@@ -62,10 +63,11 @@ describe "Orders", type: :feature do
62
63
  feature.update_attribute(:permissions, vote: {
63
64
  authorization_handler_name: "decidim/dummy_authorization_handler"
64
65
  })
65
- visit_feature
66
66
  end
67
67
 
68
68
  it "shows a modal dialog" do
69
+ visit_feature
70
+
69
71
  within "#project-#{project.id}-item" do
70
72
  page.find('.budget--list__action').click
71
73
  end
@@ -80,6 +82,7 @@ describe "Orders", type: :feature do
80
82
 
81
83
  it "removes a project from the current order" do
82
84
  visit_feature
85
+
83
86
  expect(page).to have_content "ASSIGNED: €25,000,000"
84
87
 
85
88
  within "#project-#{project.id}-item" do
@@ -145,7 +148,7 @@ describe "Orders", type: :feature do
145
148
  context "and has a finished order" do
146
149
  let!(:order) do
147
150
  order = create(:order, user: user, feature: feature)
148
- order.projects << projects
151
+ order.projects = projects
149
152
  order.checked_out_at = Time.current
150
153
  order.save!
151
154
  order
@@ -169,6 +172,47 @@ describe "Orders", type: :feature do
169
172
  end
170
173
  end
171
174
  end
175
+
176
+ context "and votes are disabled" do
177
+ let!(:feature) do
178
+ create(:budget_feature,
179
+ :with_votes_disabled,
180
+ manifest: manifest,
181
+ participatory_process: participatory_process)
182
+ end
183
+
184
+ it "cannot create new orders" do
185
+ visit_feature
186
+
187
+ expect(page).to have_selector('button.budget--list__action[disabled]', count: 3)
188
+ expect(page).to have_no_selector('.budget-summary')
189
+ end
190
+ end
191
+
192
+ context "and show votes are enabled" do
193
+ let!(:feature) do
194
+ create(:budget_feature,
195
+ :with_show_votes_enabled,
196
+ manifest: manifest,
197
+ participatory_process: participatory_process)
198
+ end
199
+
200
+ let!(:order) do
201
+ order = create(:order, user: user, feature: feature)
202
+ order.projects = projects
203
+ order.checked_out_at = Time.current
204
+ order.save!
205
+ order
206
+ end
207
+
208
+ it "displays the number of votes for a project" do
209
+ visit_feature
210
+
211
+ within "#project-#{project.id}-item" do
212
+ expect(page).to have_content("1 SUPPORT")
213
+ end
214
+ end
215
+ end
172
216
  end
173
217
 
174
218
  describe "show" do
@@ -3,9 +3,11 @@
3
3
  require "spec_helper"
4
4
 
5
5
  describe Decidim::Budgets::Project do
6
- let(:project) { build :project }
6
+ let(:project) { create :project }
7
7
  subject { project }
8
8
 
9
+ include_examples "has reference"
10
+
9
11
  it { is_expected.to be_valid }
10
12
 
11
13
  context "without a feature" do
@@ -27,4 +29,17 @@ describe Decidim::Budgets::Project do
27
29
 
28
30
  it { is_expected.not_to be_valid }
29
31
  end
32
+
33
+ context "#orders_count" do
34
+ let(:project) { create :project, budget: 75_000_000 }
35
+ let(:order) { create :order, feature: project.feature }
36
+ let(:unfinished_order) { create :order, feature: project.feature }
37
+ let!(:line_item) { create :line_item, project: project, order: order }
38
+ let!(:line_item_1) { create :line_item, project: project , order: unfinished_order}
39
+
40
+ it "return number of finished orders for this project" do
41
+ order.reload.update_attributes!(checked_out_at: Time.current)
42
+ expect(project.confirmed_orders_count).to eq(1)
43
+ end
44
+ end
30
45
  end
@@ -65,6 +65,15 @@ describe Decidim::Budgets::ProjectSearch do
65
65
  expect(subject.results).to match_array [project1,project2]
66
66
  end
67
67
  end
68
+
69
+ context "when `global` is being sent" do
70
+ let!(:resource_without_scope) { create(:project, feature: current_feature, scope: nil)}
71
+ let(:params) { default_params.merge(scope_id: ["global"]) }
72
+
73
+ it "returns resources without a scope" do
74
+ expect(subject.results).to eq [resource_without_scope]
75
+ end
76
+ end
68
77
  end
69
78
 
70
79
  context "category_id" do
@@ -1,6 +1,6 @@
1
1
  RSpec.shared_context "admin" do
2
2
  let(:organization) { create(:organization) }
3
- let!(:user) { create(:user, :admin, :confirmed, organization: organization, email: "admin@decidim.org") }
3
+ let!(:user) { create(:user, :admin, :confirmed, organization: organization, email: "admin@example.org") }
4
4
  let(:participatory_process) { create(:participatory_process, :with_steps, organization: organization) }
5
5
  let(:process_admin) { create :user, :confirmed, organization: organization }
6
6
  let!(:user_role) { create :participatory_process_user_role, user: process_admin, participatory_process: participatory_process }
@@ -38,6 +38,28 @@ RSpec.shared_examples "manage projects" do
38
38
  end
39
39
  end
40
40
 
41
+ context "seeing finished and pending orders" do
42
+ let!(:project) { create(:project, budget: 70_000_000, feature: current_feature) }
43
+
44
+ let!(:finished_orders) do
45
+ orders = create_list(:order, 10, feature: current_feature)
46
+ orders.each do |order|
47
+ order.update_attribute(:line_items, [create(:line_item, project: project, order: order)])
48
+ order.update_attribute(:checked_out_at, Date.today)
49
+ end
50
+ end
51
+
52
+ let!(:pending_orders) do
53
+ create_list(:order, 5, feature: current_feature, checked_out_at: nil)
54
+ end
55
+
56
+ it "shows the order count" do
57
+ visit current_path
58
+ expect(page).to have_content("Finished orders: 10")
59
+ expect(page).to have_content("Pending orders: 5")
60
+ end
61
+ end
62
+
41
63
  it "creates a new project" do
42
64
  find(".actions .new").click
43
65
 
@@ -22,7 +22,7 @@ module Decidim
22
22
  return broadcast(:invalid) if form.invalid?
23
23
 
24
24
  create_comment
25
- send_notification_to_author unless @author == @commentable.author
25
+ send_notification_to_author if has_author? && !same_author?
26
26
 
27
27
  broadcast(:ok, @comment)
28
28
  end
@@ -46,6 +46,14 @@ module Decidim
46
46
  CommentNotificationMailer.comment_created(@author, @comment, @commentable).deliver_later
47
47
  end
48
48
  end
49
+
50
+ def has_author?
51
+ @commentable.respond_to?(:author) && @commentable.author.present?
52
+ end
53
+
54
+ def same_author?
55
+ @author == @commentable.author
56
+ end
49
57
  end
50
58
  end
51
59
  end
@@ -10,7 +10,7 @@ const Icon = ({ name, iconExtraClassName }) => {
10
10
  return (
11
11
  <svg className={`icon ${iconExtraClassName} ${name}`}>
12
12
  <use xmlnsXlink="http://www.w3.org/1999/xlink" xlinkHref={`${assetUrl('icons.svg')}#${name}`} />
13
- </svg>
13
+ </svg>
14
14
  );
15
15
  };
16
16
 
@@ -104,12 +104,11 @@ export class AddCommentForm extends Component {
104
104
  <label className="show-for-sr" htmlFor={`add-comment-${type}-${id}`}>{ I18n.t("components.add_comment_form.form.body.label") }</label>
105
105
  {this._renderTextArea()}
106
106
  {this._renderTextAreaError()}
107
- <input
108
- type="submit"
109
- className={submitButtonClassName}
110
- value={I18n.t("components.add_comment_form.form.submit")}
111
- disabled={disabled}
112
- />
107
+ <button type="submit"
108
+ className={submitButtonClassName}
109
+ disabled={disabled}>
110
+ {I18n.t("components.add_comment_form.form.submit")}
111
+ </button>
113
112
  </div>
114
113
  </form>
115
114
  );
@@ -183,7 +182,7 @@ export class AddCommentForm extends Component {
183
182
  const koButtonClassName = classnames(buttonClassName, 'opinion-toggle--ko', {
184
183
  'is-active': alignment === -1
185
184
  });
186
- const neutralButtonClassName = classnames(buttonClassName, 'opinion-toggle--neutral', {
185
+ const neutralButtonClassName = classnames(buttonClassName, 'opinion-toggle--meh', {
187
186
  'is-active': alignment === 0
188
187
  });
189
188
 
@@ -194,7 +193,7 @@ export class AddCommentForm extends Component {
194
193
  className={okButtonClassName}
195
194
  onClick={() => this.setState({ alignment: 1 })}
196
195
  >
197
- <Icon name="icon-thumb-up" />
196
+ <Icon iconExtraClassName="" name="icon-thumb-up" />
198
197
  </button>
199
198
  <button
200
199
  className={neutralButtonClassName}
@@ -206,7 +205,7 @@ export class AddCommentForm extends Component {
206
205
  className={koButtonClassName}
207
206
  onClick={() => this.setState({ alignment: -1 })}
208
207
  >
209
- <Icon name="icon-thumb-down" />
208
+ <Icon iconExtraClassName="" name="icon-thumb-down" />
210
209
  </button>
211
210
  </div>
212
211
  );
@@ -353,6 +352,7 @@ const AddCommentFormWithMutation = graphql(gql`
353
352
  addComment: {
354
353
  __typename: 'Comment',
355
354
  id: uuid(),
355
+ sgid: uuid(),
356
356
  type: "Decidim::Comments::Comment",
357
357
  createdAt: new Date().toISOString(),
358
358
  body,
@@ -368,7 +368,8 @@ const AddCommentFormWithMutation = graphql(gql`
368
368
  upVotes: 0,
369
369
  upVoted: false,
370
370
  downVotes: 0,
371
- downVoted: false
371
+ downVoted: false,
372
+ alreadyReported: false
372
373
  }
373
374
  }
374
375
  },
@@ -61,9 +61,9 @@ describe("<AddCommentForm />", () => {
61
61
 
62
62
  it("should use prop submitButtonClassName as a className prop for submit button", () => {
63
63
  const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} submitButtonClassName="button small hollow" />);
64
- expect(wrapper.find('input[type="submit"]')).to.have.className('button');
65
- expect(wrapper.find('input[type="submit"]')).to.have.className('small');
66
- expect(wrapper.find('input[type="submit"]')).to.have.className('hollow');
64
+ expect(wrapper.find('button[type="submit"]')).to.have.className('button');
65
+ expect(wrapper.find('button[type="submit"]')).to.have.className('small');
66
+ expect(wrapper.find('button[type="submit"]')).to.have.className('hollow');
67
67
  });
68
68
 
69
69
  it("should enable the submit button if textarea is not blank", () => {
@@ -73,7 +73,7 @@ describe("<AddCommentForm />", () => {
73
73
  value: 'This is a comment'
74
74
  }
75
75
  });
76
- expect(wrapper.find('input[type="submit"]')).not.to.be.disabled();
76
+ expect(wrapper.find('button[type="submit"]')).not.to.be.disabled();
77
77
  });
78
78
 
79
79
  it("should disable the submit button if textarea is blank", () => {
@@ -88,7 +88,7 @@ describe("<AddCommentForm />", () => {
88
88
  value: ''
89
89
  }
90
90
  });
91
- expect(wrapper.find('input[type="submit"]')).to.be.disabled();
91
+ expect(wrapper.find('button[type="submit"]')).to.be.disabled();
92
92
  });
93
93
 
94
94
  it("should not render a div with class 'opinion-toggle'", () => {
@@ -1,3 +1,4 @@
1
+ /* eslint-disable max-lines, camelcase */
1
2
  import { Component, PropTypes } from 'react';
2
3
  import { propType } from 'graphql-anywhere';
3
4
  import gql from 'graphql-tag';
@@ -8,6 +9,7 @@ import classnames from 'classnames';
8
9
  import AddCommentForm from './add_comment_form.component';
9
10
  import UpVoteButton from './up_vote_button.component';
10
11
  import DownVoteButton from './down_vote_button.component';
12
+ import Icon from '../application/icon.component';
11
13
 
12
14
  import commentFragment from './comment.fragment.graphql';
13
15
  import commentDataFragment from './comment_data.fragment.graphql';
@@ -26,9 +28,21 @@ class Comment extends Component {
26
28
  };
27
29
  }
28
30
 
31
+ componentDidMount() {
32
+ if ($(document).foundation) {
33
+ const { comment: { id } } = this.props;
34
+ $(`#flagModalComment${id}`).foundation();
35
+ }
36
+ }
37
+
29
38
  render() {
30
- const { comment: { id, author, body, createdAt }, articleClassName } = this.props;
39
+ const { session, comment: { id, author, body, createdAt }, articleClassName } = this.props;
31
40
  const formattedCreatedAt = ` ${moment(createdAt).format("LLL")}`;
41
+ let modalName = 'loginModal';
42
+
43
+ if (session && session.user) {
44
+ modalName = `flagModalComment${id}`;
45
+ }
32
46
 
33
47
  return (
34
48
  <article id={`comment_${id}`} className={articleClassName}>
@@ -43,6 +57,12 @@ class Comment extends Component {
43
57
  <time dateTime={createdAt}>{formattedCreatedAt}</time>
44
58
  </div>
45
59
  </div>
60
+ <div className="author-data__extra">
61
+ <button type="button" title={ I18n.t("components.comment.report.title") } data-open={modalName}>
62
+ <Icon name="icon-flag" iconExtraClassName="icon--small"></Icon>
63
+ </button>
64
+ {this._renderFlagModal()}
65
+ </div>
46
66
  </div>
47
67
  </div>
48
68
  <div className="comment__content">
@@ -223,6 +243,76 @@ class Comment extends Component {
223
243
 
224
244
  return null;
225
245
  }
246
+
247
+ /**
248
+ * Render a modal to report the comment.
249
+ * @private
250
+ * @return {Void|DOMElement} - The comment's report modal or not.
251
+ */
252
+ _renderFlagModal() {
253
+ const { session, comment: { id, sgid, alreadyReported } } = this.props;
254
+ const authenticityToken = this._getAuthenticityToken();
255
+
256
+ if (session && session.user) {
257
+ return (
258
+ <div className="reveal flag-modal" id={`flagModalComment${id}`} data-reveal>
259
+ <div className="reveal__header">
260
+ <h3 className="reveal__title">{ I18n.t("components.comment.report.title") }</h3>
261
+ <button
262
+ className="close-button"
263
+ aria-label={ I18n.t("components.comment.report.close") }
264
+ type="button"
265
+ onClick={() => $(`#flagModalComment${id}`).foundation('close')}>
266
+ <span aria-hidden="true">&times;</span>
267
+ </button>
268
+ </div>
269
+ {
270
+ (() => {
271
+ if (alreadyReported) {
272
+ return (
273
+ <p key={`already-reported-comment-${id}`}>{ I18n.t("components.comment.report.already_reported") }</p>
274
+ );
275
+ }
276
+ return [
277
+ <p key={`report-description-comment-${id}`}>{ I18n.t("components.comment.report.description") }</p>,
278
+ <form key={`report-form-comment-${id}`} method="post" action={`/report?sgid=${sgid}`}>
279
+ <input type="hidden" name="authenticity_token" value={authenticityToken} />
280
+ <label htmlFor={`report_comment_${id}_reason_spam`}>
281
+ <input type="radio" value="spam" name="report[reason]" id={`report_comment_${id}_reason_spam`} defaultChecked />
282
+ { I18n.t("components.comment.report.reasons.spam") }
283
+ </label>
284
+ <label htmlFor={`report_comment_${id}_reason_offensive`}>
285
+ <input type="radio" value="offensive" name="report[reason]" id={`report_comment_${id}_reason_offensive`} />
286
+ { I18n.t("components.comment.report.reasons.offensive") }
287
+ </label>
288
+ <label htmlFor={`report_comment_${id}_reason_does_not_belong`}>
289
+ <input type="radio" value="does_not_belong" name="report[reason]" id={`report_comment_${id}_reason_does_not_belong`} />
290
+ { I18n.t("components.comment.report.reasons.does_not_belong", { organization_name: session.user.organizationName }) }
291
+ </label>
292
+ <label htmlFor={`report_comment_${id}_details`}>
293
+ { I18n.t("components.comment.report.details") }
294
+ <textarea rows="4" name="report[details]" id={`report_comment_${id}_details`} />
295
+ </label>
296
+ <button type="submit" name="commit" className="button">{ I18n.t("components.comment.report.action") }</button>
297
+ </form>
298
+ ];
299
+ })()
300
+ }
301
+ </div>
302
+ );
303
+ }
304
+
305
+ return null;
306
+ }
307
+
308
+ /**
309
+ * Get Rails authenticity token so we can send requests through the report forms.
310
+ * @private
311
+ * @return {string} - The current authenticity token.
312
+ */
313
+ _getAuthenticityToken() {
314
+ return $('meta[name="csrf-token"]').attr('content');
315
+ }
226
316
  }
227
317
 
228
318
  Comment.fragments = {