diff --git a/lms/djangoapps/discussion/rest_api/api.py b/lms/djangoapps/discussion/rest_api/api.py index 7244127dc2a3..19ccf26d19a4 100644 --- a/lms/djangoapps/discussion/rest_api/api.py +++ b/lms/djangoapps/discussion/rest_api/api.py @@ -279,7 +279,7 @@ def get_thread_list_url(request, course_key, topic_id_list=None, following=False return request.build_absolute_uri(urlunparse(("", "", path, "", urlencode(query_list), ""))) -def get_course(request, course_key): +def get_course(request, course_key, check_tab=True): """ Return general discussion information for the course. @@ -289,6 +289,7 @@ def get_course(request, course_key): determining the requesting user. course_key: The key of the course to get information for + check_tab: Whether to check if the discussion tab is enabled for the course Returns: @@ -322,7 +323,7 @@ def _format_datetime(dt): """ return dt.isoformat().replace('+00:00', 'Z') - course = _get_course(course_key, request.user) + course = _get_course(course_key, request.user, check_tab=check_tab) user_roles = get_user_role_names(request.user, course_key) course_config = DiscussionsConfiguration.get(course_key) EDIT_REASON_CODES = getattr(settings, "DISCUSSION_MODERATION_EDIT_REASON_CODES", {}) @@ -331,7 +332,7 @@ def _format_datetime(dt): course_config.posting_restrictions, course.get_discussion_blackout_datetimes() ) - + discussion_tab = CourseTabList.get_tab_by_type(course.tabs, 'discussion') return { "id": str(course_key), "is_posting_enabled": is_posting_enabled, @@ -370,7 +371,7 @@ def _format_datetime(dt): {"code": reason_code, "label": label} for (reason_code, label) in CLOSE_REASON_CODES.items() ], - + 'show_discussions': bool(discussion_tab and discussion_tab.is_enabled(course, request.user)), } diff --git a/lms/djangoapps/discussion/rest_api/tests/test_api.py b/lms/djangoapps/discussion/rest_api/tests/test_api.py index 18c4447a54c1..5e34b688d15f 100644 --- a/lms/djangoapps/discussion/rest_api/tests/test_api.py +++ b/lms/djangoapps/discussion/rest_api/tests/test_api.py @@ -189,6 +189,10 @@ def test_discussions_disabled(self): with pytest.raises(DiscussionDisabledError): get_course(self.request, _discussion_disabled_course_for(self.user).id) + def test_discussions_disabled_v2(self): + data = get_course(self.request, _discussion_disabled_course_for(self.user).id, False) + assert data['show_discussions'] is False + def test_basic(self): assert get_course(self.request, self.course.id) == { 'id': str(self.course.id), @@ -211,6 +215,7 @@ def test_basic(self): 'user_roles': {'Student'}, 'edit_reasons': [{'code': 'test-edit-reason', 'label': 'Test Edit Reason'}], 'post_close_reasons': [{'code': 'test-close-reason', 'label': 'Test Close Reason'}], + 'show_discussions': True, } @ddt.data( diff --git a/lms/djangoapps/discussion/rest_api/tests/test_views.py b/lms/djangoapps/discussion/rest_api/tests/test_views.py index af41e4b87174..d7bf6c0e139e 100644 --- a/lms/djangoapps/discussion/rest_api/tests/test_views.py +++ b/lms/djangoapps/discussion/rest_api/tests/test_views.py @@ -538,6 +538,7 @@ def test_basic(self): "user_roles": ["Student"], "edit_reasons": [{"code": "test-edit-reason", "label": "Test Edit Reason"}], "post_close_reasons": [{"code": "test-close-reason", "label": "Test Close Reason"}], + 'show_discussions': True, } ) diff --git a/lms/djangoapps/discussion/rest_api/urls.py b/lms/djangoapps/discussion/rest_api/urls.py index 13d06288d639..f8c5bb3255b0 100644 --- a/lms/djangoapps/discussion/rest_api/urls.py +++ b/lms/djangoapps/discussion/rest_api/urls.py @@ -16,6 +16,7 @@ CourseTopicsViewV2, CourseTopicsViewV3, CourseView, + CourseViewV2, LearnerThreadView, ReplaceUsernamesView, RetireUserView, @@ -64,6 +65,11 @@ CourseView.as_view(), name="discussion_course" ), + re_path( + fr"^v2/courses/{settings.COURSE_ID_PATTERN}", + CourseViewV2.as_view(), + name="discussion_course_v2" + ), re_path(r'^v1/accounts/retire_forum/?$', RetireUserView.as_view(), name="retire_discussion_user"), path('v1/accounts/replace_username', ReplaceUsernamesView.as_view(), name="replace_discussion_username"), re_path( diff --git a/lms/djangoapps/discussion/rest_api/views.py b/lms/djangoapps/discussion/rest_api/views.py index 905b4ab49038..2b0bf8c41e5b 100644 --- a/lms/djangoapps/discussion/rest_api/views.py +++ b/lms/djangoapps/discussion/rest_api/views.py @@ -119,6 +119,36 @@ def get(self, request, course_id): return Response(get_course(request, course_key)) +@view_auth_classes() +class CourseViewV2(DeveloperErrorViewMixin, APIView): + """ + General discussion metadata API v2. + """ + + @apidocs.schema( + parameters=[ + apidocs.string_parameter("course_id", apidocs.ParameterLocation.PATH, description="Course ID") + ], + responses={ + 200: CourseMetadataSerailizer(read_only=True, required=False), + 401: "The requester is not authenticated.", + 403: "The requester cannot access the specified course.", + 404: "The requested course does not exist.", + } + ) + def get(self, request, course_id): + """ + Retrieve general discussion metadata for a course. + + **Example Requests**: + GET /api/discussion/v2/courses/course-v1:ExampleX+Subject101+2015 + """ + course_key = CourseKey.from_string(course_id) + # Record user activity for tracking progress towards a user's course goals (for mobile app) + UserActivity.record_user_activity(request.user, course_key, request=request, only_if_mobile_app=True) + return Response(get_course(request, course_key, False)) + + @view_auth_classes() class CourseActivityStatsView(DeveloperErrorViewMixin, APIView): """