Example #1
0
    def _get_resume_course_info(self, request, course_id):
        """
        Returns information relevant to resume course functionality.

        Returns a tuple: (has_visited_course, resume_course_url)
            has_visited_course: True if the user has ever completed a block, False otherwise.
            resume_course_url: The URL of the 'resume course' block if the user has completed a block,
                otherwise the URL of the first block to start the course.

        """
        course_outline_root_block = get_course_outline_block_tree(
            request, course_id, request.user)
        resume_block = get_resume_block(
            course_outline_root_block) if course_outline_root_block else None
        has_visited_course = bool(resume_block)
        if resume_block:
            resume_course_url = resume_block['lms_web_url']
        else:
            start_block = get_start_block(
                course_outline_root_block
            ) if course_outline_root_block else None
            resume_course_url = start_block[
                'lms_web_url'] if start_block else None

        return has_visited_course, resume_course_url
Example #2
0
def _get_course_section_mapping(request, course_id):
    """

    """
    course_section_mapping = {}

    if not course_id:
        return course_section_mapping

    # For all sections in course map the id to the display_name.
    course_block_tree = get_course_outline_block_tree(request, course_id)
    if not course_block_tree:
        return None

    course_sections = course_block_tree.get('children')

    course_section_mapping_id = 0
    for section in course_sections:
        course_section_mapping.update({
            section['id']: {
                'block_order': course_section_mapping_id,
                'display_name': section['display_name']
            }
        })

        course_section_mapping_id += 1

    return course_section_mapping
Example #3
0
 def get(self, request, course_id, **kwargs):
     """
     Displays the learning path page for the specified course.
     """
     course_key = CourseKey.from_string(course_id)
     course = get_course_by_id(course_key, depth=2)
     course_block_tree = get_course_outline_block_tree(request, course_id)
     completion_profile = CompletionProfile.objects.get(
         user=request.user, course_key=course_key)
     discussions_stats = get_forum_statistics(course_id, request.user.id)
     context = {
         'course':
         course,
         'display_name':
         course_block_tree['display_name'],
         'chapters':
         zip(course_block_tree['children'],
             completion_profile.chapterprogress.all()),
         'LANGUAGE_CODE':
         request.LANGUAGE_CODE,
         'learning_path_class':
         'active',
         'platform_name':
         configuration_helpers.get_value('PLATFORM_NAME',
                                         settings.PLATFORM_NAME),
         'request':
         request,
         'discussions_stats':
         discussions_stats,
     }
     return render_to_response('ed2go/learning_path.html', context)
Example #4
0
def get_course_assignments(course_key, user, request, include_access=False):
    """
    Returns a list of assignment (at the subsection/sequential level) due dates for the given course.

    Each returned object is a namedtuple with fields: title, url, date, contains_gated_content, complete, past_due
    """
    assignments = []
    # Ideally this function is always called with a request being passed in, but because it is also
    # a subfunction of `get_course_date_blocks` which does not require a request, we are being defensive here.
    if not request:
        return assignments

    now = datetime.now(pytz.UTC)
    course_root_block = get_course_outline_block_tree(request, str(course_key), user, allow_start_dates_in_future=True)
    for section in course_root_block.get('children', []):
        for subsection in section.get('children', []):
            if not subsection.get('due') or not subsection.get('graded'):
                continue

            contains_gated_content = include_access and subsection.get('contains_gated_content', False)
            title = subsection.get('display_name', _('Assignment'))

            url = None
            assignment_released = not subsection.get('start') or subsection.get('start') < now
            if assignment_released:
                url = subsection.get('lms_web_url')

            complete = subsection.get('complete')
            past_due = not complete and subsection.get('due', now + timedelta(1)) < now
            assignments.append(_Assignment(
                subsection.get('id'), title, url, subsection.get('due'), contains_gated_content, complete, past_due
            ))

    return assignments
