Commit 661f37ec by Calen Pennington

Merge remote-tracking branch 'edx/master' into opaque-keys-merge-master

Conflicts:
	lms/djangoapps/courseware/tests/test_views.py
	lms/djangoapps/instructor/tests/test_api.py
	lms/djangoapps/instructor/tests/test_legacy_anon_csv.py
	lms/djangoapps/instructor/views/api.py
	lms/djangoapps/instructor/views/legacy.py
parents 44b15619 0a6ea26c
@shard_3 @shard_1
Feature: CMS Video Component Editor Feature: CMS Video Component Editor
As a course author, I want to be able to create video components As a course author, I want to be able to create video components
......
...@@ -142,3 +142,8 @@ To add a course team member: ...@@ -142,3 +142,8 @@ To add a course team member:
#. Click **Add a New Team Member**. #. Click **Add a New Team Member**.
#. Enter the new team member's email address, then click **ADD USER**. #. Enter the new team member's email address, then click **ADD USER**.
You can also assign privileged roles to users when you work in the LMS.
Regardless of where the role is assigned, these administrative team members can
work on your course in both the LMS and in Studio. For more information on
assigning roles while you run your course, see
:ref:`Course_Staffing`.
\ No newline at end of file
...@@ -12,12 +12,22 @@ May, 2014 ...@@ -12,12 +12,22 @@ May, 2014
* - Date * - Date
- Change - Change
- 05/13/14 * - 05/14/14
- Updated the :ref:`Running Your Course Index` chapter to remove references
to the "new beta" Instructor Dashboard.
* -
- Updated the :ref:`Enrollment` section to reflect that usernames or email - Updated the :ref:`Enrollment` section to reflect that usernames or email
addresses can be used to batch enroll students. addresses can be used to batch enroll students.
* -
- Updated the :ref:`Grades` section to reflect new features on the problem
**Staff Debug** viewer for rescoring, resetting attempts, and deleting
student state.
* -
- Updated the :ref:`Course_Staffing` section to state the labeling
differences between Studio and the LMS with respect to course team roles.
* - 05/09/14 * - 05/09/14
- Updated :ref:`Assigning_discussion_roles` with a note about course staff requiring - Updated :ref:`Assigning_discussion_roles` with a note about course staff
explicit granting of discussion administration roles. requiring explicit granting of discussion administration roles.
* - * -
- Added :ref:`VitalSource` topic. - Added :ref:`VitalSource` topic.
* - 05/08/14 * - 05/08/14
...@@ -26,7 +36,8 @@ May, 2014 ...@@ -26,7 +36,8 @@ May, 2014
- Updated the :ref:`Discussions` chapter to include a topic on closing - Updated the :ref:`Discussions` chapter to include a topic on closing
discussions. discussions.
* - 05/06/14 * - 05/06/14
- Expanded the :ref:`Grades` chapter to include a topic on interpreting the score histograms for problems. - Expanded the :ref:`Grades` chapter to include a topic on interpreting the
score histograms for problems.
* - * -
- Updated :ref:`LTI Component` to reflect changes to the Studio UI. - Updated :ref:`LTI Component` to reflect changes to the Studio UI.
* - 05/02/14 * - 05/02/14
......
...@@ -21,9 +21,7 @@ To view course data: ...@@ -21,9 +21,7 @@ To view course data:
#. View the live version of your course. #. View the live version of your course.
#. Click **Instructor** then **Try New Beta Dashboard**. #. Click **Instructor**, then click **Course Info** if necessary.
#. Click **Course Info** if necessary.
The **Basic Course Information** section of the page that opens lists The **Basic Course Information** section of the page that opens lists
information about the course. information about the course.
......
...@@ -86,9 +86,7 @@ To enroll students or staff members: ...@@ -86,9 +86,7 @@ To enroll students or staff members:
#. View the live version of your course. #. View the live version of your course.
#. Click **Instructor** then **Try New Beta Dashboard**. #. Click **Instructor**, then click **Membership**.
#. Click **Membership**.
#. In the **Batch Enrollment** section of the page, enter the username or email #. In the **Batch Enrollment** section of the page, enter the username or email
address of the student, or enter multiple names or addresses separated by address of the student, or enter multiple names or addresses separated by
...@@ -98,7 +96,7 @@ To enroll students or staff members: ...@@ -98,7 +96,7 @@ To enroll students or staff members:
note that this feature is better suited to courses with smaller enrollments, note that this feature is better suited to courses with smaller enrollments,
rather than courses with massive enrollments. rather than courses with massive enrollments.
5. To streamline the course enrollment process, leave **Auto Enroll** selected. 4. To streamline the course enrollment process, leave **Auto Enroll** selected.
#. To send students an email message, leave **Notify students by email** #. To send students an email message, leave **Notify students by email**
selected. selected.
...@@ -129,9 +127,7 @@ To view the enrollment count for a course: ...@@ -129,9 +127,7 @@ To view the enrollment count for a course:
#. View the live version of your course. #. View the live version of your course.
#. Click **Instructor** then **Try New Beta Dashboard**. #. Click **Instructor**, then click **Course Info** if necessary.
#. Click **Course Info** if necessary.
The **Enrollment Information** section of the page that opens shows the total The **Enrollment Information** section of the page that opens shows the total
number of people who are currently enrolled. number of people who are currently enrolled.
......
...@@ -12,14 +12,13 @@ for working with students, grades, and other members of the staff. ...@@ -12,14 +12,13 @@ for working with students, grades, and other members of the staff.
* Instructors * Instructors
.. **Question**: how does this team, set up on the Instructor Dashboard, differ from the "Course Team Members" that you add in Studio (Settings > Course Team)? You can assign these privileged roles when you work in either the LMS or in
Studio, and the users who have these roles can work on your course in both the
The administrative team that helps you run your course in the LMS can include LMS and Studio. For more information on setting up a team in Studio, see
some, all, or none of the people who help you set up the course in Studio. You
assign these administrative roles in the LMS, separately from the roles you
assign in Studio. For more information on setting up a team in Studio, see
:ref:`Add Course Team Members`. :ref:`Add Course Team Members`.
.. note:: The LMS "Course Staff" role is the same as the Studio "Staff" role, and the LMS "Instructors" role is the same as the Studio "Admin" role.
You can also designate teams of people to beta test your course and to You can also designate teams of people to beta test your course and to
moderate and manage its discussions by assigning other LMS roles. The beta moderate and manage its discussions by assigning other LMS roles. The beta
testers and discussion administrators must be enrolled in your course, but testers and discussion administrators must be enrolled in your course, but
...@@ -76,9 +75,7 @@ To assign a staff role: ...@@ -76,9 +75,7 @@ To assign a staff role:
#. View the live version of your course. #. View the live version of your course.
#. Click **Instructor** then **Try New Beta Dashboard**. #. Click **Instructor**, then click **Membership**.
#. Click **Membership**.
#. In the **Administration List Management** section, use the drop-down list to #. In the **Administration List Management** section, use the drop-down list to
select **Course Staff** or **Instructors**. select **Course Staff** or **Instructors**.
......
...@@ -81,9 +81,7 @@ To download or view student data: ...@@ -81,9 +81,7 @@ To download or view student data:
#. View the live version of your course. #. View the live version of your course.
#. Click **Instructor** then **Try New Beta Dashboard**. #. Click **Instructor**, then click **Data Download**.
#. Click **Data Download**.
#. To download data about enrolled students in a CSV file, click **Download profile information as a CSV**. #. To download data about enrolled students in a CSV file, click **Download profile information as a CSV**.
...@@ -108,9 +106,7 @@ To display demographic data for your students: ...@@ -108,9 +106,7 @@ To display demographic data for your students:
#. View the live version of your course. #. View the live version of your course.
#. Click **Instructor** then **Try New Beta Dashboard**. #. Click **Instructor**, then click **Analytics**.
#. Click **Analytics**.
* The Year of Birth section displays a chart of enrolled students plotted by year of birth. * The Year of Birth section displays a chart of enrolled students plotted by year of birth.
...@@ -139,9 +135,8 @@ To download a file of assigned user IDs and anonymized user IDs: ...@@ -139,9 +135,8 @@ To download a file of assigned user IDs and anonymized user IDs:
#. View the live version of your course. #. View the live version of your course.
#. Click **Instructor** > **Try New Beta Dashboard**. #. Click **Instructor**, then click **Data Download**.
#. Click **Get Student Anonymized IDs CSV**.
#. Click **Data Download** > **Get Student Anonymized IDs CSV**.
You are prompted to open or save the (course-id)-anon-id.csv file for your course. This file contains the user ID that is assigned to each student at registration and its corresponding anonymized ID. Values are included for every student who ever enrolled for your course. You are prompted to open or save the (course-id)-anon-id.csv file for your course. This file contains the user ID that is assigned to each student at registration and its corresponding anonymized ID. Values are included for every student who ever enrolled for your course.
......
...@@ -97,15 +97,11 @@ Before you can assign roles to your discussion administrators, you need their em ...@@ -97,15 +97,11 @@ Before you can assign roles to your discussion administrators, you need their em
* To get this information for a staff member, on the Instructor Dashboard click **Membership** and then select **Course Staff** from the drop-down list. * To get this information for a staff member, on the Instructor Dashboard click **Membership** and then select **Course Staff** from the drop-down list.
* To get this information for an enrolled student, on the Instructor Dashboard click **Data Download** > **Download profile information as a CSV**. * To get this information for an enrolled student, on the Instructor Dashboard click **Data Download** > **Download profile information as a CSV**.
**Tip**: These instructions are for the new Instructor Dashboard: click **Try New Beta Dashboard**.
To assign a role: To assign a role:
#. View the live version of your course. #. View the live version of your course.
#. Click **Instructor** then **Try New Beta Dashboard**. #. Click **Instructor**, then click **Membership**.
#. Click **Membership**.
#. In the Administration List Management section, use the drop-down list to select Discussion Admins, Discussion Moderators, or Discussion Community TAs. #. In the Administration List Management section, use the drop-down list to select Discussion Admins, Discussion Moderators, or Discussion Community TAs.
......
...@@ -11,7 +11,7 @@ Change Log ...@@ -11,7 +11,7 @@ Change Log
* - Date * - Date
- Change - Change
* - 05/0614 * - 05/06/14
- Added enrollment event types to the :ref:`Tracking Logs` chapter. - Added enrollment event types to the :ref:`Tracking Logs` chapter.
* - 05/05/14 * - 05/05/14
- Removed information on the Poll module. `Polls <http://edx.readthedocs.org/projects/ca/en/latest/exercises_tools/poll.html>`_ are now covered in the *Building and Running an edX Course* guide. - Removed information on the Poll module. `Polls <http://edx.readthedocs.org/projects/ca/en/latest/exercises_tools/poll.html>`_ are now covered in the *Building and Running an edX Course* guide.
...@@ -31,7 +31,7 @@ Change Log ...@@ -31,7 +31,7 @@ Change Log
* - * -
- Reformatted the :ref:`Tracking Logs` chapter to improve readability. - Reformatted the :ref:`Tracking Logs` chapter to improve readability.
* - 03/28/14 * - 03/28/14
- Added the :ref:'Data_Czar' chapter. - Added the :ref:`Data_Czar` chapter.
* - 03/24/14 * - 03/24/14
- Added the ``user_api_usercoursetag`` table to the :ref:`Student_Info` chapter and the ``assigned_user_to_partition`` and ``child_render`` event types to the :ref:`Tracking Logs` chapter. - Added the ``user_api_usercoursetag`` table to the :ref:`Student_Info` chapter and the ``assigned_user_to_partition`` and ``child_render`` event types to the :ref:`Tracking Logs` chapter.
* - 03/19/14 * - 03/19/14
......
# coding=UTF-8
""" """
Tests courseware views.py Tests courseware views.py
""" """
...@@ -46,7 +47,7 @@ class TestJumpTo(TestCase): ...@@ -46,7 +47,7 @@ class TestJumpTo(TestCase):
self.course_key = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall') self.course_key = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall')
def test_jumpto_invalid_location(self): def test_jumpto_invalid_location(self):
location = self.course_key.make_usage_key(None, 'NoSuchPlace') location = self.course_key.make_usage_key(None, 'NoSuchPlace')
# This is fragile, but unfortunately the problem is that within the LMS we # This is fragile, but unfortunately the problem is that within the LMS we
# can't use the reverse calls from the CMS # can't use the reverse calls from the CMS
jumpto_url = '{0}/{1}/jump_to/{2}'.format('/courses', self.course_key.to_deprecated_string(), location.to_deprecated_string()) jumpto_url = '{0}/{1}/jump_to/{2}'.format('/courses', self.course_key.to_deprecated_string(), location.to_deprecated_string())
...@@ -121,14 +122,14 @@ class ViewsTestCase(TestCase): ...@@ -121,14 +122,14 @@ class ViewsTestCase(TestCase):
# depreciated function # depreciated function
mock_user = MagicMock() mock_user = MagicMock()
mock_user.is_authenticated.return_value = False mock_user.is_authenticated.return_value = False
self.assertEquals(views.user_groups(mock_user), []) self.assertEqual(views.user_groups(mock_user), [])
def test_get_current_child(self): def test_get_current_child(self):
self.assertIsNone(views.get_current_child(MagicMock())) self.assertIsNone(views.get_current_child(MagicMock()))
mock_xmodule = MagicMock() mock_xmodule = MagicMock()
mock_xmodule.position = -1 mock_xmodule.position = -1
mock_xmodule.get_display_items.return_value = ['one', 'two'] mock_xmodule.get_display_items.return_value = ['one', 'two']
self.assertEquals(views.get_current_child(mock_xmodule), 'one') self.assertEqual(views.get_current_child(mock_xmodule), 'one')
mock_xmodule_2 = MagicMock() mock_xmodule_2 = MagicMock()
mock_xmodule_2.position = 3 mock_xmodule_2.position = 3
mock_xmodule_2.get_display_items.return_value = [] mock_xmodule_2.get_display_items.return_value = []
...@@ -206,13 +207,13 @@ class ViewsTestCase(TestCase): ...@@ -206,13 +207,13 @@ class ViewsTestCase(TestCase):
chat_settings = views.chat_settings(mock_course, mock_user) chat_settings = views.chat_settings(mock_course, mock_user)
# Test the proper format of all chat settings # Test the proper format of all chat settings
self.assertEquals(chat_settings['domain'], domain) self.assertEqual(chat_settings['domain'], domain)
self.assertEquals(chat_settings['room'], "a-b-c_class") self.assertEqual(chat_settings['room'], "a-b-c_class")
self.assertEquals(chat_settings['username'], "johndoe@%s" % domain) self.assertEqual(chat_settings['username'], "johndoe@%s" % domain)
# TODO: this needs to be changed once we figure out how to # TODO: this needs to be changed once we figure out how to
# generate/store a real password. # generate/store a real password.
self.assertEquals(chat_settings['password'], "johndoe@%s" % domain) self.assertEqual(chat_settings['password'], "johndoe@%s" % domain)
def test_course_mktg_about_coming_soon(self): def test_course_mktg_about_coming_soon(self):
# we should not be able to find this course # we should not be able to find this course
...@@ -450,8 +451,16 @@ class ProgressPageTests(ModuleStoreTestCase): ...@@ -450,8 +451,16 @@ class ProgressPageTests(ModuleStoreTestCase):
MakoMiddleware().process_request(self.request) MakoMiddleware().process_request(self.request)
<<<<<<< HEAD
course = CourseFactory(start=datetime(2013, 9, 16, 7, 17, 28)) course = CourseFactory(start=datetime(2013, 9, 16, 7, 17, 28))
self.course = modulestore().get_course(course.id) # pylint: disable=no-member self.course = modulestore().get_course(course.id) # pylint: disable=no-member
=======
course = CourseFactory(
start=datetime(2013, 9, 16, 7, 17, 28),
grade_cutoffs={u'çü†øƒƒ': 0.75, 'Pass': 0.5},
)
self.course = modulestore().get_instance(course.id, course.location) # pylint: disable=no-member
>>>>>>> edx/master
self.chapter = ItemFactory(category='chapter', parent_location=self.course.location) # pylint: disable=no-member self.chapter = ItemFactory(category='chapter', parent_location=self.course.location) # pylint: disable=no-member
self.section = ItemFactory(category='sequential', parent_location=self.chapter.location) self.section = ItemFactory(category='sequential', parent_location=self.chapter.location)
...@@ -460,5 +469,15 @@ class ProgressPageTests(ModuleStoreTestCase): ...@@ -460,5 +469,15 @@ class ProgressPageTests(ModuleStoreTestCase):
def test_pure_ungraded_xblock(self): def test_pure_ungraded_xblock(self):
ItemFactory(category='acid', parent_location=self.vertical.location) ItemFactory(category='acid', parent_location=self.vertical.location)
<<<<<<< HEAD
resp = views.progress(self.request, self.course.id.to_deprecated_string()) resp = views.progress(self.request, self.course.id.to_deprecated_string())
self.assertEquals(resp.status_code, 200) self.assertEquals(resp.status_code, 200)
=======
resp = views.progress(self.request, self.course.id)
self.assertEqual(resp.status_code, 200)
def test_non_asci_grade_cutoffs(self):
resp = views.progress(self.request, self.course.id)
self.assertEqual(resp.status_code, 200)
>>>>>>> edx/master
...@@ -1324,18 +1324,28 @@ class TestInstructorAPILevelsDataDump(ModuleStoreTestCase, LoginEnrollmentTestCa ...@@ -1324,18 +1324,28 @@ class TestInstructorAPILevelsDataDump(ModuleStoreTestCase, LoginEnrollmentTestCa
self.assertEqual(student_json['username'], student.username) self.assertEqual(student_json['username'], student.username)
self.assertEqual(student_json['email'], student.email) self.assertEqual(student_json['email'], student.email)
@patch.object(instructor.views.api, 'anonymous_id_for_user', Mock(return_value='42'))
@patch.object(instructor.views.api, 'unique_id_for_user', Mock(return_value='41'))
def test_get_anon_ids(self): def test_get_anon_ids(self):
""" """
Test the CSV output for the anonymized user ids. Test the CSV output for the anonymized user ids.
""" """
<<<<<<< HEAD
url = reverse('get_anon_ids', kwargs={'course_id': self.course.id.to_deprecated_string()}) url = reverse('get_anon_ids', kwargs={'course_id': self.course.id.to_deprecated_string()})
with patch('instructor.views.api.unique_id_for_user') as mock_unique: with patch('instructor.views.api.unique_id_for_user') as mock_unique:
mock_unique.return_value = '42' mock_unique.return_value = '42'
response = self.client.get(url, {}) response = self.client.get(url, {})
=======
url = reverse('get_anon_ids', kwargs={'course_id': self.course.id})
response = self.client.get(url, {})
>>>>>>> edx/master
self.assertEqual(response['Content-Type'], 'text/csv') self.assertEqual(response['Content-Type'], 'text/csv')
body = response.content.replace('\r', '') body = response.content.replace('\r', '')
self.assertTrue(body.startswith('"User ID","Anonymized user ID"\n"2","42"\n')) self.assertTrue(body.startswith(
self.assertTrue(body.endswith('"7","42"\n')) '"User ID","Anonymized user ID","Course Specific Anonymized user ID"'
'\n"2","41","42"\n'
))
self.assertTrue(body.endswith('"7","41","42"\n'))
def test_list_report_downloads(self): def test_list_report_downloads(self):
url = reverse('list_report_downloads', kwargs={'course_id': self.course.id.to_deprecated_string()}) url = reverse('list_report_downloads', kwargs={'course_id': self.course.id.to_deprecated_string()})
......
...@@ -17,12 +17,13 @@ from django.core.urlresolvers import reverse ...@@ -17,12 +17,13 @@ from django.core.urlresolvers import reverse
from courseware.tests.helpers import LoginEnrollmentTestCase from courseware.tests.helpers import LoginEnrollmentTestCase
from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE
import instructor.views.legacy
from student.roles import CourseStaffRole from student.roles import CourseStaffRole
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.django import modulestore, clear_existing_modulestores from xmodule.modulestore.django import modulestore, clear_existing_modulestores
from xmodule.modulestore.locations import SlashSeparatedCourseKey from xmodule.modulestore.locations import SlashSeparatedCourseKey
from mock import patch from mock import Mock, patch
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
...@@ -51,14 +52,25 @@ class TestInstructorDashboardAnonCSV(ModuleStoreTestCase, LoginEnrollmentTestCas ...@@ -51,14 +52,25 @@ class TestInstructorDashboardAnonCSV(ModuleStoreTestCase, LoginEnrollmentTestCas
self.login(self.instructor, self.password) self.login(self.instructor, self.password)
self.enroll(self.toy) self.enroll(self.toy)
@patch.object(instructor.views.legacy, 'anonymous_id_for_user', Mock(return_value='42'))
@patch.object(instructor.views.legacy, 'unique_id_for_user', Mock(return_value='41'))
def test_download_anon_csv(self): def test_download_anon_csv(self):
course = self.toy course = self.toy
<<<<<<< HEAD
url = reverse('instructor_dashboard_legacy', kwargs={'course_id': course.id.to_deprecated_string()}) url = reverse('instructor_dashboard_legacy', kwargs={'course_id': course.id.to_deprecated_string()})
with patch('instructor.views.legacy.unique_id_for_user') as mock_unique: with patch('instructor.views.legacy.unique_id_for_user') as mock_unique:
mock_unique.return_value = 42 mock_unique.return_value = 42
response = self.client.post(url, {'action': 'Download CSV of all student anonymized IDs'}) response = self.client.post(url, {'action': 'Download CSV of all student anonymized IDs'})
=======
url = reverse('instructor_dashboard_legacy', kwargs={'course_id': course.id})
response = self.client.post(url, {'action': 'Download CSV of all student anonymized IDs'})
>>>>>>> edx/master
self.assertEqual(response['Content-Type'], 'text/csv') self.assertEqual(response['Content-Type'], 'text/csv')
body = response.content.replace('\r', '') body = response.content.replace('\r', '')
self.assertEqual(body, '"User ID","Anonymized user ID"\n"2","42"\n') self.assertEqual(
body,
('"User ID","Anonymized user ID","Course Specific Anonymized user ID"'
'\n"2","41","42"\n')
)
...@@ -33,7 +33,7 @@ from django_comment_common.models import ( ...@@ -33,7 +33,7 @@ from django_comment_common.models import (
) )
from courseware.models import StudentModule from courseware.models import StudentModule
from student.models import unique_id_for_user, CourseEnrollment from student.models import CourseEnrollment, unique_id_for_user, anonymous_id_for_user
import instructor_task.api import instructor_task.api
from instructor_task.api_helper import AlreadyRunningError from instructor_task.api_helper import AlreadyRunningError
from instructor_task.views import get_task_completion_info from instructor_task.views import get_task_completion_info
...@@ -630,9 +630,15 @@ def get_anon_ids(request, course_id): # pylint: disable=W0613 ...@@ -630,9 +630,15 @@ def get_anon_ids(request, course_id): # pylint: disable=W0613
students = User.objects.filter( students = User.objects.filter(
courseenrollment__course_id=course_id, courseenrollment__course_id=course_id,
).order_by('id') ).order_by('id')
<<<<<<< HEAD
header = ['User ID', 'Anonymized user ID'] header = ['User ID', 'Anonymized user ID']
rows = [[s.id, unique_id_for_user(s)] for s in students] rows = [[s.id, unique_id_for_user(s)] for s in students]
return csv_response(course_id.to_deprecated_string().replace('/', '-') + '-anon-ids.csv', header, rows) return csv_response(course_id.to_deprecated_string().replace('/', '-') + '-anon-ids.csv', header, rows)
=======
header = ['User ID', 'Anonymized user ID', 'Course Specific Anonymized user ID']
rows = [[s.id, unique_id_for_user(s), anonymous_id_for_user(s, course_id)] for s in students]
return csv_response(course_id.replace('/', '-') + '-anon-ids.csv', header, rows)
>>>>>>> edx/master
@ensure_csrf_cookie @ensure_csrf_cookie
......
...@@ -40,7 +40,6 @@ from lms.lib.xblock.runtime import quote_slashes ...@@ -40,7 +40,6 @@ from lms.lib.xblock.runtime import quote_slashes
# Submissions is a Django app that is currently installed # Submissions is a Django app that is currently installed
# from the edx-ora2 repo, although it will likely move in the future. # from the edx-ora2 repo, although it will likely move in the future.
from submissions import api as sub_api from submissions import api as sub_api
from student.models import anonymous_id_for_user
from bulk_email.models import CourseEmail, CourseAuthorization from bulk_email.models import CourseEmail, CourseAuthorization
from courseware import grades from courseware import grades
...@@ -68,7 +67,12 @@ from instructor_task.views import get_task_completion_info ...@@ -68,7 +67,12 @@ from instructor_task.views import get_task_completion_info
from edxmako.shortcuts import render_to_response, render_to_string from edxmako.shortcuts import render_to_response, render_to_string
from class_dashboard import dashboard_data from class_dashboard import dashboard_data
from psychometrics import psychoanalyze from psychometrics import psychoanalyze
from student.models import CourseEnrollment, CourseEnrollmentAllowed, unique_id_for_user from student.models import (
CourseEnrollment,
CourseEnrollmentAllowed,
unique_id_for_user,
anonymous_id_for_user
)
from student.views import course_from_id from student.views import course_from_id
import track.views import track.views
from xblock.field_data import DictFieldData from xblock.field_data import DictFieldData
...@@ -688,9 +692,15 @@ def instructor_dashboard(request, course_id): ...@@ -688,9 +692,15 @@ def instructor_dashboard(request, course_id):
courseenrollment__course_id=course_key, courseenrollment__course_id=course_key,
).order_by('id') ).order_by('id')
<<<<<<< HEAD
datatable = {'header': ['User ID', 'Anonymized user ID']} datatable = {'header': ['User ID', 'Anonymized user ID']}
datatable['data'] = [[s.id, unique_id_for_user(s)] for s in students] datatable['data'] = [[s.id, unique_id_for_user(s)] for s in students]
return return_csv(course_key.to_deprecated_string().replace('/', '-') + '-anon-ids.csv', datatable) return return_csv(course_key.to_deprecated_string().replace('/', '-') + '-anon-ids.csv', datatable)
=======
datatable = {'header': ['User ID', 'Anonymized user ID', 'Course Specific Anonymized user ID']}
datatable['data'] = [[s.id, unique_id_for_user(s), anonymous_id_for_user(s, course_id)] for s in students]
return return_csv(course_id.replace('/', '-') + '-anon-ids.csv', datatable)
>>>>>>> edx/master
#---------------------------------------- #----------------------------------------
# Group management # Group management
......
...@@ -103,7 +103,7 @@ $(function () { ...@@ -103,7 +103,7 @@ $(function () {
descending_grades = sorted(grade_cutoffs, key=lambda x: grade_cutoffs[x], reverse=True) descending_grades = sorted(grade_cutoffs, key=lambda x: grade_cutoffs[x], reverse=True)
for grade in descending_grades: for grade in descending_grades:
percent = grade_cutoffs[grade] percent = grade_cutoffs[grade]
grade_cutoff_ticks.append( [ percent, "{0} {1:.0%}".format(grade, percent) ] ) grade_cutoff_ticks.append( [ percent, u"{0} {1:.0%}".format(grade, percent) ] )
else: else:
grade_cutoff_ticks = [ ] grade_cutoff_ticks = [ ]
%> %>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment