Commit cbc02078 by Piotr Mitros

Semi-generic registration mechanism for modules. Still need to clean up…

Semi-generic registration mechanism for modules. Still need to clean up references in content_parser

--HG--
branch : pmitros-mod-template
parent 39011ce0
...@@ -26,28 +26,10 @@ import track.views ...@@ -26,28 +26,10 @@ import track.views
import courseware.content_parser as content_parser import courseware.content_parser as content_parser
import courseware.modules.capa_module import courseware.modules
import courseware.modules.html_module
import courseware.modules.schematic_module
import courseware.modules.seq_module
import courseware.modules.template_module
import courseware.modules.vertical_module
import courseware.modules.video_module
log = logging.getLogger("mitx.courseware") log = logging.getLogger("mitx.courseware")
## TODO: Add registration mechanism
modx_modules={'problem':courseware.modules.capa_module.LoncapaModule,
'video':courseware.modules.video_module.VideoModule,
'html':courseware.modules.html_module.HtmlModule,
'vertical':courseware.modules.vertical_module.VerticalModule,
'sequential':courseware.modules.seq_module.SequentialModule,
'tab':courseware.modules.seq_module.SequentialModule,
'schematic':courseware.modules.schematic_module.SchematicModule}
for f in os.listdir(settings.DATA_DIR+'/custom_tags'):
modx_modules[f] = courseware.modules.template_module.TemplateModule
def object_cache(cache, user, module_type, module_id): def object_cache(cache, user, module_type, module_id):
# We don't look up on user -- all queries include user # We don't look up on user -- all queries include user
# Additional lookup would require a DB hit the way Django # Additional lookup would require a DB hit the way Django
...@@ -78,18 +60,18 @@ def modx_dispatch(request, module=None, dispatch=None, id=None): ...@@ -78,18 +60,18 @@ def modx_dispatch(request, module=None, dispatch=None, id=None):
ajax_url = '/modx/'+module+'/'+id+'/' ajax_url = '/modx/'+module+'/'+id+'/'
id_tag=modx_modules[module].id_attribute id_tag=courseware.modules.get_module_class(module.id_attribute)
# Grab the XML corresponding to the request from course.xml # Grab the XML corresponding to the request from course.xml
xml = content_parser.module_xml(content_parser.course_file(request.user), module, id_tag, id) xml = content_parser.module_xml(content_parser.course_file(request.user), module, id_tag, id)
# Create the module # Create the module
instance=modx_modules[module](xml, instance=courseware.modules.get_module_class(module)(xml,
s.module_id, s.module_id,
ajax_url=ajax_url, ajax_url=ajax_url,
state=s.state, state=s.state,
track_function = make_track_function(request), track_function = make_track_function(request),
render_function = None) render_function = None)
# Let the module handle the AJAX # Let the module handle the AJAX
ajax_return=instance.handle_ajax(dispatch, request.POST) ajax_return=instance.handle_ajax(dispatch, request.POST)
# Save the state back to the database # Save the state back to the database
...@@ -104,7 +86,7 @@ def render_x_module(user, request, xml_module, module_object_preload): ...@@ -104,7 +86,7 @@ def render_x_module(user, request, xml_module, module_object_preload):
''' Generic module for extensions. This renders to HTML. ''' ''' Generic module for extensions. This renders to HTML. '''
# Check if problem has an instance in DB # Check if problem has an instance in DB
module_type=xml_module.tag module_type=xml_module.tag
module_class=modx_modules[module_type] module_class=courseware.modules.get_module_class(module_type)
module_id=xml_module.get('id') #module_class.id_attribute) or "" module_id=xml_module.get('id') #module_class.id_attribute) or ""
# Grab state from database # Grab state from database
......
import os
import os.path
from django.conf import settings
import capa_module
import html_module
import schematic_module
import seq_module
import template_module
import vertical_module
import video_module
# Import all files in modules directory, excluding backups (# and . in name)
# and __init__
#
# Stick them in a list
modx_module_list = []
for f in os.listdir(os.path.dirname(__file__)):
if f!='__init__.py' and \
f[-3:] == ".py" and \
"." not in f[:-3] \
and '#' not in f:
mod_path = 'courseware.modules.'+f[:-3]
mod = __import__(mod_path, fromlist = "courseware.modules")
if 'Module' in mod.__dict__:
modx_module_list.append(mod)
# Convert list to a dictionary for lookup by tag
modx_modules = {}
for module in modx_module_list:
for tag in module.Module.get_xml_tags():
modx_modules[tag] = module.Module
def get_module_class(tag):
return modx_modules[tag]
...@@ -26,15 +26,18 @@ import courseware.content_parser as content_parser ...@@ -26,15 +26,18 @@ import courseware.content_parser as content_parser
log = logging.getLogger("mitx.courseware") log = logging.getLogger("mitx.courseware")
class LoncapaModule(XModule): class Module(XModule):
''' Interface between capa_problem and x_module. Originally a hack ''' Interface between capa_problem and x_module. Originally a hack
meant to be refactored out, but it seems to be serving a useful meant to be refactored out, but it seems to be serving a useful
prupose now. We can e.g .destroy and create the capa_problem on a prupose now. We can e.g .destroy and create the capa_problem on a
reset. reset.
''' '''
xml_tags = ["problem"]
id_attribute = "filename" id_attribute = "filename"
@classmethod
def get_xml_tags(c):
return ["problem"]
def get_state(self): def get_state(self):
state = self.lcp.get_state() state = self.lcp.get_state()
......
...@@ -7,14 +7,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string ...@@ -7,14 +7,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string
from x_module import XModule from x_module import XModule
from lxml import etree from lxml import etree
class HtmlModule(XModule): class Module(XModule):
id_attribute = 'filename' id_attribute = 'filename'
def get_state(self): def get_state(self):
return json.dumps({ }) return json.dumps({ })
def get_xml_tags(): @classmethod
return "html" def get_xml_tags(c):
return ["html"]
def get_html(self): def get_html(self):
if self.filename==None: if self.filename==None:
......
...@@ -6,14 +6,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string ...@@ -6,14 +6,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string
from x_module import XModule from x_module import XModule
class SchematicModule(XModule): class Module(XModule):
id_attribute = 'id' id_attribute = 'id'
def get_state(self): def get_state(self):
return json.dumps({ }) return json.dumps({ })
def get_xml_tags(): @classmethod
return "schematic" def get_xml_tags(c):
return ["schematic"]
def get_html(self): def get_html(self):
return '<input type="hidden" class="schematic" name="{item_id}" height="480" width="640">'.format(item_id=self.item_id) return '<input type="hidden" class="schematic" name="{item_id}" height="480" width="640">'.format(item_id=self.item_id)
......
...@@ -13,7 +13,7 @@ from x_module import XModule ...@@ -13,7 +13,7 @@ from x_module import XModule
# OBSOLETE: This obsoletes 'type' # OBSOLETE: This obsoletes 'type'
class_priority = ['video', 'problem'] class_priority = ['video', 'problem']
class SequentialModule(XModule): class Module(XModule):
''' Layout module which lays out content in a temporal sequence ''' Layout module which lays out content in a temporal sequence
''' '''
id_attribute = 'id' id_attribute = 'id'
...@@ -21,7 +21,8 @@ class SequentialModule(XModule): ...@@ -21,7 +21,8 @@ class SequentialModule(XModule):
def get_state(self): def get_state(self):
return json.dumps({ 'position':self.position }) return json.dumps({ 'position':self.position })
def get_xml_tags(): @classmethod
def get_xml_tags(c):
return ["sequential", 'tab'] return ["sequential", 'tab']
def get_html(self): def get_html(self):
......
...@@ -7,14 +7,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string ...@@ -7,14 +7,15 @@ from mitxmako.shortcuts import render_to_response, render_to_string
from x_module import XModule from x_module import XModule
from lxml import etree from lxml import etree
class VerticalModule(XModule): class Module(XModule):
id_attribute = 'id' id_attribute = 'id'
def get_state(self): def get_state(self):
return json.dumps({ }) return json.dumps({ })
def get_xml_tags(): @classmethod
return "vertical" def get_xml_tags(c):
return ["vertical"]
def get_html(self): def get_html(self):
return render_to_string('vert_module.html',{'items':self.contents}) return render_to_string('vert_module.html',{'items':self.contents})
......
...@@ -11,7 +11,7 @@ from x_module import XModule ...@@ -11,7 +11,7 @@ from x_module import XModule
log = logging.getLogger("mitx.courseware.modules") log = logging.getLogger("mitx.courseware.modules")
class VideoModule(XModule): class Module(XModule):
#id_attribute = 'youtube' #id_attribute = 'youtube'
video_time = 0 video_time = 0
...@@ -28,9 +28,10 @@ class VideoModule(XModule): ...@@ -28,9 +28,10 @@ class VideoModule(XModule):
log.debug(u"STATE POSITION {0}".format(self.position)) log.debug(u"STATE POSITION {0}".format(self.position))
return json.dumps({ 'position':self.position }) return json.dumps({ 'position':self.position })
def get_xml_tags(): @classmethod
def get_xml_tags(c):
'''Tags in the courseware file guaranteed to correspond to the module''' '''Tags in the courseware file guaranteed to correspond to the module'''
return "video" return ["video"]
def video_list(self): def video_list(self):
l = self.youtube.split(',') l = self.youtube.split(',')
......
...@@ -10,7 +10,8 @@ class XModule(object): ...@@ -10,7 +10,8 @@ class XModule(object):
''' '''
id_attribute='name' # An attribute guaranteed to be unique id_attribute='name' # An attribute guaranteed to be unique
def get_xml_tags(): @classmethod
def get_xml_tags(c):
''' Tags in the courseware file guaranteed to correspond to the module ''' ''' Tags in the courseware file guaranteed to correspond to the module '''
return [] return []
......
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