Annotation Tools: Add helper functions and fixed pep8/pylint errors
Small plugin fixes
This commit is contained in:
45
common/lib/xmodule/xmodule/annotator_mixin.py
Normal file
45
common/lib/xmodule/xmodule/annotator_mixin.py
Normal file
@@ -0,0 +1,45 @@
|
||||
"""
|
||||
Annotations Tool Mixin
|
||||
This file contains global variables and functions used in the various Annotation Tools.
|
||||
"""
|
||||
from pkg_resources import resource_string
|
||||
from lxml import etree
|
||||
from urlparse import urlparse
|
||||
from os.path import splitext, basename
|
||||
from HTMLParser import HTMLParser
|
||||
|
||||
def get_instructions(xmltree):
|
||||
""" Removes <instructions> from the xmltree and returns them as a string, otherwise None. """
|
||||
instructions = xmltree.find('instructions')
|
||||
if instructions is not None:
|
||||
instructions.tag = 'div'
|
||||
xmltree.remove(instructions)
|
||||
return etree.tostring(instructions, encoding='unicode')
|
||||
return None
|
||||
|
||||
def get_extension(srcurl):
|
||||
''' get the extension of a given url '''
|
||||
if 'youtu' in srcurl:
|
||||
return 'video/youtube'
|
||||
else:
|
||||
disassembled = urlparse(srcurl)
|
||||
file_ext = splitext(basename(disassembled.path))[1]
|
||||
return 'video/' + file_ext.replace('.', '')
|
||||
|
||||
class MLStripper(HTMLParser):
|
||||
"helper function for html_to_text below"
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
self.fed = []
|
||||
def handle_data(self, d):
|
||||
self.fed.append(d)
|
||||
def handle_entityref(self, name):
|
||||
self.fed.append('&%s;' % name)
|
||||
def get_data(self):
|
||||
return ''.join(self.fed)
|
||||
|
||||
def html_to_text(html):
|
||||
"strips the html tags off of the text to return plaintext"
|
||||
s = MLStripper()
|
||||
s.feed(html)
|
||||
return s.get_data()
|
||||
@@ -23,8 +23,8 @@ def retrieve_token(userid, secret):
|
||||
dtnow = datetime.datetime.now()
|
||||
dtutcnow = datetime.datetime.utcnow()
|
||||
delta = dtnow - dtutcnow
|
||||
newhour, newmin = divmod((delta.days * 24 * 60 * 60 + delta.seconds + 30) // 60, 60)
|
||||
newtime = "%s%+02d:%02d" % (dtnow.isoformat(), newhour, newmin)
|
||||
newhour, newmin = divmod((delta.days * 24 * 60 * 60 + delta.seconds + 30) // 60, 60) # pylint: disable=E1103
|
||||
newtime = "%s%+02d:%02d" % (dtnow.isoformat(), newhour, newmin) # pylint: disable=E1103
|
||||
# uses the issued time (UTC plus timezone), the consumer key and the user's email to maintain a
|
||||
# federated system in the annotation backend server
|
||||
custom_data = {"issuedAt": newtime, "consumerKey": secret, "userId": userid, "ttl": 86400}
|
||||
|
||||
52
common/lib/xmodule/xmodule/tests/test_annotator_mixin.py
Normal file
52
common/lib/xmodule/xmodule/tests/test_annotator_mixin.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""
|
||||
This test will run for annotator_mixin.py
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from lxml import etree
|
||||
|
||||
from xmodule.annotator_mixin import get_instructions, get_extension, html_to_text
|
||||
|
||||
class HelperFunctionTest(unittest.TestCase):
|
||||
"""
|
||||
Tests to ensure that the following helper functions work for the annotation tool
|
||||
"""
|
||||
sample_xml = '''
|
||||
<annotatable>
|
||||
<instructions><p>Helper Test Instructions.</p></instructions>
|
||||
</annotatable>
|
||||
'''
|
||||
sample_sourceurl = "http://video-js.zencoder.com/oceans-clip.mp4"
|
||||
sample_youtubeurl = "http://www.youtube.com/watch?v=yxLIu-scR9Y"
|
||||
sample_html = '<p><b>Testing here</b> and not bolded here</p>'
|
||||
|
||||
def test_get_instructions(self):
|
||||
"""
|
||||
Function takes in an input of a specific xml string with surrounding instructions tags and returns a valid html string.
|
||||
"""
|
||||
xmltree = etree.fromstring(self.sample_xml)
|
||||
|
||||
expected_xml = u"<div><p>Helper Test Instructions.</p></div>"
|
||||
actual_xml = get_instructions(xmltree) # pylint: disable=W0212
|
||||
self.assertIsNotNone(actual_xml)
|
||||
self.assertEqual(expected_xml.strip(), actual_xml.strip())
|
||||
|
||||
xmltree = etree.fromstring('<annotatable>foo</annotatable>')
|
||||
actual = get_instructions(xmltree) # pylint: disable=W0212
|
||||
self.assertIsNone(actual)
|
||||
|
||||
def test_get_extension(self):
|
||||
"""
|
||||
Tests whether given a url if the video will return a youtube source or extension
|
||||
"""
|
||||
expectedyoutube = 'video/youtube'
|
||||
expectednotyoutube = 'video/mp4'
|
||||
result1 = get_extension(self.sample_sourceurl) # pylint: disable=W0212
|
||||
result2 = get_extension(self.sample_youtubeurl) # pylint: disable=W0212
|
||||
self.assertEqual(expectedyoutube, result2)
|
||||
self.assertEqual(expectednotyoutube, result1)
|
||||
|
||||
def test_html_to_text(self):
|
||||
expectedText = "Testing here and not bolded here"
|
||||
result = html_to_text(self.sample_html)
|
||||
self.assertEqual(expectedText, result)
|
||||
@@ -12,9 +12,9 @@ class TokenRetriever(unittest.TestCase):
|
||||
"""
|
||||
def test_token(self):
|
||||
"""
|
||||
Test for the token generator. Give an a random username and secret token, it should create the properly encoded string of text.
|
||||
Test for the token generator. Give an a random username and secret token, it should create the properly encoded string of text.
|
||||
"""
|
||||
expected = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpc3N1ZWRBdCI6ICIyMDE0LTAyLTI3VDE3OjAwOjQyLjQwNjQ0MSswOjAwIiwgImNvbnN1bWVyS2V5IjogImZha2Vfc2VjcmV0IiwgInVzZXJJZCI6ICJ1c2VybmFtZSIsICJ0dGwiOiA4NjQwMH0.Dx1PoF-7mqBOOSGDMZ9R_s3oaaLRPnn6CJgGGF2A5CQ"
|
||||
response = retrieve_token("username", "fake_secret")
|
||||
self.assertEqual(expected.split('.')[0], response.split('.')[0])
|
||||
self.assertNotEqual(expected.split('.')[2], response.split('.')[2])
|
||||
self.assertNotEqual(expected.split('.')[2], response.split('.')[2])
|
||||
|
||||
@@ -66,6 +66,6 @@ class VideoAnnotationModuleTestCase(unittest.TestCase):
|
||||
"""
|
||||
Tests to make sure variables passed in truly exist within the html once it is all rendered.
|
||||
"""
|
||||
context = self.mod.get_html() # pylint: disable=W0212
|
||||
context = self.mod.get_html() # pylint: disable=W0212
|
||||
for key in ['display_name', 'instructions_html', 'sourceUrl', 'typeSource', 'poster', 'annotation_storage']:
|
||||
self.assertIn(key, context)
|
||||
|
||||
@@ -6,6 +6,7 @@ from pkg_resources import resource_string
|
||||
from xmodule.x_module import XModule
|
||||
from xmodule.raw_module import RawDescriptor
|
||||
from xblock.core import Scope, String
|
||||
from xmodule.annotator_mixin import get_instructions
|
||||
from xmodule.annotator_token import retrieve_token
|
||||
|
||||
import textwrap
|
||||
@@ -70,12 +71,7 @@ class TextAnnotationModule(AnnotatableFields, XModule):
|
||||
|
||||
def _extract_instructions(self, xmltree):
|
||||
""" Removes <instructions> from the xmltree and returns them as a string, otherwise None. """
|
||||
instructions = xmltree.find('instructions')
|
||||
if instructions is not None:
|
||||
instructions.tag = 'div'
|
||||
xmltree.remove(instructions)
|
||||
return etree.tostring(instructions, encoding='unicode')
|
||||
return None
|
||||
return get_instructions(xmltree)
|
||||
|
||||
def get_html(self):
|
||||
""" Renders parameters to template. """
|
||||
|
||||
@@ -7,6 +7,7 @@ from pkg_resources import resource_string
|
||||
from xmodule.x_module import XModule
|
||||
from xmodule.raw_module import RawDescriptor
|
||||
from xblock.core import Scope, String
|
||||
from xmodule.annotator_mixin import get_instructions, get_extension
|
||||
from xmodule.annotator_token import retrieve_token
|
||||
|
||||
import textwrap
|
||||
@@ -65,24 +66,11 @@ class VideoAnnotationModule(AnnotatableFields, XModule):
|
||||
|
||||
def _extract_instructions(self, xmltree):
|
||||
""" Removes <instructions> from the xmltree and returns them as a string, otherwise None. """
|
||||
instructions = xmltree.find('instructions')
|
||||
if instructions is not None:
|
||||
instructions.tag = 'div'
|
||||
xmltree.remove(instructions)
|
||||
return etree.tostring(instructions, encoding='unicode')
|
||||
return None
|
||||
return get_instructions(xmltree)
|
||||
|
||||
def _get_extension(self, srcurl):
|
||||
''' get the extension of a given url '''
|
||||
if 'youtu' in srcurl:
|
||||
return 'video/youtube'
|
||||
else:
|
||||
spliturl = srcurl.split(".")
|
||||
extensionplus1 = spliturl[len(spliturl) - 1]
|
||||
spliturl = extensionplus1.split("?")
|
||||
extensionplus2 = spliturl[0]
|
||||
spliturl = extensionplus2.split("#")
|
||||
return 'video/' + spliturl[0]
|
||||
return get_extension(srcurl)
|
||||
|
||||
def get_html(self):
|
||||
""" Renders parameters to template. """
|
||||
|
||||
@@ -17,9 +17,21 @@
|
||||
}
|
||||
|
||||
.annotator-wrapper .mce-container {
|
||||
z-index:3000000000!important; /*To fix full-screen problems*/
|
||||
z-index: 3000000000!important; /*To fix full-screen problems*/
|
||||
}
|
||||
|
||||
.mce-container-body {
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.iframe[id="annotator-field"] {
|
||||
width: inherit;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
div.mce-tinymce.mce-container.mce-panel {
|
||||
min-width:400px;
|
||||
}
|
||||
|
||||
/* Some change in the design of Annotator */
|
||||
.annotator-editor .annotator-widget{
|
||||
@@ -30,4 +42,4 @@
|
||||
.mce-ico.mce-i-rubric{
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QkBBB07nraNoQAAAhZJREFUKM+NkstrE1EUxr+5c08ykztpJtVoazHBF8FgQQzonyBKEZS6FrQKLl0EXBRT0ZULJSs3oii4TyHgu90IlTaL6qouWlv7Ck1N0BSnmZk714WbPHz07M4534+Pw3eAHdTY8A9+Nd9/bshU1DpnO4HXjh2ZY2J9/OSTxHTrnP8PvJYf+BDQ6qEDaQBB43jrTusUFy4oPjsYWYzF+VS91nxLYfdhKgONaQT3W/KMxr1XY5e+qj86f8zsKYYsZ6AvjWFzA8ORHkAnwN8So7evzL/8pzMAXL/Hq8mMv1up371T7Z+/c3n9cKeuDS6Xy6dN07zLuZ56Onk2Ed2/ANJsnE/PQMpgyffle+kYzwazB1+3waVS6X48Hr9BRPB9H57nYXplFKeSt8D1Hriug9XKF0x+Lmw+ys8m2m42DOOn4zhQSsGyLOi6jqONm9isbmFVFlDbaGKx8QaB1rvdlbNhGLAsC0IIGIYBIQSy2ROQ0oOp7wOPraHXEugRvDtnzjmi0SiICEIIEBGklAB9B6cmbG0AUnrY5m73h+m6DsYYTNMEYwxEBMY0hGNVhHkcZigBO9qHlDHS7cwYg23bAIBQKAQigud7IH0XwtxDoHwEIQ9SLKx0wa7rPiaivYyxESklXNeFBg0mjyNQTQSuATMSm6ipuYt//eVcLhdeXl5+UKlUlur1upqamVAv3j3/VCyOD3VqfwF6uLp3q+vMcgAAAABJRU5ErkJggg==');
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
@@ -101,4 +101,4 @@ Annotator.Plugin.Flagging = (function(_super) {
|
||||
|
||||
return Flagging;
|
||||
|
||||
})(Annotator.Plugin);
|
||||
})(Annotator.Plugin);
|
||||
|
||||
@@ -82,6 +82,7 @@ Annotator.Plugin.Reply = (function(_super) {
|
||||
var string;
|
||||
return self;
|
||||
});
|
||||
field.remove();
|
||||
this.annotation = annotation;
|
||||
//Create the actions for the buttons
|
||||
return ret;
|
||||
|
||||
35
common/static/js/vendor/ova/tags-annotator.js
vendored
35
common/static/js/vendor/ova/tags-annotator.js
vendored
@@ -1,3 +1,27 @@
|
||||
/*
|
||||
HighlightTags Annotator Plugin v1.0 (https://github.com/lduarte1991/tags-annotator)
|
||||
Copyright (C) 2014 Luis F Duarte
|
||||
License: https://github.com/lduarte1991/tags-annotator/blob/master/LICENSE.rst
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/*===============================================================================
|
||||
===============================================================================
|
||||
===============================================================================
|
||||
===============================================================================
|
||||
==============================================================================*/
|
||||
/*
|
||||
* jQuery Plugin: Tokenizing Autocomplete Text Entry
|
||||
* Version 1.6.0
|
||||
@@ -22,7 +46,7 @@ var DEFAULT_SETTINGS = {
|
||||
|
||||
// Display settings
|
||||
hintText: "Type in a search term",
|
||||
noResultsText: "No results",
|
||||
noResultsText: "Not Found. Hit ENTER to add a personal tag.",
|
||||
searchingText: "Searching...",
|
||||
deleteText: "×",
|
||||
animateDropdown: true,
|
||||
@@ -39,7 +63,7 @@ var DEFAULT_SETTINGS = {
|
||||
prePopulate: null,
|
||||
processPrePopulate: false,
|
||||
|
||||
// Manipulation settings
|
||||
// Manipulation settings
|
||||
idPrefix: "token-input-",
|
||||
|
||||
// Formatters
|
||||
@@ -271,7 +295,10 @@ $.TokenList = function (input, url_or_data, settings) {
|
||||
add_token($(selected_dropdown_item).data("tokeninput"));
|
||||
hidden_input.change();
|
||||
return false;
|
||||
}
|
||||
} else{
|
||||
add_token({id:$(this).val(), name:$(this).val()});
|
||||
hidden_input.change();
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY.ESCAPE:
|
||||
@@ -886,7 +913,7 @@ Annotator.Plugin.HighlightTags = (function(_super) {
|
||||
HighlightTags.prototype.field = null;
|
||||
HighlightTags.prototype.input = null;
|
||||
HighlightTags.prototype.colors = null;
|
||||
HighlightTags.prototype.isFirstTime = true;
|
||||
HighlightTags.prototype.isFirstTime = true;
|
||||
|
||||
//this function will initialize the plug in. Create your fields here in the editor and viewer.
|
||||
HighlightTags.prototype.pluginInit = function() {
|
||||
|
||||
Reference in New Issue
Block a user