Skip to content

Commit

Permalink
Merge pull request #121 from open-craft/haikuginger/nested-xblock-ref…
Browse files Browse the repository at this point in the history
…actor

Refactor MentoringBlock to use StudioContainerWithNestedXBlocksMixin
  • Loading branch information
haikuginger authored Oct 4, 2016
2 parents 88450ee + 97749d8 commit cbc895f
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 39 deletions.
89 changes: 75 additions & 14 deletions problem_builder/mentoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from xblock.fragment import Fragment
from xblock.validation import ValidationMessage

from .message import MentoringMessageBlock
from .message import MentoringMessageBlock, get_message_label
from .mixins import (
_normalize_id, QuestionMixin, MessageParentMixin, StepParentMixin, XBlockWithTranslationServiceMixin
)
Expand All @@ -44,9 +44,16 @@
from xblockutils.resources import ResourceLoader
from xblockutils.settings import XBlockWithSettingsMixin, ThemableXBlockMixin
from xblockutils.studio_editable import (
NestedXBlockSpec, StudioEditableXBlockMixin, StudioContainerXBlockMixin, StudioContainerWithNestedXBlocksMixin,
NestedXBlockSpec, StudioEditableXBlockMixin, StudioContainerWithNestedXBlocksMixin,
)

from problem_builder.answer import AnswerBlock, AnswerRecapBlock
from problem_builder.mcq import MCQBlock, RatingBlock
from problem_builder.mrq import MRQBlock
from problem_builder.plot import PlotBlock
from problem_builder.slider import SliderBlock
from problem_builder.table import MentoringTableBlock


try:
# Used to detect if we're in the workbench so we can add Font Awesome
Expand Down Expand Up @@ -220,7 +227,7 @@ def max_score(self):
return 1.0


