Commit 98fcee03 by J. Cliff Dyer

Added content visibility policy to LMS xblocks

* Includes learner_visibility_policy method to unify block and content
  visibility settings.
parent 2b7866bf
...@@ -5,6 +5,8 @@ Namespace that defines fields common to all blocks used in the LMS ...@@ -5,6 +5,8 @@ Namespace that defines fields common to all blocks used in the LMS
#from django.utils.translation import ugettext_noop as _ #from django.utils.translation import ugettext_noop as _
from lazy import lazy from lazy import lazy
from enum import Enum
from xblock.fields import Boolean, Scope, String, XBlockMixin, Dict from xblock.fields import Boolean, Scope, String, XBlockMixin, Dict
from xblock.validation import ValidationMessage from xblock.validation import ValidationMessage
from xmodule.modulestore.inheritance import UserPartitionList from xmodule.modulestore.inheritance import UserPartitionList
...@@ -15,6 +17,17 @@ from xmodule.partitions.partitions import NoSuchUserPartitionError, NoSuchUserPa ...@@ -15,6 +17,17 @@ from xmodule.partitions.partitions import NoSuchUserPartitionError, NoSuchUserPa
_ = lambda text: text _ = lambda text: text
class LearnerVisibilityPolicy(Enum):
"""
Possible visibility states
"""
visible = 1
block_hidden = 2
content_hidden = 3
content_hidden_after_due_date = 4
content_hidden_after_submission = 5
class GroupAccessDict(Dict): class GroupAccessDict(Dict):
"""Special Dict class for serializing the group_access field""" """Special Dict class for serializing the group_access field"""
def from_json(self, access_dict): def from_json(self, access_dict):
...@@ -26,6 +39,26 @@ class GroupAccessDict(Dict): ...@@ -26,6 +39,26 @@ class GroupAccessDict(Dict):
return {unicode(k): access_dict[k] for k in access_dict} return {unicode(k): access_dict[k] for k in access_dict}
class EnumString(String):
"""
Provides a String field constrained to an enumerated set of configured
values.
"""
def __init__(self, options=None, *args, **kwargs):
super(EnumString, self).__init__(*args, **kwargs)
self.options = options or set()
def from_json(self, string):
if string not in self.options:
raise ValueError('{!r} not in {}'.format(string, self.options))
return super(EnumString, self).from_json(string)
def to_json(self, string):
if string not in self.options:
raise ValueError('{!r} not in {}'.format(string, self.options))
return super(EnumString, self).to_json(string)
class LmsBlockMixin(XBlockMixin): class LmsBlockMixin(XBlockMixin):
""" """
Mixin that defines fields common to all blocks used in the LMS Mixin that defines fields common to all blocks used in the LMS
...@@ -66,10 +99,21 @@ class LmsBlockMixin(XBlockMixin): ...@@ -66,10 +99,21 @@ class LmsBlockMixin(XBlockMixin):
deprecated=True deprecated=True
) )
visible_to_staff_only = Boolean( visible_to_staff_only = Boolean(
help=_("If true, can be seen only by course staff, regardless of start date."), help=_("If true, block is only visibl to course staff, regardless of start date."),
default=False, default=False,
scope=Scope.settings, scope=Scope.settings,
) )
content_visibility_policy = EnumString(
options={
u'visible',
u'hidden',
u'hidden_after_due_date',
u'hidden_after_submission',
},
help=_("Determines when and if block content is hidden from learners."),
default=u'always_visible',
scope=Scope.settings,
)
group_access = GroupAccessDict( group_access = GroupAccessDict(
help=_( help=_(
"A dictionary that maps which groups can be shown this block. The keys " "A dictionary that maps which groups can be shown this block. The keys "
...@@ -102,7 +146,7 @@ class LmsBlockMixin(XBlockMixin): ...@@ -102,7 +146,7 @@ class LmsBlockMixin(XBlockMixin):
merged_access = parent.merged_group_access.copy() merged_access = parent.merged_group_access.copy()
if self.group_access is not None: if self.group_access is not None:
for partition_id, group_ids in self.group_access.items(): for partition_id, group_ids in self.group_access.iteritems():
if group_ids: # skip if the "local" group_access for this partition is None or empty. if group_ids: # skip if the "local" group_access for this partition is None or empty.
if partition_id in merged_access: if partition_id in merged_access:
if merged_access[partition_id] is False: if merged_access[partition_id] is False:
...@@ -174,3 +218,23 @@ class LmsBlockMixin(XBlockMixin): ...@@ -174,3 +218,23 @@ class LmsBlockMixin(XBlockMixin):
) )
) )
return validation return validation
def learner_visibility_policy(self):
"""
Return the unified visibility policy for this block.
This combines values from `visible_to_staff_only` and
`content_visibility_policy` to determine the policy for allowing a
learner to access the block or its content. BlockTransformers will
handle actual implementation of this policy.
"""
if self.visible_to_staff_only:
return LearnerVisibilityPolicy.block_hidden
else:
visibility_mapping = {
u'hidden': LearnerVisibilityPolicy.content_hidden,
u'hidden_after_due_date': LearnerVisibilityPolicy.content_hidden_after_due_date,
u'hidden_after_submission': LearnerVisibilityPolicy.content_hidden_after_submission,
}
return visibility_mapping.get(self.content_visibility_policy, LearnerVisibilityPolicy.visible)
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