Commit db084466 by Jonathan Piacenti

Several CSS fixes. Dropped title field. Fixed markdown handling. Added Feedback.

parent 13de8d1b
"""TO-DO: Write a description of what this XBlock is."""
from collections import OrderedDict
import bleach
from django.template import Template, Context
from bleach import clean
from markdown import markdown
import pkg_resources
......@@ -12,20 +13,31 @@ from xblock.fields import Scope, List, String, Dict
from xblock.fragment import Fragment
ALLOWED_TAGS = {
'h1': [], 'h2': [], 'h3': [], 'h4': [], 'h5': [], 'h6': [],
'a': ['target', 'href', 'class'], 'strong': [], 'em': [], 'blockquote': [],
'pre': [], 'li': [], 'ul': [], 'ol': [], 'code': ['class'], 'p': [],
}
def process_markdown(raw_text):
return bleach.clean(markdown(raw_text), tags=ALLOWED_TAGS, strip_comments=False)
class PollBlock(XBlock):
"""
Poll XBlock. Allows a teacher to poll users, and presents the results so
far of the poll to the user when finished.
"""
title = String(default='Poll')
question = String(default='What is your favorite color?')
answers = List(
default=(('Red', 'Red'), ('Blue', 'Blue'), ('Green', 'Green'),
('Other', 'Other')),
scope=Scope.settings, help="The questions on this poll."
scope=Scope.settings, help="The question on this poll."
)
feedback = String(help="Text to display after the user votes.")
tally = Dict(default={'Red': 0, 'Blue': 0, 'Green': 0, 'Other': 0},
scope=Scope.content,
scope=Scope.user_state_summary,
help="Total tally of answers from students.")
choice = String(scope=Scope.user_state, help="The student's answer")
......@@ -36,7 +48,12 @@ class PollBlock(XBlock):
@XBlock.json_handler
def get_results(self, data, suffix=''):
return {'question': markdown(clean(self.question)), 'tally': self.tally_detail()}
detail, total = self.tally_detail()
print process_markdown(self.feedback)
return {
'question': process_markdown(self.question), 'tally': detail,
'total': total, 'feedback': process_markdown(self.feedback),
}
def tally_detail(self):
"""
......@@ -52,7 +69,8 @@ class PollBlock(XBlock):
'answer': value,
'key': key,
'top': False,
'choice': False
'choice': False,
'last': False,
})
total += tally[-1]['count']
......@@ -71,7 +89,8 @@ class PollBlock(XBlock):
if tally:
# Mark the top item to make things easier for Handlebars.
tally[0]['top'] = True
return tally
tally[-1]['last'] = True
return tally, total
def get_choice(self):
"""
......@@ -98,17 +117,20 @@ class PollBlock(XBlock):
choice = self.get_choice()
print bleach.ALLOWED_ATTRIBUTES
context.update({
'choice': choice,
# Offset so choices will always be True.
'answers': self.answers,
'question': markdown(clean(self.question)),
'title': self.title,
'question': process_markdown(self.question),
'feedback': process_markdown(self.feedback),
'js_template': js_template,
})
if self.choice:
context.update({'tally': self.tally_detail()})
detail, total = self.tally_detail()
context.update({'tally': detail, 'total': total})
context = Context(context)
html = self.resource_string("public/html/poll.html")
......@@ -134,8 +156,8 @@ class PollBlock(XBlock):
js_template = self.resource_string('/public/handlebars/studio.handlebars')
context.update({
'question': clean(self.question),
'title': self.title,
'question': self.question,
'feedback': self.feedback,
'js_template': js_template
})
context = Context(context)
......@@ -155,14 +177,15 @@ class PollBlock(XBlock):
def studio_submit(self, data, suffix=''):
# I wonder if there's something for live validation feedback already.
result = {'success': True, 'errors': []}
if 'title' not in data or not data['title']:
# This can be blank, if it needs to be.
title = ''
else:
title = data['title'][:200]
if 'question' not in data or not data['question']:
result['errors'].append("You must specify a question.")
result['success'] = False
else:
question = data['question'][:4096]
if 'feedback' not in data or not data['feedback']:
feedback = ''
else:
feedback = data['feedback'][:4096]
# Need this meta information, otherwise the questions will be
# shuffled by Python's dictionary data type.
......@@ -182,7 +205,6 @@ class PollBlock(XBlock):
continue
if key in poll_order:
answers.append((key, value))
self.title = title
if not len(answers) > 1:
result['errors'].append(
......@@ -196,9 +218,8 @@ class PollBlock(XBlock):
answers.sort(key=lambda x: poll_order.index(x[0]), reverse=True)
self.answers = answers
self.question = data['question']
print answers
self.question = question
self.feedback = feedback
tally = self.tally
......
......@@ -18,7 +18,7 @@
display: table-cell;
width: 100%;
vertical-align: middle;
padding-bottom: .2em;
background-color: #fafbfc;
}
ul.poll-answers, ul.poll-answers-results {
......@@ -28,6 +28,10 @@ ul.poll-answers, ul.poll-answers-results {
li.poll-answer {
display: block;
border-bottom-width: .5em;
}
li.poll-spacer {
height: .25em;
}
ul.poll-answers-results {
......@@ -47,16 +51,20 @@ li.poll-result {
.poll-percent-container {
display: table-cell;
font-weight: bold;
text-align: left;
padding-left: .2em;
vertical-align: middle;
}
.poll-result-answer-container {
.poll-percent-display {
font-weight: bold;
}
.poll-top-choice {
color: #e37222;
}
.poll-footnote {
margin-top: 1em;
margin-bottom: 1em;
}
\ No newline at end of file
......@@ -3,11 +3,11 @@
.poll-delete-answer {
float: right;
}
#question-editor-container{
#poll-question-editor-container, #poll-feedback-editor-container{
width: 100%;
text-align: center;
}
#question-editor{
#poll-question-editor, #poll-feedback-editor{
width: 98%;
height: 7em;
text-align: left;
......@@ -20,7 +20,7 @@
padding: 10px;
}
h2 label {
label.poll-label {
font-weight: bold;
font-size: 16pt;
}
\ No newline at end of file
......@@ -4,7 +4,7 @@
{{#each tally}}
<li class="poll-result">
<div class="poll-result-input-container">
<input id="answer-{{key}}" type="radio" disabled {{#if choice}}checked="True"{{/if}} />
<input id="answer-{{key}}" type="radio" disabled {{#choice}}checked="True"{{/choice}} />
</div>
<div class="percentage-gauge-container">
<div class="percentage-gauge" style="width:{{percent}}%;">
......@@ -12,9 +12,21 @@
</div>
</div>
<div class="poll-percent-container">
<span class="poll-percent-display{{#if top}} poll-top-choice{{/if}}">{{percent}}%</span>
<span class="poll-percent-display{{#top}} poll-top-choice{{/top}}">{{percent}}%</span>
</div>
</li>
{{^last}}
<li class="poll-spacer">
</li>
{{/last}}
{{/each}}
</ul>
<input type="submit" name="poll-submit" onclick="return false;" value="Submit" disabled>
<div class="poll-footnote"><small>Results gathered from {{total}} respondent(s).</small></div>
{{#feedback}}
<hr />
<div class="poll-feedback">
{{{this}}}
</div>
{{/feedback}}
</script>
\ No newline at end of file
......@@ -3,7 +3,6 @@
{# If no form is present, the Javascript will load the results instead. #}
{% if not choice %}
<form>
<h2>{{ title }}</h2>
{{question|safe}}
<ul class="poll-answers">
{% for key, answer in answers %}
......
......@@ -3,18 +3,23 @@
<form id="poll-form">
<ul class="list-input settings-list" id="poll-line-items">
<li class="field comp-setting-entry is-set">
<div class="wrapper-comp-setting">
<label class="label setting-label" for="poll-title">Title</label>
<input class="input setting-input" name="title" id="poll-title" value="{{title}}" type="text" />
</div>
<span class="tip setting-help">Enter a title to act as the header for this Poll.</span>
</li>
<li class="field comp-setting-entry is-set">
<h2><label for="question-editor">Question/Prompt</label></h2>
<h2><label for="poll-question-editor">Question/Prompt</label></h2>
<a href="//daringfireball.net/projects/markdown/syntax" target="_blank">Markdown Syntax</a> is supported.
<div id="question-editor-container">
<textarea class="input setting-input" name="question" id="question-editor">{{question|safe}}</textarea>
<div id="poll-question-editor-container">
<textarea class="input setting-input" name="question" id="poll-question-editor">{{question}}</textarea>
</div>
<span class="tip setting-help">Enter the prompt for the user.</span>
</li>
<li class="field comp-setting-entry is-set">
<h2><label for="poll-feedback-editor">Feedback</label></h2>
<a href="//daringfireball.net/projects/markdown/syntax" target="_blank">Markdown Syntax</a> is supported.
<div id="poll-feedback-editor-container">
<textarea class="input setting-input" name="feedback" id="poll-feedback-editor">{{feedback}}</textarea>
</div>
<span class="tip setting-help">
This text will be displayed for the user as some extra feedback after they have
submitted their response to the poll.
</span>
</li>
<li class="field comp-setting-entry is-set">
<p>
......
......@@ -47,7 +47,8 @@ function PollEditBlock(runtime, element) {
}
});
data['title'] = $('#poll-title', element).val();
data['question'] = $('#question-editor', element).val();
data['question'] = $('#poll-question-editor', element).val();
data['feedback'] = $('#poll-feedback-editor', element).val();
data['poll_order'] = poll_order;
function check_return(data) {
if (data['success']) {
......
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