Example #5
0
def is_course_accessed(user, course_id):
    """
    Check if the learner accessed the course.

    Arguments:
        user (User): Django User object.
        course_id (String): The course identifier

    Returns:
        (bool): True if course has been accessed by the enterprise learner.
    """
    request = _create_placeholder_request(user)
    course_outline_root_block = get_course_outline_block_tree(request, course_id, user)
    resume_block = get_resume_block(course_outline_root_block) if course_outline_root_block else None
    return bool(resume_block)
Example #6
0
def award_section_badges(course_id, request):
    """
    Traverse through the course outline and check each section to see if it needs to assign a badge.
    :return:
    """
    course_block_tree = get_course_outline_block_tree(request, course_id)
    if not course_block_tree:
        return None

    course_sections = course_block_tree.get('children')

    for section in course_sections:

        if section.get('complete'):
            award_section_badge(request.user, course_id, section['id'])
Example #7
0
 def get(self, request, course_id):
     """
     api to get course outline in sequence
     :param request:
     :param course_id:
     :return: dictionary of course outline tree structure
     """
     user = request.user
     try:
         course_tree = get_course_outline_block_tree(request, course_id, user)
     except ItemNotFoundError:
         # this exception is raised in few cases like if invalid course_id is passed
         return Response(data='Course not found', status=status.HTTP_404_NOT_FOUND)
     if course_tree is None:
         return Response(data='Course not found', status=status.HTTP_404_NOT_FOUND)
     return Response(course_tree, status=status.HTTP_200_OK)
Example #8
0
    def get(self, request, *args, **kwargs):
        from openedx.features.course_experience.utils import get_course_outline_block_tree
        logs.info('request %s', request.__dict__)
        data = request.data
        logs.info('data %s', data)
        popular_topic_list = []
        if 'HTTP_KEY' and 'HTTP_SECRET' in request.data:
            #log.info('key and secret parameter in header')
            key = data.get('HTTP_KEY')
            secret = data.get('HTTP_SECRET')
            #log.info('key, secret %s,%s',key,secret)
            from oauth2_provider.models import Application
            cliet_obj = Application.objects.filter(client_id=key,
                                                   client_secret=secret)
            if not cliet_obj:
                popular_topic_dict = {}
                popular_topic_dict["result"] = "Invalid Key and Secret"
                popular_topic_list.append(popular_topic_dict)
                return JsonResponse(popular_topic_list, status=200, safe=False)
        else:
            popular_topic_dict = {}
            popular_topic_dict["result"] = "Invalid Key and Secret"
            popular_topic_list.append(popular_topic_dict)
            return JsonResponse(popular_topic_list, status=200, safe=False)

        cid = CourseKey.from_string("course-v1:SVT+SVT001+2019_Feb_SVT001")

        user = User.objects.get(email=data.get('emailid'))
        enroll_user = CourseEnrollment.objects.get(course_id=cid,
                                                   is_active=1,
                                                   user=user)
        user_is_enrolled = True
        course_block_tree = get_course_outline_block_tree(
            request, str(enroll_user.course_id),
            enroll_user.user if user_is_enrolled else None)
        course_sections = course_block_tree.get('children')
        course_outline = []
        for section in course_sections:
            course_dict = {}
            for subsection in section.get('children', []):
                course_dict["unit_name"] = subsection['display_name']
                course_dict["unit_link"] = subsection['lms_web_url']
                break
            course_outline.append(course_dict)

        return JsonResponse(course_outline, status=200, safe=False)
Example #9
0
    def handle(self, *args, **options):
        course_key = None
        if len(args) == 1:
            course_key = CourseKey.from_string(args[0])

        module_store = modulestore()
        if course_key:
            course = module_store.get_course(course_key)
            courses = [course]
        else:
            courses = module_store.get_courses()

        fake_request = RequestFactory().get(u'/')
        fake_request.user = User.objects.filter(is_superuser=True).first()

        for course in courses:
            course_block_tree = get_course_outline_block_tree(fake_request, str(course.id))
            for chapter in course_block_tree['children']:
                key = chapter['display_name'].replace('.', ':')
                course.discussion_topics[key] = {u'id': 'i4x-edx-' + chapter['block_id']}
            module_store.update_item(course, fake_request.user.id)
