Commit 33ce3d42 by E. Kolpakov

Validation warning when no content matches configured filters

parent ea428273
......@@ -361,6 +361,31 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe
lib_tools.update_children(self, user_id, user_perms, update_db)
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):
"""
Validates the state of this Library Content Module Instance. This
......@@ -381,30 +406,27 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe
)
return validation
lib_tools = self.runtime.service(self, 'library_tools')
has_children_matching_filter = False
for library_key, version in self.source_libraries:
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")
)
)
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")
)
)
if not self._validate_library_version(validation, lib_tools, version, library_key):
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
def editor_saved(self, user, old_metadata, old_content):
......
......@@ -18,7 +18,7 @@ class LibraryToolsService(object):
def __init__(self, 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
'library' XBlock with meta-information about the library.
......@@ -39,24 +39,39 @@ class LibraryToolsService(object):
Get the version (an ObjectID) of the given library.
Returns None if the library does not exist.
"""
library = self._get_library(lib_key)
library = self.get_library(lib_key)
if library:
# 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
return library.location.library_key.version_guid
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
"""
if dest_block.capa_type == ANY_CAPA_TYPE_VALUE:
if capa_type == ANY_CAPA_TYPE_VALUE:
return True
if not isinstance(child_descriptor, CapaDescriptor):
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):
"""
......@@ -89,7 +104,7 @@ class LibraryToolsService(object):
# First, load and validate the source_libraries:
libraries = []
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:
raise ValueError("Required library not found.")
if user_perms and not user_perms.can_read(library_key):
......@@ -109,11 +124,9 @@ class LibraryToolsService(object):
Internal method to copy blocks from the library recursively
"""
new_children = []
for child_key in from_block.children:
child = self.store.get_item(child_key, depth=9)
if filter_problem_type and not self._filter_child(dest_block, child):
continue
target_capa_type = dest_block.capa_type if filter_problem_type else ANY_CAPA_TYPE_VALUE
filtered_children = self.get_filtered_children(from_block, target_capa_type)
for child_key, child in filtered_children:
# 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.
# 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