def create_flag(apps, schema_editor):
    Flag = apps.get_model('waffle', 'Flag')
    # Replacement for flag_undefined_default=True on flag definition
    Flag.objects.get_or_create(
        name=waffle_flags()[REJECTED_EXAM_OVERRIDES_GRADE].name,
        defaults={'everyone': True})
    Flag.objects.get_or_create(
        name=waffle_flags()[ENFORCE_FREEZE_GRADE_AFTER_COURSE_END].name,
        defaults={'everyone': True})
    Flag.objects.get_or_create(name=waffle_flags()[WRITABLE_GRADEBOOK].name,
                               defaults={'everyone': True})
Beispiel #2
0
    def setUpClass(cls):
        super(GradebookViewTest, cls).setUpClass()
        cls.namespaced_url = 'grades_api:v1:course_gradebook'
        cls.waffle_flag = waffle_flags()[WRITABLE_GRADEBOOK]

        cls.course = CourseFactory.create(display_name='test-course', run='run-1')
        cls.course_overview = CourseOverviewFactory.create(id=cls.course.id)

        # we re-assign cls.course from what's created in the parent class, so we have to
        # re-create the enrollments, too.
        cls._create_user_enrollments(cls.course, cls.student, cls.other_student)

        cls.chapter_1 = ItemFactory.create(
            category='chapter',
            parent_location=cls.course.location,
            display_name="Chapter 1",
        )
        cls.chapter_2 = ItemFactory.create(
            category='chapter',
            parent_location=cls.course.location,
            display_name="Chapter 2",
        )
        cls.subsections = {
            cls.chapter_1.location: [
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_1.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='HW 1',
                    format='Homework',
                    graded=True,
                ),
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_1.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='Lab 1',
                    format='Lab',
                    graded=True,
                ),
            ],
            cls.chapter_2.location: [
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_2.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='HW 2',
                    format='Homework',
                    graded=True,
                ),
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_2.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='Lab 2',
                    format='Lab',
                    graded=True,
                ),
            ],
        }
Beispiel #3
0
    def setUpClass(cls):
        super(GradebookViewTestBase, cls).setUpClass()
        cls.namespaced_url = 'grades_api:v1:course_gradebook'
        cls.waffle_flag = waffle_flags()[WRITABLE_GRADEBOOK]

        cls.course = CourseFactory.create(display_name='test-course',
                                          run='run-1')
        cls.course_key = cls.course.id
        cls.course_overview = CourseOverviewFactory.create(id=cls.course.id)

        cls.chapter_1 = ItemFactory.create(
            category='chapter',
            parent_location=cls.course.location,
            display_name="Chapter 1",
        )
        cls.chapter_2 = ItemFactory.create(
            category='chapter',
            parent_location=cls.course.location,
            display_name="Chapter 2",
        )
        cls.subsections = {
            cls.chapter_1.location: [
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_1.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='HW 1',
                    format='Homework',
                    graded=True,
                ),
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_1.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='Lab 1',
                    format='Lab',
                    graded=True,
                ),
            ],
            cls.chapter_2.location: [
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_2.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='HW 2',
                    format='Homework',
                    graded=True,
                ),
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_2.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='Lab 2',
                    format='Lab',
                    graded=True,
                ),
            ],
        }
Beispiel #4
0
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)

    section_data = {
        'section_key':
        'student_admin',
        'section_display_name':
        _('Student Admin'),
        'access':
        access,
        'is_small_course':
        is_small_course,
        'get_student_enrollment_status_url':
        reverse('get_student_enrollment_status',
                kwargs={'course_id': unicode(course_key)}),
        'get_student_progress_url_url':
        reverse('get_student_progress_url',
                kwargs={'course_id': unicode(course_key)}),
        'enrollment_url':
        reverse('students_update_enrollment',
                kwargs={'course_id': unicode(course_key)}),
        'reset_student_attempts_url':
        reverse('reset_student_attempts',
                kwargs={'course_id': unicode(course_key)}),
        'reset_student_attempts_for_entrance_exam_url':
        reverse(
            'reset_student_attempts_for_entrance_exam',
            kwargs={'course_id': unicode(course_key)},
        ),
        'rescore_problem_url':
        reverse('rescore_problem', kwargs={'course_id': unicode(course_key)}),
        'override_problem_score_url':
        reverse('override_problem_score',
                kwargs={'course_id': unicode(course_key)}),
        'rescore_entrance_exam_url':
        reverse('rescore_entrance_exam',
                kwargs={'course_id': unicode(course_key)}),
        'student_can_skip_entrance_exam_url':
        reverse(
            'mark_student_can_skip_entrance_exam',
            kwargs={'course_id': unicode(course_key)},
        ),
        'list_instructor_tasks_url':
        reverse('list_instructor_tasks',
                kwargs={'course_id': unicode(course_key)}),
        'list_entrace_exam_instructor_tasks_url':
        reverse('list_entrance_exam_instructor_tasks',
                kwargs={'course_id': unicode(course_key)}),
        'spoc_gradebook_url':
        reverse('spoc_gradebook', kwargs={'course_id': unicode(course_key)}),
    }
    if waffle_flags()[WRITABLE_GRADEBOOK].is_enabled(
            course_key) and settings.WRITABLE_GRADEBOOK_URL:
        section_data['writable_gradebook_url'] = urljoin(
            settings.WRITABLE_GRADEBOOK_URL, '/' + text_type(course_key))
    return section_data