Example #10
0
 def get_course_outline(self, model, course_id):
     """
     Get course outline of course_id
     :param model:
     :param course_id:
     :return:
     """
     tab_type = 'courseware'
     # from courseware.courses import get_course_with_access
     course_key = self.get_course_key(course_id)
     with self.get_module_store().bulk_operations(course_key):
         course, privilege = self.get_course_with_access(
             model.request.user, 'load', course_key)
         if not course:
             return None, privilege
         # Render the page
         # tab = CourseTabList.get_tab_by_type(course.tabs, tab_type)
         # page_context = create_page_context(request, course=course, tab=tab)
         from openedx.features.course_experience.utils import get_course_outline_block_tree
         courseware_outline = get_course_outline_block_tree(
             model.request, course_id)
         return xdj.dobject(courseware_outline), privilege
    def get(self, request, *args, **kwargs):
        course_key_string = kwargs.get('course_key_string')
        course_key = CourseKey.from_string(course_key_string)
        course_usage_key = modulestore().make_course_usage_key(course_key)

        if not course_home_mfe_outline_tab_is_active(course_key):
            raise Http404

        # Enable NR tracing for this view based on course
        monitoring_utils.set_custom_attribute('course_id', course_key_string)
        monitoring_utils.set_custom_attribute('user_id', request.user.id)
        monitoring_utils.set_custom_attribute('is_staff',
                                              request.user.is_staff)

        course = get_course_with_access(request.user,
                                        'load',
                                        course_key,
                                        check_if_enrolled=False)

        masquerade_object, request.user = setup_masquerade(
            request,
            course_key,
            staff_access=has_access(request.user, 'staff', course_key),
            reset_masquerade_data=True,
        )

        user_is_masquerading = is_masquerading(
            request.user, course_key, course_masquerade=masquerade_object)

        course_overview = CourseOverview.get_from_id(course_key)
        enrollment = CourseEnrollment.get_enrollment(request.user, course_key)
        allow_anonymous = COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled(
            course_key)
        allow_public = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC
        allow_public_outline = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC_OUTLINE

        # User locale settings
        user_timezone_locale = user_timezone_locale_prefs(request)
        user_timezone = user_timezone_locale['user_timezone']

        dates_tab_link = request.build_absolute_uri(
            reverse('dates', args=[course.id]))
        if course_home_mfe_dates_tab_is_active(course.id):
            dates_tab_link = get_learning_mfe_home_url(course_key=course.id,
                                                       view_name='dates')

        # Set all of the defaults
        access_expiration = None
        course_blocks = None
        course_goals = {'goal_options': [], 'selected_goal': None}
        course_tools = CourseToolsPluginManager.get_enabled_course_tools(
            request, course_key)
        dates_widget = {
            'course_date_blocks': [],
            'dates_tab_link': dates_tab_link,
            'user_timezone': user_timezone,
        }
        enroll_alert = {
            'can_enroll': True,
            'extra_text': None,
        }
        handouts_html = None
        offer_data = None
        resume_course = {
            'has_visited_course': False,
            'url': None,
        }
        welcome_message_html = None

        is_enrolled = enrollment and enrollment.is_active
        is_staff = bool(has_access(request.user, 'staff', course_key))
        show_enrolled = is_enrolled or is_staff
        if show_enrolled:
            course_blocks = get_course_outline_block_tree(
                request, course_key_string, request.user)
            date_blocks = get_course_date_blocks(course,
                                                 request.user,
                                                 request,
                                                 num_assignments=1)
            dates_widget['course_date_blocks'] = [
                block for block in date_blocks
                if not isinstance(block, TodaysDate)
            ]

            handouts_html = get_course_info_section(request, request.user,
                                                    course, 'handouts')
            welcome_message_html = get_current_update_for_user(request, course)

            offer_data = generate_offer_data(request.user, course_overview)
            access_expiration = get_access_expiration_data(
                request.user, course_overview)

            # Only show the set course goal message for enrolled, unverified
            # users in a course that allows for verified statuses.
            is_already_verified = CourseEnrollment.is_enrolled_as_verified(
                request.user, course_key)
            if not is_already_verified and has_course_goal_permission(
                    request, course_key_string, {'is_enrolled': is_enrolled}):
                course_goals = {
                    'goal_options':
                    valid_course_goals_ordered(include_unsure=True),
                    'selected_goal': None
                }

                selected_goal = get_course_goal(request.user, course_key)
                if selected_goal:
                    course_goals['selected_goal'] = {
                        'key': selected_goal.goal_key,
                        'text': get_course_goal_text(selected_goal.goal_key),
                    }

            try:
                resume_block = get_key_to_last_completed_block(
                    request.user, course.id)
                resume_course['has_visited_course'] = True
                resume_path = reverse('jump_to',
                                      kwargs={
                                          'course_id': course_key_string,
                                          'location': str(resume_block)
                                      })
                resume_course['url'] = request.build_absolute_uri(resume_path)
            except UnavailableCompletionData:
                start_block = get_start_block(course_blocks)
                resume_course['url'] = start_block['lms_web_url']

        elif allow_public_outline or allow_public or user_is_masquerading:
            course_blocks = get_course_outline_block_tree(
                request, course_key_string, None)
            if allow_public or user_is_masquerading:
                handouts_html = get_course_info_section(
                    request, request.user, course, 'handouts')

        if not show_enrolled:
            if CourseMode.is_masters_only(course_key):
                enroll_alert['can_enroll'] = False
                enroll_alert['extra_text'] = _(
                    'Please contact your degree administrator or '
                    'edX Support if you have questions.')
            elif course.invitation_only:
                enroll_alert['can_enroll'] = False

        data = {
            'access_expiration': access_expiration,
            'course_blocks': course_blocks,
            'course_goals': course_goals,
            'course_tools': course_tools,
            'dates_widget': dates_widget,
            'enroll_alert': enroll_alert,
            'handouts_html': handouts_html,
            'has_ended': course.has_ended(),
            'offer': offer_data,
            'resume_course': resume_course,
            'welcome_message_html': welcome_message_html,
        }
        context = self.get_serializer_context()
        context['course_overview'] = course_overview
        context['enable_links'] = show_enrolled or allow_public
        context['enrollment'] = enrollment
        serializer = self.get_serializer_class()(data, context=context)

        return Response(serializer.data)
