decidim 0.3.2 → 0.4.0

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 (198) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/Gemfile.lock +49 -55
  4. data/README.md +2 -1
  5. data/Rakefile +4 -4
  6. data/decidim-admin/app/assets/stylesheets/decidim/admin/extra/_label-required.scss +3 -0
  7. data/decidim-admin/app/assets/stylesheets/decidim/admin/extra/_title_bar.scss +57 -1
  8. data/decidim-admin/app/commands/decidim/admin/create_participatory_process_admin.rb +28 -7
  9. data/decidim-admin/app/commands/decidim/admin/create_participatory_process_step.rb +2 -1
  10. data/decidim-admin/app/commands/decidim/admin/destroy_participatory_process_step.rb +5 -2
  11. data/decidim-admin/app/commands/decidim/admin/update_feature.rb +1 -0
  12. data/decidim-admin/app/commands/decidim/admin/update_organization.rb +10 -5
  13. data/decidim-admin/app/commands/decidim/admin/update_participatory_process.rb +4 -2
  14. data/decidim-admin/app/controllers/decidim/admin/application_controller.rb +2 -0
  15. data/decidim-admin/app/controllers/decidim/admin/concerns/has_attachments.rb +10 -1
  16. data/decidim-admin/app/controllers/decidim/admin/concerns/participatory_process_admin.rb +0 -5
  17. data/decidim-admin/app/controllers/decidim/admin/features/base_controller.rb +0 -1
  18. data/decidim-admin/app/controllers/decidim/admin/moderations_controller.rb +7 -4
  19. data/decidim-admin/app/controllers/decidim/admin/organization_controller.rb +9 -3
  20. data/decidim-admin/app/controllers/decidim/admin/participatory_process_user_roles_controller.rb +17 -0
  21. data/decidim-admin/app/controllers/decidim/admin/participatory_processes_controller.rb +11 -3
  22. data/decidim-admin/app/forms/decidim/admin/feature_form.rb +6 -0
  23. data/decidim-admin/app/forms/decidim/admin/organization_form.rb +5 -0
  24. data/decidim-admin/app/forms/decidim/admin/participatory_process_copy_form.rb +2 -3
  25. data/decidim-admin/app/forms/decidim/admin/participatory_process_form.rb +2 -0
  26. data/decidim-admin/app/forms/decidim/admin/static_page_form.rb +6 -0
  27. data/decidim-admin/app/helpers/decidim/admin/menu_helper.rb +1 -1
  28. data/decidim-admin/app/jobs/decidim/admin/newsletter_job.rb +9 -5
  29. data/decidim-admin/app/views/decidim/admin/attachments/_form.html.erb +1 -12
  30. data/decidim-admin/app/views/decidim/admin/features/_feature.html.erb +2 -2
  31. data/decidim-admin/app/views/decidim/admin/features/_form.html.erb +18 -0
  32. data/decidim-admin/app/views/decidim/admin/moderations/_report.html.erb +2 -2
  33. data/decidim-admin/app/views/decidim/admin/organization/_form.html.erb +5 -35
  34. data/decidim-admin/app/views/decidim/admin/participatory_process_groups/_form.html.erb +1 -1
  35. data/decidim-admin/app/views/decidim/admin/participatory_process_user_roles/index.html.erb +16 -0
  36. data/decidim-admin/app/views/decidim/admin/participatory_processes/_form.html.erb +2 -14
  37. data/decidim-admin/app/views/layouts/decidim/admin/_title_bar.html.erb +26 -19
  38. data/decidim-admin/app/views/layouts/decidim/admin/participatory_process.html.erb +2 -2
  39. data/decidim-admin/bin/rails +2 -2
  40. data/decidim-admin/config/i18n-tasks.yml +2 -0
  41. data/decidim-admin/config/locales/ca.yml +9 -5
  42. data/decidim-admin/config/locales/en.yml +9 -5
  43. data/decidim-admin/config/locales/es.yml +11 -5
  44. data/decidim-admin/config/locales/eu.yml +0 -5
  45. data/decidim-admin/config/locales/fr.yml +18 -23
  46. data/decidim-admin/config/locales/it.yml +0 -5
  47. data/decidim-admin/config/routes.rb +5 -3
  48. data/decidim-admin/decidim-admin.gemspec +2 -2
  49. data/decidim-admin/lib/decidim/admin/test/manage_attachments_examples.rb +1 -2
  50. data/decidim-admin/spec/commands/create_participatory_process_admin_spec.rb +42 -26
  51. data/decidim-admin/spec/commands/create_participatory_process_spec.rb +2 -1
  52. data/decidim-admin/spec/commands/create_participatory_process_step_spec.rb +56 -0
  53. data/decidim-admin/spec/commands/destroy_participatory_process_step_spec.rb +2 -2
  54. data/decidim-admin/spec/commands/update_feature_spec.rb +6 -0
  55. data/decidim-admin/spec/controllers/participatory_processes_controller_spec.rb +3 -6
  56. data/decidim-admin/spec/features/admin_copy_participatory_process_spec.rb +9 -9
  57. data/decidim-admin/spec/features/admin_manages_features_spec.rb +32 -0
  58. data/decidim-admin/spec/features/admin_manages_participatory_processes_spec.rb +3 -4
  59. data/decidim-admin/spec/forms/static_page_form_spec.rb +12 -0
  60. data/decidim-admin/spec/jobs/newsletter_job_spec.rb +3 -0
  61. data/decidim-admin/spec/shared/manage_process_admins_examples.rb +22 -0
  62. data/decidim-admin/spec/shared/manage_processes_examples.rb +6 -0
  63. data/decidim-admin/spec/spec_helper.rb +4 -0
  64. data/decidim-api/bin/rails +2 -2
  65. data/decidim-api/decidim-api.gemspec +3 -3
  66. data/decidim-api/spec/spec_helper.rb +4 -0
  67. data/decidim-api/spec/types/query_type_spec.rb +2 -2
  68. data/decidim-budgets/app/models/decidim/budgets/project.rb +5 -0
  69. data/decidim-budgets/bin/rails +2 -2
  70. data/decidim-budgets/config/locales/fr.yml +2 -2
  71. data/decidim-budgets/decidim-budgets.gemspec +2 -2
  72. data/decidim-budgets/lib/decidim/budgets/feature.rb +1 -1
  73. data/decidim-budgets/spec/spec_helper.rb +4 -0
  74. data/decidim-comments/app/assets/javascripts/decidim/comments/bundle.js +0 -0
  75. data/decidim-comments/app/commands/decidim/comments/create_comment.rb +10 -14
  76. data/decidim-comments/app/frontend/application/application.component.tsx +1 -1
  77. data/decidim-comments/app/frontend/comments/add_comment_form.component.test.tsx +33 -26
  78. data/decidim-comments/app/frontend/comments/add_comment_form.component.tsx +109 -83
  79. data/decidim-comments/app/frontend/comments/comment.component.test.tsx +29 -24
  80. data/decidim-comments/app/frontend/comments/comment.component.tsx +12 -5
  81. data/decidim-comments/app/frontend/comments/comment_thread.component.test.tsx +12 -7
  82. data/decidim-comments/app/frontend/comments/comment_thread.component.tsx +7 -2
  83. data/decidim-comments/app/frontend/comments/comments.component.tsx +26 -15
  84. data/decidim-comments/app/frontend/comments/down_vote_button.component.test.tsx +9 -4
  85. data/decidim-comments/app/frontend/comments/down_vote_button.component.tsx +56 -37
  86. data/decidim-comments/app/frontend/comments/up_vote_button.component.test.tsx +9 -4
  87. data/decidim-comments/app/frontend/comments/up_vote_button.component.tsx +31 -16
  88. data/decidim-comments/app/frontend/comments/vote_button.component.tsx +3 -0
  89. data/decidim-comments/app/mailers/decidim/comments/comment_notification_mailer.rb +8 -6
  90. data/decidim-comments/app/models/decidim/comments/comment.rb +13 -1
  91. data/decidim-comments/app/views/decidim/comments/comment_notification_mailer/comment_created.html.erb +1 -1
  92. data/decidim-comments/app/views/decidim/comments/comment_notification_mailer/reply_created.html.erb +1 -1
  93. data/decidim-comments/bin/rails +2 -2
  94. data/decidim-comments/config/locales/ca.yml +2 -0
  95. data/decidim-comments/config/locales/en.yml +2 -0
  96. data/decidim-comments/config/locales/es.yml +2 -0
  97. data/decidim-comments/config/locales/fr.yml +2 -2
  98. data/decidim-comments/decidim-comments.gemspec +3 -3
  99. data/decidim-comments/lib/decidim/comments/commentable.rb +1 -0
  100. data/decidim-comments/spec/commands/create_comment_spec.rb +22 -54
  101. data/decidim-comments/spec/features/notifications_spec.rb +2 -6
  102. data/decidim-comments/spec/mailers/comment_notification_mailer_spec.rb +5 -4
  103. data/decidim-comments/spec/models/comment_spec.rb +32 -2
  104. data/decidim-comments/spec/shared/author_localised_email.rb +2 -3
  105. data/decidim-comments/spec/spec_helper.rb +4 -0
  106. data/decidim-dev/decidim-dev.gemspec +3 -4
  107. data/decidim-dev/lib/decidim/dev.rb +23 -1
  108. data/decidim-dev/lib/decidim/dev/common_rake.rb +3 -0
  109. data/decidim-dev/lib/decidim/dev/railtie.rb +3 -3
  110. data/decidim-dev/lib/decidim/dev/test/base_spec_helper.rb +4 -3
  111. data/decidim-dev/lib/decidim/dev/test/rspec_support/capybara.rb +3 -0
  112. data/decidim-dev/lib/decidim/dev/test/rspec_support/feature.rb +8 -0
  113. data/decidim-dev/lib/decidim/dev/test/rspec_support/feature_context.rb +4 -2
  114. data/decidim-dev/lib/decidim/dev/test/rspec_support/geocoder.rb +7 -2
  115. data/decidim-dev/lib/decidim/dev/test/rspec_support/phantomjs_polyfills/phantomjs-getOwnPropertyNames.js +16 -0
  116. data/decidim-dev/lib/decidim/dev/test/rspec_support/warden.rb +17 -1
  117. data/decidim-meetings/app/helpers/decidim/meetings/application_helper.rb +1 -0
  118. data/decidim-meetings/app/helpers/decidim/meetings/meetings_helper.rb +24 -0
  119. data/decidim-meetings/app/views/decidim/meetings/meetings/_meetings.html.erb +1 -1
  120. data/decidim-meetings/bin/rails +2 -2
  121. data/decidim-meetings/config/locales/ca.yml +1 -0
  122. data/decidim-meetings/config/locales/en.yml +2 -1
  123. data/decidim-meetings/config/locales/es.yml +1 -0
  124. data/decidim-meetings/config/locales/fr.yml +5 -5
  125. data/decidim-meetings/decidim-meetings.gemspec +2 -2
  126. data/decidim-meetings/lib/decidim/meetings/feature.rb +1 -1
  127. data/decidim-meetings/spec/features/admin_manages_meetings_attachments_spec.rb +1 -1
  128. data/decidim-meetings/spec/features/admin_manages_meetings_spec.rb +1 -1
  129. data/decidim-meetings/spec/features/explore_meetings_spec.rb +1 -1
  130. data/decidim-meetings/spec/features/process_admin_manages_meetings_attachments_spec.rb +1 -1
  131. data/decidim-meetings/spec/features/process_admin_manages_meetings_spec.rb +1 -1
  132. data/decidim-meetings/spec/helpers/meetings_helper_spec.rb +16 -0
  133. data/decidim-meetings/spec/spec_helper.rb +4 -0
  134. data/decidim-pages/app/models/decidim/pages/page.rb +5 -0
  135. data/decidim-pages/bin/rails +2 -2
  136. data/decidim-pages/decidim-pages.gemspec +2 -2
  137. data/decidim-pages/lib/decidim/pages/feature.rb +1 -1
  138. data/decidim-pages/spec/commands/destroy_page_spec.rb +1 -1
  139. data/decidim-pages/spec/spec_helper.rb +4 -0
  140. data/decidim-proposals/app/assets/config/decidim_proposals_manifest.js +1 -0
  141. data/decidim-proposals/app/assets/javascripts/decidim/proposals/add_proposal.js.es6 +23 -0
  142. data/decidim-proposals/app/forms/decidim/proposals/proposal_form.rb +7 -1
  143. data/decidim-proposals/app/models/decidim/proposals/proposal.rb +14 -2
  144. data/decidim-proposals/app/views/decidim/proposals/proposals/_proposal.html.erb +1 -0
  145. data/decidim-proposals/app/views/decidim/proposals/proposals/new.html.erb +5 -0
  146. data/decidim-proposals/bin/rails +2 -2
  147. data/decidim-proposals/config/locales/fr.yml +11 -11
  148. data/decidim-proposals/db/migrate/20170307085300_migrate_proposal_reports_data_to_reports.rb +1 -1
  149. data/decidim-proposals/decidim-proposals.gemspec +2 -2
  150. data/decidim-proposals/lib/decidim/proposals/feature.rb +1 -1
  151. data/decidim-proposals/spec/features/proposals_spec.rb +8 -2
  152. data/decidim-proposals/spec/models/decidim/proposals/proposal_spec.rb +35 -0
  153. data/decidim-proposals/spec/shared/create_proposal_examples.rb +20 -14
  154. data/decidim-proposals/spec/shared/manage_proposals_examples.rb +13 -16
  155. data/decidim-proposals/spec/shared/proposal_form_examples.rb +22 -16
  156. data/decidim-proposals/spec/spec_helper.rb +4 -0
  157. data/decidim-results/app/models/decidim/results/result.rb +10 -0
  158. data/decidim-results/bin/rails +2 -2
  159. data/decidim-results/config/locales/fr.yml +2 -2
  160. data/decidim-results/decidim-results.gemspec +2 -2
  161. data/decidim-results/lib/decidim/results/feature.rb +1 -1
  162. data/decidim-results/spec/features/comments_spec.rb +10 -0
  163. data/decidim-results/spec/spec_helper.rb +4 -0
  164. data/decidim-surveys/app/models/decidim/surveys/survey_question.rb +2 -0
  165. data/decidim-surveys/bin/rails +2 -2
  166. data/decidim-surveys/decidim-surveys.gemspec +2 -2
  167. data/decidim-surveys/lib/decidim/surveys/feature.rb +3 -2
  168. data/decidim-surveys/spec/forms/decidim/surveys/admin/survey_question_form_spec.rb +1 -1
  169. data/decidim-surveys/spec/models/decidim/surveys/survey_question_spec.rb +7 -1
  170. data/decidim-surveys/spec/spec_helper.rb +5 -0
  171. data/decidim-system/app/controllers/decidim/system/application_controller.rb +1 -1
  172. data/decidim-system/app/controllers/decidim/system/devise/sessions_controller.rb +1 -0
  173. data/decidim-system/app/helpers/decidim/system/menu_helper.rb +1 -1
  174. data/decidim-system/app/views/decidim/system/shared/_notices.html.erb +11 -0
  175. data/decidim-system/app/views/layouts/decidim/system/application.html.erb +1 -1
  176. data/decidim-system/app/views/layouts/decidim/system/login.html.erb +1 -1
  177. data/decidim-system/bin/rails +2 -2
  178. data/decidim-system/config/locales/ca.yml +4 -0
  179. data/decidim-system/config/locales/en.yml +4 -0
  180. data/decidim-system/config/locales/es.yml +4 -0
  181. data/decidim-system/db/migrate/20160919105637_devise_create_decidim_admins.rb +5 -5
  182. data/decidim-system/db/seeds.rb +1 -1
  183. data/decidim-system/decidim-system.gemspec +2 -2
  184. data/decidim-system/spec/factories.rb +2 -2
  185. data/decidim-system/spec/features/manage_admins_spec.rb +3 -3
  186. data/decidim-system/spec/spec_helper.rb +4 -0
  187. data/decidim.gemspec +6 -6
  188. data/docs/how_to_create_a_plugin.md +2 -2
  189. data/lib/generators/decidim/app_generator.rb +1 -1
  190. data/lib/generators/decidim/install_generator.rb +35 -27
  191. data/lib/generators/decidim/templates/Gemfile.erb +1 -0
  192. data/lib/generators/decidim/templates/initializer.rb +7 -1
  193. data/logo.svg +62 -0
  194. data/package.json +37 -35
  195. data/tsconfig.json +3 -0
  196. data/yarn.lock +1017 -486
  197. metadata +32 -25
  198. data/decidim-admin/app/assets/stylesheets/decidim/admin/extra/_language-chooser.scss +0 -4
