Commit b5bf4b75 by Alexander Kryklia Committed by Александр

Enable latex problems via key in course.settings.

BLD-426
parent 64758673
......@@ -16,6 +16,9 @@ Blades: Disallow users to enter video url's in http.
LMS: Improve the acessibility of the forum follow post buttons.
Blades: Latex problems are now enabled via use_latex_compiler
key in course settings. (BLD-426)
Blades: Fix bug when the speed can only be changed when the video is playing.
LMS: Change bulk email implementation to use less memory, and to better handle
......
......@@ -19,11 +19,19 @@ Feature: CMS.Component Adding
| Component |
| Text |
| Announcement |
| E-text Written in LaTeX |
Then I see HTML components in this order:
| Component |
| Text |
| Announcement |
Scenario: I can add Latex HTML components
Given I am in Studio editing a new unit
Given I have enabled latex compiler
When I add this type of HTML component:
| Component |
| E-text Written in LaTeX |
Then I see HTML components in this order:
| Component |
| E-text Written in LaTeX |
Scenario: I can add Common Problem components
......@@ -58,9 +66,22 @@ Feature: CMS.Component Adding
| Drag and Drop |
| Image Mapped Input |
| Math Expression Input |
| Problem Written in LaTeX |
| Problem with Adaptive Hint |
Scenario: I can add Advanced Latex Problem components
Given I am in Studio editing a new unit
Given I have enabled latex compiler
When I add a "<Component>" "Advanced Problem" component
Then I see a "<Component>" Problem component
# Flush out the database before the next example executes
And I reset the database
Examples:
| Component |
| Problem Written in LaTeX |
| Problem with Adaptive Hint in Latex |
Scenario: I see a prompt on delete
Given I am in Studio editing a new unit
And I add a "Discussion" "single step" component
......
......@@ -22,6 +22,7 @@ def i_see_only_the_html_display_name(step):
@step('I have created an E-text Written in LaTeX$')
def i_created_etext_in_latex(step):
world.create_course_with_unit()
step.given('I have enabled latex compiler')
world.create_component_instance(
step=step,
category='html',
......
......@@ -5,6 +5,7 @@ import json
from lettuce import world, step
from nose.tools import assert_equal, assert_true # pylint: disable=E0611
from common import type_in_codemirror, open_new_course
from advanced_settings import change_value
from course_import import import_file, go_to_import
from selenium.webdriver.common.keys import Keys
......@@ -159,9 +160,19 @@ def cancel_does_not_save_changes(step):
step.given("I see the advanced settings and their expected values")
@step('I have enabled latex compiler')
def enable_latex_compiler(step):
url = world.browser.url
step.given("I select the Advanced Settings")
change_value(step, 'use_latex_compiler', True)
world.visit(url)
world.wait_for_xmodule()
@step('I have created a LaTeX Problem')
def create_latex_problem(step):
world.create_course_with_unit()
step.given('I have enabled latex compiler')
world.create_component_instance(
step=step,
category='problem',
......
......@@ -193,12 +193,14 @@ def edit_unit(request, location):
# add boilerplates
if hasattr(component_class, 'templates'):
for template in component_class.templates():
component_templates[category].append((
template['metadata'].get('display_name'),
category,
template['metadata'].get('markdown') is not None,
template.get('template_id')
))
filter_templates = getattr(component_class, 'filter_templates', None)
if not filter_templates or filter_templates(template, course):
component_templates[category].append((
template['metadata'].get('display_name'),
category,
template['metadata'].get('markdown') is not None,
template.get('template_id')
))
# Check if there are any advanced modules specified in the course policy.
# These modules should be specified as a list of strings, where the strings
......
......@@ -29,7 +29,7 @@
<%static:include path="js/metadata-list-entry.underscore" />
</script>
<% showHighLevelSource='source_code' in editable_metadata_fields and editable_metadata_fields['source_code']['explicitly_set'] %>
<% showHighLevelSource='source_code' in editable_metadata_fields and editable_metadata_fields['source_code']['explicitly_set'] and enable_latex_compiler %>
<% metadata_field_copy = copy.copy(editable_metadata_fields) %>
## Delete 'source_code' field (if it exists) so metadata editor view does not attempt to render it.
% if 'source_code' in editable_metadata_fields:
......
......@@ -158,6 +158,11 @@ class CapaFields(object):
# TODO: someday it should be possible to not duplicate this definition here
# and in inheritance.py
)
use_latex_compiler = Boolean(
help="Enable LaTeX templates?",
default=False,
scope=Scope.settings
)
class CapaModule(CapaFields, XModule):
......@@ -1174,10 +1179,23 @@ class CapaDescriptor(CapaFields, RawDescriptor):
metadata_translations = dict(RawDescriptor.metadata_translations)
metadata_translations['attempts'] = 'max_attempts'
@classmethod
def filter_templates(cls, template, course):
"""
Filter template that contains 'latex' from templates.
Show them only if use_latex_compiler is set to True in
course settings.
"""
return (not 'latex' in template['template_id'] or course.use_latex_compiler)
def get_context(self):
_context = RawDescriptor.get_context(self)
_context.update({'markdown': self.markdown,
'enable_markdown': self.markdown is not None})
_context.update({
'markdown': self.markdown,
'enable_markdown': self.markdown is not None,
'enable_latex_compiler': self.use_latex_compiler,
})
return _context
# VS[compat]
......@@ -1193,9 +1211,14 @@ class CapaDescriptor(CapaFields, RawDescriptor):
@property
def non_editable_metadata_fields(self):
non_editable_fields = super(CapaDescriptor, self).non_editable_metadata_fields
non_editable_fields.extend([CapaDescriptor.due, CapaDescriptor.graceperiod,
CapaDescriptor.force_save_button, CapaDescriptor.markdown,
CapaDescriptor.text_customization])
non_editable_fields.extend([
CapaDescriptor.due,
CapaDescriptor.graceperiod,
CapaDescriptor.force_save_button,
CapaDescriptor.markdown,
CapaDescriptor.text_customization,
CapaDescriptor.use_latex_compiler,
])
return non_editable_fields
# Proxy to CapaModule for access to any of its attributes
......
......@@ -7,7 +7,7 @@ from lxml import etree
from path import path
from pkg_resources import resource_string
from xblock.fields import Scope, String
from xblock.fields import Scope, String, Boolean
from xmodule.editing_module import EditingDescriptor
from xmodule.html_checker import check_html
from xmodule.stringify import stringify_children
......@@ -30,6 +30,11 @@ class HtmlFields(object):
)
data = String(help="Html contents to display for this module", default=u"", scope=Scope.content)
source_code = String(help="Source code for LaTeX documents. This feature is not well-supported.", scope=Scope.settings)
use_latex_compiler = Boolean(
help="Enable LaTeX templates?",
default=False,
scope=Scope.settings
)
class HtmlModule(HtmlFields, XModule):
......@@ -82,6 +87,16 @@ class HtmlDescriptor(HtmlFields, XmlDescriptor, EditingDescriptor):
nc.append(candidate[:-4] + '.html')
return candidates + nc
@classmethod
def filter_templates(cls, template, course):
"""
Filter template that contains 'latex' from templates.
Show them only if use_latex_compiler is set to True in
course settings.
"""
return (not 'latex' in template['template_id'] or course.use_latex_compiler)
def get_context(self):
"""
an override to add in specific rendering context, in this case we need to
......@@ -90,7 +105,10 @@ class HtmlDescriptor(HtmlFields, XmlDescriptor, EditingDescriptor):
_context = EditingDescriptor.get_context(self)
# Add some specific HTML rendering context when editing HTML modules where we pass
# the root /c4x/ url for assets. This allows client-side substitutions to occur.
_context.update({'base_asset_url': StaticContent.get_base_url_path_for_course_assets(self.location) + '/'})
_context.update({
'base_asset_url': StaticContent.get_base_url_path_for_course_assets(self.location) + '/',
'enable_latex_compiler': self.use_latex_compiler,
})
return _context
# NOTE: html descriptors are special. We do not want to parse and
......@@ -191,6 +209,12 @@ class HtmlDescriptor(HtmlFields, XmlDescriptor, EditingDescriptor):
elt.set("filename", relname)
return elt
@property
def non_editable_metadata_fields(self):
non_editable_fields = super(HtmlDescriptor, self).non_editable_metadata_fields
non_editable_fields.append(HtmlDescriptor.use_latex_compiler)
return non_editable_fields
class AboutFields(object):
display_name = String(
......
......@@ -47,6 +47,10 @@ class InheritanceMixin(XBlockMixin):
help="String customization substitutions for particular locations",
scope=Scope.settings
)
use_latex_compiler = Boolean(
help="Enable LaTeX templates?",
default=False,
scope=Scope.settings)
def compute_inherited_metadata(descriptor):
......
---
metadata:
display_name: Problem with Adaptive Hint
source_code: |
\subsection{Problem With Adaptive Hint}
% Adaptive hints are messages provided to students which depend on
% student input. These hints are produced using a script embedded
% within the problem (written in Python).
%
% Here is an example. This example uses LaTeX as a high-level
% soure language for the problem. The problem can also be coded
% directly in XML.
This problem demonstrates a question with hints, based on using the
{\tt hintfn} method.
\begin{edXscript}
def test_str(expect, ans):
print expect, ans
ans = ans.strip("'")
ans = ans.strip('"')
return expect == ans.lower()
def hint_fn(answer_ids, student_answers, new_cmap, old_cmap):
aid = answer_ids[0]
ans = str(student_answers[aid]).lower()
print 'hint_fn called, ans=', ans
hint = ''
if 'java' in ans:
hint = 'that is only good for drinking'
elif 'perl' in ans:
hint = 'not that rich'
elif 'pascal' in ans:
hint = 'that is a beatnick language'
elif 'fortran' in ans:
hint = 'those were the good days'
elif 'clu' in ans:
hint = 'you must be invariant'
if hint:
hint = "<font color='blue'>Hint: {0}</font>".format(hint)
new_cmap.set_hint_and_mode(aid,hint,'always')
\end{edXscript}
What is the best programming language that exists today? You may
enter your answer in upper or lower case, with or without quotes.
\edXabox{type="custom" cfn='test_str' expect='python' hintfn='hint_fn'}
markdown: !!null
data: |
<problem>
......@@ -61,7 +16,7 @@ data: |
ans = ans.strip("'")
ans = ans.strip('"')
return expect == ans.lower()
def hint_fn(answer_ids, student_answers, new_cmap, old_cmap):
aid = answer_ids[0]
ans = str(student_answers[aid]).lower()
......
---
metadata:
display_name: Problem with Adaptive Hint in Latex
source_code: |
\subsection{Problem With Adaptive Hint}
% Adaptive hints are messages provided to students which depend on
% student input. These hints are produced using a script embedded
% within the problem (written in Python).
%
% Here is an example. This example uses LaTeX as a high-level
% soure language for the problem. The problem can also be coded
% directly in XML.
This problem demonstrates a question with hints, based on using the
{\tt hintfn} method.
\begin{edXscript}
def test_str(expect, ans):
print expect, ans
ans = ans.strip("'")
ans = ans.strip('"')
return expect == ans.lower()
def hint_fn(answer_ids, student_answers, new_cmap, old_cmap):
aid = answer_ids[0]
ans = str(student_answers[aid]).lower()
print 'hint_fn called, ans=', ans
hint = ''
if 'java' in ans:
hint = 'that is only good for drinking'
elif 'perl' in ans:
hint = 'not that rich'
elif 'pascal' in ans:
hint = 'that is a beatnick language'
elif 'fortran' in ans:
hint = 'those were the good days'
elif 'clu' in ans:
hint = 'you must be invariant'
if hint:
hint = "<font color='blue'>Hint: {0}</font>".format(hint)
new_cmap.set_hint_and_mode(aid,hint,'always')
\end{edXscript}
What is the best programming language that exists today? You may
enter your answer in upper or lower case, with or without quotes.
\edXabox{type="custom" cfn='test_str' expect='python' hintfn='hint_fn'}
markdown: !!null
data: |
<problem>
<text>
<p>
<h4>Problem With Adaptive Hint</h4>
</p>
<p>
This problem demonstrates a question with hints, based on using the <tt class="tt">hintfn</tt> method. </p>
<script type="text/python" system_path="python_lib">
def test_str(expect, ans):
print expect, ans
ans = ans.strip("'")
ans = ans.strip('"')
return expect == ans.lower()
def hint_fn(answer_ids, student_answers, new_cmap, old_cmap):
aid = answer_ids[0]
ans = str(student_answers[aid]).lower()
print 'hint_fn called, ans=', ans
hint = ''
if 'java' in ans:
hint = 'that is only good for drinking'
elif 'perl' in ans:
hint = 'not that rich'
elif 'pascal' in ans:
hint = 'that is a beatnick language'
elif 'fortran' in ans:
hint = 'those were the good days'
elif 'clu' in ans:
hint = 'you must be invariant'
if hint:
hint = "&lt;font color='blue'&gt;Hint: {0}&lt;/font&gt;".format(hint)
new_cmap.set_hint_and_mode(aid,hint,'always')
</script>
<p>
What is the best programming language that exists today? You may enter your answer in upper or lower case, with or without quotes. </p>
<p>
<customresponse cfn="test_str" expect="python">
<textline correct_answer="python"/>
<hintgroup hintfn="hint_fn"/>
</customresponse>
</p>
</text>
</problem>
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