Example #12
0
    def get(self, request, *args, **kwargs):
        course_key_string = kwargs.get('course_key_string')
        course_key = CourseKey.from_string(course_key_string)
        course_usage_key = modulestore().make_course_usage_key(course_key)

        if not course_home_mfe_outline_tab_is_active(course_key):
            raise Http404

        # Enable NR tracing for this view based on course
        monitoring_utils.set_custom_attribute('course_id', course_key_string)
        monitoring_utils.set_custom_attribute('user_id', request.user.id)
        monitoring_utils.set_custom_attribute('is_staff',
                                              request.user.is_staff)

        course = get_course_with_access(request.user,
                                        'load',
                                        course_key,
                                        check_if_enrolled=False)

        _masquerade, request.user = setup_masquerade(
            request,
            course_key,
            staff_access=has_access(request.user, 'staff', course_key),
            reset_masquerade_data=True,
        )

        course_overview = CourseOverview.get_from_id(course_key)
        enrollment = CourseEnrollment.get_enrollment(request.user, course_key)
        allow_anonymous = COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled(
            course_key)
        allow_public = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC
        allow_public_outline = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC_OUTLINE
        is_enrolled = enrollment and enrollment.is_active
        is_staff = bool(has_access(request.user, 'staff', course_key))
        show_enrolled = is_enrolled or is_staff

        show_handouts = show_enrolled or allow_public
        handouts_html = get_course_info_section(
            request, request.user, course, 'handouts') if show_handouts else ''

        # TODO: TNL-7185 Legacy: Refactor to return the offer & expired data and format the message in the MFE
        offer_html = show_enrolled and generate_offer_html(
            request.user, course_overview)
        course_expired_html = show_enrolled and generate_course_expired_message(
            request.user, course_overview)

        welcome_message_html = None
        if show_enrolled:
            if LATEST_UPDATE_FLAG.is_enabled(course_key):
                welcome_message_html = LatestUpdateFragmentView(
                ).latest_update_html(request, course)
            elif get_course_tag(request.user, course_key,
                                PREFERENCE_KEY) != 'False':
                welcome_message_html = WelcomeMessageFragmentView(
                ).welcome_message_html(request, course)

        enroll_alert = {
            'can_enroll': True,
            'extra_text': None,
        }
        if not show_enrolled:
            if CourseMode.is_masters_only(course_key):
                enroll_alert['can_enroll'] = False
                enroll_alert['extra_text'] = _(
                    'Please contact your degree administrator or '
                    'edX Support if you have questions.')
            elif course.invitation_only:
                enroll_alert['can_enroll'] = False

        course_tools = CourseToolsPluginManager.get_enabled_course_tools(
            request, course_key)
        date_blocks = get_course_date_blocks(course,
                                             request.user,
                                             request,
                                             num_assignments=1)

        # User locale settings
        user_timezone_locale = user_timezone_locale_prefs(request)
        user_timezone = user_timezone_locale['user_timezone']

        dates_tab_link = request.build_absolute_uri(
            reverse('dates', args=[course.id]))
        if course_home_mfe_dates_tab_is_active(course.id):
            dates_tab_link = get_microfrontend_url(course_key=course.id,
                                                   view_name='dates')

        course_blocks = None
        if show_enrolled or allow_public or allow_public_outline:
            outline_user = request.user if show_enrolled else None
            course_blocks = get_course_outline_block_tree(
                request, course_key_string, outline_user)

        resume_course = {
            'has_visited_course': False,
            'url': None,
        }
        if show_enrolled:
            try:
                resume_block = get_key_to_last_completed_block(
                    request.user, course.id)
                resume_course['has_visited_course'] = True
            except UnavailableCompletionData:
                resume_block = course_usage_key
            resume_path = reverse('jump_to',
                                  kwargs={
                                      'course_id': course_key_string,
                                      'location': str(resume_block)
                                  })
            resume_course['url'] = request.build_absolute_uri(resume_path)

        dates_widget = {
            'course_date_blocks': [
                block for block in date_blocks
                if not isinstance(block, TodaysDate)
            ],
            'dates_tab_link':
            dates_tab_link,
            'user_timezone':
            user_timezone,
        }

        # Only show the set course goal message for enrolled, unverified
        # users in a course that allows for verified statuses.
        is_already_verified = CourseEnrollment.is_enrolled_as_verified(
            request.user, course_key)
        if (not is_already_verified and has_course_goal_permission(
                request, course_key_string, {'is_enrolled': is_enrolled})):
            course_goals = {
                'goal_options':
                valid_course_goals_ordered(include_unsure=True),
                'selected_goal': None
            }

            selected_goal = get_course_goal(request.user, course_key)
            if selected_goal:
                course_goals['selected_goal'] = {
                    'key': selected_goal.goal_key,
                    'text': get_course_goal_text(selected_goal.goal_key),
                }
        else:
            course_goals = {'goal_options': [], 'selected_goal': None}

        data = {
            'course_blocks': course_blocks,
            'course_expired_html': course_expired_html or None,
            'course_goals': course_goals,
            'course_tools': course_tools,
            'dates_widget': dates_widget,
            'enroll_alert': enroll_alert,
            'handouts_html': handouts_html or None,
            'has_ended': course.has_ended(),
            'offer_html': offer_html or None,
            'resume_course': resume_course,
            'welcome_message_html': welcome_message_html or None,
        }
        context = self.get_serializer_context()
        context['course_key'] = course_key
        context['enable_links'] = show_enrolled or allow_public
        serializer = self.get_serializer_class()(data, context=context)

        return Response(serializer.data)