class MentoringBlock(BaseMentoringBlock, StudioContainerXBlockMixin, StepParentMixin):
class MentoringBlock(BaseMentoringBlock, StudioContainerWithNestedXBlocksMixin, StepParentMixin):
"""
An XBlock providing mentoring capabilities
Expand Down Expand Up @@ -321,6 +328,64 @@ class MentoringBlock(BaseMentoringBlock, StudioContainerXBlockMixin, StepParentM
'display_submit', 'feedback_label', 'weight', 'extended_feedback'
)

@property
def allowed_nested_blocks(self):
"""
Returns a list of allowed nested XBlocks. Each item can be either
* An XBlock class
* A NestedXBlockSpec
If XBlock class is used it is assumed that this XBlock is enabled and allows multiple instances.
NestedXBlockSpec allows explicitly setting disabled/enabled state, disabled reason (if any) and single/multiple
instances
"""
additional_blocks = []
try:
from xmodule.video_module.video_module import VideoDescriptor
additional_blocks.append(NestedXBlockSpec(
VideoDescriptor, category='video', label=_(u"Video")
))
except ImportError:
pass
try:
from imagemodal import ImageModal
additional_blocks.append(NestedXBlockSpec(
ImageModal, category='imagemodal', label=_(u"Image Modal")
))
except ImportError:
pass

message_block_shims = [
NestedXBlockSpec(
MentoringMessageBlock,
category='pb-message',
boilerplate=message_type,
label=get_message_label(message_type),
)
for message_type in (
'completed',
'incomplete',
'max_attempts_reached',
)
]

if self.is_assessment:
message_block_shims.append(
NestedXBlockSpec(
MentoringMessageBlock,
category='pb-message',
boilerplate='on-assessment-review',
label=get_message_label('on-assessment-review'),
)
)

return [
NestedXBlockSpec(AnswerBlock, boilerplate='studio_default'),
MCQBlock, RatingBlock, MRQBlock,
NestedXBlockSpec(None, category="html", label=self._("HTML")),
AnswerRecapBlock, MentoringTableBlock, PlotBlock, SliderBlock
] + additional_blocks + message_block_shims

@property
def is_assessment(self):
""" Checks if mentoring XBlock is in assessment mode """
Expand Down Expand Up @@ -817,23 +882,19 @@ def author_edit_view(self, context):
"""
Add some HTML to the author view that allows authors to add child blocks.
"""
fragment = Fragment(u'<div class="mentoring">') # This DIV is needed for CSS to apply to the previews
self.render_children(context, fragment, can_reorder=True, can_add=False)
fragment.add_content(u'</div>')

# Show buttons to add review-related child blocks only in assessment mode.
fragment.add_content(loader.render_template('templates/html/mentoring_add_buttons.html', {
"show_review": self.is_assessment,
}))
local_context = context.copy()
local_context['author_edit_view'] = True
fragment = super(MentoringBlock, self).author_edit_view(local_context)
fragment.add_content(loader.render_template('templates/html/mentoring_url_name.html', {
"url_name": self.url_name
'url_name': self.url_name
}))
fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/problem-builder.css'))
fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/problem-builder-edit.css'))
fragment.add_css_url(self.runtime.local_resource_url(self, 'public/css/problem-builder-tinymce-content.css'))
fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/util.js'))
fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/mentoring_edit.js'))
fragment.initialize_js('MentoringEditComponents')
fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/container_edit.js'))
fragment.initialize_js('ProblemBuilderContainerEdit')

return fragment

@staticmethod
Expand Down
10 changes: 10 additions & 0 deletions problem_builder/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class MentoringMessageBlock(XBlock, StudioEditableXBlockMixin, XBlockWithTransla
MESSAGE_TYPES = {
"completed": {
"display_name": _(u"Completed"),
"studio_label": _(u'Message (Complete)'),
"long_display_name": _(u"Message shown when complete"),
"default": _(u"Great job!"),
"description": _(
Expand All @@ -54,6 +55,7 @@ class MentoringMessageBlock(XBlock, StudioEditableXBlockMixin, XBlockWithTransla
},
"incomplete": {
"display_name": _(u"Incomplete"),
"studio_label": _(u'Message (Incomplete)'),
"long_display_name": _(u"Message shown when incomplete"),
"default": _(u"Not quite! You can try again, though."),
"description": _(
Expand All @@ -64,6 +66,7 @@ class MentoringMessageBlock(XBlock, StudioEditableXBlockMixin, XBlockWithTransla
},
"max_attempts_reached": {
"display_name": _(u"Reached max. # of attempts"),
"studio_label": _(u'Message (Max # Attempts)'),
"long_display_name": _(u"Message shown when student reaches max. # of attempts"),
"default": _(u"Sorry, you have used up all of your allowed submissions."),
"description": _(
Expand All @@ -74,6 +77,7 @@ class MentoringMessageBlock(XBlock, StudioEditableXBlockMixin, XBlockWithTransla
},
"on-assessment-review": {
"display_name": _(u"Review with attempts left"),
"studio_label": _(u'Message (Assessment Review)'),
"long_display_name": _(u"Message shown during review when attempts remain"),
"default": _(
u"Note: if you retake this assessment, only your final score counts. "
Expand All @@ -100,6 +104,8 @@ class MentoringMessageBlock(XBlock, StudioEditableXBlockMixin, XBlockWithTransla
},
}

has_author_view = True

content = String(
display_name=_("Message"),
help=_("Message to display upon completion"),
Expand Down Expand Up @@ -189,3 +195,7 @@ class CompletedMentoringMessageShim(object):
class IncompleteMentoringMessageShim(object):
CATEGORY = 'pb-message'
STUDIO_LABEL = _("Message (Incomplete)")


def get_message_label(type):
return MentoringMessageBlock.MESSAGE_TYPES[type]['studio_label']
5 changes: 3 additions & 2 deletions problem_builder/questionnaire.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
from xblockutils.studio_editable import StudioEditableXBlockMixin, StudioContainerXBlockMixin, XBlockWithPreviewMixin

from .choice import ChoiceBlock
from .mentoring import MentoringBlock
from .message import MentoringMessageBlock
from .mixins import QuestionMixin, XBlockWithTranslationServiceMixin
from .tip import TipBlock
Expand Down Expand Up @@ -94,8 +93,10 @@ def student_view(self, context=None):

fragment = Fragment(loader.render_template(template_path, context))
# If we use local_resource_url(self, ...) the runtime may insert many identical copies
# of questionnaire.[css/js] into the DOM. So we use the mentoring block here if possible
# of questionnaire.[css/js] into the DOM. So we use the mentoring block here if possible.
block_with_resources = self.get_parent()
from .mentoring import MentoringBlock
# We use an inline import here to avoid a circular dependency with the .mentoring module.
if not isinstance(block_with_resources, MentoringBlock):
block_with_resources = self
fragment.add_css_url(self.runtime.local_resource_url(block_with_resources, 'public/css/questionnaire.css'))
Expand Down
23 changes: 0 additions & 23 deletions problem_builder/templates/html/mentoring_add_buttons.html

This file was deleted.

0 comments on commit cbc895f

Please sign in to comment.