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
a0bae0c7
Commit
a0bae0c7
authored
Mar 27, 2015
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert VerticalModule/VerticalDescriptor to a pure XBlock: VerticalBlock
parent
8341f1b7
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
130 additions
and
71 deletions
+130
-71
common/djangoapps/xmodule_modifiers.py
+6
-2
common/lib/xmodule/setup.py
+2
-2
common/lib/xmodule/xmodule/css/wrapper/display.scss
+0
-0
common/lib/xmodule/xmodule/tests/test_crowdsource_hinter.py
+3
-3
common/lib/xmodule/xmodule/tests/test_studio_editable.py
+5
-2
common/lib/xmodule/xmodule/tests/test_vertical.py
+9
-3
common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py
+23
-8
common/lib/xmodule/xmodule/vertical_block.py
+68
-31
common/lib/xmodule/xmodule/wrapper_module.py
+6
-12
lms/djangoapps/courseware/features/common.py
+5
-5
lms/djangoapps/courseware/tests/test_module_render.py
+2
-2
lms/static/sass/course/courseware/_courseware.scss
+1
-1
No files found.
common/djangoapps/xmodule_modifiers.py
View file @
a0bae0c7
...
@@ -9,16 +9,19 @@ import static_replace
...
@@ -9,16 +9,19 @@ import static_replace
import
uuid
import
uuid
import
markupsafe
import
markupsafe
from
lxml
import
html
,
etree
from
lxml
import
html
,
etree
from
contracts
import
contract
from
django.conf
import
settings
from
django.conf
import
settings
from
django.utils.timezone
import
UTC
from
django.utils.timezone
import
UTC
from
django.utils.html
import
escape
from
django.utils.html
import
escape
from
django.contrib.auth.models
import
User
from
edxmako.shortcuts
import
render_to_string
from
edxmako.shortcuts
import
render_to_string
from
xblock.core
import
XBlock
from
xblock.exceptions
import
InvalidScopeError
from
xblock.exceptions
import
InvalidScopeError
from
xblock.fragment
import
Fragment
from
xblock.fragment
import
Fragment
from
xmodule.seq_module
import
SequenceModule
from
xmodule.seq_module
import
SequenceModule
from
xmodule.vertical_
module
import
VerticalModule
from
xmodule.vertical_
block
import
VerticalBlock
from
xmodule.x_module
import
shim_xmodule_js
,
XModuleDescriptor
,
XModule
,
PREVIEW_VIEWS
,
STUDIO_VIEW
from
xmodule.x_module
import
shim_xmodule_js
,
XModuleDescriptor
,
XModule
,
PREVIEW_VIEWS
,
STUDIO_VIEW
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
...
@@ -193,6 +196,7 @@ def grade_histogram(module_id):
...
@@ -193,6 +196,7 @@ def grade_histogram(module_id):
return
grades
return
grades
@contract
(
user
=
User
,
has_instructor_access
=
bool
,
block
=
XBlock
,
view
=
basestring
,
frag
=
Fragment
,
context
=
dict
)
def
add_staff_markup
(
user
,
has_instructor_access
,
block
,
view
,
frag
,
context
):
# pylint: disable=unused-argument
def
add_staff_markup
(
user
,
has_instructor_access
,
block
,
view
,
frag
,
context
):
# pylint: disable=unused-argument
"""
"""
Updates the supplied module with a new get_html function that wraps
Updates the supplied module with a new get_html function that wraps
...
@@ -204,7 +208,7 @@ def add_staff_markup(user, has_instructor_access, block, view, frag, context):
...
@@ -204,7 +208,7 @@ def add_staff_markup(user, has_instructor_access, block, view, frag, context):
Does nothing if module is a SequenceModule.
Does nothing if module is a SequenceModule.
"""
"""
# TODO: make this more general, eg use an XModule attribute instead
# TODO: make this more general, eg use an XModule attribute instead
if
isinstance
(
block
,
Vertical
Module
)
and
(
not
context
or
not
context
.
get
(
'child_of_vertical'
,
False
)):
if
isinstance
(
block
,
Vertical
Block
)
and
(
not
context
or
not
context
.
get
(
'child_of_vertical'
,
False
)):
# check that the course is a mongo backed Studio course before doing work
# check that the course is a mongo backed Studio course before doing work
is_mongo_course
=
modulestore
()
.
get_modulestore_type
(
block
.
location
.
course_key
)
!=
ModuleStoreEnum
.
Type
.
xml
is_mongo_course
=
modulestore
()
.
get_modulestore_type
(
block
.
location
.
course_key
)
!=
ModuleStoreEnum
.
Type
.
xml
is_studio_course
=
block
.
course_edit_method
==
"Studio"
is_studio_course
=
block
.
course_edit_method
==
"Studio"
...
...
common/lib/xmodule/setup.py
View file @
a0bae0c7
...
@@ -22,7 +22,6 @@ XMODULES = [
...
@@ -22,7 +22,6 @@ XMODULES = [
"section = xmodule.backcompat_module:SemanticSectionDescriptor"
,
"section = xmodule.backcompat_module:SemanticSectionDescriptor"
,
"sequential = xmodule.seq_module:SequenceDescriptor"
,
"sequential = xmodule.seq_module:SequenceDescriptor"
,
"slides = xmodule.backcompat_module:TranslateCustomTagDescriptor"
,
"slides = xmodule.backcompat_module:TranslateCustomTagDescriptor"
,
"vertical = xmodule.vertical_module:VerticalDescriptor"
,
"video = xmodule.video_module:VideoDescriptor"
,
"video = xmodule.video_module:VideoDescriptor"
,
"videoalpha = xmodule.video_module:VideoDescriptor"
,
"videoalpha = xmodule.video_module:VideoDescriptor"
,
"videodev = xmodule.backcompat_module:TranslateCustomTagDescriptor"
,
"videodev = xmodule.backcompat_module:TranslateCustomTagDescriptor"
,
...
@@ -32,7 +31,6 @@ XMODULES = [
...
@@ -32,7 +31,6 @@ XMODULES = [
"static_tab = xmodule.html_module:StaticTabDescriptor"
,
"static_tab = xmodule.html_module:StaticTabDescriptor"
,
"custom_tag_template = xmodule.raw_module:RawDescriptor"
,
"custom_tag_template = xmodule.raw_module:RawDescriptor"
,
"about = xmodule.html_module:AboutDescriptor"
,
"about = xmodule.html_module:AboutDescriptor"
,
"wrapper = xmodule.wrapper_module:WrapperDescriptor"
,
"graphical_slider_tool = xmodule.gst_module:GraphicalSliderToolDescriptor"
,
"graphical_slider_tool = xmodule.gst_module:GraphicalSliderToolDescriptor"
,
"annotatable = xmodule.annotatable_module:AnnotatableDescriptor"
,
"annotatable = xmodule.annotatable_module:AnnotatableDescriptor"
,
"textannotation = xmodule.textannotation_module:TextAnnotationDescriptor"
,
"textannotation = xmodule.textannotation_module:TextAnnotationDescriptor"
,
...
@@ -47,6 +45,8 @@ XMODULES = [
...
@@ -47,6 +45,8 @@ XMODULES = [
]
]
XBLOCKS
=
[
XBLOCKS
=
[
"library = xmodule.library_root_xblock:LibraryRoot"
,
"library = xmodule.library_root_xblock:LibraryRoot"
,
"vertical = xmodule.vertical_block:VerticalBlock"
,
"wrapper = xmodule.wrapper_module:WrapperBlock"
,
]
]
setup
(
setup
(
...
...
common/lib/xmodule/xmodule/css/wrapper/display.scss
deleted
100644 → 0
View file @
8341f1b7
common/lib/xmodule/xmodule/tests/test_crowdsource_hinter.py
View file @
a0bae0c7
...
@@ -7,7 +7,7 @@ import unittest
...
@@ -7,7 +7,7 @@ import unittest
import
copy
import
copy
from
xmodule.crowdsource_hinter
import
CrowdsourceHinterModule
from
xmodule.crowdsource_hinter
import
CrowdsourceHinterModule
from
xmodule.vertical_
module
import
VerticalModule
,
VerticalDescriptor
from
xmodule.vertical_
block
import
VerticalBlock
from
xmodule.x_module
import
STUDENT_VIEW
from
xmodule.x_module
import
STUDENT_VIEW
from
xblock.field_data
import
DictFieldData
from
xblock.field_data
import
DictFieldData
from
xblock.fragment
import
Fragment
from
xblock.fragment
import
Fragment
...
@@ -203,8 +203,8 @@ class VerticalWithModulesFactory(object):
...
@@ -203,8 +203,8 @@ class VerticalWithModulesFactory(object):
"""Make a vertical."""
"""Make a vertical."""
field_data
=
{
'data'
:
VerticalWithModulesFactory
.
sample_problem_xml
}
field_data
=
{
'data'
:
VerticalWithModulesFactory
.
sample_problem_xml
}
system
=
get_test_system
()
system
=
get_test_system
()
descriptor
=
Vertical
Descriptor
.
from
_xml
(
VerticalWithModulesFactory
.
sample_problem_xml
,
system
)
descriptor
=
Vertical
Block
.
parse
_xml
(
VerticalWithModulesFactory
.
sample_problem_xml
,
system
)
module
=
Vertical
Module
(
system
,
descriptor
,
field_data
)
module
=
Vertical
Block
(
system
,
descriptor
,
field_data
)
return
module
return
module
...
...
common/lib/xmodule/xmodule/tests/test_studio_editable.py
View file @
a0bae0c7
...
@@ -2,11 +2,14 @@
...
@@ -2,11 +2,14 @@
Tests for StudioEditableModule.
Tests for StudioEditableModule.
"""
"""
from
xmodule.tests.test_vertical
import
BaseVertical
Module
Test
from
xmodule.tests.test_vertical
import
BaseVertical
Block
Test
from
xmodule.x_module
import
AUTHOR_VIEW
from
xmodule.x_module
import
AUTHOR_VIEW
class
StudioEditableModuleTestCase
(
BaseVerticalModuleTest
):
class
StudioEditableModuleTestCase
(
BaseVerticalBlockTest
):
"""
Class containing StudioEditableModule tests.
"""
def
test_render_reorderable_children
(
self
):
def
test_render_reorderable_children
(
self
):
"""
"""
Test the behavior of render_reorderable_children.
Test the behavior of render_reorderable_children.
...
...
common/lib/xmodule/xmodule/tests/test_vertical.py
View file @
a0bae0c7
...
@@ -9,12 +9,15 @@ from xmodule.tests.xml import factories as xml
...
@@ -9,12 +9,15 @@ from xmodule.tests.xml import factories as xml
from
xmodule.x_module
import
STUDENT_VIEW
,
AUTHOR_VIEW
from
xmodule.x_module
import
STUDENT_VIEW
,
AUTHOR_VIEW
class
BaseVerticalModuleTest
(
XModuleXmlImportTest
):
class
BaseVerticalBlockTest
(
XModuleXmlImportTest
):
"""
Tests for the BaseVerticalBlock.
"""
test_html_1
=
'Test HTML 1'
test_html_1
=
'Test HTML 1'
test_html_2
=
'Test HTML 2'
test_html_2
=
'Test HTML 2'
def
setUp
(
self
):
def
setUp
(
self
):
super
(
BaseVertical
Module
Test
,
self
)
.
setUp
()
super
(
BaseVertical
Block
Test
,
self
)
.
setUp
()
# construct module
# construct module
course
=
xml
.
CourseFactory
.
build
()
course
=
xml
.
CourseFactory
.
build
()
sequence
=
xml
.
SequenceFactory
.
build
(
parent
=
course
)
sequence
=
xml
.
SequenceFactory
.
build
(
parent
=
course
)
...
@@ -35,7 +38,10 @@ class BaseVerticalModuleTest(XModuleXmlImportTest):
...
@@ -35,7 +38,10 @@ class BaseVerticalModuleTest(XModuleXmlImportTest):
self
.
vertical
.
xmodule_runtime
=
self
.
module_system
self
.
vertical
.
xmodule_runtime
=
self
.
module_system
class
VerticalModuleTestCase
(
BaseVerticalModuleTest
):
class
VerticalBlockTestCase
(
BaseVerticalBlockTest
):
"""
Tests for the VerticalBlock.
"""
def
test_render_student_view
(
self
):
def
test_render_student_view
(
self
):
"""
"""
Test the rendering of the student view.
Test the rendering of the student view.
...
...
common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py
View file @
a0bae0c7
...
@@ -23,6 +23,7 @@ from unittest.case import SkipTest, TestCase
...
@@ -23,6 +23,7 @@ from unittest.case import SkipTest, TestCase
from
xblock.field_data
import
DictFieldData
from
xblock.field_data
import
DictFieldData
from
xblock.fields
import
ScopeIds
from
xblock.fields
import
ScopeIds
from
xblock.core
import
XBlock
from
opaque_keys.edx.locations
import
Location
from
opaque_keys.edx.locations
import
Location
...
@@ -42,8 +43,8 @@ from xmodule.crowdsource_hinter import CrowdsourceHinterDescriptor
...
@@ -42,8 +43,8 @@ from xmodule.crowdsource_hinter import CrowdsourceHinterDescriptor
from
xmodule.seq_module
import
SequenceDescriptor
from
xmodule.seq_module
import
SequenceDescriptor
from
xmodule.conditional_module
import
ConditionalDescriptor
from
xmodule.conditional_module
import
ConditionalDescriptor
from
xmodule.randomize_module
import
RandomizeDescriptor
from
xmodule.randomize_module
import
RandomizeDescriptor
from
xmodule.vertical_
module
import
VerticalDescriptor
from
xmodule.vertical_
block
import
VerticalBlock
from
xmodule.wrapper_module
import
Wrapper
Descriptor
from
xmodule.wrapper_module
import
Wrapper
Block
from
xmodule.tests
import
get_test_descriptor_system
,
get_test_system
from
xmodule.tests
import
get_test_descriptor_system
,
get_test_system
...
@@ -74,8 +75,8 @@ CONTAINER_XMODULES = {
...
@@ -74,8 +75,8 @@ CONTAINER_XMODULES = {
CrowdsourceHinterDescriptor
:
[{}],
CrowdsourceHinterDescriptor
:
[{}],
RandomizeDescriptor
:
[{}],
RandomizeDescriptor
:
[{}],
SequenceDescriptor
:
[{}],
SequenceDescriptor
:
[{}],
Vertical
Descriptor
:
[{}],
Vertical
Block
:
[{}],
Wrapper
Descriptor
:
[{}],
Wrapper
Block
:
[{}],
}
}
# These modules are editable in studio yet
# These modules are editable in studio yet
...
@@ -141,7 +142,10 @@ class ContainerModuleRuntimeFactory(ModuleSystemFactory):
...
@@ -141,7 +142,10 @@ class ContainerModuleRuntimeFactory(ModuleSystemFactory):
if
depth
==
0
:
if
depth
==
0
:
self
.
get_module
.
side_effect
=
lambda
x
:
LeafModuleFactory
(
descriptor_cls
=
HtmlDescriptor
)
self
.
get_module
.
side_effect
=
lambda
x
:
LeafModuleFactory
(
descriptor_cls
=
HtmlDescriptor
)
else
:
else
:
self
.
get_module
.
side_effect
=
lambda
x
:
ContainerModuleFactory
(
descriptor_cls
=
VerticalDescriptor
,
depth
=
depth
-
1
)
self
.
get_module
.
side_effect
=
lambda
x
:
ContainerModuleFactory
(
descriptor_cls
=
VerticalBlock
,
depth
=
depth
-
1
)
@post_generation
@post_generation
def
position
(
self
,
create
,
position
=
2
,
**
kwargs
):
# pylint: disable=unused-argument, method-hidden
def
position
(
self
,
create
,
position
=
2
,
**
kwargs
):
# pylint: disable=unused-argument, method-hidden
...
@@ -166,7 +170,10 @@ class ContainerDescriptorRuntimeFactory(DescriptorSystemFactory):
...
@@ -166,7 +170,10 @@ class ContainerDescriptorRuntimeFactory(DescriptorSystemFactory):
if
depth
==
0
:
if
depth
==
0
:
self
.
load_item
.
side_effect
=
lambda
x
:
LeafModuleFactory
(
descriptor_cls
=
HtmlDescriptor
)
self
.
load_item
.
side_effect
=
lambda
x
:
LeafModuleFactory
(
descriptor_cls
=
HtmlDescriptor
)
else
:
else
:
self
.
load_item
.
side_effect
=
lambda
x
:
ContainerModuleFactory
(
descriptor_cls
=
VerticalDescriptor
,
depth
=
depth
-
1
)
self
.
load_item
.
side_effect
=
lambda
x
:
ContainerModuleFactory
(
descriptor_cls
=
VerticalBlock
,
depth
=
depth
-
1
)
@post_generation
@post_generation
def
position
(
self
,
create
,
position
=
2
,
**
kwargs
):
# pylint: disable=unused-argument, method-hidden
def
position
(
self
,
create
,
position
=
2
,
**
kwargs
):
# pylint: disable=unused-argument, method-hidden
...
@@ -323,7 +330,12 @@ class TestStudentView(XBlockWrapperTestMixin, TestCase):
...
@@ -323,7 +330,12 @@ class TestStudentView(XBlockWrapperTestMixin, TestCase):
This tests that student_view and XModule.get_html produce the same results.
This tests that student_view and XModule.get_html produce the same results.
"""
"""
def
skip_if_invalid
(
self
,
descriptor_cls
):
def
skip_if_invalid
(
self
,
descriptor_cls
):
if
descriptor_cls
.
module_class
.
student_view
!=
XModule
.
student_view
:
pure_xblock_class
=
issubclass
(
descriptor_cls
,
XBlock
)
and
not
issubclass
(
descriptor_cls
,
XModuleDescriptor
)
if
pure_xblock_class
:
student_view
=
descriptor_cls
.
student_view
else
:
student_view
=
descriptor_cls
.
module_class
.
student_view
if
student_view
!=
XModule
.
student_view
:
raise
SkipTest
(
descriptor_cls
.
__name__
+
" implements student_view"
)
raise
SkipTest
(
descriptor_cls
.
__name__
+
" implements student_view"
)
def
check_property
(
self
,
descriptor
):
def
check_property
(
self
,
descriptor
):
...
@@ -344,7 +356,10 @@ class TestStudioView(XBlockWrapperTestMixin, TestCase):
...
@@ -344,7 +356,10 @@ class TestStudioView(XBlockWrapperTestMixin, TestCase):
if
descriptor_cls
in
NOT_STUDIO_EDITABLE
:
if
descriptor_cls
in
NOT_STUDIO_EDITABLE
:
raise
SkipTest
(
descriptor_cls
.
__name__
+
" is not editable in studio"
)
raise
SkipTest
(
descriptor_cls
.
__name__
+
" is not editable in studio"
)
if
descriptor_cls
.
studio_view
!=
XModuleDescriptor
.
studio_view
:
pure_xblock_class
=
issubclass
(
descriptor_cls
,
XBlock
)
and
not
issubclass
(
descriptor_cls
,
XModuleDescriptor
)
if
pure_xblock_class
:
raise
SkipTest
(
descriptor_cls
.
__name__
+
" is a pure XBlock and implements studio_view"
)
elif
descriptor_cls
.
studio_view
!=
XModuleDescriptor
.
studio_view
:
raise
SkipTest
(
descriptor_cls
.
__name__
+
" implements studio_view"
)
raise
SkipTest
(
descriptor_cls
.
__name__
+
" implements studio_view"
)
def
check_property
(
self
,
descriptor
):
def
check_property
(
self
,
descriptor
):
...
...
common/lib/xmodule/xmodule/vertical_
module
.py
→
common/lib/xmodule/xmodule/vertical_
block
.py
View file @
a0bae0c7
"""
VerticalBlock - an XBlock which renders its children in a column.
"""
import
logging
from
copy
import
copy
from
lxml
import
etree
from
xblock.core
import
XBlock
from
xblock.fragment
import
Fragment
from
xblock.fragment
import
Fragment
from
xmodule.x_module
import
XModule
,
STUDENT_VIEW
from
xmodule.mako_module
import
MakoTemplateBlockBase
from
xmodule.seq_module
import
SequenceDescriptor
from
xmodule.progress
import
Progress
from
xmodule.progress
import
Progress
from
xmodule.studio_editable
import
StudioEditableModule
,
StudioEditableDescriptor
from
xmodule.seq_module
import
SequenceFields
from
pkg_resources
import
resource_string
from
xmodule.studio_editable
import
StudioEditableBlock
from
copy
import
copy
from
xmodule.x_module
import
STUDENT_VIEW
,
XModuleFields
from
xmodule.xml_module
import
XmlParserMixin
log
=
logging
.
getLogger
(
__name__
)
# HACK: This shouldn't be hard-coded to two types
# HACK: This shouldn't be hard-coded to two types
# OBSOLETE: This obsoletes 'type'
# OBSOLETE: This obsoletes 'type'
class_priority
=
[
'video'
,
'problem'
]
CLASS_PRIORITY
=
[
'video'
,
'problem'
]
class
VerticalFields
(
object
):
has_children
=
True
class
VerticalBlock
(
SequenceFields
,
XModuleFields
,
StudioEditableBlock
,
XmlParserMixin
,
MakoTemplateBlockBase
,
XBlock
):
"""
Layout XBlock for rendering subblocks vertically.
"""
mako_template
=
'widgets/sequence-edit.html'
js_module_name
=
"VerticalBlock"
class
VerticalModule
(
VerticalFields
,
XModule
,
StudioEditableModule
):
has_children
=
True
''' Layout module for laying out submodules vertically.'''
def
student_view
(
self
,
context
):
def
student_view
(
self
,
context
):
"""
Renders the student view of the block in the LMS.
"""
fragment
=
Fragment
()
fragment
=
Fragment
()
contents
=
[]
contents
=
[]
child_context
=
{}
if
not
context
else
copy
(
context
)
child_context
=
{}
if
not
context
else
copy
(
context
)
child_context
[
'child_of_vertical'
]
=
True
child_context
[
'child_of_vertical'
]
=
True
# pylint: disable=no-member
for
child
in
self
.
get_display_items
():
for
child
in
self
.
get_display_items
():
rendered_child
=
child
.
render
(
STUDENT_VIEW
,
child_context
)
rendered_child
=
child
.
render
(
STUDENT_VIEW
,
child_context
)
fragment
.
add_frag_resources
(
rendered_child
)
fragment
.
add_frag_resources
(
rendered_child
)
...
@@ -47,7 +61,7 @@ class VerticalModule(VerticalFields, XModule, StudioEditableModule):
...
@@ -47,7 +61,7 @@ class VerticalModule(VerticalFields, XModule, StudioEditableModule):
"""
"""
fragment
=
Fragment
()
fragment
=
Fragment
()
root_xblock
=
context
.
get
(
'root_xblock'
)
root_xblock
=
context
.
get
(
'root_xblock'
)
is_root
=
root_xblock
and
root_xblock
.
location
==
self
.
location
is_root
=
root_xblock
and
root_xblock
.
location
==
self
.
location
# pylint: disable=no-member
# For the container page we want the full drag-and-drop, but for unit pages we want
# For the container page we want the full drag-and-drop, but for unit pages we want
# a more concise version that appears alongside the "View =>" link-- unless it is
# a more concise version that appears alongside the "View =>" link-- unless it is
...
@@ -57,37 +71,60 @@ class VerticalModule(VerticalFields, XModule, StudioEditableModule):
...
@@ -57,37 +71,60 @@ class VerticalModule(VerticalFields, XModule, StudioEditableModule):
return
fragment
return
fragment
def
get_progress
(
self
):
def
get_progress
(
self
):
"""
Returns the progress on this block and all children.
"""
# TODO: Cache progress or children array?
# TODO: Cache progress or children array?
children
=
self
.
get_children
()
children
=
self
.
get_children
()
# pylint: disable=no-member
progresses
=
[
child
.
get_progress
()
for
child
in
children
]
progresses
=
[
child
.
get_progress
()
for
child
in
children
]
progress
=
reduce
(
Progress
.
add_counts
,
progresses
,
None
)
progress
=
reduce
(
Progress
.
add_counts
,
progresses
,
None
)
return
progress
return
progress
def
get_icon_class
(
self
):
def
get_icon_class
(
self
):
child_classes
=
set
(
child
.
get_icon_class
()
for
child
in
self
.
get_children
())
"""
Returns the highest priority icon class.
"""
child_classes
=
set
(
child
.
get_icon_class
()
for
child
in
self
.
get_children
())
# pylint: disable=no-member
new_class
=
'other'
new_class
=
'other'
for
c
in
class_priority
:
for
higher_class
in
CLASS_PRIORITY
:
if
c
in
child_classes
:
if
higher_class
in
child_classes
:
new_class
=
c
new_class
=
higher_class
return
new_class
return
new_class
@classmethod
class
VerticalDescriptor
(
VerticalFields
,
SequenceDescriptor
,
StudioEditableDescriptor
):
def
definition_from_xml
(
cls
,
xml_object
,
system
):
"""
children
=
[]
Descriptor class for editing verticals.
for
child
in
xml_object
:
"""
try
:
module_class
=
VerticalModule
child_block
=
system
.
process_xml
(
etree
.
tostring
(
child
,
encoding
=
'unicode'
))
# pylint: disable=no-member
children
.
append
(
child_block
.
scope_ids
.
usage_id
)
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/vertical/edit.coffee'
)]}
except
Exception
as
exc
:
# pylint: disable=broad-except
js_module_name
=
"VerticalDescriptor"
log
.
exception
(
"Unable to load child when parsing Vertical. Continuing..."
)
if
system
.
error_tracker
is
not
None
:
# TODO (victor): Does this need its own definition_to_xml method? Otherwise it looks
system
.
error_tracker
(
u"ERROR: {0}"
.
format
(
exc
))
# like verticals will get exported as sequentials...
continue
return
{},
children
def
definition_to_xml
(
self
,
resource_fs
):
xml_object
=
etree
.
Element
(
'vertical'
)
# pylint: disable=no-member
for
child
in
self
.
get_children
():
# pylint: disable=no-member
self
.
runtime
.
add_block_as_child_node
(
child
,
xml_object
)
return
xml_object
@property
@property
def
non_editable_metadata_fields
(
self
):
def
non_editable_metadata_fields
(
self
):
non_editable_fields
=
super
(
VerticalDescriptor
,
self
)
.
non_editable_metadata_fields
"""
Gather all fields which can't be edited.
"""
non_editable_fields
=
super
(
VerticalBlock
,
self
)
.
non_editable_metadata_fields
non_editable_fields
.
extend
([
non_editable_fields
.
extend
([
VerticalDescriptor
.
due
,
self
.
fields
[
'due'
]
,
])
])
return
non_editable_fields
return
non_editable_fields
def
studio_view
(
self
,
context
):
fragment
=
super
(
VerticalBlock
,
self
)
.
studio_view
(
context
)
# This continues to use the old XModuleDescriptor javascript code to enabled studio editing.
# TODO: Remove this when studio better supports editing of pure XBlocks.
fragment
.
add_javascript
(
'VerticalBlock = XModule.Descriptor;'
)
return
fragment
common/lib/xmodule/xmodule/wrapper_module.py
View file @
a0bae0c7
# Same as vertical,
# Same as vertical,
# But w/o css delimiters between children
# But w/o css delimiters between children
from
xmodule.vertical_
module
import
VerticalModule
,
VerticalDescriptor
from
xmodule.vertical_
block
import
VerticalBlock
from
pkg_resources
import
resource_string
from
pkg_resources
import
resource_string
# HACK: This shouldn't be hard-coded to two types
# HACK: This shouldn't be hard-coded to two types
...
@@ -9,14 +9,8 @@ from pkg_resources import resource_string
...
@@ -9,14 +9,8 @@ from pkg_resources import resource_string
class_priority
=
[
'video'
,
'problem'
]
class_priority
=
[
'video'
,
'problem'
]
class
WrapperModule
(
VerticalModule
):
class
WrapperBlock
(
VerticalBlock
):
''' Layout module for laying out submodules vertically w/o css delimiters'''
'''
Layout block for laying out sub-blocks vertically *w/o* css delimiters.
has_children
=
True
'''
css
=
{
'scss'
:
[
resource_string
(
__name__
,
'css/wrapper/display.scss'
)]}
pass
class
WrapperDescriptor
(
VerticalDescriptor
):
module_class
=
WrapperModule
has_children
=
True
lms/djangoapps/courseware/features/common.py
View file @
a0bae0c7
...
@@ -13,7 +13,7 @@ from student.models import CourseEnrollment
...
@@ -13,7 +13,7 @@ from student.models import CourseEnrollment
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
from
xmodule.course_module
import
CourseDescriptor
from
xmodule.course_module
import
CourseDescriptor
from
courseware.courses
import
get_course_by_id
from
courseware.courses
import
get_course_by_id
from
xmodule
import
seq_module
,
vertical_
module
from
xmodule
import
seq_module
,
vertical_
block
from
logging
import
getLogger
from
logging
import
getLogger
logger
=
getLogger
(
__name__
)
logger
=
getLogger
(
__name__
)
...
@@ -181,7 +181,7 @@ def get_courseware_with_tabs(course_id):
...
@@ -181,7 +181,7 @@ def get_courseware_with_tabs(course_id):
}, {
}, {
'clickable_tab_count': 1,
'clickable_tab_count': 1,
'section_name': 'System Usage Sequence',
'section_name': 'System Usage Sequence',
'tab_classes': ['Vertical
Descriptor
']
'tab_classes': ['Vertical
Block
']
}, {
}, {
'clickable_tab_count': 0,
'clickable_tab_count': 0,
'section_name': 'Lab0: Using the tools',
'section_name': 'Lab0: Using the tools',
...
@@ -196,7 +196,7 @@ def get_courseware_with_tabs(course_id):
...
@@ -196,7 +196,7 @@ def get_courseware_with_tabs(course_id):
'sections': [{
'sections': [{
'clickable_tab_count': 4,
'clickable_tab_count': 4,
'section_name': 'Administrivia and Circuit Elements',
'section_name': 'Administrivia and Circuit Elements',
'tab_classes': ['Vertical
Descriptor', 'VerticalDescriptor', 'VerticalDescriptor', 'VerticalDescriptor
']
'tab_classes': ['Vertical
Block', 'VerticalBlock', 'VerticalBlock', 'VerticalBlock
']
}, {
}, {
'clickable_tab_count': 0,
'clickable_tab_count': 0,
'section_name': 'Basic Circuit Analysis',
'section_name': 'Basic Circuit Analysis',
...
@@ -215,7 +215,7 @@ def get_courseware_with_tabs(course_id):
...
@@ -215,7 +215,7 @@ def get_courseware_with_tabs(course_id):
'sections': [{
'sections': [{
'clickable_tab_count': 2,
'clickable_tab_count': 2,
'section_name': 'Midterm Exam',
'section_name': 'Midterm Exam',
'tab_classes': ['Vertical
Descriptor', 'VerticalDescriptor
']
'tab_classes': ['Vertical
Block', 'VerticalBlock
']
}]
}]
}]
}]
"""
"""
...
@@ -228,7 +228,7 @@ def get_courseware_with_tabs(course_id):
...
@@ -228,7 +228,7 @@ def get_courseware_with_tabs(course_id):
'section_name'
:
s
.
display_name_with_default
,
'section_name'
:
s
.
display_name_with_default
,
'clickable_tab_count'
:
len
(
s
.
get_children
())
if
(
type
(
s
)
==
seq_module
.
SequenceDescriptor
)
else
0
,
'clickable_tab_count'
:
len
(
s
.
get_children
())
if
(
type
(
s
)
==
seq_module
.
SequenceDescriptor
)
else
0
,
'tabs'
:
[{
'tabs'
:
[{
'children_count'
:
len
(
t
.
get_children
())
if
(
type
(
t
)
==
vertical_
module
.
VerticalDescriptor
)
else
0
,
'children_count'
:
len
(
t
.
get_children
())
if
(
type
(
t
)
==
vertical_
block
.
VerticalBlock
)
else
0
,
'class'
:
t
.
__class__
.
__name__
}
for
t
in
s
.
get_children
()
'class'
:
t
.
__class__
.
__name__
}
for
t
in
s
.
get_children
()
]
]
}
for
s
in
c
.
get_children
()
if
not
s
.
hide_from_toc
]
}
for
s
in
c
.
get_children
()
if
not
s
.
hide_from_toc
]
...
...
lms/djangoapps/courseware/tests/test_module_render.py
View file @
a0bae0c7
...
@@ -800,8 +800,8 @@ class MongoViewInStudioTest(ViewInStudioTest):
...
@@ -800,8 +800,8 @@ class MongoViewInStudioTest(ViewInStudioTest):
# Render the parent vertical, then check that there is only a single "View Unit in Studio" link.
# Render the parent vertical, then check that there is only a single "View Unit in Studio" link.
result_fragment
=
self
.
module
.
render
(
STUDENT_VIEW
)
result_fragment
=
self
.
module
.
render
(
STUDENT_VIEW
)
# The single "View Unit in Studio" link should appear before the first xmodule vertical definition.
# The single "View Unit in Studio" link should appear before the first xmodule vertical definition.
parts
=
result_fragment
.
content
.
split
(
'
xmodule_VerticalModule
'
)
parts
=
result_fragment
.
content
.
split
(
'
data-block-type="vertical"
'
)
self
.
assertEqual
(
3
,
len
(
parts
),
"Did not find two vertical
module
s"
)
self
.
assertEqual
(
3
,
len
(
parts
),
"Did not find two vertical
block
s"
)
self
.
assertIn
(
'View Unit in Studio'
,
parts
[
0
])
self
.
assertIn
(
'View Unit in Studio'
,
parts
[
0
])
self
.
assertNotIn
(
'View Unit in Studio'
,
parts
[
1
])
self
.
assertNotIn
(
'View Unit in Studio'
,
parts
[
1
])
self
.
assertNotIn
(
'View Unit in Studio'
,
parts
[
2
])
self
.
assertNotIn
(
'View Unit in Studio'
,
parts
[
2
])
...
...
lms/static/sass/course/courseware/_courseware.scss
View file @
a0bae0c7
...
@@ -162,7 +162,7 @@ div.course-wrapper {
...
@@ -162,7 +162,7 @@ div.course-wrapper {
}
}
}
}
section
.x
module_WrapperModule
div
.vert-mod
>
div
{
section
.x
block-student_view-wrapper
div
.vert-mod
>
div
{
border-bottom
:
none
;
border-bottom
:
none
;
}
}
...
...
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