Commit f48af8b8 by Don Mitchell

Server side controller and model stubbed in. Now to wire to view.

parent 279747ab
......@@ -58,7 +58,7 @@ from cms.djangoapps.models.settings.course_details import CourseDetails,\
CourseSettingsEncoder
from cms.djangoapps.models.settings.course_grading import CourseGradingModel
from cms.djangoapps.contentstore.utils import get_modulestore
from lxml import etree
from cms.djangoapps.models.settings.course_metadata import CourseMetadata
# to install PIL on MacOSX: 'easy_install http://dist.repoze.org/PIL-1.1.6.tar.gz'
......@@ -1181,6 +1181,59 @@ def course_grader_updates(request, org, course, name, grader_index=None):
@login_required
@ensure_csrf_cookie
def course_edit_metadata(request, org, course, name):
"""
Send models and views as well as html for editing the course editable metadata to the client.
org, course, name: Attributes of the Location for the item to edit
"""
location = ['i4x', org, course, 'course', name]
# check that logged in user has permissions to this item
if not has_access(request.user, location):
raise PermissionDenied()
editable = CourseMetadata.fetch(location)
return render_to_response('course_info.html', {
'active_tab': 'settings',
'editable_metadata': editable,
'url_base' : "/" + org + "/" + course + "/",
'blacklist_keys' : CourseMetadata.FILTERED_LIST
})
@expect_json
@login_required
@ensure_csrf_cookie
def course_metadata_rest_access(request, org, course, name):
"""
restful CRUD operations on metadata. The payload is a json rep of the metadata dicts. For delete, otoh,
the payload is either a key or a list of keys to delete.
org, course: Attributes of the Location for the item to edit
"""
location = ['i4x', org, course, 'course', name]
# check that logged in user has permissions to this item
if not has_access(request.user, location):
raise PermissionDenied()
# NB: we're setting Backbone.emulateHTTP to true on the client so everything comes as a post!!!
if request.method == 'POST' and 'HTTP_X_HTTP_METHOD_OVERRIDE' in request.META:
real_method = request.META['HTTP_X_HTTP_METHOD_OVERRIDE']
else:
real_method = request.method
if request.method == 'GET':
return HttpResponse(json.dumps(CourseMetadata.fetch(location)), mimetype="application/json")
elif real_method == 'DELETE': # coming as POST need to pull from Request Header X-HTTP-Method-Override DELETE
return HttpResponse(json.dumps(CourseMetadata.delete_key(location, request.POST)), mimetype="application/json")
elif request.method == 'POST':
return HttpResponse(json.dumps(CourseMetadata.update_from_json(location, request.POST)), mimetype="application/json")
@login_required
@ensure_csrf_cookie
def asset_index(request, org, course, name):
"""
Display an editable asset library
......
from xmodule.modulestore import Location
from contentstore.utils import get_modulestore
class CourseMetadata(object):
'''
For CRUD operations on metadata fields which do not have specific editors on the other pages including any user generated ones.
The objects have no predefined attrs but instead are obj encodings of the editable metadata.
'''
FILTERED_LIST = ['start', 'end', 'enrollment_start', 'enrollment_end', 'tabs', 'graceperiod']
@classmethod
def fetch(cls, course_location):
"""
Fetch the key:value editable course details for the given course from persistence and return a CourseMetadata model.
"""
if not isinstance(course_location, Location):
course_location = Location(course_location)
course = {}
descriptor = get_modulestore(course_location).get_item(course_location)
for k, v in descriptor.metadata.iteritems():
if k not in cls.FILTERED_LIST:
course[k] = v
return course
@classmethod
def update_from_json(cls, course_location, jsondict):
"""
Decode the json into CourseMetadata and save any changed attrs to the db
"""
descriptor = get_modulestore(course_location).get_item(course_location)
dirty = False
for k, v in jsondict.iteritems():
# should it be an error if one of the filtered list items is in the payload?
if k not in cls.FILTERED_LIST and (k not in descriptor.metadata or descriptor.metadata[k] != v):
dirty = True
descriptor.metadata[k] = v
if dirty:
get_modulestore(course_location).update_metadata(course_location, descriptor.metadata)
# Could just generate and return a course obj w/o doing any db reads, but I put the reads in as a means to confirm
# it persisted correctly
return cls.fetch(course_location)
@classmethod
def delete_key(cls, course_location, payload):
'''
Remove the given metadata key(s) from the course. payload can be a single key or [key..]
'''
descriptor = get_modulestore(course_location).get_item(course_location)
if isinstance(payload, list):
for key in payload:
if key in descriptor.metadata:
del descriptor.metadata[key]
else:
if payload in descriptor.metadata:
del descriptor.metadata[payload]
get_modulestore(course_location).update_metadata(course_location, descriptor.metadata)
return cls.fetch(course_location)
\ 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