AA-150: Adding a general end point for the Course Home MFE

This endpoint is intended to contain generic information for
every page in the Course Home MFE. It contains course information
for the header (Course title, org, number, key) as well as staff
status for the user and the Course tabs to display.
This commit is contained in:
Dillon Dumesnil
2020-05-21 08:37:17 -07:00
parent 97af77e785
commit 8a74bbd5fb
11 changed files with 172 additions and 4 deletions

View File

@@ -0,0 +1,37 @@
# pylint: disable=abstract-method
"""
Course Home Course Metadata Serializers. Returns Course Metadata used for all
Course Home pages.
"""
from django.urls import reverse
from rest_framework import serializers
class CourseTabSerializer(serializers.Serializer):
"""
Serializer for the Course Home Tabs
"""
tab_id = serializers.CharField()
title = serializers.SerializerMethodField()
url = serializers.SerializerMethodField()
def get_title(self, tab):
return tab.title or tab.get('name', '')
def get_url(self, tab):
request = self.context.get('request')
return request.build_absolute_uri(tab.link_func(self.context.get('course'), reverse))
class CourseHomeMetadataSerializer(serializers.Serializer):
"""
Serializer for the Course Home Course Metadata
"""
course_id = serializers.CharField()
is_staff = serializers.BooleanField()
number = serializers.CharField()
org = serializers.CharField()
tabs = CourseTabSerializer(many=True)
title = serializers.CharField()

View File

@@ -0,0 +1,53 @@
"""
Tests for the Course Home Course Metadata API in the Course Home API
"""
import ddt
from django.urls import reverse
from course_modes.models import CourseMode
from lms.djangoapps.course_home_api.tests.utils import BaseCourseHomeTests
from student.models import CourseEnrollment
from student.tests.factories import UserFactory
@ddt.ddt
class CourseHomeMetadataTests(BaseCourseHomeTests):
"""
Tests for the Course Home Course Metadata API
"""
@classmethod
def setUpClass(cls):
BaseCourseHomeTests.setUpClass()
cls.url = reverse('course-home-course-metadata', args=[cls.course.id])
def test_get_authenticated_user(self):
CourseEnrollment.enroll(self.user, self.course.id, CourseMode.VERIFIED)
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertFalse(response.data.get('is_staff'))
# 'Course', 'Wiki', 'Progress' tabs
self.assertEqual(len(response.data.get('tabs', [])), 3)
def test_get_authenticated_staff_user(self):
self.client.logout()
staff_user = UserFactory(
username='staff',
email='staff@example.com',
password='bar',
is_staff=True
)
self.client.login(username=staff_user.username, password='bar')
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
self.assertTrue(response.data['is_staff'])
# This differs for a staff user because they also receive the Instructor tab
# 'Course', 'Wiki', 'Progress', and 'Instructor' tabs
self.assertEqual(len(response.data.get('tabs', [])), 4)
def test_get_unknown_course(self):
url = reverse('course-home-course-metadata', args=['course-v1:unknown+course+2T2020'])
response = self.client.get(url)
self.assertEqual(response.status_code, 404)

View File

@@ -0,0 +1,65 @@
"""
General view for the Course Home that contains metadata every page needs.
"""
from rest_framework.generics import RetrieveAPIView
from rest_framework.response import Response
from opaque_keys.edx.keys import CourseKey
from lms.djangoapps.courseware.access import has_access
from lms.djangoapps.courseware.tabs import get_course_tab_list
from lms.djangoapps.course_api.api import course_detail
from lms.djangoapps.course_home_api.course_metadata.v1.serializers import CourseHomeMetadataSerializer
class CourseHomeMetadataView(RetrieveAPIView):
"""
**Use Cases**
Request Course metadata details for the Course Home MFE that every page needs.
**Example Requests**
GET api/course_home/v1/course_metadata/{course_key}
**Response Values**
Body consists of the following fields:
course_id: (str) The Course's id (Course Run key)
is_staff: (bool) Indicates if the user is staff
number: (str) The Course's number
org: (str) The Course's organization
tabs: List of Course Tabs to display. They are serialized as:
tab_id: (str) The tab's id
title: (str) The title of the tab to display
url: (str) The url to view the tab
title: (str) The Course's display title
**Returns**
* 200 on success with above fields.
* 404 if the course is not available or cannot be seen.
"""
serializer_class = CourseHomeMetadataSerializer
def get(self, request, *args, **kwargs):
course_key_string = kwargs.get('course_key_string')
course_key = CourseKey.from_string(course_key_string)
course = course_detail(request, request.user.username, course_key)
data = {
'course_id': course.id,
'is_staff': has_access(request.user, 'staff', course_key).has_access,
'number': course.display_number_with_default,
'org': course.display_org_with_default,
'tabs': get_course_tab_list(request.user, course),
'title': course.display_name_with_default,
}
context = self.get_serializer_context()
context['course'] = course
serializer = self.get_serializer_class()(data, context=context)
return Response(serializer.data)

View File

@@ -1,3 +1,4 @@
# pylint: disable=abstract-method
"""
Dates Tab Serializers. Represents the relevant dates for a Course.
"""

View File

@@ -56,7 +56,9 @@ class DatesTabView(RetrieveAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = DatesTabSerializer
def get(self, request, course_key_string):
def get(self, request, *args, **kwargs):
course_key_string = kwargs.get('course_key_string')
# Enable NR tracing for this view based on course
monitoring_utils.set_custom_metric('course_id', course_key_string)
monitoring_utils.set_custom_metric('user_id', request.user.id)

View File

@@ -40,7 +40,7 @@ class BaseCourseHomeTests(SharedModuleStoreTestCase):
modulestore=cls.store,
)
chapter = ItemFactory(parent=cls.course, category='chapter')
ItemFactory(parent=chapter, category='sequential', display_name='sequence')
ItemFactory(parent=chapter, category='sequential')
CourseModeFactory(course_id=cls.course.id, mode_slug=CourseMode.AUDIT)
CourseModeFactory(

View File

@@ -6,15 +6,25 @@ Contains all the URLs for the Course Home
from django.conf import settings
from django.urls import re_path
from lms.djangoapps.course_home_api.dates.v1 import views
from lms.djangoapps.course_home_api.dates.v1.views import DatesTabView
from lms.djangoapps.course_home_api.course_metadata.v1.views import CourseHomeMetadataView
urlpatterns = []
# URL for Course metadata content
urlpatterns += [
re_path(
r'v1/course_metadata/{}'.format(settings.COURSE_KEY_PATTERN),
CourseHomeMetadataView.as_view(),
name='course-home-course-metadata'
),
]
# Dates Tab URLs
urlpatterns += [
re_path(
r'v1/dates/{}'.format(settings.COURSE_KEY_PATTERN),
views.DatesTabView.as_view(),
DatesTabView.as_view(),
name='course-home-dates-tab'
),
]