Merge pull request #1815 from MITx/fix/cdodge/studio-forum-improvements
Fix/cdodge/studio forum improvements
This commit is contained in:
@@ -3,6 +3,7 @@ from pkg_resources import resource_string, resource_listdir
|
||||
|
||||
from xmodule.x_module import XModule
|
||||
from xmodule.raw_module import RawDescriptor
|
||||
from xmodule.editing_module import MetadataOnlyEditingDescriptor
|
||||
from xblock.core import String, Scope
|
||||
|
||||
|
||||
@@ -28,7 +29,7 @@ class DiscussionModule(DiscussionFields, XModule):
|
||||
return self.system.render_template('discussion/_discussion_module.html', context)
|
||||
|
||||
|
||||
class DiscussionDescriptor(DiscussionFields, RawDescriptor):
|
||||
class DiscussionDescriptor(DiscussionFields, MetadataOnlyEditingDescriptor, RawDescriptor):
|
||||
module_class = DiscussionModule
|
||||
template_dir_name = "discussion"
|
||||
|
||||
|
||||
@@ -41,6 +41,18 @@ class XMLEditingDescriptor(EditingDescriptor):
|
||||
js_module_name = "XMLEditingDescriptor"
|
||||
|
||||
|
||||
class MetadataOnlyEditingDescriptor(EditingDescriptor):
|
||||
"""
|
||||
Module which only provides an editing interface for the metadata, it does
|
||||
not expose a UI for editing the module data
|
||||
"""
|
||||
|
||||
js = {'coffee': [resource_string(__name__, 'js/src/raw/edit/metadata-only.coffee')]}
|
||||
js_module_name = "MetadataOnlyEditingDescriptor"
|
||||
|
||||
mako_template = "widgets/metadata-only-edit.html"
|
||||
|
||||
|
||||
class JSONEditingDescriptor(EditingDescriptor):
|
||||
"""
|
||||
Module that provides a raw editing view of its data as XML. It does not perform
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
class @MetadataOnlyEditingDescriptor extends XModule.Descriptor
|
||||
constructor: (@element) ->
|
||||
|
||||
save: ->
|
||||
data: null
|
||||
@@ -252,7 +252,6 @@ class Location(_LocationBase):
|
||||
def __repr__(self):
|
||||
return "Location%s" % repr(tuple(self))
|
||||
|
||||
|
||||
@property
|
||||
def course_id(self):
|
||||
"""Return the ID of the Course that this item belongs to by looking
|
||||
@@ -414,7 +413,6 @@ class ModuleStore(object):
|
||||
return courses
|
||||
|
||||
|
||||
|
||||
class ModuleStoreBase(ModuleStore):
|
||||
'''
|
||||
Implement interface functionality that can be shared.
|
||||
@@ -425,6 +423,7 @@ class ModuleStoreBase(ModuleStore):
|
||||
'''
|
||||
self._location_errors = {} # location -> ErrorLog
|
||||
self.metadata_inheritance_cache = None
|
||||
self.modulestore_update_signal = None # can be set by runtime to route notifications of datastore changes
|
||||
|
||||
def _get_errorlog(self, location):
|
||||
"""
|
||||
|
||||
@@ -9,6 +9,7 @@ from itertools import repeat
|
||||
from path import path
|
||||
from datetime import datetime
|
||||
from operator import attrgetter
|
||||
from uuid import uuid4
|
||||
|
||||
from importlib import import_module
|
||||
from xmodule.errortracker import null_error_tracker, exc_info_to_str
|
||||
@@ -30,6 +31,10 @@ log = logging.getLogger(__name__)
|
||||
# there is only one revision for each item. Once we start versioning inside the CMS,
|
||||
# that assumption will have to change
|
||||
|
||||
def get_course_id_no_run(location):
|
||||
'''
|
||||
'''
|
||||
return "/".join([location.org, location.course])
|
||||
|
||||
class MongoKeyValueStore(KeyValueStore):
|
||||
"""
|
||||
@@ -333,7 +338,7 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
'''
|
||||
key = metadata_cache_key(location)
|
||||
tree = {}
|
||||
|
||||
|
||||
if not force_refresh:
|
||||
# see if we are first in the request cache (if present)
|
||||
if self.request_cache is not None and key in self.request_cache.data.get('metadata_inheritance', {}):
|
||||
@@ -348,7 +353,7 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
if not tree:
|
||||
# if not in subsystem, or we are on force refresh, then we have to compute
|
||||
tree = self.compute_metadata_inheritance_tree(location)
|
||||
|
||||
|
||||
# now write out computed tree to caching subsystem (e.g. memcached), if available
|
||||
if self.metadata_inheritance_cache_subsystem is not None:
|
||||
self.metadata_inheritance_cache_subsystem.set(key, tree)
|
||||
@@ -541,8 +546,15 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
Clone a new item that is a copy of the item at the location `source`
|
||||
and writes it to `location`
|
||||
"""
|
||||
item = None
|
||||
try:
|
||||
source_item = self.collection.find_one(location_to_query(source))
|
||||
|
||||
# allow for some programmatically generated substitutions in metadata, e.g. Discussion_id's should be auto-generated
|
||||
for key in source_item['metadata'].keys():
|
||||
if source_item['metadata'][key] == '$$GUID$$':
|
||||
source_item['metadata'][key] = uuid4().hex
|
||||
|
||||
source_item['_id'] = Location(location).dict()
|
||||
self.collection.insert(
|
||||
source_item,
|
||||
@@ -566,12 +578,19 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
course.tabs = existing_tabs
|
||||
self.update_metadata(course.location, course._model_data._kvs._metadata)
|
||||
|
||||
return item
|
||||
except pymongo.errors.DuplicateKeyError:
|
||||
raise DuplicateItemError(location)
|
||||
|
||||
# recompute (and update) the metadata inheritance tree which is cached
|
||||
self.refresh_cached_metadata_inheritance_tree(Location(location))
|
||||
self.fire_updated_modulestore_signal(get_course_id_no_run(Location(location)), Location(location))
|
||||
|
||||
return item
|
||||
|
||||
def fire_updated_modulestore_signal(self, course_id, location):
|
||||
if self.modulestore_update_signal is not None:
|
||||
self.modulestore_update_signal.send(self, modulestore=self, course_id=course_id,
|
||||
location=location)
|
||||
|
||||
def get_course_for_item(self, location, depth=0):
|
||||
'''
|
||||
@@ -643,6 +662,8 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
self._update_single_item(location, {'definition.children': children})
|
||||
# recompute (and update) the metadata inheritance tree which is cached
|
||||
self.refresh_cached_metadata_inheritance_tree(Location(location))
|
||||
# fire signal that we've written to DB
|
||||
self.fire_updated_modulestore_signal(get_course_id_no_run(Location(location)), Location(location))
|
||||
|
||||
def update_metadata(self, location, metadata):
|
||||
"""
|
||||
@@ -669,6 +690,7 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
self._update_single_item(location, {'metadata': metadata})
|
||||
# recompute (and update) the metadata inheritance tree which is cached
|
||||
self.refresh_cached_metadata_inheritance_tree(loc)
|
||||
self.fire_updated_modulestore_signal(get_course_id_no_run(Location(location)), Location(location))
|
||||
|
||||
def delete_item(self, location):
|
||||
"""
|
||||
@@ -692,6 +714,7 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
safe=self.collection.safe)
|
||||
# recompute (and update) the metadata inheritance tree which is cached
|
||||
self.refresh_cached_metadata_inheritance_tree(Location(location))
|
||||
self.fire_updated_modulestore_signal(get_course_id_no_run(Location(location)), Location(location))
|
||||
|
||||
def get_parent_locations(self, location, course_id):
|
||||
'''Find all locations that are the parents of this location in this
|
||||
|
||||
@@ -29,6 +29,6 @@ class RawDescriptor(XmlDescriptor, XMLEditingDescriptor):
|
||||
line, offset = err.position
|
||||
msg = ("Unable to create xml for problem {loc}. "
|
||||
"Context: '{context}'".format(
|
||||
context=lines[line - 1][offset - 40:offset + 40],
|
||||
loc=self.location))
|
||||
context=lines[line - 1][offset - 40:offset + 40],
|
||||
loc=self.location))
|
||||
raise Exception, msg, sys.exc_info()[2]
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
metadata:
|
||||
display_name: Discussion Tag
|
||||
for: Topic-Level Student-Visible Label
|
||||
id: 6002x_group_discussion_by_this
|
||||
id: $$GUID$$
|
||||
discussion_category: Week 1
|
||||
data: |
|
||||
<discussion for="Topic-Level Student-Visible Label" id="6002x_group_discussion_by_this" discussion_category="Week 1" />
|
||||
<discussion />
|
||||
children: []
|
||||
|
||||
@@ -340,7 +340,9 @@ class XModuleDescriptor(XModuleFields, HTMLSnippet, ResourceTemplates, XBlock):
|
||||
|
||||
# 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', 'published_date', 'published_by', 'is_draft', 'xml_attributes']
|
||||
|
||||
system_metadata_fields = ['data_dir', 'published_date', 'published_by', 'is_draft',
|
||||
'discussion_id', 'xml_attributes']
|
||||
|
||||
# A list of descriptor attributes that must be equal for the descriptors to
|
||||
# be equal
|
||||
|
||||
Reference in New Issue
Block a user