decidim 0.0.4 → 0.0.5

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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.json +2 -5
  3. data/.mention-bot +2 -1
  4. data/.yardopts +8 -0
  5. data/Gemfile.lock +64 -62
  6. data/README.md +11 -9
  7. data/decidim-admin/app/assets/javascripts/decidim/admin/sort_steps.js.es6 +3 -3
  8. data/decidim-admin/app/assets/stylesheets/decidim/admin/_email_preview.scss +5 -0
  9. data/decidim-admin/app/assets/stylesheets/decidim/admin/application.scss +1 -0
  10. data/decidim-admin/app/commands/decidim/admin/create_newsletter.rb +30 -0
  11. data/decidim-admin/app/commands/decidim/admin/deliver_newsletter.rb +29 -0
  12. data/decidim-admin/app/commands/decidim/admin/destroy_participatory_process_step.rb +9 -0
  13. data/decidim-admin/app/commands/decidim/admin/update_newsletter.rb +33 -0
  14. data/decidim-admin/app/constraints/decidim/admin/organization_dashboard_constraint.rb +1 -1
  15. data/decidim-admin/app/controllers/decidim/admin/features_controller.rb +2 -2
  16. data/decidim-admin/app/controllers/decidim/admin/newsletters_controller.rb +115 -0
  17. data/decidim-admin/app/controllers/decidim/admin/participatory_processes_controller.rb +4 -4
  18. data/decidim-admin/app/forms/decidim/admin/newsletter_form.rb +15 -0
  19. data/decidim-admin/app/jobs/decidim/admin/newsletter_delivery_job.rb +18 -0
  20. data/decidim-admin/app/jobs/decidim/admin/newsletter_job.rb +32 -0
  21. data/decidim-admin/app/models/decidim/admin/abilities/admin_user.rb +4 -0
  22. data/decidim-admin/app/models/decidim/admin/abilities/base.rb +4 -0
  23. data/decidim-admin/app/models/decidim/admin/abilities/collaborator_user.rb +19 -0
  24. data/decidim-admin/app/models/decidim/admin/abilities/participatory_process_admin.rb +1 -1
  25. data/decidim-admin/app/queries/decidim/admin/manageable_participatory_processes_for_user.rb +1 -1
  26. data/decidim-admin/app/views/decidim/admin/newsletters/_form.html.erb +5 -0
  27. data/decidim-admin/app/views/decidim/admin/newsletters/edit.html.erb +11 -0
  28. data/decidim-admin/app/views/decidim/admin/newsletters/index.html.erb +47 -0
  29. data/decidim-admin/app/views/decidim/admin/newsletters/new.html.erb +11 -0
  30. data/decidim-admin/app/views/decidim/admin/newsletters/show.html.erb +14 -0
  31. data/decidim-admin/app/views/decidim/admin/participatory_process_steps/_form.html.erb +1 -1
  32. data/decidim-admin/app/views/decidim/admin/participatory_processes/_form.html.erb +1 -1
  33. data/decidim-admin/app/views/decidim/admin/static_pages/_form.html.erb +1 -1
  34. data/decidim-admin/app/views/layouts/decidim/admin/_sidebar.html.erb +1 -0
  35. data/decidim-admin/config/locales/ca.yml +40 -0
  36. data/decidim-admin/config/locales/en.yml +40 -0
  37. data/decidim-admin/config/locales/es.yml +40 -0
  38. data/decidim-admin/config/routes.rb +7 -0
  39. data/decidim-admin/decidim-admin.gemspec +0 -1
  40. data/decidim-admin/lib/decidim/admin/engine.rb +1 -0
  41. data/decidim-admin/lib/decidim/admin/features/base_controller.rb +5 -1
  42. data/decidim-admin/spec/commands/create_newsletter_spec.rb +62 -0
  43. data/decidim-admin/spec/commands/deliver_newsletter_spec.rb +45 -0
  44. data/decidim-admin/spec/commands/destroy_participatory_process_step_spec.rb +12 -0
  45. data/decidim-admin/spec/commands/update_newsletter_spec.rb +64 -0
  46. data/decidim-admin/spec/features/admin_manages_newsletters_spec.rb +147 -0
  47. data/decidim-admin/spec/features/admin_manages_participatory_processes_spec.rb +1 -5
  48. data/decidim-admin/spec/features/static_pages_spec.rb +16 -0
  49. data/decidim-admin/spec/forms/newsletter_form_spec.rb +47 -0
  50. data/decidim-admin/spec/jobs/newsletter_delivery_job_spec.rb +25 -0
  51. data/decidim-admin/spec/jobs/newsletter_job_spec.rb +29 -0
  52. data/decidim-admin/spec/models/abilities/collaborator_user_spec.rb +66 -0
  53. data/decidim-admin/spec/organization_dashboard_constraint_spec.rb +55 -0
  54. data/decidim-admin/spec/queries/manageable_participatory_processes_for_user_spec.rb +8 -0
  55. data/decidim-admin/spec/shared/manage_processes_examples.rb +1 -5
  56. data/decidim-api/lib/decidim/api.rb +2 -7
  57. data/decidim-api/lib/decidim/api/{types/mutation.rb → mutation_type.rb} +0 -0
  58. data/decidim-api/lib/decidim/api/{types/query.rb → query_type.rb} +0 -0
  59. data/decidim-budgets/app/assets/javascripts/decidim/budgets/projects.js.es6 +4 -4
  60. data/decidim-budgets/app/commands/decidim/budgets/add_line_item.rb +4 -2
  61. data/decidim-budgets/app/commands/decidim/budgets/checkout.rb +7 -3
  62. data/decidim-budgets/app/models/decidim/budgets/order.rb +16 -1
  63. data/decidim-budgets/app/models/decidim/budgets/project.rb +16 -0
  64. data/decidim-budgets/app/views/decidim/budgets/line_items/update_budget.js.erb +7 -7
  65. data/decidim-budgets/app/views/decidim/budgets/projects/_budget_confirm.html.erb +27 -25
  66. data/decidim-budgets/app/views/decidim/budgets/projects/_budget_summary.html.erb +4 -13
  67. data/decidim-budgets/app/views/decidim/budgets/projects/_order_progress.html.erb +23 -21
  68. data/decidim-budgets/app/views/decidim/budgets/projects/_order_selected_projects.html.erb +25 -23
  69. data/decidim-budgets/app/views/decidim/budgets/projects/_order_total_budget.html.erb +3 -1
  70. data/decidim-budgets/app/views/decidim/budgets/projects/_project.html.erb +32 -30
  71. data/decidim-budgets/app/views/decidim/budgets/projects/_projects.html.erb +1 -3
  72. data/decidim-budgets/app/views/decidim/budgets/projects/index.html.erb +0 -4
  73. data/decidim-budgets/app/views/decidim/budgets/projects/show.html.erb +5 -6
  74. data/decidim-budgets/config/i18n-tasks.yml +1 -0
  75. data/decidim-budgets/config/locales/ca.yml +7 -2
  76. data/decidim-budgets/config/locales/en.yml +17 -6
  77. data/decidim-budgets/config/locales/es.yml +7 -2
  78. data/decidim-budgets/lib/decidim/budgets/feature.rb +2 -2
  79. data/decidim-budgets/spec/commands/add_line_item_spec.rb +16 -3
  80. data/decidim-budgets/spec/commands/cancel_order_spec.rb +7 -1
  81. data/decidim-budgets/spec/commands/checkout_spec.rb +9 -2
  82. data/decidim-budgets/spec/commands/remove_line_item_spec.rb +16 -5
  83. data/decidim-budgets/spec/features/orders_spec.rb +8 -2
  84. data/decidim-budgets/spec/models/order_spec.rb +31 -2
  85. data/decidim-budgets/spec/shared/admin_shared_context.rb +1 -1
  86. data/decidim-comments/README.md +1 -1
  87. data/decidim-comments/app/assets/javascripts/decidim/comments/bundle.js +0 -0
  88. data/decidim-comments/app/frontend/comments/add_comment_form.component.jsx +156 -93
  89. data/decidim-comments/app/frontend/comments/add_comment_form.component.test.jsx +36 -23
  90. data/decidim-comments/app/frontend/comments/add_comment_form.mutation.graphql +5 -3
  91. data/decidim-comments/app/frontend/comments/add_comment_form_commentable.fragment.graphql +4 -0
  92. data/decidim-comments/app/frontend/comments/add_comment_form_session.fragment.graphql +6 -0
  93. data/decidim-comments/app/frontend/comments/comment.component.jsx +11 -13
  94. data/decidim-comments/app/frontend/comments/comment.component.test.jsx +22 -21
  95. data/decidim-comments/app/frontend/comments/comment.fragment.graphql +4 -4
  96. data/decidim-comments/app/frontend/comments/comment_data.fragment.graphql +4 -3
  97. data/decidim-comments/app/frontend/comments/comment_order_selector.component.jsx +1 -1
  98. data/decidim-comments/app/frontend/comments/comment_thread.component.jsx +3 -3
  99. data/decidim-comments/app/frontend/comments/comment_thread.component.test.jsx +3 -3
  100. data/decidim-comments/app/frontend/comments/comment_thread.fragment.graphql +1 -1
  101. data/decidim-comments/app/frontend/comments/comments.component.jsx +47 -39
  102. data/decidim-comments/app/frontend/comments/comments.component.test.jsx +51 -38
  103. data/decidim-comments/app/frontend/comments/comments.query.graphql +10 -4
  104. data/decidim-comments/app/frontend/comments/down_vote_button.component.jsx +6 -3
  105. data/decidim-comments/app/frontend/comments/up_vote_button.component.jsx +7 -4
  106. data/decidim-comments/app/frontend/support/generate_comments_data.js +4 -4
  107. data/decidim-comments/app/models/decidim/comments/comment.rb +7 -9
  108. data/decidim-comments/app/queries/decidim/comments/{comments_with_replies.rb → sorted_comments.rb} +3 -8
  109. data/decidim-comments/app/types/decidim/comments/commentable_interface.rb +44 -0
  110. data/decidim-comments/app/types/decidim/comments/commentable_mutation_type.rb +29 -0
  111. data/decidim-comments/app/types/decidim/comments/commentable_type.rb +14 -0
  112. data/decidim-comments/config/locales/ca.yml +3 -1
  113. data/decidim-comments/config/locales/en.yml +5 -2
  114. data/decidim-comments/config/locales/es.yml +3 -1
  115. data/decidim-comments/lib/decidim/comments.rb +4 -0
  116. data/decidim-comments/{app/types/decidim/comments → lib/decidim/comments/api}/add_comment_type.rb +0 -0
  117. data/decidim-comments/{app/types/decidim/comments → lib/decidim/comments/api}/comment_mutation_type.rb +0 -0
  118. data/decidim-comments/{app/types/decidim/comments → lib/decidim/comments/api}/comment_type.rb +11 -17
  119. data/decidim-comments/lib/decidim/comments/commentable.rb +45 -0
  120. data/decidim-comments/lib/decidim/comments/comments_helper.rb +15 -10
  121. data/decidim-comments/lib/decidim/comments/mutation_extensions.rb +8 -16
  122. data/decidim-comments/lib/decidim/comments/query_extensions.rb +5 -8
  123. data/decidim-comments/lib/decidim/comments/test/factories.rb +3 -3
  124. data/decidim-comments/spec/commands/vote_comment_spec.rb +3 -1
  125. data/decidim-comments/spec/features/comments_spec.rb +28 -14
  126. data/decidim-comments/spec/features/notifications_spec.rb +1 -1
  127. data/decidim-comments/spec/helpers/comments_helper_spec.rb +4 -27
  128. data/decidim-comments/spec/models/comment_spec.rb +7 -11
  129. data/decidim-comments/spec/models/comment_vote_spec.rb +3 -1
  130. data/decidim-comments/spec/models/seed_spec.rb +3 -4
  131. data/decidim-comments/spec/queries/{comments_with_replies_spec.rb → sorted_comments_spec.rb} +12 -29
  132. data/decidim-comments/spec/types/comment_type_spec.rb +23 -17
  133. data/decidim-comments/spec/types/commentable_mutation_type_spec.rb +34 -0
  134. data/decidim-comments/spec/types/commentable_type_spec.rb +48 -0
  135. data/decidim-comments/spec/types/mutation_type_spec.rb +5 -22
  136. data/decidim-comments/spec/types/query_type_spec.rb +0 -24
  137. data/decidim-dev/config/i18n-tasks.yml +4 -0
  138. data/decidim-dev/decidim-dev.gemspec +1 -1
  139. data/decidim-dev/lib/decidim/dev/test/rspec_support/action_mailer.rb +10 -4
  140. data/decidim-dev/lib/decidim/dev/test/rspec_support/feature.rb +6 -5
  141. data/decidim-dev/lib/decidim/dev/test/rspec_support/i18n.rb +0 -1
  142. data/decidim-meetings/app/assets/javascripts/decidim/meetings/map.js.es6.erb +8 -3
  143. data/decidim-meetings/app/assets/stylesheets/decidim/meetings/map.css +3 -1
  144. data/decidim-meetings/app/controllers/decidim/meetings/meetings_controller.rb +2 -2
  145. data/decidim-meetings/app/forms/decidim/meetings/admin/close_meeting_form.rb +2 -1
  146. data/decidim-meetings/app/helpers/decidim/meetings/map_helper.rb +1 -0
  147. data/decidim-meetings/app/services/decidim/meetings/meeting_search.rb +7 -3
  148. data/decidim-meetings/app/views/decidim/meetings/meetings/_datetime.html.erb +1 -1
  149. data/decidim-meetings/app/views/decidim/meetings/meetings/_filters.html.erb +5 -5
  150. data/decidim-meetings/app/views/decidim/meetings/meetings/_linked_meetings.html.erb +1 -1
  151. data/decidim-meetings/app/views/decidim/meetings/meetings/index.html.erb +1 -5
  152. data/decidim-meetings/app/views/decidim/meetings/meetings/show.html.erb +16 -9
  153. data/decidim-meetings/config/locales/ca.yml +2 -3
  154. data/decidim-meetings/config/locales/en.yml +2 -3
  155. data/decidim-meetings/config/locales/es.yml +2 -3
  156. data/decidim-meetings/spec/features/explore_meetings_spec.rb +75 -24
  157. data/decidim-meetings/spec/forms/close_meeting_form_spec.rb +1 -1
  158. data/decidim-meetings/spec/services/meeting_search_spec.rb +15 -12
  159. data/decidim-meetings/vendor/assets/javascripts/leaflet.markercluster.js +7 -0
  160. data/decidim-meetings/vendor/assets/stylesheets/MarkerCluster.Default.css +60 -0
  161. data/decidim-meetings/vendor/assets/stylesheets/MarkerCluster.css +14 -0
  162. data/decidim-pages/app/models/decidim/pages/page.rb +22 -0
  163. data/decidim-pages/app/views/decidim/pages/application/show.html.erb +2 -6
  164. data/decidim-pages/config/locales/ca.yml +2 -2
  165. data/decidim-pages/config/locales/en.yml +2 -2
  166. data/decidim-pages/config/locales/es.yml +2 -2
  167. data/decidim-pages/lib/decidim/pages/feature.rb +2 -2
  168. data/decidim-pages/spec/features/page_show_spec.rb +0 -33
  169. data/decidim-proposals/app/controllers/decidim/proposals/admin/proposal_answers_controller.rb +2 -0
  170. data/decidim-proposals/app/controllers/decidim/proposals/admin/proposals_controller.rb +2 -0
  171. data/decidim-proposals/app/models/decidim/proposals/abilities/admin_user.rb +45 -0
  172. data/decidim-proposals/app/models/decidim/proposals/abilities/process_admin_user.rb +57 -0
  173. data/decidim-proposals/app/models/decidim/proposals/proposal.rb +21 -0
  174. data/decidim-proposals/app/views/decidim/proposals/admin/proposals/_form.html.erb +1 -1
  175. data/decidim-proposals/app/views/decidim/proposals/admin/proposals/index.html.erb +16 -10
  176. data/decidim-proposals/app/views/decidim/proposals/proposal_votes/update_buttons_and_counters.js.erb +4 -4
  177. data/decidim-proposals/app/views/decidim/proposals/proposals/_filters.html.erb +7 -3
  178. data/decidim-proposals/app/views/decidim/proposals/proposals/_proposal.html.erb +2 -6
  179. data/decidim-proposals/app/views/decidim/proposals/proposals/_remaining_votes_count.html.erb +3 -1
  180. data/decidim-proposals/app/views/decidim/proposals/proposals/_tags.html.erb +1 -1
  181. data/decidim-proposals/app/views/decidim/proposals/proposals/_vote_button.html.erb +23 -21
  182. data/decidim-proposals/app/views/decidim/proposals/proposals/_votes_count.html.erb +9 -6
  183. data/decidim-proposals/app/views/decidim/proposals/proposals/_votes_limit.html.erb +1 -3
  184. data/decidim-proposals/app/views/decidim/proposals/proposals/index.html.erb +0 -4
  185. data/decidim-proposals/app/views/decidim/proposals/proposals/new.html.erb +1 -1
  186. data/decidim-proposals/app/views/decidim/proposals/proposals/show.html.erb +2 -6
  187. data/decidim-proposals/config/locales/ca.yml +8 -1
  188. data/decidim-proposals/config/locales/en.yml +8 -1
  189. data/decidim-proposals/config/locales/es.yml +8 -1
  190. data/decidim-proposals/lib/decidim/proposals/admin_engine.rb +7 -0
  191. data/decidim-proposals/lib/decidim/proposals/feature.rb +6 -2
  192. data/decidim-proposals/spec/features/proposals_spec.rb +226 -40
  193. data/decidim-proposals/spec/models/decidim/proposals/abilities/admin_user_spec.rb +62 -0
  194. data/decidim-proposals/spec/models/decidim/proposals/abilities/process_admin_user_spec.rb +63 -0
  195. data/decidim-proposals/spec/shared/manage_proposals_examples.rb +161 -50
  196. data/decidim-results/app/models/decidim/results/result.rb +21 -0
  197. data/decidim-results/app/views/decidim/results/results/index.html.erb +0 -4
  198. data/decidim-results/app/views/decidim/results/results/show.html.erb +2 -8
  199. data/decidim-results/config/i18n-tasks.yml +1 -0
  200. data/decidim-results/config/locales/ca.yml +5 -2
  201. data/decidim-results/config/locales/en.yml +5 -2
  202. data/decidim-results/config/locales/es.yml +5 -2
  203. data/decidim-results/lib/decidim/results/feature.rb +2 -2
  204. data/decidim-results/spec/services/result_stats_calculator_spec.rb +2 -2
  205. data/decidim-results/spec/shared/admin_shared_context.rb +1 -1
  206. data/decidim-system/config/i18n-tasks.yml +1 -1
  207. data/package.json +50 -51
  208. data/yarn.lock +198 -151
  209. metadata +69 -36
  210. data/decidim-admin/spec/features/admin_access_control.rb +0 -52
  211. data/decidim-api/lib/decidim/api/types/author_interface.rb +0 -13
  212. data/decidim-api/lib/decidim/api/types/localized_string.rb +0 -13
  213. data/decidim-api/lib/decidim/api/types/translated_field.rb +0 -44
  214. data/decidim-api/spec/types/localized_string_type_spec.rb +0 -31
  215. data/decidim-api/spec/types/translated_field_type_spec.rb +0 -69
  216. data/decidim-comments/app/frontend/comments/add_comment_form.fragment.graphql +0 -6