@@ -14,6 +14,11 @@ import generateUserData from "../support/generate_user_data";
14
14
  import { loadLocaleTranslations } from "../support/load_translations";
15
15
 
16
16
  describe("<Comment />", () => {
17
+ const orderBy = "older";
18
+ const rootCommentable = {
19
+ id: "1",
20
+ type: "Decidim::DummyResource",
21
+ };
17
22
  let comment: CommentFragment;
18
23
  let session: any = null;
19
24
 
@@ -31,17 +36,17 @@ describe("<Comment />", () => {
31
36
  });
32
37
 
33
38
  it("should render an article with class comment", () => {
34
- const wrapper = shallow(<Comment comment={comment} session={session} />);
39
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
35
40
  expect(wrapper.find("article.comment").exists()).toBeTruthy();
36
41
  });
37
42
 
38
43
  it("should render a time tag with comment's created at", () => {
39
- const wrapper = shallow(<Comment comment={comment} session={session} />);
44
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
40
45
  expect(wrapper.find("time").prop("dateTime")).toEqual(comment.createdAt);
41
46
  });
42
47
 
43
48
  it("should render author's name in a link with class author__name", () => {
44
- const wrapper = shallow(<Comment comment={comment} session={session} />);
49
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
45
50
  expect(wrapper.find("a.author__name").text()).toEqual(comment.author.name);
46
51
  });
47
52
 
@@ -51,28 +56,28 @@ describe("<Comment />", () => {
51
56
  });
52
57
 
53
58
  it("should render 'Deleted user' inside a badge", () => {
54
- const wrapper = shallow(<Comment comment={comment} session={session} />);
59
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
55
60
  expect(wrapper.find("span.label.label--small.label--basic").text()).toEqual("Deleted user");
56
61
  });
57
62
  });
