diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1a7454e1ec..da918fec42 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,7 @@ These are notable changes in edx-platform. This is a rolling list of changes, in roughly chronological order, most recent first. Add your entries at or near the top. Include a label indicating the component affected. +LMS: Disable data download buttons on the instructor dashboard for large courses LMS: Refactor and clean student dashboard templates. diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index 9736a3d8a2..35f7257902 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -9,6 +9,7 @@ from mitxmako.shortcuts import render_to_response from django.core.urlresolvers import reverse from django.utils.html import escape from django.http import Http404 +from django.conf import settings from courseware.access import has_access from courseware.courses import get_course_by_id @@ -45,10 +46,19 @@ def instructor_dashboard_2(request, course_id): _section_analytics(course_id), ] + enrollment_count = sections[0]['enrollment_count'] + + disable_buttons = False + max_enrollment_for_buttons = settings.MITX_FEATURES.get("MAX_ENROLLMENT_INSTR_BUTTONS") + if max_enrollment_for_buttons is not None: + disable_buttons = enrollment_count > max_enrollment_for_buttons + + context = { 'course': course, 'old_dashboard_url': reverse('instructor_dashboard', kwargs={'course_id': course_id}), 'sections': sections, + 'disable_buttons': disable_buttons, } return render_to_response('instructor/instructor_dashboard_2/instructor_dashboard_2.html', context) diff --git a/lms/djangoapps/instructor/views/legacy.py b/lms/djangoapps/instructor/views/legacy.py index 61b43fa9cc..6d7e75baa4 100644 --- a/lms/djangoapps/instructor/views/legacy.py +++ b/lms/djangoapps/instructor/views/legacy.py @@ -105,12 +105,15 @@ def instructor_dashboard(request, course_id): else: idash_mode = request.session.get('idash_mode', 'Grades') + enrollment_number = CourseEnrollment.objects.filter(course_id=course_id, is_active=1).count() + # assemble some course statistics for output to instructor def get_course_stats_table(): - datatable = {'header': ['Statistic', 'Value'], - 'title': _u('Course Statistics At A Glance'), - } - data = [['# Enrolled', CourseEnrollment.objects.filter(course_id=course_id, is_active=1).count()]] + datatable = { + 'header': ['Statistic', 'Value'], + 'title': _u('Course Statistics At A Glance'), + } + data = [['# Enrolled', enrollment_number]] data += [['Date', timezone.now().isoformat()]] data += compute_course_stats(course).items() if request.user.is_staff: @@ -832,35 +835,43 @@ def instructor_dashboard(request, course_id): if not datatable: course_stats = get_course_stats_table() + # disable buttons for large courses + disable_buttons = False + max_enrollment_for_buttons = settings.MITX_FEATURES.get("MAX_ENROLLMENT_INSTR_BUTTONS") + if max_enrollment_for_buttons is not None: + disable_buttons = enrollment_number > max_enrollment_for_buttons + #---------------------------------------- # context for rendering - context = {'course': course, - 'staff_access': True, - 'admin_access': request.user.is_staff, - 'instructor_access': instructor_access, - 'forum_admin_access': forum_admin_access, - 'datatable': datatable, - 'course_stats': course_stats, - 'msg': msg, - 'modeflag': {idash_mode: 'selectedmode'}, - 'studio_url': studio_url, + context = { + 'course': course, + 'staff_access': True, + 'admin_access': request.user.is_staff, + 'instructor_access': instructor_access, + 'forum_admin_access': forum_admin_access, + 'datatable': datatable, + 'course_stats': course_stats, + 'msg': msg, + 'modeflag': {idash_mode: 'selectedmode'}, + 'studio_url': studio_url, - 'to_option': email_to_option, # email - 'subject': email_subject, # email - 'editor': email_editor, # email - 'email_msg': email_msg, # email - 'show_email_tab': show_email_tab, # email + 'to_option': email_to_option, # email + 'subject': email_subject, # email + 'editor': email_editor, # email + 'email_msg': email_msg, # email + 'show_email_tab': show_email_tab, # email - 'problems': problems, # psychometrics - 'plots': plots, # psychometrics - 'course_errors': modulestore().get_item_errors(course.location), - 'instructor_tasks': instructor_tasks, - 'offline_grade_log': offline_grades_available(course_id), - 'cohorts_ajax_url': reverse('cohorts', kwargs={'course_id': course_id}), + 'problems': problems, # psychometrics + 'plots': plots, # psychometrics + 'course_errors': modulestore().get_item_errors(course.location), + 'instructor_tasks': instructor_tasks, + 'offline_grade_log': offline_grades_available(course_id), + 'cohorts_ajax_url': reverse('cohorts', kwargs={'course_id': course_id}), - 'analytics_results': analytics_results, - } + 'analytics_results': analytics_results, + 'disable_buttons': disable_buttons + } if settings.MITX_FEATURES.get('ENABLE_INSTRUCTOR_BETA_DASHBOARD'): context['beta_dashboard_url'] = reverse('instructor_dashboard_2', kwargs={'course_id': course_id}) diff --git a/lms/envs/common.py b/lms/envs/common.py index 731c4f3c51..22047afb28 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -182,6 +182,10 @@ MITX_FEATURES = { # Automatically approve student identity verification attempts 'AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING': False, + + # Disable instructor dash buttons for downloading course data + # when enrollment exceeds this number + 'MAX_ENROLLMENT_INSTR_BUTTONS': 200, } # Used for A/B testing diff --git a/lms/static/sass/base/_variables.scss b/lms/static/sass/base/_variables.scss index 9d8820e369..c1bbcd5d6f 100644 --- a/lms/static/sass/base/_variables.scss +++ b/lms/static/sass/base/_variables.scss @@ -219,6 +219,11 @@ $action-secondary-disabled-fg: $white; $header-graphic-super-color: $m-blue-d1; $header-graphic-sub-color: $m-gray-d2; +// State-based colors +$error-color: $error-red; +$warning-color: $m-pink; +$confirm-color: $m-green; + // ==================== // MISC: visual horizontal rules diff --git a/lms/static/sass/course/instructor/_instructor.scss b/lms/static/sass/course/instructor/_instructor.scss index 6ec7f617ab..01b6004258 100644 --- a/lms/static/sass/course/instructor/_instructor.scss +++ b/lms/static/sass/course/instructor/_instructor.scss @@ -40,6 +40,8 @@ } } + // ==================== + // system feedback - messages .msg { border-radius: 1px; @@ -51,15 +53,51 @@ } } - .msg-confirm { - border-top: 2px solid green; - background: tint(green,90%); + // TYPE: warning + .msg-warning { + border-top: 2px solid $warning-color; + background: tint($warning-color,95%); .copy { - color: green; + color: $warning-color; } } + // TYPE: confirm + .msg-confirm { + border-top: 2px solid $confirm-color; + background: tint($confirm-color,95%); + + .copy { + color: $confirm-color; + } + } + + // TYPE: confirm + .msg-error { + border-top: 2px solid $error-color; + background: tint($error-color,95%); + + .copy { + color: $error-color; + } + } + + // ==================== + + // inline copy + .copy-confirm { + color: $confirm-color; + } + + .copy-warning { + color: $warning-color; + } + + .copy-error { + color: $error-color; + } + .list-advice { list-style: none; padding: 0; diff --git a/lms/static/sass/course/instructor/_instructor_2.scss b/lms/static/sass/course/instructor/_instructor_2.scss index 61dab3ef1c..1a4777d0e0 100644 --- a/lms/static/sass/course/instructor/_instructor_2.scss +++ b/lms/static/sass/course/instructor/_instructor_2.scss @@ -18,6 +18,77 @@ right: 15px; font-size: 11pt; } + + // system feedback - messages + .msg { + border-radius: 1px; + padding: 10px 15px; + margin-bottom: 20px; + + .copy { + font-weight: 600; + } + } + + // TYPE: warning + .msg-warning { + border-top: 2px solid $warning-color; + background: tint($warning-color,95%); + + .copy { + color: $warning-color; + } + } + + // TYPE: confirm + .msg-confirm { + border-top: 2px solid $confirm-color; + background: tint($confirm-color,95%); + + .copy { + color: $confirm-color; + } + } + + // TYPE: confirm + .msg-error { + border-top: 2px solid $error-color; + background: tint($error-color,95%); + + .copy { + color: $error-color; + } + } + + // ==================== + + // inline copy + .copy-confirm { + color: $confirm-color; + } + + .copy-warning { + color: $warning-color; + } + + .copy-error { + color: $error-color; + } + + .list-advice { + list-style: none; + padding: 0; + margin: 20px 0; + + .item { + font-weight: 600; + margin-bottom: 10px; + + &:last-child { + margin-bottom: 0; + } + } + } } section.instructor-dashboard-content-2 { diff --git a/lms/templates/courseware/instructor_dashboard.html b/lms/templates/courseware/instructor_dashboard.html index 7b06d8e309..4688259274 100644 --- a/lms/templates/courseware/instructor_dashboard.html +++ b/lms/templates/courseware/instructor_dashboard.html @@ -146,35 +146,59 @@ function goto( mode) %if modeflag.get('Grades'): %if offline_grade_log: -

Pre-computed grades ${offline_grade_log} available: Use? -

+

+ Pre-computed grades ${offline_grade_log} available: Use? + + +

%endif + +
+

${_("Grade Downloads")}

+ % if disable_buttons: + +
+ +
+

+ ${_("Note: some of these buttons are known to time out for larger " + "courses. We have temporarily disabled those features for courses " + "with more than {max_enrollment} students. We are urgently working on " + "fixing this issue. Thank you for your patience as we continue " + "working to improve the platform!").format( + max_enrollment=settings.MITX_FEATURES['MAX_ENROLLMENT_INSTR_BUTTONS'] + )} +

+
+
+ % endif +

- ${_("Gradebook")} + ${_("Gradebook")}

- ${_("Grade summary")} + ${_("Grade summary")}

- +

- - + +

- - + +

- - + +


@@ -188,7 +212,7 @@ function goto( mode)

${_("The assignments defined for this course should match the ones stored in the gradebook, for this to work properly!")}