diff --git a/common/lib/xmodule/xmodule/annotator_mixin.py b/common/lib/xmodule/xmodule/annotator_mixin.py
index aa597702db..93768f564c 100644
--- a/common/lib/xmodule/xmodule/annotator_mixin.py
+++ b/common/lib/xmodule/xmodule/annotator_mixin.py
@@ -6,7 +6,10 @@ from lxml import etree
from urlparse import urlparse
from os.path import splitext, basename
from HTMLParser import HTMLParser
+from xblock.core import Scope, String
+# Make '_' a no-op so we can scrape strings
+_ = lambda text: text
def get_instructions(xmltree):
""" Removes from the xmltree and returns them as a string, otherwise None. """
@@ -53,3 +56,37 @@ def html_to_text(html):
htmlstripper = MLStripper()
htmlstripper.feed(html)
return htmlstripper.get_data()
+
+
+class CommonAnnotatorMixin(object):
+ 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",
+ )
diff --git a/common/lib/xmodule/xmodule/imageannotation_module.py b/common/lib/xmodule/xmodule/imageannotation_module.py
index 14843f8885..e19f5a9100 100644
--- a/common/lib/xmodule/xmodule/imageannotation_module.py
+++ b/common/lib/xmodule/xmodule/imageannotation_module.py
@@ -7,7 +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, html_to_text
+from xmodule.annotator_mixin import CommonAnnotatorMixin, get_instructions, html_to_text
from xmodule.annotator_token import retrieve_token
from xblock.fragment import Fragment
@@ -62,7 +62,7 @@ class AnnotatableFields(object):
)
-class ImageAnnotationModule(AnnotatableFields, XModule):
+class ImageAnnotationModule(AnnotatableFields, CommonAnnotatorMixin, XModule):
'''Image Annotation Module'''
js = {
'coffee': [
@@ -97,12 +97,14 @@ class ImageAnnotationModule(AnnotatableFields, XModule):
context = {
'display_name': self.display_name_with_default,
'instructions_html': self.instructions,
- 'annotation_storage': self.annotation_storage_url,
'token': retrieve_token(self.user, self.annotation_token_secret),
'tag': self.instructor_tags,
'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))
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")
diff --git a/common/lib/xmodule/xmodule/textannotation_module.py b/common/lib/xmodule/xmodule/textannotation_module.py
index f561dd2c2c..1224dc2524 100644
--- a/common/lib/xmodule/xmodule/textannotation_module.py
+++ b/common/lib/xmodule/xmodule/textannotation_module.py
@@ -6,7 +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_mixin import CommonAnnotatorMixin, get_instructions
from xmodule.annotator_token import retrieve_token
from xblock.fragment import Fragment
import textwrap
@@ -47,11 +47,17 @@ class AnnotatableFields(object):
scope=Scope.settings,
default='None',
)
+ diacritics = String(
+ 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"))
-class TextAnnotationModule(AnnotatableFields, XModule):
+class TextAnnotationModule(AnnotatableFields, CommonAnnotatorMixin, XModule):
''' Text Annotation Module '''
js = {'coffee': [],
'js': []}
@@ -82,8 +88,12 @@ class TextAnnotationModule(AnnotatableFields, XModule):
'source': self.source,
'instructions_html': self.instructions,
'content_html': self.content,
- 'annotation_storage': self.annotation_storage_url,
'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,
}
fragment = Fragment(self.system.render_template('textannotation.html', context))
fragment.add_javascript_url("/static/js/vendor/tinymce/js/tinymce/tinymce.full.min.js")
diff --git a/common/lib/xmodule/xmodule/videoannotation_module.py b/common/lib/xmodule/xmodule/videoannotation_module.py
index d882d4e6a7..b07f9a700f 100644
--- a/common/lib/xmodule/xmodule/videoannotation_module.py
+++ b/common/lib/xmodule/xmodule/videoannotation_module.py
@@ -7,7 +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_mixin import CommonAnnotatorMixin, get_instructions, get_extension
from xmodule.annotator_token import retrieve_token
from xblock.fragment import Fragment
@@ -32,14 +32,24 @@ class AnnotatableFields(object):
display_name=_("Display Name"),
help=_("Display name for this module"),
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=""
)
- 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, CommonAnnotatorMixin, XModule):
'''Video Annotation Module'''
js = {
'coffee': [
@@ -85,8 +95,11 @@ class VideoAnnotationModule(AnnotatableFields, XModule):
'typeSource': extension,
'poster': self.poster_url,
'content_html': self.content,
- 'annotation_storage': self.annotation_storage_url,
'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))
fragment.add_javascript_url("/static/js/vendor/tinymce/js/tinymce/tinymce.full.min.js")
diff --git a/common/static/js/vendor/ova/OpenSeaDragonAnnotation.js b/common/static/js/vendor/ova/OpenSeaDragonAnnotation.js
index d8c2f595c0..938af6e8d3 100644
--- a/common/static/js/vendor/ova/OpenSeaDragonAnnotation.js
+++ b/common/static/js/vendor/ova/OpenSeaDragonAnnotation.js
@@ -380,19 +380,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
clickTimeThreshold: viewer.clickTimeThreshold,
clickDistThreshold: viewer.clickDistThreshold
});
-
- /* Set elements to the control menu */
- viewer.annotatorControl = viewer.wrapperAnnotation.element;
- if( viewer.toolbar ){
- viewer.toolbar.addControl(
- viewer.annotatorControl,
- {anchor: $.ControlAnchor.BOTTOM_RIGHT}
- );
- }else{
- viewer.addControl(
- viewer.annotatorControl,
- {anchor: $.ControlAnchor.TOP_LEFT}
- );
+ if(this.options.viewer.annotation_mode == "everyone" || this.options.viewer.flags){
+ /* Set elements to the control menu */
+ viewer.annotatorControl = viewer.wrapperAnnotation.element;
+ if( viewer.toolbar ){
+ viewer.toolbar.addControl(
+ viewer.annotatorControl,
+ {anchor: $.ControlAnchor.BOTTOM_RIGHT}
+ );
+ }else{
+ viewer.addControl(
+ viewer.annotatorControl,
+ {anchor: $.ControlAnchor.TOP_LEFT}
+ );
+ }
}
},
_reset: function(){
diff --git a/common/static/js/vendor/ova/catch/css/main.css b/common/static/js/vendor/ova/catch/css/main.css
index b79bd80e0a..5f5406c560 100644
--- a/common/static/js/vendor/ova/catch/css/main.css
+++ b/common/static/js/vendor/ova/catch/css/main.css
@@ -379,14 +379,14 @@
display:inline-block;
color:#302f2f;
font-family:arial;
- font-size:15px;
+ font-size:14px;
font-weight:bold;
padding:6px 24px;
text-decoration:none;
margin: 0px 0px 10px 0px;
cursor:pointer;
- width:140px;
+ width:115px;
text-align:center;
}
@@ -468,7 +468,7 @@
#mainCatch .searchbox input{
margin: 0;
padding: 0;
- width: 60%;
+ width: 50%;
margin-left: 10px;
display: inline;
float: left;
@@ -493,19 +493,28 @@
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{
opacity:0.5;
box-shadow: 2px 4px 5px #888888;
}
#mainCatch .selectors{
- width:40%;
+ width:45%;
position:relative;
float:left;
}
#mainCatch .searchbox{
- width:60%;
+ width:52%;
position:relative;
float:right;
}
@@ -515,6 +524,7 @@
position:relative;
padding-right:5px;
margin-top:8px;
+ font-size:14px;
}
#mainCatch .replies .replyItem .deleteReply{
diff --git a/common/static/js/vendor/ova/catch/js/catch.js b/common/static/js/vendor/ova/catch/js/catch.js
index 442873659f..a45b778d99 100644
--- a/common/static/js/vendor/ova/catch/js/catch.js
+++ b/common/static/js/vendor/ova/catch/js/catch.js
@@ -42,29 +42,29 @@ annotationList:
''+
''+
- 'User'+
+ gettext('User')+
'
'+
''+
- 'Annotation'+
+ gettext('Annotation')+
'
'+
'{{#if videoFormat}}'+
''+
- 'Start'+
+ gettext('Start')+
'
'+
''+
- 'End'+
+ gettext('End')+
'
'+
'{{/if}}'+
''+
- '#Replies'+
+ gettext('#Replies')+
'
'+
''+
- 'Date posted'+
+ gettext('Date posted')+
'
'+
''+
''+
@@ -73,30 +73,41 @@ annotationList:
'{{/each}}'+
''+
'',
+//Main->PublicPrivateInstructor
+annotationPublicPrivateInstructor:
+ ''+gettext('My Notes')+'myNotes
'+
+ '
'+gettext('Instructor')+'instructor
'+
+ '
'+gettext('Public')+'public
'+
+ ''+gettext('Search')+'
'+gettext('Clear')+'
',
+
//Main->PublicPrivate
annotationPublicPrivate:
- 'My NotesmyNotes
'+
- '
Publicpublic
'+
- '',
+ ''+gettext('My Notes')+'myNotes
'+
+ '
'+gettext('Public')+'public
'+
+ ''+gettext('Search')+'
'+gettext('Clear')+'
',
//Main->MediaSelector
annotationMediaSelector:
''+
'- '+
- 'Text'+
+ gettext('Text')+
'
'+
'- '+
- 'Video'+
+ gettext('Video')+
'
'+
- 'li class="ui-state-default" media="image">'+
- 'Image'+
+ '- '+
+ gettext('Image')+
'
'+
'
',
@@ -126,7 +137,7 @@ annotationReply:
''+
''+
'{{/if}}'+
- 'Delete
'+
+ ''+gettext('Delete')+'
'+
'
'+
''+
'{{#if this.text}}'+
@@ -233,13 +244,13 @@ annotationDetail:
''+
'
'+
- '
Reply
'+
+ '
'+gettext('Reply')+'
'+
'
Show Replies
'+
'{{#if authToEditButton}}'+
- '
Edit
'+
+ '
'+gettext('Edit')+'
'+
'{{/if}}'+
'{{#if authToDeleteButton}}'+
- '
Delete
'+
+ '
'+gettext('Delete')+'
'+
'{{/if}}'+
'
'+
@@ -248,7 +259,7 @@ annotationDetail:
'{{#if tags}}'+
'