Example #13
0
    def get(self, request, *args, **kwargs):
        course_key_string = kwargs.get('course_key_string')
        course_key = CourseKey.from_string(course_key_string)
        course_usage_key = modulestore().make_course_usage_key(course_key)

        if course_home_legacy_is_active(course_key):
            raise Http404

        # Enable NR tracing for this view based on course
        monitoring_utils.set_custom_attribute('course_id', course_key_string)
        monitoring_utils.set_custom_attribute('user_id', request.user.id)
        monitoring_utils.set_custom_attribute('is_staff',
                                              request.user.is_staff)

        course = get_course_with_access(request.user,
                                        'load',
                                        course_key,
                                        check_if_enrolled=False)

        masquerade_object, request.user = setup_masquerade(
            request,
            course_key,
            staff_access=has_access(request.user, 'staff', course_key),
            reset_masquerade_data=True,
        )

        user_is_masquerading = is_masquerading(
            request.user, course_key, course_masquerade=masquerade_object)

        course_overview = CourseOverview.get_from_id(course_key)
        enrollment = CourseEnrollment.get_enrollment(request.user, course_key)
        allow_anonymous = COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled(
            course_key)
        allow_public = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC
        allow_public_outline = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC_OUTLINE

        # User locale settings
        user_timezone_locale = user_timezone_locale_prefs(request)
        user_timezone = user_timezone_locale['user_timezone']

        if course_home_legacy_is_active(course.id):
            dates_tab_link = request.build_absolute_uri(
                reverse('dates', args=[course.id]))
        else:
            dates_tab_link = get_learning_mfe_home_url(course_key=course.id,
                                                       view_name='dates')

        # Set all of the defaults
        access_expiration = None
        cert_data = None
        course_blocks = None
        course_goals = {'goal_options': [], 'selected_goal': None}
        course_tools = CourseToolsPluginManager.get_enabled_course_tools(
            request, course_key)
        dates_widget = {
            'course_date_blocks': [],
            'dates_tab_link': dates_tab_link,
            'user_timezone': user_timezone,
        }
        enroll_alert = {
            'can_enroll': True,
            'extra_text': None,
        }
        handouts_html = None
        offer_data = None
        resume_course = {
            'has_visited_course': False,
            'url': None,
        }
        welcome_message_html = None

        is_enrolled = enrollment and enrollment.is_active
        is_staff = bool(has_access(request.user, 'staff', course_key))
        show_enrolled = is_enrolled or is_staff
        if show_enrolled:
            course_blocks = get_course_outline_block_tree(
                request, course_key_string, request.user)
            date_blocks = get_course_date_blocks(course,
                                                 request.user,
                                                 request,
                                                 num_assignments=1)
            dates_widget['course_date_blocks'] = [
                block for block in date_blocks
                if not isinstance(block, TodaysDate)
            ]

            handouts_html = get_course_info_section(request, request.user,
                                                    course, 'handouts')
            welcome_message_html = get_current_update_for_user(request, course)

            offer_data = generate_offer_data(request.user, course_overview)
            access_expiration = get_access_expiration_data(
                request.user, course_overview)
            cert_data = get_cert_data(request.user, course,
                                      enrollment.mode) if is_enrolled else None

            # Only show the set course goal message for enrolled, unverified
            # users in a course that allows for verified statuses.
            is_already_verified = CourseEnrollment.is_enrolled_as_verified(
                request.user, course_key)
            if not is_already_verified and has_course_goal_permission(
                    request, course_key_string, {'is_enrolled': is_enrolled}):
                course_goals = {
                    'goal_options':
                    valid_course_goals_ordered(include_unsure=True),
                    'selected_goal': None
                }

                selected_goal = get_course_goal(request.user, course_key)
                if selected_goal:
                    course_goals['selected_goal'] = {
                        'key': selected_goal.goal_key,
                        'text': get_course_goal_text(selected_goal.goal_key),
                    }

            try:
                resume_block = get_key_to_last_completed_block(
                    request.user, course.id)
                resume_course['has_visited_course'] = True
                resume_path = reverse('jump_to',
                                      kwargs={
                                          'course_id': course_key_string,
                                          'location': str(resume_block)
                                      })
                resume_course['url'] = request.build_absolute_uri(resume_path)
            except UnavailableCompletionData:
                start_block = get_start_block(course_blocks)
                resume_course['url'] = start_block['lms_web_url']

        elif allow_public_outline or allow_public or user_is_masquerading:
            course_blocks = get_course_outline_block_tree(
                request, course_key_string, None)
            if allow_public or user_is_masquerading:
                handouts_html = get_course_info_section(
                    request, request.user, course, 'handouts')

        if not show_enrolled:
            if CourseMode.is_masters_only(course_key):
                enroll_alert['can_enroll'] = False
                enroll_alert['extra_text'] = _(
                    'Please contact your degree administrator or '
                    'edX Support if you have questions.')
            elif course.invitation_only:
                enroll_alert['can_enroll'] = False

        # Sometimes there are sequences returned by Course Blocks that we
        # don't actually want to show to the user, such as when a sequence is
        # composed entirely of units that the user can't access. The Learning
        # Sequences API knows how to roll this up, so we use it determine which
        # sequences we should remove from course_blocks.
        #
        # The long term goal is to remove the Course Blocks API call entirely,
        # so this is a tiny first step in that migration.
        if course_blocks and learning_sequences_api_available(
                course_key, request.user):
            user_course_outline = get_user_course_outline(
                course_key, request.user, datetime.now(tz=timezone.utc))
            available_seq_ids = {
                str(usage_key)
                for usage_key in user_course_outline.sequences
            }

            # course_blocks is a reference to the root of the course, so we go
            # through the chapters (sections) to look for sequences to remove.
            for chapter_data in course_blocks['children']:
                chapter_data['children'] = [
                    seq_data for seq_data in chapter_data['children'] if
                    (seq_data['id'] in available_seq_ids or
                     # Edge case: Sometimes we have weird course structures.
                     # We expect only sequentials here, but if there is
                     # another type, just skip it (don't filter it out).
                     seq_data['type'] != 'sequential')
                ] if 'children' in chapter_data else []

        data = {
            'access_expiration': access_expiration,
            'cert_data': cert_data,
            'course_blocks': course_blocks,
            'course_goals': course_goals,
            'course_tools': course_tools,
            'dates_widget': dates_widget,
            'enroll_alert': enroll_alert,
            'handouts_html': handouts_html,
            'has_ended': course.has_ended(),
            'offer': offer_data,
            'resume_course': resume_course,
            'welcome_message_html': welcome_message_html,
        }
        context = self.get_serializer_context()
        context['course_overview'] = course_overview
        context['enable_links'] = show_enrolled or allow_public
        context['enrollment'] = enrollment
        serializer = self.get_serializer_class()(data, context=context)

        return Response(serializer.data)
