diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index 9f6c01996eb1e9ebd76a7bf068804e16b459919c..ed61cdd99c6eb4ea80c1fd522f186a3b12051917 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -1031,7 +1031,6 @@ class CourseEnrollmentManager(models.Manager): def num_enrolled_in(self, course_id): """ Returns the count of active enrollments in a course. - 'course_id' is the course_id to return enrollments """ @@ -1042,6 +1041,21 @@ class CourseEnrollmentManager(models.Manager): return enrollment_number + def is_small_course(self, course_id): + """ + Returns false if the number of enrollments are one greater than 'max_enrollments' else true + + 'course_id' is the course_id to return enrollments + """ + max_enrollments = settings.FEATURES.get("MAX_ENROLLMENT_INSTR_BUTTONS") + + enrollment_number = super(CourseEnrollmentManager, self).get_queryset().filter( + course_id=course_id, + is_active=1 + )[:max_enrollments + 1].count() + + return enrollment_number <= max_enrollments + def num_enrolled_in_exclude_admins(self, course_id): """ Returns the count of active enrollments in a course excluding instructors, staff and CCX coaches. diff --git a/lms/djangoapps/instructor/toggles.py b/lms/djangoapps/instructor/toggles.py new file mode 100644 index 0000000000000000000000000000000000000000..3242b12fb92fcd8156c8e13b7ee1b2c71339a33e --- /dev/null +++ b/lms/djangoapps/instructor/toggles.py @@ -0,0 +1,30 @@ +""" +Toggles for instructor app +""" + +from openedx.core.djangoapps.waffle_utils import WaffleFlagNamespace, WaffleFlag + +# Namespace for instructor waffle flags. +WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='instructor') + +# Waffle flag to use optimised is_small_course. +# .. toggle_name: verify_student.optimised_is_small_course +# .. toggle_implementation: WaffleFlag +# .. toggle_default: False +# .. toggle_description: Supports staged rollout to improved is_small_course method. +# .. toggle_category: instructor +# .. toggle_use_cases: incremental_release, open_edx +# .. toggle_creation_date: 2020-07-02 +# .. toggle_expiration_date: n/a +# .. toggle_warnings: n/a +# .. toggle_tickets: PROD-1740 +# .. toggle_status: supported +OPTIMISED_IS_SMALL_COURSE = WaffleFlag( + waffle_namespace=WAFFLE_FLAG_NAMESPACE, + flag_name='optimised_is_small_course', + flag_undefined_default=False +) + + +def use_optimised_is_small_course(): + return OPTIMISED_IS_SMALL_COURSE.is_enabled() diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index c0b63a9b098599204c7b0d350eb73aa7b416107a..5daff61c526b381b2709e34626a210092a4fe05f 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -7,6 +7,7 @@ import datetime import logging import uuid from functools import reduce +import time import pytz import six @@ -32,6 +33,7 @@ from xblock.fields import ScopeIds from bulk_email.api import is_bulk_email_feature_enabled from course_modes.models import CourseMode, CourseModesArchive from edxmako.shortcuts import render_to_response +from instructor.toggles import use_optimised_is_small_course from lms.djangoapps.certificates import api as certs_api from lms.djangoapps.certificates.models import ( CertificateGenerationConfiguration, @@ -132,6 +134,7 @@ def instructor_dashboard_2(request, course_id): reports_enabled = configuration_helpers.get_value('SHOW_ECOMMERCE_REPORTS', False) sections = [] + start_time = time.time() # starts time before _section_student_admin (further calls is_small_course) if access['staff']: sections.extend([ _section_course_info(course, access), @@ -140,6 +143,8 @@ def instructor_dashboard_2(request, course_id): _section_discussions_management(course, access), _section_student_admin(course, access), ]) + if course_id == 'course-v1:HarvardX+CS50+X': + log.info('Investigating log at %s : after _section_student_admin', time.time() - start_time) if access['data_researcher']: sections.append(_section_data_download(course, access)) @@ -195,7 +200,8 @@ def instructor_dashboard_2(request, course_id): if can_see_special_exams: sections.append(_section_special_exams(course, access)) - + if course_id == 'course-v1:HarvardX+CS50+X': + log.info('Investigating log at %s : section certificate', time.time() - start_time) # Certificates panel # This is used to generate example certificates # and enable self-generated certificates for a course. @@ -214,7 +220,14 @@ def instructor_dashboard_2(request, course_id): if len(openassessment_blocks) > 0 and access['staff']: sections.append(_section_open_response_assessment(request, course, openassessment_blocks, access)) - disable_buttons = not _is_small_course(course_key) + if course_id == 'course-v1:HarvardX+CS50+X': + log.info('Investigating log at %s : before Disable Button (calling is_small_course)', time.time() - start_time) + if use_optimised_is_small_course(): + disable_buttons = not CourseEnrollment.objects.is_small_course(course_key) + else: + disable_buttons = not _is_small_course(course_key) + if course_id == 'course-v1:HarvardX+CS50+X': + log.info('Investigating log at %s : after Disable Button (calling is_small_course)', time.time() - start_time) certificate_white_list = CertificateWhitelist.get_certificate_white_list(course_key) generate_certificate_exceptions_url = reverse( @@ -235,6 +248,8 @@ def instructor_dashboard_2(request, course_id): kwargs={'course_id': six.text_type(course_key)} ) + if course_id == 'course-v1:HarvardX+CS50+X': + log.info('Investigating log at %s : Before Context', time.time() - start_time) certificate_invalidations = CertificateInvalidation.get_certificate_invalidations(course_key) context = { @@ -617,7 +632,10 @@ def _is_small_course(course_key): def _section_student_admin(course, access): """ Provide data for the corresponding dashboard section """ course_key = course.id - is_small_course = _is_small_course(course_key) + if use_optimised_is_small_course(): + is_small_course = CourseEnrollment.objects.is_small_course(course_key) + else: + is_small_course = _is_small_course(course_key) section_data = { 'section_key': 'student_admin',