Beispiel #5
0
 def test_no_gradebook_learner_count_message(self):
     """
     Test that, when the writable gradebook featue IS enabled, there is NOT
     a message that the feature is only available for courses with small
     numbers of learners.
     """
     waffle_flag = waffle_flags()[WRITABLE_GRADEBOOK]
     with override_waffle_flag(waffle_flag, active=True):
         response = self.client.get(self.url)
     assert TestInstructorDashboard.GRADEBOOK_LEARNER_COUNT_MESSAGE not in response.content.decode('utf-8')
     self.assertContains(response, 'View Gradebook')
    def test_staff_can_see_writable_gradebook(self):
        """
        Test that, when the writable gradebook featue is enabled, a staff member can see it.
        """
        waffle_flag = waffle_flags()[WRITABLE_GRADEBOOK]
        with override_waffle_flag(waffle_flag, active=True):
            response = self.client.get(self.url)

        expected_gradebook_url = 'http://gradebook.local.edx.org/{}'.format(self.course.id)
        self.assertIn(expected_gradebook_url, response.content)
        self.assertIn('View Gradebook', response.content)
Beispiel #7
0
    def test_staff_can_see_writable_gradebook_as_subdirectory(self):
        """
        Test that, when the writable gradebook feature is enabled and
        deployed in a subdirectory, a staff member can see it.
        """
        waffle_flag = waffle_flags()[WRITABLE_GRADEBOOK]
        with override_waffle_flag(waffle_flag, active=True):
            response = self.client.get(self.url)

        expected_gradebook_url = f'{settings.WRITABLE_GRADEBOOK_URL}/{self.course.id}'
        self.assertContains(response, expected_gradebook_url)
        self.assertContains(response, 'View Gradebook')
Beispiel #8
0
    def test_staff_can_see_writable_gradebook(self):
        """
        Test that, when the writable gradebook feature is enabled and
        deployed in another domain, a staff member can see it.
        """
        waffle_flag = waffle_flags()[WRITABLE_GRADEBOOK]
        with override_waffle_flag(waffle_flag, active=True):
            response = self.client.get(self.url)

        expected_gradebook_url = f'http://gradebook.local.edx.org/{self.course.id}'
        self.assertContains(response, expected_gradebook_url)
        self.assertContains(response, 'View Gradebook')
 def wrapped_function(self, request, **kwargs):
     """
     Wraps the given view function.
     """
     course_key = get_course_key(request, kwargs.get('course_id'))
     if not waffle_flags()[WRITABLE_GRADEBOOK].is_enabled(course_key):
         raise self.api_error(
             status_code=status.HTTP_403_FORBIDDEN,
             developer_message=
             'The writable gradebook feature is not enabled for this course.',
             error_code='feature_not_enabled')
     return view_func(self, request, **kwargs)
Beispiel #10
0
 def wrapped_function(self, request, **kwargs):
     """
     Wraps the given view function.
     """
     course_key = get_course_key(request, kwargs.get('course_id'))
     if not waffle_flags()[WRITABLE_GRADEBOOK].is_enabled(course_key):
         raise self.api_error(
             status_code=status.HTTP_403_FORBIDDEN,
             developer_message='The writable gradebook feature is not enabled for this course.',
             error_code='feature_not_enabled'
         )
     return view_func(self, request, **kwargs)
 def test_no_gradebook_learner_count_message(self):
     """
     Test that, when the writable gradebook featue IS enabled, there is NOT
     a message that the feature is only available for courses with small
     numbers of learners.
     """
     waffle_flag = waffle_flags()[WRITABLE_GRADEBOOK]
     with override_waffle_flag(waffle_flag, active=True):
         response = self.client.get(self.url)
     self.assertNotIn(
         TestInstructorDashboard.GRADEBOOK_LEARNER_COUNT_MESSAGE,
         response.content
     )
     self.assertIn('View Gradebook', response.content)
