Commit fa285e09 by wajeeha-khalid

MA-1189 - Discussion API: implemented GET comment children

parent 450e625d
...@@ -415,7 +415,7 @@ def get_comment_list(request, thread_id, endorsed, page, page_size, mark_as_read ...@@ -415,7 +415,7 @@ def get_comment_list(request, thread_id, endorsed, page, page_size, mark_as_read
raise Http404 raise Http404
num_pages = (resp_total + page_size - 1) / page_size if resp_total else 1 num_pages = (resp_total + page_size - 1) / page_size if resp_total else 1
results = [CommentSerializer(response, context=context).data for response in responses] results = [CommentSerializer(response, remove_fields=["children"], context=context).data for response in responses]
return get_paginated_data(request, results, page, num_pages) return get_paginated_data(request, results, page, num_pages)
...@@ -718,6 +718,50 @@ def get_thread(request, thread_id): ...@@ -718,6 +718,50 @@ def get_thread(request, thread_id):
return serializer.data return serializer.data
def get_response_comments(request, comment_id, page, page_size):
"""
Return the list of comments for the given thread response.
Arguments:
request: The django request object used for build_absolute_uri and
determining the requesting user.
comment_id: The id of the comment/response to get child comments for.
page: The page number (1-indexed) to retrieve
page_size: The number of comments to retrieve per page
Returns:
A paginated result containing a list of comments
"""
try:
cc_comment = Comment(id=comment_id).retrieve()
cc_thread, context = _get_thread_and_context(request, cc_comment["thread_id"])
if cc_thread["thread_type"] == "question":
thread_responses = cc_thread["endorsed_responses"] + cc_thread["non_endorsed_responses"]
else:
thread_responses = cc_thread["children"]
response_comments = []
for response in thread_responses:
if response["id"] == comment_id:
response_comments = response["children"]
break
response_skip = page_size * (page - 1)
paged_response_comments = response_comments[response_skip:(response_skip + page_size)]
results = [CommentSerializer(comment, context=context).data for comment in paged_response_comments]
comments_count = len(response_comments)
num_pages = (comments_count + page_size - 1) / page_size if comments_count else 1
return get_paginated_data(request, results, page, num_pages)
except CommentClientRequestError:
raise Http404
def delete_thread(request, thread_id): def delete_thread(request, thread_id):
""" """
Delete a thread. Delete a thread.
......
...@@ -290,6 +290,15 @@ class CommentSerializer(_ContentSerializer): ...@@ -290,6 +290,15 @@ class CommentSerializer(_ContentSerializer):
non_updatable_fields = NON_UPDATABLE_COMMENT_FIELDS non_updatable_fields = NON_UPDATABLE_COMMENT_FIELDS
def __init__(self, *args, **kwargs):
remove_fields = kwargs.pop('remove_fields', None)
super(CommentSerializer, self).__init__(*args, **kwargs)
if remove_fields:
# for multiple fields in a list
for field_name in remove_fields:
self.fields.pop(field_name)
def get_endorsed_by(self, obj): def get_endorsed_by(self, obj):
""" """
Returns the username of the endorsing user, if the information is Returns the username of the endorsing user, if the information is
......
...@@ -1146,7 +1146,6 @@ class GetCommentListTest(CommentsServiceMockMixin, SharedModuleStoreTestCase): ...@@ -1146,7 +1146,6 @@ class GetCommentListTest(CommentsServiceMockMixin, SharedModuleStoreTestCase):
"abuse_flagged": False, "abuse_flagged": False,
"voted": False, "voted": False,
"vote_count": 4, "vote_count": 4,
"children": [],
"editable_fields": ["abuse_flagged", "voted"], "editable_fields": ["abuse_flagged", "voted"],
}, },
{ {
...@@ -1166,7 +1165,6 @@ class GetCommentListTest(CommentsServiceMockMixin, SharedModuleStoreTestCase): ...@@ -1166,7 +1165,6 @@ class GetCommentListTest(CommentsServiceMockMixin, SharedModuleStoreTestCase):
"abuse_flagged": True, "abuse_flagged": True,
"voted": False, "voted": False,
"vote_count": 7, "vote_count": 7,
"children": [],
"editable_fields": ["abuse_flagged", "voted"], "editable_fields": ["abuse_flagged", "voted"],
}, },
] ]
......
...@@ -662,7 +662,6 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase): ...@@ -662,7 +662,6 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
"endorsed": False, "endorsed": False,
"abuse_flaggers": [], "abuse_flaggers": [],
"votes": {"up_count": 4}, "votes": {"up_count": 4},
"children": [],
}] }]
expected_comments = [{ expected_comments = [{
"id": "test_comment", "id": "test_comment",
...@@ -681,7 +680,6 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase): ...@@ -681,7 +680,6 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
"abuse_flagged": False, "abuse_flagged": False,
"voted": True, "voted": True,
"vote_count": 4, "vote_count": 4,
"children": [],
"editable_fields": ["abuse_flagged", "voted"], "editable_fields": ["abuse_flagged", "voted"],
}] }]
self.register_get_thread_response({ self.register_get_thread_response({
...@@ -1025,3 +1023,73 @@ class ThreadViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase) ...@@ -1025,3 +1023,73 @@ class ThreadViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase)
self.register_get_thread_error_response(self.thread_id, 404) self.register_get_thread_error_response(self.thread_id, 404)
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
@httpretty.activate
class CommentViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
"""Tests for CommentViewSet Retrieve"""
def setUp(self):
super(CommentViewSetRetrieveTest, self).setUp()
self.url = reverse("comment-detail", kwargs={"comment_id": "test_comment"})
self.thread_id = "test_thread"
self.comment_id = "test_comment"
def make_comment_data(self, comment_id, parent_id=None, children=[]): # pylint: disable=W0102
"""
Returns comment dict object as returned by comments service
"""
return make_minimal_cs_comment({
"id": comment_id,
"parent_id": parent_id,
"course_id": unicode(self.course.id),
"thread_id": self.thread_id,
"thread_type": "discussion",
"username": self.user.username,
"user_id": str(self.user.id),
"created_at": "2015-06-03T00:00:00Z",
"updated_at": "2015-06-03T00:00:00Z",
"body": "Original body",
"children": children,
})
def test_basic(self):
self.register_get_user_response(self.user)
cs_comment_child = self.make_comment_data("test_child_comment", self.comment_id, children=[])
cs_comment = self.make_comment_data(self.comment_id, None, [cs_comment_child])
cs_thread = make_minimal_cs_thread({
"id": self.thread_id,
"course_id": unicode(self.course.id),
"children": [cs_comment],
})
self.register_get_thread_response(cs_thread)
self.register_get_comment_response(cs_comment)
expected_response_data = {
"id": "test_child_comment",
"parent_id": self.comment_id,
"thread_id": self.thread_id,
"author": self.user.username,
"author_label": None,
"raw_body": "Original body",
"rendered_body": "<p>Original body</p>",
"created_at": "2015-06-03T00:00:00Z",
"updated_at": "2015-06-03T00:00:00Z",
"children": [],
"endorsed_at": None,
"endorsed": False,
"endorsed_by": None,
"endorsed_by_label": None,
"voted": False,
"vote_count": 0,
"abuse_flagged": False,
"editable_fields": ["abuse_flagged", "raw_body", "voted"]
}
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertEqual(json.loads(response.content)['results'][0], expected_response_data)
def test_retrieve_nonexistent_comment(self):
self.register_get_comment_error_response(self.comment_id, 404)
response = self.client.get(self.url)
self.assertEqual(response.status_code, 404)
...@@ -18,6 +18,7 @@ from discussion_api.api import ( ...@@ -18,6 +18,7 @@ from discussion_api.api import (
delete_thread, delete_thread,
delete_comment, delete_comment,
get_comment_list, get_comment_list,
get_response_comments,
get_course, get_course,
get_course_topics, get_course_topics,
get_thread, get_thread,
...@@ -25,7 +26,7 @@ from discussion_api.api import ( ...@@ -25,7 +26,7 @@ from discussion_api.api import (
update_comment, update_comment,
update_thread, update_thread,
) )
from discussion_api.forms import CommentListGetForm, ThreadListGetForm from discussion_api.forms import CommentListGetForm, ThreadListGetForm, _PaginationForm
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin
...@@ -299,6 +300,8 @@ class CommentViewSet(_ViewMixin, DeveloperErrorViewMixin, ViewSet): ...@@ -299,6 +300,8 @@ class CommentViewSet(_ViewMixin, DeveloperErrorViewMixin, ViewSet):
GET /api/discussion/v1/comments/?thread_id=0123456789abcdef01234567 GET /api/discussion/v1/comments/?thread_id=0123456789abcdef01234567
GET /api/discussion/v1/comments/2123456789abcdef01234555
POST /api/discussion/v1/comments/ POST /api/discussion/v1/comments/
{ {
"thread_id": "0123456789abcdef01234567", "thread_id": "0123456789abcdef01234567",
...@@ -310,7 +313,7 @@ class CommentViewSet(_ViewMixin, DeveloperErrorViewMixin, ViewSet): ...@@ -310,7 +313,7 @@ class CommentViewSet(_ViewMixin, DeveloperErrorViewMixin, ViewSet):
DELETE /api/discussion/v1/comments/comment_id DELETE /api/discussion/v1/comments/comment_id
**GET Parameters**: **GET Comment List Parameters**:
* thread_id (required): The thread to retrieve comments for * thread_id (required): The thread to retrieve comments for
...@@ -325,6 +328,15 @@ class CommentViewSet(_ViewMixin, DeveloperErrorViewMixin, ViewSet): ...@@ -325,6 +328,15 @@ class CommentViewSet(_ViewMixin, DeveloperErrorViewMixin, ViewSet):
* mark_as_read: Will mark the thread of the comments as read. (default * mark_as_read: Will mark the thread of the comments as read. (default
is False) is False)
**GET Child Comment List Parameters**:
* comment_id (required): The comment to retrieve child comments for
* page: The (1-indexed) page to retrieve (default is 1)
* page_size: The number of items per page (default is 10, max is 100)
**POST Parameters**: **POST Parameters**:
* thread_id (required): The thread to post the comment in * thread_id (required): The thread to post the comment in
...@@ -420,6 +432,22 @@ class CommentViewSet(_ViewMixin, DeveloperErrorViewMixin, ViewSet): ...@@ -420,6 +432,22 @@ class CommentViewSet(_ViewMixin, DeveloperErrorViewMixin, ViewSet):
) )
) )
def retrieve(self, request, comment_id=None):
"""
Implements the GET method for comments against response ID
"""
form = _PaginationForm(request.GET)
if not form.is_valid():
raise ValidationError(form.errors)
return Response(
get_response_comments(
request,
comment_id,
form.cleaned_data["page"],
form.cleaned_data["page_size"]
)
)
def create(self, request): def create(self, request):
""" """
Implements the POST method for the list endpoint as described in the Implements the POST method for the list endpoint as described in the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment