def instructor_dashboard_2(request, course_id):
    """ Display the instructor dashboard for a course. """
    try:
        course_key = CourseKey.from_string(course_id)
    except InvalidKeyError:
        log.error(
            u"Unable to find course with course key %s while loading the Instructor Dashboard.",
            course_id)
        return HttpResponseServerError()

    course = get_course_by_id(course_key, depth=0)

    access = {
        'admin':
        request.user.is_staff,
        'instructor':
        bool(has_access(request.user, 'instructor', course)),
        'finance_admin':
        CourseFinanceAdminRole(course_key).has_user(request.user),
        'sales_admin':
        CourseSalesAdminRole(course_key).has_user(request.user),
        'staff':
        bool(has_access(request.user, 'staff', course)),
        'forum_admin':
        has_forum_access(request.user, course_key, FORUM_ROLE_ADMINISTRATOR),
    }

    if not access['staff']:
        raise Http404()

    is_white_label = CourseMode.is_white_label(course_key)

    sections = [
        _section_course_info(course, access),
        _section_membership(course, access, is_white_label),
        _section_cohort_management(course, access),
        _section_student_admin(course, access),
        _section_data_download(course, access),
    ]

    analytics_dashboard_message = None
    if settings.ANALYTICS_DASHBOARD_URL:
        # Construct a URL to the external analytics dashboard
        analytics_dashboard_url = '{0}/courses/{1}'.format(
            settings.ANALYTICS_DASHBOARD_URL, unicode(course_key))
        link_start = "<a href=\"{}\" target=\"_blank\">".format(
            analytics_dashboard_url)
        analytics_dashboard_message = _(
            "To gain insights into student enrollment and participation {link_start}"
            "visit {analytics_dashboard_name}, our new course analytics product{link_end}."
        )
        analytics_dashboard_message = analytics_dashboard_message.format(
            link_start=link_start,
            link_end="</a>",
            analytics_dashboard_name=settings.ANALYTICS_DASHBOARD_NAME)

        # Temporarily show the "Analytics" section until we have a better way of linking to Insights
        sections.append(_section_analytics(course, access))

    # Check if there is corresponding entry in the CourseMode Table related to the Instructor Dashboard course
    course_mode_has_price = False
    paid_modes = CourseMode.paid_modes_for_course(course_key)
    if len(paid_modes) == 1:
        course_mode_has_price = True
    elif len(paid_modes) > 1:
        log.error(
            u"Course %s has %s course modes with payment options. Course must only have "
            u"one paid course mode to enable eCommerce options.",
            unicode(course_key), len(paid_modes))

    if settings.FEATURES.get('INDIVIDUAL_DUE_DATES') and access['instructor']:
        sections.insert(3, _section_extensions(course))

    # Gate access to course email by feature flag & by course-specific authorization
    if bulk_email_is_enabled_for_course(course_key):
        sections.append(_section_send_email(course, access))

    # Gate access to Metrics tab by featue flag and staff authorization
    if settings.FEATURES['CLASS_DASHBOARD'] and access['staff']:
        sections.append(_section_metrics(course, access))

    # Gate access to Ecommerce tab
    if course_mode_has_price and (access['finance_admin']
                                  or access['sales_admin']):
        sections.append(
            _section_e_commerce(course, access, paid_modes[0], is_white_label,
                                is_white_label))

    # Gate access to Special Exam tab depending if either timed exams or proctored exams
    # are enabled in the course

    # NOTE: For now, if we only have procotred exams enabled, then only platform Staff
    # (user.is_staff) will be able to view the special exams tab. This may
    # change in the future
    can_see_special_exams = (
        ((course.enable_proctored_exams and request.user.is_staff)
         or course.enable_timed_exams)
        and settings.FEATURES.get('ENABLE_SPECIAL_EXAMS', False))
    if can_see_special_exams:
        sections.append(_section_special_exams(course, access))

    # Certificates panel
    # This is used to generate example certificates
    # and enable self-generated certificates for a course.
    certs_enabled = CertificateGenerationConfiguration.current().enabled
    if certs_enabled and access['admin']:
        sections.append(_section_certificates(course))

    disable_buttons = not _is_small_course(course_key)

    certificate_white_list = CertificateWhitelist.get_certificate_white_list(
        course_key)
    generate_certificate_exceptions_url = reverse(  # pylint: disable=invalid-name
        'generate_certificate_exceptions',
        kwargs={
            'course_id': unicode(course_key),
            'generate_for': ''
        })
    generate_bulk_certificate_exceptions_url = reverse(  # pylint: disable=invalid-name
        'generate_bulk_certificate_exceptions',
        kwargs={'course_id': unicode(course_key)})
    certificate_exception_view_url = reverse(
        'certificate_exception_view',
        kwargs={'course_id': unicode(course_key)})

    certificate_invalidation_view_url = reverse(  # pylint: disable=invalid-name
        'certificate_invalidation_view',
        kwargs={'course_id': unicode(course_key)})

    certificate_invalidations = CertificateInvalidation.get_certificate_invalidations(
        course_key)

    context = {
        'course': course,
        'studio_url': get_studio_url(course, 'course'),
        'sections': sections,
        'disable_buttons': disable_buttons,
        'analytics_dashboard_message': analytics_dashboard_message,
        'certificate_white_list': certificate_white_list,
        'certificate_invalidations': certificate_invalidations,
        'generate_certificate_exceptions_url':
        generate_certificate_exceptions_url,
        'generate_bulk_certificate_exceptions_url':
        generate_bulk_certificate_exceptions_url,
        'certificate_exception_view_url': certificate_exception_view_url,
        'certificate_invalidation_view_url': certificate_invalidation_view_url,
    }

    return render_to_response(
        'instructor/instructor_dashboard_2/instructor_dashboard_2.html',
        context)
