Commit 2d785c99 by Matjaz Gregoric

Redesigned tooltips for LMS theme.

This changes the look of MCQ/MRQ tooltips to better fit into the LMS design.
parent 67048650
......@@ -52,6 +52,7 @@ function MentoringBlock(runtime, element) {
if (!clickedInside(item_feedback_selector, item_feedback_parent_selector)) {
$(item_feedback_selector).not(':hidden').hide();
$('.choice-tips-container').removeClass('with-tips');
}
});
......
......@@ -3,7 +3,9 @@
function MessageView(element, mentoring) {
return {
messageDOM: $('.feedback', element),
allChoicesDOM: $('.choice', element),
allPopupsDOM: $('.choice-tips, .feedback', element),
allPopupContainersDOM: $('.choice-tips-container', element),
allResultsDOM: $('.choice-result', element),
clearPopupEvents: function() {
this.allPopupsDOM.hide();
......@@ -28,6 +30,11 @@ function MessageView(element, mentoring) {
popupDOM.css('height', '');
}
var container = popupDOM.parent('.choice-tips-container');
if (container.length) {
this.allPopupContainersDOM.addClass('with-tips').removeClass('active');
container.addClass('active');
}
popupDOM.show();
mentoring.publish_event({
......@@ -53,6 +60,8 @@ function MessageView(element, mentoring) {
}
},
clearResult: function() {
this.allPopupContainersDOM.removeClass('with-tips active');
this.allChoicesDOM.removeClass('correct incorrect');
this.allPopupsDOM.html('').hide();
this.allResultsDOM.removeClass(
'checkmark-incorrect icon-exclamation fa-exclamation checkmark-correct icon-ok fa-check'
......@@ -85,6 +94,7 @@ function MCQBlock(runtime, element) {
if (this.mode === 'assessment')
return;
mentoring = this.mentoring;
var messageView = MessageView(element, mentoring);
......@@ -99,14 +109,17 @@ function MCQBlock(runtime, element) {
var choiceTipsCloseDOM;
if (result.status === "correct" && choiceInputDOM.val() === result.submission) {
choiceDOM.addClass('correct');
choiceResultDOM.addClass('checkmark-correct icon-ok fa-check');
}
else if (choiceInputDOM.val() === result.submission || _.isNull(result.submission)) {
choiceDOM.addClass('incorrect');
choiceResultDOM.addClass('checkmark-incorrect icon-exclamation fa-exclamation');
}
if (result.tips && choiceInputDOM.val() === result.submission) {
mentoring.setContent(choiceTipsDOM, result.tips);
messageView.showMessage(choiceTipsDOM);
}
choiceTipsCloseDOM = $('.close', choiceTipsDOM);
......@@ -121,9 +134,6 @@ function MCQBlock(runtime, element) {
messageView.showMessage('<div class="message-content">You have not provided an answer.</div>' +
'<div class="close icon-remove-sign fa-times-circle"></div>');
}
else if (result.tips) {
messageView.showMessage(result.tips);
}
},
clearResult: function() {
......@@ -189,8 +199,10 @@ function MRQBlock(runtime, element) {
if (!hide_results &&
(result.completed || choiceInputDOM.prop('checked') || options.max_attempts <= 0)) {
if (choice.completed) {
choiceDOM.addClass('correct');
choiceResultDOM.addClass('checkmark-correct icon-ok fa-check');
} else if (!choice.completed) {
choiceDOM.addClass('incorrect');
choiceResultDOM.addClass('checkmark-incorrect icon-exclamation fa-exclamation');
}
......
.themed-xblock.mentoring .questionnaire .choice-result {
display: table-cell;
}
.themed-xblock.mentoring .choice-result::before {
content: "";
display: block;
width: 36px;
}
.themed-xblock.mentoring .checkmark-incorrect {
color: #c1373f;
}
.themed-xblock.mentoring .checkmark-correct::before {
content: "\f00c";
}
.themed-xblock.mentoring .checkmark-incorrect::before {
content: "\f00d";
}
......@@ -15,4 +29,78 @@
div.course-wrapper section.course-content .themed-xblock.mentoring p:empty {
display: block;
margin-bottom: 1.41575em;
}
.themed-xblock.mentoring .choices-list {
display: table;
width: 100%;
border-spacing: 0;
}
.themed-xblock.mentoring .choice-label {
display: table-cell;
vertical-align: middle;
width: 100%;
padding-bottom: 10px;
padding-top: 2px;
}
.themed-xblock.mentoring .choice-label span.low {
line-height: inherit;
}
.themed-xblock.mentoring .choice-result,
.themed-xblock.mentoring .choice-label,
.themed-xblock.mentoring .choice-tips-container {
vertical-align: top;
}
.themed-xblock.mentoring .choice-tips {
position: relative;
}
.themed-xblock.mentoring .questionnaire .choice {
display: table-row;
}
.themed-xblock.mentoring .questionnaire .feedback {
min-height: 100%;
border-left: 2px solid #ddd;
}
.themed-xblock.mentoring .questionnaire .choice-tips,
.themed-xblock.mentoring .questionnaire .feedback {
color: #3c3c3c;
background: transparent;
font-family: inherit;
font-size: inherit;
opacity: 1;
padding: 0 20px;
}
.themed-xblock.mentoring .questionnaire .choice-tips-container {
display: table-cell;
}
.themed-xblock.mentoring .questionnaire .choice-tips p,
.themed-xblock.mentoring .questionnaire .feedback p {
color: #3c3c3c;
}
.themed-xblock.mentoring .questionnaire .choice-tips .close,
.themed-xblock.mentoring .questionnaire .feedback .close {
display: none;
}
.themed-xblock.mentoring .choice .choice-tips-container.with-tips {
border-left: 2px solid #ddd;
}
.themed-xblock.mentoring .choice.correct .choice-tips-container.active {
border-color: #629b2b;
}
.themed-xblock.mentoring .choice.incorrect .choice-tips-container.active {
border-color: #c1373f;
}
\ No newline at end of file
......@@ -11,7 +11,9 @@
<input class="choice-selector" type="radio" name="{{ self.name }}" value="{{ choice.value }}"{% if self.student_choice == choice.value %} checked{% endif %} />
<span class="choice-text">{{ choice.content|safe }}</span>
</label>
<div class="choice-tips"></div>
<div class="choice-tips-container">
<div class="choice-tips"></div>
</div>
</div>
{% endfor %}
<div class="feedback"></div>
......
......@@ -13,7 +13,9 @@
{% if choice.value in self.student_choices %} checked{% endif %} />
<span class="choice-text">{{ choice.content|safe }}</span>
</label>
<div class="choice-tips"></div>
<div class="choice-tips-container">
<div class="choice-tips"></div>
</div>
</div>
{% endfor %}
<div class="feedback"></div>
......
......@@ -4,40 +4,36 @@
<p>{{ self.question }}</p>
</legend>
<div class="choices-list">
<div class="choice">
<div class="choice-result fa icon-2x"></div>
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="1"{% if self.student_choice == '1' %} checked{% endif %} />1</label>
<span class="low"> - {{ self.low }}</span>
<div class="choice-tips"></div>
</div>
<div class="choice">
<div class="choice-result fa icon-2x"></div>
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="2"{% if self.student_choice == '2' %} checked{% endif %} />2</label>
<div class="choice-tips"></div>
</div>
<div class="choice">
<div class="choice-result fa icon-2x"></div>
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="3"{% if self.student_choice == '3' %} checked{% endif %} />3</label>
<div class="choice-tips"></div>
</div>
<div class="choice">
<div class="choice-result fa icon-2x"></div>
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="4"{% if self.student_choice == '4' %} checked{% endif %} />4</label>
<div class="choice-tips"></div>
</div>
<div class="choice">
<div class="choice-result fa icon-2x"></div>
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="5"{% if self.student_choice == '5' %} checked{% endif %} />5</label>
<span class="low"> - {{ self.high }}</span>
<div class="choice-tips"></div>
</div>
{% for value in '12345' %}
<div class="choice">
<div class="choice-result fa icon-2x"></div>
<label class="choice-label">
<input class="choice-selector" type="radio" name="{{ self.name }}" value="{{ value }}"
{% if self.student_choice == value %}checked{% endif %} />
{{ value }}
{% if forloop.first %}
<span class="low">- {{ self.low }}</span>
{% endif %}
{% if forloop.last %}
<span class="low">- {{ self.high }}</span>
{% endif %}
</label>
<div class="choice-tips-container">
<div class="choice-tips"></div>
</div>
</div>
{% endfor %}
{% for choice in custom_choices %}
<div class="choice">
<div class="choice-result fa icon-2x"></div>
<label><input type="radio" name="{{ self.name }}" value="{{ choice.value }}"{% if self.student_choice == '{{ choice.value }}' %} checked{% endif %} />
<label class="choice-label">
<input class="choice-selector" type="radio" name="{{ self.name }}" value="{{ choice.value }}"
{% if self.student_choice == '{{ choice.value }}' %} checked{% endif %} />
<span class="choice-text">{{ choice.content|safe }}</span>
</label>
<div class="choice-tips"></div>
<div class="choice-tips-container">
<div class="choice-tips"></div>
</div>
</div>
{% endfor %}
<div class="feedback"></div>
......
......@@ -21,6 +21,9 @@
# Imports ###########################################################
import ddt
from mock import patch, Mock
from mentoring import MentoringBlock
from .base_test import MentoringBaseTest
......@@ -76,11 +79,11 @@ class MCQBlockTest(MentoringBaseTest):
self.assertEqual(mcq1_choices[0].text, 'Yes')
self.assertEqual(mcq1_choices[1].text, 'Maybe not')
self.assertEqual(mcq1_choices[2].text, "I don't understand")
self.assertEqual(mcq2_choices[0].text, '1')
self.assertEqual(mcq2_choices[0].text, '1 - Not good at all')
self.assertEqual(mcq2_choices[1].text, '2')
self.assertEqual(mcq2_choices[2].text, '3')
self.assertEqual(mcq2_choices[3].text, '4')
self.assertEqual(mcq2_choices[4].text, '5')
self.assertEqual(mcq2_choices[4].text, '5 - Extremely good')
self.assertEqual(mcq2_choices[5].text, "I don't want to rate it")
mcq1_choices_input = self._get_inputs(mcq1_choices)
......@@ -112,8 +115,13 @@ class MCQBlockTest(MentoringBaseTest):
submit.click()
self.wait_until_disabled(submit)
self.assertEqual(mcq1.find_element_by_css_selector(".feedback").text, 'Great!')
self.assertEqual(mcq2.find_element_by_css_selector(".feedback").text, 'Will do better next time...')
mcq1_tips = mcq1.find_element_by_css_selector(".choice-tips .tip p")
mcq2_tips = mcq2.find_element_by_css_selector(".choice-tips .tip p")
self.assertEqual(mcq1_tips.text, 'Great!')
self.assertTrue(mcq1_tips.is_displayed())
self.assertEqual(mcq2_tips.text, 'Will do better next time...')
self.assertTrue(mcq2_tips.is_displayed())
self.assertEqual(messages.text, '')
self.assertFalse(messages.is_displayed())
......@@ -125,11 +133,32 @@ class MCQBlockTest(MentoringBaseTest):
submit.click()
self.wait_until_disabled(submit)
self.assertEqual(mcq1.find_element_by_css_selector(".feedback").text, 'Great!')
self.assertEqual(mcq2.find_element_by_css_selector(".feedback").text, 'I love good grades.')
mcq1_tips = mcq1.find_element_by_css_selector(".choice-tips .tip p")
mcq2_tips = mcq2.find_element_by_css_selector(".choice-tips .tip p")
self.assertEqual(mcq1_tips.text, 'Great!')
self.assertTrue(mcq1_tips.is_displayed())
self.assertEqual(mcq2_tips.text, 'I love good grades.')
self.assertTrue(mcq2_tips.is_displayed())
self.assertIn('All is good now...\nCongratulations!', messages.text)
self.assertTrue(messages.is_displayed())
# The choice tip containers should have the with-tips class.
mcq1_tip_containers = mcq1.find_elements_by_css_selector('.choice-tips-container.with-tips')
mcq2_tip_containers = mcq2.find_elements_by_css_selector('.choice-tips-container.with-tips')
self.assertEqual(len(mcq1_tip_containers), 3)
self.assertEqual(len(mcq2_tip_containers), 6)
# Clicking outside the tips should hide the tips and clear the with-tips class.
mcq1.find_element_by_css_selector('.mentoring .question-title').click()
mcq2.find_element_by_css_selector('.mentoring .question-title').click()
mcq1_tip_containers = mcq1.find_elements_by_css_selector('.choice-tips-container.with-tips')
mcq2_tip_containers = mcq2.find_elements_by_css_selector('.choice-tips-container.with-tips')
self.assertEqual(len(mcq1_tip_containers), 0)
self.assertEqual(len(mcq2_tip_containers), 0)
self.assertFalse(mcq1_tips.is_displayed())
self.assertFalse(mcq2_tips.is_displayed())
def test_mcq_with_comments(self):
mentoring = self.go_to_page('Mcq With Comments 1')
mcq = mentoring.find_element_by_css_selector('fieldset.choices')
......@@ -231,3 +260,12 @@ class MCQBlockTest(MentoringBaseTest):
self.wait_until_disabled(submit)
self.assertIn('Congratulations!', messages.text)
@patch.object(MentoringBlock, 'get_theme', Mock(return_value={'package': 'mentoring',
'locations': ['public/themes/lms.css']}))
class MCQBlockAprosThemeTest(MCQBlockTest):
"""
Test MRQ/MCQ questions without the LMS theme which is on by default.
"""
pass
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