Commit fa6e5338 by Greg Price

Add fields to discussion thread list endpoint

This commit adds fields that are related to the requesting user's
interaction with the thread (e.g. following).
parent 603eae65
...@@ -14,6 +14,7 @@ from django_comment_common.models import ( ...@@ -14,6 +14,7 @@ from django_comment_common.models import (
Role, Role,
) )
from lms.lib.comment_client.thread import Thread from lms.lib.comment_client.thread import Thread
from lms.lib.comment_client.user import User
from openedx.core.djangoapps.course_groups.cohorts import get_cohort_id from openedx.core.djangoapps.course_groups.cohorts import get_cohort_id
...@@ -76,7 +77,7 @@ def get_course_topics(course, user): ...@@ -76,7 +77,7 @@ def get_course_topics(course, user):
} }
def _cc_thread_to_api_thread(thread): def _cc_thread_to_api_thread(thread, cc_user):
""" """
Convert a thread data dict from the comment_client format (which is a direct Convert a thread data dict from the comment_client format (which is a direct
representation of the format returned by the comments service) to the format representation of the format returned by the comments service) to the format
...@@ -98,6 +99,10 @@ def _cc_thread_to_api_thread(thread): ...@@ -98,6 +99,10 @@ def _cc_thread_to_api_thread(thread):
ret.update({ ret.update({
"topic_id": thread["commentable_id"], "topic_id": thread["commentable_id"],
"raw_body": thread["body"], "raw_body": thread["body"],
"following": thread["id"] in cc_user["subscribed_thread_ids"],
"abuse_flagged": cc_user["id"] in thread["abuse_flaggers"],
"voted": thread["id"] in cc_user["upvoted_ids"],
"vote_count": thread["votes"]["up_count"],
"comment_count": thread["comments_count"], "comment_count": thread["comments_count"],
"unread_comment_count": thread["unread_comments_count"], "unread_comment_count": thread["unread_comments_count"],
}) })
...@@ -125,6 +130,7 @@ def get_thread_list(request, course_key, page, page_size): ...@@ -125,6 +130,7 @@ def get_thread_list(request, course_key, page, page_size):
name__in=[FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA], name__in=[FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA],
users=request.user users=request.user
).exists() ).exists()
cc_user = User.from_django_user(request.user).retrieve()
threads, result_page, num_pages, _ = Thread.search({ threads, result_page, num_pages, _ = Thread.search({
"course_id": unicode(course_key), "course_id": unicode(course_key),
"group_id": None if user_is_privileged else get_cohort_id(request.user, course_key), "group_id": None if user_is_privileged else get_cohort_id(request.user, course_key),
...@@ -139,5 +145,5 @@ def get_thread_list(request, course_key, page, page_size): ...@@ -139,5 +145,5 @@ def get_thread_list(request, course_key, page, page_size):
if result_page != page: if result_page != page:
raise Http404 raise Http404
results = [_cc_thread_to_api_thread(thread) for thread in threads] results = [_cc_thread_to_api_thread(thread, cc_user) for thread in threads]
return get_paginated_data(request, results, page, num_pages) return get_paginated_data(request, results, page, num_pages)
...@@ -323,13 +323,16 @@ class GetCourseTopicsTest(ModuleStoreTestCase): ...@@ -323,13 +323,16 @@ class GetCourseTopicsTest(ModuleStoreTestCase):
@ddt.ddt @ddt.ddt
@httpretty.activate
class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase): class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
"""Test for get_thread_list""" """Test for get_thread_list"""
def setUp(self): def setUp(self):
super(GetThreadListTest, self).setUp() super(GetThreadListTest, self).setUp()
httpretty.reset()
httpretty.enable()
self.addCleanup(httpretty.disable)
self.maxDiff = None # pylint: disable=invalid-name self.maxDiff = None # pylint: disable=invalid-name
self.user = UserFactory.create() self.user = UserFactory.create()
self.register_get_user_response(self.user)
self.request = RequestFactory().get("/test_path") self.request = RequestFactory().get("/test_path")
self.request.user = self.user self.request.user = self.user
self.course = CourseFactory.create() self.course = CourseFactory.create()
...@@ -366,6 +369,11 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase): ...@@ -366,6 +369,11 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
}) })
def test_thread_content(self): def test_thread_content(self):
self.register_get_user_response(
self.user,
subscribed_thread_ids=["test_thread_id_0"],
upvoted_ids=["test_thread_id_1"]
)
source_threads = [ source_threads = [
{ {
"id": "test_thread_id_0", "id": "test_thread_id_0",
...@@ -378,6 +386,8 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase): ...@@ -378,6 +386,8 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
"body": "Test body", "body": "Test body",
"pinned": False, "pinned": False,
"closed": False, "closed": False,
"abuse_flaggers": [],
"votes": {"up_count": 4},
"comments_count": 5, "comments_count": 5,
"unread_comments_count": 3, "unread_comments_count": 3,
}, },
...@@ -392,6 +402,8 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase): ...@@ -392,6 +402,8 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
"body": "More content", "body": "More content",
"pinned": False, "pinned": False,
"closed": True, "closed": True,
"abuse_flaggers": [],
"votes": {"up_count": 9},
"comments_count": 18, "comments_count": 18,
"unread_comments_count": 0, "unread_comments_count": 0,
}, },
...@@ -406,6 +418,8 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase): ...@@ -406,6 +418,8 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
"body": "Still more content", "body": "Still more content",
"pinned": True, "pinned": True,
"closed": False, "closed": False,
"abuse_flaggers": [str(self.user.id)],
"votes": {"up_count": 0},
"comments_count": 0, "comments_count": 0,
"unread_comments_count": 0, "unread_comments_count": 0,
}, },
...@@ -422,6 +436,10 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase): ...@@ -422,6 +436,10 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
"raw_body": "Test body", "raw_body": "Test body",
"pinned": False, "pinned": False,
"closed": False, "closed": False,
"following": True,
"abuse_flagged": False,
"voted": False,
"vote_count": 4,
"comment_count": 5, "comment_count": 5,
"unread_comment_count": 3, "unread_comment_count": 3,
}, },
...@@ -436,6 +454,10 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase): ...@@ -436,6 +454,10 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
"raw_body": "More content", "raw_body": "More content",
"pinned": False, "pinned": False,
"closed": True, "closed": True,
"following": False,
"abuse_flagged": False,
"voted": True,
"vote_count": 9,
"comment_count": 18, "comment_count": 18,
"unread_comment_count": 0, "unread_comment_count": 0,
}, },
...@@ -450,6 +472,10 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase): ...@@ -450,6 +472,10 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
"raw_body": "Still more content", "raw_body": "Still more content",
"pinned": True, "pinned": True,
"closed": False, "closed": False,
"following": False,
"abuse_flagged": True,
"voted": False,
"vote_count": 0,
"comment_count": 0, "comment_count": 0,
"unread_comment_count": 0, "unread_comment_count": 0,
}, },
......
...@@ -141,6 +141,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase): ...@@ -141,6 +141,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
) )
def test_basic(self): def test_basic(self):
self.register_get_user_response(self.user, upvoted_ids=["test_thread"])
source_threads = [{ source_threads = [{
"id": "test_thread", "id": "test_thread",
"course_id": unicode(self.course.id), "course_id": unicode(self.course.id),
...@@ -152,6 +153,8 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase): ...@@ -152,6 +153,8 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
"body": "Test body", "body": "Test body",
"pinned": False, "pinned": False,
"closed": False, "closed": False,
"abuse_flaggers": [],
"votes": {"up_count": 4},
"comments_count": 5, "comments_count": 5,
"unread_comments_count": 3, "unread_comments_count": 3,
}] }]
...@@ -166,6 +169,10 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase): ...@@ -166,6 +169,10 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
"raw_body": "Test body", "raw_body": "Test body",
"pinned": False, "pinned": False,
"closed": False, "closed": False,
"following": False,
"abuse_flagged": False,
"voted": True,
"vote_count": 4,
"comment_count": 5, "comment_count": 5,
"unread_comment_count": 3, "unread_comment_count": 3,
}] }]
...@@ -190,6 +197,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase): ...@@ -190,6 +197,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
}) })
def test_pagination(self): def test_pagination(self):
self.register_get_user_response(self.user)
self.register_get_threads_response([], page=1, num_pages=1) self.register_get_threads_response([], page=1, num_pages=1)
response = self.client.get( response = self.client.get(
self.url, self.url,
......
...@@ -21,6 +21,19 @@ class CommentsServiceMockMixin(object): ...@@ -21,6 +21,19 @@ class CommentsServiceMockMixin(object):
status=200 status=200
) )
def register_get_user_response(self, user, subscribed_thread_ids=None, upvoted_ids=None):
"""Register a mock response for GET on the CS user instance endpoint"""
httpretty.register_uri(
httpretty.GET,
"http://localhost:4567/api/v1/users/{id}".format(id=user.id),
body=json.dumps({
"id": str(user.id),
"subscribed_thread_ids": subscribed_thread_ids or [],
"upvoted_ids": upvoted_ids or [],
}),
status=200
)
def assert_last_query_params(self, expected_params): def assert_last_query_params(self, expected_params):
""" """
Assert that the last mock request had the expected query parameters Assert that the last mock request had the expected query parameters
......
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