def instructor_dashboard_2(request, course_id):
    """ Display the instructor dashboard for a course. """
    try:
        course_key = CourseKey.from_string(course_id)
    except InvalidKeyError:
        log.error(u"Unable to find course with course key %s while loading the Instructor Dashboard.", course_id)
        return HttpResponseServerError()

    course = get_course_by_id(course_key, depth=0)

    access = {
        'admin': request.user.is_staff,
        'instructor': bool(has_access(request.user, 'instructor', course)),
        'finance_admin': CourseFinanceAdminRole(course_key).has_user(request.user),
        'sales_admin': CourseSalesAdminRole(course_key).has_user(request.user),
        'staff': bool(has_access(request.user, 'staff', course)),
        'forum_admin': has_forum_access(request.user, course_key, FORUM_ROLE_ADMINISTRATOR),
    }

    if not access['staff']:
        raise Http404()

    is_white_label = CourseMode.is_white_label(course_key)

    sections = [
        _section_course_info(course, access),
        _section_membership(course, access, is_white_label),
        _section_cohort_management(course, access),
        _section_student_admin(course, access),
        _section_data_download(course, access),
    ]

    analytics_dashboard_message = None
    if settings.ANALYTICS_DASHBOARD_URL:
        # Construct a URL to the external analytics dashboard
        analytics_dashboard_url = '{0}/courses/{1}'.format(settings.ANALYTICS_DASHBOARD_URL, unicode(course_key))
        link_start = HTML("<a href=\"{}\" target=\"_blank\">").format(analytics_dashboard_url)
        analytics_dashboard_message = _(
            "To gain insights into student enrollment and participation {link_start}"
            "visit {analytics_dashboard_name}, our new course analytics product{link_end}."
        )
        analytics_dashboard_message = Text(analytics_dashboard_message).format(
            link_start=link_start, link_end=HTML("</a>"), analytics_dashboard_name=settings.ANALYTICS_DASHBOARD_NAME)

        # Temporarily show the "Analytics" section until we have a better way of linking to Insights
        sections.append(_section_analytics(course, access))

    # Check if there is corresponding entry in the CourseMode Table related to the Instructor Dashboard course
    course_mode_has_price = False
    paid_modes = CourseMode.paid_modes_for_course(course_key)
    if len(paid_modes) == 1:
        course_mode_has_price = True
    elif len(paid_modes) > 1:
        log.error(
            u"Course %s has %s course modes with payment options. Course must only have "
            u"one paid course mode to enable eCommerce options.",
            unicode(course_key), len(paid_modes)
        )

    if settings.FEATURES.get('INDIVIDUAL_DUE_DATES') and access['instructor']:
        sections.insert(3, _section_extensions(course))

    # Gate access to course email by feature flag & by course-specific authorization
    if BulkEmailFlag.feature_enabled(course_key):
        sections.append(_section_send_email(course, access))

    # Gate access to Metrics tab by featue flag and staff authorization
    if settings.FEATURES['CLASS_DASHBOARD'] and access['staff']:
        sections.append(_section_metrics(course, access))

    # Gate access to Ecommerce tab
    if course_mode_has_price and (access['finance_admin'] or access['sales_admin']):
        sections.append(_section_e_commerce(course, access, paid_modes[0], is_white_label, is_white_label))

    # Gate access to Special Exam tab depending if either timed exams or proctored exams
    # are enabled in the course

    # NOTE: For now, if we only have procotred exams enabled, then only platform Staff
    # (user.is_staff) will be able to view the special exams tab. This may
    # change in the future
    can_see_special_exams = (
        ((course.enable_proctored_exams and request.user.is_staff) or course.enable_timed_exams) and
        settings.FEATURES.get('ENABLE_SPECIAL_EXAMS', False)
    )
    if can_see_special_exams:
        sections.append(_section_special_exams(course, access))

    # Certificates panel
    # This is used to generate example certificates
    # and enable self-generated certificates for a course.
    certs_enabled = CertificateGenerationConfiguration.current().enabled
    if certs_enabled and access['admin']:
        sections.append(_section_certificates(course))

    disable_buttons = not _is_small_course(course_key)

    certificate_white_list = CertificateWhitelist.get_certificate_white_list(course_key)
    generate_certificate_exceptions_url = reverse(  # pylint: disable=invalid-name
        'generate_certificate_exceptions',
        kwargs={'course_id': unicode(course_key), 'generate_for': ''}
    )
    generate_bulk_certificate_exceptions_url = reverse(  # pylint: disable=invalid-name
        'generate_bulk_certificate_exceptions',
        kwargs={'course_id': unicode(course_key)}
    )
    certificate_exception_view_url = reverse(
        'certificate_exception_view',
        kwargs={'course_id': unicode(course_key)}
    )

    certificate_invalidation_view_url = reverse(  # pylint: disable=invalid-name
        'certificate_invalidation_view',
        kwargs={'course_id': unicode(course_key)}
    )

    certificate_invalidations = CertificateInvalidation.get_certificate_invalidations(course_key)

    context = {
        'course': course,
        'studio_url': get_studio_url(course, 'course'),
        'sections': sections,
        'disable_buttons': disable_buttons,
        'analytics_dashboard_message': analytics_dashboard_message,
        'certificate_white_list': certificate_white_list,
        'certificate_invalidations': certificate_invalidations,
        'generate_certificate_exceptions_url': generate_certificate_exceptions_url,
        'generate_bulk_certificate_exceptions_url': generate_bulk_certificate_exceptions_url,
        'certificate_exception_view_url': certificate_exception_view_url,
        'certificate_invalidation_view_url': certificate_invalidation_view_url,
    }

    return render_to_response('instructor/instructor_dashboard_2/instructor_dashboard_2.html', context)