@@ -8,8 +8,10 @@ import generateUserGroupData from '../support/generate_user_group_data';
8
8
 
9
9
  describe("<AddCommentForm />", () => {
10
10
  let session = null;
11
- const commentableId = "1";
12
- const commentableType = "Decidim::ParticipatoryProcess";
11
+ const commentable = {
12
+ id: "1",
13
+ type: "Decidim::DummyResource"
14
+ };
13
15
  const addCommentStub = () => {
14
16
  return null;
15
17
  }
@@ -22,50 +24,50 @@ describe("<AddCommentForm />", () => {
22
24
  });
23
25
 
24
26
  it("should render a div with class add-comment", () => {
25
- const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} />);
27
+ const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
26
28
  expect(wrapper.find('div.add-comment')).to.present();
27
29
  });
28
30
 
29
31
  it("should have a reference to body textarea", () => {
30
- const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} />);
32
+ const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
31
33
  expect(wrapper.instance().bodyTextArea).to.be.ok;
32
34
  });
33
35
 
34
36
  it("should initialize with a state property disabled as true", () => {
35
- const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} />);
37
+ const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
36
38
  expect(wrapper).to.have.state('disabled', true);
37
39
  });
38
40
 
39
41
  it("should have a default prop showTitle as true", () => {
40
- const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} />);
42
+ const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
41
43
  expect(wrapper).to.have.prop('showTitle').equal(true);
42
44
  });
43
45
 
44
46
  it("should not render the title if prop showTitle is false", () => {
45
- const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} showTitle={false} />);
47
+ const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} showTitle={false} />);
46
48
  expect(wrapper.find('h5.section-heading')).not.to.be.present();
47
49
  });
48
50
 
49
51
  it("should have a default prop submitButtonClassName as 'button button--sc'", () => {
50
- const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} />);
52
+ const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
51
53
  expect(wrapper).to.have.prop('submitButtonClassName').equal('button button--sc');
52
54
  });
53
55
 
54
56
  it("should have a default prop maxLength of 1000", () => {
55
- const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} />);
57
+ const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
56
58
  expect(wrapper).to.have.prop('maxLength').equal(1000);
57
59
  });
58
60
 
59
61
 
60
62
  it("should use prop submitButtonClassName as a className prop for submit button", () => {
61
- const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} submitButtonClassName="button small hollow" />);
63
+ const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} submitButtonClassName="button small hollow" />);
62
64
  expect(wrapper.find('input[type="submit"]')).to.have.className('button');
63
65
  expect(wrapper.find('input[type="submit"]')).to.have.className('small');
64
66
  expect(wrapper.find('input[type="submit"]')).to.have.className('hollow');
65
67
  });
66
68
 
67
69
  it("should enable the submit button if textarea is not blank", () => {
68
- const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} />);
70
+ const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
69
71
  wrapper.find('textarea').simulate('change', {
70
72
  target: {
71
73
  value: 'This is a comment'
@@ -75,7 +77,7 @@ describe("<AddCommentForm />", () => {
75
77
  });
76
78
 
77
79
  it("should disable the submit button if textarea is blank", () => {
78
- const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} />);
80
+ const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
79
81
  wrapper.find('textarea').simulate('change', {
80
82
  target: {
81
83
  value: 'This will be deleted'
@@ -90,7 +92,7 @@ describe("<AddCommentForm />", () => {
90
92
  });
91
93
 
92
94
  it("should not render a div with class 'opinion-toggle'", () => {
93
- const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} />);
95
+ const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
94
96
  expect(wrapper.find('.opinion-toggle')).not.to.be.present();
95
97
  });
96
98
 
@@ -103,7 +105,7 @@ describe("<AddCommentForm />", () => {
103
105
  beforeEach(() => {
104
106
  addComment = sinon.spy();
105
107
  onCommentAdded = sinon.spy();
106
- wrapper = mount(<AddCommentForm addComment={addComment} session={session} commentableId={commentableId} commentableType={commentableType} onCommentAdded={onCommentAdded} />);
108
+ wrapper = mount(<AddCommentForm addComment={addComment} session={session} commentable={commentable} onCommentAdded={onCommentAdded} />);
107
109
  message = 'This will be submitted';
108
110
  wrapper.instance().bodyTextArea.value = message;
109
111
  });
@@ -131,25 +133,25 @@ describe("<AddCommentForm />", () => {
131
133
  });
132
134
 
133
135
  it("should initialize state with a property alignment and value 0", () => {
134
- const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} arguable />);
136
+ const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} arguable />);
135
137
  expect(wrapper).to.have.state('alignment').equal(0);
136
138
  });
137
139
 
138
140
  describe("when receiving an optional prop arguable with value true", () => {
139
141
  it("should render a div with class 'opinion-toggle'", () => {
140
- const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} arguable />);
142
+ const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} arguable />);
141
143
  expect(wrapper.find('.opinion-toggle')).to.be.present();
142
144
  });
