Merge branch 'master' of github.com:edx/edx-platform into bugfix/ichuang/make-edit-link-use-static-asset-path

Conflicts:
	common/djangoapps/xmodule_modifiers.py
This commit is contained in:
ichuang
2013-10-07 21:23:05 -04:00
870 changed files with 37614 additions and 13739 deletions

View File

@@ -1,19 +1,34 @@
"""
Functions that can are used to modify XBlock fragments for use in the LMS and Studio
"""
import datetime
import json
import logging
import static_replace
from django.conf import settings
from functools import wraps
from django.utils.timezone import UTC
from mitxmako.shortcuts import render_to_string
from xblock.fragment import Fragment
from xmodule.seq_module import SequenceModule
from xmodule.vertical_module import VerticalModule
import datetime
from django.utils.timezone import UTC
log = logging.getLogger("mitx.xmodule_modifiers")
log = logging.getLogger(__name__)
def wrap_xmodule(get_html, module, template, context=None):
def wrap_fragment(fragment, new_content):
"""
Returns a new Fragment that has `new_content` and all
as its content, and all of the resources from fragment
"""
wrapper_frag = Fragment(content=new_content)
wrapper_frag.add_frag_resources(fragment)
return wrapper_frag
def wrap_xmodule(template, block, view, frag, context): # pylint: disable=unused-argument
"""
Wraps the results of get_html in a standard <section> with identifying
data so that the appropriate javascript module can be loaded onto it.
@@ -26,23 +41,22 @@ def wrap_xmodule(get_html, module, template, context=None):
class_: the module class name
module_name: the js_module_name of the module
"""
if context is None:
context = {}
@wraps(get_html)
def _get_html():
context.update({
'content': get_html(),
'display_name': module.display_name,
'class_': module.__class__.__name__,
'module_name': module.js_module_name
})
# If XBlock generated this class, then use the first baseclass
# as the name (since that's the original, unmixed class)
class_name = getattr(block, 'unmixed_class', block.__class__).__name__
return render_to_string(template, context)
return _get_html
template_context = {
'content': frag.content,
'display_name': block.display_name,
'class_': class_name,
'module_name': block.js_module_name,
}
return wrap_fragment(frag, render_to_string(template, template_context))
def replace_jump_to_id_urls(get_html, course_id, jump_to_id_base_url):
def replace_jump_to_id_urls(course_id, jump_to_id_base_url, block, view, frag, context): # pylint: disable=unused-argument
"""
This will replace a link between courseware in the format
/jump_to/<id> with a URL for a page that will correctly redirect
@@ -55,38 +69,33 @@ def replace_jump_to_id_urls(get_html, course_id, jump_to_id_base_url):
redirect. e.g. /courses/<org>/<course>/<run>/jump_to_id. NOTE the <id> will be appended to
the end of this URL at re-write time
output: a wrapped get_html() function pointer, which, when called, will apply the
rewrite rules
output: a new :class:`~xblock.fragment.Fragment` that modifies `frag` with
content that has been update with /jump_to links replaced
"""
@wraps(get_html)
def _get_html():
return static_replace.replace_jump_to_id_urls(get_html(), course_id, jump_to_id_base_url)
return _get_html
return wrap_fragment(frag, static_replace.replace_jump_to_id_urls(frag.content, course_id, jump_to_id_base_url))
def replace_course_urls(get_html, course_id):
def replace_course_urls(course_id, block, view, frag, context): # pylint: disable=unused-argument
"""
Updates the supplied module with a new get_html function that wraps
the old get_html function and substitutes urls of the form /course/...
with urls that are /courses/<course_id>/...
"""
@wraps(get_html)
def _get_html():
return static_replace.replace_course_urls(get_html(), course_id)
return _get_html
return wrap_fragment(frag, static_replace.replace_course_urls(frag.content, course_id))
def replace_static_urls(get_html, data_dir, course_id=None, static_asset_path=''):
def replace_static_urls(data_dir, block, view, frag, context, course_id=None, static_asset_path=''): # pylint: disable=unused-argument
"""
Updates the supplied module with a new get_html function that wraps
the old get_html function and substitutes urls of the form /static/...
with urls that are /static/<prefix>/...
"""
@wraps(get_html)
def _get_html():
return static_replace.replace_static_urls(get_html(), data_dir, course_id, static_asset_path=static_asset_path)
return _get_html
return wrap_fragment(frag, static_replace.replace_static_urls(
frag.content,
data_dir,
course_id,
static_asset_path=static_asset_path
))
def grade_histogram(module_id):
@@ -111,22 +120,7 @@ def grade_histogram(module_id):
return grades
def save_module(get_html, module):
"""
Updates the given get_html function for the given module to save the fields
after rendering.
"""
@wraps(get_html)
def _get_html():
"""Cache the rendered output, save, then return the output."""
rendered_html = get_html()
module.save()
return rendered_html
return _get_html
def add_histogram(get_html, module, user):
def add_histogram(user, block, view, frag, context): # pylint: disable=unused-argument
"""
Updates the supplied module with a new get_html function that wraps
the output of the old get_html function with additional information
@@ -135,65 +129,60 @@ def add_histogram(get_html, module, user):
Does nothing if module is a SequenceModule or a VerticalModule.
"""
@wraps(get_html)
def _get_html():
# TODO: make this more general, eg use an XModule attribute instead
if isinstance(block, (SequenceModule, VerticalModule)):
return frag
if type(module) in [SequenceModule, VerticalModule]: # TODO: make this more general, eg use an XModule attribute instead
return get_html()
block_id = block.id
if block.descriptor.has_score:
histogram = grade_histogram(block_id)
render_histogram = len(histogram) > 0
else:
histogram = None
render_histogram = False
module_id = module.id
if module.descriptor.has_score:
histogram = grade_histogram(module_id)
render_histogram = len(histogram) > 0
else:
histogram = None
render_histogram = False
if settings.MITX_FEATURES.get('ENABLE_LMS_MIGRATION'):
[filepath, filename] = getattr(block.descriptor, 'xml_attributes', {}).get('filename', ['', None])
osfs = block.system.filestore
if filename is not None and osfs.exists(filename):
# if original, unmangled filename exists then use it (github
# doesn't like symlinks)
filepath = filename
data_dir = module.lms.static_asset_path or osfs.root_path.rsplit('/')[-1]
giturl = block.giturl or 'https://github.com/MITx'
edit_link = "%s/%s/tree/master/%s" % (giturl, data_dir, filepath)
else:
edit_link = False
# Need to define all the variables that are about to be used
giturl = ""
data_dir = ""
if settings.MITX_FEATURES.get('ENABLE_LMS_MIGRATION'):
[filepath, filename] = getattr(module.descriptor, 'xml_attributes', {}).get('filename', ['', None])
osfs = module.system.filestore
if filename is not None and osfs.exists(filename):
# if original, unmangled filename exists then use it (github
# doesn't like symlinks)
filepath = filename
data_dir = module.lms.static_asset_path or osfs.root_path.rsplit('/')[-1]
giturl = module.lms.giturl or 'https://github.com/MITx'
edit_link = "%s/%s/tree/master/%s" % (giturl, data_dir, filepath)
else:
edit_link = False
# Need to define all the variables that are about to be used
giturl = ""
data_dir = ""
source_file = block.source_file # source used to generate the problem XML, eg latex or word
source_file = module.lms.source_file # source used to generate the problem XML, eg latex or word
# useful to indicate to staff if problem has been released or not
# TODO (ichuang): use _has_access_descriptor.can_load in lms.courseware.access, instead of now>mstart comparison here
now = datetime.datetime.now(UTC())
is_released = "unknown"
mstart = block.descriptor.start
# useful to indicate to staff if problem has been released or not
# TODO (ichuang): use _has_access_descriptor.can_load in lms.courseware.access, instead of now>mstart comparison here
now = datetime.datetime.now(UTC())
is_released = "unknown"
mstart = module.descriptor.lms.start
if mstart is not None:
is_released = "<font color='red'>Yes!</font>" if (now > mstart) else "<font color='green'>Not yet</font>"
if mstart is not None:
is_released = "<font color='red'>Yes!</font>" if (now > mstart) else "<font color='green'>Not yet</font>"
staff_context = {'fields': [(field.name, getattr(module, field.name)) for field in module.fields],
'lms_fields': [(field.name, getattr(module.lms, field.name)) for field in module.lms.fields],
'xml_attributes' : getattr(module.descriptor, 'xml_attributes', {}),
'location': module.location,
'xqa_key': module.lms.xqa_key,
'source_file': source_file,
'source_url': '%s/%s/tree/master/%s' % (giturl, data_dir, source_file),
'category': str(module.__class__.__name__),
# Template uses element_id in js function names, so can't allow dashes
'element_id': module.location.html_id().replace('-', '_'),
'edit_link': edit_link,
'user': user,
'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER', 'http://xqa:server@content-qa.mitx.mit.edu/xqa'),
'histogram': json.dumps(histogram),
'render_histogram': render_histogram,
'module_content': get_html(),
'is_released': is_released,
}
return render_to_string("staff_problem_info.html", staff_context)
return _get_html
staff_context = {'fields': [(name, field.read_from(block)) for name, field in block.fields.items()],
'xml_attributes': getattr(block.descriptor, 'xml_attributes', {}),
'location': block.location,
'xqa_key': block.xqa_key,
'source_file': source_file,
'source_url': '%s/%s/tree/master/%s' % (giturl, data_dir, source_file),
'category': str(block.__class__.__name__),
# Template uses element_id in js function names, so can't allow dashes
'element_id': block.location.html_id().replace('-', '_'),
'edit_link': edit_link,
'user': user,
'xqa_server': settings.MITX_FEATURES.get('USE_XQA_SERVER', 'http://xqa:server@content-qa.mitx.mit.edu/xqa'),
'histogram': json.dumps(histogram),
'render_histogram': render_histogram,
'block_content': frag.content,
'is_released': is_released,
}
return wrap_fragment(frag, render_to_string("staff_problem_info.html", staff_context))