Commit 4f6d3f86 by Tim Krones

Move code shared by existing mentoring block (problem builder) and new

mentoring block (step builder) to common superclass.
parent 99b72b12
...@@ -92,6 +92,21 @@ class BaseMentoringBlock( ...@@ -92,6 +92,21 @@ class BaseMentoringBlock(
default=True, default=True,
scope=Scope.content scope=Scope.content
) )
max_attempts = Integer(
display_name=_("Max. attempts allowed"),
help=_("Maximum number of times students are allowed to attempt the questions belonging to this block"),
default=0,
scope=Scope.content,
enforce_type=True
)
# User state
num_attempts = Integer(
# Number of attempts a user has answered for this questions
default=0,
scope=Scope.user_state,
enforce_type=True
)
has_children = True has_children = True
...@@ -110,6 +125,28 @@ class BaseMentoringBlock( ...@@ -110,6 +125,28 @@ class BaseMentoringBlock(
except AttributeError: except AttributeError:
return unicode(self.scope_ids.usage_id) return unicode(self.scope_ids.usage_id)
@property
def review_tips_json(self):
return json.dumps(self.review_tips)
@property
def max_attempts_reached(self):
return self.max_attempts > 0 and self.num_attempts >= self.max_attempts
def get_message_content(self, message_type, or_default=False):
for child_id in self.children:
if child_isinstance(self, child_id, MentoringMessageBlock):
child = self.runtime.get_block(child_id)
if child.type == message_type:
content = child.content
if hasattr(self.runtime, 'replace_jump_to_id_urls'):
content = self.runtime.replace_jump_to_id_urls(content)
return content
if or_default:
# Return the default value since no custom message is set.
# Note the WYSIWYG editor usually wraps the .content HTML in a <p> tag so we do the same here.
return '<p>{}</p>'.format(MentoringMessageBlock.MESSAGE_TYPES[message_type]['default'])
def get_theme(self): def get_theme(self):
""" """
Gets theme settings from settings service. Falls back to default (LMS) theme Gets theme settings from settings service. Falls back to default (LMS) theme
...@@ -129,6 +166,22 @@ class BaseMentoringBlock( ...@@ -129,6 +166,22 @@ class BaseMentoringBlock(
for theme_file in theme_files: for theme_file in theme_files:
fragment.add_css(ResourceLoader(theme_package).load_unicode(theme_file)) fragment.add_css(ResourceLoader(theme_package).load_unicode(theme_file))
def feedback_dispatch(self, target_data, stringify):
if self.show_extended_feedback():
if stringify:
return json.dumps(target_data)
else:
return target_data
def correct_json(self, stringify=True):
return self.feedback_dispatch(self.score.correct, stringify)
def incorrect_json(self, stringify=True):
return self.feedback_dispatch(self.score.incorrect, stringify)
def partial_json(self, stringify=True):
return self.feedback_dispatch(self.score.partially_correct, stringify)
@XBlock.json_handler @XBlock.json_handler
def view(self, data, suffix=''): def view(self, data, suffix=''):
""" """
...@@ -185,13 +238,6 @@ class MentoringBlock(BaseMentoringBlock, StudioContainerXBlockMixin, StepParentM ...@@ -185,13 +238,6 @@ class MentoringBlock(BaseMentoringBlock, StudioContainerXBlockMixin, StepParentM
default=None, default=None,
scope=Scope.content scope=Scope.content
) )
max_attempts = Integer(
display_name=_("Max. Attempts Allowed"),
help=_("Number of max attempts allowed for this questions"),
default=0,
scope=Scope.content,
enforce_type=True
)
enforce_dependency = Boolean( enforce_dependency = Boolean(
display_name=_("Enforce Dependency"), display_name=_("Enforce Dependency"),
help=_("Should the next step be the current block to complete?"), help=_("Should the next step be the current block to complete?"),
...@@ -247,12 +293,6 @@ class MentoringBlock(BaseMentoringBlock, StudioContainerXBlockMixin, StepParentM ...@@ -247,12 +293,6 @@ class MentoringBlock(BaseMentoringBlock, StudioContainerXBlockMixin, StepParentM
default=False, default=False,
scope=Scope.user_state scope=Scope.user_state
) )
num_attempts = Integer(
# Number of attempts a user has answered for this questions
default=0,
scope=Scope.user_state,
enforce_type=True
)
step = Integer( step = Integer(
# Keep track of the student assessment progress. # Keep track of the student assessment progress.
default=0, default=0,
...@@ -475,29 +515,9 @@ class MentoringBlock(BaseMentoringBlock, StudioContainerXBlockMixin, StepParentM ...@@ -475,29 +515,9 @@ class MentoringBlock(BaseMentoringBlock, StudioContainerXBlockMixin, StepParentM
review_tips.append(tip_html) review_tips.append(tip_html)
return review_tips return review_tips
@property
def review_tips_json(self):
return json.dumps(self.review_tips)
def show_extended_feedback(self): def show_extended_feedback(self):
return self.extended_feedback and self.max_attempts_reached return self.extended_feedback and self.max_attempts_reached
def feedback_dispatch(self, target_data, stringify):
if self.show_extended_feedback():
if stringify:
return json.dumps(target_data)
else:
return target_data
def correct_json(self, stringify=True):
return self.feedback_dispatch(self.score.correct, stringify)
def incorrect_json(self, stringify=True):
return self.feedback_dispatch(self.score.incorrect, stringify)
def partial_json(self, stringify=True):
return self.feedback_dispatch(self.score.partially_correct, stringify)
@XBlock.json_handler @XBlock.json_handler
def get_results(self, queries, suffix=''): def get_results(self, queries, suffix=''):
""" """
...@@ -739,24 +759,6 @@ class MentoringBlock(BaseMentoringBlock, StudioContainerXBlockMixin, StepParentM ...@@ -739,24 +759,6 @@ class MentoringBlock(BaseMentoringBlock, StudioContainerXBlockMixin, StepParentM
'result': 'success' 'result': 'success'
} }
@property
def max_attempts_reached(self):
return self.max_attempts > 0 and self.num_attempts >= self.max_attempts
def get_message_content(self, message_type, or_default=False):
for child_id in self.children:
if child_isinstance(self, child_id, MentoringMessageBlock):
child = self.runtime.get_block(child_id)
if child.type == message_type:
content = child.content
if hasattr(self.runtime, 'replace_jump_to_id_urls'):
content = self.runtime.replace_jump_to_id_urls(content)
return content
if or_default:
# Return the default value since no custom message is set.
# Note the WYSIWYG editor usually wraps the .content HTML in a <p> tag so we do the same here.
return '<p>{}</p>'.format(MentoringMessageBlock.MESSAGE_TYPES[message_type]['default'])
def validate(self): def validate(self):
""" """
Validates the state of this XBlock except for individual field values. Validates the state of this XBlock except for individual field values.
...@@ -832,13 +834,6 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes ...@@ -832,13 +834,6 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes
An XBlock providing mentoring capabilities with explicit steps An XBlock providing mentoring capabilities with explicit steps
""" """
# Content # Content
max_attempts = Integer(
display_name=_("Max. attempts allowed"),
help=_("Maximum number of times students are allowed to attempt this mentoring block"),
default=0,
scope=Scope.content,
enforce_type=True
)
extended_feedback = Boolean( extended_feedback = Boolean(
display_name=_("Extended feedback"), display_name=_("Extended feedback"),
help=_("Show extended feedback when all attempts are used up?"), help=_("Show extended feedback when all attempts are used up?"),
...@@ -855,12 +850,6 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes ...@@ -855,12 +850,6 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes
) )
# User state # User state
num_attempts = Integer(
# Number of attempts user has attempted this mentoring block
default=0,
scope=Scope.user_state,
enforce_type=True
)
active_step = Integer( active_step = Integer(
# Keep track of the student progress. # Keep track of the student progress.
default=0, default=0,
...@@ -922,10 +911,6 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes ...@@ -922,10 +911,6 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes
return any(child_isinstance(self, child_id, ReviewStepBlock) for child_id in self.children) return any(child_isinstance(self, child_id, ReviewStepBlock) for child_id in self.children)
@property @property
def max_attempts_reached(self):
return self.max_attempts > 0 and self.num_attempts >= self.max_attempts
@property
def assessment_message(self): def assessment_message(self):
""" """
Get the message to display to a student following a submission in assessment mode. Get the message to display to a student following a submission in assessment mode.
...@@ -976,10 +961,6 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes ...@@ -976,10 +961,6 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes
review_tips.append(tip_html) review_tips.append(tip_html)
return review_tips return review_tips
@property
def review_tips_json(self):
return json.dumps(self.review_tips)
@XBlock.json_handler @XBlock.json_handler
def get_review_tips(self, data, suffix): def get_review_tips(self, data, suffix):
return { return {
...@@ -989,36 +970,6 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes ...@@ -989,36 +970,6 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes
def show_extended_feedback(self): def show_extended_feedback(self):
return self.extended_feedback return self.extended_feedback
def feedback_dispatch(self, target_data, stringify):
if self.show_extended_feedback():
if stringify:
return json.dumps(target_data)
else:
return target_data
def correct_json(self, stringify=True):
return self.feedback_dispatch(self.score.correct, stringify)
def incorrect_json(self, stringify=True):
return self.feedback_dispatch(self.score.incorrect, stringify)
def partial_json(self, stringify=True):
return self.feedback_dispatch(self.score.partially_correct, stringify)
def get_message_content(self, message_type, or_default=False):
for child_id in self.children:
if child_isinstance(self, child_id, MentoringMessageBlock):
child = self.runtime.get_block(child_id)
if child.type == message_type:
content = child.content
if hasattr(self.runtime, 'replace_jump_to_id_urls'):
content = self.runtime.replace_jump_to_id_urls(content)
return content
if or_default:
# Return the default value since no custom message is set.
# Note the WYSIWYG editor usually wraps the .content HTML in a <p> tag so we do the same here.
return '<p>{}</p>'.format(MentoringMessageBlock.MESSAGE_TYPES[message_type]['default'])
def student_view(self, context): def student_view(self, context):
fragment = Fragment() fragment = Fragment()
children_contents = [] children_contents = []
......
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