|
|
|
|
@@ -1,5 +1,7 @@
|
|
|
|
|
from util.json_request import expect_json
|
|
|
|
|
import json
|
|
|
|
|
import logging
|
|
|
|
|
from collections import defaultdict
|
|
|
|
|
|
|
|
|
|
from django.http import HttpResponse, Http404
|
|
|
|
|
from django.contrib.auth.decorators import login_required
|
|
|
|
|
@@ -15,6 +17,10 @@ from static_replace import replace_urls
|
|
|
|
|
from mitxmako.shortcuts import render_to_response, render_to_string
|
|
|
|
|
from xmodule.modulestore.django import modulestore
|
|
|
|
|
from xmodule_modifiers import replace_static_urls, wrap_xmodule
|
|
|
|
|
from xmodule.exceptions import NotFoundError
|
|
|
|
|
from functools import partial
|
|
|
|
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ==== Public views ==================================================
|
|
|
|
|
@@ -103,7 +109,7 @@ def edit_item(request):
|
|
|
|
|
'js_module': item.js_module_name,
|
|
|
|
|
'category': item.category,
|
|
|
|
|
'name': item.name,
|
|
|
|
|
'previews': get_module_previews(item),
|
|
|
|
|
'previews': get_module_previews(request, item),
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -124,16 +130,64 @@ def user_author_string(user):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
def preview_dispatch(request, module_id, dispatch):
|
|
|
|
|
def preview_dispatch(request, preview_id, location, dispatch=None):
|
|
|
|
|
"""
|
|
|
|
|
Dispatch an AJAX action to a preview XModule
|
|
|
|
|
|
|
|
|
|
Expects a POST request, and passes the arguments to the module
|
|
|
|
|
|
|
|
|
|
module_id: The Location of the module to dispatch to
|
|
|
|
|
preview_id (str): An identifier specifying which preview this module is used for
|
|
|
|
|
location: The Location of the module to dispatch to
|
|
|
|
|
dispatch: The action to execute
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
instance_state, shared_state = load_preview_state(request, preview_id, location)
|
|
|
|
|
descriptor = modulestore().get_item(location)
|
|
|
|
|
instance = load_preview_module(request, preview_id, descriptor, instance_state, shared_state)
|
|
|
|
|
# Let the module handle the AJAX
|
|
|
|
|
try:
|
|
|
|
|
ajax_return = instance.handle_ajax(dispatch, request.POST)
|
|
|
|
|
except NotFoundError:
|
|
|
|
|
log.exception("Module indicating to user that request doesn't exist")
|
|
|
|
|
raise Http404
|
|
|
|
|
except:
|
|
|
|
|
log.exception("error processing ajax call")
|
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
save_preview_state(request, preview_id, location, instance.get_instance_state(), instance.get_shared_state())
|
|
|
|
|
return HttpResponse(ajax_return)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_preview_state(request, preview_id, location):
|
|
|
|
|
"""
|
|
|
|
|
Load the state of a preview module from the request
|
|
|
|
|
|
|
|
|
|
preview_id (str): An identifier specifying which preview this module is used for
|
|
|
|
|
location: The Location of the module to dispatch to
|
|
|
|
|
"""
|
|
|
|
|
if 'preview_states' not in request.session:
|
|
|
|
|
request.session['preview_states'] = defaultdict(dict)
|
|
|
|
|
|
|
|
|
|
instance_state = request.session['preview_states'][preview_id, location].get('instance')
|
|
|
|
|
shared_state = request.session['preview_states'][preview_id, location].get('shared')
|
|
|
|
|
|
|
|
|
|
return instance_state, shared_state
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def save_preview_state(request, preview_id, location, instance_state, shared_state):
|
|
|
|
|
"""
|
|
|
|
|
Load the state of a preview module to the request
|
|
|
|
|
|
|
|
|
|
preview_id (str): An identifier specifying which preview this module is used for
|
|
|
|
|
location: The Location of the module to dispatch to
|
|
|
|
|
instance_state: The instance state to save
|
|
|
|
|
shared_state: The shared state to save
|
|
|
|
|
"""
|
|
|
|
|
if 'preview_states' not in request.session:
|
|
|
|
|
request.session['preview_states'] = defaultdict(dict)
|
|
|
|
|
|
|
|
|
|
request.session['preview_states'][preview_id, location]['instance'] = instance_state
|
|
|
|
|
request.session['preview_states'][preview_id, location]['shared'] = shared_state
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def render_from_lms(template_name, dictionary, context=None, namespace='main'):
|
|
|
|
|
@@ -143,54 +197,64 @@ def render_from_lms(template_name, dictionary, context=None, namespace='main'):
|
|
|
|
|
return render_to_string(template_name, dictionary, context, namespace="lms." + namespace)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def sample_module_system(descriptor):
|
|
|
|
|
def preview_module_system(request, preview_id, descriptor):
|
|
|
|
|
"""
|
|
|
|
|
Returns a ModuleSystem for the specified descriptor that is specialized for
|
|
|
|
|
rendering module previews.
|
|
|
|
|
|
|
|
|
|
request: The active django request
|
|
|
|
|
preview_id (str): An identifier specifying which preview this module is used for
|
|
|
|
|
descriptor: An XModuleDescriptor
|
|
|
|
|
"""
|
|
|
|
|
return ModuleSystem(
|
|
|
|
|
ajax_url=reverse('preview_dispatch', args=[descriptor.location.url(), '']),
|
|
|
|
|
ajax_url=reverse('preview_dispatch', args=[preview_id, descriptor.location.url(), '']),
|
|
|
|
|
# TODO (cpennington): Do we want to track how instructors are using the preview problems?
|
|
|
|
|
track_function=lambda x: None,
|
|
|
|
|
track_function=lambda type, event: None,
|
|
|
|
|
filestore=descriptor.system.resources_fs,
|
|
|
|
|
get_module=get_sample_module,
|
|
|
|
|
get_module=partial(get_preview_module, request, preview_id),
|
|
|
|
|
render_template=render_from_lms,
|
|
|
|
|
debug=True,
|
|
|
|
|
replace_urls=replace_urls
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_sample_module(location):
|
|
|
|
|
def get_preview_module(request, preview_id, location):
|
|
|
|
|
"""
|
|
|
|
|
Returns a sample XModule at the specified location. The sample_data is chosen arbitrarily
|
|
|
|
|
from the set of sample data for the descriptor specified by Location
|
|
|
|
|
Returns a preview XModule at the specified location. The preview_data is chosen arbitrarily
|
|
|
|
|
from the set of preview data for the descriptor specified by Location
|
|
|
|
|
|
|
|
|
|
request: The active django request
|
|
|
|
|
preview_id (str): An identifier specifying which preview this module is used for
|
|
|
|
|
location: A Location
|
|
|
|
|
"""
|
|
|
|
|
descriptor = modulestore().get_item(location)
|
|
|
|
|
instance_state, shared_state = descriptor.get_sample_state()[0]
|
|
|
|
|
return load_sample_module(descriptor, instance_state, shared_state)
|
|
|
|
|
return load_preview_module(request, preview_id, descriptor, instance_state, shared_state)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_sample_module(descriptor, instance_state, shared_state):
|
|
|
|
|
def load_preview_module(request, preview_id, descriptor, instance_state, shared_state):
|
|
|
|
|
"""
|
|
|
|
|
Return a sample XModule instantiated from the supplied descriptor, instance_state, and shared_state
|
|
|
|
|
Return a preview XModule instantiated from the supplied descriptor, instance_state, and shared_state
|
|
|
|
|
|
|
|
|
|
request: The active django request
|
|
|
|
|
preview_id (str): An identifier specifying which preview this module is used for
|
|
|
|
|
descriptor: An XModuleDescriptor
|
|
|
|
|
instance_state: An instance state string
|
|
|
|
|
shared_state: A shared state string
|
|
|
|
|
"""
|
|
|
|
|
system = sample_module_system(descriptor)
|
|
|
|
|
system = preview_module_system(request, preview_id, descriptor)
|
|
|
|
|
module = descriptor.xmodule_constructor(system)(instance_state, shared_state)
|
|
|
|
|
module.get_html = replace_static_urls(
|
|
|
|
|
wrap_xmodule(module.get_html, module, "xmodule_display.html"),
|
|
|
|
|
module.metadata['data_dir']
|
|
|
|
|
)
|
|
|
|
|
save_preview_state(request, preview_id, descriptor.location.url(),
|
|
|
|
|
module.get_instance_state(), module.get_shared_state())
|
|
|
|
|
|
|
|
|
|
return module
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_module_previews(descriptor):
|
|
|
|
|
def get_module_previews(request, descriptor):
|
|
|
|
|
"""
|
|
|
|
|
Returns a list of preview XModule html contents. One preview is returned for each
|
|
|
|
|
pair of states returned by get_sample_state() for the supplied descriptor.
|
|
|
|
|
@@ -198,8 +262,8 @@ def get_module_previews(descriptor):
|
|
|
|
|
descriptor: An XModuleDescriptor
|
|
|
|
|
"""
|
|
|
|
|
preview_html = []
|
|
|
|
|
for instance_state, shared_state in descriptor.get_sample_state():
|
|
|
|
|
module = load_sample_module(descriptor, instance_state, shared_state)
|
|
|
|
|
for idx, (instance_state, shared_state) in enumerate(descriptor.get_sample_state()):
|
|
|
|
|
module = load_preview_module(request, str(idx), descriptor, instance_state, shared_state)
|
|
|
|
|
preview_html.append(module.get_html())
|
|
|
|
|
return preview_html
|
|
|
|
|
|
|
|
|
|
@@ -225,6 +289,6 @@ def save_item(request):
|
|
|
|
|
export_to_github(course, "CMS Edit", author_string)
|
|
|
|
|
|
|
|
|
|
descriptor = modulestore().get_item(item_location)
|
|
|
|
|
preview_html = get_module_previews(descriptor)
|
|
|
|
|
preview_html = get_module_previews(request, descriptor)
|
|
|
|
|
|
|
|
|
|
return HttpResponse(json.dumps(preview_html))
|
|
|
|
|
|