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
aee05410
Commit
aee05410
authored
Nov 26, 2014
by
Jonathan Piacenti
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Better handling of JSON.
parent
7f5affef
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
83 additions
and
66 deletions
+83
-66
poll/poll.py
+56
-46
poll/public/handlebars/studio.handlebars
+6
-2
poll/public/html/poll_edit.html
+4
-4
poll/public/js/poll_edit.js
+17
-14
No files found.
poll/poll.py
View file @
aee05410
...
...
@@ -12,6 +12,22 @@ from xblockutils.resources import ResourceLoader
from
.utils
import
process_markdown
# When changing these constants, check the templates as well for places
# where the user is informed about them.
MAX_PARAGRAPH_LEN
=
5000
MAX_URL_LEN
=
1000
MAX_ANSWER_LEN
=
250
# These two don't have mentions in the templates, but will cause error
# messages.
MAX_ANSWERS
=
25
MAX_KEY_LEN
=
100
class
PollBlock
(
XBlock
):
"""
...
...
@@ -195,53 +211,51 @@ class PollBlock(XBlock):
@XBlock.json_handler
def
studio_submit
(
self
,
data
,
suffix
=
''
):
# I wonder if there's something for live validation feedback already.
result
=
{
'success'
:
True
,
'errors'
:
[]}
if
'question'
not
in
data
or
not
data
[
'question'
]:
question
=
data
.
get
(
'question'
,
''
)
.
strip
()[:
MAX_PARAGRAPH_LEN
]
feedback
=
data
.
get
(
'feedback'
,
''
)
.
strip
()[:
MAX_PARAGRAPH_LEN
]
if
not
question
:
result
[
'errors'
]
.
append
(
"You must specify a question."
)
result
[
'success'
]
=
False
answers
=
[]
if
'answers'
not
in
data
or
not
isinstance
(
data
[
'answers'
],
list
):
source_answers
=
[]
result
[
'success'
]
=
False
result
[
'errors'
]
.
append
(
"'answers' is not present, or not a JSON array."
)
else
:
question
=
data
[
'question'
][:
4096
]
if
'feedback'
not
in
data
or
not
data
[
'feedback'
]
.
strip
():
feedback
=
''
else
:
feedback
=
data
[
'feedback'
][:
4096
]
# Need this meta information, otherwise the questions will be
# shuffled by Python's dictionary data type.
poll_order
=
[
key
.
strip
()
.
replace
(
'answer-'
,
''
)
for
key
in
data
.
get
(
'poll_order'
,
[])
]
# Aggressively clean/sanity check answers list.
answers
=
{}
for
key
,
value
in
data
.
items
():
img
=
False
text
=
False
if
key
.
startswith
(
'answer-'
):
text
=
'label'
if
key
.
startswith
(
'img-answer-'
):
img
=
'img'
if
not
(
text
or
img
):
continue
key
=
key
.
replace
(
'answer-'
,
''
)
.
replace
(
'img-'
,
''
)
if
not
key
or
key
.
isspace
():
continue
value
=
value
.
strip
()[:
250
]
if
not
value
or
value
.
isspace
():
continue
update_dict
=
{
img
or
text
:
value
}
if
key
in
answers
:
answers
[
key
]
.
update
(
update_dict
)
continue
if
key
in
poll_order
:
answers
[
key
]
=
update_dict
source_answers
=
data
[
'answers'
]
for
value
in
answers
.
values
():
if
'label'
not
in
value
:
value
[
'label'
]
=
None
if
'img'
not
in
value
:
value
[
'img'
]
=
None
# Set a reasonable limit to the number of answers in a poll.
if
len
(
source_answers
)
>
MAX_ANSWERS
:
result
[
'success'
]
=
False
result
[
'errors'
]
.
append
(
""
)
# Make sure all components are present and clean them.
for
answer
in
source_answers
:
if
not
isinstance
(
answer
,
dict
):
result
[
'success'
]
=
False
result
[
'errors'
]
.
append
(
"Answer {0} not a javascript object!"
.
format
(
answer
))
continue
key
=
answer
.
get
(
'key'
,
''
)
.
strip
()
if
not
key
:
result
[
'success'
]
=
False
result
[
'errors'
]
.
append
(
"Answer {0} contains no key."
.
format
(
answer
))
if
len
(
key
)
>
MAX_KEY_LEN
:
result
[
'success'
]
=
False
result
[
'errors'
]
.
append
(
"Key '{0}' too long."
.
format
(
key
))
img
=
answer
.
get
(
'img'
,
''
)
.
strip
()[:
MAX_URL_LEN
]
label
=
answer
.
get
(
'label'
,
''
)
.
strip
()[:
MAX_ANSWER_LEN
]
if
not
(
img
or
label
):
result
[
'success'
]
=
False
result
[
'errors'
]
.
append
(
"Answer {0} has no text or img. One is needed."
)
answers
.
append
((
key
,
{
'label'
:
label
,
'img'
:
img
}))
if
not
len
(
answers
)
>
1
:
result
[
'errors'
]
.
append
(
...
...
@@ -251,10 +265,6 @@ class PollBlock(XBlock):
if
not
result
[
'success'
]:
return
result
# Need to sort the answers.
answers
=
list
(
answers
.
items
())
answers
.
sort
(
key
=
lambda
x
:
poll_order
.
index
(
x
[
0
]))
self
.
answers
=
answers
self
.
question
=
question
self
.
feedback
=
feedback
...
...
poll/public/handlebars/studio.handlebars
View file @
aee05410
...
...
@@ -11,8 +11,11 @@
<
div
class
=
"poll-move-down"
>&
#
9660
;
<
/div
>
<
/div
>
<
/div
>
<
span
class
=
"tip setting-help"
>
Enter
an
answer
for
the
user
to
select
.
An
answer
must
have
an
image
URL
or
text
,
and
can
have
both
.
<
/span
>
<
a
href
=
"#"
class
=
"button action-button poll-delete-answer"
>
Delete
<
/a
>
<
span
class
=
"tip setting-help"
>
Enter
an
answer
for
the
user
to
select
.
An
answer
must
have
an
image
URL
or
text
,
and
can
have
both
.
(
Text
truncated
at
250
characters
,
Image
URL
at
1000
)
<
/span
>
<
a
href
=
"#"
class
=
"button action-button poll-delete-answer"
onclick
=
"return false;"
>
Delete
<
/a
>
<
/li
>
{{/
each
}}
</script>
\ No newline at end of file
poll/public/html/poll_edit.html
View file @
aee05410
...
...
@@ -8,7 +8,7 @@
<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>
<span
class=
"tip setting-help"
>
Enter the prompt for the user.
(Truncated after 5000 characters)
</span>
</li>
<li
class=
"field comp-setting-entry is-set"
>
<h2><label
for=
"poll-feedback-editor"
>
Feedback
</label></h2>
...
...
@@ -18,7 +18,7 @@
</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.
submitted their response to the poll.
(Truncated after 5000 characters)
</span>
</li>
<li
class=
"field comp-setting-entry is-set"
>
...
...
@@ -34,10 +34,10 @@
<div
class=
"xblock-actions"
>
<ul>
<li
class=
"action-item"
id=
"poll-add-answer"
>
<a
href=
"#"
class=
"button action-button"
class=
"poll-add-answer-link"
>
Add Answer
</a>
<a
href=
"#"
class=
"button action-button"
class=
"poll-add-answer-link"
onclick=
"return false;"
>
Add Answer
</a>
</li>
<li
class=
"action-item"
>
<input
type=
"submit"
class=
"button action-primary save-button"
value=
"Save
"
/>
<input
id=
"poll-submit-options"
type=
"submit"
class=
"button action-primary save-button"
value=
"Save"
onclick=
"return false;
"
/>
</li>
<li
class=
"action-item"
>
<a
href=
"#"
class=
"button cancel-button"
>
Cancel
</a>
...
...
poll/public/js/poll_edit.js
View file @
aee05410
...
...
@@ -52,32 +52,35 @@ function PollEditBlock(runtime, element) {
new_answer
.
fadeOut
(
250
).
fadeIn
(
250
);
});
var
to_disable
=
[
'#poll-add-answer-link'
,
'input[type=submit'
,
'.poll-delete-answer'
];
for
(
var
selector
in
to_disable
)
{
$
(
selector
,
element
).
click
(
function
(
event
)
{
event
.
preventDefault
();
}
)
}
$
(
element
).
find
(
'.cancel-button'
,
element
).
bind
(
'click'
,
function
()
{
runtime
.
notify
(
'cancel'
,
{});
});
$
(
element
).
find
(
'.save-button'
,
element
).
bind
(
'click'
,
function
()
{
var
handlerUrl
=
runtime
.
handlerUrl
(
element
,
'studio_submit'
);
var
data
=
{};
var
poll_ord
er
=
[];
var
data
=
{
'answers'
:
[]
};
var
track
er
=
[];
$
(
'#poll-form input'
,
element
).
each
(
function
(
i
)
{
data
[
this
.
name
]
=
this
.
value
;
if
(
this
.
name
.
indexOf
(
'answer-'
)
==
0
){
poll_order
.
push
(
this
.
name
);
var
key
=
'label'
;
if
(
this
.
name
.
indexOf
(
'answer-'
)
>=
0
){
var
name
=
this
.
name
.
replace
(
'answer-'
,
''
);
if
(
this
.
name
.
indexOf
(
'img-'
)
==
0
){
name
=
name
.
replace
(
'img-'
,
''
);
key
=
'img'
}
if
(
tracker
.
indexOf
(
name
)
==
-
1
){
tracker
.
push
(
name
);
data
[
'answers'
].
push
({
'key'
:
name
})
}
var
index
=
tracker
.
indexOf
(
name
);
data
[
'answers'
][
index
][
key
]
=
this
.
value
;
return
}
data
[
this
.
name
]
=
this
.
value
});
data
[
'title'
]
=
$
(
'#poll-title'
,
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'
])
{
window
.
location
.
reload
(
false
);
...
...
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