diff --git a/common/lib/xmodule/xmodule/conditional_module.py b/common/lib/xmodule/xmodule/conditional_module.py index c022c3742a..c7f4ee51eb 100644 --- a/common/lib/xmodule/xmodule/conditional_module.py +++ b/common/lib/xmodule/xmodule/conditional_module.py @@ -1,9 +1,12 @@ +import json import logging from xmodule.x_module import XModule from xmodule.modulestore import Location from xmodule.seq_module import SequenceDescriptor +from pkg_resources import resource_string + log = logging.getLogger('mitx.' + __name__) class ConditionalModule(XModule): @@ -18,26 +21,31 @@ class ConditionalModule(XModule): ''' + js = {'coffee': [resource_string(__name__, 'js/src/capa/display.coffee'), + resource_string(__name__, 'js/src/collapsible.coffee'), + resource_string(__name__, 'js/src/javascript_loader.coffee'), + ]} + + js_module_name = "Problem" + css = {'scss': [resource_string(__name__, 'css/capa/display.scss')]} + + def __init__(self, system, location, definition, descriptor, instance_state=None, shared_state=None, **kwargs): """ In addition to the normal XModule init, provide: - self.required_module_list = list of (tag, url_name) tuples of modules required by this one. self.condition = string describing condition required """ XModule.__init__(self, system, location, definition, descriptor, instance_state, shared_state, **kwargs) self.contents = None - self.required_modules_list = [tuple(x.split('/',1)) for x in self.metadata.get('required','').split('&')] + #self.required_modules_list = [tuple(x.split('/',1)) for x in self.metadata.get('required','').split('&')] self.condition = self.metadata.get('condition','') - log.debug('conditional module required=%s' % self.required_modules_list) + #log.debug('conditional module required=%s' % self.required_modules_list) def _get_required_modules(self): self.required_modules = [] - for (tag, name) in self.required_modules_list: - loc = self.location.dict() - loc['category'] = tag - loc['name'] = name + for loc in self.descriptor.required_module_locations: module = self.system.get_module(loc) self.required_modules.append(module) log.debug('required_modules=%s' % (self.required_modules)) @@ -49,6 +57,8 @@ class ConditionalModule(XModule): # all required modules must be completed, as determined by # the modules .is_completed() method for module in self.required_modules: + log.debug('in is_condition_satisfied; student_answers=%s' % module.lcp.student_answers) + log.debug('in is_condition_satisfied; instance_state=%s' % module.instance_state) if not hasattr(module, 'is_completed'): raise Exception('Error in conditional module: required module %s has no .is_completed() method' % module) if not module.is_completed(): @@ -63,10 +73,25 @@ class ConditionalModule(XModule): return True def get_html(self): + self.is_condition_satisfied() + return self.system.render_template('problem_ajax.html', { + 'element_id': self.location.html_id(), + 'id': self.id, + 'ajax_url': self.system.ajax_url, + }) + + def handle_ajax(self, dispatch, post): + ''' + This is called by courseware.module_render, to handle an AJAX call. + ''' + log.debug('conditional_module handle_ajax: dispatch=%s' % dispatch) + if not self.is_condition_satisfied(): - context = {'module': self, - } - return self.system.render_template('conditional_module.html', context) + context = {'module': self} + html = self.system.render_template('conditional_module.html', context) + # html = render_to_string('conditional_module.html', context) + return json.dumps({'html': html}) + #return self.system.render_template('conditional_module.html', context) if self.contents is None: self.contents = [child.get_html() for child in self.get_display_items()] @@ -76,7 +101,8 @@ class ConditionalModule(XModule): log.debug('rendered conditional module %s' % str(self.location)) - return html + return json.dumps({'html': html}) + #return html class ConditionalDescriptor(SequenceDescriptor): module_class = ConditionalModule @@ -85,4 +111,21 @@ class ConditionalDescriptor(SequenceDescriptor): stores_state = True has_score = False + + def __init__(self, *args, **kwargs): + super(ConditionalDescriptor, self).__init__(*args, **kwargs) + + required_module_list = [tuple(x.split('/',1)) for x in self.metadata.get('required','').split('&')] + self.required_module_locations = [] + for (tag, name) in required_module_list: + loc = self.location.dict() + loc['category'] = tag + loc['name'] = name + self.required_module_locations.append(Location(loc)) + log.debug('ConditionalDescriptor required_module_locations=%s' % self.required_module_locations) + + def get_required_module_descriptors(self): + """Returns a list of XModuleDescritpor instances upon which this module depends, but are + not children of this module""" + return [self.system.load_item(loc) for loc in self.required_module_locations] \ No newline at end of file diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index 5387a9b083..0e4e8e0f00 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -585,6 +585,11 @@ class XModuleDescriptor(Plugin, HTMLSnippet, ResourceTemplates): self._inherited_metadata.add(attr) self.metadata[attr] = metadata[attr] + def get_required_module_descriptors(self): + """Returns a list of XModuleDescritpor instances upon which this module depends, but are + not children of this module""" + return [] + def get_children(self): """Returns a list of XModuleDescriptor instances for the children of this module""" diff --git a/lms/djangoapps/courseware/models.py b/lms/djangoapps/courseware/models.py index 21ef8b3d66..bd01318f63 100644 --- a/lms/djangoapps/courseware/models.py +++ b/lms/djangoapps/courseware/models.py @@ -113,6 +113,9 @@ class StudentModuleCache(object): descriptor_filter=lambda descriptor: True, select_for_update=False): """ + obtain and return cache for descriptor descendents (ie children) AND modules required by the descriptor, + but which are not children of the module + course_id: the course in the context of which we want StudentModules. user: the django user for whom to load modules. descriptor: An XModuleDescriptor @@ -132,7 +135,7 @@ class StudentModuleCache(object): if depth is None or depth > 0: new_depth = depth - 1 if depth is not None else depth - for child in descriptor.get_children(): + for child in descriptor.get_children() + descriptor.get_required_module_descriptors(): descriptors.extend(get_child_descriptors(child, new_depth, descriptor_filter)) return descriptors