diff --git a/problem_builder/answer.py b/problem_builder/answer.py index c4584886..f09016d5 100644 --- a/problem_builder/answer.py +++ b/problem_builder/answer.py @@ -141,13 +141,7 @@ class AnswerBlock(AnswerMixin, StepMixin, StudioEditableXBlockMixin, XBlock): enforce_type=True ) - editable_fields = ('question', 'name', 'min_characters', 'weight', 'default_from') - - @property - def display_name_with_default(self): - if not self.lonely_step: - return self._(u"Question {number}").format(number=self.step_number) - return self._(u"Question") + editable_fields = ('question', 'name', 'min_characters', 'weight', 'default_from', 'display_name', 'show_title') @lazy def student_input(self): @@ -172,6 +166,7 @@ def mentoring_view(self, context=None): """ Render this XBlock within a mentoring block. """ context = context or {} context['self'] = self + context['hide_header'] = context.get('hide_header', False) or not self.show_title html = loader.render_template('templates/html/answer_editable.html', context) fragment = Fragment(html) diff --git a/problem_builder/mentoring.py b/problem_builder/mentoring.py index 5a72d0a1..8d8177bb 100644 --- a/problem_builder/mentoring.py +++ b/problem_builder/mentoring.py @@ -559,7 +559,9 @@ def author_edit_view(self, context): """ Add some HTML to the author view that allows authors to add child blocks. """ - fragment = super(MentoringBlock, self).author_edit_view(context) + fragment = Fragment(u'
') # 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'
') fragment.add_content(loader.render_template('templates/html/mentoring_add_buttons.html', {})) fragment.add_content(loader.render_template('templates/html/mentoring_url_name.html', { "url_name": self.url_name diff --git a/problem_builder/mrq.py b/problem_builder/mrq.py index 44ff13c4..0fec59ca 100644 --- a/problem_builder/mrq.py +++ b/problem_builder/mrq.py @@ -69,7 +69,10 @@ class MRQBlock(QuestionnaireAbstractBlock): default=[], ) hide_results = Boolean(display_name="Hide results", scope=Scope.content, default=False) - editable_fields = ('question', 'required_choices', 'ignored_choices', 'message', 'weight', 'hide_results', ) + editable_fields = ( + 'question', 'required_choices', 'ignored_choices', 'message', 'display_name', + 'show_title', 'weight', 'hide_results', + ) def describe_choice_correctness(self, choice_value): if choice_value in self.required_choices: diff --git a/problem_builder/public/css/questionnaire.css b/problem_builder/public/css/questionnaire.css index c56344d4..f7b1af8b 100644 --- a/problem_builder/public/css/questionnaire.css +++ b/problem_builder/public/css/questionnaire.css @@ -1,19 +1,23 @@ .mentoring .questionnaire .choices-list { + display: table; position: relative; + width: 100%; + border-spacing: 0 6px; padding-top: 10px; margin-bottom: 10px; } .mentoring .questionnaire .choice-result { - display: inline-block; + display: table-cell; width: 40px; - vertical-align: middle; + vertical-align: top; cursor: pointer; float: none; } .mentoring .questionnaire .choice { overflow-y: hidden; + display: table-row; } .mentoring .questionnaire .choice-result.checkmark-correct, @@ -32,10 +36,11 @@ background: none repeat scroll 0 0 #66A5B5; font-family: arial; font-size: 14px; - overflow-y: auto; opacity: 0.9; - padding: 10px; + padding: 22px 10px; width: 300px; + min-height: 40px; + z-index: 10000; } .mentoring .questionnaire .choice-tips .title { @@ -48,6 +53,7 @@ .mentoring .questionnaire .feedback .tip-choice-group, .mentoring .questionnaire .feedback .message-content { position: relative; + overflow-y: auto; } .mentoring .questionnaire .choice-tips .close, @@ -69,26 +75,13 @@ } .mentoring .choices-list .choice-selector { - margin-right: 5px; + display: table-cell; + vertical-align: top; + width: 28px; } .mentoring .choice-label { - display: inline-block; - margin-top: 8px; - margin-bottom: 5px; + display: table-cell; + vertical-align: top; line-height: 1.3; } - -.mentoring .choices-list .choice-text > .xblock-light-child * { - vertical-align: middle; -} - -.mentoring .choices-list .choice-text > .xblock-light-child, -.mentoring .choices-list .choice-text > .xblock-light-child > .html_child { - /* - HTML Light Child content is wrapped in two divs: div.xblock-light-child and just div - On the other hand, choice are usually rendered inline. - Hence, we render first two divs inline, than all the actual content of HTML is rendered as is - */ - display: inline-block; -} diff --git a/problem_builder/public/js/questionnaire.js b/problem_builder/public/js/questionnaire.js index 033a2b3d..a967c5b6 100644 --- a/problem_builder/public/js/questionnaire.js +++ b/problem_builder/public/js/questionnaire.js @@ -20,15 +20,22 @@ function MessageView(element, mentoring) { var data = $(tip).data(); if (data && data.width) { popupDOM.css('width', data.width); + popupDOM.find('.tip-choice-group').css('width', data.width); } else { popupDOM.css('width', ''); + popupDOM.find('.tip-choice-group').css('width', ''); } if (data && data.height) { popupDOM.css('height', data.height); + popupDOM.css('maxHeight', data.height); } else { popupDOM.css('height', ''); + popupDOM.css('maxHeight', ''); } + // .tip-choice-group should always be the same height as the popup + // for scrolling to work properly. + popupDOM.find('.tip-choice-group').height(popupDOM.height()); var container = popupDOM.parent('.choice-tips-container'); if (container.length) { diff --git a/problem_builder/questionnaire.py b/problem_builder/questionnaire.py index 34feed39..74837e7b 100644 --- a/problem_builder/questionnaire.py +++ b/problem_builder/questionnaire.py @@ -20,6 +20,8 @@ # Imports ########################################################### +from django.utils.safestring import mark_safe +import logging from lxml import etree from xblock.core import XBlock from xblock.fields import Scope, String, Float, List, UNIQUE_ID @@ -81,7 +83,7 @@ class QuestionnaireAbstractBlock(StudioEditableXBlockMixin, StudioContainerXBloc scope=Scope.content, enforce_type=True ) - editable_fields = ('question', 'message', 'weight') + editable_fields = ('question', 'message', 'weight', 'display_name', 'show_title') has_children = True def _(self, text): @@ -98,6 +100,9 @@ def parse_xml(cls, node, runtime, keys, id_generator): # Load XBlock properties from the XML attributes: for name, value in node.items(): + if name not in block.fields: + logging.warn("XBlock %s does not contain field %s", type(block), name) + continue field = block.fields[name] if isinstance(field, List) and not value.startswith('['): # This list attribute is just a string of comma separated strings: @@ -114,10 +119,13 @@ def parse_xml(cls, node, runtime, keys, id_generator): return block @property - def display_name_with_default(self): - if not self.lonely_step: - return self._(u"Question {number}").format(number=self.step_number) - return self._(u"Question") + def html_id(self): + """ + A short, simple ID string used to uniquely identify this question. + + This is only used by templates for matching and