Commit 4aef50bf by Mike Chen

CapawikiModule not replacing CapaModule

parent bae419f6
...@@ -8,7 +8,7 @@ class @CapawikiDescriptor ...@@ -8,7 +8,7 @@ class @CapawikiDescriptor
{'capa': @capa_box.val(), 'wiki': @wiki_box.val()} {'capa': @capa_box.val(), 'wiki': @wiki_box.val()}
debug: (msg) -> debug: (msg) ->
console.log msg # console.log msg
loadParser: (url) -> loadParser: (url) ->
@debug "Retrieving grammar rules from " + url @debug "Retrieving grammar rules from " + url
...@@ -23,6 +23,10 @@ class @CapawikiDescriptor ...@@ -23,6 +23,10 @@ class @CapawikiDescriptor
"Line " + e.line + ", column " + e.column + ": " + e.message "Line " + e.line + ", column " + e.column + ": " + e.message
else e.message else e.message
dom2capa: (node) ->
serializer = new XMLSerializer()
capa = serializer.serializeToString(node)
buildXML: (parsed) -> buildXML: (parsed) ->
dom_parser = new DOMParser() dom_parser = new DOMParser()
doc = dom_parser.parseFromString("<problem />", "text/xml"); doc = dom_parser.parseFromString("<problem />", "text/xml");
...@@ -56,13 +60,6 @@ class @CapawikiDescriptor ...@@ -56,13 +60,6 @@ class @CapawikiDescriptor
center.append title center.append title
problem.append center problem.append center
else if section.type == 'linebreaks'
text = create_text_element('')
for i in [0..section.count] by 1
br = doc.createElement('br')
text.append(br)
problem.append(text)
else if section.type == 'multiple_choice' else if section.type == 'multiple_choice'
newel = $(doc.createElement('choiceresponse')) newel = $(doc.createElement('choiceresponse'))
...@@ -129,19 +126,23 @@ class @CapawikiDescriptor ...@@ -129,19 +126,23 @@ class @CapawikiDescriptor
else else
throw new SyntaxError("unexpected section type " + section.type) throw new SyntaxError("unexpected section type " + section.type)
parse: (source, done, fail) -> capa = @dom2capa(doc)
return capa
parse: (source) ->
try try
result = @parser.parse source result = @parser.parse (source + '\n')
return {'result': result, 'status': 'success'}
catch e catch e
message = @buildParserErrorMessage e message = @buildParserErrorMessage e
return fail(result) return {'message': message, 'status': 'error'}
return done(result)
convert: (parsed, done, fail) -> convert: (parsed) ->
try try
xml = @buildXML parsed xml = @buildXML parsed
return {'xml': xml, 'status': 'success'}
catch e catch e
message = @buildParserErrorMessage e message = @buildParserErrorMessage e
return fail(result) return {'message': message, 'status': 'error'}
return done(xml) return done(xml)
\ No newline at end of file
...@@ -6,17 +6,23 @@ class CMS.Views.CapawikiEdit extends Backbone.View ...@@ -6,17 +6,23 @@ class CMS.Views.CapawikiEdit extends Backbone.View
'click .cancel': 'cancel' 'click .cancel': 'cancel'
'click .module-edit': 'editSubmodule' 'click .module-edit': 'editSubmodule'
'click .save-update': 'save' 'click .save-update': 'save'
'keyup .wiki-box': 'checkAutoSave' 'keyup .capa-box': 'checkAutoSave'
'keyup .wiki-box': 'runParser'
'change .wiki-box': 'runParser'
initialize: -> initialize: ->
@$el.load @model.editUrl(), => @$el.load @model.editUrl(), =>
@descriptor = XModule.loadModule($(@el).find('.xmodule_edit')) @descriptor = XModule.loadModule($(@el).find('.xmodule_edit'))
@capa_box = $(".capa-box", @el) @capa_box = $(".capa-box", @el)
@wiki_box = $(".wiki-box", @el) @wiki_box = $(".wiki-box", @el)
@message_box = $(".message-box", @el)
@model.module = @descriptor @model.module = @descriptor
@throttledAutoSave = _.throttle(@autoSave, 0); @throttledAutoSave = _.throttle(@autoSave, 0);
XModule.loadModules('display') XModule.loadModules('display')
debug: (msg) ->
# console.log msg
checkAutoSaveTimeout: -> checkAutoSaveTimeout: ->
@auto_save_timer = null @auto_save_timer = null
@throttledAutoSave() @throttledAutoSave()
...@@ -28,18 +34,26 @@ class CMS.Views.CapawikiEdit extends Backbone.View ...@@ -28,18 +34,26 @@ class CMS.Views.CapawikiEdit extends Backbone.View
@auto_save_timer = window.setTimeout(callback, 1000) @auto_save_timer = window.setTimeout(callback, 1000)
hideMessage: -> hideMessage: ->
@message_box.css {"display":"none"} @message_box.text ""
showMessage: (message) -> showMessage: (message) ->
@message_box.css {"display":"block"}
@message_box.text message @message_box.text message
showError: (message) -> showError: (message) ->
@showMessage(message) @showMessage(message)
runParser: ->
out = @descriptor.parse @wiki_box.val()
if out.status == "success"
out = @descriptor.convert out.result
if out.status == "success"
@capa_box.val out.xml
@checkAutoSave()
@hideMessage()
@showMessage(out.message)
autoSave: -> autoSave: ->
@model.save().done((previews) => @model.save().done((previews) =>
@hideMessage()
previews_section = @$el.find('.previews').empty() previews_section = @$el.find('.previews').empty()
$.each(previews, (idx, preview) => $.each(previews, (idx, preview) =>
preview_wrapper = $('<section/>', class: 'preview').append preview preview_wrapper = $('<section/>', class: 'preview').append preview
......
<section class="capa-edit">
<a class="silent-save-update" />
<div class="parser-message-box" style="display:none;">Input parsed successfully.</div>
<textarea name="" class="edit-box source-box" rows="8" cols="40"></textarea>
<textarea name="" class="edit-box capa-box" rows="8" cols="40">${data}</textarea>
</section>
<section class="capawiki-edit"> <section class="capawiki-edit">
<div class="parser-message-box" style="display:none;">Input parsed successfully.</div> <div class="message-box">Input parsed successfully.</div>
<textarea name="" class="edit-box wiki-box" rows="8" cols="40" style="display: inline-block;">${data['wiki']}</textarea> <textarea name="" class="edit-box wiki-box" rows="8" cols="40" style="display: inline-block;">${data['wiki']}</textarea>
<textarea name="" class="edit-box capa-box" rows="8" cols="40">${data['capa']}</textarea> <textarea name="" class="edit-box capa-box" rows="8" cols="40">${data['capa']}</textarea>
</section> </section>
...@@ -26,7 +26,8 @@ setup( ...@@ -26,7 +26,8 @@ setup(
"html = xmodule.html_module:HtmlDescriptor", "html = xmodule.html_module:HtmlDescriptor",
"image = xmodule.backcompat_module:TranslateCustomTagDescriptor", "image = xmodule.backcompat_module:TranslateCustomTagDescriptor",
"error = xmodule.error_module:ErrorDescriptor", "error = xmodule.error_module:ErrorDescriptor",
"problem = xmodule.capawiki_module:CapawikiDescriptor", "problem = xmodule.capa_module:CapaDescriptor",
"capawiki = xmodule.capawiki_module:CapawikiDescriptor",
"problemset = xmodule.vertical_module:VerticalDescriptor", "problemset = xmodule.vertical_module:VerticalDescriptor",
"section = xmodule.backcompat_module:SemanticSectionDescriptor", "section = xmodule.backcompat_module:SemanticSectionDescriptor",
"sequential = xmodule.seq_module:SequenceDescriptor", "sequential = xmodule.seq_module:SequenceDescriptor",
......
...@@ -15,10 +15,8 @@ class CapawikiModule(CapaModule): ...@@ -15,10 +15,8 @@ class CapawikiModule(CapaModule):
def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs): def __init__(self, system, location, definition, instance_state=None, shared_state=None, **kwargs):
# self._definition = {'capa': '<problem />', 'wiki': ''} # self._definition = {'capa': '<problem />', 'wiki': ''}
self._definition = definition self._definition = definition
if isinstance(definition['data'], dict) and 'capa' in definition['data']: assert isinstance(definition['data'], dict) and 'capa' in definition['data']
self.capa_definition = {'data': definition['data']['capa']} self.capa_definition = {'data': definition['data']['capa']}
else:
self.capa_definition = definition
super(CapawikiModule, self).__init__(system, location, self.capa_definition, instance_state, super(CapawikiModule, self).__init__(system, location, self.capa_definition, instance_state,
shared_state, **kwargs) shared_state, **kwargs)
......
class @CapaDescriptor
constructor: (@element) ->
@problem_text = ""
@edit_box = $(".edit-box.capa-box", @element)
@source_box = $(".edit-box.source-box", @element)
@message_box = $(".parser-message-box", @element)
@loadSource()
@buildParser()
@throttledAutoSave = _.throttle(@autoSave, 0);
@source_box.keyup =>
@parse()
save: -> @edit_box.val()
loadSource: ->
parser = new DOMParser()
doc = parser.parseFromString @edit_box.val(), "text/xml"
nodes = doc.childNodes
for node in nodes
if node.nodeType == 8 # nodeType = 8 --> #comment
@source_box.val node.nodeValue
buildParser: ->
$.get "/static/grammars/main.jspeg", (data) =>
@grammar = data
@parser = PEG.buildParser @grammar
, "text"
buildErrorMessage: (e) ->
if e.line != undefined && e.column != undefined
"Line " + e.line + ", column " + e.column + ": " + e.message
else e.message
checkAutoSaveTimeout: ->
@auto_save_timer = null
@throttledAutoSave()
checkAutoSave: ->
callback = _.bind(@checkAutoSaveTimeout, this)
if @auto_save_timer
@auto_save_timer = window.clearTimeout(@auto_save_timer)
@auto_save_timer = window.setTimeout(callback, 1000)
autoSave: (event) ->
$(".silent-save-update").click();
parse: ->
try
source = @source_box.val() + "\n"
result = @parser.parse (source)
console.log result
@outputXML(result, source)
@message_box.css {"display":"none"}
catch e
console.log @buildErrorMessage(e)
@message_box.html @buildErrorMessage(e)
@message_box.css {"display":"block"}
outputXML: (parsed, source) ->
@edit_box.val @buildXML(parsed, source)
@checkAutoSave()
dom2capa: (node) ->
serializer = new XMLSerializer()
capa = serializer.serializeToString(node)
buildXML: (parsed, source) ->
dom_parser = new DOMParser()
doc = dom_parser.parseFromString("<problem />", "text/xml");
problem = $(doc).find('problem')
create_text_element = (content) ->
el = $(doc.createElement('text'))
for line in content.split('\n')
el.append doc.createTextNode(line)
el.append doc.createElement('br')
el.children().last().remove()
return el
variable_name_wrapper = (expression) ->
match = /^\{(.+)\}$/.exec(expression)
return if match then "$" + match[1] else expression
for section in parsed
if section.type == 'text'
newel = create_text_element(section.text)
problem.append(newel)
else if section.type == 'image'
center = $(doc.createElement('center'))
img = $(doc.createElement('img'))
img.attr 'src', section.url
center.append img
if section.title
title = create_text_element(section.title)
center.append doc.createElement('br')
center.append title
problem.append center
else if section.type == 'linebreaks'
text = create_text_element('')
for i in [0..section.count] by 1
br = doc.createElement('br')
text.append(br)
problem.append(text)
else if section.type == 'multiple_choice'
newel = $(doc.createElement('choiceresponse'))
# count the number of correct choices
num_correct = 0
for choice in section.choices
if choice.correct
num_correct += 1
if num_correct == 1
group = $(doc.createElement('radiogroup'))
else if num_correct > 1
group = $(doc.createElement('checkboxgroup'))
newel.append(group)
for choice_def in section.choices
choice = $(doc.createElement('choice'))
choice.attr 'correct', choice_def.correct
choice.append create_text_element(choice_def.text)
group.append(choice)
problem.append(newel)
else if section.type == 'numerical'
newel = $(doc.createElement('numericalresponse'))
newel.attr 'answer', variable_name_wrapper(section.answer)
tolerance = $(doc.createElement('responseparam'))
tolerance.attr 'type', 'tolerance'
if section.tolerance == undefined
section.tolerance = "5%"
tolerance.attr 'default', section.tolerance
tolerance.attr 'name', 'tol'
tolerance.attr 'description', 'Numerical Tolerance'
newel.append tolerance
newel.append doc.createElement('textline')
problem.append(newel)
else if section.type == 'string'
newel = $(doc.createElement('stringresponse'))
newel.attr 'answer', variable_name_wrapper(section.answer)
newel.append doc.createElement('textline')
problem.append(newel)
else if section.type == 'formula'
formularesponse = $(doc.createElement("formularesponse"))
formularesponse.attr 'samples', section.samples
formularesponse.attr 'answer', variable_name_wrapper(section.answer)
formularesponse.attr 'type', 'cs'
tolerance = $(doc.createElement('responseparam'))
tolerance.attr 'type', 'tolerance'
if section.tolerance == undefined
section.tolerance = "5%"
tolerance.attr 'default', section.tolerance
tolerance.attr 'name', 'tol'
tolerance.attr 'description', 'Numerical Tolerance'
formularesponse.append tolerance
formularesponse.append doc.createElement('textline')
problem.append(formularesponse)
else
throw new SyntaxError("unexpected section type " + section.type)
doc.appendChild doc.createComment(source)
capa = @dom2capa(doc)
return capa
\ No newline at end of file
import logging import logging
from .xml import XMLModuleStore from .xml import XMLModuleStore
from xmodule.x_module import Location
from .exceptions import DuplicateItemError from .exceptions import DuplicateItemError
import re import re
...@@ -8,7 +9,7 @@ import re ...@@ -8,7 +9,7 @@ import re
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def import_from_xml(store, data_dir, course_dirs=None, eager=True, def import_from_xml_capawiki(store, data_dir, course_dirs=None, eager=True,
default_class='xmodule.raw_module.RawDescriptor'): default_class='xmodule.raw_module.RawDescriptor'):
""" """
Import the specified xml data_dir into the "store" modulestore, Import the specified xml data_dir into the "store" modulestore,
...@@ -28,13 +29,18 @@ def import_from_xml(store, data_dir, course_dirs=None, eager=True, ...@@ -28,13 +29,18 @@ def import_from_xml(store, data_dir, course_dirs=None, eager=True,
# TODO (cpennington): This forces import to overrite the same items. # TODO (cpennington): This forces import to overrite the same items.
# This should in the future create new revisions of the items on import # This should in the future create new revisions of the items on import
if module.location.category == "problem":
loc = module.location.dict()
loc['category'] = 'capawiki'
module.location = Location(loc)
try: try:
store.create_item(module.location) store.create_item(module.location)
except DuplicateItemError: except DuplicateItemError:
log.exception('Item already exists at %s' % module.location.url()) log.exception('Item already exists at %s' % module.location.url())
pass pass
if 'data' in module.definition: if 'data' in module.definition:
if module.location.category == "problem": if module.location.category == "capawiki":
data = { data = {
'capa': module.definition['data'], 'capa': module.definition['data'],
'wiki': '', 'wiki': '',
...@@ -43,9 +49,51 @@ def import_from_xml(store, data_dir, course_dirs=None, eager=True, ...@@ -43,9 +49,51 @@ def import_from_xml(store, data_dir, course_dirs=None, eager=True,
else: else:
store.update_item(module.location, module.definition['data']) store.update_item(module.location, module.definition['data'])
if 'children' in module.definition: if 'children' in module.definition:
children = []
for x in module.definition['children']:
children.append(x.replace('/problem/', '/capawiki/'))
store.update_children(module.location, children)
# NOTE: It's important to use own_metadata here to avoid writing
# inherited metadata everywhere.
store.update_metadata(module.location, dict(module.own_metadata))
return module_store
def import_from_xml_original(store, data_dir, course_dirs=None, eager=True,
default_class='xmodule.raw_module.RawDescriptor'):
"""
Import the specified xml data_dir into the "store" modulestore,
using org and course as the location org and course.
course_dirs: If specified, the list of course_dirs to load. Otherwise, load
all course dirs
"""
module_store = XMLModuleStore(
data_dir,
default_class=default_class,
eager=eager,
course_dirs=course_dirs
)
for module in module_store.modules.itervalues():
# TODO (cpennington): This forces import to overrite the same items.
# This should in the future create new revisions of the items on import
try:
store.create_item(module.location)
except DuplicateItemError:
log.exception('Item already exists at %s' % module.location.url())
pass
if 'data' in module.definition:
store.update_item(module.location, module.definition['data'])
if 'children' in module.definition:
store.update_children(module.location, module.definition['children']) store.update_children(module.location, module.definition['children'])
# NOTE: It's important to use own_metadata here to avoid writing # NOTE: It's important to use own_metadata here to avoid writing
# inherited metadata everywhere. # inherited metadata everywhere.
store.update_metadata(module.location, dict(module.own_metadata)) store.update_metadata(module.location, dict(module.own_metadata))
return module_store return module_store
import_from_xml = import_from_xml_capawiki
\ No newline at end of file
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