decidim-comments 0.21.0 → 0.23.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/decidim/comments/bundle.js +67 -67
  3. data/app/assets/javascripts/decidim/comments/bundle.js.map +1 -1
  4. data/app/cells/decidim/comments/comment_activity_cell.rb +2 -22
  5. data/app/cells/decidim/comments/comment_cell.rb +22 -0
  6. data/app/cells/decidim/comments/comment_m/footer.erb +5 -0
  7. data/app/cells/decidim/comments/comment_m/top.erb +7 -0
  8. data/app/cells/decidim/comments/comment_m_cell.rb +29 -0
  9. data/app/commands/decidim/comments/create_comment.rb +8 -8
  10. data/app/events/decidim/comments/comment_by_followed_user_group_event.rb +9 -0
  11. data/app/events/decidim/comments/comment_event.rb +14 -9
  12. data/app/events/decidim/comments/user_group_mentioned_event.rb +10 -0
  13. data/app/forms/decidim/comments/comment_form.rb +17 -1
  14. data/app/frontend/application/icon.component.tsx +16 -4
  15. data/app/frontend/comments/add_comment_form.component.test.tsx +31 -29
  16. data/app/frontend/comments/add_comment_form.component.tsx +34 -18
  17. data/app/frontend/comments/comment.component.test.tsx +36 -5
  18. data/app/frontend/comments/comment.component.tsx +218 -88
  19. data/app/frontend/comments/comment_order_selector.component.tsx +26 -7
  20. data/app/frontend/comments/comment_thread.component.test.tsx +9 -8
  21. data/app/frontend/comments/comment_thread.component.tsx +3 -1
  22. data/app/frontend/comments/comments.component.test.tsx +17 -14
  23. data/app/frontend/comments/comments.component.tsx +28 -4
  24. data/app/frontend/comments/down_vote_button.component.tsx +27 -9
  25. data/app/frontend/comments/up_vote_button.component.tsx +27 -9
  26. data/app/frontend/comments/vote_button.component.tsx +4 -0
  27. data/app/frontend/comments/vote_button_component.test.tsx +14 -8
  28. data/app/frontend/mutations/add_comment.mutation.graphql +2 -2
  29. data/app/frontend/mutations/down_vote.mutation.graphql +2 -2
  30. data/app/frontend/mutations/up_vote.mutation.graphql +2 -2
  31. data/app/frontend/queries/comments.query.graphql +2 -2
  32. data/app/frontend/support/schema.ts +1060 -735
  33. data/app/helpers/decidim/comments/comment_cells_helper.rb +33 -0
  34. data/app/models/decidim/comments/comment.rb +81 -22
  35. data/app/models/decidim/comments/seed.rb +1 -1
  36. data/app/queries/decidim/comments/metrics/comments_metric_manage.rb +1 -6
  37. data/app/services/decidim/comments/new_comment_notification_creator.rb +28 -3
  38. data/app/types/decidim/comments/commentable_interface.rb +1 -1
  39. data/app/types/decidim/comments/commentable_mutation_type.rb +6 -3
  40. data/config/locales/am-ET.yml +1 -0
  41. data/config/locales/ar.yml +4 -1
  42. data/config/locales/bg-BG.yml +6 -0
  43. data/config/locales/bg.yml +6 -0
  44. data/config/locales/ca.yml +19 -2
  45. data/config/locales/cs.yml +31 -14
  46. data/config/locales/da-DK.yml +1 -0
  47. data/config/locales/da.yml +1 -0
  48. data/config/locales/de.yml +47 -24
  49. data/config/locales/el.yml +121 -0
  50. data/config/locales/en.yml +18 -1
  51. data/config/locales/eo.yml +1 -0
  52. data/config/locales/es-MX.yml +18 -1
  53. data/config/locales/es-PY.yml +18 -1
  54. data/config/locales/es.yml +18 -1
  55. data/config/locales/et-EE.yml +1 -0
  56. data/config/locales/et.yml +1 -0
  57. data/config/locales/eu.yml +4 -1
  58. data/config/locales/fi-plain.yml +18 -1
  59. data/config/locales/fi.yml +25 -8
  60. data/config/locales/fr-CA.yml +123 -0
  61. data/config/locales/fr.yml +25 -2
  62. data/config/locales/ga-IE.yml +1 -0
  63. data/config/locales/gl.yml +17 -1
  64. data/config/locales/hr-HR.yml +1 -0
  65. data/config/locales/hr.yml +1 -0
  66. data/config/locales/hu.yml +12 -2
  67. data/config/locales/id-ID.yml +4 -1
  68. data/config/locales/is-IS.yml +3 -3
  69. data/config/locales/is.yml +76 -0
  70. data/config/locales/it.yml +21 -1
  71. data/config/locales/ja-JP.yml +120 -0
  72. data/config/locales/ja.yml +121 -0
  73. data/config/locales/ko-KR.yml +1 -0
  74. data/config/locales/ko.yml +1 -0
  75. data/config/locales/lt-LT.yml +1 -0
  76. data/config/locales/lt.yml +1 -0
  77. data/config/locales/lv.yml +118 -0
  78. data/config/locales/mt-MT.yml +1 -0
  79. data/config/locales/mt.yml +1 -0
  80. data/config/locales/nl.yml +27 -8
  81. data/config/locales/no.yml +18 -2
  82. data/config/locales/om-ET.yml +1 -0
  83. data/config/locales/pl.yml +63 -40
  84. data/config/locales/pt-BR.yml +5 -2
  85. data/config/locales/pt.yml +47 -25
  86. data/config/locales/ro-RO.yml +124 -0
  87. data/config/locales/ru.yml +4 -1
  88. data/config/locales/si-LK.yml +1 -0
  89. data/config/locales/sk-SK.yml +116 -0
  90. data/config/locales/sk.yml +120 -0
  91. data/config/locales/sl.yml +4 -0
  92. data/config/locales/so-SO.yml +1 -0
  93. data/config/locales/sr-CS.yml +20 -0
  94. data/config/locales/sv.yml +26 -3
  95. data/config/locales/sw-KE.yml +1 -0
  96. data/config/locales/ti-ER.yml +1 -0
  97. data/config/locales/tr-TR.yml +54 -31
  98. data/config/locales/uk.yml +4 -2
  99. data/config/locales/vi-VN.yml +1 -0
  100. data/config/locales/vi.yml +1 -0
  101. data/config/locales/zh-CN.yml +121 -0
  102. data/config/locales/zh-TW.yml +1 -0
  103. data/db/migrate/20200320105911_index_foreign_keys_in_decidim_comments_comments.rb +7 -0
  104. data/db/migrate/20200706123136_make_comments_handle_i18n.rb +41 -0
  105. data/db/migrate/20200828101910_add_commentable_counter_cache_to_comments.rb +9 -0
  106. data/lib/decidim/comments/api/comment_type.rb +5 -1
  107. data/lib/decidim/comments/comment_serializer.rb +7 -2
  108. data/lib/decidim/comments/comment_vote_serializer.rb +5 -1
  109. data/lib/decidim/comments/commentable.rb +11 -0
  110. data/lib/decidim/comments/comments_helper.rb +28 -4
  111. data/lib/decidim/comments/engine.rb +13 -0
  112. data/lib/decidim/comments/mutation_extensions.rb +8 -0
  113. data/lib/decidim/comments/query_extensions.rb +4 -0
  114. data/lib/decidim/comments/test/factories.rb +10 -1
  115. data/lib/decidim/comments/test/shared_examples/comment_event.rb +12 -2
  116. data/lib/decidim/comments/test/shared_examples/create_comment_context.rb +3 -2
  117. data/lib/decidim/comments/version.rb +1 -1
  118. metadata +59 -13
@@ -43,28 +43,47 @@ class CommentOrderSelector extends React.Component<CommentOrderSelectorProps, Co
43
43
  <ul
44
44
  className="dropdown menu"
45
45
  data-dropdown-menu="data-dropdown-menu"
46
+ data-autoclose="false"
47
+ data-disable-hover="true"
48
+ data-click-open="true"
49
+ data-close-on-click="true"
50
+ tabIndex={-1}
46
51
  ref={this.setDropdown}
47
52
  >
48
- <li>
49
- <a>{I18n.t(`components.comment_order_selector.order.${orderBy}`)}</a>
50
- <ul className="menu">
53
+ <li className="is-dropdown-submenu-parent" tabIndex={-1}>
54
+ <a
55
+ href="#"
56
+ id="comments-order-menu-control"
57
+ aria-label={I18n.t("components.comment_order_selector.title")}
58
+ aria-controls="comments-order-menu"
59
+ aria-haspopup="true"
60
+ >
61
+ {I18n.t(`components.comment_order_selector.order.${orderBy}`)}
62
+ </a>
63
+ <ul
64
+ className="menu is-dropdown-submenu"
65
+ id="language-chooser-menu"
66
+ role="menu"
67
+ aria-labelledby="comments-order-menu-control"
68
+ tabIndex={-1}
69
+ >
51
70
  <li>
52
- <a href="" className="test" onClick={this.updateOrder("best_rated")} >
71
+ <a href="#" className="test" onClick={this.updateOrder("best_rated")} tabIndex={-1}>
53
72
  {I18n.t("components.comment_order_selector.order.best_rated")}
54
73
  </a>
55
74
  </li>
56
75
  <li>
57
- <a href="" onClick={this.updateOrder("recent")} >
76
+ <a href="#" onClick={this.updateOrder("recent")} tabIndex={-1}>
58
77
  {I18n.t("components.comment_order_selector.order.recent")}
59
78
  </a>
60
79
  </li>
61
80
  <li>
62
- <a href="" onClick={this.updateOrder("older")} >
81
+ <a href="#" onClick={this.updateOrder("older")} tabIndex={-1}>
63
82
  {I18n.t("components.comment_order_selector.order.older")}
64
83
  </a>
65
84
  </li>
66
85
  <li>
67
- <a href="" onClick={this.updateOrder("most_discussed")} >
86
+ <a href="" onClick={this.updateOrder("most_discussed")} tabIndex={-1}>
68
87
  {I18n.t("components.comment_order_selector.order.most_discussed")}
69
88
  </a>
70
89
  </li>
@@ -9,7 +9,8 @@ import generateCommentsData from "../support/generate_comments_data";
9
9
  import generateCUserData from "../support/generate_user_data";
10
10
  import { loadLocaleTranslations } from "../support/load_translations";
11
11
 
