From 74714c4ed7cfe7423c8fe65290a1653306340b31 Mon Sep 17 00:00:00 2001 From: Adam Palay Date: Thu, 6 Mar 2014 09:47:15 -0500 Subject: [PATCH 1/2] Update data download dash for parity (LMS-1203) --- lms/djangoapps/instructor/views/api.py | 10 ++++++---- .../src/instructor_dashboard/data_download.coffee | 8 ++++++++ .../instructor_dashboard_2/data_download.html | 13 +++++++++---- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index 8fbd22a4c5..f140b02f15 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -23,10 +23,12 @@ from courseware.access import has_access from courseware.courses import get_course_with_access, get_course_by_id from django.contrib.auth.models import User from django_comment_client.utils import has_forum_access -from django_comment_common.models import (Role, - FORUM_ROLE_ADMINISTRATOR, - FORUM_ROLE_MODERATOR, - FORUM_ROLE_COMMUNITY_TA) +from django_comment_common.models import ( + Role, + FORUM_ROLE_ADMINISTRATOR, + FORUM_ROLE_MODERATOR, + FORUM_ROLE_COMMUNITY_TA, +) from courseware.models import StudentModule from student.models import unique_id_for_user diff --git a/lms/static/coffee/src/instructor_dashboard/data_download.coffee b/lms/static/coffee/src/instructor_dashboard/data_download.coffee index c491abec18..f977199f0d 100644 --- a/lms/static/coffee/src/instructor_dashboard/data_download.coffee +++ b/lms/static/coffee/src/instructor_dashboard/data_download.coffee @@ -18,6 +18,7 @@ class DataDownload @$section.data 'wrapper', @ # gather elements @$list_studs_btn = @$section.find("input[name='list-profiles']'") + @$list_studs_csv_btn = @$section.find("input[name='list-profiles-csv']'") @$list_anon_btn = @$section.find("input[name='list-anon-ids']'") @$grade_config_btn = @$section.find("input[name='dump-gradeconf']'") @$calculate_grades_csv_btn = @$section.find("input[name='calculate-grades-csv']'") @@ -43,6 +44,13 @@ class DataDownload # this handler binds to both the download # and the csv button + @$list_studs_csv_btn.click (e) => + url = @$list_studs_btn.data 'endpoint' + # handle csv special case + # redirect the document to the csv file. + url += '/csv' + location.href = url + @$list_studs_btn.click (e) => url = @$list_studs_btn.data 'endpoint' diff --git a/lms/templates/instructor/instructor_dashboard_2/data_download.html b/lms/templates/instructor/instructor_dashboard_2/data_download.html index db59caa770..9e1c9fa73c 100644 --- a/lms/templates/instructor/instructor_dashboard_2/data_download.html +++ b/lms/templates/instructor/instructor_dashboard_2/data_download.html @@ -6,14 +6,19 @@

${_("Data Download")}

-

${_("The following button displays a list of all students enrolled in this course, along with profile information such as email address and username. The data can also be downloaded as a CSV file.")}

+

${_("The following button generates a CSV file of all students enrolled in this course, along with profile information such as email address and username.")}

-

-

+

+ + % if not disable_buttons: +

${_("For smaller courses, profile information for enrolled students can be listed directly on this page:")}

+

+ %endif
+
-

${_("Displays the grading configuration for the course. The grading configuration is the breakdown of graded subsections of the course (such as exams and problem sets), and can be changed on the 'Grading' page (under 'Settings') in Studio.")}

+

${_("The following button displays the grading configuration for the course. The grading configuration is the breakdown of graded subsections of the course (such as exams and problem sets), and can be changed on the 'Grading' page (under 'Settings') in Studio.")}

From 6ca099d5b6622c3dc621fd6455096c763934769c Mon Sep 17 00:00:00 2001 From: Sarina Canelake Date: Wed, 12 Mar 2014 13:12:36 -0400 Subject: [PATCH 2/2] Acceptance tests for beta instructor dash LMS-1203 --- lms/djangoapps/instructor/features/common.py | 31 +++++++++++ .../instructor/features/data_download.feature | 10 ++++ .../instructor/features/data_download.py | 6 +++ .../instructor_dashboard/data_download.coffee | 54 +++++++++---------- 4 files changed, 71 insertions(+), 30 deletions(-) diff --git a/lms/djangoapps/instructor/features/common.py b/lms/djangoapps/instructor/features/common.py index 433992a72e..c12273030a 100644 --- a/lms/djangoapps/instructor/features/common.py +++ b/lms/djangoapps/instructor/features/common.py @@ -7,12 +7,24 @@ Define common steps for instructor dashboard acceptance tests. from __future__ import absolute_import +from django.conf import settings from lettuce import world, step +from mock import patch from nose.tools import assert_in # pylint: disable=E0611 from courseware.tests.factories import StaffFactory, InstructorFactory +@step(u'Given I am "([^"]*)" for a very large course') +def make_staff_or_instructor_for_large_course(step, role): + make_large_course(step, role) + + +@patch.dict('courseware.access.settings.FEATURES', {"MAX_ENROLLMENT_INSTR_BUTTONS": 0}) +def make_large_course(step, role): + i_am_staff_or_instructor(step, role) + + @step(u'Given I am "([^"]*)" for a course') def i_am_staff_or_instructor(step, role): # pylint: disable=unused-argument ## In summary: makes a test course, makes a new Staff or Instructor user @@ -99,5 +111,24 @@ def click_a_button(step, button): # pylint: disable=unused-argument world.css_click('input[name="list-profiles"]') + elif button == "Download profile information as a CSV": + # Go to the data download section of the instructor dash + go_to_section("data_download") + # Don't do anything else, next step will handle clicking & downloading + else: raise ValueError("Unrecognized button option " + button) + + +@step(u'I visit the "([^"]*)" tab') +def click_a_button(step, tab_name): # pylint: disable=unused-argument + # course_info, membership, student_admin, data_download, analytics, send_email + tab_name_dict = { + 'Course Info': 'course_info', + 'Membership': 'membership', + 'Student Admin': 'student_admin', + 'Data Download': 'data_download', + 'Analytics': 'analytics', + 'Email': 'send_email', + } + go_to_section(tab_name_dict[tab_name]) diff --git a/lms/djangoapps/instructor/features/data_download.feature b/lms/djangoapps/instructor/features/data_download.feature index 52388e8b7d..6efe9c6397 100644 --- a/lms/djangoapps/instructor/features/data_download.feature +++ b/lms/djangoapps/instructor/features/data_download.feature @@ -7,6 +7,7 @@ Feature: LMS.Instructor Dash Data Download ### todos when more time can be spent on instructor dashboard #Scenario: Download profile information as a CSV #Scenario: Download student anonymized IDs as a CSV + ## Need to figure out how to assert csvs will download without actually downloading them Scenario: List enrolled students' profile information Given I am "" for a course @@ -17,6 +18,15 @@ Feature: LMS.Instructor Dash Data Download | instructor | | staff | + Scenario: List enrolled students' profile information for a large course + Given I am "" for a very large course + When I visit the "Data Download" tab + Then I do not see a button to 'List enrolled students' profile information' + Examples: + | Role | + | instructor | + | staff | + Scenario: View the grading configuration Given I am "" for a course When I click "Grading Configuration" diff --git a/lms/djangoapps/instructor/features/data_download.py b/lms/djangoapps/instructor/features/data_download.py index dd6aac6aa7..6d08551781 100644 --- a/lms/djangoapps/instructor/features/data_download.py +++ b/lms/djangoapps/instructor/features/data_download.py @@ -9,6 +9,7 @@ acceptance tests. from lettuce import world, step from nose.tools import assert_in, assert_regexp_matches # pylint: disable=E0611 from terrain.steps import reload_the_page +from splinter.request_handler.request_handler import RequestHandler @step(u'I see a table of student profiles') @@ -39,6 +40,11 @@ def find_student_profile_table(step): # pylint: disable=unused-argument assert_in(datum, world.css_text('#data-student-profiles-table')) +@step(u"I do not see a button to 'List enrolled students' profile information'") +def no_student_profile_table(step): # pylint: disable=unused-argument + world.is_css_not_present('input[name="list-profiles"]') + + @step(u"I see the grading configuration for the course") def find_grading_config(step): # pylint: disable=unused-argument # Find the grading configuration display diff --git a/lms/static/coffee/src/instructor_dashboard/data_download.coffee b/lms/static/coffee/src/instructor_dashboard/data_download.coffee index f977199f0d..b8f89c5fe8 100644 --- a/lms/static/coffee/src/instructor_dashboard/data_download.coffee +++ b/lms/static/coffee/src/instructor_dashboard/data_download.coffee @@ -54,40 +54,34 @@ class DataDownload @$list_studs_btn.click (e) => url = @$list_studs_btn.data 'endpoint' - # handle csv special case - if $(e.target).data 'csv' - # redirect the document to the csv file. - url += '/csv' - location.href = url - else - # Dynamically generate slickgrid table for displaying student profile information - @clear_display() - @$download_display_table.text gettext('Loading...') + # Dynamically generate slickgrid table for displaying student profile information + @clear_display() + @$download_display_table.text gettext('Loading...') - # fetch user list - $.ajax - dataType: 'json' - url: url - error: std_ajax_err => - @clear_display() - @$download_request_response_error.text gettext("Error getting student list.") - success: (data) => - @clear_display() + # fetch user list + $.ajax + dataType: 'json' + url: url + error: std_ajax_err => + @clear_display() + @$download_request_response_error.text gettext("Error getting student list.") + success: (data) => + @clear_display() - # display on a SlickGrid - options = - enableCellNavigation: true - enableColumnReorder: false - forceFitColumns: true - rowHeight: 35 + # display on a SlickGrid + options = + enableCellNavigation: true + enableColumnReorder: false + forceFitColumns: true + rowHeight: 35 - columns = ({id: feature, field: feature, name: feature} for feature in data.queried_features) - grid_data = data.students + columns = ({id: feature, field: feature, name: feature} for feature in data.queried_features) + grid_data = data.students - $table_placeholder = $ '
', class: 'slickgrid' - @$download_display_table.append $table_placeholder - grid = new Slick.Grid($table_placeholder, grid_data, columns, options) - # grid.autosizeColumns() + $table_placeholder = $ '
', class: 'slickgrid' + @$download_display_table.append $table_placeholder + grid = new Slick.Grid($table_placeholder, grid_data, columns, options) + # grid.autosizeColumns() @$grade_config_btn.click (e) => url = @$grade_config_btn.data 'endpoint'