Commit 46ed857c by Calen Pennington

Merge pull request #1221 from cpennington/lms-xblock-css-js

Put XBlock css and javascript onto the LMS courseware page
parents 5359e2eb 2514dca5
...@@ -7,6 +7,7 @@ from xmodule.seq_module import SequenceDescriptor ...@@ -7,6 +7,7 @@ from xmodule.seq_module import SequenceDescriptor
from lxml import etree from lxml import etree
from xblock.fields import Scope, Integer from xblock.fields import Scope, Integer
from xblock.fragment import Fragment
log = logging.getLogger('mitx.' + __name__) log = logging.getLogger('mitx.' + __name__)
...@@ -77,12 +78,12 @@ class RandomizeModule(RandomizeFields, XModule): ...@@ -77,12 +78,12 @@ class RandomizeModule(RandomizeFields, XModule):
return [self.child_descriptor] return [self.child_descriptor]
def get_html(self): def student_view(self, context):
if self.child is None: if self.child is None:
# raise error instead? In fact, could complain on descriptor load... # raise error instead? In fact, could complain on descriptor load...
return u"<div>Nothing to randomize between</div>" return Fragment(content=u"<div>Nothing to randomize between</div>")
return self.child.render('student_view').content return self.child.render('student_view', context)
def get_icon_class(self): def get_icon_class(self):
return self.child.get_icon_class() if self.child else 'other' return self.child.get_icon_class() if self.child else 'other'
......
...@@ -9,6 +9,7 @@ from xmodule.x_module import XModule ...@@ -9,6 +9,7 @@ from xmodule.x_module import XModule
from xmodule.progress import Progress from xmodule.progress import Progress
from xmodule.exceptions import NotFoundError from xmodule.exceptions import NotFoundError
from xblock.fields import Integer, Scope from xblock.fields import Integer, Scope
from xblock.fragment import Fragment
from pkg_resources import resource_string from pkg_resources import resource_string
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -43,12 +44,6 @@ class SequenceModule(SequenceFields, XModule): ...@@ -43,12 +44,6 @@ class SequenceModule(SequenceFields, XModule):
if getattr(self.system, 'position', None) is not None: if getattr(self.system, 'position', None) is not None:
self.position = int(self.system.position) self.position = int(self.system.position)
self.rendered = False
def get_html(self):
self.render()
return self.content
def get_progress(self): def get_progress(self):
''' Return the total progress, adding total done and total available. ''' Return the total progress, adding total done and total available.
(assumes that each submodule uses the same "units" for progress.) (assumes that each submodule uses the same "units" for progress.)
...@@ -66,20 +61,24 @@ class SequenceModule(SequenceFields, XModule): ...@@ -66,20 +61,24 @@ class SequenceModule(SequenceFields, XModule):
return json.dumps({'success': True}) return json.dumps({'success': True})
raise NotFoundError('Unexpected dispatch type') raise NotFoundError('Unexpected dispatch type')
def render(self): def student_view(self, context):
# If we're rendering this sequence, but no position is set yet, # If we're rendering this sequence, but no position is set yet,
# default the position to the first element # default the position to the first element
if self.position is None: if self.position is None:
self.position = 1 self.position = 1
if self.rendered:
return
## Returns a set of all types of all sub-children ## Returns a set of all types of all sub-children
contents = [] contents = []
fragment = Fragment()
for child in self.get_display_items(): for child in self.get_display_items():
progress = child.get_progress() progress = child.get_progress()
rendered_child = child.render('student_view', context)
fragment.add_frag_resources(rendered_child)
childinfo = { childinfo = {
'content': child.render('student_view').content, 'content': rendered_child.content,
'title': "\n".join( 'title': "\n".join(
grand_child.display_name grand_child.display_name
for grand_child in child.get_children() for grand_child in child.get_children()
...@@ -98,11 +97,12 @@ class SequenceModule(SequenceFields, XModule): ...@@ -98,11 +97,12 @@ class SequenceModule(SequenceFields, XModule):
'element_id': self.location.html_id(), 'element_id': self.location.html_id(),
'item_id': self.id, 'item_id': self.id,
'position': self.position, 'position': self.position,
'tag': self.location.category 'tag': self.location.category,
} }
self.content = self.system.render_template('seq_module.html', params) fragment.add_content(self.system.render_template('seq_module.html', params))
self.rendered = True
return fragment
def get_icon_class(self): def get_icon_class(self):
child_classes = set(child.get_icon_class() child_classes = set(child.get_icon_class()
......
...@@ -12,7 +12,7 @@ from mock import Mock ...@@ -12,7 +12,7 @@ from mock import Mock
from xblock.field_data import DictFieldData from xblock.field_data import DictFieldData
from xblock.fields import ScopeIds from xblock.fields import ScopeIds
from xmodule.x_module import ModuleSystem from xmodule.x_module import ModuleSystem, XModule, XModuleDescriptor
from xmodule.mako_module import MakoDescriptorSystem from xmodule.mako_module import MakoDescriptorSystem
from xmodule.annotatable_module import AnnotatableDescriptor from xmodule.annotatable_module import AnnotatableDescriptor
from xmodule.capa_module import CapaDescriptor from xmodule.capa_module import CapaDescriptor
...@@ -143,6 +143,10 @@ class TestStudentView(TestXBlockWrapper): ...@@ -143,6 +143,10 @@ class TestStudentView(TestXBlockWrapper):
# Check that when an xmodule is instantiated from descriptor_cls # Check that when an xmodule is instantiated from descriptor_cls
# it generates the same thing from student_view that it does from get_html # it generates the same thing from student_view that it does from get_html
def check_student_view_leaf_node(self, descriptor_cls): def check_student_view_leaf_node(self, descriptor_cls):
if descriptor_cls.module_class.student_view != XModule.student_view:
raise SkipTest(descriptor_cls.__name__ + " implements student_view")
descriptor = self.leaf_module(descriptor_cls) descriptor = self.leaf_module(descriptor_cls)
assert_equal( assert_equal(
descriptor._xmodule.get_html(), descriptor._xmodule.get_html(),
...@@ -165,6 +169,10 @@ class TestStudentView(TestXBlockWrapper): ...@@ -165,6 +169,10 @@ class TestStudentView(TestXBlockWrapper):
# with only xmodule children, it generates the same html from student_view # with only xmodule children, it generates the same html from student_view
# as it does using get_html # as it does using get_html
def check_student_view_container_node_xmodules_only(self, descriptor_cls): def check_student_view_container_node_xmodules_only(self, descriptor_cls):
if descriptor_cls.module_class.student_view != XModule.student_view:
raise SkipTest(descriptor_cls.__name__ + " implements student_view")
descriptor = self.container_module(descriptor_cls, 2) descriptor = self.container_module(descriptor_cls, 2)
assert_equal( assert_equal(
descriptor._xmodule.get_html(), descriptor._xmodule.get_html(),
...@@ -197,7 +205,10 @@ class TestStudioView(TestXBlockWrapper): ...@@ -197,7 +205,10 @@ class TestStudioView(TestXBlockWrapper):
# it generates the same thing from studio_view that it does from get_html # it generates the same thing from studio_view that it does from get_html
def check_studio_view_leaf_node(self, descriptor_cls): def check_studio_view_leaf_node(self, descriptor_cls):
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:
raise SkipTest(descriptor_cls.__name__ + " implements studio_view")
descriptor = self.leaf_descriptor(descriptor_cls) descriptor = self.leaf_descriptor(descriptor_cls)
assert_equal(descriptor.get_html(), descriptor.render('studio_view').content) assert_equal(descriptor.get_html(), descriptor.render('studio_view').content)
...@@ -222,6 +233,9 @@ class TestStudioView(TestXBlockWrapper): ...@@ -222,6 +233,9 @@ class TestStudioView(TestXBlockWrapper):
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:
raise SkipTest(descriptor_cls.__name__ + " implements studio_view")
descriptor = self.container_descriptor(descriptor_cls, 2) descriptor = self.container_descriptor(descriptor_cls, 2)
assert_equal(descriptor.get_html(), descriptor.render('studio_view').content) assert_equal(descriptor.get_html(), descriptor.render('studio_view').content)
......
...@@ -9,6 +9,7 @@ from xmodule.x_module import XModule ...@@ -9,6 +9,7 @@ from xmodule.x_module import XModule
from xmodule.progress import Progress from xmodule.progress import Progress
from xmodule.exceptions import NotFoundError from xmodule.exceptions import NotFoundError
from xblock.fields import Float, String, Boolean, Scope from xblock.fields import Float, String, Boolean, Scope
from xblock.fragment import Fragment
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -84,14 +85,14 @@ class TimeLimitModule(TimeLimitFields, XModule): ...@@ -84,14 +85,14 @@ class TimeLimitModule(TimeLimitFields, XModule):
def get_remaining_time_in_ms(self): def get_remaining_time_in_ms(self):
return int((self.ending_at - time()) * 1000) return int((self.ending_at - time()) * 1000)
def get_html(self): def student_view(self, context):
# assumes there is one and only one child, so it only renders the first child # assumes there is one and only one child, so it only renders the first child
children = self.get_display_items() children = self.get_display_items()
if children: if children:
child = children[0] child = children[0]
return child.render('student_view').content return child.render('student_view', context)
else: else:
return u"" return Fragment()
def get_progress(self): def get_progress(self):
''' Return the total progress, adding total done and total available. ''' Return the total progress, adding total done and total available.
......
from xblock.fragment import Fragment
from xmodule.x_module import XModule from xmodule.x_module import XModule
from xmodule.seq_module import SequenceDescriptor from xmodule.seq_module import SequenceDescriptor
from xmodule.progress import Progress from xmodule.progress import Progress
...@@ -17,18 +18,24 @@ class VerticalModule(VerticalFields, XModule): ...@@ -17,18 +18,24 @@ class VerticalModule(VerticalFields, XModule):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
XModule.__init__(self, *args, **kwargs) XModule.__init__(self, *args, **kwargs)
self.contents = None
def get_html(self): def student_view(self, context):
if self.contents is None: fragment = Fragment()
self.contents = [{ contents = []
for child in self.get_display_items():
rendered_child = child.render('student_view', context)
fragment.add_frag_resources(rendered_child)
contents.append({
'id': child.id, 'id': child.id,
'content': child.render('student_view').content 'content': rendered_child.content
} for child in self.get_display_items()] })
return self.system.render_template('vert_module.html', { fragment.add_content(self.system.render_template('vert_module.html', {
'items': self.contents 'items': contents
}) }))
return fragment
def get_progress(self): def get_progress(self):
# TODO: Cache progress or children array? # TODO: Cache progress or children array?
......
...@@ -31,6 +31,7 @@ from django_comment_client.utils import get_discussion_title ...@@ -31,6 +31,7 @@ from django_comment_client.utils import get_discussion_title
from student.models import UserTestGroup, CourseEnrollment from student.models import UserTestGroup, CourseEnrollment
from util.cache import cache, cache_if_anonymous from util.cache import cache, cache_if_anonymous
from xblock.fragment import Fragment
from xmodule.modulestore import Location from xmodule.modulestore import Location
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import InvalidLocationError, ItemNotFoundError, NoPathToItem from xmodule.modulestore.exceptions import InvalidLocationError, ItemNotFoundError, NoPathToItem
...@@ -327,7 +328,7 @@ def index(request, course_id, chapter=None, section=None, ...@@ -327,7 +328,7 @@ def index(request, course_id, chapter=None, section=None,
'COURSE_TITLE': course.display_name_with_default, 'COURSE_TITLE': course.display_name_with_default,
'course': course, 'course': course,
'init': '', 'init': '',
'content': '', 'fragment': Fragment(),
'staff_access': staff_access, 'staff_access': staff_access,
'masquerade': masq, 'masquerade': masq,
'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER', 'http://xqa:server@content-qa.mitx.mit.edu/xqa') 'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER', 'http://xqa:server@content-qa.mitx.mit.edu/xqa')
...@@ -395,7 +396,7 @@ def index(request, course_id, chapter=None, section=None, ...@@ -395,7 +396,7 @@ def index(request, course_id, chapter=None, section=None,
# check here if this section *is* a timed module. # check here if this section *is* a timed module.
if section_module.category == 'timelimit': if section_module.category == 'timelimit':
timer_context = update_timelimit_module(user, course_id, student_module_cache, timer_context = update_timelimit_module(user, course_id, section_field_data_cache,
section_descriptor, section_module) section_descriptor, section_module)
if 'timer_expiration_duration' in timer_context: if 'timer_expiration_duration' in timer_context:
context.update(timer_context) context.update(timer_context)
...@@ -407,7 +408,7 @@ def index(request, course_id, chapter=None, section=None, ...@@ -407,7 +408,7 @@ def index(request, course_id, chapter=None, section=None,
# add in the appropriate timer information to the rendering context: # add in the appropriate timer information to the rendering context:
context.update(check_for_active_timelimit_module(request, course_id, course)) context.update(check_for_active_timelimit_module(request, course_id, course))
context['content'] = section_module.render('student_view').content context['fragment'] = section_module.render('student_view')
else: else:
# section is none, so display a message # section is none, so display a message
prev_section = get_current_child(chapter_module) prev_section = get_current_child(chapter_module)
...@@ -417,11 +418,15 @@ def index(request, course_id, chapter=None, section=None, ...@@ -417,11 +418,15 @@ def index(request, course_id, chapter=None, section=None,
prev_section_url = reverse('courseware_section', kwargs={'course_id': course_id, prev_section_url = reverse('courseware_section', kwargs={'course_id': course_id,
'chapter': chapter_descriptor.url_name, 'chapter': chapter_descriptor.url_name,
'section': prev_section.url_name}) 'section': prev_section.url_name})
context['content'] = render_to_string('courseware/welcome-back.html', context['fragment'] = Fragment(content=render_to_string(
{'course': course, 'courseware/welcome-back.html',
'chapter_module': chapter_module, {
'prev_section': prev_section, 'course': course,
'prev_section_url': prev_section_url}) 'chapter_module': chapter_module,
'prev_section': prev_section,
'prev_section_url': prev_section_url
}
))
result = render_to_response('courseware/courseware.html', context) result = render_to_response('courseware/courseware.html', context)
except Exception as e: except Exception as e:
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
## all needs to stay together for the Candy.js plugin to work. ## all needs to stay together for the Candy.js plugin to work.
<link rel="stylesheet" href="${static.url('candy_res/candy_full.css')}" /> <link rel="stylesheet" href="${static.url('candy_res/candy_full.css')}" />
% endif % endif
${fragment.head_html()}
</%block> </%block>
<%block name="js_extra"> <%block name="js_extra">
...@@ -150,6 +151,8 @@ ...@@ -150,6 +151,8 @@
</script> </script>
% endif % endif
${fragment.foot_html()}
</%block> </%block>
% if timer_expiration_duration: % if timer_expiration_duration:
...@@ -185,7 +188,7 @@ ...@@ -185,7 +188,7 @@
% endif % endif
<section class="course-content"> <section class="course-content">
${content} ${fragment.body_html()}
</section> </section>
</div> </div>
</section> </section>
......
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