143
145
 
144
146
  it("should set state alignment to 1 if user clicks ok button and change its class", () => {
145
- const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} arguable />);
147
+ const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} arguable />);
146
148
  wrapper.find('.opinion-toggle--ok').simulate('click');
147
149
  expect(wrapper.find('.opinion-toggle--ok')).to.have.className('is-active');
148
150
  expect(wrapper).to.have.state('alignment').equal(1);
149
151
  });
150
152
 
151
153
  it("should set state alignment to -11 if user clicks ko button and change its class", () => {
152
- const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} arguable />);
154
+ const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} arguable />);
153
155
  wrapper.find('.opinion-toggle--ko').simulate('click');
154
156
  expect(wrapper.find('.opinion-toggle--ko')).to.have.className('is-active');
155
157
  expect(wrapper).to.have.state('alignment').equal(-1);
@@ -162,7 +164,7 @@ describe("<AddCommentForm />", () => {
162
164
 
163
165
  beforeEach(() => {
164
166
  addComment = sinon.spy();
165
- wrapper = mount(<AddCommentForm addComment={addComment} session={session} commentableId={commentableId} commentableType={commentableType} arguable />);
167
+ wrapper = mount(<AddCommentForm addComment={addComment} session={session} commentable={commentable} arguable />);
166
168
  message = 'This will be submitted';
167
169
  wrapper.instance().bodyTextArea.value = message;
168
170
  });
@@ -190,12 +192,12 @@ describe("<AddCommentForm />", () => {
190
192
  });
191
193
 
192
194
  it("should have a reference to user_group_id select", () => {
193
- const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} />);
195
+ const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
194
196
  expect(wrapper.instance().userGroupIdSelect).to.be.ok;
195
197
  });
196
198
 
197
199
  it("should render a select with option tags for each verified user group", () => {
198
- const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentableId={commentableId} commentableType={commentableType} />);
200
+ const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
199
201
  expect(wrapper.find('select')).to.have.exactly(3).descendants('option');
200
202
  });
201
203
 
@@ -207,7 +209,7 @@ describe("<AddCommentForm />", () => {
207
209
 
208
210
  beforeEach(() => {
209
211
  addComment = sinon.spy();
210
- wrapper = mount(<AddCommentForm addComment={addComment} session={session} commentableId={commentableId} commentableType={commentableType} />);
212
+ wrapper = mount(<AddCommentForm addComment={addComment} session={session} commentable={commentable} />);
211
213
  message = 'This will be submitted';
212
214
  userGroupId = session.verifiedUserGroups[1].id;
213
215
  wrapper.instance().bodyTextArea.value = message;
@@ -230,5 +232,16 @@ describe("<AddCommentForm />", () => {
230
232
  });
231
233
  });
232
234
  });
233
- })
235
+ });
236
+
237
+ describe("when session is null", () => {
238
+ beforeEach(() => {
239
+ session = null;
240
+ });
241
+
242
+ it("display a message to sign in or sign up", () => {
243
+ const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
244
+ expect(wrapper.find('span')).to.include.text("sign up");
245
+ });
246
+ });
234
247
  });