12
- describe("<CommentThread />", () => {
12
+ describe("<CommentThread commentsMaxLength={commentsMaxLength} />", () => {
13
+ const commentsMaxLength: number = 1000;
13
14
  const orderBy = "older";
14
15
  const rootCommentable = {
15
16
  id: "1",
@@ -30,7 +31,7 @@ describe("<CommentThread />", () => {
30
31
 
31
32
  describe("when comment doesn't have comments", () => {
32
33
  it("should not render a title with author name", () => {
33
- const wrapper = shallow(<CommentThread comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
34
+ const wrapper = shallow(<CommentThread commentsMaxLength={commentsMaxLength} comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
34
35
  expect(wrapper.find("h6.comment-thread__title").exists()).toBeFalsy();
35
36
  });
36
37
  });
@@ -41,7 +42,7 @@ describe("<CommentThread />", () => {
41
42
  });
42
43
 
43
44
  it("should render a h6 comment-thread__title with author name", () => {
44
- const wrapper = shallow(<CommentThread comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
45
+ const wrapper = shallow(<CommentThread commentsMaxLength={commentsMaxLength} comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
45
46
  expect(wrapper.find("h6.comment-thread__title").text()).toContain(`Conversation with ${comment.author.name}`);
46
47
  });
47
48
 
@@ -51,7 +52,7 @@ describe("<CommentThread />", () => {
51
52
  });
52
53
 
53
54
  it("should render a h6 comment-thread__title with 'Deleted participant'", () => {
54
- const wrapper = shallow(<CommentThread comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
55
+ const wrapper = shallow(<CommentThread commentsMaxLength={commentsMaxLength} comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
55
56
  expect(wrapper.find("h6.comment-thread__title").text()).toContain("Conversation with Deleted participant");
56
57
  });
57
58
  });
@@ -59,22 +60,22 @@ describe("<CommentThread />", () => {
59
60
 
60
61
  describe("should render a Comment", () => {
61
62
  it("and pass the session as a prop to it", () => {
62
- const wrapper = shallow(<CommentThread comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
63
+ const wrapper = shallow(<CommentThread commentsMaxLength={commentsMaxLength} comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
63
64
  expect(wrapper.find(Comment).first().props()).toHaveProperty("session", session);
64
65
  });
65
66
 
66
67
  it("and pass comment data as a prop to it", () => {
67
- const wrapper = shallow(<CommentThread comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
68
+ const wrapper = shallow(<CommentThread commentsMaxLength={commentsMaxLength} comment={comment} session={session} rootCommentable={rootCommentable} orderBy={orderBy} />);
68
69
  expect(wrapper.find(Comment).first().props()).toHaveProperty("comment", comment);
69
70
  });
70
71
 
71
72
  it("and pass the votable as a prop to it", () => {
72
- const wrapper = shallow(<CommentThread comment={comment} session={session} votable={true} rootCommentable={rootCommentable} orderBy={orderBy} />);
73
+ const wrapper = shallow(<CommentThread commentsMaxLength={commentsMaxLength} comment={comment} session={session} votable={true} rootCommentable={rootCommentable} orderBy={orderBy} />);
73
74
  expect(wrapper.find(Comment).first().props()).toHaveProperty("votable", true);
74
75
  });
75
76
 
76
77
  it("and pass the isRootComment equal true", () => {
77
- const wrapper = shallow(<CommentThread comment={comment} session={session} votable={true} rootCommentable={rootCommentable} orderBy={orderBy} />);
78
+ const wrapper = shallow(<CommentThread commentsMaxLength={commentsMaxLength} comment={comment} session={session} votable={true} rootCommentable={rootCommentable} orderBy={orderBy} />);
78
79
  expect(wrapper.find(Comment).first().props()).toHaveProperty("isRootComment", true);
79
80
  });
80
81
  });
@@ -18,6 +18,7 @@ interface CommentThreadProps {
18
18
  votable?: boolean;
19
19
  rootCommentable: AddCommentFormCommentableFragment;
20
20
  orderBy: string;
21
+ commentsMaxLength: number;
21
22
  }
22
23
 
23
24
  /**
@@ -33,7 +34,7 @@ class CommentThread extends React.Component<CommentThreadProps> {
33
34
  };
34
35
 
35
36
  public render() {
36
- const { comment, session, votable, rootCommentable, orderBy } = this.props;
37
+ const { comment, session, votable, rootCommentable, orderBy, commentsMaxLength } = this.props;
37
38
 
38
39
  return (
39
40
  <div>
@@ -46,6 +47,7 @@ class CommentThread extends React.Component<CommentThreadProps> {
46
47
  isRootComment={true}
47
48
  rootCommentable={rootCommentable}
48
49
  orderBy={orderBy}
50
+ commentsMaxLength={commentsMaxLength}
49
51
  />
50
52
  </div>
51
53
  </div>
@@ -12,12 +12,15 @@ import resolveGraphQLQuery from "../support/resolve_graphql_query";
12
12
 
13
13
  import { loadLocaleTranslations } from "../support/load_translations";
14
14
 
15
- describe("<Comments />", () => {
15
+ describe("<Comments commentsMaxLength={commentsMaxLength} />", () => {
16
16
  let commentable: any = {};
17
17
  let session: any = null;
18
+ const commentsMaxLength: number = 1000;
18
19
  const commentableId = "1";
19
20
  const commentableType = "Decidim::DummyResources::DummyResource";
20
21
  const orderBy = "older";
22
+ const locale = "en";
23
+ const toggleTranslations = false;
21
24
  const reorderComments = jasmine.createSpy("reorderComments");
22
25
 
23
26
  beforeEach(() => {
@@ -52,19 +55,19 @@ describe("<Comments />", () => {
52
55
  });
53
56
 
54
57
  it("renders loading-comments class and the respective loading text", () => {
55
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} loading={true} />);
58
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} loading={true} />);
56
59
  expect(wrapper.find(".loading-comments").exists()).toBeTruthy();
57
60
  expect(wrapper.find("h2").text()).toEqual("Loading comments ...");
58
61
  });
59
62
 
60
63
  it("renders a div of id comments", () => {
61
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
64
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
62
65
  expect(wrapper.find("#comments").exists()).toBeTruthy();
63
66
  });
64
67
 
65
68
  describe("renders a CommentThread component for each comment", () => {
66
69
  it("and pass filter comment data as a prop to it", () => {
67
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
70
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
68
71
  expect(wrapper.find(CommentThread).length).toEqual(commentable.comments.length);
69
72
  wrapper.find(CommentThread).forEach((node, idx) => {
70
73
  expect(node.prop("comment")).toEqual(commentable.comments[idx]);
@@ -72,7 +75,7 @@ describe("<Comments />", () => {
72
75
  });
73
76
 
74
77
  it("and pass the session as a prop to it", () => {
75
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
78
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
76
79
  expect(wrapper.find(CommentThread).length).toEqual(commentable.comments.length);
77
80
  wrapper.find(CommentThread).forEach((node) => {
78
81
  expect(node.prop("session")).toEqual(session);
@@ -80,7 +83,7 @@ describe("<Comments />", () => {
80
83
  });
81
84
 
82
85
  it("and pass the commentable 'commentsHaveVotes' property as a prop to it", () => {
83
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
86
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
84
87
  expect(wrapper.find(CommentThread).length).toEqual(commentable.comments.length);
85
88
  wrapper.find(CommentThread).forEach((node) => {
86
89
  expect(node.prop("votable")).toBeTruthy();
@@ -89,13 +92,13 @@ describe("<Comments />", () => {
89
92
  });
90
93
 
91
94
  it("renders comments count", () => {
92
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
95
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
93
96
  const rex = new RegExp(`${commentable.comments.length} comments`);
94
97
  expect(wrapper.find("h2.section-heading").text()).toMatch(rex);
95
98
  });
96
99
 
97
100
  it("renders a AddCommentForm component and pass the commentable 'commentsHaveAlignment' as a prop", () => {
98
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
101
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
99
102
  expect(wrapper.find(AddCommentForm).length).toEqual(1);
100
103
  expect(wrapper.find(AddCommentForm).prop("arguable")).toBeTruthy();
101
104
  });
@@ -107,12 +110,12 @@ describe("<Comments />", () => {
107
110
  });
108
111
 
109
112
  it("doesn't render an AddCommentForm component", () => {
110
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
113
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
111
114
  expect(wrapper.find(AddCommentForm).exists()).toBeFalsy();
112
115
  });
113
116
 
114
117
  it("renders a callout message to inform the user that comments are blocked", () => {
115
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
118
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
116
119
  expect(wrapper.find(".callout.warning").text()).toContain("disabled");
117
120
  });
118
121
  });
@@ -123,24 +126,24 @@ describe("<Comments />", () => {
123
126
  });
124
127
 
125
128
  it("doesn't render an AddCommentForm component", () => {
126
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
129
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
127
130
  expect(wrapper.find(AddCommentForm).exists()).toBeFalsy();
128
131
  });
129
132
 
130
133
  it("renders a callout message to inform the user that comments are blocked", () => {
131
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
134
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
132
135
  expect(wrapper.find(".callout.warning").text()).toContain("not able");
133
136
  });
134
137
  });
135
138
 
136
139
  describe("renders a CommentOrderSelector component", () => {
137
140
  it("and pass the reorderComments as a prop to it", () => {
138
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
141
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
139
142
  expect(wrapper.find(CommentOrderSelector).prop("reorderComments")).toEqual(reorderComments);
140
143
  });
141
144
 
142
145
  it("and pass the orderBy as a prop to it", () => {
143
- const wrapper = shallow(<Comments commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
146
+ const wrapper = shallow(<Comments locale={locale} toggleTranslations={toggleTranslations} commentsMaxLength={commentsMaxLength} commentable={commentable} session={session} reorderComments={reorderComments} orderBy={orderBy} />);
144
147
  expect(wrapper.find(CommentOrderSelector).prop("defaultOrderBy")).toEqual("older");
145
148
  });
146
149
  });
@@ -1,6 +1,8 @@
1
1
  import * as React from "react";
2
2
  import { graphql } from "react-apollo";
3
3
 
4
+ const PropTypes = require("prop-types");
5
+
4
6
  import Application from "../application/application.component";
5
7
 
6
8
  import AddCommentForm from "./add_comment_form.component";
@@ -15,10 +17,13 @@ import {
15
17
  const { I18n, Translate } = require("react-i18nify");
16
18
 
17
19
  interface CommentsProps extends GetCommentsQuery {
20
+ locale: string;
21
+ toggleTranslations: boolean;
18
22
  loading?: boolean;
19
23
  orderBy: string;
20
24
  singleCommentId?: string;
21
25
  reorderComments: (orderBy: string) => void;
26
+ commentsMaxLength: number;
22
27
  }
23
28
 
24
29
  /**
@@ -37,8 +42,20 @@ export class Comments extends React.Component<CommentsProps> {
37
42
  }
38
43
  };
39
44
 
45
+ public static childContextTypes: any = {
46
+ locale: PropTypes.string,
47
+ toggleTranslations: PropTypes.bool
48
+ };
49
+
50
+ public getChildContext() {
51
+ return {
52
+ locale: this.props.locale,
53
+ toggleTranslations: this.props.toggleTranslations
54
+ };
55
+ }
56
+
40
57
  public render() {
41
- const { commentable: { totalCommentsCount = 0 }, singleCommentId, loading } = this.props;
58
+ const { commentable: { totalCommentsCount = 0 }, singleCommentId, loading, commentsMaxLength } = this.props;
42
59
  let commentClasses = "comments";
43
60
  let commentHeader = I18n.t("components.comments.title", { count: totalCommentsCount });
44
61
  if (singleCommentId && singleCommentId !== "") {
@@ -164,7 +181,7 @@ export class Comments extends React.Component<CommentsProps> {
164
181
  * @returns {ReactComponent[]} - A collection of CommentThread components
165
182
  */
166
183
  private _renderCommentThreads() {
167
- const { session, commentable, orderBy } = this.props;
184
+ const { session, commentable, orderBy, commentsMaxLength } = this.props;
168
185
  const { comments, commentsHaveVotes } = commentable;
169
186
 
170
187
  return comments.map((comment) => (
@@ -175,6 +192,7 @@ export class Comments extends React.Component<CommentsProps> {
175
192
  votable={commentsHaveVotes}
176
193
  rootCommentable={commentable}
177
194
  orderBy={orderBy}
195
+ commentsMaxLength={commentsMaxLength}
178
196
  />
179
197
  ));
180
198
  }
@@ -185,7 +203,7 @@ export class Comments extends React.Component<CommentsProps> {
185
203
  * @returns {Void|ReactComponent} - A AddCommentForm component or nothing
186
204
  */
187
205
  private _renderAddCommentForm() {
188
- const { session, commentable, orderBy, singleCommentId } = this.props;
206
+ const { session, commentable, orderBy, singleCommentId, commentsMaxLength } = this.props;
189
207
  const { acceptsNewComments, commentsHaveAlignment, userAllowedToComment } = commentable;
190
208
 
191
209
  if (singleCommentId && singleCommentId !== "") {
@@ -200,6 +218,7 @@ export class Comments extends React.Component<CommentsProps> {
200
218
  arguable={commentsHaveAlignment}
201
219
  rootCommentable={commentable}
202
220
  orderBy={orderBy}
221
+ commentsMaxLength={commentsMaxLength}
203
222
  />
204
223
  );
205
224
  }
@@ -244,6 +263,8 @@ const CommentsWithData: any = graphql<GetCommentsQuery, CommentsProps>(commentsQ
244
263
  export interface CommentsApplicationProps extends GetCommentsQueryVariables {
245
264
  singleCommentId: string;
246
265
  locale: string;
266
+ toggleTranslations: boolean;
267
+ commentsMaxLength: number;
247
268
  }
248
269
 
249
270
  /**
@@ -251,11 +272,14 @@ export interface CommentsApplicationProps extends GetCommentsQueryVariables {
251
272
  * connect it with Apollo client and store.
252
273
  * @returns {ReactComponent} - A component wrapped within an Application component
253
274
  */
254
- const CommentsApplication: React.SFC<CommentsApplicationProps> = ({ locale, commentableId, commentableType, singleCommentId }) => (
275
+ const CommentsApplication: React.SFC<CommentsApplicationProps> = ({ locale, toggleTranslations, commentableId, commentableType, singleCommentId, commentsMaxLength }) => (
255
276
  <Application locale={locale}>
256
277
  <CommentsWithData
278
+ commentsMaxLength={commentsMaxLength}
257
279
  commentableId={commentableId}
258
280
  commentableType={commentableType}
281
+ locale={locale}
282
+ toggleTranslations={toggleTranslations}
259
283
  orderBy="older"
260
284
  singleCommentId={singleCommentId}
261
285
  />
@@ -1,6 +1,8 @@
1
1
  import * as React from "react";
2
2
  import { graphql, MutationFunc } from "react-apollo";
3
3
 
4
+ const PropTypes = require("prop-types");
5
+
4
6
  import VoteButton from "./vote_button.component";
5
7
 
6
8
  import {
@@ -12,21 +14,25 @@ import {
12
14
  GetCommentsQuery
13
15
  } from "../support/schema";
14
16
 
17
+ const { I18n } = require("react-i18nify");
18
+
15
19
  interface DownVoteButtonProps {
16
20
  session: AddCommentFormSessionFragment & {
17
21
  user: any;
18
22
  } | null;
19
23
  comment: DownVoteButtonFragment;
20
- downVote?: () => void;
24
+ downVote?: (context: any) => void;
21
25
  rootCommentable: AddCommentFormCommentableFragment;
22
26
  orderBy: string;
23
27
  }
24
28
 
25
- export const DownVoteButton: React.SFC<DownVoteButtonProps> = ({
26
- session,
27
- comment: { downVotes, upVoted, downVoted },
28
- downVote
29
- }) => {
29
+ export const DownVoteButton: React.SFC<DownVoteButtonProps> = (
30
+ {
31
+ session,
32
+ comment: { downVotes, upVoted, downVoted },
33
+ downVote
34
+ },
35
+ context) => {
30
36
  let selectedClass = "";
31
37
 
32
38
  if (downVoted) {
@@ -37,13 +43,15 @@ export const DownVoteButton: React.SFC<DownVoteButtonProps> = ({
37
43
 
38
44
  const userLoggedIn = session && session.user;
39
45
  const disabled = false;
46
+ const voteAction = () => downVote && downVote(context);
40
47
 
41
48
  return (
42
49
  <VoteButton
43
50
  buttonClassName="comment__votes--down"
44
51
  iconName="icon-chevron-bottom"
52
+ text={I18n.t("components.down_vote_button.text")}
45
53
  votes={downVotes}
46
- voteAction={downVote}
54
+ voteAction={voteAction}
47
55
  disabled={disabled}
48
56
  selectedClass={selectedClass}
49
57
  userLoggedIn={userLoggedIn}
@@ -51,13 +59,20 @@ export const DownVoteButton: React.SFC<DownVoteButtonProps> = ({
51
59
  );
52
60
  };
53
61
 
62
+ DownVoteButton.contextTypes = {
63
+ locale: PropTypes.string,
64
+ toggleTranslations: PropTypes.bool
65
+ };
66
+
54
67
  const downVoteMutation = require("../mutations/down_vote.mutation.graphql");
55
68
  const getCommentsQuery = require("../queries/comments.query.graphql");
56
69
 
57
70
  const DownVoteButtonWithMutation = graphql<DownVoteMutation, DownVoteButtonProps>(downVoteMutation, {
58
71
  props: ({ ownProps, mutate }: { ownProps: DownVoteButtonProps, mutate: MutationFunc<DownVoteMutation> }) => ({
59
- downVote: () => mutate({
72
+ downVote: ({ locale, toggleTranslations }: any) => mutate({
60
73
  variables: {
74
+ locale,
75
+ toggleTranslations,
61
76
  id: ownProps.comment.id
62
77
  },
63
78
  optimisticResponse: {
@@ -74,9 +89,12 @@ const DownVoteButtonWithMutation = graphql<DownVoteMutation, DownVoteButtonProps
74
89
  },
75
90
  update: (store, { data }: { data: DownVoteMutation }) => {
76
91
  const variables = {
92
+ locale,
93
+ toggleTranslations,
77
94
  commentableId: ownProps.rootCommentable.id,
78
95
  commentableType: ownProps.rootCommentable.type,
79
- orderBy: ownProps.orderBy
96
+ orderBy: ownProps.orderBy,
97
+ singleCommentId: null
80
98
  };
81
99
 
82
100
  const commentReducer = (comment: CommentFragment): CommentFragment => {