def writable_gradebook(request, course_id):
    """
    Show the writable gradebook for this course:
    - Only displayed to course staff
    """
    course_key = CourseKey.from_string(course_id)
    if not waffle_flags()[WRITABLE_GRADEBOOK].is_enabled(course_key):
        return HttpResponseNotFound()

    course = get_course_with_access(request.user, 'load', course_key)

    course_grade = CourseGradeFactory().read(request.user, course)
    courseware_summary = course_grade.chapter_grades.values()
    course_sections = []

    for chapter in courseware_summary:
        chapter_name = chapter['display_name']
        for section in chapter['sections']:
            if section.problem_scores and section.graded and chapter_name not in course_sections:
                course_sections.append(chapter_name)

    return render_to_response(
        'courseware/writable_gradebook.html',
        {
            'number_of_students':
            2,
            'course':
            course,
            'course_id':
            course_key,
            'course_sections':
            course_sections,
            # Checked above
            'staff_access':
            True,
            'ordered_grades':
            sorted(course.grade_cutoffs.items(),
                   key=lambda i: i[1],
                   reverse=True),
        })
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)

    section_data = {
        'section_key': 'student_admin',
        'section_display_name': _('Student Admin'),
        'access': access,
        'is_small_course': is_small_course,
        'get_student_enrollment_status_url': reverse(
            'get_student_enrollment_status',
            kwargs={'course_id': unicode(course_key)}
        ),
        'get_student_progress_url_url': reverse('get_student_progress_url', kwargs={'course_id': unicode(course_key)}),
        'enrollment_url': reverse('students_update_enrollment', kwargs={'course_id': unicode(course_key)}),
        'reset_student_attempts_url': reverse('reset_student_attempts', kwargs={'course_id': unicode(course_key)}),
        'reset_student_attempts_for_entrance_exam_url': reverse(
            'reset_student_attempts_for_entrance_exam',
            kwargs={'course_id': unicode(course_key)},
        ),
        'rescore_problem_url': reverse('rescore_problem', kwargs={'course_id': unicode(course_key)}),
        'override_problem_score_url': reverse('override_problem_score', kwargs={'course_id': unicode(course_key)}),
        'rescore_entrance_exam_url': reverse('rescore_entrance_exam', kwargs={'course_id': unicode(course_key)}),
        'student_can_skip_entrance_exam_url': reverse(
            'mark_student_can_skip_entrance_exam',
            kwargs={'course_id': unicode(course_key)},
        ),
        'list_instructor_tasks_url': reverse('list_instructor_tasks', kwargs={'course_id': unicode(course_key)}),
        'list_entrace_exam_instructor_tasks_url': reverse('list_entrance_exam_instructor_tasks',
                                                          kwargs={'course_id': unicode(course_key)}),
        'spoc_gradebook_url': reverse('spoc_gradebook', kwargs={'course_id': unicode(course_key)}),
    }
    if waffle_flags()[WRITABLE_GRADEBOOK].is_enabled(course_key) and settings.WRITABLE_GRADEBOOK_URL:
        section_data['writable_gradebook_url'] = urljoin(settings.WRITABLE_GRADEBOOK_URL, '/' + text_type(course_key))
    return section_data
Beispiel #14
0
 def setUp(self):
     super(FreezeGradingAfterCourseEndTest, self).setUp()
     self.users = [UserFactory.create() for _ in range(12)]
     self.user = self.users[0]
     self.freeze_grade_flag = waffle_flags(
     )[ENFORCE_FREEZE_GRADE_AFTER_COURSE_END]
Beispiel #15
0
 def setUp(self):
     super(FreezeGradingAfterCourseEndTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
     self.users = [UserFactory.create() for _ in range(12)]
     self.user = self.users[0]
     self.freeze_grade_flag = waffle_flags(
     )[ENFORCE_FREEZE_GRADE_AFTER_COURSE_END]
Beispiel #16
0
    def setUpClass(cls):
        super(GradebookViewTestBase, cls).setUpClass()
        cls.namespaced_url = 'grades_api:v1:course_gradebook'
        cls.waffle_flag = waffle_flags()[WRITABLE_GRADEBOOK]

        cls.course = CourseFactory.create(display_name='test-course', run='run-1')
        cls.course_key = cls.course.id
        cls.course_overview = CourseOverviewFactory.create(id=cls.course.id)

        cls.chapter_1 = ItemFactory.create(
            category='chapter',
            parent_location=cls.course.location,
            display_name="Chapter 1",
        )
        cls.chapter_2 = ItemFactory.create(
            category='chapter',
            parent_location=cls.course.location,
            display_name="Chapter 2",
        )
        cls.subsections = {
            cls.chapter_1.location: [
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_1.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='HW 1',
                    format='Homework',
                    graded=True,
                ),
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_1.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='Lab 1',
                    format='Lab',
                    graded=True,
                ),
            ],
            cls.chapter_2.location: [
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_2.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='HW 2',
                    format='Homework',
                    graded=True,
                ),
                ItemFactory.create(
                    category='sequential',
                    parent_location=cls.chapter_2.location,
                    due=datetime(2017, 12, 18, 11, 30, 00),
                    display_name='Lab 2',
                    format='Lab',
                    graded=True,
                ),
            ],
        }
        cls.course_data = CourseData(None, course=cls.course)
        # we have to force the collection of course data from the block_structure API
        # so that CourseGrade.course_data objects can later have a non-null effective_structure
        _ = cls.course_data.collected_structure
Beispiel #17
0
 def setUp(self):
     super(FreezeGradingAfterCourseEndTest, self).setUp()
     self.users = [UserFactory.create() for _ in xrange(12)]
     self.user = self.users[0]
     self.freeze_grade_flag = waffle_flags()[ENFORCE_FREEZE_GRADE_AFTER_COURSE_END]