Commit d261ea4a by swdanielli

add some tooltips and code documentation

parent b8a79af5
"""TO-DO: Write a description of what this XBlock is."""
import json, string, random, re
import pkg_resources
......@@ -24,27 +22,58 @@ from webob.response import Response
class RecommenderXBlock(XBlock):
"""
This XBlock will show a set of recommended resources provided by students.
This XBlock will show a set of recommended resources which may be helpful to students solving a given problem.
The resources are provided and edited by students; they can also vote for useful resources and flag problematic ones.
"""
# Scope-wide. List of JSON objects corresponding to recommendations combine XML and user.
default_recommendations = List(help="List of help resources", default=[], scope=Scope.content)
# Block-wide. List of JSON objects corresponding to recommendations as defined in XML.
default_recommendations = List(help="List of default help resources", default=[], scope=Scope.content)
# A list of default recommenations, it is a JSON object across all users, all runs of a course, for this xblock.
# Usage: default_recommendations[index] = {
# "id": (Integer) id of a resource,
# "title": (String) title of a resource; a 1-3 sentence summary of a resource
# "upvotes" : (Integer) number of upvotes,
# "downvotes" : (Integer) number of downvotes,
# "url" : (String) the url of a resource,
# "description" : (String) the url of a resource's screenshot,
# "descriptionText" : (String) a paragraph of description/summary of a resource }
recommendations = List(help="List of help resources", default=[], scope=Scope.user_state_summary)
# Block-wide. Dict of JSON objects corresponding to configurations of amazon web service for file uploading.
s3_configuration = Dict(help="List of help resources", default={}, scope=Scope.user_state_summary)
# List of deleted recommendation ID.
deletedRecommendationIds = List(help="List of help resources", default=[], scope=Scope.user_state_summary)
# Ids of upvoted resources for this particular user
upvotedIds = List(help="List of items user gave upvote to", default=[], scope=Scope.user_state)
# Ids of downvoted resources for this particular user
downvotedIds = List(help="List of items user gave downvote to", default=[], scope=Scope.user_state)
# Ids of flagged resource (problematic resource) for this particular user
flaggedIds = List(help="List of items user flagged to", default=[], scope=Scope.user_state)
# Reasons of flagged resource (problematic resource) for this particular user
flaggedReasons = List(help="List of reasons of items user flagged to", default=[], scope=Scope.user_state)
# A list of recommenations provided by students, it is a JSON object aggregated across many users of a single block.
# Usage: the same as default_recommendations
s3_configuration = Dict(help="Dictionary of Amazon S3 information", default={}, scope=Scope.user_state_summary)
# A dictionary of Amazon S3 information for file uploading, it is a JSON object aggregated across many users of a single block.
# Usage: s3_configuration = {
# "aws_access_key": (String) access key of Amazon S3 account
# "aws_secret_key": (String) secret key of Amazon S3 account
# "bucketName": (String) Bucket name of Amazon S3 account
# "uploadedFileDir": (String) The path (relative to root directory) of the directory for storing uploaded files }
deletedRecommendationIds = List(help="List of deleted resources' ID", default=[], scope=Scope.user_state_summary)
# A list of deleted recommendations' ids, it is a JSON object aggregated across many users of a single block.
# Usage: deletedRecommendationIds[index] = (Integer) id of a deleted resource
upvotedIds = List(help="List of resources' ids which user upvoted to", default=[], scope=Scope.user_state)
# A list of recommendations' ids which user upvoted to; it is a JSON object for one user, for one block, and for one run of a course.
# Usage: upvotedIds[index] = (Integer) id of a resource which was upvoted by the current user
downvotedIds = List(help="List of resources' ids which user downvoted to", default=[], scope=Scope.user_state)
# A list of recommendations' ids which user downvoted to; it is a JSON object for one user, for one block, and for one run of a course.
# Usage: downvotedIds[index] = (Integer) id of a resource which was downvoted by the current user
flaggedIds = List(help="List of problematic resources' ids which user flagged to", default=[], scope=Scope.user_state)
# A list of problematic recommendations' ids which user flagged to; it is a JSON object for one user, for one block, and for one run of a course.
# Usage: flaggedIds[index] = (Integer) id of a problematic resource which was flagged by the current user
# Reasons of flagged resource (problematic resource) for this particular user
flaggedReasons = List(help="List of reasons why the corresponding resources were flagged by user as problematic", default=[], scope=Scope.user_state)
# A list of reasons why the corresponding resources were flagged by user as problematic; it is a JSON object for one user, for one block, and for one run of a course.
# Usage: flaggedReasons[index] = (String) reason why the corresponding resource was flagged by the current user as problematic
template_lookup = None
resource_content_fields = ['url', 'title', 'description', 'descriptionText']
# the dictionary keys for storing the content of a recommendation
def resource_string(self, path):
"""Handy helper for getting static file resources from our Python package."""
......@@ -76,6 +105,12 @@ class RecommenderXBlock(XBlock):
return idx
return -1
def checkRedundancy(self, url1, url2):
"""
Check redundant resource by comparing the url.
"""
return url1.split('#')[0].split('%23')[0] == url2.split('#')[0].split('%23')[0]
@XBlock.json_handler
def delete_resource(self, data, suffix=''):
"""
......@@ -292,7 +327,7 @@ class RecommenderXBlock(XBlock):
# check url for redundancy
for recommendation in self.recommendations:
if recommendation['url'] == data['url']:
if self.checkRedundancy(recommendation['url'], data['url']):
result['error'] = 'redundant resource'
tracker.emit('add_resource', result)
result['Success'] = False
......@@ -337,9 +372,9 @@ class RecommenderXBlock(XBlock):
result['old_' + field] = self.recommendations[idx][field]
result[field] = data[field]
# check url for redundancy
if self.recommendations[idx]['url'] != data['url']:
if not( self.checkRedundancy(self.recommendations[idx]['url'], data['url']) ):
for recommendation in self.recommendations:
if recommendation['url'] == data['url']:
if self.checkRedundancy(recommendation['url'], data['url']):
result['error'] = 'existing url'
for field in self.resource_content_fields:
result['dup_' + field] = self.recommendations[self.recommendations.index(recommendation)][field]
......@@ -465,8 +500,6 @@ class RecommenderXBlock(XBlock):
frag.initialize_js('RecommenderXBlock')
return frag
# TO-DO: change this to create the scenarios you'd like to see in the
# workbench while developing your XBlock.
@staticmethod
def workbench_scenarios():
"""A canned scenario for display in the workbench."""
......
......@@ -89,6 +89,7 @@
<input type="button" value="Flag resource" class="flag_reason_submit">
</div>
<div class="editSourceBlock">
<div class="editSourceBlockTitle">Edit the resource and make it more helpful for other students with this problem. Please do not give the answer directly.</div>
<div style="float: left">Title&nbsp;</div><div class = 'redTxt'>*</div>
<textarea
class="edit_title"
......@@ -102,12 +103,12 @@
class="edit_descriptionText"
placeholder="Provide a meaningful description so other students know whether this is useful to them"></textarea><br/>
<form method="post" id="editResourceForm">
Previewing screenshot: <input type="file" name="file"><br/>
Preview screenshot: <input type="file" name="file" class='editResourceScreenshot'><br/>
<input type="button" value="Save change" class="edit_submit" disabled >
</form>
</div>
<div class="recommender_add">
<div class="addSourceBlockTitle">Suggest a resource which can help other students with this problem.</div>
<div class="addSourceBlockTitle">Suggest a resource which can help other students with this problem. Please do not give the answer directly.</div>
<div style="float: left">Title&nbsp;</div><div class = 'redTxt'>*</div>
<textarea
class="in_title"
......@@ -121,7 +122,7 @@
class="in_descriptionText"
placeholder="Provide a meaningful description so other students know whether this is useful to them"></textarea><br/>
<form method="post" id="addResourceForm">
Previewing screenshot: <input type="file" name="file"><br/>
Preview screenshot: <input type="file" name="file" class='addResourceScreenshot'><br/>
<input type="button" value="Add resource" class="add_submit" disabled >
</form>
</div>
......
......@@ -4,7 +4,8 @@ var tooltipsCatsPerResource = [
'.recommender_vote_arrow_down',
'.recommender_vote_score',
'a',
'.flagResource'
'.flagResource',
'.staffEdition'
];
var tooltipsCats = [
......@@ -12,28 +13,50 @@ var tooltipsCats = [
'.previewingImg',
'.in_title',
'.in_url',
'.edit_title',
'.edit_url',
'.in_descriptionText',
'.addResourceScreenshot',
'.backToViewButton',
'.flag_reason',
'.aws_access_key',
'.aws_secret_key',
'.bucketName',
'.uploadedFileDir',
'.delete_resource',
'.recommender_row_top.resource_list_expanded'
];
var tooltipsEditCats = [
'.edit_title',
'.edit_url',
'.edit_descriptionText',
'.editResourceScreenshot'
];
var tooltipsCatsText = {
'.resource_add_button': 'Recommend a new resource which may be helpful to other students solving this problem',
'.resource_edit_button': 'Edit this resource',
'.recommender_vote_arrow_up': 'Upvote if the resource is helpful',
'.recommender_vote_arrow_down': 'Downvote if the resource is not helpful',
'.recommender_vote_score': 'Votes', //
'a': 'Resource title', // TODO: I would suggest making the description be the tooltip.
'a': 'Resource title', // TODO: I would suggest making the description be the tooltip.
'.staffEdition': 'Add Amazon S3 information for file uploading or delete this resource; these functions are restricted to course staff',
'.previewingImg': 'Preview image (typically, a screenshot)',
'.in_title': 'Give a short (1-3 sentence) summary of the resource; ideally, this should be concise, but give enough detail to let students know whether this resources is useful to them',
'.in_url': 'Cut-and-paste the URL of the resource.',
'.in_descriptionText': 'Give a paragraph of summary of the resource; the summary should be more detailed than you gave in Title',
'.addResourceScreenshot': 'Upload a preview screenshot (in GIF/PNG/JPG) of the resource; ideally, this should let students know whether this resources is useful to them',
'.edit_title': 'Give a short (1-3 sentence) summary of the resource; ideally, this should be concise, but give enough detail to let students know whether this resources is useful to them',
'.edit_url': 'Cut-and-paste the URL of the resource.', // TODO: Give instructions to go to element of learning sequence, or time in video
'.edit_descriptionText': 'Give a paragraph of summary of the resource; the summary should be more detailed than you gave in Title',
'.editResourceScreenshot': 'Upload a preview screenshot (in GIF/PNG/JPG) of the resource; ideally, this should let students know whether this resources is useful to them',
'.backToViewButton': 'Go back to the main list',
'.flag_reason': 'Give a meaningful reason for why this resource should be removed',
'.flagResource': 'Flag this resource as problematic and give your reason',
'.aws_access_key': 'Give the access key of your Amazon s3 account',
'.aws_secret_key': 'Give the secret key of your Amazon s3 account',
'.bucketName': 'Give the bucket name of your Amazon s3 account',
'.uploadedFileDir': 'Give the path (relative to root directory) of the directory for storing uploaded files',
'.delete_resource': 'Delete this resource',
'.recommender_row_top': 'Show a list of student-recommented related resources',
'.recommender_row_top.resource_list_expanded': 'Hide the recommendations list'
};
......@@ -49,7 +72,7 @@ var staff_edit_buttons_text = {
'delete_resource': "Delete resource",
"endorse_resource": "Endorse resource",
"deendorse_resource": "De-endorse resource",
"submit_s3_info": "Submit information for Amazon Web Services S3"
"submit_s3_info": "Add Amazon S3 information for file uploading"
}
var staff_edit_textareas = [
......@@ -60,10 +83,10 @@ var staff_edit_textareas = [
]
var staff_edit_textareas_text = {
'aws_access_key': 'Amazon Web Services access key',
'aws_secret_key': 'Amazon Web Services secret key',
'bucketName': 'Bucket name of your Amazon Web Services',
'uploadedFileDir': 'Directory for your upload files'
'aws_access_key': 'Amazon S3 access key',
'aws_secret_key': 'Amazon S3 secret key',
'bucketName': 'Bucket name of your Amazon S3',
'uploadedFileDir': 'Directory for your uploaded files'
}
var staff_edit_textareas_placeholder = {
......
......@@ -449,6 +449,9 @@ function RecommenderXBlock(runtime, element) {
$('#editResourceForm').find("input[name='file']").change(function() {
if ($(this).val() != '') { enableEditSubmit(); }
});
/* Add tooltips for editting page */
addTooltipPerCats(tooltipsEditCats);
/* Upload the screen shot, submit the edited resource, save the resource in the database, and update the current view of resource */
$('.edit_submit').unbind();
......@@ -626,7 +629,8 @@ function RecommenderXBlock(runtime, element) {
maxWidth: '300'
});
return;
}
}
if ($(cats).hasClass('tooltipstered')) { return; }
$(cats).tooltipster({
content: $('<span>' + tooltipsCatsText[cats] + '</span>'),
theme: '.my-custom-theme',
......@@ -637,6 +641,26 @@ function RecommenderXBlock(runtime, element) {
});
}
/* Add tooltips to each cat in cats */
function addTooltipPerCats(cats) {
cats.forEach(function(cat, ind) {
try {
$(cat).tooltipster('destroy');
}
catch (e) { }
});
cats.forEach(function(cat, ind) {
try {
$(cat).tooltipster({
content: $('<span>' + tooltipsCatsText[cat] + '</span>'),
theme: '.my-custom-theme',
maxWidth: '300'
});
}
catch (e) { }
});
}
/* Add tooltips to each component in each resource */
function addTooltipPerResource(ele) {
tooltipsCatsPerResource.forEach(function(cats, ind) {
......@@ -673,7 +697,7 @@ function RecommenderXBlock(runtime, element) {
if (result['is_user_staff']) {
is_user_staff = true;
addFunctionsForStaff();
$('.recommender_resource').each(function(index, ele) { addFunctionsForStaffPerResource(ele); });
$('.recommender_resource').each(function(index, ele) { addFunctionsForStaffPerResource(ele); addTooltipPerResource(ele); });
}
}
});
......
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