Commit dfb4cea9 by Xavier Antoviaque

Merge pull request #9 from open-craft/mtyaka/tip-styles

Redesigned tooltips for LMS theme.
parents 09d8dbd7 2d785c99
...@@ -52,6 +52,7 @@ function MentoringBlock(runtime, element) { ...@@ -52,6 +52,7 @@ function MentoringBlock(runtime, element) {
if (!clickedInside(item_feedback_selector, item_feedback_parent_selector)) { if (!clickedInside(item_feedback_selector, item_feedback_parent_selector)) {
$(item_feedback_selector).not(':hidden').hide(); $(item_feedback_selector).not(':hidden').hide();
$('.choice-tips-container').removeClass('with-tips');
} }
}); });
......
...@@ -3,7 +3,9 @@ ...@@ -3,7 +3,9 @@
function MessageView(element, mentoring) { function MessageView(element, mentoring) {
return { return {
messageDOM: $('.feedback', element), messageDOM: $('.feedback', element),
allChoicesDOM: $('.choice', element),
allPopupsDOM: $('.choice-tips, .feedback', element), allPopupsDOM: $('.choice-tips, .feedback', element),
allPopupContainersDOM: $('.choice-tips-container', element),
allResultsDOM: $('.choice-result', element), allResultsDOM: $('.choice-result', element),
clearPopupEvents: function() { clearPopupEvents: function() {
this.allPopupsDOM.hide(); this.allPopupsDOM.hide();
...@@ -28,6 +30,11 @@ function MessageView(element, mentoring) { ...@@ -28,6 +30,11 @@ function MessageView(element, mentoring) {
popupDOM.css('height', ''); 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(); popupDOM.show();
mentoring.publish_event({ mentoring.publish_event({
...@@ -53,6 +60,8 @@ function MessageView(element, mentoring) { ...@@ -53,6 +60,8 @@ function MessageView(element, mentoring) {
} }
}, },
clearResult: function() { clearResult: function() {
this.allPopupContainersDOM.removeClass('with-tips active');
this.allChoicesDOM.removeClass('correct incorrect');
this.allPopupsDOM.html('').hide(); this.allPopupsDOM.html('').hide();
this.allResultsDOM.removeClass( this.allResultsDOM.removeClass(
'checkmark-incorrect icon-exclamation fa-exclamation checkmark-correct icon-ok fa-check' 'checkmark-incorrect icon-exclamation fa-exclamation checkmark-correct icon-ok fa-check'
...@@ -85,6 +94,7 @@ function MCQBlock(runtime, element) { ...@@ -85,6 +94,7 @@ function MCQBlock(runtime, element) {
if (this.mode === 'assessment') if (this.mode === 'assessment')
return; return;
mentoring = this.mentoring; mentoring = this.mentoring;
var messageView = MessageView(element, mentoring); var messageView = MessageView(element, mentoring);
...@@ -99,14 +109,17 @@ function MCQBlock(runtime, element) { ...@@ -99,14 +109,17 @@ function MCQBlock(runtime, element) {
var choiceTipsCloseDOM; var choiceTipsCloseDOM;
if (result.status === "correct" && choiceInputDOM.val() === result.submission) { if (result.status === "correct" && choiceInputDOM.val() === result.submission) {
choiceDOM.addClass('correct');
choiceResultDOM.addClass('checkmark-correct icon-ok fa-check'); choiceResultDOM.addClass('checkmark-correct icon-ok fa-check');
} }
else if (choiceInputDOM.val() === result.submission || _.isNull(result.submission)) { else if (choiceInputDOM.val() === result.submission || _.isNull(result.submission)) {
choiceDOM.addClass('incorrect');
choiceResultDOM.addClass('checkmark-incorrect icon-exclamation fa-exclamation'); choiceResultDOM.addClass('checkmark-incorrect icon-exclamation fa-exclamation');
} }
if (result.tips && choiceInputDOM.val() === result.submission) { if (result.tips && choiceInputDOM.val() === result.submission) {
mentoring.setContent(choiceTipsDOM, result.tips); mentoring.setContent(choiceTipsDOM, result.tips);
messageView.showMessage(choiceTipsDOM);
} }
choiceTipsCloseDOM = $('.close', choiceTipsDOM); choiceTipsCloseDOM = $('.close', choiceTipsDOM);
...@@ -121,9 +134,6 @@ function MCQBlock(runtime, element) { ...@@ -121,9 +134,6 @@ function MCQBlock(runtime, element) {
messageView.showMessage('<div class="message-content">You have not provided an answer.</div>' + messageView.showMessage('<div class="message-content">You have not provided an answer.</div>' +
'<div class="close icon-remove-sign fa-times-circle"></div>'); '<div class="close icon-remove-sign fa-times-circle"></div>');
} }
else if (result.tips) {
messageView.showMessage(result.tips);
}
}, },
clearResult: function() { clearResult: function() {
...@@ -189,8 +199,10 @@ function MRQBlock(runtime, element) { ...@@ -189,8 +199,10 @@ function MRQBlock(runtime, element) {
if (!hide_results && if (!hide_results &&
(result.completed || choiceInputDOM.prop('checked') || options.max_attempts <= 0)) { (result.completed || choiceInputDOM.prop('checked') || options.max_attempts <= 0)) {
if (choice.completed) { if (choice.completed) {
choiceDOM.addClass('correct');
choiceResultDOM.addClass('checkmark-correct icon-ok fa-check'); choiceResultDOM.addClass('checkmark-correct icon-ok fa-check');
} else if (!choice.completed) { } else if (!choice.completed) {
choiceDOM.addClass('incorrect');
choiceResultDOM.addClass('checkmark-incorrect icon-exclamation fa-exclamation'); 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 { .themed-xblock.mentoring .checkmark-incorrect {
color: #c1373f; color: #c1373f;
} }
.themed-xblock.mentoring .checkmark-correct::before {
content: "\f00c";
}
.themed-xblock.mentoring .checkmark-incorrect::before { .themed-xblock.mentoring .checkmark-incorrect::before {
content: "\f00d"; content: "\f00d";
} }
...@@ -15,4 +29,78 @@ ...@@ -15,4 +29,78 @@
div.course-wrapper section.course-content .themed-xblock.mentoring p:empty { div.course-wrapper section.course-content .themed-xblock.mentoring p:empty {
display: block; display: block;
margin-bottom: 1.41575em; 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 @@ ...@@ -11,7 +11,9 @@
<input class="choice-selector" type="radio" name="{{ self.name }}" value="{{ choice.value }}"{% if self.student_choice == choice.value %} checked{% endif %} /> <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> <span class="choice-text">{{ choice.content|safe }}</span>
</label> </label>
<div class="choice-tips"></div> <div class="choice-tips-container">
<div class="choice-tips"></div>
</div>
</div> </div>
{% endfor %} {% endfor %}
<div class="feedback"></div> <div class="feedback"></div>
......
...@@ -13,7 +13,9 @@ ...@@ -13,7 +13,9 @@
{% if choice.value in self.student_choices %} checked{% endif %} /> {% if choice.value in self.student_choices %} checked{% endif %} />
<span class="choice-text">{{ choice.content|safe }}</span> <span class="choice-text">{{ choice.content|safe }}</span>
</label> </label>
<div class="choice-tips"></div> <div class="choice-tips-container">
<div class="choice-tips"></div>
</div>
</div> </div>
{% endfor %} {% endfor %}
<div class="feedback"></div> <div class="feedback"></div>
......
...@@ -4,40 +4,36 @@ ...@@ -4,40 +4,36 @@
<p>{{ self.question }}</p> <p>{{ self.question }}</p>
</legend> </legend>
<div class="choices-list"> <div class="choices-list">
<div class="choice"> {% for value in '12345' %}
<div class="choice-result fa icon-2x"></div> <div class="choice">
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="1"{% if self.student_choice == '1' %} checked{% endif %} />1</label> <div class="choice-result fa icon-2x"></div>
<span class="low"> - {{ self.low }}</span> <label class="choice-label">
<div class="choice-tips"></div> <input class="choice-selector" type="radio" name="{{ self.name }}" value="{{ value }}"
</div> {% if self.student_choice == value %}checked{% endif %} />
<div class="choice"> {{ value }}
<div class="choice-result fa icon-2x"></div> {% if forloop.first %}
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="2"{% if self.student_choice == '2' %} checked{% endif %} />2</label> <span class="low">- {{ self.low }}</span>
<div class="choice-tips"></div> {% endif %}
</div> {% if forloop.last %}
<div class="choice"> <span class="low">- {{ self.high }}</span>
<div class="choice-result fa icon-2x"></div> {% endif %}
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="3"{% if self.student_choice == '3' %} checked{% endif %} />3</label> </label>
<div class="choice-tips"></div> <div class="choice-tips-container">
</div> <div class="choice-tips"></div>
<div class="choice"> </div>
<div class="choice-result fa icon-2x"></div> </div>
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="4"{% if self.student_choice == '4' %} checked{% endif %} />4</label> {% endfor %}
<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 choice in custom_choices %} {% for choice in custom_choices %}
<div class="choice"> <div class="choice">
<div class="choice-result fa icon-2x"></div> <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> <span class="choice-text">{{ choice.content|safe }}</span>
</label> </label>
<div class="choice-tips"></div> <div class="choice-tips-container">
<div class="choice-tips"></div>
</div>
</div> </div>
{% endfor %} {% endfor %}
<div class="feedback"></div> <div class="feedback"></div>
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
# Imports ########################################################### # Imports ###########################################################
import ddt import ddt
from mock import patch, Mock
from mentoring import MentoringBlock
from .base_test import MentoringBaseTest from .base_test import MentoringBaseTest
...@@ -76,11 +79,11 @@ class MCQBlockTest(MentoringBaseTest): ...@@ -76,11 +79,11 @@ class MCQBlockTest(MentoringBaseTest):
self.assertEqual(mcq1_choices[0].text, 'Yes') self.assertEqual(mcq1_choices[0].text, 'Yes')
self.assertEqual(mcq1_choices[1].text, 'Maybe not') self.assertEqual(mcq1_choices[1].text, 'Maybe not')
self.assertEqual(mcq1_choices[2].text, "I don't understand") 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[1].text, '2')
self.assertEqual(mcq2_choices[2].text, '3') self.assertEqual(mcq2_choices[2].text, '3')
self.assertEqual(mcq2_choices[3].text, '4') 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") self.assertEqual(mcq2_choices[5].text, "I don't want to rate it")
mcq1_choices_input = self._get_inputs(mcq1_choices) mcq1_choices_input = self._get_inputs(mcq1_choices)
...@@ -112,8 +115,13 @@ class MCQBlockTest(MentoringBaseTest): ...@@ -112,8 +115,13 @@ class MCQBlockTest(MentoringBaseTest):
submit.click() submit.click()
self.wait_until_disabled(submit) self.wait_until_disabled(submit)
self.assertEqual(mcq1.find_element_by_css_selector(".feedback").text, 'Great!') mcq1_tips = mcq1.find_element_by_css_selector(".choice-tips .tip p")
self.assertEqual(mcq2.find_element_by_css_selector(".feedback").text, 'Will do better next time...') 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.assertEqual(messages.text, '')
self.assertFalse(messages.is_displayed()) self.assertFalse(messages.is_displayed())
...@@ -125,11 +133,32 @@ class MCQBlockTest(MentoringBaseTest): ...@@ -125,11 +133,32 @@ class MCQBlockTest(MentoringBaseTest):
submit.click() submit.click()
self.wait_until_disabled(submit) self.wait_until_disabled(submit)
self.assertEqual(mcq1.find_element_by_css_selector(".feedback").text, 'Great!') mcq1_tips = mcq1.find_element_by_css_selector(".choice-tips .tip p")
self.assertEqual(mcq2.find_element_by_css_selector(".feedback").text, 'I love good grades.') 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.assertIn('All is good now...\nCongratulations!', messages.text)
self.assertTrue(messages.is_displayed()) 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): def test_mcq_with_comments(self):
mentoring = self.go_to_page('Mcq With Comments 1') mentoring = self.go_to_page('Mcq With Comments 1')
mcq = mentoring.find_element_by_css_selector('fieldset.choices') mcq = mentoring.find_element_by_css_selector('fieldset.choices')
...@@ -231,3 +260,12 @@ class MCQBlockTest(MentoringBaseTest): ...@@ -231,3 +260,12 @@ class MCQBlockTest(MentoringBaseTest):
self.wait_until_disabled(submit) self.wait_until_disabled(submit)
self.assertIn('Congratulations!', messages.text) 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