Merge branch 'master' into feature/christina/fields
This commit is contained in:
@@ -2,7 +2,7 @@ from student.models import (User, UserProfile, Registration,
|
||||
CourseEnrollmentAllowed, CourseEnrollment)
|
||||
from django.contrib.auth.models import Group
|
||||
from datetime import datetime
|
||||
from factory import DjangoModelFactory, Factory, SubFactory, PostGenerationMethodCall
|
||||
from factory import DjangoModelFactory, Factory, SubFactory, PostGenerationMethodCall, post_generation
|
||||
from uuid import uuid4
|
||||
|
||||
|
||||
@@ -45,6 +45,16 @@ class UserFactory(DjangoModelFactory):
|
||||
last_login = datetime(2012, 1, 1)
|
||||
date_joined = datetime(2011, 1, 1)
|
||||
|
||||
@post_generation
|
||||
def profile(obj, create, extracted, **kwargs):
|
||||
if create:
|
||||
obj.save()
|
||||
return UserProfileFactory.create(user=obj, **kwargs)
|
||||
elif kwargs:
|
||||
raise Exception("Cannot build a user profile without saving the user")
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class AdminFactory(UserFactory):
|
||||
is_staff = True
|
||||
|
||||
@@ -1,16 +1,280 @@
|
||||
"""
|
||||
This file demonstrates writing tests using the unittest module. These will pass
|
||||
when you run "manage.py test".
|
||||
|
||||
Replace this with more appropriate tests for your application.
|
||||
"""
|
||||
"""Tests for the util package"""
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.http import Http404
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
from student.tests.factories import UserFactory
|
||||
from util import views
|
||||
from zendesk import ZendeskError
|
||||
import json
|
||||
import mock
|
||||
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
def test_basic_addition(self):
|
||||
@mock.patch.dict("django.conf.settings.MITX_FEATURES", {"ENABLE_FEEDBACK_SUBMISSION": True})
|
||||
@override_settings(ZENDESK_URL="dummy", ZENDESK_USER="dummy", ZENDESK_API_KEY="dummy")
|
||||
@mock.patch("util.views._ZendeskApi", autospec=True)
|
||||
class SubmitFeedbackViaZendeskTest(TestCase):
|
||||
def setUp(self):
|
||||
"""Set up data for the test case"""
|
||||
self._request_factory = RequestFactory()
|
||||
self._anon_user = AnonymousUser()
|
||||
self._auth_user = UserFactory.create(
|
||||
email="test@edx.org",
|
||||
username="test",
|
||||
profile__name="Test User"
|
||||
)
|
||||
# This contains a tag to ensure that tags are submitted correctly
|
||||
self._anon_fields = {
|
||||
"email": "test@edx.org",
|
||||
"name": "Test User",
|
||||
"subject": "a subject",
|
||||
"details": "some details",
|
||||
"tag": "a tag"
|
||||
}
|
||||
# This does not contain a tag to ensure that tag is optional
|
||||
self._auth_fields = {"subject": "a subject", "details": "some details"}
|
||||
|
||||
def _test_request(self, user, fields):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
Generate a request and invoke the view, returning the response.
|
||||
|
||||
The request will be a POST request from the given `user`, with the given
|
||||
`fields` in the POST body.
|
||||
"""
|
||||
self.assertEqual(1 + 1, 2)
|
||||
req = self._request_factory.post(
|
||||
"/submit_feedback",
|
||||
data=fields,
|
||||
HTTP_REFERER="test_referer",
|
||||
HTTP_USER_AGENT="test_user_agent"
|
||||
)
|
||||
req.user = user
|
||||
return views.submit_feedback_via_zendesk(req)
|
||||
|
||||
def _assert_bad_request(self, response, field, zendesk_mock_class):
|
||||
"""
|
||||
Assert that the given `response` contains correct failure data.
|
||||
|
||||
It should have a 400 status code, and its content should be a JSON
|
||||
object containing the specified `field` and an `error`.
|
||||
"""
|
||||
self.assertEqual(response.status_code, 400)
|
||||
resp_json = json.loads(response.content)
|
||||
self.assertTrue("field" in resp_json)
|
||||
self.assertEqual(resp_json["field"], field)
|
||||
self.assertTrue("error" in resp_json)
|
||||
# There should be absolutely no interaction with Zendesk
|
||||
self.assertFalse(zendesk_mock_class.return_value.mock_calls)
|
||||
|
||||
def _test_bad_request_omit_field(self, user, fields, omit_field, zendesk_mock_class):
|
||||
"""
|
||||
Invoke the view with a request missing a field and assert correctness.
|
||||
|
||||
The request will be a POST request from the given `user`, with POST
|
||||
fields taken from `fields` minus the entry specified by `omit_field`.
|
||||
The response should have a 400 (bad request) status code and specify
|
||||
the invalid field and an error message, and the Zendesk API should not
|
||||
have been invoked.
|
||||
"""
|
||||
filtered_fields = {k: v for (k, v) in fields.items() if k != omit_field}
|
||||
resp = self._test_request(user, filtered_fields)
|
||||
self._assert_bad_request(resp, omit_field, zendesk_mock_class)
|
||||
|
||||
def _test_bad_request_empty_field(self, user, fields, empty_field, zendesk_mock_class):
|
||||
"""
|
||||
Invoke the view with an empty field and assert correctness.
|
||||
|
||||
The request will be a POST request from the given `user`, with POST
|
||||
fields taken from `fields`, replacing the entry specified by
|
||||
`empty_field` with the empty string. The response should have a 400
|
||||
(bad request) status code and specify the invalid field and an error
|
||||
message, and the Zendesk API should not have been invoked.
|
||||
"""
|
||||
altered_fields = fields.copy()
|
||||
altered_fields[empty_field] = ""
|
||||
resp = self._test_request(user, altered_fields)
|
||||
self._assert_bad_request(resp, empty_field, zendesk_mock_class)
|
||||
|
||||
def _test_success(self, user, fields):
|
||||
"""
|
||||
Generate a request, invoke the view, and assert success.
|
||||
|
||||
The request will be a POST request from the given `user`, with the given
|
||||
`fields` in the POST body. The response should have a 200 (success)
|
||||
status code.
|
||||
"""
|
||||
resp = self._test_request(user, fields)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
def test_bad_request_anon_user_no_name(self, zendesk_mock_class):
|
||||
"""Test a request from an anonymous user not specifying `name`."""
|
||||
self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "name", zendesk_mock_class)
|
||||
self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "name", zendesk_mock_class)
|
||||
|
||||
def test_bad_request_anon_user_no_email(self, zendesk_mock_class):
|
||||
"""Test a request from an anonymous user not specifying `email`."""
|
||||
self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "email", zendesk_mock_class)
|
||||
self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "email", zendesk_mock_class)
|
||||
|
||||
def test_bad_request_anon_user_no_subject(self, zendesk_mock_class):
|
||||
"""Test a request from an anonymous user not specifying `subject`."""
|
||||
self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "subject", zendesk_mock_class)
|
||||
self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "subject", zendesk_mock_class)
|
||||
|
||||
def test_bad_request_anon_user_no_details(self, zendesk_mock_class):
|
||||
"""Test a request from an anonymous user not specifying `details`."""
|
||||
self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "details", zendesk_mock_class)
|
||||
self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "details", zendesk_mock_class)
|
||||
|
||||
def test_valid_request_anon_user(self, zendesk_mock_class):
|
||||
"""
|
||||
Test a valid request from an anonymous user.
|
||||
|
||||
The response should have a 200 (success) status code, and a ticket with
|
||||
the given information should have been submitted via the Zendesk API.
|
||||
"""
|
||||
zendesk_mock_instance = zendesk_mock_class.return_value
|
||||
zendesk_mock_instance.create_ticket.return_value = 42
|
||||
self._test_success(self._anon_user, self._anon_fields)
|
||||
expected_calls = [
|
||||
mock.call.create_ticket(
|
||||
{
|
||||
"ticket": {
|
||||
"requester": {"name": "Test User", "email": "test@edx.org"},
|
||||
"subject": "a subject",
|
||||
"comment": {"body": "some details"},
|
||||
"tags": ["a tag"]
|
||||
}
|
||||
}
|
||||
),
|
||||
mock.call.update_ticket(
|
||||
42,
|
||||
{
|
||||
"ticket": {
|
||||
"comment": {
|
||||
"public": False,
|
||||
"body":
|
||||
"Additional information:\n\n"
|
||||
"HTTP_USER_AGENT: test_user_agent\n"
|
||||
"HTTP_REFERER: test_referer"
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
]
|
||||
self.assertEqual(zendesk_mock_instance.mock_calls, expected_calls)
|
||||
|
||||
def test_bad_request_auth_user_no_subject(self, zendesk_mock_class):
|
||||
"""Test a request from an authenticated user not specifying `subject`."""
|
||||
self._test_bad_request_omit_field(self._auth_user, self._auth_fields, "subject", zendesk_mock_class)
|
||||
self._test_bad_request_empty_field(self._auth_user, self._auth_fields, "subject", zendesk_mock_class)
|
||||
|
||||
def test_bad_request_auth_user_no_details(self, zendesk_mock_class):
|
||||
"""Test a request from an authenticated user not specifying `details`."""
|
||||
self._test_bad_request_omit_field(self._auth_user, self._auth_fields, "details", zendesk_mock_class)
|
||||
self._test_bad_request_empty_field(self._auth_user, self._auth_fields, "details", zendesk_mock_class)
|
||||
|
||||
def test_valid_request_auth_user(self, zendesk_mock_class):
|
||||
"""
|
||||
Test a valid request from an authenticated user.
|
||||
|
||||
The response should have a 200 (success) status code, and a ticket with
|
||||
the given information should have been submitted via the Zendesk API.
|
||||
"""
|
||||
zendesk_mock_instance = zendesk_mock_class.return_value
|
||||
zendesk_mock_instance.create_ticket.return_value = 42
|
||||
self._test_success(self._auth_user, self._auth_fields)
|
||||
expected_calls = [
|
||||
mock.call.create_ticket(
|
||||
{
|
||||
"ticket": {
|
||||
"requester": {"name": "Test User", "email": "test@edx.org"},
|
||||
"subject": "a subject",
|
||||
"comment": {"body": "some details"},
|
||||
"tags": []
|
||||
}
|
||||
}
|
||||
),
|
||||
mock.call.update_ticket(
|
||||
42,
|
||||
{
|
||||
"ticket": {
|
||||
"comment": {
|
||||
"public": False,
|
||||
"body":
|
||||
"Additional information:\n\n"
|
||||
"username: test\n"
|
||||
"HTTP_USER_AGENT: test_user_agent\n"
|
||||
"HTTP_REFERER: test_referer"
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
]
|
||||
self.assertEqual(zendesk_mock_instance.mock_calls, expected_calls)
|
||||
|
||||
def test_get_request(self, zendesk_mock_class):
|
||||
"""Test that a GET results in a 405 even with all required fields"""
|
||||
req = self._request_factory.get("/submit_feedback", data=self._anon_fields)
|
||||
req.user = self._anon_user
|
||||
resp = views.submit_feedback_via_zendesk(req)
|
||||
self.assertEqual(resp.status_code, 405)
|
||||
self.assertIn("Allow", resp)
|
||||
self.assertEqual(resp["Allow"], "POST")
|
||||
# There should be absolutely no interaction with Zendesk
|
||||
self.assertFalse(zendesk_mock_class.mock_calls)
|
||||
|
||||
def test_zendesk_error_on_create(self, zendesk_mock_class):
|
||||
"""
|
||||
Test Zendesk returning an error on ticket creation.
|
||||
|
||||
We should return a 500 error with no body
|
||||
"""
|
||||
err = ZendeskError(msg="", error_code=404)
|
||||
zendesk_mock_instance = zendesk_mock_class.return_value
|
||||
zendesk_mock_instance.create_ticket.side_effect = err
|
||||
resp = self._test_request(self._anon_user, self._anon_fields)
|
||||
self.assertEqual(resp.status_code, 500)
|
||||
self.assertFalse(resp.content)
|
||||
|
||||
def test_zendesk_error_on_update(self, zendesk_mock_class):
|
||||
"""
|
||||
Test for Zendesk returning an error on ticket update.
|
||||
|
||||
If Zendesk returns any error on ticket update, we return a 200 to the
|
||||
browser because the update contains additional information that is not
|
||||
necessary for the user to have submitted their feedback.
|
||||
"""
|
||||
err = ZendeskError(msg="", error_code=500)
|
||||
zendesk_mock_instance = zendesk_mock_class.return_value
|
||||
zendesk_mock_instance.update_ticket.side_effect = err
|
||||
resp = self._test_request(self._anon_user, self._anon_fields)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
@mock.patch.dict("django.conf.settings.MITX_FEATURES", {"ENABLE_FEEDBACK_SUBMISSION": False})
|
||||
def test_not_enabled(self, zendesk_mock_class):
|
||||
"""
|
||||
Test for Zendesk submission not enabled in `settings`.
|
||||
|
||||
We should raise Http404.
|
||||
"""
|
||||
with self.assertRaises(Http404):
|
||||
self._test_request(self._anon_user, self._anon_fields)
|
||||
|
||||
def test_zendesk_not_configured(self, zendesk_mock_class):
|
||||
"""
|
||||
Test for Zendesk not fully configured in `settings`.
|
||||
|
||||
For each required configuration parameter, test that setting it to
|
||||
`None` causes an otherwise valid request to return a 500 error.
|
||||
"""
|
||||
def test_case(missing_config):
|
||||
with mock.patch(missing_config, None):
|
||||
with self.assertRaises(Exception):
|
||||
self._test_request(self._anon_user, self._anon_fields)
|
||||
|
||||
test_case("django.conf.settings.ZENDESK_URL")
|
||||
test_case("django.conf.settings.ZENDESK_USER")
|
||||
test_case("django.conf.settings.ZENDESK_API_KEY")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
import pprint
|
||||
import sys
|
||||
|
||||
@@ -7,15 +8,21 @@ from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.context_processors import csrf
|
||||
from django.core.mail import send_mail
|
||||
from django.http import Http404
|
||||
from django.http import HttpResponse
|
||||
from django.core.validators import ValidationError, validate_email
|
||||
from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed, HttpResponseServerError
|
||||
from django.shortcuts import redirect
|
||||
from django_future.csrf import ensure_csrf_cookie
|
||||
from mitxmako.shortcuts import render_to_response, render_to_string
|
||||
from urllib import urlencode
|
||||
import zendesk
|
||||
|
||||
import capa.calc
|
||||
import track.views
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def calculate(request):
|
||||
''' Calculator in footer of every page. '''
|
||||
equation = request.GET['equation']
|
||||
@@ -29,36 +36,142 @@ def calculate(request):
|
||||
return HttpResponse(json.dumps({'result': str(result)}))
|
||||
|
||||
|
||||
def send_feedback(request):
|
||||
''' Feeback mechanism in footer of every page. '''
|
||||
try:
|
||||
username = request.user.username
|
||||
class _ZendeskApi(object):
|
||||
def __init__(self):
|
||||
"""
|
||||
Instantiate the Zendesk API.
|
||||
|
||||
All of `ZENDESK_URL`, `ZENDESK_USER`, and `ZENDESK_API_KEY` must be set
|
||||
in `django.conf.settings`.
|
||||
"""
|
||||
self._zendesk_instance = zendesk.Zendesk(
|
||||
settings.ZENDESK_URL,
|
||||
settings.ZENDESK_USER,
|
||||
settings.ZENDESK_API_KEY,
|
||||
use_api_token=True,
|
||||
api_version=2
|
||||
)
|
||||
|
||||
def create_ticket(self, ticket):
|
||||
"""
|
||||
Create the given `ticket` in Zendesk.
|
||||
|
||||
The ticket should have the format specified by the zendesk package.
|
||||
"""
|
||||
ticket_url = self._zendesk_instance.create_ticket(data=ticket)
|
||||
return zendesk.get_id_from_url(ticket_url)
|
||||
|
||||
def update_ticket(self, ticket_id, update):
|
||||
"""
|
||||
Update the Zendesk ticket with id `ticket_id` using the given `update`.
|
||||
|
||||
The update should have the format specified by the zendesk package.
|
||||
"""
|
||||
self._zendesk_instance.update_ticket(ticket_id=ticket_id, data=update)
|
||||
|
||||
|
||||
def submit_feedback_via_zendesk(request):
|
||||
"""
|
||||
Create a new user-requested Zendesk ticket.
|
||||
|
||||
If Zendesk submission is not enabled, any request will raise `Http404`.
|
||||
If any configuration parameter (`ZENDESK_URL`, `ZENDESK_USER`, or
|
||||
`ZENDESK_API_KEY`) is missing, any request will raise an `Exception`.
|
||||
The request must be a POST request specifying `subject` and `details`.
|
||||
If the user is not authenticated, the request must also specify `name` and
|
||||
`email`. If the user is authenticated, the `name` and `email` will be
|
||||
populated from the user's information. If any required parameter is
|
||||
missing, a 400 error will be returned indicating which field is missing and
|
||||
providing an error message. If Zendesk returns any error on ticket
|
||||
creation, a 500 error will be returned with no body. Once created, the
|
||||
ticket will be updated with a private comment containing additional
|
||||
information from the browser and server, such as HTTP headers and user
|
||||
state. Whether or not the update succeeds, if the user's ticket is
|
||||
successfully created, an empty successful response (200) will be returned.
|
||||
"""
|
||||
if not settings.MITX_FEATURES.get('ENABLE_FEEDBACK_SUBMISSION', False):
|
||||
raise Http404()
|
||||
if request.method != "POST":
|
||||
return HttpResponseNotAllowed(["POST"])
|
||||
if (
|
||||
not settings.ZENDESK_URL or
|
||||
not settings.ZENDESK_USER or
|
||||
not settings.ZENDESK_API_KEY
|
||||
):
|
||||
raise Exception("Zendesk enabled but not configured")
|
||||
|
||||
def build_error_response(status_code, field, err_msg):
|
||||
return HttpResponse(json.dumps({"field": field, "error": err_msg}), status=status_code)
|
||||
|
||||
additional_info = {}
|
||||
|
||||
required_fields = ["subject", "details"]
|
||||
if not request.user.is_authenticated():
|
||||
required_fields += ["name", "email"]
|
||||
required_field_errs = {
|
||||
"subject": "Please provide a subject.",
|
||||
"details": "Please provide details.",
|
||||
"name": "Please provide your name.",
|
||||
"email": "Please provide a valid e-mail.",
|
||||
}
|
||||
|
||||
for field in required_fields:
|
||||
if field not in request.POST or not request.POST[field]:
|
||||
return build_error_response(400, field, required_field_errs[field])
|
||||
|
||||
subject = request.POST["subject"]
|
||||
details = request.POST["details"]
|
||||
tags = []
|
||||
if "tag" in request.POST:
|
||||
tags = [request.POST["tag"]]
|
||||
|
||||
if request.user.is_authenticated():
|
||||
realname = request.user.profile.name
|
||||
email = request.user.email
|
||||
except:
|
||||
username = "anonymous"
|
||||
email = "anonymous"
|
||||
additional_info["username"] = request.user.username
|
||||
else:
|
||||
realname = request.POST["name"]
|
||||
email = request.POST["email"]
|
||||
try:
|
||||
validate_email(email)
|
||||
except ValidationError:
|
||||
return build_error_response(400, "email", required_field_errs["email"])
|
||||
|
||||
for header in ["HTTP_REFERER", "HTTP_USER_AGENT"]:
|
||||
additional_info[header] = request.META.get(header)
|
||||
|
||||
zendesk_api = _ZendeskApi()
|
||||
|
||||
additional_info_string = (
|
||||
"Additional information:\n\n" +
|
||||
"\n".join("%s: %s" % (key, value) for (key, value) in additional_info.items() if value is not None)
|
||||
)
|
||||
|
||||
new_ticket = {
|
||||
"ticket": {
|
||||
"requester": {"name": realname, "email": email},
|
||||
"subject": subject,
|
||||
"comment": {"body": details},
|
||||
"tags": tags
|
||||
}
|
||||
}
|
||||
try:
|
||||
browser = request.META['HTTP_USER_AGENT']
|
||||
except:
|
||||
browser = "Unknown"
|
||||
ticket_id = zendesk_api.create_ticket(new_ticket)
|
||||
except zendesk.ZendeskError as err:
|
||||
log.error("%s", str(err))
|
||||
return HttpResponse(status=500)
|
||||
|
||||
feedback = render_to_string("feedback_email.txt",
|
||||
{"subject": request.POST['subject'],
|
||||
"url": request.POST['url'],
|
||||
"time": datetime.datetime.now().isoformat(),
|
||||
"feedback": request.POST['message'],
|
||||
"email": email,
|
||||
"browser": browser,
|
||||
"user": username})
|
||||
# Additional information is provided as a private update so the information
|
||||
# is not visible to the user.
|
||||
ticket_update = {"ticket": {"comment": {"public": False, "body": additional_info_string}}}
|
||||
try:
|
||||
zendesk_api.update_ticket(ticket_id, ticket_update)
|
||||
except zendesk.ZendeskError as err:
|
||||
log.error("%s", str(err))
|
||||
# The update is not strictly necessary, so do not indicate failure to the user
|
||||
pass
|
||||
|
||||
send_mail("MITx Feedback / " + request.POST['subject'],
|
||||
feedback,
|
||||
settings.DEFAULT_FROM_EMAIL,
|
||||
[settings.DEFAULT_FEEDBACK_EMAIL],
|
||||
fail_silently=False
|
||||
)
|
||||
return HttpResponse(json.dumps({'success': True}))
|
||||
return HttpResponse()
|
||||
|
||||
|
||||
def info(request):
|
||||
|
||||
5
common/lib/xmodule/xmodule/js/src/.gitignore
vendored
5
common/lib/xmodule/xmodule/js/src/.gitignore
vendored
@@ -1 +1,4 @@
|
||||
# Please do not ignore *.js files. Some xmodules are written in JS.
|
||||
# Ignore .js files in this folder as they are compiled from coffeescript
|
||||
# For each of the xmodules subdirectories, add a .gitignore file that
|
||||
# will version any *.js file that is specifically written, not compiled.
|
||||
*.js
|
||||
|
||||
2
common/lib/xmodule/xmodule/js/src/capa/.gitignore
vendored
Normal file
2
common/lib/xmodule/xmodule/js/src/capa/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
!imageinput.js
|
||||
!schematic.js
|
||||
1
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/.gitignore
vendored
Normal file
1
common/lib/xmodule/xmodule/js/src/graphical_slider_tool/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!*.js
|
||||
1
common/lib/xmodule/xmodule/js/src/poll/.gitignore
vendored
Normal file
1
common/lib/xmodule/xmodule/js/src/poll/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!*.js
|
||||
1
common/lib/xmodule/xmodule/js/src/sequence/display/.gitignore
vendored
Normal file
1
common/lib/xmodule/xmodule/js/src/sequence/display/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!*.js
|
||||
1
common/lib/xmodule/xmodule/js/src/videoalpha/display/.gitignore
vendored
Normal file
1
common/lib/xmodule/xmodule/js/src/videoalpha/display/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!html5_video.js
|
||||
@@ -37,11 +37,17 @@ class XModuleCourseFactory(Factory):
|
||||
new_course.display_name = display_name
|
||||
|
||||
new_course.lms.start = gmtime()
|
||||
new_course.tabs = [{"type": "courseware"},
|
||||
{"type": "course_info", "name": "Course Info"},
|
||||
{"type": "discussion", "name": "Discussion"},
|
||||
{"type": "wiki", "name": "Wiki"},
|
||||
{"type": "progress", "name": "Progress"}]
|
||||
new_course.tabs = kwargs.get(
|
||||
'tabs',
|
||||
[
|
||||
{"type": "courseware"},
|
||||
{"type": "course_info", "name": "Course Info"},
|
||||
{"type": "discussion", "name": "Discussion"},
|
||||
{"type": "wiki", "name": "Wiki"},
|
||||
{"type": "progress", "name": "Progress"}
|
||||
]
|
||||
)
|
||||
new_course.discussion_link = kwargs.get('discussion_link')
|
||||
|
||||
# Update the data in the mongo datastore
|
||||
store.update_metadata(new_course.location.url(), own_metadata(new_course))
|
||||
|
||||
Reference in New Issue
Block a user