Merge pull request #1609 from MITx/diana/refactor-chemical-equation
Refactor Chemical Equation Preview
This commit is contained in:
@@ -45,8 +45,10 @@ import re
|
||||
import shlex # for splitting quoted strings
|
||||
import sys
|
||||
import os
|
||||
import pyparsing
|
||||
|
||||
from registry import TagRegistry
|
||||
from capa.chem import chemcalc
|
||||
|
||||
log = logging.getLogger('mitx.' + __name__)
|
||||
|
||||
@@ -752,6 +754,45 @@ class ChemicalEquationInput(InputTypeBase):
|
||||
"""
|
||||
return {'previewer': '/static/js/capa/chemical_equation_preview.js', }
|
||||
|
||||
def handle_ajax(self, dispatch, get):
|
||||
'''
|
||||
Since we only have chemcalc preview this input, check to see if it
|
||||
matches the corresponding dispatch and send it through if it does
|
||||
'''
|
||||
if dispatch == 'preview_chemcalc':
|
||||
return self.preview_chemcalc(get)
|
||||
return {}
|
||||
|
||||
def preview_chemcalc(self, get):
|
||||
"""
|
||||
Render an html preview of a chemical formula or equation. get should
|
||||
contain a key 'formula' and value 'some formula string'.
|
||||
|
||||
Returns a json dictionary:
|
||||
{
|
||||
'preview' : 'the-preview-html' or ''
|
||||
'error' : 'the-error' or ''
|
||||
}
|
||||
"""
|
||||
|
||||
result = {'preview': '',
|
||||
'error': ''}
|
||||
formula = get['formula']
|
||||
if formula is None:
|
||||
result['error'] = "No formula specified."
|
||||
return result
|
||||
|
||||
try:
|
||||
result['preview'] = chemcalc.render_to_html(formula)
|
||||
except pyparsing.ParseException as p:
|
||||
result['error'] = "Couldn't parse formula: {0}".format(p)
|
||||
except Exception:
|
||||
# this is unexpected, so log
|
||||
log.warning("Error while previewing chemical formula", exc_info=True)
|
||||
result['error'] = "Error while rendering preview"
|
||||
|
||||
return result
|
||||
|
||||
registry.register(ChemicalEquationInput)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<div class="incorrect" id="status_${id}">
|
||||
% endif
|
||||
|
||||
<input type="text" name="input_${id}" id="input_${id}" value="${value|h}"
|
||||
<input type="text" name="input_${id}" id="input_${id}" data-input-id="${id}" value="${value|h}"
|
||||
% if size:
|
||||
size="${size}"
|
||||
% endif
|
||||
|
||||
@@ -482,27 +482,43 @@ class ChemicalEquationTest(unittest.TestCase):
|
||||
'''
|
||||
Check that chemical equation inputs work.
|
||||
'''
|
||||
|
||||
def test_rendering(self):
|
||||
size = "42"
|
||||
xml_str = """<chemicalequationinput id="prob_1_2" size="{size}"/>""".format(size=size)
|
||||
def setUp(self):
|
||||
self.size = "42"
|
||||
xml_str = """<chemicalequationinput id="prob_1_2" size="{size}"/>""".format(size=self.size)
|
||||
|
||||
element = etree.fromstring(xml_str)
|
||||
|
||||
state = {'value': 'H2OYeah', }
|
||||
the_input = lookup_tag('chemicalequationinput')(test_system, element, state)
|
||||
self.the_input = lookup_tag('chemicalequationinput')(test_system, element, state)
|
||||
|
||||
context = the_input._get_render_context()
|
||||
|
||||
def test_rendering(self):
|
||||
''' Verify that the render context matches the expected render context'''
|
||||
context = self.the_input._get_render_context()
|
||||
|
||||
expected = {'id': 'prob_1_2',
|
||||
'value': 'H2OYeah',
|
||||
'status': 'unanswered',
|
||||
'msg': '',
|
||||
'size': size,
|
||||
'size': self.size,
|
||||
'previewer': '/static/js/capa/chemical_equation_preview.js',
|
||||
}
|
||||
self.assertEqual(context, expected)
|
||||
|
||||
|
||||
def test_chemcalc_ajax_sucess(self):
|
||||
''' Verify that using the correct dispatch and valid data produces a valid response'''
|
||||
|
||||
data = {'formula': "H"}
|
||||
response = self.the_input.handle_ajax("preview_chemcalc", data)
|
||||
|
||||
self.assertTrue('preview' in response)
|
||||
self.assertNotEqual(response['preview'], '')
|
||||
self.assertEqual(response['error'], "")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class DragAndDropTest(unittest.TestCase):
|
||||
'''
|
||||
@@ -631,4 +647,4 @@ class AnnotationInputTest(unittest.TestCase):
|
||||
}
|
||||
|
||||
self.maxDiff = None
|
||||
self.assertDictEqual(context, expected)
|
||||
self.assertDictEqual(context, expected)
|
||||
|
||||
@@ -11,9 +11,14 @@
|
||||
}
|
||||
|
||||
prev_id = "#" + this.id + "_preview";
|
||||
preview_div = $(prev_id)
|
||||
preview_div = $(prev_id);
|
||||
|
||||
$.get("/preview/chemcalc/", {"formula" : this.value}, create_handler(preview_div));
|
||||
// find the closest parent problems-wrapper and use that url
|
||||
url = $(this).closest('.problems-wrapper').data('url');
|
||||
// grab the input id from the input
|
||||
input_id = $(this).data('input-id')
|
||||
|
||||
Problem.inputAjax(url, input_id, 'preview_chemcalc', {"formula" : this.value}, create_handler(preview_div));
|
||||
}
|
||||
|
||||
inputs = $('.chemicalequationinput input');
|
||||
|
||||
@@ -16,7 +16,6 @@ from django.views.decorators.csrf import csrf_exempt
|
||||
from requests.auth import HTTPBasicAuth
|
||||
|
||||
from capa.xqueue_interface import XQueueInterface
|
||||
from capa.chem import chemcalc
|
||||
from courseware.access import has_access
|
||||
from mitxmako.shortcuts import render_to_string
|
||||
from models import StudentModule, StudentModuleCache
|
||||
@@ -559,42 +558,6 @@ def modx_dispatch(request, dispatch, location, course_id):
|
||||
return HttpResponse(ajax_return)
|
||||
|
||||
|
||||
def preview_chemcalc(request):
|
||||
"""
|
||||
Render an html preview of a chemical formula or equation. The fact that
|
||||
this is here is a bit of hack. See the note in lms/urls.py about why it's
|
||||
here. (Victor is to blame.)
|
||||
|
||||
request should be a GET, with a key 'formula' and value 'some formula string'.
|
||||
|
||||
Returns a json dictionary:
|
||||
{
|
||||
'preview' : 'the-preview-html' or ''
|
||||
'error' : 'the-error' or ''
|
||||
}
|
||||
"""
|
||||
if request.method != "GET":
|
||||
raise Http404
|
||||
|
||||
result = {'preview': '',
|
||||
'error': ''}
|
||||
formula = request.GET.get('formula')
|
||||
if formula is None:
|
||||
result['error'] = "No formula specified."
|
||||
|
||||
return HttpResponse(json.dumps(result))
|
||||
|
||||
try:
|
||||
result['preview'] = chemcalc.render_to_html(formula)
|
||||
except pyparsing.ParseException as p:
|
||||
result['error'] = "Couldn't parse formula: {0}".format(p)
|
||||
except Exception:
|
||||
# this is unexpected, so log
|
||||
log.warning("Error while previewing chemical formula", exc_info=True)
|
||||
result['error'] = "Error while rendering preview"
|
||||
|
||||
return HttpResponse(json.dumps(result))
|
||||
|
||||
|
||||
def get_score_bucket(grade, max_grade):
|
||||
"""
|
||||
|
||||
@@ -224,14 +224,6 @@ if settings.COURSEWARE_ENABLED:
|
||||
'courseware.module_render.modx_dispatch',
|
||||
name='modx_dispatch'),
|
||||
|
||||
# TODO (vshnayder): This is a hack. It creates a direct connection from
|
||||
# the LMS to capa functionality, and really wants to go through the
|
||||
# input types system so that previews can be context-specific.
|
||||
# Unfortunately, we don't have time to think through the right way to do
|
||||
# that (and implement it), and it's not a terrible thing to provide a
|
||||
# generic chemical-equation rendering service.
|
||||
url(r'^preview/chemcalc', 'courseware.module_render.preview_chemcalc',
|
||||
name='preview_chemcalc'),
|
||||
|
||||
# Software Licenses
|
||||
|
||||
|
||||
Reference in New Issue
Block a user