Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cms/djangoapps/contentstore/views/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
OPEN_ENDED_COMPONENT_TYPES = ["combinedopenended", "peergrading"]
NOTE_COMPONENT_TYPES = ['notes']
ADVANCED_COMPONENT_TYPES = [
'textannotation',
'videoannotation',
'annotatable',
'word_cloud',
'graphical_slider_tool',
Expand Down
37 changes: 37 additions & 0 deletions cms/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,43 @@
};
</script>
<script type="text/javascript" src="${static.url("js/vendor/require.js")}"></script>

<link rel="stylesheet" href="${static.url('css/vendor/ova/edx-annotator.css')}" />
## ova
<!-- Annotator -->
<script src="${static.url('js/vendor/jquery.min.js')}"></script>
<script src="${static.url('js/vendor/ova/annotator-full.js')}"></script>
<link rel="stylesheet" href="${static.url('css/vendor/ova/annotator.css')}">
<!--video-js-->
<link href="http://vjs.zencdn.net/4.2/video-js.css" rel="stylesheet">
<script src="${static.url('js/vendor/ova/video.dev.js')}"></script>
<!--Youtube Pluging-->
<script src="${static.url('js/vendor/ova/vjs.youtube.js')}"></script>
<!--RangeSlider Pluging-->
<script src="${static.url('js/vendor/ova/rangeslider.js')}"></script>
<link href="${static.url('css/vendor/ova/rangeslider.css')}" rel="stylesheet">
<!--Share Pluging-->
<script src="${static.url('js/vendor/ova/share-annotator.js')}"></script>
<link href="${static.url('css/vendor/ova/share-annotator.css')}" rel="stylesheet">
<!--RichText Pluging-->
<script src="${static.url('js/vendor/ova/tinymce.min.js')}"></script>
<script src="${static.url('js/vendor/ova/richText-annotator.js')}"></script>
<link href="${static.url('css/vendor/ova/richText-annotator.css')}" rel="stylesheet">
<!--Reply Pluging-->
<script src="${static.url('js/vendor/ova/reply-annotator.js')}"></script>
<!--HighlightTags Pluging-->
<script src="${static.url('js/vendor/ova/tags-annotator.js')}"></script>
<link href="${static.url('css/vendor/ova/tags-annotator.css')}" rel="stylesheet">
<!--Flagging Pluging-->
<script src="${static.url('js/vendor/ova/flagging-annotator.js')}"></script>
<link href="${static.url('css/vendor/ova/flagging-annotator.css')}" rel="stylesheet">
<!--OpenVideoAnnotation Pluging-->
<script src="${static.url('js/vendor/ova/ova.js')}"></script>
<link href="${static.url('css/vendor/ova/ova.css')}" rel="stylesheet">
<!--Catch-->
<script src="${static.url('js/vendor/ova/catch/js/catch.js')}"></script>
<script src="${static.url('js/vendor/ova/catch/js/handlebars-1.1.2.js')}"></script>
<link href="${static.url('js/vendor/ova/catch/css/main.css')}" rel="stylesheet">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these scripts need to be loaded via require.js, instead of via <script> tags.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all, happy new year 2014
Thank you very much for reviewing the code
I going to answer all your reviews.
I do not know how to use Require.js. As soon as possible I will try to use this library, and make a new pull


## js templates
<script id="system-feedback-tpl" type="text/template">
Expand Down
2 changes: 2 additions & 0 deletions cms/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
# ajax view that actually does the work
url(r'^login_post$', 'student.views.login_user', name='login_post'),
url(r'^logout$', 'student.views.logout_user', name='logout'),

url(r'^token/', 'student.views.token', name="token"),#added token
)

# restful api
Expand Down
50 changes: 50 additions & 0 deletions common/djangoapps/student/firebase_token_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from array import array
from base64 import urlsafe_b64encode
import hashlib
import hmac
import sys
try:
import json
except ImportError:
import simplejson as json
import time
import datetime

__all__ = ['create_token']

TOKEN_SEP = '.'

def create_token(secret, data):
claims = data

return _encode_token(secret, claims)


if sys.version_info < (2, 7):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we support versions of Python other than 2.7? @wedaly @jzoldak, could one of you chime in?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We currently support only version 2.7

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it was more correct in this way.
Please, let me know if you want to change it

def _encode(bytes_data):
# Python 2.6 has problems with bytearrays in b64
encoded = urlsafe_b64encode(bytes(bytes_data))
return encoded.decode('utf-8').replace('=', '')
else:
def _encode(bytes):
encoded = urlsafe_b64encode(bytes)
return encoded.decode('utf-8').replace('=', '')


def _encode_json(obj):
return _encode(bytearray(json.dumps(obj), 'utf-8'))

def _sign(secret, to_sign):
def portable_bytes(s):
try:
return bytes(s, 'utf-8')
except TypeError:
return bytes(s)
return _encode(hmac.new(portable_bytes(secret), portable_bytes(to_sign), hashlib.sha256).digest())

def _encode_token(secret, claims):
encoded_header = _encode_json({'typ': 'JWT', 'alg': 'HS256'})
encoded_claims = _encode_json(claims)
secure_bits = '%s%s%s' % (encoded_header, TOKEN_SEP, encoded_claims)
sig = _sign(secret, secure_bits)
return '%s%s%s' % (secure_bits, TOKEN_SEP, sig)
17 changes: 17 additions & 0 deletions common/djangoapps/student/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1362,3 +1362,20 @@ def change_email_settings(request):
track.views.server_track(request, "change-email-settings", {"receive_emails": "no", "course": course_id}, page='dashboard')

return HttpResponse(json.dumps({'success': True}))

from student.firebase_token_generator import create_token
from django.http import HttpResponse

@login_required
def token(request):
import datetime
dtnow = datetime.datetime.now();dtutcnow = datetime.datetime.utcnow()
delta = dtnow - dtutcnow
hh,mm = divmod((delta.days * 24*60*60 + delta.seconds + 30) // 60, 60)
time = "%s%+02d:%02d" % (dtnow.isoformat(), hh, mm)
SECRET = '4c7f4d1c-8ac4-4e9f-84c8-b271c57fcac4'
custom_data = { "issuedAt": time, "consumerKey": "4c7f4d1c-8ac4-4e9f-84c8-b271c57fcac4", "userId": "username", "ttl": 86400}
token = create_token(SECRET, custom_data)
response = HttpResponse(token, mimetype="text/plain")

return response
2 changes: 2 additions & 0 deletions common/lib/xmodule/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
"wrapper = xmodule.wrapper_module:WrapperDescriptor",
"graphical_slider_tool = xmodule.gst_module:GraphicalSliderToolDescriptor",
"annotatable = xmodule.annotatable_module:AnnotatableDescriptor",
"textannotation = xmodule.textannotation_module:TextAnnotationDescriptor",
"videoannotation = xmodule.videoannotation_module:VideoAnnotationDescriptor",
"foldit = xmodule.foldit_module:FolditDescriptor",
"word_cloud = xmodule.word_cloud_module:WordCloudDescriptor",
"hidden = xmodule.hidden_module:HiddenDescriptor",
Expand Down
1 change: 1 addition & 0 deletions common/lib/xmodule/xmodule/modulestore/inheritance.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class InheritanceMixin(XBlockMixin):
due = Date(help="Date that this problem is due by", scope=Scope.settings)
giturl = String(help="url root for course data git repository", scope=Scope.settings)
xqa_key = String(help="DO NOT USE", scope=Scope.settings)
annotation_storage_url = String(help="Location of Annotation backend", scope=Scope.settings, default="http://your_annotation_storage.com", display_name = "annotation_storage_url")
graceperiod = Timedelta(
help="Amount of time after the due date that submissions will be accepted",
scope=Scope.settings
Expand Down
106 changes: 106 additions & 0 deletions common/lib/xmodule/xmodule/textannotation_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import logging

from lxml import etree
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 django.conf import settings

import textwrap
import xmodule.x_module

log = logging.getLogger(__name__)

class AnnotatableFields(object):
"""Fields for `TextModule` and `TextDescriptor`."""
data = String(help="XML data for the annotation", scope=Scope.content,
default=textwrap.dedent(
"""\
<annotatable>
<instructions>
<p>
Add the instructions to the assignment here.
</p>
</instructions>
<p>
Lorem ipsum dolor sit amet, at amet animal petentium nec. Id augue nemore postulant mea. Ex eam dicant noluisse expetenda, alia admodum abhorreant qui et. An ceteros expetenda mea, tale natum ipsum quo no, ut pro paulo alienum noluisse.
</p>
</annotatable>
"""))
display_name = String(
display_name="Display Name",
help="Display name for this module",
scope=Scope.settings,
default='Text Annotation',
)
tags = String(
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",
scope=Scope.settings,
default='imagery:red,parallelism:blue',
)
source = String(
display_name="Source/Citation",
help="Optional for citing source of any material used. Automatic citation can be done using <a href=\"http://easybib.com\">EasyBib</a>",
scope=Scope.settings,
default='None',
)

class TextAnnotationModule(AnnotatableFields, XModule):
js = {'coffee': [],
'js': []}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reformat:

js = {
    'coffee': [],
    'js': [],
}

# js_module_name = "TextAnnotation"
css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]}
icon_class = 'textannotation'

def __init__(self, *args, **kwargs):
XModule.__init__(self, *args, **kwargs)

xmltree = etree.fromstring(self.data)

self.instructions = self._extract_instructions(xmltree)
self.content = etree.tostring(xmltree, encoding='unicode')
#settings.LMS_BASE
#self.location.org
self.element_id = self.location.name
self.highlight_colors = ['yellow', 'orange', 'purple', 'blue', 'green']


def _render_content(self):
""" Renders annotatable content with annotation spans and returns HTML. """
xmltree = etree.fromstring(self.content)
if 'display_name' in xmltree.attrib:
del xmltree.attrib['display_name']

return etree.tostring(xmltree, encoding='unicode')

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

def get_html(self):
""" Renders parameters to template. """
context = {
'display_name': self.display_name_with_default,
'tag': self.tags,
'source':self.source,
'element_id': self.element_id,
'instructions_html': self.instructions,
'content_html': self._render_content(),
'annotation_storage':self.annotation_storage_url
}

return self.system.render_template('textannotation.html', context)


class TextAnnotationDescriptor(AnnotatableFields, RawDescriptor):
module_class = TextAnnotationModule
mako_template = "widgets/raw-edit.html"
Loading