decidim-comments 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/assets/javascripts/decidim/comments/bundle.js +28 -23
- data/app/assets/javascripts/decidim/comments/bundle.js.map +1 -1
- data/app/commands/decidim/comments/create_comment.rb +10 -0
- data/app/forms/decidim/comments/comment_form.rb +1 -1
- data/app/frontend/comments/add_comment_form.component.jsx +171 -87
- data/app/frontend/comments/add_comment_form.component.test.jsx +41 -22
- data/app/frontend/comments/add_comment_form.mutation.graphql +5 -3
- data/app/frontend/comments/add_comment_form_commentable.fragment.graphql +4 -0
- data/app/frontend/comments/add_comment_form_session.fragment.graphql +6 -0
- data/app/frontend/comments/comment.component.jsx +18 -18
- data/app/frontend/comments/comment.component.test.jsx +22 -21
- data/app/frontend/comments/comment.fragment.graphql +4 -4
- data/app/frontend/comments/comment_data.fragment.graphql +4 -3
- data/app/frontend/comments/comment_order_selector.component.jsx +3 -3
- data/app/frontend/comments/comment_thread.component.jsx +8 -3
- data/app/frontend/comments/comment_thread.component.test.jsx +3 -3
- data/app/frontend/comments/comment_thread.fragment.graphql +1 -1
- data/app/frontend/comments/comments.component.jsx +52 -33
- data/app/frontend/comments/comments.component.test.jsx +51 -38
- data/app/frontend/comments/comments.query.graphql +10 -4
- data/app/frontend/comments/down_vote_button.component.jsx +6 -3
- data/app/frontend/comments/up_vote_button.component.jsx +7 -4
- data/app/frontend/comments/vote_button.component.jsx +5 -0
- data/app/frontend/comments/vote_button_component.test.jsx +1 -1
- data/app/frontend/entry.test.js +2 -0
- data/app/frontend/support/generate_comments_data.js +4 -4
- data/app/mailers/decidim/comments/comment_notification_mailer.rb +31 -0
- data/app/models/decidim/comments/comment.rb +13 -9
- data/app/queries/decidim/comments/{comments_with_replies.rb → sorted_comments.rb} +3 -8
- data/app/types/decidim/comments/commentable_interface.rb +44 -0
- data/app/types/decidim/comments/commentable_mutation_type.rb +29 -0
- data/app/types/decidim/comments/commentable_type.rb +14 -0
- data/app/views/decidim/comments/comment_notification_mailer/comment_created.html.erb +18 -0
- data/app/views/decidim/comments/comment_notification_mailer/reply_created.html.erb +18 -0
- data/config/locales/ca.yml +20 -4
- data/config/locales/en.yml +22 -5
- data/config/locales/es.yml +20 -4
- data/config/locales/eu.yml +5 -0
- data/lib/decidim/comments.rb +5 -0
- data/{app/types/decidim/comments → lib/decidim/comments/api}/add_comment_type.rb +0 -0
- data/{app/types/decidim/comments → lib/decidim/comments/api}/comment_mutation_type.rb +0 -0
- data/{app/types/decidim/comments → lib/decidim/comments/api}/comment_type.rb +11 -17
- data/lib/decidim/comments/commentable.rb +45 -0
- data/{app/helpers → lib}/decidim/comments/comments_helper.rb +15 -10
- data/lib/decidim/comments/mutation_extensions.rb +8 -16
- data/lib/decidim/comments/query_extensions.rb +5 -8
- data/lib/decidim/comments/test/factories.rb +3 -3
- metadata +21 -12
- data/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
|
12
|
-
|
11
|
+
const commentable = {
|
12
|
+
id: "1",
|
13
|
+
type: "Decidim::DummyResource"
|
14
|
+
};
|
13
15
|
const addCommentStub = () => {
|
14
16
|
return null;
|
15
17
|
}
|
@@ -22,44 +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}
|
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}
|
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}
|
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}
|
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}
|
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}
|
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
|
|
56
|
+
it("should have a default prop maxLength of 1000", () => {
|
57
|
+
const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
|
58
|
+
expect(wrapper).to.have.prop('maxLength').equal(1000);
|
59
|
+
});
|
60
|
+
|
61
|
+
|
54
62
|
it("should use prop submitButtonClassName as a className prop for submit button", () => {
|
55
|
-
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session}
|
63
|
+
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} submitButtonClassName="button small hollow" />);
|
56
64
|
expect(wrapper.find('input[type="submit"]')).to.have.className('button');
|
57
65
|
expect(wrapper.find('input[type="submit"]')).to.have.className('small');
|
58
66
|
expect(wrapper.find('input[type="submit"]')).to.have.className('hollow');
|
59
67
|
});
|
60
68
|
|
61
69
|
it("should enable the submit button if textarea is not blank", () => {
|
62
|
-
const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session}
|
70
|
+
const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
|
63
71
|
wrapper.find('textarea').simulate('change', {
|
64
72
|
target: {
|
65
73
|
value: 'This is a comment'
|
@@ -69,7 +77,7 @@ describe("<AddCommentForm />", () => {
|
|
69
77
|
});
|
70
78
|
|
71
79
|
it("should disable the submit button if textarea is blank", () => {
|
72
|
-
const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session}
|
80
|
+
const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
|
73
81
|
wrapper.find('textarea').simulate('change', {
|
74
82
|
target: {
|
75
83
|
value: 'This will be deleted'
|
@@ -84,7 +92,7 @@ describe("<AddCommentForm />", () => {
|
|
84
92
|
});
|
85
93
|
|
86
94
|
it("should not render a div with class 'opinion-toggle'", () => {
|
87
|
-
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session}
|
95
|
+
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
|
88
96
|
expect(wrapper.find('.opinion-toggle')).not.to.be.present();
|
89
97
|
});
|
90
98
|
|
@@ -97,7 +105,7 @@ describe("<AddCommentForm />", () => {
|
|
97
105
|
beforeEach(() => {
|
98
106
|
addComment = sinon.spy();
|
99
107
|
onCommentAdded = sinon.spy();
|
100
|
-
wrapper = mount(<AddCommentForm addComment={addComment} session={session}
|
108
|
+
wrapper = mount(<AddCommentForm addComment={addComment} session={session} commentable={commentable} onCommentAdded={onCommentAdded} />);
|
101
109
|
message = 'This will be submitted';
|
102
110
|
wrapper.instance().bodyTextArea.value = message;
|
103
111
|
});
|
@@ -125,25 +133,25 @@ describe("<AddCommentForm />", () => {
|
|
125
133
|
});
|
126
134
|
|
127
135
|
it("should initialize state with a property alignment and value 0", () => {
|
128
|
-
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session}
|
136
|
+
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} arguable />);
|
129
137
|
expect(wrapper).to.have.state('alignment').equal(0);
|
130
138
|
});
|
131
139
|
|
132
140
|
describe("when receiving an optional prop arguable with value true", () => {
|
133
141
|
it("should render a div with class 'opinion-toggle'", () => {
|
134
|
-
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session}
|
142
|
+
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} arguable />);
|
135
143
|
expect(wrapper.find('.opinion-toggle')).to.be.present();
|
136
144
|
});
|
137
145
|
|
138
146
|
it("should set state alignment to 1 if user clicks ok button and change its class", () => {
|
139
|
-
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session}
|
147
|
+
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} arguable />);
|
140
148
|
wrapper.find('.opinion-toggle--ok').simulate('click');
|
141
149
|
expect(wrapper.find('.opinion-toggle--ok')).to.have.className('is-active');
|
142
150
|
expect(wrapper).to.have.state('alignment').equal(1);
|
143
151
|
});
|
144
152
|
|
145
153
|
it("should set state alignment to -11 if user clicks ko button and change its class", () => {
|
146
|
-
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session}
|
154
|
+
const wrapper = shallow(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} arguable />);
|
147
155
|
wrapper.find('.opinion-toggle--ko').simulate('click');
|
148
156
|
expect(wrapper.find('.opinion-toggle--ko')).to.have.className('is-active');
|
149
157
|
expect(wrapper).to.have.state('alignment').equal(-1);
|
@@ -156,7 +164,7 @@ describe("<AddCommentForm />", () => {
|
|
156
164
|
|
157
165
|
beforeEach(() => {
|
158
166
|
addComment = sinon.spy();
|
159
|
-
wrapper = mount(<AddCommentForm addComment={addComment} session={session}
|
167
|
+
wrapper = mount(<AddCommentForm addComment={addComment} session={session} commentable={commentable} arguable />);
|
160
168
|
message = 'This will be submitted';
|
161
169
|
wrapper.instance().bodyTextArea.value = message;
|
162
170
|
});
|
@@ -184,12 +192,12 @@ describe("<AddCommentForm />", () => {
|
|
184
192
|
});
|
185
193
|
|
186
194
|
it("should have a reference to user_group_id select", () => {
|
187
|
-
const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session}
|
195
|
+
const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
|
188
196
|
expect(wrapper.instance().userGroupIdSelect).to.be.ok;
|
189
197
|
});
|
190
198
|
|
191
199
|
it("should render a select with option tags for each verified user group", () => {
|
192
|
-
const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session}
|
200
|
+
const wrapper = mount(<AddCommentForm addComment={addCommentStub} session={session} commentable={commentable} />);
|
193
201
|
expect(wrapper.find('select')).to.have.exactly(3).descendants('option');
|
194
202
|
});
|
195
203
|
|
@@ -201,7 +209,7 @@ describe("<AddCommentForm />", () => {
|
|
201
209
|
|
202
210
|
beforeEach(() => {
|
203
211
|
addComment = sinon.spy();
|
204
|
-
wrapper = mount(<AddCommentForm addComment={addComment} session={session}
|
212
|
+
wrapper = mount(<AddCommentForm addComment={addComment} session={session} commentable={commentable} />);
|
205
213
|
message = 'This will be submitted';
|
206
214
|
userGroupId = session.verifiedUserGroups[1].id;
|
207
215
|
wrapper.instance().bodyTextArea.value = message;
|
@@ -224,5 +232,16 @@ describe("<AddCommentForm />", () => {
|
|
224
232
|
});
|
225
233
|
});
|
226
234
|
});
|
227
|
-
})
|
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
|
+
});
|
228
247
|
});
|
@@ -1,5 +1,7 @@
|
|
1
1
|
mutation addComment($commentableId: String!, $commentableType: String!, $body: String!, $alignment: Int, $userGroupId: ID) {
|
2
|
-
|
3
|
-
|
2
|
+
commentable(id: $commentableId, type: $commentableType) {
|
3
|
+
addComment(body: $body, alignment: $alignment, userGroupId: $userGroupId) {
|
4
|
+
...CommentThread
|
5
|
+
}
|
4
6
|
}
|
5
|
-
}
|
7
|
+
}
|
@@ -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: {
|
71
|
+
const { comment: { acceptsNewComments }, session } = this.props;
|
72
72
|
const { showReplyForm } = this.state;
|
73
73
|
|
74
|
-
if (session &&
|
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: {
|
95
|
+
const { comment: { acceptsNewComments, hasComments }, session, isRootComment } = this.props;
|
96
96
|
const { showReplyForm } = this.state;
|
97
97
|
|
98
|
-
if (session &&
|
99
|
-
if (
|
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
|
137
|
+
* Render comment's comments alternating the css class
|
139
138
|
* @private
|
140
|
-
* @returns {Void|DomElement} - A wrapper element with comment
|
139
|
+
* @returns {Void|DomElement} - A wrapper element with comment's comments inside
|
141
140
|
*/
|
142
141
|
_renderReplies() {
|
143
|
-
const { comment: { id,
|
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 (
|
149
|
+
if (hasComments) {
|
151
150
|
return (
|
152
151
|
<div>
|
153
152
|
{
|
154
|
-
|
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 })}
|
@@ -241,11 +239,6 @@ Comment.fragments = {
|
|
241
239
|
`
|
242
240
|
};
|
243
241
|
|
244
|
-
Comment.defaultProps = {
|
245
|
-
articleClassName: 'comment',
|
246
|
-
isRootComment: false
|
247
|
-
};
|
248
|
-
|
249
242
|
Comment.propTypes = {
|
250
243
|
comment: PropTypes.oneOfType([
|
251
244
|
propType(Comment.fragments.comment).isRequired,
|
@@ -259,4 +252,11 @@ Comment.propTypes = {
|
|
259
252
|
votable: PropTypes.bool
|
260
253
|
};
|
261
254
|
|
255
|
+
Comment.defaultProps = {
|
256
|
+
articleClassName: 'comment',
|
257
|
+
isRootComment: false,
|
258
|
+
session: null,
|
259
|
+
votable: false
|
260
|
+
};
|
261
|
+
|
262
262
|
export default Comment;
|
@@ -27,7 +27,7 @@ describe("<Comment />", () => {
|
|
27
27
|
|
28
28
|
beforeEach(() => {
|
29
29
|
let commentsData = generateCommentsData(1);
|
30
|
-
commentsData[0].
|
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('
|
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
|
87
|
-
comment.
|
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
|
100
|
-
comment.
|
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
|
107
|
-
comment.
|
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
|
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.
|
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
|
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;
|
@@ -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">
|
@@ -44,7 +44,7 @@ class CommentOrderSelector extends Component {
|
|
44
44
|
<a href="" onClick={(event) => this._updateOrder(event, "older")} >
|
45
45
|
{ I18n.t("components.comment_order_selector.order.older") }
|
46
46
|
</a>
|
47
|
-
</li>
|
47
|
+
</li>
|
48
48
|
<li>
|
49
49
|
<a href="" onClick={(event) => this._updateOrder(event, "most_discussed")} >
|
50
50
|
{ I18n.t("components.comment_order_selector.order.most_discussed") }
|
@@ -57,7 +57,7 @@ class CommentOrderSelector extends Component {
|
|
57
57
|
);
|
58
58
|
}
|
59
59
|
|
60
|
-
_updateOrder(event, orderBy) {
|
60
|
+
_updateOrder(event, orderBy) {
|
61
61
|
event.preventDefault();
|
62
62
|
this.setState({ orderBy });
|
63
63
|
this.props.reorderComments(orderBy);
|
@@ -33,14 +33,14 @@ class CommentThread extends Component {
|
|
33
33
|
}
|
34
34
|
|
35
35
|
/**
|
36
|
-
* Render conversation title if comment has
|
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,
|
41
|
+
const { comment: { author, hasComments } } = this.props;
|
42
42
|
|
43
|
-
if (
|
43
|
+
if (hasComments) {
|
44
44
|
return (
|
45
45
|
<h6 className="comment-thread__title">
|
46
46
|
{ I18n.t("components.comment_thread.title", { authorName: author.name }) }
|
@@ -67,4 +67,9 @@ CommentThread.propTypes = {
|
|
67
67
|
votable: PropTypes.bool
|
68
68
|
};
|
69
69
|
|
70
|
+
CommentThread.defaultProps = {
|
71
|
+
session: null,
|
72
|
+
votable: false
|
73
|
+
};
|
74
|
+
|
70
75
|
export default CommentThread;
|