@@ -1,5 +1,7 @@
1
1
  mutation addComment($commentableId: String!, $commentableType: String!, $body: String!, $alignment: Int, $userGroupId: ID) {
2
- addComment(commentableId: $commentableId, commentableType: $commentableType, body: $body, alignment: $alignment, userGroupId: $userGroupId) {
3
- ...CommentThread
2
+ commentable(id: $commentableId, type: $commentableType) {
3
+ addComment(body: $body, alignment: $alignment, userGroupId: $userGroupId) {
4
+ ...CommentThread
5
+ }
4
6
  }
5
- }
7
+ }
@@ -0,0 +1,4 @@
1
+ fragment AddCommentFormCommentable on Commentable {
2
+ id
3
+ type
4
+ }
@@ -0,0 +1,6 @@
1
+ fragment AddCommentFormSession on Session {
2
+ verifiedUserGroups {
3
+ id
4
+ name
5
+ }
6
+ }
@@ -68,10 +68,10 @@ class Comment extends Component {
68
68
  * @returns {Void|DOMElement} - Render the reply button or not if user can reply
69
69
  */
70
70
  _renderReplyButton() {
71
- const { comment: { canHaveReplies }, session } = this.props;
71
+ const { comment: { acceptsNewComments }, session } = this.props;
72
72
  const { showReplyForm } = this.state;
73
73
 
74
- if (session && canHaveReplies) {
74
+ if (session && acceptsNewComments) {
75
75
  return (
76
76
  <button
77
77
  className="comment__reply muted-link"
@@ -92,12 +92,11 @@ class Comment extends Component {
92
92
  * @returns {Void|DOMElement} - Render the reply button or not if user can reply
93
93
  */
94
94
  _renderAdditionalReplyButton() {
95
- const { comment: { canHaveReplies, hasReplies }, session, isRootComment } = this.props;
95
+ const { comment: { acceptsNewComments, hasComments }, session, isRootComment } = this.props;
96
96
  const { showReplyForm } = this.state;
97
97
 
98
- if (session && canHaveReplies) {
99
- if (hasReplies && isRootComment) {
100
-
98
+ if (session && acceptsNewComments) {
99
+ if (hasComments && isRootComment) {
101
100
  return (
102
101
  <div className="comment__additionalreply">
103
102
  <button
@@ -135,23 +134,23 @@ class Comment extends Component {
135
134
  }
136
135
 
137
136
  /**
138
- * Render comment replies alternating the css class
137
+ * Render comment's comments alternating the css class
139
138
  * @private
140
- * @returns {Void|DomElement} - A wrapper element with comment replies inside
139
+ * @returns {Void|DomElement} - A wrapper element with comment's comments inside
141
140
  */
142
141
  _renderReplies() {
143
- const { comment: { id, replies }, session, votable, articleClassName } = this.props;
142
+ const { comment: { id, hasComments, comments }, session, votable, articleClassName } = this.props;
144
143
  let replyArticleClassName = 'comment comment--nested';
145
144
 
146
145
  if (articleClassName === 'comment comment--nested') {
147
146
  replyArticleClassName = `${replyArticleClassName} comment--nested--alt`;
148
147
  }
149
148
 
150
- if (replies) {
149
+ if (hasComments) {
151
150
  return (
152
151
  <div>
153
152
  {
154
- replies.map((reply) => (
153
+ comments.map((reply) => (
155
154
  <Comment
156
155
  key={`comment_${id}_reply_${reply.id}`}
157
156
  comment={reply}
@@ -180,9 +179,8 @@ class Comment extends Component {
180
179
  if (showReplyForm) {
181
180
  return (
182
181
  <AddCommentForm
183
- commentableId={comment.id}
184
- commentableType="Decidim::Comments::Comment"
185
182
  session={session}
183
+ commentable={comment}
186
184
  showTitle={false}
187
185
  submitButtonClassName="button small hollow"
188
186
  onCommentAdded={() => this.setState({ showReplyForm: false })}
@@ -27,7 +27,7 @@ describe("<Comment />", () => {
27
27
 
28
28
  beforeEach(() => {
29
29
  let commentsData = generateCommentsData(1);
30
- commentsData[0].replies = generateCommentsData(3);
30
+ commentsData[0].comments = generateCommentsData(3);
31
31
 
32
32
  const fragment = gql`
33
33
  ${commentFragment}
@@ -77,50 +77,40 @@ describe("<Comment />", () => {
77
77
  expect(wrapper.find(AddCommentForm)).not.to.be.present();
78
78
  wrapper.find('button.comment__reply').simulate('click');
79
79
  expect(wrapper.find(AddCommentForm)).to.have.prop('session').deep.equal(session);
80
- expect(wrapper.find(AddCommentForm)).to.have.prop('commentableId').equal(comment.id);
81
- expect(wrapper.find(AddCommentForm)).to.have.prop('commentableType').equal("Decidim::Comments::Comment");
80
+ expect(wrapper.find(AddCommentForm)).to.have.prop('commentable').deep.equal(comment);
82
81
  expect(wrapper.find(AddCommentForm)).to.have.prop('showTitle').equal(false);
83
82
  expect(wrapper.find(AddCommentForm)).to.have.prop('submitButtonClassName').equal('button small hollow');
84
83
  });
85
84
 
86
- it("should not render the reply button if the comment cannot have replies", () => {
87
- comment.canHaveReplies = false;
88
- const wrapper = shallow(<Comment comment={comment} session={session} />);
89
- expect(wrapper.find('button.comment__reply')).not.to.be.present();
90
- });
91
-
92
- it("should not render the additional reply button if the parent comment has no replies and isRootcomment", () => {
93
- comment.canHaveReplies = true;
94
- comment.hasReplies = false;
85
+ it("should not render the additional reply button if the parent comment has no comments and isRootcomment", () => {
86
+ comment.hasComments = false;
95
87
  const wrapper = shallow(<Comment comment={comment} session={session} isRootComment />);
96
88
  expect(wrapper.find('div.comment__additionalreply')).not.to.be.present();
97
89
  });
98
90
 
99
- it("should not render the additional reply button if the parent comment has replies and not isRootcomment", () => {
100
- comment.canHaveReplies = true;
101
- comment.hasReplies = true;
91
+ it("should not render the additional reply button if the parent comment has comments and not isRootcomment", () => {
92
+ comment.hasComments = true;
102
93
  const wrapper = shallow(<Comment comment={comment} session={session} />);
103
94
  expect(wrapper.find('div.comment__additionalreply')).not.to.be.present();
104
95
  });
105
96
 
106
- it("should render the additional reply button if the parent comment has replies and isRootcomment", () => {
107
- comment.canHaveReplies = true;
108
- comment.hasReplies = true;
97
+ it("should render the additional reply button if the parent comment has comments and isRootcomment", () => {
98
+ comment.hasComments = true;
109
99
  const wrapper = shallow(<Comment comment={comment} session={session} isRootComment />);
110
100
  expect(wrapper.find('div.comment__additionalreply')).to.be.present();
111
101
  });
112
102
 
113
- it("should render comment replies a separate Comment components", () => {
103
+ it("should render comment's comments as a separate Comment components", () => {
114
104
  const wrapper = shallow(<Comment comment={comment} session={session} votable />);
115
105
  wrapper.find(Comment).forEach((node, idx) => {
116
- expect(node).to.have.prop("comment").deep.equal(comment.replies[idx]);
106
+ expect(node).to.have.prop("comment").deep.equal(comment.comments[idx]);
117
107
  expect(node).to.have.prop("session").deep.equal(session);
118
108
  expect(node).to.have.prop("articleClassName").equal("comment comment--nested")
119
109
  expect(node).to.have.prop("votable").equal(true);
120
110
  });
121
111
  });
122
112
 
123
- it("should render comment replies with articleClassName as 'comment comment--nested comment--nested--alt' when articleClassName is 'comment comment--nested'", () => {
113
+ it("should render comment's comments with articleClassName as 'comment comment--nested comment--nested--alt' when articleClassName is 'comment comment--nested'", () => {
124
114
  const wrapper = shallow(<Comment comment={comment} session={session} articleClassName="comment comment--nested" />);
125
115
  wrapper.find(Comment).forEach((node) => {
126
116
  expect(node).to.have.prop("articleClassName").equal("comment comment--nested comment--nested--alt")
@@ -137,6 +127,17 @@ describe("<Comment />", () => {
137
127
  expect(wrapper).to.have.prop("isRootComment").equal(false);
138
128
  });
139
129
 
130
+ describe("when the comment cannot accept new comments", () => {
131
+ beforeEach(() => {
132
+ comment.acceptsNewComments = false;
133
+ });
134
+
135
+ it("should not render the reply button", () => {
136
+ const wrapper = shallow(<Comment comment={comment} session={session} />);
137
+ expect(wrapper.find('button.comment__reply')).not.to.be.present();
138
+ });
139
+ })
140
+
140
141
  describe("when user is not logged in", () => {
141
142
  beforeEach(() => {
142
143
  session = null;
@@ -1,12 +1,12 @@
1
1
  fragment Comment on Comment {
2
2
  ...CommentData
3
- replies {
3
+ comments {
4
4
  ...CommentData
5
- replies {
5
+ comments {
6
6
  ...CommentData
7
- replies {
7
+ comments {
8
8
  ...CommentData
9
- }
9
+ }
10
10
  }
11
11
  }
12
12
  }
@@ -1,13 +1,14 @@
1
1
  fragment CommentData on Comment {
2
2
  id
3
+ type
3
4
  body
4
5
  createdAt
5
6
  author {
6
- name,
7
+ name
7
8
  avatarUrl
8
9
  }
9
- hasReplies
10
- canHaveReplies
10
+ hasComments
11
+ acceptsNewComments
11
12
  alignment
12
13
  ...UpVote
13
14
  ...DownVote
@@ -26,7 +26,7 @@ class CommentOrderSelector extends Component {
26
26
  return (
27
27
  <div className="order-by__dropdown order-by__dropdown--right">
28
28
  <span className="order-by__text">{ I18n.t("components.comment_order_selector.title") }</span>
29
- <ul className="dropdown menu" data-dropdown-menu>
29
+ <ul className="dropdown menu" data-dropdown-menu data-close-on-click-inside="false">
30
30
  <li>
31
31
  <a>{ I18n.t(`components.comment_order_selector.order.${orderBy}`) }</a>
32
32
  <ul className="menu">
@@ -33,14 +33,14 @@ class CommentThread extends Component {
33
33
  }
34
34
 
35
35
  /**
36
- * Render conversation title if comment has replies
36
+ * Render conversation title if comment has commments
37
37
  * @private
38
38
  * @returns {Void|DOMElement} - The conversation's title
39
39
  */
40
40
  _renderTitle() {
41
- const { comment: { author, hasReplies } } = this.props;
41
+ const { comment: { author, hasComments } } = this.props;
42
42
 
43
- if (hasReplies) {
43
+ if (hasComments) {
44
44
  return (
45
45
  <h6 className="comment-thread__title">
46
46
  { I18n.t("components.comment_thread.title", { authorName: author.name }) }
@@ -41,16 +41,16 @@ describe('<CommentThread />', () => {
41
41
  comment = filter(fragment, commentsData[0]);
42
42
  });
43
43
 
44
- describe("when comment doesn't have replies", () => {
44
+ describe("when comment doesn't have comments", () => {
45
45
  it("should not render a title with author name", () => {
46
46
  const wrapper = shallow(<CommentThread comment={comment} session={session} />);
47
47
  expect(wrapper.find('h6.comment-thread__title')).not.to.present();
48
48
  });
49
49
  });
50
50
 
51
- describe("when comment does have replies", () => {
51
+ describe("when comment does has comments", () => {
52
52
  beforeEach(() => {
53
- comment.hasReplies = true;
53
+ comment.hasComments = true;
54
54
  });
55
55
 
56
56
  it("should render a h6 comment-thread__title with author name", () => {
@@ -2,6 +2,6 @@ fragment CommentThread on Comment {
2
2
  author {
3
3
  name
4
4
  }
5
- hasReplies,
5
+ hasComments
6
6
  ...Comment
7
7
  }