Example #14
0
    def _create_courseware_context(self, request):
        """
        Returns and creates the rendering context for the courseware.
        Also returns the table of contents for the courseware.
        """
        course_url_name = default_course_url_name(self.course.id)
        course_url = reverse(
            course_url_name,
            kwargs={'course_id': six.text_type(self.course.id)})
        show_search = (
            settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH') or
            (settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH_FOR_COURSE_STAFF')
             and self.is_staff))
        staff_access = self.is_staff

        reset_deadlines_url = reverse(
            'openedx.course_experience.reset_course_deadlines',
            kwargs={'course_id': six.text_type(self.course.id)})

        allow_anonymous = allow_public_access(self.course,
                                              [COURSE_VISIBILITY_PUBLIC])
        display_reset_dates_banner = False
        if not allow_anonymous and RELATIVE_DATES_FLAG.is_enabled(
                self.course.id):  # pylint: disable=too-many-nested-blocks
            course_overview = CourseOverview.objects.get(
                id=str(self.course_key))
            end_date = getattr(course_overview, 'end_date')
            if course_overview.self_paced and (not end_date
                                               or timezone.now() < end_date):
                if (CourseEnrollment.objects.filter(
                        course=course_overview,
                        user=request.user,
                        mode=CourseMode.VERIFIED).exists()):
                    course_block_tree = get_course_outline_block_tree(
                        request, str(self.course_key), request.user)
                    course_sections = course_block_tree.get('children', [])
                    for section in course_sections:
                        if display_reset_dates_banner:
                            break
                        for subsection in section.get('children', []):
                            if (not subsection.get('complete', True)
                                    and subsection.get(
                                        'due',
                                        timezone.now() + timedelta(1)) <
                                    timezone.now()):
                                display_reset_dates_banner = True
                                break

        courseware_context = {
            'csrf':
            csrf(self.request)['csrf_token'],
            'course':
            self.course,
            'course_url':
            course_url,
            'chapter':
            self.chapter,
            'section':
            self.section,
            'init':
            '',
            'fragment':
            Fragment(),
            'staff_access':
            staff_access,
            'can_masquerade':
            self.can_masquerade,
            'masquerade':
            self.masquerade,
            'supports_preview_menu':
            True,
            'studio_url':
            get_studio_url(self.course, 'course'),
            'xqa_server':
            settings.FEATURES.get('XQA_SERVER', "http://your_xqa_server.com"),
            'bookmarks_api_url':
            reverse('bookmarks'),
            'language_preference':
            self._get_language_preference(),
            'disable_optimizely':
            not WaffleSwitchNamespace('RET').is_enabled(
                'enable_optimizely_in_courseware'),
            'section_title':
            None,
            'sequence_title':
            None,
            'disable_accordion':
            COURSE_OUTLINE_PAGE_FLAG.is_enabled(self.course.id),
            'show_search':
            show_search,
            'relative_dates_is_enabled':
            RELATIVE_DATES_FLAG.is_enabled(self.course.id),
            'reset_deadlines_url':
            reset_deadlines_url,
            'display_reset_dates_banner':
            display_reset_dates_banner,
        }
        courseware_context.update(
            get_experiment_user_metadata_context(
                self.course,
                self.effective_user,
            ))
        table_of_contents = toc_for_course(
            self.effective_user,
            self.request,
            self.course,
            self.chapter_url_name,
            self.section_url_name,
            self.field_data_cache,
        )
        courseware_context['accordion'] = render_accordion(
            self.request,
            self.course,
            table_of_contents['chapters'],
        )

        courseware_context['course_sock_fragment'] = CourseSockFragmentView(
        ).render_to_fragment(request, course=self.course_overview)

        # entrance exam data
        self._add_entrance_exam_to_context(courseware_context)

        if self.section:
            # chromeless data
            if self.section.chrome:
                chrome = [
                    s.strip() for s in self.section.chrome.lower().split(",")
                ]
                if 'accordion' not in chrome:
                    courseware_context['disable_accordion'] = True
                if 'tabs' not in chrome:
                    courseware_context['disable_tabs'] = True

            # default tab
            if self.section.default_tab:
                courseware_context['default_tab'] = self.section.default_tab

            # section data
            courseware_context[
                'section_title'] = self.section.display_name_with_default
            section_context = self._create_section_context(
                table_of_contents['previous_of_active_section'],
                table_of_contents['next_of_active_section'],
            )
            courseware_context['fragment'] = self.section.render(
                self.view, section_context)

            if self.section.position and self.section.has_children:
                self._add_sequence_title_to_context(courseware_context)

        # Courseware MFE link
        if show_courseware_mfe_link(request.user, staff_access,
                                    self.course.id):
            if self.section:
                try:
                    unit_key = UsageKey.from_string(
                        request.GET.get('activate_block_id', ''))
                    # `activate_block_id` is typically a Unit (a.k.a. Vertical),
                    # but it can technically be any block type. Do a check to
                    # make sure it's really a Unit before we use it for the MFE.
                    if unit_key.block_type != 'vertical':
                        unit_key = None
                except InvalidKeyError:
                    unit_key = None

                courseware_context[
                    'microfrontend_link'] = get_microfrontend_url(
                        self.course.id, self.section.location, unit_key)
            else:
                courseware_context[
                    'microfrontend_link'] = get_microfrontend_url(
                        self.course.id)
        else:
            courseware_context['microfrontend_link'] = None

        return courseware_context