Repository navigation
Annotation tools #2024
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Annotation tools #2024
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We currently support only version 2.7
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought it was more correct in this way. |
||
| 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) | ||
| 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': []} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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" | ||
There was a problem hiding this comment.
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.There was a problem hiding this comment.
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