decidim-comments 0.0.3 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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;
|