Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xblock-poll
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
xblock-poll
Commits
db084466
Commit
db084466
authored
Nov 19, 2014
by
Jonathan Piacenti
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Several CSS fixes. Dropped title field. Fixed markdown handling. Added Feedback.
parent
13de8d1b
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
88 additions
and
39 deletions
+88
-39
poll/poll.py
+42
-21
poll/public/css/poll.css
+13
-4
poll/public/css/poll_edit.css
+4
-3
poll/public/handlebars/results.handlebars
+15
-2
poll/public/html/poll.html
+0
-1
poll/public/html/poll_edit.html
+12
-7
poll/public/js/poll_edit.js
+2
-1
No files found.
poll/poll.py
View file @
db084466
"""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 question
s
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
...
...
poll/public/css/poll.css
View file @
db084466
...
...
@@ -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
poll/public/css/poll_edit.css
View file @
db084466
...
...
@@ -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
poll/public/handlebars/results.handlebars
View file @
db084466
...
...
@@ -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
poll/public/html/poll.html
View file @
db084466
...
...
@@ -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 %}
...
...
poll/public/html/poll_edit.html
View file @
db084466
...
...
@@ -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"
/>
<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=
"poll-question-editor-container"
>
<textarea
class=
"input setting-input"
name=
"question"
id=
"poll-question-editor"
>
{{question}}
</textarea>
</div>
<span
class=
"tip setting-help"
>
Enter a title to act as the header for this Poll
.
</span>
<span
class=
"tip setting-help"
>
Enter the prompt for the user
.
</span>
</li>
<li
class=
"field comp-setting-entry is-set"
>
<h2><label
for=
"question-editor"
>
Question/Prompt
</label></h2>
<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=
"question
-editor-container"
>
<textarea
class=
"input setting-input"
name=
"question"
id=
"question-editor"
>
{{question|safe
}}
</textarea>
<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>
...
...
poll/public/js/poll_edit.js
View file @
db084466
...
...
@@ -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'
])
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment