Merge pull request #751 from MITx/cdodge/meta-data-cms-editing
Cdodge/meta data cms editing
This commit is contained in:
@@ -104,12 +104,14 @@ def edit_item(request):
|
||||
|
||||
item = modulestore().get_item(item_location)
|
||||
item.get_html = wrap_xmodule(item.get_html, item, "xmodule_edit.html")
|
||||
|
||||
return render_to_response('unit.html', {
|
||||
'contents': item.get_html(),
|
||||
'js_module': item.js_module_name,
|
||||
'category': item.category,
|
||||
'url_name': item.url_name,
|
||||
'previews': get_module_previews(request, item),
|
||||
'metadata': item.metadata
|
||||
})
|
||||
|
||||
|
||||
@@ -284,6 +286,19 @@ def save_item(request):
|
||||
children = request.POST['children']
|
||||
modulestore().update_children(item_location, children)
|
||||
|
||||
# cdodge: also commit any metadata which might have been passed along in the
|
||||
# POST from the client, if it is there
|
||||
# note, that the postback is not the complete metadata, as there's system metadata which is
|
||||
# not presented to the end-user for editing. So let's fetch the original and
|
||||
# 'apply' the submitted metadata, so we don't end up deleting system metadata
|
||||
if request.POST['metadata']:
|
||||
posted_metadata = request.POST['metadata']
|
||||
# fetch original
|
||||
existing_item = modulestore().get_item(item_location)
|
||||
# update existing metadata with submitted metadata (which can be partial)
|
||||
existing_item.metadata.update(posted_metadata)
|
||||
modulestore().update_metadata(item_location, existing_item.metadata)
|
||||
|
||||
# Export the course back to github
|
||||
# This uses wildcarding to find the course, which requires handling
|
||||
# multiple courses returned, but there should only ever be one
|
||||
|
||||
@@ -3,14 +3,26 @@ class CMS.Models.Module extends Backbone.Model
|
||||
defaults:
|
||||
data: ''
|
||||
children: ''
|
||||
metadata: {}
|
||||
|
||||
loadModule: (element) ->
|
||||
elt = $(element).find('.xmodule_edit').first()
|
||||
@module = XModule.loadModule(elt)
|
||||
# find the metadata edit region which should be setup server side,
|
||||
# so that we can wire up posting back those changes
|
||||
@metadata_elt = $(element).find('.metadata_edit')
|
||||
|
||||
editUrl: ->
|
||||
"/edit_item?#{$.param(id: @get('id'))}"
|
||||
|
||||
save: (args...) ->
|
||||
@set(data: @module.save()) if @module
|
||||
# cdodge: package up metadata which is separated into a number of input fields
|
||||
# there's probably a better way to do this, but at least this lets me continue to move onwards
|
||||
if @metadata_elt
|
||||
_metadata = {}
|
||||
# walk through the set of elments which have the 'xmetadata_name' attribute and
|
||||
# build up a object to pass back to the server on the subsequent POST
|
||||
_metadata[$(el).data("metadata-name")]=el.value for el in $('[data-metadata-name]', @metadata_elt)
|
||||
@set(metadata: _metadata)
|
||||
super(args...)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<%include file="metadata-edit.html" />
|
||||
<section class="html-edit">
|
||||
<textarea name="" class="edit-box" rows="8" cols="40">${data}</textarea>
|
||||
</section>
|
||||
|
||||
10
cms/templates/widgets/metadata-edit.html
Normal file
10
cms/templates/widgets/metadata-edit.html
Normal file
@@ -0,0 +1,10 @@
|
||||
% if metadata:
|
||||
<section class="metadata_edit">
|
||||
<h3>Metadata</h3>
|
||||
<ul>
|
||||
% for keyname in editable_metadata_fields:
|
||||
<li>${keyname}: <input type='text' data-metadata-name='${keyname}' value='${metadata[keyname]}' size='60' /></li>
|
||||
% endfor
|
||||
</ul>
|
||||
</section>
|
||||
% endif
|
||||
@@ -1,3 +1,4 @@
|
||||
<%include file="metadata-edit.html" />
|
||||
<section class="raw-edit">
|
||||
<textarea name="" class="edit-box" rows="8" cols="40">${data | h}</textarea>
|
||||
</section>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<%include file="metadata-edit.html" />
|
||||
<div class="content">
|
||||
<section class="modules">
|
||||
<ol>
|
||||
|
||||
@@ -6,7 +6,9 @@ import json
|
||||
def expect_json(view_function):
|
||||
@wraps(view_function)
|
||||
def expect_json_with_cloned_request(request, *args, **kwargs):
|
||||
if request.META['CONTENT_TYPE'] == "application/json":
|
||||
# cdodge: fix postback errors in CMS. The POST 'content-type' header can include additional information
|
||||
# e.g. 'charset', so we can't do a direct string compare
|
||||
if request.META['CONTENT_TYPE'].lower().startswith("application/json"):
|
||||
cloned_request = copy.copy(request)
|
||||
cloned_request.POST = cloned_request.POST.copy()
|
||||
cloned_request.POST.update(json.loads(request.body))
|
||||
|
||||
@@ -17,13 +17,13 @@ class EditingDescriptor(MakoModuleDescriptor):
|
||||
js = {'coffee': [resource_string(__name__, 'js/src/raw/edit.coffee')]}
|
||||
js_module_name = "RawDescriptor"
|
||||
|
||||
def get_context(self):
|
||||
return {
|
||||
'module': self,
|
||||
'data': self.definition.get('data', ''),
|
||||
# TODO (vshnayder): allow children and metadata to be edited.
|
||||
#'children' : self.definition.get('children, ''),
|
||||
|
||||
# TODO: show both own metadata and inherited?
|
||||
#'metadata' : self.own_metadata,
|
||||
}
|
||||
# cdodge: a little refactoring here, since we're basically doing the same thing
|
||||
# here as with our parent class, let's call into it to get the basic fields
|
||||
# set and then add our additional fields. Trying to keep it DRY.
|
||||
def get_context(self):
|
||||
_context = MakoModuleDescriptor.get_context(self)
|
||||
# Add our specific template information (the raw data body)
|
||||
_context.update({ 'data' : self.definition.get('data','') })
|
||||
return _context
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from x_module import XModuleDescriptor, DescriptorSystem
|
||||
import logging
|
||||
|
||||
|
||||
class MakoDescriptorSystem(DescriptorSystem):
|
||||
@@ -31,8 +32,18 @@ class MakoModuleDescriptor(XModuleDescriptor):
|
||||
"""
|
||||
Return the context to render the mako template with
|
||||
"""
|
||||
return {'module': self}
|
||||
return {'module': self,
|
||||
'metadata': self.metadata,
|
||||
'editable_metadata_fields' : self.editable_metadata_fields
|
||||
}
|
||||
|
||||
def get_html(self):
|
||||
return self.system.render_template(
|
||||
self.mako_template, self.get_context())
|
||||
|
||||
# cdodge: encapsulate a means to expose "editable" metadata fields (i.e. not internal system metadata)
|
||||
@property
|
||||
def editable_metadata_fields(self):
|
||||
subset = [name for name in self.metadata.keys() if name not in self.system_metadata_fields]
|
||||
return subset
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from xmodule.x_module import XModule
|
||||
from xmodule.progress import Progress
|
||||
from xmodule.exceptions import NotFoundError
|
||||
from pkg_resources import resource_string
|
||||
from .editing_module import EditingDescriptor
|
||||
|
||||
log = logging.getLogger("mitx.common.lib.seq_module")
|
||||
|
||||
@@ -95,7 +96,8 @@ class SequenceModule(XModule):
|
||||
'element_id': self.location.html_id(),
|
||||
'item_id': self.id,
|
||||
'position': self.position,
|
||||
'tag': self.location.category}
|
||||
'tag': self.location.category
|
||||
}
|
||||
|
||||
self.content = self.system.render_template('seq_module.html', params)
|
||||
self.rendered = True
|
||||
|
||||
@@ -352,6 +352,10 @@ class XModuleDescriptor(Plugin, HTMLSnippet):
|
||||
'data_dir'
|
||||
)
|
||||
|
||||
# cdodge: this is a list of metadata names which are 'system' metadata
|
||||
# and should not be edited by an end-user
|
||||
system_metadata_fields = [ 'data_dir' ]
|
||||
|
||||
# A list of descriptor attributes that must be equal for the descriptors to
|
||||
# be equal
|
||||
equality_attributes = ('definition', 'metadata', 'location',
|
||||
|
||||
Reference in New Issue
Block a user