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
#from django.utils.translation import ugettext_noop as _
from lazy import lazy
from enum import Enum
from xblock.fields import Boolean, Scope, String, XBlockMixin, Dict
from xblock.validation import ValidationMessage
from xmodule.modulestore.inheritance import UserPartitionList
......@@ -15,6 +17,17 @@ from xmodule.partitions.partitions import NoSuchUserPartitionError, NoSuchUserPa
_ = 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):
"""Special Dict class for serializing the group_access field"""
def from_json(self, access_dict):
......@@ -26,6 +39,26 @@ class GroupAccessDict(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):
"""
Mixin that defines fields common to all blocks used in the LMS
......@@ -66,10 +99,21 @@ class LmsBlockMixin(XBlockMixin):
deprecated=True
)
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,
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(
help=_(
"A dictionary that maps which groups can be shown this block. The keys "
......@@ -102,7 +146,7 @@ class LmsBlockMixin(XBlockMixin):
merged_access = parent.merged_group_access.copy()
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 partition_id in merged_access:
if merged_access[partition_id] is False:
......@@ -174,3 +218,23 @@ class LmsBlockMixin(XBlockMixin):
)
)
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