Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 76 additions & 16 deletions problem_builder/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from .sub_api import sub_api
from lazy import lazy
from xblock.core import XBlock
from xblock.fields import Scope, List, String
from xblock.fields import Scope, List, String, Boolean, Dict
from xblock.fragment import Fragment
from xblock.validation import ValidationMessage
from xblockutils.helpers import child_isinstance
Expand Down Expand Up @@ -172,6 +172,20 @@ class DashboardBlock(StudioEditableXBlockMixin, XBlock):
).format(example_here='["2754b8afc03a439693b9887b6f1d9e36", "215028f7df3d4c68b14fb5fea4da7053"]'),
scope=Scope.settings,
)
exclude_questions = Dict(
display_name=_("Questions to be hidden"),
help=_(
"Optional rules to exclude specific questions both from displaying in dashboard and from the calculated "
"average. Rules must start with the url_name of a mentoring block, followed by list of question numbers "
"to exclude. Rule set must be in JSON format. Question numbers are one-based (the first question being "
"number 1). Must be in JSON format. Examples: {examples_here}"
).format(
examples_here='{"2754b8afc03a439693b9887b6f1d9e36":[1,2], "215028f7df3d4c68b14fb5fea4da7053":[1,5]}'
),
scope=Scope.content,
multiline_editor=True,
resettable_editor=False,
)
color_rules = String(
display_name=_("Color Coding Rules"),
help=_(
Expand Down Expand Up @@ -207,8 +221,23 @@ class DashboardBlock(StudioEditableXBlockMixin, XBlock):
),
scope=Scope.content,
)
average_label = String(
display_name=_("Label for average value"),
default=_("Average"),
help=_("Label to be shown for calculated average"),
scope=Scope.content,
)
show_numbers = Boolean(
display_name=_("Display values"),
default=True,
help=_("Toggles if numeric values are displayed"),
scope=Scope.content
)

editable_fields = ('display_name', 'mentoring_ids', 'color_rules', 'visual_rules', 'visual_title', 'visual_desc')
editable_fields = (
'display_name', 'mentoring_ids', 'exclude_questions', 'average_label', 'show_numbers',
'color_rules', 'visual_rules', 'visual_title', 'visual_desc'
)
css_path = 'public/css/dashboard.css'
js_path = 'public/js/dashboard.js'

Expand Down Expand Up @@ -321,6 +350,12 @@ def _get_course_name(self):
except Exception:
return ""

def _get_problem_questions(self, mentoring_block):
""" Generator returning only children of specified block that are MCQs """
for child_id in mentoring_block.children:
if child_isinstance(mentoring_block, child_id, MCQBlock):
yield child_id

def student_view(self, context=None): # pylint: disable=unused-argument
"""
Standard view of this XBlock.
Expand All @@ -336,20 +371,35 @@ def student_view(self, context=None): # pylint: disable=unused-argument
'display_name': mentoring_block.display_name,
'mcqs': []
}
for child_id in mentoring_block.children:
if child_isinstance(mentoring_block, child_id, MCQBlock):
# Get the student's submitted answer to this MCQ from the submissions API:
mcq_block = self.runtime.get_block(child_id)
mcq_submission_key = self._get_submission_key(child_id)
try:
value = sub_api.get_submissions(mcq_submission_key, limit=1)[0]["answer"]
except IndexError:
value = None
block['mcqs'].append({
"display_name": mcq_block.display_name_with_default,
"value": value,
"color": self.color_for_value(value) if value is not None else None,
})
try:
hide_questions = self.exclude_questions.get(mentoring_block.url_name, [])
except Exception: # pylint: disable=broad-except-clause
log.exception("Cannot parse exclude_questions setting - probably malformed: %s", self.exclude_questions)
hide_questions = []

for question_number, child_id in enumerate(self._get_problem_questions(mentoring_block), 1):
try:
if question_number in hide_questions:
continue
except TypeError:
log.exception(
"Cannot check question number - expected list of ints got: %s",
hide_questions
)

# Get the student's submitted answer to this MCQ from the submissions API:
mcq_block = self.runtime.get_block(child_id)
mcq_submission_key = self._get_submission_key(child_id)
try:
value = sub_api.get_submissions(mcq_submission_key, limit=1)[0]["answer"]
except IndexError:
value = None

block['mcqs'].append({
"display_name": mcq_block.display_name_with_default,
"value": value,
"color": self.color_for_value(value) if value is not None else None,
})
# If the values are numeric, display an average:
numeric_values = [
float(mcq['value']) for mcq in block['mcqs']
Expand Down Expand Up @@ -384,6 +434,8 @@ def student_view(self, context=None): # pylint: disable=unused-argument
'blocks': blocks,
'display_name': self.display_name,
'visual_repr': visual_repr,
'average_label': self.average_label,
'show_numbers': self.show_numbers,
})

fragment = Fragment(html)
Expand All @@ -406,6 +458,14 @@ def add_error(msg):
except InvalidUrlName as e:
add_error(_(u'Invalid block url_name given: "{bad_url_name}"').format(bad_url_name=unicode(e)))

if data.exclude_questions:
for key, value in data.exclude_questions.iteritems():
if not isinstance(value, list):
add_error(
_(u"Exclude questions is malformed: value for key {key} is {value}, expected list of integers")
.format(key=key, value=value)
)

if data.color_rules:
try:
self.parse_color_rules_str(data.color_rules, ignore_errors=False)
Expand Down
4 changes: 4 additions & 0 deletions problem_builder/public/css/dashboard.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@
.pb-dashboard table .avg-row td.desc {
font-style: italic;
}

.pb-dashboard-visual {
text-align: center;
}
24 changes: 19 additions & 5 deletions problem_builder/templates/html/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,30 @@ <h2>{{display_name}}</h2>
{% for mcq in block.mcqs %}
<tr>
<th class="desc">{{ mcq.display_name }}</th>
<td class="value" {% if mcq.color %}style="border-right-color: {{mcq.color}};"{% endif %}>
{% if mcq.value %}{{ mcq.value }}{% endif %}
<td class="value"
{% if mcq.color %} style="border-right-color: {{mcq.color}};"{% endif %}
{% if not show_numbers %}
{% if mcq.value %} aria-label="Score: {{mcq.value}}" {% else %} aria-label="{% trans 'No value yet' %}" {%endif%}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@e-kolpakov I've never seen anyone try to use aria-label on a td element, and I don't blame you for trying since the spec says it is allowed. However, I wanted to perform a quick implementation test for using aria-label on a td element and I found that only Voiceover will read the aria-label, and only if there is an explicit value in the td element, and it reads both. If the cell is empty, it ignores the aria-label. Testing in NVDA and JAWS revealed that only explicit td values are read. aria-labels are ignored.

I recommend using off-screen text (class=sr) inside the table cells in this use case.

{% endif %}
>
{% if mcq.value and show_numbers %}
{{ mcq.value }}
{% endif %}
</td>
</tr>
{% endfor %}
{% if block.has_average %}
<tr class="avg-row">
<th class="desc">{% trans "Average" %}</th>
<td class="value" {% if block.average_color %}style="border-right-color: {{block.average_color}};"{% endif %}>
{{ block.average|floatformat }}
<th class="desc">{{ average_label }}</th>
<td class="value"
{% if block.average_color %} style="border-right-color: {{block.average_color}};"{% endif %}
{% if not show_numbers %}
{% if block.average %} aria-label="Score: {{block.average|floatformat}}" {% else %} aria-label="{% trans 'No value yet' %}" {%endif%}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@e-kolpakov see above comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@e-kolpakov @antoviaque this is the only a11y issue found in Mark's review. Can you guys submit a PR to fix it asap? Thanks!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sarina Sure! Do you want it this week, or can it be done in next week's sprint? I would prefer the later if possible, as there will also likely be some additional follow-up fixes/improvements from Harvard, this way we could do everything at once. But let me know.

Thanks for the review @cptvitamin

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Next week is fine - "ASAP" as in, "as soon as prioritization possible" :)

On Thu, Apr 30, 2015 at 12:58 AM, Xavier Antoviaque <
notifications@github.com> wrote:

In problem_builder/templates/html/dashboard.html
#16 (comment)
:

           </td>
         </tr>
       {% endfor %}
       {% if block.has_average %}
        <tr class="avg-row">
  •          <th class="desc">{% trans "Average" %}</th>
    
  •          <td class="value" {% if block.average_color %}style="border-right-color: {{block.average_color}};"{% endif %}>
    
  •            {{ block.average|floatformat }}
    
  •          <th class="desc">{{ average_label }}</th>
    
  •          <td class="value"
    
  •              {% if block.average_color %} style="border-right-color: {{block.average_color}};"{% endif %}
    
  •              {% if not show_numbers %}
    
  •                {% if block.average %} aria-label="Score: {{block.average|floatformat}}" {% else %} aria-label="{% trans 'No value yet' %}" {%endif%}
    

@sarina https://github.com/sarina Sure! Do you want it this week, or
can it be done in next week's sprint? I would prefer the later if possible,
as there will also likely be some additional follow-up fixes/improvements
from Harvard, this way we could do everything at once. But let me know.

Thanks for the review @cptvitamin https://github.com/cptvitamin


Reply to this email directly or view it on GitHub
https://github.com/open-craft/problem-builder/pull/16/files#r29403780.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sarina Ok, perfect : ) Thank you!

{% endif %}
>
{% if show_numbers %}
{{ block.average|floatformat }}
{% endif %}
</td>
</tr>
{% endif %}
Expand Down
Loading