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
0bd2286e
Commit
0bd2286e
authored
May 15, 2014
by
Johnny Brown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
show a friendly message for an empty course rather than an error page
parent
85f1997f
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
202 additions
and
25 deletions
+202
-25
AUTHORS
+1
-0
common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
+36
-0
common/lib/xmodule/xmodule/x_module.py
+23
-0
lms/djangoapps/courseware/tests/test_navigation.py
+57
-0
lms/djangoapps/courseware/tests/test_view_authentication.py
+42
-13
lms/djangoapps/courseware/tests/test_views.py
+1
-1
lms/djangoapps/courseware/views.py
+38
-11
lms/templates/courseware/courseware.html
+4
-0
No files found.
AUTHORS
View file @
0bd2286e
...
@@ -151,3 +151,4 @@ Steven Burch <stv@stanford.edu>
...
@@ -151,3 +151,4 @@ Steven Burch <stv@stanford.edu>
Waqas Khalid <wkhalid@edx.org>
Waqas Khalid <wkhalid@edx.org>
Muhammad Ammar <mammar@edx.org>
Muhammad Ammar <mammar@edx.org>
Abdallah Nassif <abdoosh00@gmail.com>
Abdallah Nassif <abdoosh00@gmail.com>
Johnny Brown <johnnybrown7@gmail.com>
common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py
View file @
0bd2286e
...
@@ -506,6 +506,42 @@ class SplitModuleTest(unittest.TestCase):
...
@@ -506,6 +506,42 @@ class SplitModuleTest(unittest.TestCase):
return
element
return
element
class
TestHasChildrenAtDepth
(
SplitModuleTest
):
"""Test the has_children_at_depth method of XModuleMixin. """
def
test_has_children_at_depth
(
self
):
course_locator
=
CourseLocator
(
org
=
'testx'
,
offering
=
'GreekHero'
,
branch
=
'draft'
)
block_locator
=
BlockUsageLocator
(
course_locator
,
'course'
,
'head12345'
)
block
=
modulestore
()
.
get_item
(
block_locator
)
self
.
assertRaises
(
ValueError
,
block
.
has_children_at_depth
,
-
1
,
)
self
.
assertTrue
(
block
.
has_children_at_depth
(
0
))
self
.
assertTrue
(
block
.
has_children_at_depth
(
1
))
self
.
assertFalse
(
block
.
has_children_at_depth
(
2
))
ch1
=
modulestore
()
.
get_item
(
BlockUsageLocator
(
course_locator
,
'chapter'
,
block_id
=
'chapter1'
)
)
self
.
assertFalse
(
ch1
.
has_children_at_depth
(
0
))
ch2
=
modulestore
()
.
get_item
(
BlockUsageLocator
(
course_locator
,
'chapter'
,
block_id
=
'chapter2'
)
)
self
.
assertFalse
(
ch2
.
has_children_at_depth
(
0
))
ch3
=
modulestore
()
.
get_item
(
BlockUsageLocator
(
course_locator
,
'chapter'
,
block_id
=
'chapter3'
)
)
self
.
assertTrue
(
ch3
.
has_children_at_depth
(
0
))
self
.
assertFalse
(
ch3
.
has_children_at_depth
(
1
))
class
SplitModuleCourseTests
(
SplitModuleTest
):
class
SplitModuleCourseTests
(
SplitModuleTest
):
'''
'''
Course CRUD operation tests
Course CRUD operation tests
...
...
common/lib/xmodule/xmodule/x_module.py
View file @
0bd2286e
...
@@ -209,6 +209,29 @@ class XModuleMixin(XBlockMixin):
...
@@ -209,6 +209,29 @@ class XModuleMixin(XBlockMixin):
result
[
field
.
name
]
=
field
.
read_json
(
self
)
result
[
field
.
name
]
=
field
.
read_json
(
self
)
return
result
return
result
def
has_children_at_depth
(
self
,
depth
):
"""
Returns true if self has children at the given depth. depth==0 returns
false if self is a leaf, true otherwise.
SELF
|
[child at depth 0]
/
\
[depth 1] [depth 1]
/
\
[depth 2] [depth 2]
So the example above would return True for `has_children_at_depth(2)`, and False
for depth > 2
"""
if
depth
<
0
:
raise
ValueError
(
"negative depth argument is invalid"
)
elif
depth
==
0
:
return
bool
(
self
.
get_children
())
else
:
return
any
(
child
.
has_children_at_depth
(
depth
-
1
)
for
child
in
self
.
get_children
())
def
get_content_titles
(
self
):
def
get_content_titles
(
self
):
"""
"""
Returns list of content titles for all of self's children.
Returns list of content titles for all of self's children.
...
...
lms/djangoapps/courseware/tests/test_navigation.py
View file @
0bd2286e
...
@@ -13,6 +13,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
...
@@ -13,6 +13,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from
courseware.tests.helpers
import
LoginEnrollmentTestCase
,
check_for_get_code
from
courseware.tests.helpers
import
LoginEnrollmentTestCase
,
check_for_get_code
from
courseware.tests.modulestore_config
import
TEST_DATA_MIXED_MODULESTORE
from
courseware.tests.modulestore_config
import
TEST_DATA_MIXED_MODULESTORE
from
courseware.tests.factories
import
GlobalStaffFactory
@override_settings
(
MODULESTORE
=
TEST_DATA_MIXED_MODULESTORE
)
@override_settings
(
MODULESTORE
=
TEST_DATA_MIXED_MODULESTORE
)
...
@@ -35,6 +36,8 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
...
@@ -35,6 +36,8 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
display_name
=
'Welcome'
)
display_name
=
'Welcome'
)
self
.
section9
=
ItemFactory
.
create
(
parent_location
=
self
.
chapter9
.
location
,
self
.
section9
=
ItemFactory
.
create
(
parent_location
=
self
.
chapter9
.
location
,
display_name
=
'factory_section'
)
display_name
=
'factory_section'
)
self
.
unit0
=
ItemFactory
.
create
(
parent_location
=
self
.
section0
.
location
,
display_name
=
'New Unit'
)
# Create student accounts and activate them.
# Create student accounts and activate them.
for
i
in
range
(
len
(
self
.
STUDENT_INFO
)):
for
i
in
range
(
len
(
self
.
STUDENT_INFO
)):
...
@@ -43,6 +46,8 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
...
@@ -43,6 +46,8 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
self
.
create_account
(
username
,
email
,
password
)
self
.
create_account
(
username
,
email
,
password
)
self
.
activate_user
(
email
)
self
.
activate_user
(
email
)
self
.
staff_user
=
GlobalStaffFactory
()
@override_settings
(
SESSION_INACTIVITY_TIMEOUT_IN_SECONDS
=
1
)
@override_settings
(
SESSION_INACTIVITY_TIMEOUT_IN_SECONDS
=
1
)
def
test_inactive_session_timeout
(
self
):
def
test_inactive_session_timeout
(
self
):
"""
"""
...
@@ -135,3 +140,55 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
...
@@ -135,3 +140,55 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
self
.
assertRedirects
(
resp
,
reverse
(
'courseware_chapter'
,
self
.
assertRedirects
(
resp
,
reverse
(
'courseware_chapter'
,
kwargs
=
{
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
(),
kwargs
=
{
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
(),
'chapter'
:
'factory_chapter'
}))
'chapter'
:
'factory_chapter'
}))
def
test_incomplete_course
(
self
):
email
=
self
.
staff_user
.
email
password
=
"test"
self
.
login
(
email
,
password
)
self
.
enroll
(
self
.
test_course
,
True
)
test_course_id
=
self
.
test_course
.
id
.
to_deprecated_string
()
check_for_get_code
(
self
,
200
,
reverse
(
'courseware'
,
kwargs
=
{
'course_id'
:
test_course_id
}
)
)
section
=
ItemFactory
.
create
(
parent_location
=
self
.
test_course
.
location
,
display_name
=
'New Section'
)
check_for_get_code
(
self
,
200
,
reverse
(
'courseware'
,
kwargs
=
{
'course_id'
:
test_course_id
}
)
)
subsection
=
ItemFactory
.
create
(
parent_location
=
section
.
location
,
display_name
=
'New Subsection'
)
check_for_get_code
(
self
,
200
,
reverse
(
'courseware'
,
kwargs
=
{
'course_id'
:
test_course_id
}
)
)
ItemFactory
.
create
(
parent_location
=
subsection
.
location
,
display_name
=
'New Unit'
)
check_for_get_code
(
self
,
302
,
reverse
(
'courseware'
,
kwargs
=
{
'course_id'
:
test_course_id
}
)
)
lms/djangoapps/courseware/tests/test_view_authentication.py
View file @
0bd2286e
...
@@ -112,23 +112,39 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
...
@@ -112,23 +112,39 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
def
setUp
(
self
):
def
setUp
(
self
):
self
.
course
=
CourseFactory
.
create
(
number
=
'999'
,
display_name
=
'Robot_Super_Course'
)
self
.
course
=
CourseFactory
.
create
(
number
=
'999'
,
display_name
=
'Robot_Super_Course'
)
self
.
overview_chapter
=
ItemFactory
.
create
(
display_name
=
'Overview'
)
self
.
courseware_chapter
=
ItemFactory
.
create
(
display_name
=
'courseware'
)
self
.
courseware_chapter
=
ItemFactory
.
create
(
display_name
=
'courseware'
)
self
.
overview_chapter
=
ItemFactory
.
create
(
parent_location
=
self
.
course
.
location
,
display_name
=
'Super Overview'
)
self
.
welcome_section
=
ItemFactory
.
create
(
parent_location
=
self
.
overview_chapter
.
location
,
display_name
=
'Super Welcome'
)
self
.
welcome_unit
=
ItemFactory
.
create
(
parent_location
=
self
.
welcome_section
.
location
,
display_name
=
'Super Unit'
)
self
.
course
=
modulestore
()
.
get_course
(
self
.
course
.
id
)
self
.
course
=
modulestore
()
.
get_course
(
self
.
course
.
id
)
self
.
test_course
=
CourseFactory
.
create
(
number
=
'666'
,
display_name
=
'Robot_Sub_Course'
)
self
.
test_course
=
CourseFactory
.
create
(
number
=
'666'
,
display_name
=
'Robot_Sub_Course'
)
self
.
other_org_course
=
CourseFactory
.
create
(
org
=
'Other_Org_Course'
)
self
.
other_org_course
=
CourseFactory
.
create
(
org
=
'Other_Org_Course'
)
self
.
sub_courseware_chapter
=
ItemFactory
.
create
(
self
.
sub_courseware_chapter
=
ItemFactory
.
create
(
parent_location
=
self
.
test_course
.
location
,
display_name
=
'courseware'
parent_location
=
self
.
test_course
.
location
,
display_name
=
'courseware'
)
)
self
.
sub_overview_chapter
=
ItemFactory
.
create
(
self
.
sub_overview_chapter
=
ItemFactory
.
create
(
parent_location
=
self
.
sub_courseware_chapter
.
location
,
parent_location
=
self
.
sub_courseware_chapter
.
location
,
display_name
=
'Overview'
display_name
=
'Overview'
)
)
self
.
welcome_section
=
ItemFactory
.
create
(
self
.
sub_
welcome_section
=
ItemFactory
.
create
(
parent_location
=
self
.
overview_chapter
.
location
,
parent_location
=
self
.
sub_
overview_chapter
.
location
,
display_name
=
'Welcome'
display_name
=
'Welcome'
)
)
self
.
sub_welcome_unit
=
ItemFactory
.
create
(
parent_location
=
self
.
sub_welcome_section
.
location
,
display_name
=
'New Unit'
)
self
.
test_course
=
modulestore
()
.
get_course
(
self
.
test_course
.
id
)
self
.
test_course
=
modulestore
()
.
get_course
(
self
.
test_course
.
id
)
self
.
global_staff_user
=
GlobalStaffFactory
()
self
.
global_staff_user
=
GlobalStaffFactory
()
...
@@ -151,9 +167,13 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
...
@@ -151,9 +167,13 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
self
.
login
(
self
.
unenrolled_user
)
self
.
login
(
self
.
unenrolled_user
)
response
=
self
.
client
.
get
(
reverse
(
'courseware'
,
response
=
self
.
client
.
get
(
reverse
(
'courseware'
,
kwargs
=
{
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
()}))
kwargs
=
{
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
()}))
self
.
assertRedirects
(
response
,
self
.
assertRedirects
(
reverse
(
'about_course'
,
response
,
args
=
[
self
.
course
.
id
.
to_deprecated_string
()]))
reverse
(
'about_course'
,
args
=
[
self
.
course
.
id
.
to_deprecated_string
()]
)
)
def
test_redirection_enrolled
(
self
):
def
test_redirection_enrolled
(
self
):
"""
"""
...
@@ -162,14 +182,22 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
...
@@ -162,14 +182,22 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
"""
"""
self
.
login
(
self
.
enrolled_user
)
self
.
login
(
self
.
enrolled_user
)
response
=
self
.
client
.
get
(
reverse
(
'courseware'
,
response
=
self
.
client
.
get
(
kwargs
=
{
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
()}))
reverse
(
'courseware'
,
kwargs
=
{
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
()}
)
)
self
.
assertRedirects
(
response
,
self
.
assertRedirects
(
reverse
(
'courseware_section'
,
response
,
reverse
(
'courseware_section'
,
kwargs
=
{
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
(),
kwargs
=
{
'course_id'
:
self
.
course
.
id
.
to_deprecated_string
(),
'chapter'
:
'Overview'
,
'chapter'
:
self
.
overview_chapter
.
url_name
,
'section'
:
'Welcome'
}))
'section'
:
self
.
welcome_section
.
url_name
}
)
)
def
test_instructor_page_access_nonstaff
(
self
):
def
test_instructor_page_access_nonstaff
(
self
):
"""
"""
...
@@ -314,6 +342,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
...
@@ -314,6 +342,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
"""
"""
now
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
now
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
tomorrow
=
now
+
datetime
.
timedelta
(
days
=
1
)
tomorrow
=
now
+
datetime
.
timedelta
(
days
=
1
)
self
.
course
.
start
=
tomorrow
self
.
course
.
start
=
tomorrow
self
.
test_course
.
start
=
tomorrow
self
.
test_course
.
start
=
tomorrow
self
.
course
=
self
.
update_course
(
self
.
course
)
self
.
course
=
self
.
update_course
(
self
.
course
)
...
...
lms/djangoapps/courseware/tests/test_views.py
View file @
0bd2286e
...
@@ -145,7 +145,7 @@ class ViewsTestCase(TestCase):
...
@@ -145,7 +145,7 @@ class ViewsTestCase(TestCase):
mock_module
.
position
=
3
mock_module
.
position
=
3
mock_module
.
get_display_items
.
return_value
=
[]
mock_module
.
get_display_items
.
return_value
=
[]
self
.
assertRaises
(
Http404
,
views
.
redirect_to_course_position
,
self
.
assertRaises
(
Http404
,
views
.
redirect_to_course_position
,
mock_module
)
mock_module
,
views
.
CONTENT_DEPTH
)
def
test_registered_for_course
(
self
):
def
test_registered_for_course
(
self
):
self
.
assertFalse
(
views
.
registered_for_course
(
'Basketweaving'
,
None
))
self
.
assertFalse
(
views
.
registered_for_course
(
'Basketweaving'
,
None
))
...
...
lms/djangoapps/courseware/views.py
View file @
0bd2286e
...
@@ -52,6 +52,7 @@ log = logging.getLogger("edx.courseware")
...
@@ -52,6 +52,7 @@ log = logging.getLogger("edx.courseware")
template_imports
=
{
'urllib'
:
urllib
}
template_imports
=
{
'urllib'
:
urllib
}
CONTENT_DEPTH
=
2
def
user_groups
(
user
):
def
user_groups
(
user
):
"""
"""
...
@@ -113,17 +114,36 @@ def render_accordion(request, course, chapter, section, field_data_cache):
...
@@ -113,17 +114,36 @@ def render_accordion(request, course, chapter, section, field_data_cache):
return
render_to_string
(
'courseware/accordion.html'
,
context
)
return
render_to_string
(
'courseware/accordion.html'
,
context
)
def
get_current_child
(
xmodule
):
def
get_current_child
(
xmodule
,
min_depth
=
None
):
"""
"""
Get the xmodule.position's display item of an xmodule that has a position and
Get the xmodule.position's display item of an xmodule that has a position and
children. If xmodule has no position or is out of bounds, return the first child.
children. If xmodule has no position or is out of bounds, return the first
child with children extending down to content_depth.
For example, if chapter_one has no position set, with two child sections,
section-A having no children and section-B having a discussion unit,
`get_current_child(chapter, min_depth=1)` will return section-B.
Returns None only if there are no children at all.
Returns None only if there are no children at all.
"""
"""
def
_get_default_child_module
(
child_modules
):
"""Returns the first child of xmodule, subject to min_depth."""
if
not
child_modules
:
default_child
=
None
elif
not
min_depth
>
0
:
default_child
=
child_modules
[
0
]
else
:
content_children
=
[
child
for
child
in
child_modules
if
child
.
has_children_at_depth
(
min_depth
-
1
)]
default_child
=
content_children
[
0
]
if
content_children
else
None
return
default_child
if
not
hasattr
(
xmodule
,
'position'
):
if
not
hasattr
(
xmodule
,
'position'
):
return
None
return
None
if
xmodule
.
position
is
None
:
if
xmodule
.
position
is
None
:
pos
=
0
return
_get_default_child_module
(
xmodule
.
get_display_items
())
else
:
else
:
# position is 1-indexed.
# position is 1-indexed.
pos
=
xmodule
.
position
-
1
pos
=
xmodule
.
position
-
1
...
@@ -132,14 +152,15 @@ def get_current_child(xmodule):
...
@@ -132,14 +152,15 @@ def get_current_child(xmodule):
if
0
<=
pos
<
len
(
children
):
if
0
<=
pos
<
len
(
children
):
child
=
children
[
pos
]
child
=
children
[
pos
]
elif
len
(
children
)
>
0
:
elif
len
(
children
)
>
0
:
# Something is wrong. Default to first child
# module has a set position, but the position is out of range.
child
=
children
[
0
]
# return default child.
child
=
_get_default_child_module
(
children
)
else
:
else
:
child
=
None
child
=
None
return
child
return
child
def
redirect_to_course_position
(
course_module
):
def
redirect_to_course_position
(
course_module
,
content_depth
):
"""
"""
Return a redirect to the user's current place in the course.
Return a redirect to the user's current place in the course.
...
@@ -153,7 +174,7 @@ def redirect_to_course_position(course_module):
...
@@ -153,7 +174,7 @@ def redirect_to_course_position(course_module):
"""
"""
urlargs
=
{
'course_id'
:
course_module
.
id
.
to_deprecated_string
()}
urlargs
=
{
'course_id'
:
course_module
.
id
.
to_deprecated_string
()}
chapter
=
get_current_child
(
course_module
)
chapter
=
get_current_child
(
course_module
,
min_depth
=
content_depth
)
if
chapter
is
None
:
if
chapter
is
None
:
# oops. Something bad has happened.
# oops. Something bad has happened.
raise
Http404
(
"No chapter found when loading current position in course"
)
raise
Http404
(
"No chapter found when loading current position in course"
)
...
@@ -163,7 +184,7 @@ def redirect_to_course_position(course_module):
...
@@ -163,7 +184,7 @@ def redirect_to_course_position(course_module):
return
redirect
(
reverse
(
'courseware_chapter'
,
kwargs
=
urlargs
))
return
redirect
(
reverse
(
'courseware_chapter'
,
kwargs
=
urlargs
))
# Relying on default of returning first child
# Relying on default of returning first child
section
=
get_current_child
(
chapter
)
section
=
get_current_child
(
chapter
,
min_depth
=
content_depth
-
1
)
if
section
is
None
:
if
section
is
None
:
raise
Http404
(
"No section found when loading current position in course"
)
raise
Http404
(
"No section found when loading current position in course"
)
...
@@ -266,9 +287,6 @@ def index(request, course_id, chapter=None, section=None,
...
@@ -266,9 +287,6 @@ def index(request, course_id, chapter=None, section=None,
studio_url
=
get_studio_url
(
course_key
,
'course'
)
studio_url
=
get_studio_url
(
course_key
,
'course'
)
if
chapter
is
None
:
return
redirect_to_course_position
(
course_module
)
context
=
{
context
=
{
'csrf'
:
csrf
(
request
)[
'csrf_token'
],
'csrf'
:
csrf
(
request
)[
'csrf_token'
],
'accordion'
:
render_accordion
(
request
,
course
,
chapter
,
section
,
field_data_cache
),
'accordion'
:
render_accordion
(
request
,
course
,
chapter
,
section
,
field_data_cache
),
...
@@ -283,6 +301,15 @@ def index(request, course_id, chapter=None, section=None,
...
@@ -283,6 +301,15 @@ def index(request, course_id, chapter=None, section=None,
'reverifications'
:
fetch_reverify_banner_info
(
request
,
course_key
),
'reverifications'
:
fetch_reverify_banner_info
(
request
,
course_key
),
}
}
has_content
=
course
.
has_children_at_depth
(
CONTENT_DEPTH
)
if
not
has_content
:
# Show empty courseware for a course with no units
return
render_to_response
(
'courseware/courseware.html'
,
context
)
elif
chapter
is
None
:
# passing CONTENT_DEPTH avoids returning 404 for a course with an
# empty first section and a second section with content
return
redirect_to_course_position
(
course_module
,
CONTENT_DEPTH
)
# Only show the chat if it's enabled by the course and in the
# Only show the chat if it's enabled by the course and in the
# settings.
# settings.
show_chat
=
course
.
show_chat
and
settings
.
FEATURES
[
'ENABLE_CHAT'
]
show_chat
=
course
.
show_chat
and
settings
.
FEATURES
[
'ENABLE_CHAT'
]
...
...
lms/templates/courseware/courseware.html
View file @
0bd2286e
...
@@ -195,7 +195,11 @@ ${fragment.foot_html()}
...
@@ -195,7 +195,11 @@ ${fragment.foot_html()}
<div
id=
"accordion"
style=
"display: none"
>
<div
id=
"accordion"
style=
"display: none"
>
<nav
aria-label=
"${_('Course Navigation')}"
>
<nav
aria-label=
"${_('Course Navigation')}"
>
% if accordion.strip():
${accordion}
${accordion}
% else:
<div
class=
"chapter"
>
${_("No content has been added to this course")}
</div>
% endif
</nav>
</nav>
</div>
</div>
</div>
</div>
...
...
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