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).
This commit is contained in:
@@ -14,6 +14,7 @@ from django_comment_common.models import (
|
||||
Role,
|
||||
)
|
||||
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
|
||||
|
||||
|
||||
@@ -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
|
||||
representation of the format returned by the comments service) to the format
|
||||
@@ -98,6 +99,10 @@ def _cc_thread_to_api_thread(thread):
|
||||
ret.update({
|
||||
"topic_id": thread["commentable_id"],
|
||||
"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"],
|
||||
"unread_comment_count": thread["unread_comments_count"],
|
||||
})
|
||||
@@ -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],
|
||||
users=request.user
|
||||
).exists()
|
||||
cc_user = User.from_django_user(request.user).retrieve()
|
||||
threads, result_page, num_pages, _ = Thread.search({
|
||||
"course_id": unicode(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):
|
||||
if result_page != page:
|
||||
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)
|
||||
|
||||
@@ -323,13 +323,16 @@ class GetCourseTopicsTest(ModuleStoreTestCase):
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@httpretty.activate
|
||||
class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
|
||||
"""Test for get_thread_list"""
|
||||
def setUp(self):
|
||||
super(GetThreadListTest, self).setUp()
|
||||
httpretty.reset()
|
||||
httpretty.enable()
|
||||
self.addCleanup(httpretty.disable)
|
||||
self.maxDiff = None # pylint: disable=invalid-name
|
||||
self.user = UserFactory.create()
|
||||
self.register_get_user_response(self.user)
|
||||
self.request = RequestFactory().get("/test_path")
|
||||
self.request.user = self.user
|
||||
self.course = CourseFactory.create()
|
||||
@@ -366,6 +369,11 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
|
||||
})
|
||||
|
||||
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 = [
|
||||
{
|
||||
"id": "test_thread_id_0",
|
||||
@@ -378,6 +386,8 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
|
||||
"body": "Test body",
|
||||
"pinned": False,
|
||||
"closed": False,
|
||||
"abuse_flaggers": [],
|
||||
"votes": {"up_count": 4},
|
||||
"comments_count": 5,
|
||||
"unread_comments_count": 3,
|
||||
},
|
||||
@@ -392,6 +402,8 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
|
||||
"body": "More content",
|
||||
"pinned": False,
|
||||
"closed": True,
|
||||
"abuse_flaggers": [],
|
||||
"votes": {"up_count": 9},
|
||||
"comments_count": 18,
|
||||
"unread_comments_count": 0,
|
||||
},
|
||||
@@ -406,6 +418,8 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
|
||||
"body": "Still more content",
|
||||
"pinned": True,
|
||||
"closed": False,
|
||||
"abuse_flaggers": [str(self.user.id)],
|
||||
"votes": {"up_count": 0},
|
||||
"comments_count": 0,
|
||||
"unread_comments_count": 0,
|
||||
},
|
||||
@@ -422,6 +436,10 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
|
||||
"raw_body": "Test body",
|
||||
"pinned": False,
|
||||
"closed": False,
|
||||
"following": True,
|
||||
"abuse_flagged": False,
|
||||
"voted": False,
|
||||
"vote_count": 4,
|
||||
"comment_count": 5,
|
||||
"unread_comment_count": 3,
|
||||
},
|
||||
@@ -436,6 +454,10 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
|
||||
"raw_body": "More content",
|
||||
"pinned": False,
|
||||
"closed": True,
|
||||
"following": False,
|
||||
"abuse_flagged": False,
|
||||
"voted": True,
|
||||
"vote_count": 9,
|
||||
"comment_count": 18,
|
||||
"unread_comment_count": 0,
|
||||
},
|
||||
@@ -450,6 +472,10 @@ class GetThreadListTest(CommentsServiceMockMixin, ModuleStoreTestCase):
|
||||
"raw_body": "Still more content",
|
||||
"pinned": True,
|
||||
"closed": False,
|
||||
"following": False,
|
||||
"abuse_flagged": True,
|
||||
"voted": False,
|
||||
"vote_count": 0,
|
||||
"comment_count": 0,
|
||||
"unread_comment_count": 0,
|
||||
},
|
||||
|
||||
@@ -141,6 +141,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
)
|
||||
|
||||
def test_basic(self):
|
||||
self.register_get_user_response(self.user, upvoted_ids=["test_thread"])
|
||||
source_threads = [{
|
||||
"id": "test_thread",
|
||||
"course_id": unicode(self.course.id),
|
||||
@@ -152,6 +153,8 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"body": "Test body",
|
||||
"pinned": False,
|
||||
"closed": False,
|
||||
"abuse_flaggers": [],
|
||||
"votes": {"up_count": 4},
|
||||
"comments_count": 5,
|
||||
"unread_comments_count": 3,
|
||||
}]
|
||||
@@ -166,6 +169,10 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"raw_body": "Test body",
|
||||
"pinned": False,
|
||||
"closed": False,
|
||||
"following": False,
|
||||
"abuse_flagged": False,
|
||||
"voted": True,
|
||||
"vote_count": 4,
|
||||
"comment_count": 5,
|
||||
"unread_comment_count": 3,
|
||||
}]
|
||||
@@ -190,6 +197,7 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
})
|
||||
|
||||
def test_pagination(self):
|
||||
self.register_get_user_response(self.user)
|
||||
self.register_get_threads_response([], page=1, num_pages=1)
|
||||
response = self.client.get(
|
||||
self.url,
|
||||
|
||||
@@ -21,6 +21,19 @@ class CommentsServiceMockMixin(object):
|
||||
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):
|
||||
"""
|
||||
Assert that the last mock request had the expected query parameters
|
||||
|
||||
Reference in New Issue
Block a user