def instructor_dashboard_2(request, course_id):
    """ Display the instructor dashboard for a course. """
    try:
        course_key = CourseKey.from_string(course_id)
    except InvalidKeyError:
        log.error(
            u"Unable to find course with course key %s while loading the Instructor Dashboard.",
            course_id)
        return HttpResponseServerError()

    course = get_course_by_id(course_key, depth=0)

    access = {
        'admin':
        request.user.is_staff,
        'instructor':
        bool(has_access(request.user, 'instructor', course)),
        'finance_admin':
        CourseFinanceAdminRole(course_key).has_user(request.user),
        'sales_admin':
        CourseSalesAdminRole(course_key).has_user(request.user),
        'staff':
        bool(has_access(request.user, 'staff', course)),
        'forum_admin':
        has_forum_access(request.user, course_key, FORUM_ROLE_ADMINISTRATOR),
    }

    if not access['staff']:
        raise Http404()

    is_white_label = CourseMode.is_white_label(course_key)

    reports_enabled = configuration_helpers.get_value('SHOW_ECOMMERCE_REPORTS',
                                                      False)

    sections = [
        _section_course_info(course, access),
        _section_membership(course, access, is_white_label),
        _section_cohort_management(course, access),
        _section_discussions_management(course, access),
        _section_student_admin(course, access),
        _section_data_download(course, access),
    ]

    analytics_dashboard_message = None
    if show_analytics_dashboard_message(course_key):
        # Construct a URL to the external analytics dashboard
        analytics_dashboard_url = '{0}/courses/{1}'.format(
            settings.ANALYTICS_DASHBOARD_URL, unicode(course_key))
        link_start = HTML("<a href=\"{}\" target=\"_blank\">").format(
            analytics_dashboard_url)
        analytics_dashboard_message = _(
            "To gain insights into student enrollment and participation {link_start}"
            "visit {analytics_dashboard_name}, our new course analytics product{link_end}."
        )
        analytics_dashboard_message = Text(analytics_dashboard_message).format(
            link_start=link_start,
            link_end=HTML("</a>"),
            analytics_dashboard_name=settings.ANALYTICS_DASHBOARD_NAME)

        # Temporarily show the "Analytics" section until we have a better way of linking to Insights
        sections.append(_section_analytics(course, access))

    # Check if there is corresponding entry in the CourseMode Table related to the Instructor Dashboard course
    course_mode_has_price = False
    paid_modes = CourseMode.paid_modes_for_course(course_key)
    if len(paid_modes) == 1:
        course_mode_has_price = True
    elif len(paid_modes) > 1:
        log.error(
            u"Course %s has %s course modes with payment options. Course must only have "
            u"one paid course mode to enable eCommerce options.",
            unicode(course_key), len(paid_modes))

    if settings.FEATURES.get('INDIVIDUAL_DUE_DATES') and access['instructor']:
        sections.insert(3, _section_extensions(course))

    # Gate access to course email by feature flag & by course-specific authorization
    if BulkEmailFlag.feature_enabled(course_key):
        sections.append(_section_send_email(course, access))

    # Gate access to Metrics tab by featue flag and staff authorization
    if settings.FEATURES['CLASS_DASHBOARD'] and access['staff']:
        sections.append(_section_metrics(course, access))

    # Gate access to Ecommerce tab
    if course_mode_has_price and (access['finance_admin']
                                  or access['sales_admin']):
        sections.append(
            _section_e_commerce(course, access, paid_modes[0], is_white_label,
                                reports_enabled))

    # Gate access to Special Exam tab depending if either timed exams or proctored exams
    # are enabled in the course

    # NOTE: For now, if we only have procotred exams enabled, then only platform Staff
    # (user.is_staff) will be able to view the special exams tab. This may
    # change in the future
    can_see_special_exams = (
        ((course.enable_proctored_exams and request.user.is_staff)
         or course.enable_timed_exams)
        and settings.FEATURES.get('ENABLE_SPECIAL_EXAMS', False))
    if can_see_special_exams:
        sections.append(_section_special_exams(course, access))

    # Certificates panel
    # This is used to generate example certificates
    # and enable self-generated certificates for a course.
    # Note: This is hidden for all CCXs
    certs_enabled = CertificateGenerationConfiguration.current(
    ).enabled and not hasattr(course_key, 'ccx')
    if certs_enabled and access['admin']:
        sections.append(_section_certificates(course))

    # define a generic function to get any category of xblock

    def get_course_blocks(course_key, category):
        """
        Retrieve all XBlocks in the course for a particular category.
    
        Returns only XBlocks that are published and haven't been deleted.
        """
        # Note: we need to check if found components have been orphaned
        # due to a bug in split modulestore (PLAT-799).  Once that bug
        # is resolved, we can skip the `_is_in_course_tree()` check entirely.
        return [
            block for block in modulestore().get_items(
                course_key,
                qualifiers={"category": category},
            )
        ]

    openassessment_blocks = modulestore().get_items(
        course_key, qualifiers={'category': 'openassessment'})

    # filter out orphaned openassessment blocks
    openassessment_blocks = [
        block for block in openassessment_blocks if block.parent is not None
    ]

    if len(openassessment_blocks) > 0:
        sections.append(
            _section_open_response_assessment(request, course,
                                              openassessment_blocks, access))

    # Get all the recap xblocks in a course

    recap_blocks = get_course_blocks(course_key, "recap")

    # Add the Recap instructor dashboard tab if there is a recap Xblock

    if len(recap_blocks) > 0:
        sections.append(_section_recap(request, course, recap_blocks, access))

    disable_buttons = not _is_small_course(course_key)

    certificate_white_list = CertificateWhitelist.get_certificate_white_list(
        course_key)
    generate_certificate_exceptions_url = reverse(  # pylint: disable=invalid-name
        'generate_certificate_exceptions',
        kwargs={
            'course_id': unicode(course_key),
            'generate_for': ''
        })
    generate_bulk_certificate_exceptions_url = reverse(  # pylint: disable=invalid-name
        'generate_bulk_certificate_exceptions',
        kwargs={'course_id': unicode(course_key)})
    certificate_exception_view_url = reverse(
        'certificate_exception_view',
        kwargs={'course_id': unicode(course_key)})

    certificate_invalidation_view_url = reverse(  # pylint: disable=invalid-name
        'certificate_invalidation_view',
        kwargs={'course_id': unicode(course_key)})

    certificate_invalidations = CertificateInvalidation.get_certificate_invalidations(
        course_key)

    context = {
        'course': course,
        'studio_url': get_studio_url(course, 'course'),
        'sections': sections,
        'disable_buttons': disable_buttons,
        'analytics_dashboard_message': analytics_dashboard_message,
        'certificate_white_list': certificate_white_list,
        'certificate_invalidations': certificate_invalidations,
        'generate_certificate_exceptions_url':
        generate_certificate_exceptions_url,
        'generate_bulk_certificate_exceptions_url':
        generate_bulk_certificate_exceptions_url,
        'certificate_exception_view_url': certificate_exception_view_url,
        'certificate_invalidation_view_url': certificate_invalidation_view_url,
    }

    return render_to_response(
        'instructor/instructor_dashboard_2/instructor_dashboard_2.html',
        context)