Commit 0e00e04c by Piotr Mitros

Basic functionality

parent a8536546
"""TO-DO: Write a description of what this XBlock is.""" # coding: utf-8
"""
This is an XBlock designed to allow people to provide feedback on our
course resources.
"""
import pkg_resources import pkg_resources
...@@ -9,62 +14,88 @@ from xblock.fragment import Fragment ...@@ -9,62 +14,88 @@ from xblock.fragment import Fragment
class RateXBlock(XBlock): class RateXBlock(XBlock):
""" """
TO-DO: document what your XBlock does. This is an XBlock -- eventually, hopefully an aside -- which
allows you to rate content in the course. We've wanted this for a
long time, but Dartmouth finally encourage me to start to build
this.
""" """
# Fields are defined on the class. You can access them in your code as mouseover_levels = List(
# self.<fieldname>. default=["Excellent", "Good", "Average", "Fair", "Poor"],
scope=Scope.settings,
help="Names of ratings for Likert-like scale"
)
mouseover_icons = List(
default=[u"😁",u"☺",u"😐",u"☹",u"😟"],
scope=Scope.settings,
help="Names of ratings for Likert-like scale"
)
levels = List( string_prompt = String(
default=0, scope=Scope.settings, default="Please provide us feedback on this section.",
help="Names of ratings", scope=Scope.settings,
help="Freeform user prompt"
) )
prompt = String( likert_prompt = String(
default=0, scope=Scope.settings, default="Please rate your overall experience with this section.",
help="User prompt", scope=Scope.settings,
help="Likert-like scale user prompt"
) )
vote = Integer( user_vote = Integer(
default=-1, scope=Scope.user_state, default=-1, scope=Scope.user_state,
help="How user voted. -1 if didn't vote", help="How user voted. -1 if didn't vote"
) )
vote_aggregate = List( vote_aggregate = List(
default=0, scope=Scope.user_state_summary, default=None, scope=Scope.user_state_summary,
help="A simple counter, to show something happening", help="A list of user votes"
) )
user_feedback = String(default = "", scope=Scope.user_state,
help = "Feedback")
def resource_string(self, path): def resource_string(self, path):
"""Handy helper for getting resources from our kit.""" """Handy helper for getting resources from our kit."""
data = pkg_resources.resource_string(__name__, path) data = pkg_resources.resource_string(__name__, path)
return data.decode("utf8") return data.decode("utf8")
# TO-DO: change this view to display your data your own way.
def student_view(self, context=None): def student_view(self, context=None):
""" """
The primary view of the RateXBlock, shown to students The primary view of the RateXBlock, shown to students
when viewing courses. when viewing courses.
""" """
html = self.resource_string("static/html/rate.html") html = self.resource_string("static/html/rate.html")
frag = Fragment(html.format(self=self)) scale_item = u'<span class="rate_likert_rating rate_rating_{i}" title="{level}">{icon}</span>'
scale = u"".join(scale_item.format(level=level, icon=icon, i=i) for (level,icon,i) in zip(self.mouseover_levels, self.mouseover_icons, range(len(self.mouseover_icons))))
frag = Fragment(html.format(self=self, scale=scale))
frag.add_css(self.resource_string("static/css/rate.css")) frag.add_css(self.resource_string("static/css/rate.css"))
frag.add_javascript(self.resource_string("static/js/src/rate.js")) frag.add_javascript(self.resource_string("static/js/src/rate.js"))
frag.initialize_js('RateXBlock') frag.initialize_js('RateXBlock')
return frag return frag
# TO-DO: change this handler to perform your own actions. You may need more
# than one handler, or you may not need any handlers at all.
@XBlock.json_handler @XBlock.json_handler
def increment_count(self, data, suffix=''): def vote(self, data, suffix=''):
""" """
An example handler, which increments the data. Handle voting
""" """
# Just to show data coming in... # Make sure we're initialized
assert data['hello'] == 'world' if not self.vote_aggregate:
self.vote_aggregate = [0]*len(self.mouseover_levels)
# Remove old vote if we voted before
if self.user_vote != -1:
self.vote_aggregate[self.vote] -= 1
self.count += 1 self.user_vote = data['vote']
return {"count": self.count} self.vote_aggregate[self.user_vote] += 1
return {"success": True}
@XBlock.json_handler
def feedback(self, data, suffix=''):
self.user_feedback = data['feedback']
# TO-DO: change this to create the scenarios you'd like to see in the # TO-DO: change this to create the scenarios you'd like to see in the
# workbench while developing your XBlock. # workbench while developing your XBlock.
......
/* CSS for RateXBlock */ /* CSS for RateXBlock */
.rate_block .count { .rate_block {
text-align: center;
max-width: 400px;
border-width: 1px;
border-style: solid;
border-color: rgba(0,0,0,0.1);
padding: 10px
}
.rate_block .rate_header {
font-weight: bold; font-weight: bold;
font-size: large;
} }
.rate_block p { .rate_block .rate_likert_rating {
cursor: pointer; cursor: pointer;
} }
.rate_block .rate_string_input {
margin-bottom: 2em;
}
\ No newline at end of file
<div class="rate_block"> <div class="rate_block">
<p>RateXBlock: count is now <div class="rate_header">{self.string_prompt}</div>
<span class='count'>{self.count}</span> (click me to increment). <div class="rate_string_input">
</p> <textarea class="rate_string_area" rows="4" cols="50">{self.user_feedback}</textarea>
</div>
<div class="rate_likert_header">{self.likert_prompt}</div>
<div class="rate_likert_scale">{scale}</div>
</div> </div>
/* Javascript for RateXBlock. */ /* Javascript for RateXBlock. */
function RateXBlock(runtime, element) { var x;
function updateCount(result) {
$('.count', element).text(result.count);
}
var handlerUrl = runtime.handlerUrl(element, 'increment_count'); function RateXBlock(runtime, element) {
var vote_handler = runtime.handlerUrl(element, 'vote');
var feedback_handler = runtime.handlerUrl(element, 'feedback');
$('p', element).click(function(eventObject) { $('.rate_likert_rating', element).click(function(eventObject) {
vote_class = eventObject.currentTarget.className.split(' ').find(function f(x) { return x.startsWith("rate_rating_") } )
vote = parseInt(vote_class.split('_')[2]);
alert(vote);
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: handlerUrl, url: vote_handler,
data: JSON.stringify({"hello": "world"}), data: JSON.stringify({"vote": vote_class}),
success: updateCount
}); });
}); });
$(function ($) { $('.rate_string_area', element).change(function(eventObject) {
/* Here's where you'd do things on page load. */ x = eventObject
alert(eventObject.currentTarget.value);
$.ajax({
type: "POST",
url: feedback_handler,
data: JSON.stringify({"feedback": eventObject.currentTarget.value}),
});
}); });
} }
/*
function updateCount(result) {
$('.count', element).text(result.count);
}
*/
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