58
63
 
59
64
  it("should render author's avatar as a image tag", () => {
60
- const wrapper = shallow(<Comment comment={comment} session={session} />);
65
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
61
66
  expect(wrapper.find("a.author__avatar img").prop("src")).toEqual(comment.author.avatarUrl);
62
67
  });
63
68
 
64
69
  it("should render comment's body on a div with class comment__content", () => {
65
- const wrapper = shallow(<Comment comment={comment} session={session} />);
70
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
66
71
  expect(wrapper.find("div.comment__content").text()).toEqual(comment.body);
67
72
  });
68
73
 
69
74
  it("should initialize with a state property showReplyForm as false", () => {
70
- const wrapper = shallow(<Comment comment={comment} session={session} />);
75
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
71
76
  expect(wrapper.state()).toHaveProperty("showReplyForm", false);
72
77
  });
73
78
 
74
79
  it("should render a AddCommentForm component with the correct props when clicking the reply button", () => {
75
- const wrapper = shallow(<Comment comment={comment} session={session} />);
80
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
76
81
  expect(wrapper.find(AddCommentForm).exists()).toBeFalsy();
77
82
  wrapper.find("button.comment__reply").simulate("click");
78
83
  expect(wrapper.find(AddCommentForm).prop("session")).toEqual(session);
@@ -83,24 +88,24 @@ describe("<Comment />", () => {
83
88
 
84
89
  it("should not render the additional reply button if the parent comment has no comments and isRootcomment", () => {
85
90
  comment.hasComments = false;
86
- const wrapper = shallow(<Comment comment={comment} session={session} isRootComment={true} />);
91
+ const wrapper = shallow(<Comment comment={comment} session={session} isRootComment={true} rootCommentable={rootCommentable} orderBy={orderBy} />);
87
92
  expect(wrapper.find("div.comment__additionalreply").exists()).toBeFalsy();
88
93
  });
89
94
 
90
95
  it("should not render the additional reply button if the parent comment has comments and not isRootcomment", () => {
91
96
  comment.hasComments = true;
92
- const wrapper = shallow(<Comment comment={comment} session={session} />);
97
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
93
98
  expect(wrapper.find("div.comment__additionalreply").exists()).toBeFalsy();
94
99
  });
95
100
 
96
101
  it("should render the additional reply button if the parent comment has comments and isRootcomment", () => {
97
102
  comment.hasComments = true;
98
- const wrapper = shallow(<Comment comment={comment} session={session} isRootComment={true} />);
103
+ const wrapper = shallow(<Comment comment={comment} session={session} isRootComment={true} rootCommentable={rootCommentable} orderBy={orderBy} />);
99
104
  expect(wrapper.find("div.comment__additionalreply").exists()).toBeTruthy();
100
105
  });
101
106
 
102
107
  it("should render comment's comments as a separate Comment components", () => {
103
- const wrapper = shallow(<Comment comment={comment} session={session} votable={true} />);
108
+ const wrapper = shallow(<Comment comment={comment} session={session} votable={true} rootCommentable={rootCommentable} orderBy={orderBy} />);
104
109
  wrapper.find(Comment).forEach((node, idx) => {
105
110
  expect(node.prop("comment")).toEqual(comment.comments[idx]);
106
111
  expect(node.prop("session")).toEqual(session);
@@ -110,19 +115,19 @@ describe("<Comment />", () => {
110
115
  });
111
116
 
112
117
  it("should render comment's comments with articleClassName as 'comment comment--nested comment--nested--alt' when articleClassName is 'comment comment--nested'", () => {
113
- const wrapper = shallow(<Comment comment={comment} session={session} articleClassName="comment comment--nested" />);
118
+ const wrapper = shallow(<Comment comment={comment} session={session} articleClassName="comment comment--nested" rootCommentable={rootCommentable} orderBy={orderBy} />);
114
119
  wrapper.find(Comment).forEach((node) => {
115
120
  expect(node.prop("articleClassName")).toEqual("comment comment--nested comment--nested--alt");
116
121
  });
117
122
  });
118
123
 
119
124
  it("should have a default prop articleClassName with value 'comment'", () => {
120
- const wrapper = mount(<Comment comment={comment} session={session} />);
125
+ const wrapper = mount(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
121
126
  expect(wrapper.prop("articleClassName")).toEqual("comment");
122
127
  });
123
128
 
124
129
  it("should have a default prop isRootComment with value false", () => {
125
- const wrapper = mount(<Comment comment={comment} session={session} />);
130
+ const wrapper = mount(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
126
131
  expect(wrapper.prop("isRootComment")).toBeFalsy();
127
132
  });
128
133
 
@@ -132,7 +137,7 @@ describe("<Comment />", () => {
132
137
  });
133
138
 
134
139
  it("should not render the reply button", () => {
135
- const wrapper = shallow(<Comment comment={comment} session={session} />);
140
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
136
141
  expect(wrapper.find("button.comment__reply").exists()).toBeFalsy();
137
142
  });
138
143
  });
@@ -143,49 +148,49 @@ describe("<Comment />", () => {
143
148
  });
144
149
 
145
150
  it("should not render reply button", () => {
146
- const wrapper = shallow(<Comment comment={comment} session={session} />);
151
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
147
152
  expect(wrapper.find("button.comment__reply").exists()).toBeFalsy();
148
153
  });
149
154
 
150
155
  it("should not render the flag modal", () => {
151
- const wrapper = shallow(<Comment comment={comment} session={session} />);
156
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
152
157
  expect(wrapper.find(".flag-modal").exists()).toBeFalsy();
153
158
  });
154
159
  });
155
160
 
156
161
  it("should render a 'in favor' badge if comment's alignment is 1", () => {
157
162
  comment.alignment = 1;
158
- const wrapper = shallow(<Comment comment={comment} session={session} />);
163
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
159
164
  expect(wrapper.find("span.alignment.label").text()).toEqual("In favor");
160
165
  });
161
166
 
162
167
  it("should render a 'against' badge if comment's alignment is -1", () => {
163
168
  comment.alignment = -1;
164
- const wrapper = shallow(<Comment comment={comment} session={session} />);
169
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
165
170
  expect(wrapper.find("span.alert.label").text()).toEqual("Against");
166
171
  });
167
172
 
168
173
  it("should render the flag modal", () => {
169
- const wrapper = shallow(<Comment comment={comment} session={session} />);
174
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
170
175
  expect(wrapper.find(".flag-modal").exists()).toBeTruthy();
171
176
  });
172
177
 
173
178
  describe("when user has already reported the comment", () => {
174
179
  it("should not render the flag form", () => {
175
180
  comment.alreadyReported = true;
176
- const wrapper = shallow(<Comment comment={comment} session= {session} />);
181
+ const wrapper = shallow(<Comment comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
177
182
  expect(wrapper.find(".flag-modal form").exists()).toBeFalsy();
178
183
  });
179
184
  });
180
185
 
181
186
  describe("when the comment is votable", () => {
182
187
  it("should render an UpVoteButton component", () => {
183
- const wrapper = shallow(<Comment comment={comment} session={session} votable={true} />);
188
+ const wrapper = shallow(<Comment comment={comment} session={session} votable={true} rootCommentable={rootCommentable} orderBy={orderBy} />);
184
189
  expect(wrapper.find(UpVoteButton).prop("comment")).toEqual(comment);
185
190
  });
186
191
 
187
192
  it("should render an DownVoteButton component", () => {
188
- const wrapper = shallow(<Comment comment={comment} session={session} votable={true} />);
193
+ const wrapper = shallow(<Comment comment={comment} session={session} votable={true} rootCommentable={rootCommentable} orderBy={orderBy} />);
189
194
  expect(wrapper.find(DownVoteButton).prop("comment")).toEqual(comment);
190
195
  });
191
196
  });
@@ -9,6 +9,7 @@ import DownVoteButton from "./down_vote_button.component";
9
9
  import UpVoteButton from "./up_vote_button.component";
10
10
 
11
11
  import {
12
+ AddCommentFormCommentableFragment,
12
13
  AddCommentFormSessionFragment,
13
14
  CommentFragment,
14
15
  } from "../support/schema";
@@ -23,6 +24,8 @@ interface CommentProps {
23
24
  articleClassName?: string;
24
25
  isRootComment?: boolean;
25
26
  votable?: boolean;
27
+ rootCommentable: AddCommentFormCommentableFragment;
28
+ orderBy: string;
26
29
  }
27
30
 
28
31
  interface CommentState {
@@ -202,13 +205,13 @@ class Comment extends React.Component<CommentProps, CommentState> {
202
205
  * @returns {Void|DOMElement} - Render the upVote and downVote buttons or not
203
206
  */
204
207
  private _renderVoteButtons() {
205
- const { session, comment, votable } = this.props;
208
+ const { session, comment, votable, rootCommentable, orderBy } = this.props;
206
209
 
207
210
  if (votable) {
208
211
  return (
209
212
  <div className="comment__votes">
210
- <UpVoteButton session={session} comment={comment} />
211
- <DownVoteButton session={session} comment={comment} />
213
+ <UpVoteButton session={session} comment={comment} rootCommentable={rootCommentable} orderBy={orderBy} />
214
+ <DownVoteButton session={session} comment={comment} rootCommentable={rootCommentable} orderBy={orderBy} />
212
215
  </div>
213
216
  );
214
217
  }
@@ -222,7 +225,7 @@ class Comment extends React.Component<CommentProps, CommentState> {
222
225
  * @returns {Void|DomElement} - A wrapper element with comment's comments inside
223
226
  */
224
227
  private _renderReplies() {
225
- const { comment: { id, hasComments, comments }, session, votable, articleClassName } = this.props;
228
+ const { comment: { id, hasComments, comments }, session, votable, articleClassName, rootCommentable, orderBy } = this.props;
226
229
  let replyArticleClassName = "comment comment--nested";
227
230
 
228
231
  if (articleClassName === "comment comment--nested") {
@@ -240,6 +243,8 @@ class Comment extends React.Component<CommentProps, CommentState> {
240
243
  session={session}
241
244
  votable={votable}
242
245
  articleClassName={replyArticleClassName}
246
+ rootCommentable={rootCommentable}
247
+ orderBy={orderBy}
243
248
  />
244
249
  ))
245
250
  }
@@ -256,7 +261,7 @@ class Comment extends React.Component<CommentProps, CommentState> {
256
261
  * @returns {Void|ReactElement} - Render the AddCommentForm component or not
257
262
  */
258
263
  private _renderReplyForm() {
259
- const { session, comment } = this.props;
264
+ const { session, comment, rootCommentable, orderBy } = this.props;
260
265
  const { showReplyForm } = this.state;
261
266
 
262
267
  if (session && showReplyForm) {
@@ -268,6 +273,8 @@ class Comment extends React.Component<CommentProps, CommentState> {
268
273
  submitButtonClassName="button small hollow"
269
274
  onCommentAdded={this.toggleReplyForm}
270
275
  autoFocus={true}
276
+ rootCommentable={rootCommentable}
277
+ orderBy={orderBy}
271
278
  />
272
279
  );
273
280
  }
@@ -10,6 +10,11 @@ import generateCUserData from "../support/generate_user_data";
10
10
  import { loadLocaleTranslations } from "../support/load_translations";
11
11
 
12
12
  describe("<CommentThread />", () => {
13
+ const orderBy = "older";
14
+ const rootCommentable = {
15
+ id: "1",
16
+ type: "Decidim::DummyResource",
17
+ };
13
18
  let comment: CommentFragment;
14
19
  let session: any = null;
15
20
 
@@ -25,7 +30,7 @@ describe("<CommentThread />", () => {
25
30
 
26
31
  describe("when comment doesn't have comments", () => {
27
32
  it("should not render a title with author name", () => {
28
- const wrapper = shallow(<CommentThread comment={comment} session={session} />);
33
+ const wrapper = shallow(<CommentThread comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
29
34
  expect(wrapper.find("h6.comment-thread__title").exists()).toBeFalsy();
30
35
  });
31
36
  });
@@ -36,7 +41,7 @@ describe("<CommentThread />", () => {
36
41
  });
37
42
 
38
43
  it("should render a h6 comment-thread__title with author name", () => {
39
- const wrapper = shallow(<CommentThread comment={comment} session={session} />);
44
+ const wrapper = shallow(<CommentThread comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
40
45
  expect(wrapper.find("h6.comment-thread__title").text()).toContain(`Conversation with ${comment.author.name}`);
41
46
  });
42
47
 
@@ -46,7 +51,7 @@ describe("<CommentThread />", () => {
46
51
  });
47
52
 
48
53
  it("should render a h6 comment-thread__title with 'Deleted user'", () => {
49
- const wrapper = shallow(<CommentThread comment={comment} session={session} />);
54
+ const wrapper = shallow(<CommentThread comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
50
55
  expect(wrapper.find("h6.comment-thread__title").text()).toContain("Conversation with Deleted user");
51
56
  });
52
57
  });
@@ -54,22 +59,22 @@ describe("<CommentThread />", () => {
54
59
 
55
60
  describe("should render a Comment", () => {
56
61
  it("and pass the session as a prop to it", () => {
57
- const wrapper = shallow(<CommentThread comment={comment} session={session} />);
62
+ const wrapper = shallow(<CommentThread comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
58
63
  expect(wrapper.find(Comment).first().props()).toHaveProperty("session", session);
59
64
  });
60
65
 
61
66
  it("and pass comment data as a prop to it", () => {
62
- const wrapper = shallow(<CommentThread comment={comment} session={session} />);
67
+ const wrapper = shallow(<CommentThread comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
63
68
  expect(wrapper.find(Comment).first().props()).toHaveProperty("comment", comment);
64
69
  });
65
70
 
66
71
  it("and pass the votable as a prop to it", () => {
67
- const wrapper = shallow(<CommentThread comment={comment} session={session} votable={true} />);
72
+ const wrapper = shallow(<CommentThread comment={comment} session={session} votable={true} rootCommentable={rootCommentable} orderBy={orderBy} />);
68
73
  expect(wrapper.find(Comment).first().props()).toHaveProperty("votable", true);
69
74
  });
70
75
 
71
76
  it("and pass the isRootComment equal true", () => {
72
- const wrapper = shallow(<CommentThread comment={comment} session={session} votable={true} />);
77
+ const wrapper = shallow(<CommentThread comment={comment} session={session} votable={true} rootCommentable={rootCommentable} orderBy={orderBy} />);
73
78
  expect(wrapper.find(Comment).first().props()).toHaveProperty("isRootComment", true);
74
79
  });
75
80
  });
@@ -3,6 +3,7 @@ import * as React from "react";
3
3
  import Comment from "./comment.component";
4
4
 
5
5
  import {
6
+ AddCommentFormCommentableFragment,
6
7
  AddCommentFormSessionFragment,
7
8
  CommentFragment,
8
9
  } from "../support/schema";
@@ -15,6 +16,8 @@ interface CommentThreadProps {
15
16
  user: any;
16
17
  } | null;
17
18
  votable?: boolean;
19
+ rootCommentable: AddCommentFormCommentableFragment;
20
+ orderBy: string;
18
21
  }
19
22
 
20
23
  /**
@@ -23,14 +26,14 @@ interface CommentThreadProps {
23
26
  * @augments Component
24
27
  * @todo It doesn't handle multiple comments yet
25
28
  */
26
- class CommentThread extends React.Component<CommentThreadProps, undefined> {
29
+ class CommentThread extends React.Component<CommentThreadProps> {
27
30
  public static defaultProps: any = {
28
31
  session: null,
29
32
  votable: false,
30
33
  };
31
34
 
32
35
  public render() {
33
- const { comment, session, votable } = this.props;
36
+ const { comment, session, votable, rootCommentable, orderBy } = this.props;
34
37
 
35
38
  return (
36
39
  <div>
@@ -41,6 +44,8 @@ class CommentThread extends React.Component<CommentThreadProps, undefined> {
41
44
  session={session}
42
45
  votable={votable}
43
46
  isRootComment={true}
47
+ rootCommentable={rootCommentable}
48
+ orderBy={orderBy}
44
49
  />
45
50
  </div>
46
51
  </div>
@@ -27,7 +27,7 @@ interface CommentsProps extends GetCommentsQuery {
27
27
  * @class
28
28
  * @augments Component
29
29
  */
30
- export class Comments extends React.Component<CommentsProps, undefined> {
30
+ export class Comments extends React.Component<CommentsProps> {
31
31
  public static defaultProps: any = {
32
32
  loading: false,
33
33
  session: null,
@@ -91,7 +91,8 @@ export class Comments extends React.Component<CommentsProps, undefined> {
91
91
  * @returns {ReactComponent[]} - A collection of CommentThread components
92
92
  */
93
93
  private _renderCommentThreads() {
94
- const { session, commentable: { comments, commentsHaveVotes } } = this.props;
94
+ const { session, commentable, orderBy } = this.props;
95
+ const { comments, commentsHaveVotes } = commentable;
95
96
 
96
97
  return comments.map((comment) => (
97
98
  <CommentThread
@@ -99,6 +100,8 @@ export class Comments extends React.Component<CommentsProps, undefined> {
99
100
  comment={comment}
100
101
  session={session}
101
102
  votable={commentsHaveVotes}
103
+ rootCommentable={commentable}
104
+ orderBy={orderBy}
102
105
  />
103
106
  ));
104
107
  }
@@ -109,7 +112,7 @@ export class Comments extends React.Component<CommentsProps, undefined> {
109
112
  * @returns {Void|ReactComponent} - A AddCommentForm component or nothing
110
113
  */
111
114
  private _renderAddCommentForm() {
112
- const { session, commentable } = this.props;
115
+ const { session, commentable, orderBy } = this.props;
113
116
  const { acceptsNewComments, commentsHaveAlignment } = commentable;
114
117
 
115
118
  if (acceptsNewComments) {
@@ -118,6 +121,8 @@ export class Comments extends React.Component<CommentsProps, undefined> {
118
121
  session={session}
119
122
  commentable={commentable}
120
123
  arguable={commentsHaveAlignment}
124
+ rootCommentable={commentable}
125
+ orderBy={orderBy}
121
126
  />
122
127
  );
123
128
  }
@@ -135,21 +140,27 @@ window.Comments = Comments;
135
140
 
136
141
  export const commentsQuery = require("../queries/comments.query.graphql");
137
142
 
138
- const CommentsWithData: any = graphql(commentsQuery, {
143
+ const CommentsWithData: any = graphql<GetCommentsQuery, CommentsProps>(commentsQuery, {
139
144
  options: {
140
145
  pollInterval: 15000,
141
146
  },
142
- props: ({ ownProps, data: { loading, session, commentable, refetch }}) => ({
143
- loading,
144
- session,
145
- commentable,
146
- orderBy: ownProps.orderBy,
147
- reorderComments: (orderBy: string) => {
148
- return refetch({
149
- orderBy,
150
- });
151
- },
152
- }),
147
+ props: ({ ownProps, data }) => {
148
+ if (data) {
149
+ const { loading, session, commentable, refetch } = data;
150
+
151
+ return {
152
+ loading,
153
+ session,
154
+ commentable,
155
+ orderBy: ownProps.orderBy,
156
+ reorderComments: (orderBy: string) => {
157
+ return refetch({
158
+ orderBy,
159
+ });
160
+ },
161
+ };
162
+ }
163
+ },
153
164
  })(Comments);
154
165
 
155
166
  export interface CommentsApplicationProps extends GetCommentsQueryVariables {
@@ -10,6 +10,11 @@ import generateUserData from "../support/generate_user_data";
10
10
  import { DownVoteButtonFragment } from "../support/schema";
11
11
 
12
12
  describe("<DownVoteButton />", () => {
13
+ const orderBy = "older";
14
+ const rootCommentable = {
15
+ id: "1",
16
+ type: "Decidim::DummyResource",
17
+ };
13
18
  let comment: DownVoteButtonFragment;
14
19
  let session: any = null;
15
20
  const downVote = jasmine.createSpy("downVote");
@@ -23,7 +28,7 @@ describe("<DownVoteButton />", () => {
23
28
  });
24
29
 
25
30
  it("should render a VoteButton component with the correct props", () => {
26
- const wrapper = shallow(<DownVoteButton session={session} comment={comment} downVote={downVote} />);
31
+ const wrapper = shallow(<DownVoteButton session={session} comment={comment} downVote={downVote} rootCommentable={rootCommentable} orderBy={orderBy} />);
27
32
  expect(wrapper.find(VoteButton).prop("buttonClassName")).toEqual("comment__votes--down");
28
33
  expect(wrapper.find(VoteButton).prop("iconName")).toEqual("icon-chevron-bottom");
29
34
  expect(wrapper.find(VoteButton).prop("votes")).toEqual(comment.downVotes);
@@ -31,13 +36,13 @@ describe("<DownVoteButton />", () => {
31
36
 
32
37
  it("should pass disabled prop as true if comment downVoted is true", () => {
33
38
  comment.downVoted = true;
34
- const wrapper = shallow(<DownVoteButton session={session} comment={comment} downVote={downVote} />);
39
+ const wrapper = shallow(<DownVoteButton session={session} comment={comment} downVote={downVote} rootCommentable={rootCommentable} orderBy={orderBy} />);
35
40
  expect(wrapper.find(VoteButton).prop("disabled")).toBeTruthy();
36
41
  });
37
42
 
38
43
  it("should pass disabled prop as true if comment downVoted is true", () => {
39
44
  comment.downVoted = true;
40
- const wrapper = shallow(<DownVoteButton session={session} comment={comment} downVote={downVote} />);
45
+ const wrapper = shallow(<DownVoteButton session={session} comment={comment} downVote={downVote} rootCommentable={rootCommentable} orderBy={orderBy} />);
41
46
  expect(wrapper.find(VoteButton).prop("disabled")).toBeTruthy();
42
47
  });
43
48
 
@@ -47,7 +52,7 @@ describe("<DownVoteButton />", () => {
47
52
  });
48
53
 
49
54
  it("should pass userLoggedIn as false", () => {
50
- const wrapper = shallow(<DownVoteButton session={session} comment={comment} downVote={downVote} />);
55
+ const wrapper = shallow(<DownVoteButton session={session} comment={comment} downVote={downVote} rootCommentable={rootCommentable} orderBy={orderBy} />);
51
56
  expect(wrapper.find(VoteButton).prop("userLoggedIn")).toBeFalsy();
52
57
  });
53
58
  });