Commit 33ce3d42 by E. Kolpakov

Validation warning when no content matches configured filters

parent ea428273
...@@ -361,6 +361,31 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe ...@@ -361,6 +361,31 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe
lib_tools.update_children(self, user_id, user_perms, update_db) lib_tools.update_children(self, user_id, user_perms, update_db)
return Response() return Response()
def _validate_library_version(self, validation, lib_tools, version, library_key):
latest_version = lib_tools.get_library_version(library_key)
if latest_version is not None:
if version is None or version != latest_version:
validation.set_summary(
StudioValidationMessage(
StudioValidationMessage.WARNING,
_(u'This component is out of date. The library has new content.'),
action_class='library-update-btn', # TODO: change this to action_runtime_event='...' once the unit page supports that feature.
action_label=_(u"↻ Update now")
)
)
return False
else:
validation.set_summary(
StudioValidationMessage(
StudioValidationMessage.ERROR,
_(u'Library is invalid, corrupt, or has been deleted.'),
action_class='edit-button',
action_label=_(u"Edit Library List")
)
)
return False
return True
def validate(self): def validate(self):
""" """
Validates the state of this Library Content Module Instance. This Validates the state of this Library Content Module Instance. This
...@@ -381,30 +406,27 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe ...@@ -381,30 +406,27 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe
) )
return validation return validation
lib_tools = self.runtime.service(self, 'library_tools') lib_tools = self.runtime.service(self, 'library_tools')
has_children_matching_filter = False
for library_key, version in self.source_libraries: for library_key, version in self.source_libraries:
latest_version = lib_tools.get_library_version(library_key) if not self._validate_library_version(validation, lib_tools, version, library_key):
if latest_version is not None:
if version is None or version != latest_version:
validation.set_summary(
StudioValidationMessage(
StudioValidationMessage.WARNING,
_(u'This component is out of date. The library has new content.'),
action_class='library-update-btn', # TODO: change this to action_runtime_event='...' once the unit page supports that feature.
action_label=_(u"↻ Update now")
)
)
break
else:
validation.set_summary(
StudioValidationMessage(
StudioValidationMessage.ERROR,
_(u'Library is invalid, corrupt, or has been deleted.'),
action_class='edit-button',
action_label=_(u"Edit Library List")
)
)
break break
library = lib_tools.get_library(library_key)
children_matching_filter = lib_tools.get_filtered_children(library, self.capa_type)
# get_filtered_children returns generator, so we're basically checking if there are at least one child
# that satisfy filtering. Children are never equal to None, so None is returned only if generator was empty
has_children_matching_filter |= next(children_matching_filter, None) is not None
if not has_children_matching_filter and validation.empty:
validation.set_summary(
StudioValidationMessage(
StudioValidationMessage.WARNING,
_(u'There are no content matching configured filters in the selected libraries.'),
action_class='edit-button',
action_label=_(u"Edit Library List")
)
)
return validation return validation
def editor_saved(self, user, old_metadata, old_content): def editor_saved(self, user, old_metadata, old_content):
......
...@@ -18,7 +18,7 @@ class LibraryToolsService(object): ...@@ -18,7 +18,7 @@ class LibraryToolsService(object):
def __init__(self, modulestore): def __init__(self, modulestore):
self.store = modulestore self.store = modulestore
def _get_library(self, library_key): def get_library(self, library_key):
""" """
Given a library key like "library-v1:ProblemX+PR0B", return the Given a library key like "library-v1:ProblemX+PR0B", return the
'library' XBlock with meta-information about the library. 'library' XBlock with meta-information about the library.
...@@ -39,24 +39,39 @@ class LibraryToolsService(object): ...@@ -39,24 +39,39 @@ class LibraryToolsService(object):
Get the version (an ObjectID) of the given library. Get the version (an ObjectID) of the given library.
Returns None if the library does not exist. Returns None if the library does not exist.
""" """
library = self._get_library(lib_key) library = self.get_library(lib_key)
if library: if library:
# We need to know the library's version so ensure it's set in library.location.library_key.version_guid # We need to know the library's version so ensure it's set in library.location.library_key.version_guid
assert library.location.library_key.version_guid is not None assert library.location.library_key.version_guid is not None
return library.location.library_key.version_guid return library.location.library_key.version_guid
return None return None
def _filter_child(self, dest_block, child_descriptor): def _filter_child(self, capa_type, child_descriptor):
""" """
Filters children by CAPA problem type, if configured Filters children by CAPA problem type, if configured
""" """
if dest_block.capa_type == ANY_CAPA_TYPE_VALUE: if capa_type == ANY_CAPA_TYPE_VALUE:
return True return True
if not isinstance(child_descriptor, CapaDescriptor): if not isinstance(child_descriptor, CapaDescriptor):
return False return False
return dest_block.capa_type in child_descriptor.problem_types return capa_type in child_descriptor.problem_types
def get_filtered_children(self, from_block, capa_type=ANY_CAPA_TYPE_VALUE):
"""
Filters children of `from_block` that satisfy filter criteria
Returns generator containing (child_key, child) for all children matching filter criteria
"""
children = (
(child_key, self.store.get_item(child_key, depth=9))
for child_key in from_block.children
)
return (
(child_key, child)
for child_key, child in children
if self._filter_child(capa_type, child)
)
def update_children(self, dest_block, user_id, user_perms=None, update_db=True): def update_children(self, dest_block, user_id, user_perms=None, update_db=True):
""" """
...@@ -89,7 +104,7 @@ class LibraryToolsService(object): ...@@ -89,7 +104,7 @@ class LibraryToolsService(object):
# First, load and validate the source_libraries: # First, load and validate the source_libraries:
libraries = [] libraries = []
for library_key, old_version in dest_block.source_libraries: # pylint: disable=unused-variable for library_key, old_version in dest_block.source_libraries: # pylint: disable=unused-variable
library = self._get_library(library_key) library = self.get_library(library_key)
if library is None: if library is None:
raise ValueError("Required library not found.") raise ValueError("Required library not found.")
if user_perms and not user_perms.can_read(library_key): if user_perms and not user_perms.can_read(library_key):
...@@ -109,11 +124,9 @@ class LibraryToolsService(object): ...@@ -109,11 +124,9 @@ class LibraryToolsService(object):
Internal method to copy blocks from the library recursively Internal method to copy blocks from the library recursively
""" """
new_children = [] new_children = []
for child_key in from_block.children: target_capa_type = dest_block.capa_type if filter_problem_type else ANY_CAPA_TYPE_VALUE
child = self.store.get_item(child_key, depth=9) filtered_children = self.get_filtered_children(from_block, target_capa_type)
for child_key, child in filtered_children:
if filter_problem_type and not self._filter_child(dest_block, child):
continue
# We compute a block_id for each matching child block found in the library. # We compute a block_id for each matching child block found in the library.
# block_ids are unique within any branch, but are not unique per-course or globally. # block_ids are unique within any branch, but are not unique per-course or globally.
# We need our block_ids to be consistent when content in the library is updated, so # We need our block_ids to be consistent when content in the library is updated, so
......
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