Report the original LibraryUsageLocator in LMS analytics
This commit is contained in:
@@ -220,8 +220,11 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
|
||||
if hasattr(self, "_selected_set"):
|
||||
# Already done:
|
||||
return self._selected_set # pylint: disable=access-member-before-definition
|
||||
|
||||
lib_tools = self.runtime.service(self, 'library_tools')
|
||||
format_block_keys = lambda block_keys: lib_tools.create_block_analytics_summary(self.location.course_key, block_keys)
|
||||
|
||||
# Determine which of our children we will show:
|
||||
jsonify_block_keys = lambda keys: [unicode(self.location.course_key.make_usage_key(*key)) for key in keys]
|
||||
selected = set(tuple(k) for k in self.selected) # set of (block_type, block_id) tuples
|
||||
valid_block_keys = set([(c.block_type, c.block_id) for c in self.children]) # pylint: disable=no-member
|
||||
# Remove any selected blocks that are no longer valid:
|
||||
@@ -231,8 +234,9 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
|
||||
# Publish an event for analytics purposes:
|
||||
self.runtime.publish(self, "edx.librarycontentblock.content.removed", {
|
||||
"location": unicode(self.location),
|
||||
"blocks": jsonify_block_keys(invalid_block_keys),
|
||||
"removed": format_block_keys(invalid_block_keys),
|
||||
"reason": "invalid", # Deleted from library or library being used has changed
|
||||
"result": format_block_keys(selected),
|
||||
})
|
||||
# If max_count has been decreased, we may have to drop some previously selected blocks:
|
||||
overlimit_block_keys = set()
|
||||
@@ -242,8 +246,9 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
|
||||
# Publish an event for analytics purposes:
|
||||
self.runtime.publish(self, "edx.librarycontentblock.content.removed", {
|
||||
"location": unicode(self.location),
|
||||
"blocks": jsonify_block_keys(overlimit_block_keys),
|
||||
"removed": format_block_keys(overlimit_block_keys),
|
||||
"reason": "overlimit",
|
||||
"result": format_block_keys(selected),
|
||||
})
|
||||
# Do we have enough blocks now?
|
||||
num_to_add = self.max_count - len(selected)
|
||||
@@ -262,8 +267,8 @@ class LibraryContentModule(LibraryContentFields, XModule, StudioEditableModule):
|
||||
# Publish an event for analytics purposes:
|
||||
self.runtime.publish(self, "edx.librarycontentblock.content.assigned", {
|
||||
"location": unicode(self.location),
|
||||
"added": jsonify_block_keys(added_block_keys),
|
||||
"result": jsonify_block_keys(selected),
|
||||
"added": format_block_keys(added_block_keys),
|
||||
"result": format_block_keys(selected),
|
||||
})
|
||||
# Save our selections to the user state, to ensure consistency:
|
||||
self.selected = list(selected) # TODO: this doesn't save from the LMS "Progress" page.
|
||||
|
||||
@@ -44,6 +44,44 @@ class LibraryToolsService(object):
|
||||
return library.location.library_key.version_guid
|
||||
return None
|
||||
|
||||
def create_block_analytics_summary(self, course_key, block_keys):
|
||||
"""
|
||||
Given a CourseKey and a list of (block_type, block_id) pairs,
|
||||
prepare the JSON-ready metadata needed for analytics logging.
|
||||
|
||||
This is [
|
||||
{"usage_key": x, "original_usage_key": y, "original_usage_version": z, "descendants": [...]}
|
||||
]
|
||||
where the main list contains all top-level blocks, and descendants contains a *flat* list of all
|
||||
descendants of the top level blocks, if any.
|
||||
"""
|
||||
def summarize_block(usage_key):
|
||||
""" Basic information about the given block """
|
||||
orig_key, orig_version = self.store.get_block_original_usage(usage_key)
|
||||
return {
|
||||
"usage_key": unicode(usage_key),
|
||||
"original_usage_key": unicode(orig_key) if orig_key else None,
|
||||
"original_usage_version": unicode(orig_version) if orig_version else None,
|
||||
}
|
||||
|
||||
result_json = []
|
||||
for block_key in block_keys:
|
||||
key = course_key.make_usage_key(*block_key)
|
||||
info = summarize_block(key)
|
||||
info['descendants'] = []
|
||||
try:
|
||||
block = self.store.get_item(key, depth=None) # Load the item and all descendants
|
||||
children = list(getattr(block, "children", []))
|
||||
while children:
|
||||
child_key = children.pop()
|
||||
child = self.store.get_item(child_key)
|
||||
info['descendants'].append(summarize_block(child_key))
|
||||
children.extend(getattr(child, "children", []))
|
||||
except ItemNotFoundError:
|
||||
pass # The block has been deleted
|
||||
result_json.append(info)
|
||||
return result_json
|
||||
|
||||
def _filter_child(self, usage_key, capa_type):
|
||||
"""
|
||||
Filters children by CAPA problem type, if configured
|
||||
|
||||
@@ -10,6 +10,7 @@ from django.conf import settings
|
||||
from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig
|
||||
from openedx.core.djangoapps.user_api.api import course_tag as user_course_tag_api
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.library_tools import LibraryToolsService
|
||||
from xmodule.x_module import ModuleSystem
|
||||
from xmodule.partitions.partitions_service import PartitionService
|
||||
|
||||
@@ -199,6 +200,7 @@ class LmsModuleSystem(LmsHandlerUrls, ModuleSystem): # pylint: disable=abstract
|
||||
course_id=kwargs.get('course_id'),
|
||||
track_function=kwargs.get('track_function', None),
|
||||
)
|
||||
services['library_tools'] = LibraryToolsService(modulestore())
|
||||
services['fs'] = xblock.reference.plugins.FSService()
|
||||
self.request_token = kwargs.pop('request_token', None)
|
||||
super(LmsModuleSystem, self).__init__(**kwargs)
|
||||
|
||||
Reference in New Issue
Block a user