Commit dc338972 by Julia Hansbrough

Merge pull request #4053 from edx/harvard-annotations-on-hotfix

Harvard annotations on hotfix
parents 0df70376 e48cc16d
...@@ -7,7 +7,6 @@ from urlparse import urlparse ...@@ -7,7 +7,6 @@ from urlparse import urlparse
from os.path import splitext, basename from os.path import splitext, basename
from HTMLParser import HTMLParser from HTMLParser import HTMLParser
def get_instructions(xmltree): def get_instructions(xmltree):
""" Removes <instructions> from the xmltree and returns them as a string, otherwise None. """ """ Removes <instructions> from the xmltree and returns them as a string, otherwise None. """
instructions = xmltree.find('instructions') instructions = xmltree.find('instructions')
......
...@@ -9,13 +9,19 @@ from xmodule.raw_module import RawDescriptor ...@@ -9,13 +9,19 @@ from xmodule.raw_module import RawDescriptor
from xblock.core import Scope, String from xblock.core import Scope, String
from xmodule.annotator_mixin import get_instructions, html_to_text from xmodule.annotator_mixin import get_instructions, html_to_text
from xmodule.annotator_token import retrieve_token from xmodule.annotator_token import retrieve_token
from xblock.fragment import Fragment
import textwrap import textwrap
# Make '_' a no-op so we can scrape strings
_ = lambda text: text
class AnnotatableFields(object): class AnnotatableFields(object):
""" Fields for `ImageModule` and `ImageDescriptor`. """ """ Fields for `ImageModule` and `ImageDescriptor`. """
data = String(help="XML data for the annotation", scope=Scope.content, default=textwrap.dedent("""\ data = String(help=_("XML data for the annotation"),
scope=Scope.content,
default=textwrap.dedent("""\
<annotatable> <annotatable>
<instructions> <instructions>
<p> <p>
...@@ -36,28 +42,47 @@ class AnnotatableFields(object): ...@@ -36,28 +42,47 @@ class AnnotatableFields(object):
</annotatable> </annotatable>
""")) """))
display_name = String( display_name = String(
display_name="Display Name", display_name=_("Display Name"),
help="Display name for this module", help=_("Display name for this module"),
scope=Scope.settings, scope=Scope.settings,
default='Image Annotation', default='Image Annotation',
) )
instructor_tags = String( instructor_tags = String(
display_name="Tags for Assignments", display_name=_("Tags for Assignments"),
help="Add tags that automatically highlight in a certain color using the comma-separated form, i.e. imagery:red,parallelism:blue", help=_("Add tags that automatically highlight in a certain color using the comma-separated form, i.e. imagery:red,parallelism:blue"),
scope=Scope.settings, scope=Scope.settings,
default='professor:green,teachingAssistant:blue', default='professor:green,teachingAssistant:blue',
) )
annotation_storage_url = String( annotation_storage_url = String(
help="Location of Annotation backend", help=_("Location of Annotation backend"),
scope=Scope.settings, scope=Scope.settings,
default="http://your_annotation_storage.com", default="http://your_annotation_storage.com",
display_name="Url for Annotation Storage" display_name=_("Url for Annotation Storage")
) )
annotation_token_secret = String( annotation_token_secret = String(
help="Secret string for annotation storage", help=_("Secret string for annotation storage"),
scope=Scope.settings, scope=Scope.settings,
default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
display_name="Secret Token String for Annotation" display_name=_("Secret Token String for Annotation")
)
default_tab = String(
display_name=_("Default Annotations Tab"),
help=_("Select which tab will be the default in the annotations table: myNotes, Instructor, or Public."),
scope=Scope.settings,
default="myNotes",
)
# currently only supports one instructor, will build functionality for multiple later
instructor_email = String(
display_name=_("Email for 'Instructor' Annotations"),
help=_("Email of the user that will be attached to all annotations that will be found in 'Instructor' tab."),
scope=Scope.settings,
default="",
)
annotation_mode = String(
display_name=_("Mode for Annotation Tool"),
help=_("Type in number corresponding to following modes: 'instructor' or 'everyone'"),
scope=Scope.settings,
default="everyone",
) )
...@@ -91,18 +116,23 @@ class ImageAnnotationModule(AnnotatableFields, XModule): ...@@ -91,18 +116,23 @@ class ImageAnnotationModule(AnnotatableFields, XModule):
""" Removes <instructions> from the xmltree and returns them as a string, otherwise None. """ """ Removes <instructions> from the xmltree and returns them as a string, otherwise None. """
return get_instructions(xmltree) return get_instructions(xmltree)
def get_html(self): def student_view(self, context):
""" Renders parameters to template. """ """ Renders parameters to template. """
context = { context = {
'display_name': self.display_name_with_default, 'display_name': self.display_name_with_default,
'instructions_html': self.instructions, 'instructions_html': self.instructions,
'annotation_storage': self.annotation_storage_url,
'token': retrieve_token(self.user, self.annotation_token_secret), 'token': retrieve_token(self.user, self.annotation_token_secret),
'tag': self.instructor_tags, 'tag': self.instructor_tags,
'openseadragonjson': self.openseadragonjson, 'openseadragonjson': self.openseadragonjson,
'annotation_storage': self.annotation_storage_url,
'default_tab': self.default_tab,
'instructor_email': self.instructor_email,
'annotation_mode': self.annotation_mode,
} }
fragment = Fragment(self.system.render_template('imageannotation.html', context))
return self.system.render_template('imageannotation.html', context) fragment.add_javascript_url("/static/js/vendor/tinymce/js/tinymce/tinymce.full.min.js")
fragment.add_javascript_url("/static/js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js")
return fragment
class ImageAnnotationDescriptor(AnnotatableFields, RawDescriptor): # pylint: disable=abstract-method class ImageAnnotationDescriptor(AnnotatableFields, RawDescriptor): # pylint: disable=abstract-method
......
...@@ -69,10 +69,10 @@ class ImageAnnotationModuleTestCase(unittest.TestCase): ...@@ -69,10 +69,10 @@ class ImageAnnotationModuleTestCase(unittest.TestCase):
actual = self.mod._extract_instructions(xmltree) # pylint: disable=protected-access actual = self.mod._extract_instructions(xmltree) # pylint: disable=protected-access
self.assertIsNone(actual) self.assertIsNone(actual)
def test_get_html(self): def test_student_view(self):
""" """
Tests the function that passes in all the information in the context that will be used in templates/textannotation.html Tests the function that passes in all the information in the context that will be used in templates/textannotation.html
""" """
context = self.mod.get_html() context = self.mod.student_view({}).content
for key in ['display_name', 'instructions_html', 'annotation_storage', 'token', 'tag', 'openseadragonjson']: for key in ['display_name', 'instructions_html', 'annotation_storage', 'token', 'tag', 'openseadragonjson']:
self.assertIn(key, context) self.assertIn(key, context)
...@@ -54,10 +54,10 @@ class TextAnnotationModuleTestCase(unittest.TestCase): ...@@ -54,10 +54,10 @@ class TextAnnotationModuleTestCase(unittest.TestCase):
actual = self.mod._extract_instructions(xmltree) # pylint: disable=W0212 actual = self.mod._extract_instructions(xmltree) # pylint: disable=W0212
self.assertIsNone(actual) self.assertIsNone(actual)
def test_get_html(self): def test_student_view(self):
""" """
Tests the function that passes in all the information in the context that will be used in templates/textannotation.html Tests the function that passes in all the information in the context that will be used in templates/textannotation.html
""" """
context = self.mod.get_html() context = self.mod.student_view({}).content
for key in ['display_name', 'tag', 'source', 'instructions_html', 'content_html', 'annotation_storage', 'token']: for key in ['display_name', 'tag', 'source', 'instructions_html', 'content_html', 'annotation_storage', 'token']:
self.assertIn(key, context) self.assertIn(key, context)
...@@ -62,10 +62,10 @@ class VideoAnnotationModuleTestCase(unittest.TestCase): ...@@ -62,10 +62,10 @@ class VideoAnnotationModuleTestCase(unittest.TestCase):
self.assertEqual(expectedyoutube, result2) self.assertEqual(expectedyoutube, result2)
self.assertEqual(expectednotyoutube, result1) self.assertEqual(expectednotyoutube, result1)
def test_get_html(self): def test_student_view(self):
""" """
Tests to make sure variables passed in truly exist within the html once it is all rendered. Tests to make sure variables passed in truly exist within the html once it is all rendered.
""" """
context = self.mod.get_html() context = self.mod.student_view({}).content
for key in ['display_name', 'instructions_html', 'sourceUrl', 'typeSource', 'poster', 'annotation_storage']: for key in ['display_name', 'instructions_html', 'sourceUrl', 'typeSource', 'poster', 'annotation_storage']:
self.assertIn(key, context) self.assertIn(key, context)
...@@ -8,7 +8,7 @@ from xmodule.raw_module import RawDescriptor ...@@ -8,7 +8,7 @@ from xmodule.raw_module import RawDescriptor
from xblock.core import Scope, String from xblock.core import Scope, String
from xmodule.annotator_mixin import get_instructions from xmodule.annotator_mixin import get_instructions
from xmodule.annotator_token import retrieve_token from xmodule.annotator_token import retrieve_token
from xblock.fragment import Fragment
import textwrap import textwrap
# Make '_' a no-op so we can scrape strings # Make '_' a no-op so we can scrape strings
...@@ -17,7 +17,9 @@ _ = lambda text: text ...@@ -17,7 +17,9 @@ _ = lambda text: text
class AnnotatableFields(object): class AnnotatableFields(object):
"""Fields for `TextModule` and `TextDescriptor`.""" """Fields for `TextModule` and `TextDescriptor`."""
data = String(help=_("XML data for the annotation"), scope=Scope.content, default=textwrap.dedent("""\ data = String(help=_("XML data for the annotation"),
scope=Scope.content,
default=textwrap.dedent("""\
<annotatable> <annotatable>
<instructions> <instructions>
<p> <p>
...@@ -47,8 +49,43 @@ class AnnotatableFields(object): ...@@ -47,8 +49,43 @@ class AnnotatableFields(object):
scope=Scope.settings, scope=Scope.settings,
default='None', default='None',
) )
annotation_storage_url = String(help=_("Location of Annotation backend"), scope=Scope.settings, default="http://your_annotation_storage.com", display_name=_("Url for Annotation Storage")) diacritics = String(
annotation_token_secret = String(help=_("Secret string for annotation storage"), scope=Scope.settings, default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", display_name=_("Secret Token String for Annotation")) display_name=_("Diacritic Marks"),
help=_("Add diacritic marks to be added to a text using the comma-separated form, i.e. markname;urltomark;baseline,markname2;urltomark2;baseline2"),
scope=Scope.settings,
default='',
)
annotation_storage_url = String(
help=_("Location of Annotation backend"),
scope=Scope.settings,
default="http://your_annotation_storage.com",
display_name=_("Url for Annotation Storage")
)
annotation_token_secret = String(
help=_("Secret string for annotation storage"),
scope=Scope.settings,
default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
display_name=_("Secret Token String for Annotation")
)
default_tab = String(
display_name=_("Default Annotations Tab"),
help=_("Select which tab will be the default in the annotations table: myNotes, Instructor, or Public."),
scope=Scope.settings,
default="myNotes",
)
# currently only supports one instructor, will build functionality for multiple later
instructor_email = String(
display_name=_("Email for 'Instructor' Annotations"),
help=_("Email of the user that will be attached to all annotations that will be found in 'Instructor' tab."),
scope=Scope.settings,
default="",
)
annotation_mode = String(
display_name=_("Mode for Annotation Tool"),
help=_("Type in number corresponding to following modes: 'instructor' or 'everyone'"),
scope=Scope.settings,
default="everyone",
)
class TextAnnotationModule(AnnotatableFields, XModule): class TextAnnotationModule(AnnotatableFields, XModule):
...@@ -73,7 +110,7 @@ class TextAnnotationModule(AnnotatableFields, XModule): ...@@ -73,7 +110,7 @@ class TextAnnotationModule(AnnotatableFields, XModule):
""" Removes <instructions> from the xmltree and returns them as a string, otherwise None. """ """ Removes <instructions> from the xmltree and returns them as a string, otherwise None. """
return get_instructions(xmltree) return get_instructions(xmltree)
def get_html(self): def student_view(self, context):
""" Renders parameters to template. """ """ Renders parameters to template. """
context = { context = {
'course_key': self.runtime.course_id, 'course_key': self.runtime.course_id,
...@@ -82,10 +119,17 @@ class TextAnnotationModule(AnnotatableFields, XModule): ...@@ -82,10 +119,17 @@ class TextAnnotationModule(AnnotatableFields, XModule):
'source': self.source, 'source': self.source,
'instructions_html': self.instructions, 'instructions_html': self.instructions,
'content_html': self.content, 'content_html': self.content,
'annotation_storage': self.annotation_storage_url,
'token': retrieve_token(self.user_email, self.annotation_token_secret), 'token': retrieve_token(self.user_email, self.annotation_token_secret),
'diacritic_marks': self.diacritics,
'annotation_storage': self.annotation_storage_url,
'default_tab': self.default_tab,
'instructor_email': self.instructor_email,
'annotation_mode': self.annotation_mode,
} }
return self.system.render_template('textannotation.html', context) fragment = Fragment(self.system.render_template('textannotation.html', context))
fragment.add_javascript_url("/static/js/vendor/tinymce/js/tinymce/tinymce.full.min.js")
fragment.add_javascript_url("/static/js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js")
return fragment
class TextAnnotationDescriptor(AnnotatableFields, RawDescriptor): class TextAnnotationDescriptor(AnnotatableFields, RawDescriptor):
......
...@@ -9,6 +9,7 @@ from xmodule.raw_module import RawDescriptor ...@@ -9,6 +9,7 @@ from xmodule.raw_module import RawDescriptor
from xblock.core import Scope, String from xblock.core import Scope, String
from xmodule.annotator_mixin import get_instructions, get_extension from xmodule.annotator_mixin import get_instructions, get_extension
from xmodule.annotator_token import retrieve_token from xmodule.annotator_token import retrieve_token
from xblock.fragment import Fragment
import textwrap import textwrap
...@@ -18,7 +19,9 @@ _ = lambda text: text ...@@ -18,7 +19,9 @@ _ = lambda text: text
class AnnotatableFields(object): class AnnotatableFields(object):
""" Fields for `VideoModule` and `VideoDescriptor`. """ """ Fields for `VideoModule` and `VideoDescriptor`. """
data = String(help=_("XML data for the annotation"), scope=Scope.content, default=textwrap.dedent("""\ data = String(help=_("XML data for the annotation"),
scope=Scope.content,
default=textwrap.dedent("""\
<annotatable> <annotatable>
<instructions> <instructions>
<p> <p>
...@@ -31,12 +34,51 @@ class AnnotatableFields(object): ...@@ -31,12 +34,51 @@ class AnnotatableFields(object):
display_name=_("Display Name"), display_name=_("Display Name"),
help=_("Display name for this module"), help=_("Display name for this module"),
scope=Scope.settings, scope=Scope.settings,
default='Video Annotation', default=_('Video Annotation'),
)
sourceurl = String(
help=_("The external source URL for the video."),
display_name=_("Source URL"),
scope=Scope.settings, default="http://video-js.zencoder.com/oceans-clip.mp4"
)
poster_url = String(
help=_("Poster Image URL"),
display_name=_("Poster URL"),
scope=Scope.settings,
default=""
)
annotation_storage_url = String(
help=_("Location of Annotation backend"),
scope=Scope.settings,
default="http://your_annotation_storage.com",
display_name=_("Url for Annotation Storage")
)
annotation_token_secret = String(
help=_("Secret string for annotation storage"),
scope=Scope.settings,
default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
display_name=_("Secret Token String for Annotation")
)
default_tab = String(
display_name=_("Default Annotations Tab"),
help=_("Select which tab will be the default in the annotations table: myNotes, Instructor, or Public."),
scope=Scope.settings,
default="myNotes",
)
# currently only supports one instructor, will build functionality for multiple later
instructor_email = String(
display_name=_("Email for 'Instructor' Annotations"),
help=_("Email of the user that will be attached to all annotations that will be found in 'Instructor' tab."),
scope=Scope.settings,
default="",
)
annotation_mode = String(
display_name=_("Mode for Annotation Tool"),
help=_("Type in number corresponding to following modes: 'instructor' or 'everyone'"),
scope=Scope.settings,
default="everyone",
) )
sourceurl = String(help=_("The external source URL for the video."), display_name=_("Source URL"), scope=Scope.settings, default="http://video-js.zencoder.com/oceans-clip.mp4")
poster_url = String(help=_("Poster Image URL"), display_name=_("Poster URL"), scope=Scope.settings, default="")
annotation_storage_url = String(help=_("Location of Annotation backend"), scope=Scope.settings, default="http://your_annotation_storage.com", display_name=_("Url for Annotation Storage"))
annotation_token_secret = String(help=_("Secret string for annotation storage"), scope=Scope.settings, default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", display_name=_("Secret Token String for Annotation"))
class VideoAnnotationModule(AnnotatableFields, XModule): class VideoAnnotationModule(AnnotatableFields, XModule):
'''Video Annotation Module''' '''Video Annotation Module'''
...@@ -72,7 +114,7 @@ class VideoAnnotationModule(AnnotatableFields, XModule): ...@@ -72,7 +114,7 @@ class VideoAnnotationModule(AnnotatableFields, XModule):
''' get the extension of a given url ''' ''' get the extension of a given url '''
return get_extension(src_url) return get_extension(src_url)
def get_html(self): def student_view(self, context):
""" Renders parameters to template. """ """ Renders parameters to template. """
extension = self._get_extension(self.sourceurl) extension = self._get_extension(self.sourceurl)
...@@ -84,11 +126,16 @@ class VideoAnnotationModule(AnnotatableFields, XModule): ...@@ -84,11 +126,16 @@ class VideoAnnotationModule(AnnotatableFields, XModule):
'typeSource': extension, 'typeSource': extension,
'poster': self.poster_url, 'poster': self.poster_url,
'content_html': self.content, 'content_html': self.content,
'annotation_storage': self.annotation_storage_url,
'token': retrieve_token(self.user_email, self.annotation_token_secret), 'token': retrieve_token(self.user_email, self.annotation_token_secret),
'annotation_storage': self.annotation_storage_url,
'default_tab': self.default_tab,
'instructor_email': self.instructor_email,
'annotation_mode': self.annotation_mode,
} }
fragment = Fragment(self.system.render_template('videoannotation.html', context))
return self.system.render_template('videoannotation.html', context) fragment.add_javascript_url("/static/js/vendor/tinymce/js/tinymce/tinymce.full.min.js")
fragment.add_javascript_url("/static/js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js")
return fragment
class VideoAnnotationDescriptor(AnnotatableFields, RawDescriptor): class VideoAnnotationDescriptor(AnnotatableFields, RawDescriptor):
......
...@@ -380,7 +380,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ...@@ -380,7 +380,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
clickTimeThreshold: viewer.clickTimeThreshold, clickTimeThreshold: viewer.clickTimeThreshold,
clickDistThreshold: viewer.clickDistThreshold clickDistThreshold: viewer.clickDistThreshold
}); });
if(this.options.viewer.annotation_mode == "everyone" || this.options.viewer.flags){
/* Set elements to the control menu */ /* Set elements to the control menu */
viewer.annotatorControl = viewer.wrapperAnnotation.element; viewer.annotatorControl = viewer.wrapperAnnotation.element;
if( viewer.toolbar ){ if( viewer.toolbar ){
...@@ -394,6 +394,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ...@@ -394,6 +394,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
{anchor: $.ControlAnchor.TOP_LEFT} {anchor: $.ControlAnchor.TOP_LEFT}
); );
} }
}
}, },
_reset: function(){ _reset: function(){
//Find and remove DrawingRect. This is the previous rectangle //Find and remove DrawingRect. This is the previous rectangle
......
...@@ -379,14 +379,14 @@ ...@@ -379,14 +379,14 @@
display:inline-block; display:inline-block;
color:#302f2f; color:#302f2f;
font-family:arial; font-family:arial;
font-size:15px; font-size:14px;
font-weight:bold; font-weight:bold;
padding:6px 24px; padding:6px 24px;
text-decoration:none; text-decoration:none;
margin: 0px 0px 10px 0px; margin: 0px 0px 10px 0px;
cursor:pointer; cursor:pointer;
width:140px; width:115px;
text-align:center; text-align:center;
} }
...@@ -468,7 +468,7 @@ ...@@ -468,7 +468,7 @@
#mainCatch .searchbox input{ #mainCatch .searchbox input{
margin: 0; margin: 0;
padding: 0; padding: 0;
width: 60%; width: 50%;
margin-left: 10px; margin-left: 10px;
display: inline; display: inline;
float: left; float: left;
...@@ -493,19 +493,28 @@ ...@@ -493,19 +493,28 @@
cursor:pointer; cursor:pointer;
} }
#mainCatch .searchbox .clear-search-icon{
font-size: 12px;
text-decoration: underline;
float: right;
margin-top: 10px;
padding-right: 3px;
cursor:pointer;
}
#mainCatch .searchbox .search-icon:hover{ #mainCatch .searchbox .search-icon:hover{
opacity:0.5; opacity:0.5;
box-shadow: 2px 4px 5px #888888; box-shadow: 2px 4px 5px #888888;
} }
#mainCatch .selectors{ #mainCatch .selectors{
width:40%; width:45%;
position:relative; position:relative;
float:left; float:left;
} }
#mainCatch .searchbox{ #mainCatch .searchbox{
width:60%; width:52%;
position:relative; position:relative;
float:right; float:right;
} }
...@@ -515,6 +524,7 @@ ...@@ -515,6 +524,7 @@
position:relative; position:relative;
padding-right:5px; padding-right:5px;
margin-top:8px; margin-top:8px;
font-size:14px;
} }
#mainCatch .replies .replyItem .deleteReply{ #mainCatch .replies .replyItem .deleteReply{
......
...@@ -42,29 +42,29 @@ annotationList: ...@@ -42,29 +42,29 @@ annotationList:
'</div>'+ '</div>'+
'<div class="annotatedBy field">'+ '<div class="annotatedBy field">'+
'User'+ gettext('User')+
'</div>'+ '</div>'+
'<div class="body field">'+ '<div class="body field">'+
'Annotation'+ gettext('Annotation')+
'</div>'+ '</div>'+
'{{#if videoFormat}}'+ '{{#if videoFormat}}'+
'<div class="start field">'+ '<div class="start field">'+
'Start'+ gettext('Start')+
'</div>'+ '</div>'+
'<div class="end field">'+ '<div class="end field">'+
'End'+ gettext('End')+
'</div>'+ '</div>'+
'{{/if}}'+ '{{/if}}'+
'<div class="totalreplies field">'+ '<div class="totalreplies field">'+
'#Replies'+ gettext('#Replies')+
'</div>'+ '</div>'+
'<div class="annotatedAt field">'+ '<div class="annotatedAt field">'+
'Date posted'+ gettext('Date posted')+
'</div>'+ '</div>'+
'</div>'+ '</div>'+
'</div>'+ '</div>'+
...@@ -73,30 +73,41 @@ annotationList: ...@@ -73,30 +73,41 @@ annotationList:
'{{/each}}'+ '{{/each}}'+
'</div>'+ '</div>'+
'<div class="annotationListButtons">'+ '<div class="annotationListButtons">'+
'<div class="moreButtonCatch">More</div>'+ '<div class="moreButtonCatch">'+gettext('More')+'</div>'+
'</div>', '</div>',
//Main->PublicPrivateInstructor
annotationPublicPrivateInstructor:
'<div class="selectors"><div class="PublicPrivate myNotes active">'+gettext('My Notes')+'<span class="action">myNotes</span></div>'+
'<div class="PublicPrivate instructor"> '+gettext('Instructor')+'<span class="action">instructor</span></div>'+
'<div class="PublicPrivate public"> '+gettext('Public')+'<span class="action">public</span></div></div>'+
'<div class="searchbox"><div class="searchinst">'+gettext('Search')+'</div><select class="dropdown-list">'+
'<option>'+gettext('Users')+'</option>'+
'<option>'+gettext('Tags')+'</option>'+
'<option>'+gettext('Annotation Text')+'</option>'+
'</select><input type="text" name="search"/><div class="search-icon" alt="Run search."></div><div class="clear-search-icon" alt="Clear search.">'+gettext('Clear')+'</div></div>',
//Main->PublicPrivate //Main->PublicPrivate
annotationPublicPrivate: annotationPublicPrivate:
'<div class="selectors"><div class="PublicPrivate myNotes active">My Notes<span class="action">myNotes</span></div>'+ '<div class="selectors"><div class="PublicPrivate myNotes active">'+gettext('My Notes')+'<span class="action">myNotes</span></div>'+
'<div class="PublicPrivate public"> Public<span class="action">public</span></div></div>'+ '<div class="PublicPrivate public"> '+gettext('Public')+'<span class="action">public</span></div></div>'+
'<div class="searchbox"><div class="searchinst">Search</div><select class="dropdown-list">'+ '<div class="searchbox"><div class="searchinst">'+gettext('Search')+'</div><select class="dropdown-list">'+
'<option>Users</option>'+ '<option>'+gettext('Users')+'</option>'+
'<option>Tags</option>'+ '<option>'+gettext('Tags')+'</option>'+
'<option>Annotation Text</option>'+ '<option>'+gettext('Annotation Text')+'</option>'+
'</select><input type="text" name="search"/><div class="search-icon" alt="Run search."></div></div>', '</select><input type="text" name="search"/><div class="search-icon" alt="Run search."></div><div class="clear-search-icon" alt="Clear search.">'+gettext('Clear')+'</div></div>',
//Main->MediaSelector //Main->MediaSelector
annotationMediaSelector: annotationMediaSelector:
'<ul class="ui-tabs-nav">'+ '<ul class="ui-tabs-nav">'+
'<li class="ui-state-default" media="text">'+ '<li class="ui-state-default" media="text">'+
'Text'+ gettext('Text')+
'</li>'+ '</li>'+
'<li class="ui-state-default" media="video">'+ '<li class="ui-state-default" media="video">'+
'Video'+ gettext('Video')+
'</li>'+ '</li>'+
'li class="ui-state-default" media="image">'+ '<li class="ui-state-default" media="image">'+
'Image'+ gettext('Image')+
'</li>'+ '</li>'+
'</ul>', '</ul>',
...@@ -126,7 +137,7 @@ annotationReply: ...@@ -126,7 +137,7 @@ annotationReply:
'<div class="map"></div>'+ '<div class="map"></div>'+
'</div>'+ '</div>'+
'{{/if}}'+ '{{/if}}'+
'<div class="deleteReply">Delete</div>'+ '<div class="deleteReply">'+gettext('Delete')+'</div>'+
'</p>'+ '</p>'+
'<p>'+ '<p>'+
'{{#if this.text}}'+ '{{#if this.text}}'+
...@@ -233,13 +244,13 @@ annotationDetail: ...@@ -233,13 +244,13 @@ annotationDetail:
'</div>'+ '</div>'+
'<div class="controlReplies">'+ '<div class="controlReplies">'+
'<div class="newReply" style="text-decoration:underline">Reply</div>&nbsp;'+ '<div class="newReply" style="text-decoration:underline">'+gettext('Reply')+'</div>&nbsp;'+
'<div class="hideReplies" style="text-decoration:underline;display:{{#if hasReplies}}block{{else}}none{{/if}}">Show Replies</div>&nbsp;'+ '<div class="hideReplies" style="text-decoration:underline;display:{{#if hasReplies}}block{{else}}none{{/if}}">Show Replies</div>&nbsp;'+
'{{#if authToEditButton}}'+ '{{#if authToEditButton}}'+
'<div class="editAnnotation" style="text-decoration:underline">Edit</div>'+ '<div class="editAnnotation" style="text-decoration:underline">'+gettext('Edit')+'</div>'+
'{{/if}}'+ '{{/if}}'+
'{{#if authToDeleteButton}}'+ '{{#if authToDeleteButton}}'+
'<div class="deleteAnnotation" style="text-decoration:underline">Delete</div>'+ '<div class="deleteAnnotation" style="text-decoration:underline">'+gettext('Delete')+'</div>'+
'{{/if}}'+ '{{/if}}'+
'</div>'+ '</div>'+
...@@ -248,7 +259,7 @@ annotationDetail: ...@@ -248,7 +259,7 @@ annotationDetail:
'{{#if tags}}'+ '{{#if tags}}'+
'<div class="tags">'+ '<div class="tags">'+
'<h3>Tags:</h3>'+ '<h3>'+gettext('Tags:')+'</h3>'+
'{{#each tags}}'+ '{{#each tags}}'+
'<div class="tag">'+ '<div class="tag">'+
'{{this}}'+ '{{this}}'+
...@@ -290,7 +301,7 @@ CatchAnnotation = function (element, options) { ...@@ -290,7 +301,7 @@ CatchAnnotation = function (element, options) {
//Reset element an create a new element div //Reset element an create a new element div
element.html('<div id="mainCatch" class="annotationListContainer"></div>'); element.html('<div id="mainCatch" class="annotationListContainer"></div>');
this.current_tab = this.options.default_tab;
//INIT //INIT
var self = this; var self = this;
$( document ).ready(function() { $( document ).ready(function() {
...@@ -310,6 +321,7 @@ CatchAnnotation.prototype = { ...@@ -310,6 +321,7 @@ CatchAnnotation.prototype = {
this.TEMPLATENAMES = [ this.TEMPLATENAMES = [
"annotationList", //Main "annotationList", //Main
"annotationPublicPrivate", //Main->PublicPrivate "annotationPublicPrivate", //Main->PublicPrivate
"annotationPublicPrivateInstructor", //Main->PublicPrivateInstructor
"annotationMediaSelector", //Main->MediaSelector "annotationMediaSelector", //Main->MediaSelector
"annotationItem", //Main->ContainerRow "annotationItem", //Main->ContainerRow
"annotationReply",//Main->ContainerRow->Reply "annotationReply",//Main->ContainerRow->Reply
...@@ -317,8 +329,8 @@ CatchAnnotation.prototype = { ...@@ -317,8 +329,8 @@ CatchAnnotation.prototype = {
"annotationDetail",//Main->ContainerRow->DetailRow "annotationDetail",//Main->ContainerRow->DetailRow
]; ];
//annotator //annotator
var wrapper = $('.annotator-wrapper').parent()[0], var wrapper = $('.annotator-wrapper').parent()[0];
annotator = $.data(wrapper, 'annotator'); var annotator = $.data(wrapper, 'annotator');
this.annotator = annotator; this.annotator = annotator;
//Subscribe to annotator //Subscribe to annotator
...@@ -336,10 +348,22 @@ CatchAnnotation.prototype = { ...@@ -336,10 +348,22 @@ CatchAnnotation.prototype = {
this.HTMLTEMPLATES = CatchSources.HTMLTEMPLATES(this.options.imageUrlRoot); this.HTMLTEMPLATES = CatchSources.HTMLTEMPLATES(this.options.imageUrlRoot);
this.TEMPLATES = {}; this.TEMPLATES = {};
this._compileTemplates(); this._compileTemplates();
// the default annotations are the user's personal ones instead of instructor
// if the default tab is instructor, we must refresh the catch to pull the ones
// under the instructor's email. passing empty strings as arguments will default
// to pulling the annotations for the email within this.options.userId.
if(this.options.default_tab.toLowerCase() == 'instructor'){
this.options.userId = this.options.instructor_email;
this._refresh('','');
}
}, },
// //
// GLOBAL UTILITIES // GLOBAL UTILITIES
// //
getTemplate: function(templateName){
return this.TEMPLATES[templateName]() || '';
},
refreshCatch: function(newInstance) { refreshCatch: function(newInstance) {
var mediaType = this.options.media || 'text', var mediaType = this.options.media || 'text',
annotationItems = [], annotationItems = [],
...@@ -380,10 +404,16 @@ CatchAnnotation.prototype = { ...@@ -380,10 +404,16 @@ CatchAnnotation.prototype = {
if (newInstance){ if (newInstance){
var videoFormat = (mediaType === "video") ? true:false; var videoFormat = (mediaType === "video") ? true:false;
var publicPrivateTemplate = '';
if (self.options.showPublicPrivate) {
var templateName = this.options.instructor_email ?
"annotationPublicPrivateInstructor" :
"annotationPublicPrivate";
}
el.html(self.TEMPLATES.annotationList({ el.html(self.TEMPLATES.annotationList({
annotationItems: annotationItems, annotationItems: annotationItems,
videoFormat: videoFormat, videoFormat: videoFormat,
PublicPrivate: self.options.showPublicPrivate?self.TEMPLATES.annotationPublicPrivate():'', PublicPrivate: this.getTemplate(templateName),
MediaSelector: self.options.showMediaSelector?self.TEMPLATES.annotationMediaSelector():'', MediaSelector: self.options.showMediaSelector?self.TEMPLATES.annotationMediaSelector():'',
})); }));
}else{ }else{
...@@ -402,10 +432,21 @@ CatchAnnotation.prototype = { ...@@ -402,10 +432,21 @@ CatchAnnotation.prototype = {
//Set PublicPrivate //Set PublicPrivate
var PublicPrivateButtons = el.find('.annotationListButtons .PublicPrivate').removeClass('active'); //reset var PublicPrivateButtons = el.find('.annotationListButtons .PublicPrivate').removeClass('active'); //reset
for (var index=0;index<PublicPrivateButtons.length;index++) { for (var index=0;index<PublicPrivateButtons.length;index++) {
var span = $(PublicPrivateButtons[index]).find('span'), var span = $(PublicPrivateButtons[index]).find('span');
isUser = (typeof self.options.userId!='undefined' && self.options.userId!='' && self.options.userId!=null); if (span.html().toLowerCase()==self.current_tab.toLowerCase()) {
if (isUser && span.html()=="myNotes") $(PublicPrivateButtons[index]).addClass('active'); switch (self.current_tab.toLowerCase()){
else if (!isUser && span.html()=="public") $(PublicPrivateButtons[index]).addClass('active'); case 'public':
self.options.userId = '';
break;
case 'instructor':
self.options.userId = this.options.instructor_email;
break;
default:
self.options.userId = this.annotator.plugins.Permissions.user.id;
break;
}
$(PublicPrivateButtons[index]).addClass('active');
}
} }
//reset all old events //reset all old events
...@@ -423,6 +464,7 @@ CatchAnnotation.prototype = { ...@@ -423,6 +464,7 @@ CatchAnnotation.prototype = {
onControlRepliesClick = this.__bind(this._onControlRepliesClick, this), onControlRepliesClick = this.__bind(this._onControlRepliesClick, this),
onMoreButtonClick = this.__bind(this._onMoreButtonClick, this), onMoreButtonClick = this.__bind(this._onMoreButtonClick, this),
onSearchButtonClick = this.__bind(this._onSearchButtonClick, this), onSearchButtonClick = this.__bind(this._onSearchButtonClick, this),
onClearSearchButtonClick = this.__bind(this._onClearSearchButtonClick, this),
onDeleteReplyButtonClick = this.__bind(this._onDeleteReplyButtonClick, this), onDeleteReplyButtonClick = this.__bind(this._onDeleteReplyButtonClick, this),
onZoomToImageBoundsButtonClick = this.__bind(this._onZoomToImageBoundsButtonClick, this); onZoomToImageBoundsButtonClick = this.__bind(this._onZoomToImageBoundsButtonClick, this);
...@@ -464,6 +506,9 @@ CatchAnnotation.prototype = { ...@@ -464,6 +506,9 @@ CatchAnnotation.prototype = {
//Search Button //Search Button
el.on("click",".searchbox .search-icon", onSearchButtonClick); el.on("click",".searchbox .search-icon", onSearchButtonClick);
//Clear Search Button
el.on("click",".searchbox .clear-search-icon", onClearSearchButtonClick);
//Delete Reply Button //Delete Reply Button
el.on("click", ".replies .replyItem .deleteReply", onDeleteReplyButtonClick); el.on("click", ".replies .replyItem .deleteReply", onDeleteReplyButtonClick);
...@@ -568,6 +613,10 @@ CatchAnnotation.prototype = { ...@@ -568,6 +613,10 @@ CatchAnnotation.prototype = {
var annotations = annotator.plugins['Store'].annotations, var annotations = annotator.plugins['Store'].annotations,
tot = typeof annotations !='undefined'?annotations.length:0, tot = typeof annotations !='undefined'?annotations.length:0,
attempts = 0; // max 100 attempts = 0; // max 100
if(annotation.media == "image"){
self.refreshCatch(true);
self.checkTotAnnotations();
} else {
//This is to watch the annotations object, to see when is deleted the annotation //This is to watch the annotations object, to see when is deleted the annotation
var ischanged = function(){ var ischanged = function(){
var new_tot = annotator.plugins['Store'].annotations.length; var new_tot = annotator.plugins['Store'].annotations.length;
...@@ -583,6 +632,7 @@ CatchAnnotation.prototype = { ...@@ -583,6 +632,7 @@ CatchAnnotation.prototype = {
},100); //wait for the change in the annotations },100); //wait for the change in the annotations
}; };
ischanged(); ischanged();
}
}); });
annotator.subscribe("annotationCreated", function (annotation){ annotator.subscribe("annotationCreated", function (annotation){
var attempts = 0; // max 100 var attempts = 0; // max 100
...@@ -770,6 +820,10 @@ CatchAnnotation.prototype = { ...@@ -770,6 +820,10 @@ CatchAnnotation.prototype = {
var allannotations = this.annotator.plugins['Store'].annotations, var allannotations = this.annotator.plugins['Store'].annotations,
osda = this.annotator.osda; osda = this.annotator.osda;
if(this.options.externalLink){
uri += (uri.indexOf('?') >= 0)?'&osdaId='+osdaId:'?osdaId='+osdaId;
location.href = uri;
}
for(var item in allannotations){ for(var item in allannotations){
var an = allannotations[item]; var an = allannotations[item];
if (typeof an.id!='undefined' && an.id == osdaId){//this is the annotation if (typeof an.id!='undefined' && an.id == osdaId){//this is the annotation
...@@ -1011,8 +1065,18 @@ CatchAnnotation.prototype = { ...@@ -1011,8 +1065,18 @@ CatchAnnotation.prototype = {
userId = ''; userId = '';
//Get userI //Get userI
userId = (action.html()=="myNotes")? this.annotator.plugins.Permissions.user.id : ''; switch (action.html()){
case 'public':
userId = '';
break;
case 'instructor':
userId = this.options.instructor_email;
break;
default:
userId = this.annotator.plugins.Permissions.user.id;
break;
}
this.current_tab = action.html();
//Change userid and refresh //Change userid and refresh
this.changeUserId(userId); this.changeUserId(userId);
}, },
...@@ -1069,6 +1133,9 @@ CatchAnnotation.prototype = { ...@@ -1069,6 +1133,9 @@ CatchAnnotation.prototype = {
this._refresh(searchtype,searchInput); this._refresh(searchtype,searchInput);
}, },
_onClearSearchButtonClick: function(evt){
this._refresh('','');
},
_clearAnnotator: function(){ _clearAnnotator: function(){
var annotator = this.annotator, var annotator = this.annotator,
store = annotator.plugins.Store, store = annotator.plugins.Store,
......
...@@ -7872,14 +7872,14 @@ $.extend( $.IIIF1_1TileSource.prototype, $.TileSource.prototype, { ...@@ -7872,14 +7872,14 @@ $.extend( $.IIIF1_1TileSource.prototype, $.TileSource.prototype, {
uri; uri;
if ( level_width < this.tile_width && level_height < this.tile_height ){ if ( level_width < this.tile_width && level_height < this.tile_height ){
iiif_size = level_width + "," + level_height; iiif_size = level_width + ",";
iiif_region = 'full'; iiif_region = 'full';
} else { } else {
iiif_tile_x = x * iiif_tile_size_width; iiif_tile_x = x * iiif_tile_size_width;
iiif_tile_y = y * iiif_tile_size_height; iiif_tile_y = y * iiif_tile_size_height;
iiif_tile_w = Math.min( iiif_tile_size_width, this.width - iiif_tile_x ); iiif_tile_w = Math.min( iiif_tile_size_width, this.width - iiif_tile_x );
iiif_tile_h = Math.min( iiif_tile_size_height, this.height - iiif_tile_y ); iiif_tile_h = Math.min( iiif_tile_size_height, this.height - iiif_tile_y );
iiif_size = Math.ceil(iiif_tile_w * scale) + "," + Math.ceil(iiif_tile_h * scale); iiif_size = Math.ceil(iiif_tile_w * scale) + ",";
iiif_region = [ iiif_tile_x, iiif_tile_y, iiif_tile_w, iiif_tile_h ].join(','); iiif_region = [ iiif_tile_x, iiif_tile_y, iiif_tile_w, iiif_tile_h ].join(',');
} }
uri = [ this['@id'], iiif_region, iiif_size, IIIF_ROTATION, IIIF_QUALITY ].join('/'); uri = [ this['@id'], iiif_region, iiif_size, IIIF_ROTATION, IIIF_QUALITY ].join('/');
......
...@@ -11,9 +11,7 @@ from xmodule.modulestore.locations import SlashSeparatedCourseKey ...@@ -11,9 +11,7 @@ from xmodule.modulestore.locations import SlashSeparatedCourseKey
@login_required @login_required
def notes(request, course_id): def notes(request, course_id):
''' Displays the student's notes. ''' ''' Displays the student's notes. '''
course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id) course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
course = get_course_with_access(request.user, 'load', course_key) course = get_course_with_access(request.user, 'load', course_key)
if not notes_enabled_for_course(course): if not notes_enabled_for_course(course):
raise Http404 raise Http404
...@@ -28,6 +26,7 @@ def notes(request, course_id): ...@@ -28,6 +26,7 @@ def notes(request, course_id):
'student': student, 'student': student,
'storage': storage, 'storage': storage,
'token': retrieve_token(student.email, course.annotation_token_secret), 'token': retrieve_token(student.email, course.annotation_token_secret),
'default_tab': 'myNotes',
} }
return render_to_response('notes.html', context) return render_to_response('notes.html', context)
...@@ -31,12 +31,9 @@ ...@@ -31,12 +31,9 @@
<%namespace name='static' file='/static_content.html'/> <%namespace name='static' file='/static_content.html'/>
${static.css(group='style-vendor-tinymce-content', raw=True)} ${static.css(group='style-vendor-tinymce-content', raw=True)}
${static.css(group='style-vendor-tinymce-skin', raw=True)} ${static.css(group='style-vendor-tinymce-skin', raw=True)}
<script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/tinymce.full.min.js', raw=True)}" />
<script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js', raw=True)}" />
</div> </div>
<div id="catchDIV"> <div id="catchDIV">
## Translators: Notes below refer to annotations. They wil later be put under a "Notes" section. <div class="annotationListContainer">${_('Note: only instructors may annotate.')}</div>
<div class="annotationListContainer">${_('You do not have any notes.')}</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -74,7 +71,7 @@ ...@@ -74,7 +71,7 @@
var unit_id = $('#sequence-list').find('.active').attr("data-element"); var unit_id = $('#sequence-list').find('.active').attr("data-element");
uri += unit_id; uri += unit_id;
var pagination = 100, var pagination = 100,
is_staff = !('${user.is_staff}'=='False'), is_staff = ('${user.email}'=='${instructor_email}'),
options = { options = {
optionsAnnotator: { optionsAnnotator: {
permissions:{ permissions:{
...@@ -174,13 +171,14 @@ ...@@ -174,13 +171,14 @@
}, },
optionsOpenSeadragon:{ optionsOpenSeadragon:{
id: "imageHolder", id: "imageHolder",
annotation_mode: "${annotation_mode}",
flags: is_staff,
prefixUrl: "${settings.STATIC_URL}" + "js/vendor/ova/images/", prefixUrl: "${settings.STATIC_URL}" + "js/vendor/ova/images/",
${openseadragonjson} ${openseadragonjson}
}, },
optionsOSDA:{}, optionsOSDA:{},
}; };
tinymce.baseURL = "${settings.STATIC_URL}" + "js/vendor/tinymce/js/tinymce";
var imgURLRoot = "${settings.STATIC_URL}" + "js/vendor/ova/catch/img/"; var imgURLRoot = "${settings.STATIC_URL}" + "js/vendor/ova/catch/img/";
if (typeof Annotator != 'undefined'){ if (typeof Annotator != 'undefined'){
...@@ -192,19 +190,33 @@ ...@@ -192,19 +190,33 @@
//Load the plugin Image/Text Annotation //Load the plugin Image/Text Annotation
var osda = new OpenSeadragonAnnotation($('#imageHolder'),options); var osda = new OpenSeadragonAnnotation($('#imageHolder'),options);
var userId = ('${default_tab}'.toLowerCase() === 'instructor') ?
'${instructor_email}':
'${user.email}';
//Catch //Catch
var annotator = osda.annotator, var annotator = osda.annotator;
catchOptions = { var catchOptions = {
media:'image', media:'image',
externalLink:false, externalLink:false,
imageUrlRoot:imgURLRoot, imageUrlRoot:imgURLRoot,
showMediaSelector: false, showMediaSelector: false,
showPublicPrivate: true, showPublicPrivate: true,
userId:'${user.email}', userId:userId,
pagination:pagination,//Number of Annotations per load in the pagination, pagination:pagination,//Number of Annotations per load in the pagination,
flags:is_staff flags:is_staff,
}, default_tab: "${default_tab}",
Catch = new CatchAnnotation($('#catchDIV'),catchOptions); instructor_email: "${instructor_email}",
annotation_mode: "${annotation_mode}",
};
// if annotations are opened to everyone (2) or if they want to create no annotations (1 with no instructor)
// then the table at the bottom of the source should be displayed
if ("${annotation_mode}" == "everyone" || ("${annotation_mode}" == "instructor" && "${instructor_email}" != ""))
var Catch = new CatchAnnotation($('#catchDIV'),catchOptions);
// if it is in instructor mode only (1), the annotator should be destroyed for all except the instructor
if ("${annotation_mode}" == "instructor" && "${instructor_email}" == "" && !is_staff)
osda.annotator.destroy();
} }
</script> </script>
\ No newline at end of file
<%! from django.utils.translation import ugettext as _ %> <%! from django.utils.translation import ugettext as _ %>
<%namespace name='static' file='static_content.html'/> <%namespace name='static' file='static_content.html'/>
${static.css(group='style-vendor-tinymce-content', raw=True)}
${static.css(group='style-vendor-tinymce-skin', raw=True)}
<script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/tinymce.full.min.js', raw=True)}"></script>
<script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js', raw=True)}" ></script>
<%inherit file="main.html" /> <%inherit file="main.html" />
<%! <%!
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
...@@ -128,7 +132,7 @@ ...@@ -128,7 +132,7 @@
}, },
}, },
auth: { auth: {
tokenUrl: location.protocol+'//'+location.host+"/token?course_id=${course.id.to_deprecated_string()}" token: "${token}"
}, },
store: { store: {
// The endpoint of the store on your server. // The endpoint of the store on your server.
...@@ -158,14 +162,12 @@ ...@@ -158,14 +162,12 @@
optionsRichText: { optionsRichText: {
tinymce:{ tinymce:{
selector: "li.annotator-item textarea", selector: "li.annotator-item textarea",
plugins: "media image insertdatetime link code", plugins: "media image codemirror",
menubar: false, menubar: false,
toolbar_items_size: 'small', toolbar_items_size: 'small',
extended_valid_elements : "iframe[src|frameborder|style|scrolling|class|width|height|name|align|id]", extended_valid_elements : "iframe[src|frameborder|style|scrolling|class|width|height|name|align|id]",
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image media rubric | code ", toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | image rubric | code ",
} }
return true;
},
}, },
auth: { auth: {
token: "${token}" token: "${token}"
...@@ -184,11 +186,10 @@ ...@@ -184,11 +186,10 @@
destroy: '/delete/:id', destroy: '/delete/:id',
search: '/search' search: '/search'
}, },
}
}; };
tinyMCE.baseURL = "${settings.STATIC_URL}" + "js/vendor/ova";
var imgURLRoot = "${settings.STATIC_URL}" + "js/vendor/ova/catch/img/"; var imgURLRoot = "${settings.STATIC_URL}" + "js/vendor/ova/catch/img/";
//remove old instances //remove old instances
if (Annotator._instances.length !== 0) { if (Annotator._instances.length !== 0) {
$('#notesHolder').annotator("destroy"); $('#notesHolder').annotator("destroy");
...@@ -207,7 +208,8 @@ ...@@ -207,7 +208,8 @@
showMediaSelector: true, showMediaSelector: true,
showPublicPrivate: true, showPublicPrivate: true,
pagination:pagination,//Number of Annotations per load in the pagination, pagination:pagination,//Number of Annotations per load in the pagination,
flags:is_staff flags:is_staff,
default_tab: "${default_tab}",
}, },
Catch = new CatchAnnotation($('#catchDIV'),catchOptions); Catch = new CatchAnnotation($('#catchDIV'),catchOptions);
</script> </script>
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
<%namespace name='static' file='/static_content.html'/> <%namespace name='static' file='/static_content.html'/>
${static.css(group='style-vendor-tinymce-content', raw=True)} ${static.css(group='style-vendor-tinymce-content', raw=True)}
${static.css(group='style-vendor-tinymce-skin', raw=True)} ${static.css(group='style-vendor-tinymce-skin', raw=True)}
<script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/tinymce.full.min.js', raw=True)}" />
<script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js', raw=True)}" />
<div class="annotatable-wrapper"> <div class="annotatable-wrapper">
<div class="annotatable-header"> <div class="annotatable-header">
...@@ -167,7 +165,6 @@ ${static.css(group='style-vendor-tinymce-skin', raw=True)} ...@@ -167,7 +165,6 @@ ${static.css(group='style-vendor-tinymce-skin', raw=True)}
}; };
var imgURLRoot = "${settings.STATIC_URL}" + "js/vendor/ova/catch/img/"; var imgURLRoot = "${settings.STATIC_URL}" + "js/vendor/ova/catch/img/";
tinymce.baseURL = "${settings.STATIC_URL}" + "js/vendor/tinymce/js/tinymce";
//remove old instances //remove old instances
if (Annotator._instances.length !== 0) { if (Annotator._instances.length !== 0) {
...@@ -177,17 +174,24 @@ ${static.css(group='style-vendor-tinymce-skin', raw=True)} ...@@ -177,17 +174,24 @@ ${static.css(group='style-vendor-tinymce-skin', raw=True)}
//Load the plugin Video/Text Annotation //Load the plugin Video/Text Annotation
var ova = new OpenVideoAnnotation.Annotator($('#textHolder'),options); var ova = new OpenVideoAnnotation.Annotator($('#textHolder'),options);
var userId = ('${default_tab}'.toLowerCase() === 'instructor') ?
'${instructor_email}':
'${user.email}';
//Catch //Catch
var annotator = ova.annotator, var annotator = ova.annotator;
catchOptions = { var catchOptions = {
media:'text', media:'text',
externalLink:false, externalLink:false,
imageUrlRoot:imgURLRoot, imageUrlRoot:imgURLRoot,
showMediaSelector: false, showMediaSelector: false,
showPublicPrivate: true, showPublicPrivate: true,
userId:'${user.email}', userId:userId,
pagination:pagination,//Number of Annotations per load in the pagination, pagination:pagination,//Number of Annotations per load in the pagination,
flags:is_staff flags:is_staff,
}, default_tab: "${default_tab}",
Catch = new CatchAnnotation($('#catchDIV'),catchOptions); instructor_email: "${instructor_email}",
annotation_mode: "${annotation_mode}",
};
var Catch = new CatchAnnotation($('#catchDIV'),catchOptions);
</script> </script>
...@@ -2,9 +2,6 @@ ...@@ -2,9 +2,6 @@
<%namespace name='static' file='/static_content.html'/> <%namespace name='static' file='/static_content.html'/>
${static.css(group='style-vendor-tinymce-content', raw=True)} ${static.css(group='style-vendor-tinymce-content', raw=True)}
${static.css(group='style-vendor-tinymce-skin', raw=True)} ${static.css(group='style-vendor-tinymce-skin', raw=True)}
<script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/tinymce.full.min.js', raw=True)}" />
<script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js', raw=True)}" />
<div class="annotatable-wrapper"> <div class="annotatable-wrapper">
<div class="annotatable-header"> <div class="annotatable-header">
...@@ -168,7 +165,6 @@ ${static.css(group='style-vendor-tinymce-skin', raw=True)} ...@@ -168,7 +165,6 @@ ${static.css(group='style-vendor-tinymce-skin', raw=True)}
}; };
var imgURLRoot = "${settings.STATIC_URL}" + "js/vendor/ova/catch/img/"; var imgURLRoot = "${settings.STATIC_URL}" + "js/vendor/ova/catch/img/";
tinymce.baseURL = "${settings.STATIC_URL}" + "js/vendor/tinymce/js/tinymce";
//remove old instances //remove old instances
if (Annotator._instances.length !== 0) { if (Annotator._instances.length !== 0) {
...@@ -179,18 +175,24 @@ ${static.css(group='style-vendor-tinymce-skin', raw=True)} ...@@ -179,18 +175,24 @@ ${static.css(group='style-vendor-tinymce-skin', raw=True)}
var ova = new OpenVideoAnnotation.Annotator($('#videoHolder'),options); var ova = new OpenVideoAnnotation.Annotator($('#videoHolder'),options);
ova.annotator.addPlugin('Tags'); ova.annotator.addPlugin('Tags');
var userId = ('${default_tab}'.toLowerCase() === 'instructor') ?
'${instructor_email}':
'${user.email}';
//Catch //Catch
var annotator = ova.annotator, var annotator = ova.annotator;
catchOptions = { var catchOptions = {
media:'video', media:'video',
externalLink:false, externalLink:false,
imageUrlRoot:imgURLRoot, imageUrlRoot:imgURLRoot,
showMediaSelector: false, showMediaSelector: false,
showPublicPrivate: true, showPublicPrivate: true,
userId:'${user.email}', userId:userId,
pagination:pagination,//Number of Annotations per load in the pagination, pagination:pagination,//Number of Annotations per load in the pagination,
flags:is_staff flags:is_staff,
}, default_tab: "${default_tab}",
Catch = new CatchAnnotation($('#catchDIV'),catchOptions); instructor_email: "${instructor_email}",
annotation_mode: "${annotation_mode}",
};
var Catch = new CatchAnnotation($('#catchDIV'),catchOptions);
</script> </script>
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