Display warning message on course outline in Studio when course contains deprecated features/components

TNL-2303
This commit is contained in:
muhammad-ammar
2015-06-10 16:37:02 +05:00
parent 1a9a69829a
commit b0eda4cac9
18 changed files with 693 additions and 63 deletions

View File

@@ -1,94 +0,0 @@
"""
API implementation of the Course Structure API for Python code.
Note: The course list and course detail functionality isn't currently supported here because
of the tricky interactions between DRF and the code.
Most of that information is available by accessing the course objects directly.
"""
from course_structure_api.v0 import serializers
from course_structure_api.v0.errors import CourseNotFoundError, CourseStructureNotAvailableError
from openedx.core.djangoapps.content.course_structures import models, tasks
from courseware import courses
def _retrieve_course(course_key):
"""Retrieves the course for the given course key.
Args:
course_key: The CourseKey for the course we'd like to retrieve.
Returns:
the course that matches the CourseKey
Raises:
CourseNotFoundError
"""
try:
return courses.get_course(course_key)
except ValueError:
raise CourseNotFoundError
def course_structure(course_key):
"""
Retrieves the entire course structure, including information about all the blocks used in the course.
Args:
course_key: the CourseKey of the course we'd like to retrieve.
Returns:
The serialized output of the course structure:
* root: The ID of the root node of the course structure.
* blocks: A dictionary that maps block IDs to a collection of
information about each block. Each block contains the following
fields.
* id: The ID of the block.
* type: The type of block. Possible values include sequential,
vertical, html, problem, video, and discussion. The type can also be
the name of a custom type of block used for the course.
* display_name: The display name configured for the block.
* graded: Whether or not the sequential or problem is graded. The
value is true or false.
* format: The assignment type.
* children: If the block has child blocks, a list of IDs of the child
blocks.
Raises:
CourseStructureNotAvailableError, CourseNotFoundError
"""
course = _retrieve_course(course_key)
try:
requested_course_structure = models.CourseStructure.objects.get(course_id=course.id)
return serializers.CourseStructureSerializer(requested_course_structure.structure).data
except models.CourseStructure.DoesNotExist:
# If we don't have data stored, generate it and return an error.
tasks.update_course_structure.delay(unicode(course_key))
raise CourseStructureNotAvailableError
def course_grading_policy(course_key):
"""
Retrieves the course grading policy.
Args:
course_key: CourseKey the corresponds to the course we'd like to know grading policy information about.
Returns:
The serialized version of the course grading policy containing the following information:
* assignment_type: The type of the assignment, as configured by course
staff. For example, course staff might make the assignment types Homework,
Quiz, and Exam.
* count: The number of assignments of the type.
* dropped: Number of assignments of the type that are dropped.
* weight: The weight, or effect, of the assignment type on the learner's
final grade.
"""
course = _retrieve_course(course_key)
return serializers.GradingPolicySerializer(course.raw_grader).data

View File

@@ -1,11 +0,0 @@
""" Errors used by the Course Structure API. """
class CourseNotFoundError(Exception):
""" The course was not found. """
pass
class CourseStructureNotAvailableError(Exception):
""" The course structure still needs to be generated. """
pass

View File

@@ -40,37 +40,3 @@ class CourseSerializer(serializers.Serializer):
def get_image_url(self, course):
""" Get the course image URL """
return course_image_url(course)
class GradingPolicySerializer(serializers.Serializer):
""" Serializer for course grading policy. """
assignment_type = serializers.CharField(source='type')
count = serializers.IntegerField(source='min_count')
dropped = serializers.IntegerField(source='drop_count')
weight = serializers.FloatField()
# pylint: disable=invalid-name
class BlockSerializer(serializers.Serializer):
""" Serializer for course structure block. """
id = serializers.CharField(source='usage_key')
type = serializers.CharField(source='block_type')
display_name = serializers.CharField()
graded = serializers.BooleanField(default=False)
format = serializers.CharField()
children = serializers.CharField()
class CourseStructureSerializer(serializers.Serializer):
""" Serializer for course structure. """
root = serializers.CharField(source='root')
blocks = serializers.SerializerMethodField('get_blocks')
def get_blocks(self, structure):
""" Serialize the individual blocks. """
serialized = {}
for key, block in structure['blocks'].iteritems():
serialized[key] = BlockSerializer(block).data
return serialized

View File

@@ -9,7 +9,6 @@ from mock import patch, Mock
from itertools import product
from django.core.urlresolvers import reverse
from django.test.utils import override_settings
from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from oauth2_provider.tests.factories import AccessTokenFactory, ClientFactory
@@ -336,6 +335,7 @@ class CourseStructureTests(CourseDetailTestMixin, CourseViewTestsMixin, ModuleSt
blocks[unicode(xblock.location)] = {
u'id': unicode(xblock.location),
u'type': xblock.category,
u'parent': None,
u'display_name': xblock.display_name,
u'format': xblock.format,
u'graded': xblock.graded,

View File

@@ -15,14 +15,14 @@ from rest_framework.reverse import reverse
from xmodule.modulestore.django import modulestore
from opaque_keys.edx.keys import CourseKey
from course_structure_api.v0 import api, serializers
from course_structure_api.v0.errors import CourseNotFoundError, CourseStructureNotAvailableError
from course_structure_api.v0 import serializers
from courseware import courses
from courseware.access import has_access
from courseware.model_data import FieldDataCache
from courseware.module_render import get_module_for_descriptor
from openedx.core.lib.api.view_utils import view_course_access, view_auth_classes
from openedx.core.lib.api.serializers import PaginationSerializer
from openedx.core.djangoapps.content.course_structures.api.v0 import api, errors
from student.roles import CourseInstructorRole, CourseStaffRole
from util.module_utils import get_dynamic_descriptor_children
@@ -73,7 +73,7 @@ class CourseViewMixin(object):
self.course_key = CourseKey.from_string(course_id)
self.check_course_permissions(self.request.user, self.course_key)
return func(self, *args, **kwargs)
except CourseNotFoundError:
except errors.CourseNotFoundError:
raise Http404
return func_wrapper
@@ -262,7 +262,7 @@ class CourseStructure(CourseViewMixin, RetrieveAPIView):
def get(self, request, **kwargs):
try:
return Response(api.course_structure(self.course_key))
except CourseStructureNotAvailableError:
except errors.CourseStructureNotAvailableError:
# If we don't have data stored, we will try to regenerate it, so
# return a 503 and as them to retry in 2 minutes.
return Response(status=503, headers={'Retry-After': '120'})