Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
0899ac56
Commit
0899ac56
authored
Apr 12, 2017
by
Robert Raposa
Committed by
Diana Huang
Apr 13, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix review comments.
parent
69ba8eb0
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
61 additions
and
65 deletions
+61
-65
common/test/acceptance/tests/lms/test_lms_course_home.py
+3
-24
lms/djangoapps/course_api/blocks/transformers/milestones.py
+57
-41
openedx/features/course_experience/templates/course_experience/course-outline-fragment.html
+1
-0
No files found.
common/test/acceptance/tests/lms/test_lms_course_home.py
View file @
0899ac56
...
@@ -7,11 +7,9 @@ from nose.plugins.attrib import attr
...
@@ -7,11 +7,9 @@ from nose.plugins.attrib import attr
from
..helpers
import
auto_auth
,
load_data_str
,
UniqueCourseTest
from
..helpers
import
auto_auth
,
load_data_str
,
UniqueCourseTest
from
...fixtures.course
import
CourseFixture
,
XBlockFixtureDesc
from
...fixtures.course
import
CourseFixture
,
XBlockFixtureDesc
from
...pages.common.logout
import
LogoutPage
from
...pages.lms.bookmarks
import
BookmarksPage
from
...pages.lms.bookmarks
import
BookmarksPage
from
...pages.lms.course_home
import
CourseHomePage
from
...pages.lms.course_home
import
CourseHomePage
from
...pages.lms.courseware
import
CoursewarePage
from
...pages.lms.courseware
import
CoursewarePage
from
...pages.studio.overview
import
CourseOutlinePage
as
StudioCourseOutlinePage
class
CourseHomeBaseTest
(
UniqueCourseTest
):
class
CourseHomeBaseTest
(
UniqueCourseTest
):
...
@@ -132,29 +130,10 @@ class CourseHomeA11yTest(CourseHomeBaseTest):
...
@@ -132,29 +130,10 @@ class CourseHomeA11yTest(CourseHomeBaseTest):
def
setUp
(
self
):
def
setUp
(
self
):
super
(
CourseHomeA11yTest
,
self
)
.
setUp
()
super
(
CourseHomeA11yTest
,
self
)
.
setUp
()
self
.
logout_page
=
LogoutPage
(
self
.
browser
)
def
test_course_home_a11y
(
self
):
def
test_course_home_a11y
(
self
):
"""
"""
Test the accessibility of the course home page with course outline.
Test the accessibility of the course home page with course outline.
"""
"""
with
self
.
_logged_in_session
():
course_home_page
=
CourseHomePage
(
self
.
browser
,
self
.
course_id
)
course_home_page
=
CourseHomePage
(
self
.
browser
,
self
.
course_id
)
course_home_page
.
visit
()
course_home_page
.
visit
()
course_home_page
.
a11y_audit
.
check_for_accessibility_errors
()
course_home_page
.
a11y_audit
.
check_for_accessibility_errors
()
@contextmanager
def
_logged_in_session
(
self
,
staff
=
False
):
"""
Ensure that the user is logged in and out appropriately at the beginning
and end of the current test.
"""
self
.
logout_page
.
visit
()
try
:
if
staff
:
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
else
:
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
yield
finally
:
self
.
logout_page
.
visit
()
lms/djangoapps/course_api/blocks/transformers/milestones.py
View file @
0899ac56
...
@@ -19,9 +19,14 @@ log = logging.getLogger(__name__)
...
@@ -19,9 +19,14 @@ log = logging.getLogger(__name__)
class
MilestonesTransformer
(
BlockStructureTransformer
):
class
MilestonesTransformer
(
BlockStructureTransformer
):
"""
"""
Adds special exams (timed, proctored, practice proctored) to the student view.
A transformer that handles both milestones and special (timed) exams.
May exclude special exams.
Excludes all blocks with unfulfilled milestones from the student view.
It excludes all blocks with unfulfilled milestones from the student view. An entrance exam is considered a
milestone, and is not considered a "special exam".
It also includes or excludes all special (timed) exams (timed, proctored, practice proctored) in/from the
student view, based on the value of `include_special_exams`.
"""
"""
WRITE_VERSION
=
1
WRITE_VERSION
=
1
READ_VERSION
=
1
READ_VERSION
=
1
...
@@ -51,21 +56,19 @@ class MilestonesTransformer(BlockStructureTransformer):
...
@@ -51,21 +56,19 @@ class MilestonesTransformer(BlockStructureTransformer):
"""
"""
Modify block structure according to the behavior of milestones and special exams.
Modify block structure according to the behavior of milestones and special exams.
"""
"""
required_content
=
self
.
get_required_content
(
usage_info
,
block_structure
)
course_key
=
block_structure
.
root_block_usage_key
.
course_key
user_can_skip
=
EntranceExamConfiguration
.
user_can_skip_entrance_exam
(
usage_info
.
user
,
course_key
)
required_content
=
milestones_helpers
.
get_required_content
(
course_key
,
usage_info
.
user
)
def
user_gated_from_block
(
block_key
):
def
user_gated_from_block
(
block_key
):
"""
"""
Checks whether the user is gated from accessing this block, first via special exams,
Checks whether the user is gated from accessing this block, first via special exams,
then via a general milestones check.
then via a general milestones check.
"""
"""
if
usage_info
.
has_staff_access
:
if
usage_info
.
has_staff_access
:
return
False
return
False
elif
self
.
has_pending_milestones_for_user
(
block_key
,
usage_info
):
elif
self
.
has_pending_milestones_for_user
(
block_key
,
usage_info
):
return
True
return
True
elif
self
.
gated_by_required_content
(
block_key
,
block_structure
,
user_can_skip
,
required_content
):
elif
self
.
gated_by_required_content
(
block_key
,
block_structure
,
required_content
):
return
True
return
True
elif
(
settings
.
FEATURES
.
get
(
'ENABLE_SPECIAL_EXAMS'
,
False
)
and
elif
(
settings
.
FEATURES
.
get
(
'ENABLE_SPECIAL_EXAMS'
,
False
)
and
(
self
.
is_special_exam
(
block_key
,
block_structure
)
and
(
self
.
is_special_exam
(
block_key
,
block_structure
)
and
...
@@ -76,14 +79,13 @@ class MilestonesTransformer(BlockStructureTransformer):
...
@@ -76,14 +79,13 @@ class MilestonesTransformer(BlockStructureTransformer):
for
block_key
in
block_structure
.
topological_traversal
():
for
block_key
in
block_structure
.
topological_traversal
():
if
user_gated_from_block
(
block_key
):
if
user_gated_from_block
(
block_key
):
block_structure
.
remove_block
(
block_key
,
False
)
block_structure
.
remove_block
(
block_key
,
False
)
el
se
:
el
if
self
.
is_special_exam
(
block_key
,
block_structure
)
:
self
.
add_special_exam_info
(
block_key
,
block_structure
,
usage_info
)
self
.
add_special_exam_info
(
block_key
,
block_structure
,
usage_info
)
@staticmethod
@staticmethod
def
is_special_exam
(
block_key
,
block_structure
):
def
is_special_exam
(
block_key
,
block_structure
):
"""
"""
Test whether the block is a special exam. These exams are always excluded
Test whether the block is a special exam.
from the student view.
"""
"""
return
(
return
(
block_structure
.
get_xblock_field
(
block_key
,
'is_proctored_enabled'
)
or
block_structure
.
get_xblock_field
(
block_key
,
'is_proctored_enabled'
)
or
...
@@ -106,45 +108,59 @@ class MilestonesTransformer(BlockStructureTransformer):
...
@@ -106,45 +108,59 @@ class MilestonesTransformer(BlockStructureTransformer):
def
add_special_exam_info
(
self
,
block_key
,
block_structure
,
usage_info
):
def
add_special_exam_info
(
self
,
block_key
,
block_structure
,
usage_info
):
"""
"""
Adds special exam information to course blocks.
For special exams, add the special exam information to the course blocks.
"""
special_exam_attempt_context
=
None
try
:
# Calls into edx_proctoring subsystem to get relevant special exam information.
# This will return None, if (user, course_id, content_id) is not applicable.
special_exam_attempt_context
=
get_attempt_status_summary
(
usage_info
.
user
.
id
,
unicode
(
block_key
.
course_key
),
unicode
(
block_key
)
)
except
ProctoredExamNotFoundException
as
ex
:
log
.
exception
(
ex
)
if
special_exam_attempt_context
:
# This user has special exam context for this block so add it.
block_structure
.
set_transformer_block_field
(
block_key
,
self
,
'special_exam_info'
,
special_exam_attempt_context
,
)
@staticmethod
def
get_required_content
(
usage_info
,
block_structure
):
"""
"""
if
self
.
is_special_exam
(
block_key
,
block_structure
):
Get the required content for the course.
# call into edx_proctoring subsystem to get relevant special exam information
This takes into account if the user can skip the entrance exam.
#
# This will return None, if (user, course_id, content_id) is not applicable
"""
special_exam_attempt_context
=
None
course_key
=
block_structure
.
root_block_usage_key
.
course_key
try
:
user_can_skip_entrance_exam
=
EntranceExamConfiguration
.
user_can_skip_entrance_exam
(
usage_info
.
user
,
course_key
)
special_exam_attempt_context
=
get_attempt_status_summary
(
required_content
=
milestones_helpers
.
get_required_content
(
course_key
,
usage_info
.
user
)
usage_info
.
user
.
id
,
unicode
(
block_key
.
course_key
),
if
not
required_content
:
unicode
(
block_key
)
return
required_content
)
except
ProctoredExamNotFoundException
as
ex
:
if
user_can_skip_entrance_exam
:
log
.
exception
(
ex
)
# remove the entrance exam from required content
entrance_exam_id
=
block_structure
.
get_xblock_field
(
block_structure
.
root_block_usage_key
,
'entrance_exam_id'
)
if
special_exam_attempt_context
:
required_content
=
[
content
for
content
in
required_content
if
not
content
==
entrance_exam_id
]
# yes, user has proctoring context about
# this level of the courseware
return
required_content
# so add to the accordion data context
block_structure
.
set_transformer_block_field
(
block_key
,
self
,
'special_exam_info'
,
special_exam_attempt_context
,
)
@staticmethod
@staticmethod
def
gated_by_required_content
(
block_key
,
block_structure
,
user_can_skip
,
required_content
):
def
gated_by_required_content
(
block_key
,
block_structure
,
required_content
):
"""
"""
Returns True if the current block associated with the block_key should be gated by the given required_content.
Returns True if the current block associated with the block_key should be gated by the given required_content.
Returns False otherwise.
Returns False otherwise.
"""
"""
if
not
required_content
:
if
not
required_content
:
return
False
return
False
exam_id
=
block_structure
.
get_xblock_field
(
block_structure
.
root_block_usage_key
,
'entrance_exam_id'
)
if
user_can_skip
:
required_content
=
[
content
for
content
in
required_content
if
not
content
==
exam_id
]
if
block_key
.
block_type
==
'chapter'
and
unicode
(
block_key
)
not
in
required_content
:
if
block_key
.
block_type
==
'chapter'
and
unicode
(
block_key
)
not
in
required_content
:
return
True
return
True
...
...
openedx/features/course_experience/templates/course_experience/course-outline-fragment.html
View file @
0899ac56
...
@@ -49,6 +49,7 @@ from django.utils.translation import ugettext as _
...
@@ -49,6 +49,7 @@ from django.utils.translation import ugettext as _
## Exam subsections expose exam status message field as well as a status icon
## Exam subsections expose exam status message field as well as a status icon
<
%
<
%
if
subsection
.
get
('
due
')
is
None:
if
subsection
.
get
('
due
')
is
None:
#
examples:
Homework
,
Lab
,
etc
.
data_string =
subsection.get('format')
data_string =
subsection.get('format')
else:
else:
if
'
special_exam_info
'
in
subsection:
if
'
special_exam_info
'
in
subsection:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment