Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ GEM
sass (>= 3.2.0)
thor
colorize (0.5.8)
ffi (1.9.0)
ffi (1.9.3)
launchy (2.1.2)
addressable (~> 2.3)
neat (1.4.0)
bourbon (>= 2.1)
sass (>= 3.2)
rake (10.0.4)
rb-fsevent (0.9.3)
rb-inotify (0.9.2)
rb-fsevent (0.9.4)
rb-inotify (0.9.3)
ffi (>= 0.5.0)
sass (3.2.12)
sys-proctable (0.9.3)
Expand Down
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
29 changes: 29 additions & 0 deletions cms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,16 @@
'css/vendor/jquery.qtip.min.css',
'js/vendor/markitup/skins/simple/style.css',
'js/vendor/markitup/sets/wiki/style.css',
'css/vendor/ova/edx-annotator.css',
'css/vendor/ova/annotator.css',
'css/vendor/ova/video-js.min.css',
'css/vendor/ova/rangeslider.css',
'css/vendor/ova/share-annotator.css',
'css/vendor/ova/richText-annotator.css',
'css/vendor/ova/tags-annotator.css',
'css/vendor/ova/flagging-annotator.css',
'css/vendor/ova/ova.css',
'js/vendor/ova/catch/css/main.css'
],
'output_filename': 'css/cms-style-vendor.css',
},
Expand Down Expand Up @@ -291,6 +301,25 @@
'output_filename': 'js/cms-modules.js',
'test_order': 1
},
'main_vendor': {
'source_filenames': [
'js/vendor/ova/annotator-full.js',
'js/vendor/ova/video.dev.js',
'js/vendor/ova/vjs.youtube.js',
'js/vendor/ova/rangeslider.js',
'js/vendor/ova/share-annotator.js',
'js/vendor/ova/tinymce.min.js',
'js/vendor/ova/richText-annotator.js',
'js/vendor/ova/reply-annotator.js',
'js/vendor/ova/tags-annotator.js',
'js/vendor/ova/flagging-annotator.js',
'js/vendor/ova/jquery-Watch.js',
'js/vendor/ova/ova.js',
'js/vendor/ova/catch/js/catch.js',
'js/vendor/ova/catch/js/handlebars-1.1.2.js'
],
'output_filename': 'js/cms-main_vendor.js',
},
}

PIPELINE_COMPILERS = (
Expand Down
2 changes: 1 addition & 1 deletion cms/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@
};
</script>
<script type="text/javascript" src="${static.url("js/vendor/require.js")}"></script>

## js templates
<script id="system-feedback-tpl" type="text/template">
<%static:include path="js/system-feedback.underscore" />
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
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
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
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
104 changes: 104 additions & 0 deletions common/lib/xmodule/xmodule/textannotation_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
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': []
}
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')
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