Merge remote-tracking branch 'origin/master' into feature/cale/cms-master
This commit is contained in:
@@ -28,6 +28,8 @@ from xmodule.x_module import ModuleSystem
|
||||
from xmodule.error_module import ErrorDescriptor, NonStaffErrorDescriptor
|
||||
from xmodule_modifiers import replace_course_urls, replace_static_urls, add_histogram, wrap_xmodule
|
||||
|
||||
from statsd import statsd
|
||||
|
||||
log = logging.getLogger("mitx.courseware")
|
||||
|
||||
|
||||
@@ -335,7 +337,7 @@ def xqueue_callback(request, course_id, userid, id, dispatch):
|
||||
'''
|
||||
# Test xqueue package, which we expect to be:
|
||||
# xpackage = {'xqueue_header': json.dumps({'lms_key':'secretkey',...}),
|
||||
# 'xqueue_body' : 'Message from grader}
|
||||
# 'xqueue_body' : 'Message from grader'}
|
||||
get = request.POST.copy()
|
||||
for key in ['xqueue_header', 'xqueue_body']:
|
||||
if not get.has_key(key):
|
||||
@@ -370,7 +372,8 @@ def xqueue_callback(request, course_id, userid, id, dispatch):
|
||||
# We go through the "AJAX" path
|
||||
# So far, the only dispatch from xqueue will be 'score_update'
|
||||
try:
|
||||
ajax_return = instance.handle_ajax(dispatch, get) # Can ignore the "ajax" return in 'xqueue_callback'
|
||||
# Can ignore the return value--not used for xqueue_callback
|
||||
instance.handle_ajax(dispatch, get)
|
||||
except:
|
||||
log.exception("error processing ajax call")
|
||||
raise
|
||||
@@ -382,6 +385,15 @@ def xqueue_callback(request, course_id, userid, id, dispatch):
|
||||
if instance_module.grade != oldgrade or instance_module.state != old_instance_state:
|
||||
instance_module.save()
|
||||
|
||||
#Bin score into range and increment stats
|
||||
score_bucket=get_score_bucket(instance_module.grade, instance_module.max_grade)
|
||||
org, course_num, run=course_id.split("/")
|
||||
statsd.increment("lms.courseware.question_answered",
|
||||
tags=["org:{0}".format(org),
|
||||
"course:{0}".format(course_num),
|
||||
"run:{0}".format(run),
|
||||
"score_bucket:{0}".format(score_bucket),
|
||||
"type:xqueue"])
|
||||
return HttpResponse("")
|
||||
|
||||
|
||||
@@ -466,6 +478,17 @@ def modx_dispatch(request, dispatch, location, course_id):
|
||||
instance_module.max_grade != old_instance_max_grade):
|
||||
instance_module.save()
|
||||
|
||||
#Bin score into range and increment stats
|
||||
score_bucket=get_score_bucket(instance_module.grade, instance_module.max_grade)
|
||||
org, course_num, run=course_id.split("/")
|
||||
statsd.increment("lms.courseware.question_answered",
|
||||
tags=["org:{0}".format(org),
|
||||
"course:{0}".format(course_num),
|
||||
"run:{0}".format(run),
|
||||
"score_bucket:{0}".format(score_bucket),
|
||||
"type:ajax"])
|
||||
|
||||
|
||||
if shared_module is not None:
|
||||
shared_module.state = instance.get_shared_state()
|
||||
if shared_module.state != old_shared_state:
|
||||
@@ -511,4 +534,17 @@ def preview_chemcalc(request):
|
||||
return HttpResponse(json.dumps(result))
|
||||
|
||||
|
||||
def get_score_bucket(grade,max_grade):
|
||||
"""
|
||||
Function to split arbitrary score ranges into 3 buckets.
|
||||
Used with statsd tracking.
|
||||
"""
|
||||
score_bucket="incorrect"
|
||||
if(grade>0 and grade<max_grade):
|
||||
score_bucket="partial"
|
||||
elif(grade==max_grade):
|
||||
score_bucket="correct"
|
||||
|
||||
return score_bucket
|
||||
|
||||
|
||||
|
||||
@@ -1,18 +1,38 @@
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django_comment_client.models import Permission, Role
|
||||
from django_comment_client.models import Role
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
args = 'user role course_id'
|
||||
help = 'Assign a role to a user'
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option('--remove',
|
||||
action='store_true',
|
||||
dest='remove',
|
||||
default=False,
|
||||
help='Remove the role instead of adding it'),
|
||||
)
|
||||
|
||||
args = '<user|email> <role> <course_id>'
|
||||
help = 'Assign a discussion forum role to a user '
|
||||
|
||||
def handle(self, *args, **options):
|
||||
role = Role.objects.get(name=args[1], course_id=args[2])
|
||||
if len(args) != 3:
|
||||
raise CommandError('Usage is assign_role {0}'.format(self.args))
|
||||
|
||||
if '@' in args[0]:
|
||||
user = User.objects.get(email=args[0])
|
||||
name_or_email, role, course_id = args
|
||||
|
||||
role = Role.objects.get(name=role, course_id=course_id)
|
||||
|
||||
if '@' in name_or_email:
|
||||
user = User.objects.get(email=name_or_email)
|
||||
else:
|
||||
user = User.objects.get(username=args[0])
|
||||
user = User.objects.get(username=name_or_email)
|
||||
|
||||
user.roles.add(role)
|
||||
if options['remove']:
|
||||
user.roles.remove(role)
|
||||
else:
|
||||
user.roles.add(role)
|
||||
|
||||
print 'Success!'
|
||||
|
||||
@@ -2,6 +2,7 @@ from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
import logging
|
||||
|
||||
from courseware.courses import get_course_by_id
|
||||
|
||||
class Role(models.Model):
|
||||
name = models.CharField(max_length=30, null=False, blank=False)
|
||||
@@ -23,6 +24,12 @@ class Role(models.Model):
|
||||
self.permissions.add(Permission.objects.get_or_create(name=permission)[0])
|
||||
|
||||
def has_permission(self, permission):
|
||||
course = get_course_by_id(self.course_id)
|
||||
if self.name == "Student" and \
|
||||
(permission.startswith('edit') or permission.startswith('update') or permission.startswith('create')) and \
|
||||
(not course.forum_posts_allowed):
|
||||
return False
|
||||
|
||||
return self.permissions.filter(name=permission).exists()
|
||||
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
|
||||
)
|
||||
|
||||
STUDENT_FILEUPLOAD_MAX_SIZE = 4*1000*1000 # 4 MB
|
||||
MAX_FILEUPLOADS_PER_INPUT = 10
|
||||
MAX_FILEUPLOADS_PER_INPUT = 20
|
||||
|
||||
# FIXME:
|
||||
# We should have separate S3 staged URLs in case we need to make changes to
|
||||
|
||||
@@ -136,6 +136,14 @@
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.0em;
|
||||
font-family: $sans-serif;
|
||||
font-weight: 700;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<%! from django_comment_client.permissions import has_permission %>
|
||||
<%inherit file="../courseware/course_navigation.html" />
|
||||
|
||||
<%block name="extratabs">
|
||||
% if has_permission(user, 'create_thread', course.id):
|
||||
<li class="right"><a href="#" class="new-post-btn"><span class="new-post-icon"></span>New Post</a></li>
|
||||
% endif
|
||||
</%block>
|
||||
@@ -3,4 +3,6 @@
|
||||
<div class="discussion-module" data-discussion-id="${discussion_id | h}">
|
||||
<a class="discussion-show control-button" href="javascript:void(0)" data-discussion-id="${discussion_id | h}"><span class="show-hide-discussion-icon"></span><span class="button-text">Show Discussion</span></a>
|
||||
<a href="#" class="new-post-btn"><span class="new-post-icon"></span>New Post</a>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
<%! from django_comment_client.permissions import has_permission %>
|
||||
|
||||
<script type="text/template" id="thread-template">
|
||||
<article class="discussion-article" data-id="${'<%- id %>'}">
|
||||
<div class="thread-content-wrapper"></div>
|
||||
@@ -7,6 +9,7 @@
|
||||
<div class="post-status-closed bottom-post-status" style="display: none">
|
||||
This thread is closed.
|
||||
</div>
|
||||
% if course is UNDEFINED or has_permission(user, 'create_comment', course.id):
|
||||
<form class="discussion-reply-new" data-id="${'<%- id %>'}">
|
||||
<h4>Post a response:</h4>
|
||||
<ul class="discussion-errors"></ul>
|
||||
@@ -15,6 +18,7 @@
|
||||
<a class="discussion-submit-post control-button" href="#">Submit</a>
|
||||
</div>
|
||||
</form>
|
||||
% endif
|
||||
</article>
|
||||
</script>
|
||||
|
||||
@@ -75,6 +79,7 @@
|
||||
<div class="discussion-response"></div>
|
||||
<ol class="comments">
|
||||
<li class="new-comment response-local">
|
||||
% if course is UNDEFINED or has_permission(user, 'create_sub_comment', course.id):
|
||||
<form class="comment-form" data-id="${'<%- wmdId %>'}">
|
||||
<ul class="discussion-errors"></ul>
|
||||
<div class="comment-body" data-id="${'<%- wmdId %>'}"
|
||||
@@ -83,6 +88,7 @@
|
||||
<a class="discussion-submit-comment control-button" href="#">Submit</a>
|
||||
</div>
|
||||
</form>
|
||||
% endif
|
||||
</li>
|
||||
</ol>
|
||||
</script>
|
||||
|
||||
11
lms/templates/google_analytics.html
Normal file
11
lms/templates/google_analytics.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-35248639-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
@@ -21,20 +21,9 @@
|
||||
<meta name="path_prefix" content="${MITX_ROOT_URL}">
|
||||
|
||||
% if not course:
|
||||
<script type="text/javascript">
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-35248639-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
|
||||
</script>
|
||||
<%include file="google_analytics.html" />
|
||||
% endif
|
||||
|
||||
</head>
|
||||
|
||||
<body class="<%block name='bodyclass'/>">
|
||||
|
||||
@@ -7,7 +7,12 @@
|
||||
|
||||
<%inherit file="../main.html" />
|
||||
|
||||
<%block name="headextra">
|
||||
<%include file="../google_analytics.html" />
|
||||
</%block>
|
||||
|
||||
<%block name="js_extra">
|
||||
|
||||
% if not registered:
|
||||
%if user.is_authenticated():
|
||||
## If the user is authenticated, clicking the enroll button just submits a form
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<%namespace name='static' file='../static_content.html'/>
|
||||
|
||||
<%inherit file="../main.html" />
|
||||
|
||||
<%block name="title"><title>Jobs</title></%block>
|
||||
@@ -50,12 +49,79 @@
|
||||
<p>If you are interested in this position, please send an email to <a href="mailto:jobs@edx.org">jobs@edx.org</a></p>
|
||||
</div>
|
||||
</article>
|
||||
<article id="learning-designer" class="job">
|
||||
<div class="inner-wrapper">
|
||||
<h3>Learning Designer/Interaction Learning Designer </h3>
|
||||
<p>The Learning Designer will work as part of the content and development team to plan, develop and deliver highly engaging and media rich online courses. The learning designer will be a flexible thinker, able to determine and apply sound pedagogical strategies to unique situations and a diverse set of academic disciplines. This is a 6-12 months contract opportunity.</p>
|
||||
<h4>Specific Responsibilities include: </h4>
|
||||
<ul>
|
||||
<li>Work with producers, product developers and course staff on implementing instructional design approaches in the development of media and other course materials. </li>
|
||||
<li>Articulate learning objectives and align them to content design strategy and assessments. </li>
|
||||
<li>Write effective instructional text, and audio and video scripts. </li>
|
||||
<li>Coordinate workflows with video and content development team</li>
|
||||
<li>Identify best practices and share these with the course staff and faculty as needed. </li>
|
||||
<li>Create course communication style guides. Train and coach teaching staff on best practices for communication and discussion management. </li>
|
||||
<li>Develop use case guides as needed on the use of edX courseware and new technologies. </li>
|
||||
<li>Serve as a liaison to instructional design teams located at X universities. </li>
|
||||
<li>Design peer review processes to be used by learners in selected courses. </li>
|
||||
<li>Ability to apply game-based learning theory and design into selected courses as appropriate.</li>
|
||||
<li>Use learning analytics and metrics to inform course design and revision process. </li>
|
||||
<li>Work closely with the Content Research Director on articulating best practices for MOOC teaching and learning and course design.</li>
|
||||
<li>Assist in the development of pilot courses used for sponsored research initiatives. </li>
|
||||
</ul>
|
||||
<h4>Qualifications:</h4>
|
||||
<p>Master's Degree in Educational Technology, Instructional Design or related field. Experience in higher education with additional experience in a start-up or research environment desirable. Excellent interpersonal and communication (written and verbal), project management, problem-solving and time management skills. The ability to be flexible with projects and to work on multiple courses essential. Ability to meet deadlines and manage expectations of constituents. Capacity to develop new and relevant technology skills. Experience using game theory design and learning analytics to inform instructional design decisions and strategy.</p>
|
||||
<h4>Technical Skills:</h4>
|
||||
<p>Video and screencasting experience. LMS Platform experience, xml, HTML, CSS, Adobe Design Suite, Camtasia or Captivate experience. Experience with web 2.0 collaboration tools.</p>
|
||||
<p>If you are interested in this position, please send an email to <a href="mailto:jobs@edx.org">jobs@edx.org</a></p>
|
||||
</div>
|
||||
</article>
|
||||
<article id="production-coordinator" class="job">
|
||||
<div class="inner-wrapper">
|
||||
<h3>Production Coordinator</h3>
|
||||
<p>The Production Coordinator supports video editors and course staff in all video related tasks, such as ingesting footage, transcoding, tracking live dates, transcriptions, organizing project deliverables and archiving completed projects.</p>
|
||||
<h4>Primary responsibilities:</h4>
|
||||
<ul>
|
||||
<li>organize, track, and manage video and associated assets across the video workflow</li>
|
||||
<li>manage project data and spreadsheets</li>
|
||||
<li>route incoming source footage, and apply metadata tags</li>
|
||||
<li>run encoding/transcoding jobs </li>
|
||||
<li>prepare and process associated video assets, such as slides and image files</li>
|
||||
<li>manage the transcription process </li>
|
||||
<ul type="circle">
|
||||
<li>traffic files among project staff and video transcription services</li>
|
||||
<li>coordinate transcript reviews with course staff</li>
|
||||
<li>integrate transcripts in course pages</li>
|
||||
</ul>
|
||||
<li>other video-related tasks as assigned.</li>
|
||||
</ul>
|
||||
<br/>
|
||||
<h4>Qualifications</h4>
|
||||
<p>The ideal candidate for the Production Coordinator position will have</p>
|
||||
<ul>
|
||||
<li>relentless attention to detail</li>
|
||||
<li>ability to communicate and collaborate effectively across the organization</li>
|
||||
<li>knowledge and understanding of digital media production tools and processes</li>
|
||||
<li>experience with compression techniques, image processing, and presentation software preferred</li>
|
||||
<li>proficiency with standard office applications </li>
|
||||
<ul type="circle">
|
||||
<li>spreadsheets</li>
|
||||
<li>word processing</li>
|
||||
<li>presentation</li>
|
||||
</ul>
|
||||
<li>experience with web publishing, e.g., HTML, XML, CSS, a plus</li>
|
||||
</ul>
|
||||
<p>If you are interested in this position, please send an email to <a href="mailto:jobs@edx.org">jobs@edx.org</a></p>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
<section class="jobs-sidebar">
|
||||
<h2>Positions</h2>
|
||||
<nav>
|
||||
<a href="#content-engineer">EdX Content Engineer</a>
|
||||
<a href="#platform-developer">Platform Developer</a>
|
||||
<a href="#learning-designer">Learning Designer</a>
|
||||
<a href="#production-coordinator">Production Coordinator</a>
|
||||
</nav>
|
||||
<h2>How to Apply</h2>
|
||||
<p>E-mail your resume, coverletter and any other materials to <a href="mailto:jobs@edx.org">jobs@edx.org</a></p>
|
||||
|
||||
Reference in New Issue
Block a user