Commit e5928bac by Christina Roberts

Merge pull request #8894 from edx/andya/lms-requirejs

Implement RequireJS Optimizer in the LMS
parents fbe07845 e9e5b5bd
""" """
Settings for Bok Choy tests that are used for running CMS and LMS. Settings for Bok Choy tests that are used when running Studio.
Bok Choy uses two different settings files: Bok Choy uses two different settings files:
1. test_static_optimized is used when invoking collectstatic 1. test_static_optimized is used when invoking collectstatic
2. bok_choy is used when running CMS and LMS 2. bok_choy is used when running the tests
Note: it isn't possible to have a single settings file, because Django doesn't Note: it isn't possible to have a single settings file, because Django doesn't
support both generating static assets to a directory and also serving static support both generating static assets to a directory and also serving static
......
...@@ -455,7 +455,7 @@ MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' ...@@ -455,7 +455,7 @@ MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
EMBARGO_SITE_REDIRECT_URL = None EMBARGO_SITE_REDIRECT_URL = None
############################### Pipeline ####################################### ############################### Pipeline #######################################
STATICFILES_STORAGE = 'cms.lib.django_require.staticstorage.OptimizedCachedRequireJsStorage' STATICFILES_STORAGE = 'openedx.core.lib.django_require.staticstorage.OptimizedCachedRequireJsStorage'
from openedx.core.lib.rooted_paths import rooted_glob from openedx.core.lib.rooted_paths import rooted_glob
...@@ -573,7 +573,7 @@ REQUIRE_BASE_URL = "./" ...@@ -573,7 +573,7 @@ REQUIRE_BASE_URL = "./"
# A sensible value would be 'app.build.js'. Leave blank to use the built-in default build profile. # A sensible value would be 'app.build.js'. Leave blank to use the built-in default build profile.
# Set to False to disable running the default profile (e.g. if only using it to build Standalone # Set to False to disable running the default profile (e.g. if only using it to build Standalone
# Modules) # Modules)
REQUIRE_BUILD_PROFILE = "build.js" REQUIRE_BUILD_PROFILE = "cms/js/build.js"
# The name of the require.js script used by your project, relative to REQUIRE_BASE_URL. # The name of the require.js script used by your project, relative to REQUIRE_BASE_URL.
REQUIRE_JS = "js/vendor/require.js" REQUIRE_JS = "js/vendor/require.js"
...@@ -592,6 +592,8 @@ REQUIRE_EXCLUDE = ("build.txt",) ...@@ -592,6 +592,8 @@ REQUIRE_EXCLUDE = ("build.txt",)
# It can also be a path to a custom class that subclasses require.environments.Environment and defines some "args" function that returns a list with the command arguments to execute. # It can also be a path to a custom class that subclasses require.environments.Environment and defines some "args" function that returns a list with the command arguments to execute.
REQUIRE_ENVIRONMENT = "node" REQUIRE_ENVIRONMENT = "node"
################################# TENDER ######################################
# If you want to enable Tender integration (http://tenderapp.com/), # If you want to enable Tender integration (http://tenderapp.com/),
# put in the subdomain where Tender hosts tender_widget.js. For example, # put in the subdomain where Tender hosts tender_widget.js. For example,
# if you want to use the URL https://example.tenderapp.com/tender_widget.js, # if you want to use the URL https://example.tenderapp.com/tender_widget.js,
......
...@@ -29,6 +29,9 @@ TEST_ROOT = REPO_ROOT / "test_root" # pylint: disable=no-value-for-parameter ...@@ -29,6 +29,9 @@ TEST_ROOT = REPO_ROOT / "test_root" # pylint: disable=no-value-for-parameter
# Enable debug so that static assets are served by Django # Enable debug so that static assets are served by Django
DEBUG = True DEBUG = True
# Set REQUIRE_DEBUG to false so that it behaves like production
REQUIRE_DEBUG = False
# Serve static files at /static directly from the staticfiles directory under test root. # Serve static files at /static directly from the staticfiles directory under test root.
# Note: optimized files for testing are generated with settings from test_static_optimized # Note: optimized files for testing are generated with settings from test_static_optimized
STATIC_URL = "/static/" STATIC_URL = "/static/"
......
...@@ -33,3 +33,4 @@ STATIC_ROOT = (TEST_ROOT / "staticfiles" / "cms").abspath() ...@@ -33,3 +33,4 @@ STATIC_ROOT = (TEST_ROOT / "staticfiles" / "cms").abspath()
# 1. Uglify is by far the slowest part of the build process # 1. Uglify is by far the slowest part of the build process
# 2. Having full source code makes debugging tests easier for developers # 2. Having full source code makes debugging tests easier for developers
os.environ['REQUIRE_BUILD_PROFILE_OPTIMIZE'] = 'none' os.environ['REQUIRE_BUILD_PROFILE_OPTIMIZE'] = 'none'
PIPELINE_JS_COMPRESSOR = None
(function () { (function () {
'use strict'; 'use strict';
var commonLibrariesPath = 'common/js/common_libraries';
var getModule = function (moduleName, excludeCommonDeps) { var getModule = function (moduleName, excludeCommonDeps) {
var module = { var module = {
name: moduleName name: moduleName
}; };
if (excludeCommonDeps) { if (excludeCommonDeps) {
module.exclude = ['js/factories/common_deps']; module.exclude = [commonLibrariesPath];
} }
return module; return module;
}; };
var getModulesList = function (modules) { var getModulesList = function (modules) {
var result = [getModule('js/factories/common_deps')]; var result = [getModule(commonLibrariesPath)];
return result.concat(modules.map(function (moduleName) { return result.concat(modules.map(function (moduleName) {
return getModule(moduleName, true); return getModule(moduleName, true);
})); }));
...@@ -84,6 +86,17 @@ ...@@ -84,6 +86,17 @@
'tender': 'empty:', 'tender': 'empty:',
'youtube': 'empty:' 'youtube': 'empty:'
}, },
/**
* Inline requireJS text templates.
*/
inlineText: true,
/**
* Stub out requireJS text in the optimized file, but leave available for non-optimized development use.
*/
stubModules: ["text"],
/** /**
* If shim config is used in the app during runtime, duplicate the config * If shim config is used in the app during runtime, duplicate the config
* here. Necessary if shim config is used, so that the shim's dependencies * here. Necessary if shim config is used, so that the shim's dependencies
......
define(['domReady!', 'jquery', 'backbone', 'underscore', 'gettext', 'text']);
...@@ -36,7 +36,7 @@ import json ...@@ -36,7 +36,7 @@ import json
</head> </head>
<body class="${static.dir_rtl()} <%block name='bodyclass'></%block> lang_${LANGUAGE_CODE}"> <body class="${static.dir_rtl()} <%block name='bodyclass'></%block> lang_${LANGUAGE_CODE}">
<%block name="view_notes"></%block> <%block name="view_notes"></%block>
<a class="nav-skip" href="#content">${_("Skip to main content")}</a> <a class="nav-skip" href="#content">${_("Skip to main content")}</a>
...@@ -46,7 +46,7 @@ import json ...@@ -46,7 +46,7 @@ import json
var require = {baseUrl: window.baseUrl}; var require = {baseUrl: window.baseUrl};
</script> </script>
<script type="text/javascript" src="${static.url("js/vendor/require.js")}"></script> <script type="text/javascript" src="${static.url("js/vendor/require.js")}"></script>
<script type="text/javascript" src="${static.url("require-config.js")}"></script> <script type="text/javascript" src="${static.url("cms/js/require-config.js")}"></script>
## js templates ## js templates
<script id="system-feedback-tpl" type="text/template"> <script id="system-feedback-tpl" type="text/template">
...@@ -81,7 +81,7 @@ import json ...@@ -81,7 +81,7 @@ import json
<%block name="jsextra"></%block> <%block name="jsextra"></%block>
<script type="text/javascript"> <script type="text/javascript">
require(['js/factories/common_deps'], function () { require(['common/js/common_libraries'], function () {
require(['js/factories/base'], function () { require(['js/factories/base'], function () {
% if context_course: % if context_course:
require(['js/factories/course'], function(CourseFactory) { require(['js/factories/course'], function(CourseFactory) {
......
...@@ -51,3 +51,25 @@ except: ...@@ -51,3 +51,25 @@ except:
from django.template.loaders.filesystem import _loader from django.template.loaders.filesystem import _loader
source, template_path = _loader.load_template_source(path) source, template_path = _loader.load_template_source(path)
%>${source}</%def> %>${source}</%def>
<%def name="require_module(module_name, class_name)">
<script type="text/javascript">
(function (require) {
% if settings.REQUIRE_DEBUG:
require(['${module_name}'], function (${class_name}) {
${caller.body()}
});
% else:
## The "raw" parameter is specified to avoid the URL from being further maninpulated by
## static_replace calls (as woudl happen if require_module is used within courseware).
## Without specifying "raw", a call to static_replace would result in the MD5 hash being
## being appended more than once, causing the import to fail in production environments.
require(['${staticfiles_storage.url(module_name + ".js") + "?raw"}'], function () {
require(['${module_name}'], function (${class_name}) {
${caller.body()}
});
});
% endif
}).call(this, require || RequireJS.require);
</script>
</%def>
define(['domReady!', 'jquery', 'backbone', 'underscore', 'gettext']);
...@@ -3,6 +3,7 @@ import json ...@@ -3,6 +3,7 @@ import json
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from student.models import anonymous_id_for_user from student.models import anonymous_id_for_user
%> %>
<%namespace name='static' file='/static_content.html'/>
<% <%
if user: if user:
params.update({'user': anonymous_id_for_user(user, None)}) params.update({'user': anonymous_id_for_user(user, None)})
...@@ -10,11 +11,7 @@ from student.models import anonymous_id_for_user ...@@ -10,11 +11,7 @@ from student.models import anonymous_id_for_user
<div id="edx-notes-wrapper-${uid}" class="edx-notes-wrapper"> <div id="edx-notes-wrapper-${uid}" class="edx-notes-wrapper">
<div class="edx-notes-wrapper-content">${content}</div> <div class="edx-notes-wrapper-content">${content}</div>
</div> </div>
<script type="text/javascript"> <%static:require_module module_name="js/edxnotes/views/notes_visibility_factory" class_name="NotesVisibilityFactory">
(function (require) { var element = document.getElementById('edx-notes-wrapper-${uid}');
require(['js/edxnotes/views/visibility_decorator'], function(EdxnotesVisibilityDecorator) { NotesVisibilityFactory.VisibilityDecorator.factory(element, ${json.dumps(params)}, ${edxnotes_visibility});
var element = document.getElementById('edx-notes-wrapper-${uid}'); </%static:require_module>
EdxnotesVisibilityDecorator.factory(element, ${json.dumps(params)}, ${edxnotes_visibility});
});
}).call(this, require || RequireJS.require);
</script>
...@@ -2,12 +2,12 @@ define(["jquery", "backbone", "teams/js/teams_tab_factory"], ...@@ -2,12 +2,12 @@ define(["jquery", "backbone", "teams/js/teams_tab_factory"],
function($, Backbone, TeamsTabFactory) { function($, Backbone, TeamsTabFactory) {
'use strict'; 'use strict';
describe("teams django app", function() { describe("Teams tab", function() {
var teamsTab; var teamsTab;
beforeEach(function() { beforeEach(function() {
setFixtures('<section class="teams-content"></section>'); setFixtures('<section class="teams-content"></section>');
teamsTab = new TeamsTabFactory({results: []}, '', 'edX/DemoX/Demo_Course'); teamsTab = new TeamsTabFactory($(".teams-content"), {results: []}, '', 'edX/DemoX/Demo_Course');
}); });
afterEach(function() { afterEach(function() {
......
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
define(['jquery', 'teams/js/views/teams_tab', 'teams/js/collections/topic'], define(['jquery', 'teams/js/views/teams_tab', 'teams/js/collections/topic'],
function ($, TeamsTabView, TopicCollection) { function ($, TeamsTabView, TopicCollection) {
return function (topics, topics_url, course_id) { return function (element, topics, topics_url, course_id) {
var topicCollection = new TopicCollection(topics, {url: topics_url, course_id: course_id, parse: true}); var topicCollection = new TopicCollection(topics, {url: topics_url, course_id: course_id, parse: true});
topicCollection.bootstrap(); topicCollection.bootstrap();
var view = new TeamsTabView({ var view = new TeamsTabView({
el: $('.teams-content'), el: element,
topicCollection: topicCollection topicCollection: topicCollection
}); });
view.render(); view.render();
......
...@@ -21,11 +21,7 @@ ...@@ -21,11 +21,7 @@
</div> </div>
<%block name="js_extra"> <%block name="js_extra">
<script type="text/javascript"> <%static:require_module module_name="teams/js/teams_tab_factory" class_name="TeamsTabFactory">
(function (require) { TeamsTabFactory($('.teams-content'), ${ json.dumps(topics, cls=EscapedEdxJSONEncoder) }, '${ topics_url }', '${ unicode(course.id) }');
require(['teams/js/teams_tab_factory'], function (TeamsTabFactory) { </%static:require_module>
new TeamsTabFactory(${ json.dumps(topics, cls=EscapedEdxJSONEncoder) }, '${ topics_url }', '${ unicode(course.id) }');
});
}).call(this, require || RequireJS.require);
</script>
</%block> </%block>
""" """
Settings for bok choy tests Settings for Bok Choy tests that are used when running LMS.
Bok Choy uses two different settings files:
1. test_static_optimized is used when invoking collectstatic
2. bok_choy is used when running the tests
Note: it isn't possible to have a single settings file, because Django doesn't
support both generating static assets to a directory and also serving static
from the same directory.
""" """
import os import os
...@@ -48,6 +56,20 @@ update_module_store_settings( ...@@ -48,6 +56,20 @@ update_module_store_settings(
) )
############################ STATIC FILES ############################# ############################ STATIC FILES #############################
# Enable debug so that static assets are served by Django
DEBUG = True
# Serve static files at /static directly from the staticfiles directory under test root
# Note: optimized files for testing are generated with settings from test_static_optimized
STATIC_URL = "/static/"
STATICFILES_FINDERS = (
'staticfiles.finders.FileSystemFinder',
)
STATICFILES_DIRS = (
(TEST_ROOT / "staticfiles" / "lms").abspath(),
)
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
MEDIA_ROOT = TEST_ROOT / "uploads" MEDIA_ROOT = TEST_ROOT / "uploads"
MEDIA_URL = "/static/uploads/" MEDIA_URL = "/static/uploads/"
...@@ -74,9 +96,6 @@ OPEN_ENDED_GRADING_INTERFACE['url'] = 'http://localhost:8041/' ...@@ -74,9 +96,6 @@ OPEN_ENDED_GRADING_INTERFACE['url'] = 'http://localhost:8041/'
EDXNOTES_PUBLIC_API = 'http://localhost:8042/api/v1' EDXNOTES_PUBLIC_API = 'http://localhost:8042/api/v1'
EDXNOTES_INTERNAL_API = 'http://localhost:8042/api/v1' EDXNOTES_INTERNAL_API = 'http://localhost:8042/api/v1'
# Enable django-pipeline and staticfiles
STATIC_ROOT = (TEST_ROOT / "staticfiles" / "lms").abspath()
# Silence noisy logs # Silence noisy logs
import logging import logging
LOG_OVERRIDES = [ LOG_OVERRIDES = [
...@@ -106,9 +125,6 @@ FEATURES['ENABLE_TEAMS'] = True ...@@ -106,9 +125,6 @@ FEATURES['ENABLE_TEAMS'] = True
# Enable custom content licensing # Enable custom content licensing
FEATURES['LICENSING'] = True FEATURES['LICENSING'] = True
# Unfortunately, we need to use debug mode to serve staticfiles
DEBUG = True
########################### Entrance Exams ################################# ########################### Entrance Exams #################################
FEATURES['MILESTONES_APP'] = True FEATURES['MILESTONES_APP'] = True
FEATURES['ENTRANCE_EXAMS'] = True FEATURES['ENTRANCE_EXAMS'] = True
......
...@@ -1199,7 +1199,7 @@ X_FRAME_OPTIONS = 'ALLOW' ...@@ -1199,7 +1199,7 @@ X_FRAME_OPTIONS = 'ALLOW'
############################### Pipeline ####################################### ############################### Pipeline #######################################
STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage' STATICFILES_STORAGE = 'openedx.core.lib.django_require.staticstorage.OptimizedCachedRequireJsStorage'
from openedx.core.lib.rooted_paths import rooted_glob from openedx.core.lib.rooted_paths import rooted_glob
...@@ -1212,8 +1212,6 @@ courseware_js = ( ...@@ -1212,8 +1212,6 @@ courseware_js = (
sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/modules/**/*.js')) sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/modules/**/*.js'))
) )
courseware_search_js = ['js/search/course/main.js']
# Before a student accesses courseware, we do not # Before a student accesses courseware, we do not
# need many of the JS dependencies. This includes # need many of the JS dependencies. This includes
...@@ -1231,6 +1229,8 @@ base_vendor_js = [ ...@@ -1231,6 +1229,8 @@ base_vendor_js = [
'js/vendor/underscore-min.js', 'js/vendor/underscore-min.js',
'js/vendor/require.js', 'js/vendor/require.js',
'js/RequireJS-namespace-undefine.js', 'js/RequireJS-namespace-undefine.js',
'js/vendor/URI.min.js',
'js/vendor/backbone-min.js'
] ]
main_vendor_js = base_vendor_js + [ main_vendor_js = base_vendor_js + [
...@@ -1239,13 +1239,17 @@ main_vendor_js = base_vendor_js + [ ...@@ -1239,13 +1239,17 @@ main_vendor_js = base_vendor_js + [
'js/vendor/jquery.qtip.min.js', 'js/vendor/jquery.qtip.min.js',
'js/vendor/swfobject/swfobject.js', 'js/vendor/swfobject/swfobject.js',
'js/vendor/jquery.ba-bbq.min.js', 'js/vendor/jquery.ba-bbq.min.js',
'js/vendor/URI.min.js', ]
# Common files used by both RequireJS code and non-RequireJS code
base_application_js = [
'js/src/utility.js',
'js/src/logger.js',
] ]
dashboard_js = ( dashboard_js = (
sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/dashboard/**/*.js')) sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/dashboard/**/*.js'))
) )
dashboard_search_js = ['js/search/dashboard/main.js']
discussion_js = sorted(rooted_glob(COMMON_ROOT / 'static', 'coffee/src/discussion/**/*.js')) discussion_js = sorted(rooted_glob(COMMON_ROOT / 'static', 'coffee/src/discussion/**/*.js'))
staff_grading_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/staff_grading/**/*.js')) staff_grading_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/staff_grading/**/*.js'))
open_ended_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/open_ended/**/*.js')) open_ended_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/open_ended/**/*.js'))
...@@ -1265,13 +1269,9 @@ student_account_js = [ ...@@ -1265,13 +1269,9 @@ student_account_js = [
'js/toggle_login_modal.js', 'js/toggle_login_modal.js',
'js/sticky_filter.js', 'js/sticky_filter.js',
'js/query-params.js', 'js/query-params.js',
'js/src/utility.js',
'js/src/accessibility_tools.js', 'js/src/accessibility_tools.js',
'js/src/ie_shim.js', 'js/src/ie_shim.js',
'js/src/string_utils.js', 'js/src/string_utils.js',
'js/student_account/enrollment.js',
'js/student_account/emailoptin.js',
'js/student_account/shoppingcart.js',
'js/student_account/models/LoginModel.js', 'js/student_account/models/LoginModel.js',
'js/student_account/models/RegisterModel.js', 'js/student_account/models/RegisterModel.js',
'js/student_account/models/PasswordResetModel.js', 'js/student_account/models/PasswordResetModel.js',
...@@ -1291,7 +1291,6 @@ verify_student_js = [ ...@@ -1291,7 +1291,6 @@ verify_student_js = [
'js/toggle_login_modal.js', 'js/toggle_login_modal.js',
'js/sticky_filter.js', 'js/sticky_filter.js',
'js/query-params.js', 'js/query-params.js',
'js/src/utility.js',
'js/src/accessibility_tools.js', 'js/src/accessibility_tools.js',
'js/src/ie_shim.js', 'js/src/ie_shim.js',
'js/src/string_utils.js', 'js/src/string_utils.js',
...@@ -1336,8 +1335,6 @@ incourse_reverify_js = [ ...@@ -1336,8 +1335,6 @@ incourse_reverify_js = [
ccx_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/ccx/**/*.js')) ccx_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/ccx/**/*.js'))
discovery_js = ['js/discovery/main.js']
certificates_web_view_js = [ certificates_web_view_js = [
'js/vendor/jquery.min.js', 'js/vendor/jquery.min.js',
'js/vendor/jquery.cookie.js', 'js/vendor/jquery.cookie.js',
...@@ -1478,20 +1475,23 @@ project_js = set(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/**/*.js')) - s ...@@ -1478,20 +1475,23 @@ project_js = set(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/**/*.js')) - s
PIPELINE_JS = { PIPELINE_JS = {
'base_application': {
'source_filenames': base_application_js,
'output_filename': 'js/lms-base-application.js',
},
'application': { 'application': {
# Application will contain all paths not in courseware_only_js # Application will contain all paths not in courseware_only_js
'source_filenames': ['js/xblock/core.js'] + sorted(common_js) + sorted(project_js) + [ 'source_filenames': ['js/xblock/core.js'] + sorted(common_js) + sorted(project_js) + base_application_js + [
'js/form.ext.js', 'js/form.ext.js',
'js/my_courses_dropdown.js', 'js/my_courses_dropdown.js',
'js/toggle_login_modal.js', 'js/toggle_login_modal.js',
'js/sticky_filter.js', 'js/sticky_filter.js',
'js/query-params.js', 'js/query-params.js',
'js/src/utility.js',
'js/src/accessibility_tools.js', 'js/src/accessibility_tools.js',
'js/src/ie_shim.js', 'js/src/ie_shim.js',
'js/src/string_utils.js', 'js/src/string_utils.js',
'js/src/logger.js',
], ],
'output_filename': 'js/lms-application.js', 'output_filename': 'js/lms-application.js',
}, },
...@@ -1499,10 +1499,6 @@ PIPELINE_JS = { ...@@ -1499,10 +1499,6 @@ PIPELINE_JS = {
'source_filenames': courseware_js, 'source_filenames': courseware_js,
'output_filename': 'js/lms-courseware.js', 'output_filename': 'js/lms-courseware.js',
}, },
'courseware_search': {
'source_filenames': courseware_search_js,
'output_filename': 'js/lms-courseware-search.js',
},
'base_vendor': { 'base_vendor': {
'source_filenames': base_vendor_js, 'source_filenames': base_vendor_js,
'output_filename': 'js/lms-base-vendor.js', 'output_filename': 'js/lms-base-vendor.js',
...@@ -1543,10 +1539,6 @@ PIPELINE_JS = { ...@@ -1543,10 +1539,6 @@ PIPELINE_JS = {
'source_filenames': dashboard_js, 'source_filenames': dashboard_js,
'output_filename': 'js/dashboard.js' 'output_filename': 'js/dashboard.js'
}, },
'dashboard_search': {
'source_filenames': dashboard_search_js,
'output_filename': 'js/dashboard-search.js',
},
'student_account': { 'student_account': {
'source_filenames': student_account_js, 'source_filenames': student_account_js,
'output_filename': 'js/student_account.js' 'output_filename': 'js/student_account.js'
...@@ -1571,18 +1563,10 @@ PIPELINE_JS = { ...@@ -1571,18 +1563,10 @@ PIPELINE_JS = {
'source_filenames': ['js/footer-edx.js'], 'source_filenames': ['js/footer-edx.js'],
'output_filename': 'js/footer-edx.js' 'output_filename': 'js/footer-edx.js'
}, },
'discovery': {
'source_filenames': discovery_js,
'output_filename': 'js/discovery.js'
},
'certificates_wv': { 'certificates_wv': {
'source_filenames': certificates_web_view_js, 'source_filenames': certificates_web_view_js,
'output_filename': 'js/certificates/web_view.js' 'output_filename': 'js/certificates/web_view.js'
}, },
'utility': {
'source_filenames': ['js/src/utility.js'],
'output_filename': 'js/utility.js'
},
'credit_wv': { 'credit_wv': {
'source_filenames': credit_web_view_js, 'source_filenames': credit_web_view_js,
'output_filename': 'js/credit/web_view.js' 'output_filename': 'js/credit/web_view.js'
...@@ -1616,7 +1600,10 @@ PIPELINE_JS_COMPRESSOR = "pipeline.compressors.uglifyjs.UglifyJSCompressor" ...@@ -1616,7 +1600,10 @@ PIPELINE_JS_COMPRESSOR = "pipeline.compressors.uglifyjs.UglifyJSCompressor"
STATICFILES_IGNORE_PATTERNS = ( STATICFILES_IGNORE_PATTERNS = (
"sass/*", "sass/*",
"coffee/*", "coffee/*.coffee",
"coffee/*/*.coffee",
"coffee/*/*/*.coffee",
"coffee/*/*/*/*.coffee",
# Symlinks used by js-test-tool # Symlinks used by js-test-tool
"xmodule_js", "xmodule_js",
...@@ -1628,6 +1615,36 @@ PIPELINE_UGLIFYJS_BINARY = 'node_modules/.bin/uglifyjs' ...@@ -1628,6 +1615,36 @@ PIPELINE_UGLIFYJS_BINARY = 'node_modules/.bin/uglifyjs'
PIPELINE_COMPILE_INPLACE = True PIPELINE_COMPILE_INPLACE = True
################################# DJANGO-REQUIRE ###############################
# The baseUrl to pass to the r.js optimizer, relative to STATIC_ROOT.
REQUIRE_BASE_URL = "./"
# The name of a build profile to use for your project, relative to REQUIRE_BASE_URL.
# A sensible value would be 'app.build.js'. Leave blank to use the built-in default build profile.
# Set to False to disable running the default profile (e.g. if only using it to build Standalone
# Modules)
REQUIRE_BUILD_PROFILE = "lms/js/build.js"
# The name of the require.js script used by your project, relative to REQUIRE_BASE_URL.
REQUIRE_JS = "js/vendor/require.js"
# A dictionary of standalone modules to build with almond.js.
REQUIRE_STANDALONE_MODULES = {}
# Whether to run django-require in debug mode.
REQUIRE_DEBUG = False
# A tuple of files to exclude from the compilation result of r.js.
REQUIRE_EXCLUDE = ("build.txt",)
# The execution environment in which to run r.js: auto, node or rhino.
# auto will autodetect the environment and make use of node if available and rhino if not.
# It can also be a path to a custom class that subclasses require.environments.Environment
# and defines some "args" function that returns a list with the command arguments to execute.
REQUIRE_ENVIRONMENT = "node"
################################# CELERY ###################################### ################################# CELERY ######################################
# Message configuration # Message configuration
......
...@@ -79,6 +79,12 @@ def should_show_debug_toolbar(_): ...@@ -79,6 +79,12 @@ def should_show_debug_toolbar(_):
########################### PIPELINE ################################# ########################### PIPELINE #################################
# # Skip RequireJS optimizer in development
STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'
# Whether to run django-require in debug mode.
REQUIRE_DEBUG = DEBUG
PIPELINE_SASS_ARGUMENTS = '--debug-info --require {proj_dir}/static/sass/bourbon/lib/bourbon.rb'.format(proj_dir=PROJECT_ROOT) PIPELINE_SASS_ARGUMENTS = '--debug-info --require {proj_dir}/static/sass/bourbon/lib/bourbon.rb'.format(proj_dir=PROJECT_ROOT)
########################### VERIFIED CERTIFICATES ################################# ########################### VERIFIED CERTIFICATES #################################
......
...@@ -29,6 +29,9 @@ TEST_ROOT = REPO_ROOT / "test_root" # pylint: disable=no-value-for-parameter ...@@ -29,6 +29,9 @@ TEST_ROOT = REPO_ROOT / "test_root" # pylint: disable=no-value-for-parameter
# Enable debug so that static assets are served by Django # Enable debug so that static assets are served by Django
DEBUG = True DEBUG = True
# Set REQUIRE_DEBUG to false so that it behaves like production
REQUIRE_DEBUG = False
# Serve static files at /static directly from the staticfiles directory under test root. # Serve static files at /static directly from the staticfiles directory under test root.
# Note: optimized files for testing are generated with settings from test_static_optimized # Note: optimized files for testing are generated with settings from test_static_optimized
STATIC_URL = "/static/" STATIC_URL = "/static/"
......
...@@ -45,3 +45,4 @@ STATIC_ROOT = (TEST_ROOT / "staticfiles" / "lms").abspath() ...@@ -45,3 +45,4 @@ STATIC_ROOT = (TEST_ROOT / "staticfiles" / "lms").abspath()
# 1. Uglify is by far the slowest part of the build process # 1. Uglify is by far the slowest part of the build process
# 2. Having full source code makes debugging tests easier for developers # 2. Having full source code makes debugging tests easier for developers
os.environ['REQUIRE_BUILD_PROFILE_OPTIMIZE'] = 'none' os.environ['REQUIRE_BUILD_PROFILE_OPTIMIZE'] = 'none'
PIPELINE_JS_COMPRESSOR = None
;(function (define) { ;(function (define) {
define(['backbone', 'course_discovery_meanings'], function(Backbone, meanings) {
'use strict'; 'use strict';
return function (Collection, Form, ResultListView, FilterBarView, FacetsBarView, searchQuery) { define(['backbone', 'js/discovery/collection', 'js/discovery/form', 'js/discovery/result_list_view',
//facet types configuration - set default display names 'js/discovery/filter_bar_view', 'js/discovery/search_facets_view'],
var facetsTypes = meanings; function(Backbone, Collection, Form, ResultListView, FilterBarView, FacetsBarView) {
var collection = new Collection([]); return function (meanings, searchQuery) {
var results = new ResultListView({ collection: collection }); //facet types configuration - set default display names
var dispatcher = _.clone(Backbone.Events); var facetsTypes = meanings;
var form = new Form();
var filters = new FilterBarView();
var facetsBarView = new FacetsBarView(facetsTypes);
dispatcher.listenTo(form, 'search', function (query) { var collection = new Collection([]);
form.showLoadingIndicator(); var results = new ResultListView({ collection: collection });
filters.changeQueryFilter(query); var dispatcher = _.clone(Backbone.Events);
}); var form = new Form();
var filters = new FilterBarView();
var facetsBarView = new FacetsBarView(facetsTypes);
dispatcher.listenTo(filters, 'search', function (searchTerm, facets) { dispatcher.listenTo(form, 'search', function (query) {
collection.performSearch(searchTerm, facets); form.showLoadingIndicator();
form.showLoadingIndicator(); filters.changeQueryFilter(query);
}); });
dispatcher.listenTo(filters, 'clear', function () { dispatcher.listenTo(filters, 'search', function (searchTerm, facets) {
form.clearSearch(); collection.performSearch(searchTerm, facets);
collection.performSearch(); form.showLoadingIndicator();
filters.hideClearAllButton(); });
});
dispatcher.listenTo(results, 'next', function () { dispatcher.listenTo(filters, 'clear', function () {
collection.loadNextPage(); form.clearSearch();
form.showLoadingIndicator(); collection.performSearch();
}); filters.hideClearAllButton();
});
dispatcher.listenTo(collection, 'search', function () { dispatcher.listenTo(results, 'next', function () {
if (collection.length > 0) { collection.loadNextPage();
form.showFoundMessage(collection.totalCount); form.showLoadingIndicator();
results.render(); });
}
else {
form.showNotFoundMessage(collection.searchTerm);
}
facetsBarView.renderFacets(collection.facets);
form.hideLoadingIndicator();
});
dispatcher.listenTo(collection, 'next', function () { dispatcher.listenTo(collection, 'search', function () {
results.renderNext(); if (collection.length > 0) {
form.hideLoadingIndicator(); form.showFoundMessage(collection.totalCount);
}); results.render();
}
else {
form.showNotFoundMessage(collection.searchTerm);
}
facetsBarView.renderFacets(collection.facets);
form.hideLoadingIndicator();
});
dispatcher.listenTo(collection, 'error', function () { dispatcher.listenTo(collection, 'next', function () {
form.showErrorMessage(); results.renderNext();
form.hideLoadingIndicator(); form.hideLoadingIndicator();
}); });
dispatcher.listenTo(facetsBarView, 'addFilter', function (data) { dispatcher.listenTo(collection, 'error', function () {
filters.addFilter(data); form.showErrorMessage();
}); form.hideLoadingIndicator();
});
// kick off search on page refresh dispatcher.listenTo(facetsBarView, 'addFilter', function (data) {
form.doSearch(searchQuery); filters.addFilter(data);
});
}; // kick off search on page refresh
form.doSearch(searchQuery);
}); };
});
})(define || RequireJS.define); })(define || RequireJS.define);
RequireJS.require([
'jquery',
'backbone',
'js/discovery/app',
'js/discovery/collection',
'js/discovery/form',
'js/discovery/result_list_view',
'js/discovery/filter_bar_view',
'js/discovery/search_facets_view'
], function ($, Backbone, App, Collection, DiscoveryForm, ResultListView, FilterBarView, FacetsBarView) {
'use strict';
var app = new App(
Collection,
DiscoveryForm,
ResultListView,
FilterBarView,
FacetsBarView,
getParameterByName('search_query')
);
});
;(function (define) { ;(function (define) {
'use strict'; 'use strict';
define(['backbone', 'js/edxnotes/utils/utils', 'underscore.string'], function (Backbone, Utils) { define(['backbone', 'js/edxnotes/utils/utils', 'underscore.string'], function (Backbone, Utils, str) {
var NoteModel = Backbone.Model.extend({ var NoteModel = Backbone.Model.extend({
defaults: { defaults: {
'id': null, 'id': null,
...@@ -47,7 +47,7 @@ define(['backbone', 'js/edxnotes/utils/utils', 'underscore.string'], function (B ...@@ -47,7 +47,7 @@ define(['backbone', 'js/edxnotes/utils/utils', 'underscore.string'], function (B
var message = this.get('quote'); var message = this.get('quote');
if (!this.get('is_expanded') && this.get('show_link')) { if (!this.get('is_expanded') && this.get('show_link')) {
message = _.str.prune(message, this.textSize); message = str.prune(message, this.textSize);
} }
return message; return message;
......
;(function (define, undefined) { ;(function (define, undefined) {
'use strict'; 'use strict';
define([ define([
'underscore', 'annotator_1.2.9', 'underscore.string' 'underscore', 'annotator_1.2.9'
], function (_, Annotator) { ], function (_, Annotator) {
/** /**
* Modifies Annotator.Plugin.Store.annotationCreated to make it trigger a new * Modifies Annotator.Plugin.Store.annotationCreated to make it trigger a new
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
define([ define([
'jquery', 'underscore', 'backbone', 'gettext', 'jquery', 'underscore', 'backbone', 'gettext',
'annotator_1.2.9', 'js/edxnotes/views/visibility_decorator', 'js/utils/animation' 'annotator_1.2.9', 'js/edxnotes/views/visibility_decorator', 'js/utils/animation'
], function($, _, Backbone, gettext, Annotator, EdxnotesVisibilityDecorator) { ], function($, _, Backbone, gettext, Annotator, VisibilityDecorator) {
var ToggleNotesView = Backbone.View.extend({ var ToggleVisibilityView = Backbone.View.extend({
events: { events: {
'click .action-toggle-notes': 'toggleHandler' 'click .action-toggle-notes': 'toggleHandler'
}, },
...@@ -52,14 +52,14 @@ define([ ...@@ -52,14 +52,14 @@ define([
}, },
enableNotes: function () { enableNotes: function () {
_.each($('.edx-notes-wrapper'), EdxnotesVisibilityDecorator.enableNote); _.each($('.edx-notes-wrapper'), VisibilityDecorator.enableNote);
this.actionLink.addClass('is-active'); this.actionLink.addClass('is-active');
this.label.text(gettext('Hide notes')); this.label.text(gettext('Hide notes'));
this.actionToggleMessage.text(gettext('Notes visible')); this.actionToggleMessage.text(gettext('Notes visible'));
}, },
disableNotes: function () { disableNotes: function () {
EdxnotesVisibilityDecorator.disableNotes(); VisibilityDecorator.disableNotes();
this.actionLink.removeClass('is-active'); this.actionLink.removeClass('is-active');
this.label.text(gettext('Show notes')); this.label.text(gettext('Show notes'));
this.actionToggleMessage.text(gettext('Notes hidden')); this.actionToggleMessage.text(gettext('Notes hidden'));
...@@ -93,12 +93,16 @@ define([ ...@@ -93,12 +93,16 @@ define([
} }
}); });
return function (visibility, visibilityUrl) { return {
return new ToggleNotesView({ ToggleVisibilityView: function (visibility, visibilityUrl) {
el: $('.edx-notes-visibility').get(0), return new ToggleVisibilityView({
visibility: visibility, el: $('.edx-notes-visibility').get(0),
visibilityUrl: visibilityUrl visibility: visibility,
}); visibilityUrl: visibilityUrl
});
},
VisibilityDecorator: VisibilityDecorator
}; };
}); });
}).call(this, define || RequireJS.define); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function(Backbone, CohortModel) {
'use strict'; 'use strict';
define(['backbone', 'js/groups/models/cohort'], function(Backbone, CohortModel) {
edx.groups = edx.groups || {}; var CohortCollection = Backbone.Collection.extend({
model : CohortModel,
edx.groups.CohortCollection = Backbone.Collection.extend({ comparator: "name",
model : CohortModel,
comparator: "name",
parse: function(response) { parse: function(response) {
return response.cohorts; return response.cohorts;
} }
});
return CohortCollection;
}); });
}).call(this, Backbone, edx.groups.CohortModel); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function(Backbone) {
'use strict'; 'use strict';
define(['backbone'], function(Backbone) {
edx.groups = edx.groups || {}; var CohortModel = Backbone.Model.extend({
idAttribute: 'id',
edx.groups.CohortModel = Backbone.Model.extend({ defaults: {
idAttribute: 'id', name: '',
defaults: { user_count: 0,
name: '', /**
user_count: 0, * Indicates how students are added to the cohort. Will be "none" (signifying manual assignment) or
/** * "random" (indicating students are randomly assigned).
* Indicates how students are added to the cohort. Will be "none" (signifying manual assignment) or */
* "random" (indicating students are randomly assigned). assignment_type: '',
*/ /**
assignment_type: '', * If this cohort is associated with a user partition group, the ID of the user partition.
/** */
* If this cohort is associated with a user partition group, the ID of the user partition. user_partition_id: null,
*/ /**
user_partition_id: null, * If this cohort is associated with a user partition group, the ID of the group within the
/** * partition associated with user_partition_id.
* If this cohort is associated with a user partition group, the ID of the group within the */
* partition associated with user_partition_id. group_id: null
*/ }
group_id: null });
} return CohortModel;
}); });
}).call(this, Backbone); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function(Backbone) {
'use strict'; 'use strict';
define(['backbone'], function(Backbone) {
edx.groups = edx.groups || {}; var DiscussionTopicsSettingsModel = Backbone.Model.extend({
defaults: {
edx.groups.DiscussionTopicsSettingsModel = Backbone.Model.extend({ course_wide_discussions: {},
defaults: { inline_discussions: {}
course_wide_discussions: {}, }
inline_discussions: {} });
} return DiscussionTopicsSettingsModel;
}); });
}).call(this, Backbone); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function(Backbone) {
'use strict'; 'use strict';
define(['backbone'], function(Backbone) {
edx.groups = edx.groups || {}; var ContentGroupModel = Backbone.Model.extend({
idAttribute: 'id',
edx.groups.ContentGroupModel = Backbone.Model.extend({ defaults: {
idAttribute: 'id', name: '',
defaults: { user_partition_id: null
name: '', }
user_partition_id: null });
} return ContentGroupModel;
}); });
}).call(this, Backbone); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function(Backbone) {
'use strict'; 'use strict';
define(['backbone'], function(Backbone) {
edx.groups = edx.groups || {}; var CourseCohortSettingsModel = Backbone.Model.extend({
idAttribute: 'id',
edx.groups.CourseCohortSettingsModel = Backbone.Model.extend({ defaults: {
idAttribute: 'id', is_cohorted: false,
defaults: { cohorted_inline_discussions: [],
is_cohorted: false, cohorted_course_wide_discussions:[],
cohorted_inline_discussions: [], always_cohort_inline_discussions: true
cohorted_course_wide_discussions:[], }
always_cohort_inline_discussions: true });
} return CourseCohortSettingsModel;
}); });
}).call(this, Backbone); }).call(this, define || RequireJS.define);
var edx = edx || {}; ;(function (define) {
(function ($, _, Backbone, gettext, interpolate_text, NotificationModel, NotificationView) {
'use strict'; 'use strict';
define(['jquery', 'underscore', 'backbone', 'gettext', 'js/models/notification', 'js/views/notification'],
function ($, _, Backbone) {
edx.groups = edx.groups || {}; var CohortDiscussionConfigurationView = Backbone.View.extend({
edx.groups.CohortDiscussionConfigurationView = Backbone.View.extend({ /**
* Add/Remove the disabled attribute on given element.
* @param {object} $element - The element to disable/enable.
* @param {bool} disable - The flag to add/remove 'disabled' attribute.
*/
setDisabled: function($element, disable) {
$element.prop('disabled', disable ? 'disabled' : false);
},
/** /**
* Add/Remove the disabled attribute on given element. * Returns the cohorted discussions list.
* @param {object} $element - The element to disable/enable. * @param {string} selector - To select the discussion elements whose ids to return.
* @param {bool} disable - The flag to add/remove 'disabled' attribute. * @returns {Array} - Cohorted discussions.
*/ */
setDisabled: function($element, disable) { getCohortedDiscussions: function(selector) {
$element.prop('disabled', disable ? 'disabled' : false); var self=this,
}, cohortedDiscussions = [];
/** _.each(self.$(selector), function (topic) {
* Returns the cohorted discussions list. cohortedDiscussions.push($(topic).data('id'))
* @param {string} selector - To select the discussion elements whose ids to return. });
* @returns {Array} - Cohorted discussions. return cohortedDiscussions;
*/ },
getCohortedDiscussions: function(selector) {
var self=this,
cohortedDiscussions = [];
_.each(self.$(selector), function (topic) { /**
cohortedDiscussions.push($(topic).data('id')) * Save the cohortSettings' changed attributes to the server via PATCH method.
}); * It shows the error message(s) if any.
return cohortedDiscussions; * @param {object} $element - Messages would be shown before this element.
}, * @param {object} fieldData - Data to update on the server.
*/
saveForm: function ($element, fieldData) {
var self = this,
cohortSettingsModel = this.cohortSettings,
saveOperation = $.Deferred(),
showErrorMessage;
/** showErrorMessage = function (message, $element) {
* Save the cohortSettings' changed attributes to the server via PATCH method. self.showMessage(message, $element, 'error');
* It shows the error message(s) if any. };
* @param {object} $element - Messages would be shown before this element. this.removeNotification();
* @param {object} fieldData - Data to update on the server.
*/
saveForm: function ($element, fieldData) {
var self = this,
cohortSettingsModel = this.cohortSettings,
saveOperation = $.Deferred(),
showErrorMessage;
showErrorMessage = function (message, $element) { cohortSettingsModel.save(
self.showMessage(message, $element, 'error'); fieldData, {patch: true, wait: true}
}; ).done(function () {
this.removeNotification(); saveOperation.resolve();
}).fail(function (result) {
var errorMessage = null;
try {
var jsonResponse = JSON.parse(result.responseText);
errorMessage = jsonResponse.error;
} catch (e) {
// Ignore the exception and show the default error message instead.
}
if (!errorMessage) {
errorMessage = gettext("We've encountered an error. Refresh your browser and then try again.");
}
showErrorMessage(errorMessage, $element);
saveOperation.reject();
});
return saveOperation.promise();
},
cohortSettingsModel.save( /**
fieldData, {patch: true, wait: true} * Shows the notification messages before given element using the NotificationModel.
).done(function () { * @param {string} message - Text message to show.
saveOperation.resolve(); * @param {object} $element - Message would be shown before this element.
}).fail(function (result) { * @param {string} type - Type of message to show e.g. confirmation or error.
var errorMessage = null; */
try { showMessage: function (message, $element, type) {
var jsonResponse = JSON.parse(result.responseText); var model = new NotificationModel({type: type || 'confirmation', title: message});
errorMessage = jsonResponse.error; this.removeNotification();
} catch (e) { this.notification = new NotificationView({
// Ignore the exception and show the default error message instead. model: model
} });
if (!errorMessage) { $element.before(this.notification.$el);
errorMessage = gettext("We've encountered an error. Refresh your browser and then try again."); this.notification.render();
},
/**
*Removes the notification messages.
*/
removeNotification: function () {
if (this.notification) {
this.notification.remove();
}
} }
showErrorMessage(errorMessage, $element);
saveOperation.reject();
});
return saveOperation.promise();
},
/**
* Shows the notification messages before given element using the NotificationModel.
* @param {string} message - Text message to show.
* @param {object} $element - Message would be shown before this element.
* @param {string} type - Type of message to show e.g. confirmation or error.
*/
showMessage: function (message, $element, type) {
var model = new NotificationModel({type: type || 'confirmation', title: message});
this.removeNotification();
this.notification = new NotificationView({
model: model
}); });
$element.before(this.notification.$el); return CohortDiscussionConfigurationView;
this.notification.render(); });
}, }).call(this, define || RequireJS.define);
/**
*Removes the notification messages.
*/
removeNotification: function () {
if (this.notification) {
this.notification.remove();
}
}
});
}).call(this, $, _, Backbone, gettext, interpolate_text, NotificationModel, NotificationView
);
var edx = edx || {}; ;(function (define) {
(function ($, _, Backbone, gettext, interpolate_text, CohortDiscussionConfigurationView) {
'use strict'; 'use strict';
define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/views/cohort_discussions'],
function ($, _, Backbone, gettext, CohortDiscussionConfigurationView) {
var CourseWideDiscussionsView = CohortDiscussionConfigurationView.extend({
events: {
'change .check-discussion-subcategory-course-wide': 'discussionCategoryStateChanged',
'click .cohort-course-wide-discussions-form .action-save': 'saveCourseWideDiscussionsForm'
},
edx.groups = edx.groups || {}; initialize: function (options) {
this.template = _.template($('#cohort-discussions-course-wide-tpl').text());
edx.groups.CourseWideDiscussionsView = CohortDiscussionConfigurationView.extend({ this.cohortSettings = options.cohortSettings;
events: { },
'change .check-discussion-subcategory-course-wide': 'discussionCategoryStateChanged',
'click .cohort-course-wide-discussions-form .action-save': 'saveCourseWideDiscussionsForm'
},
initialize: function (options) { render: function () {
this.template = _.template($('#cohort-discussions-course-wide-tpl').text()); this.$('.cohort-course-wide-discussions-nav').html(this.template({
this.cohortSettings = options.cohortSettings; courseWideTopics: this.getCourseWideDiscussionsHtml(
}, this.model.get('course_wide_discussions')
)
}));
this.setDisabled(this.$('.cohort-course-wide-discussions-form .action-save'), true);
},
render: function () { /**
this.$('.cohort-course-wide-discussions-nav').html(this.template({ * Returns the html list for course-wide discussion topics.
courseWideTopics: this.getCourseWideDiscussionsHtml( * @param {object} courseWideDiscussions - course-wide discussions object from server.
this.model.get('course_wide_discussions') * @returns {Array} - HTML list for course-wide discussion topics.
) */
})); getCourseWideDiscussionsHtml: function (courseWideDiscussions) {
this.setDisabled(this.$('.cohort-course-wide-discussions-form .action-save'), true); var subCategoryTemplate = _.template($('#cohort-discussions-subcategory-tpl').html()),
}, entries = courseWideDiscussions.entries,
children = courseWideDiscussions.children;
/** return _.map(children, function (name) {
* Returns the html list for course-wide discussion topics. var entry = entries[name];
* @param {object} courseWideDiscussions - course-wide discussions object from server. return subCategoryTemplate({
* @returns {Array} - HTML list for course-wide discussion topics. name: name,
*/ id: entry.id,
getCourseWideDiscussionsHtml: function (courseWideDiscussions) { is_cohorted: entry.is_cohorted,
var subCategoryTemplate = _.template($('#cohort-discussions-subcategory-tpl').html()), type: 'course-wide'
entries = courseWideDiscussions.entries, });
children = courseWideDiscussions.children; }).join('');
},
return _.map(children, function (name) { /**
var entry = entries[name]; * Enables the save button for course-wide discussions.
return subCategoryTemplate({ */
name: name, discussionCategoryStateChanged: function(event) {
id: entry.id, event.preventDefault();
is_cohorted: entry.is_cohorted, this.setDisabled(this.$('.cohort-course-wide-discussions-form .action-save'), false);
type: 'course-wide' },
});
}).join('');
},
/** /**
* Enables the save button for course-wide discussions. * Sends the cohorted_course_wide_discussions to the server and renders the view.
*/ */
discussionCategoryStateChanged: function(event) { saveCourseWideDiscussionsForm: function (event) {
event.preventDefault(); event.preventDefault();
this.setDisabled(this.$('.cohort-course-wide-discussions-form .action-save'), false);
},
/** var self = this,
* Sends the cohorted_course_wide_discussions to the server and renders the view. courseWideCohortedDiscussions = self.getCohortedDiscussions(
*/ '.check-discussion-subcategory-course-wide:checked'
saveCourseWideDiscussionsForm: function (event) { ),
event.preventDefault(); fieldData = { cohorted_course_wide_discussions: courseWideCohortedDiscussions };
var self = this, self.saveForm(self.$('.course-wide-discussion-topics'),fieldData)
courseWideCohortedDiscussions = self.getCohortedDiscussions( .done(function () {
'.check-discussion-subcategory-course-wide:checked' self.model.fetch()
), .done(function () {
fieldData = { cohorted_course_wide_discussions: courseWideCohortedDiscussions }; self.render();
self.showMessage(gettext('Your changes have been saved.'), self.$('.course-wide-discussion-topics'));
}).fail(function() {
var errorMessage = gettext("We've encountered an error. Refresh your browser and then try again.");
self.showMessage(errorMessage, self.$('.course-wide-discussion-topics'), 'error')
});
});
}
self.saveForm(self.$('.course-wide-discussion-topics'),fieldData) });
.done(function () { return CourseWideDiscussionsView;
self.model.fetch() });
.done(function () { }).call(this, define || RequireJS.define);
self.render();
self.showMessage(gettext('Your changes have been saved.'), self.$('.course-wide-discussion-topics'));
}).fail(function() {
var errorMessage = gettext("We've encountered an error. Refresh your browser and then try again.");
self.showMessage(errorMessage, self.$('.course-wide-discussion-topics'), 'error')
});
});
}
});
}).call(this, $, _, Backbone, gettext, interpolate_text, edx.groups.CohortDiscussionConfigurationView);
;(function (define, undefined) { ;(function (define, undefined) {
'use strict'; 'use strict';
define(['jquery', 'js/groups/views/cohorts', 'js/groups/collections/cohort', 'js/groups/models/course_cohort_settings', define(['jquery', 'js/groups/views/cohorts', 'js/groups/collections/cohort', 'js/groups/models/course_cohort_settings',
'js/groups/models/cohort_discussions'], 'js/groups/models/cohort_discussions', 'js/groups/models/content_group'],
function($) { function($, CohortsView, CohortCollection, CourseCohortSettingsModel, DiscussionTopicsSettingsModel, ContentGroupModel) {
return function(contentGroups, studioGroupConfigurationsUrl) { return function(contentGroups, studioGroupConfigurationsUrl) {
var contentGroupModels = $.map(contentGroups, function(group) {
return new ContentGroupModel({
id: group.id,
name: group.name,
user_partition_id: group.user_partition_id
});
});
var cohorts = new edx.groups.CohortCollection(), var cohorts = new CohortCollection(),
courseCohortSettings = new edx.groups.CourseCohortSettingsModel(), courseCohortSettings = new CourseCohortSettingsModel(),
discussionTopicsSettings = new edx.groups.DiscussionTopicsSettingsModel(); discussionTopicsSettings = new DiscussionTopicsSettingsModel();
var cohortManagementElement = $('.cohort-management'); var cohortManagementElement = $('.cohort-management');
...@@ -16,10 +23,10 @@ ...@@ -16,10 +23,10 @@
courseCohortSettings.url = cohortManagementElement.data('course_cohort_settings_url'); courseCohortSettings.url = cohortManagementElement.data('course_cohort_settings_url');
discussionTopicsSettings.url = cohortManagementElement.data('discussion-topics-url'); discussionTopicsSettings.url = cohortManagementElement.data('discussion-topics-url');
var cohortsView = new edx.groups.CohortsView({ var cohortsView = new CohortsView({
el: cohortManagementElement, el: cohortManagementElement,
model: cohorts, model: cohorts,
contentGroups: contentGroups, contentGroups: contentGroupModels,
cohortSettings: courseCohortSettings, cohortSettings: courseCohortSettings,
context: { context: {
discussionTopicsSettingsModel: discussionTopicsSettings, discussionTopicsSettingsModel: discussionTopicsSettings,
......
var edx = edx || {}; ;(function (define) {
(function($, _, Backbone, gettext) {
'use strict'; 'use strict';
define(['jquery', 'underscore', 'backbone', 'gettext'], function($, _, Backbone, gettext) {
edx.groups = edx.groups || {}; var CourseCohortSettingsNotificationView = Backbone.View.extend({
initialize: function(options) {
edx.groups.CourseCohortSettingsNotificationView = Backbone.View.extend({ this.template = _.template($('#cohort-state-tpl').text());
initialize: function(options) { this.cohortEnabled = options.cohortEnabled;
this.template = _.template($('#cohort-state-tpl').text()); },
this.cohortEnabled = options.cohortEnabled;
},
render: function() { render: function() {
this.$el.html(this.template({})); this.$el.html(this.template({}));
this.showCohortStateMessage(); this.showCohortStateMessage();
return this; return this;
}, },
showCohortStateMessage: function () { showCohortStateMessage: function () {
var actionToggleMessage = this.$('.action-toggle-message'); var actionToggleMessage = this.$('.action-toggle-message');
AnimationUtil.triggerAnimation(actionToggleMessage); AnimationUtil.triggerAnimation(actionToggleMessage);
if (this.cohortEnabled) { if (this.cohortEnabled) {
actionToggleMessage.text(gettext('Cohorts Enabled')); actionToggleMessage.text(gettext('Cohorts Enabled'));
} else { } else {
actionToggleMessage.text(gettext('Cohorts Disabled')); actionToggleMessage.text(gettext('Cohorts Disabled'));
}
} }
} });
return CourseCohortSettingsNotificationView;
}); });
}).call(this, $, _, Backbone, gettext); }).call(this, define || RequireJS.define);
;(function (define) { ;(function (define) {
define(['backbone'], function(Backbone) {
'use strict'; 'use strict';
return function (courseId, SearchRouter, SearchForm, SearchCollection, SearchListView) { define(['backbone', 'js/search/base/routers/search_router', 'js/search/course/views/search_form',
'js/search/base/collections/search_collection', 'js/search/course/views/search_results_view'],
function(Backbone, SearchRouter, CourseSearchForm, SearchCollection, SearchResultsView) {
var router = new SearchRouter(); return function (courseId) {
var form = new SearchForm();
var collection = new SearchCollection([], { courseId: courseId });
var results = new SearchListView({ collection: collection });
var dispatcher = _.clone(Backbone.Events);
dispatcher.listenTo(router, 'search', function (query) { var router = new SearchRouter();
form.doSearch(query); var form = new CourseSearchForm();
}); var collection = new SearchCollection([], { courseId: courseId });
var results = new SearchResultsView({ collection: collection });
var dispatcher = _.clone(Backbone.Events);
dispatcher.listenTo(form, 'search', function (query) { dispatcher.listenTo(router, 'search', function (query) {
results.showLoadingMessage(); form.doSearch(query);
collection.performSearch(query); });
router.navigate('search/' + query, { replace: true });
});
dispatcher.listenTo(form, 'clear', function () { dispatcher.listenTo(form, 'search', function (query) {
collection.cancelSearch(); results.showLoadingMessage();
results.clear(); collection.performSearch(query);
router.navigate(''); router.navigate('search/' + query, { replace: true });
}); });
dispatcher.listenTo(results, 'next', function () { dispatcher.listenTo(form, 'clear', function () {
collection.loadNextPage(); collection.cancelSearch();
}); results.clear();
router.navigate('');
});
dispatcher.listenTo(collection, 'search', function () { dispatcher.listenTo(results, 'next', function () {
results.render(); collection.loadNextPage();
}); });
dispatcher.listenTo(collection, 'next', function () { dispatcher.listenTo(collection, 'search', function () {
results.renderNext(); results.render();
}); });
dispatcher.listenTo(collection, 'error', function () { dispatcher.listenTo(collection, 'next', function () {
results.showErrorMessage(); results.renderNext();
}); });
}; dispatcher.listenTo(collection, 'error', function () {
results.showErrorMessage();
});
}); };
});
})(define || RequireJS.define); })(define || RequireJS.define);
RequireJS.require([
'jquery',
'backbone',
'js/search/course/search_app',
'js/search/base/routers/search_router',
'js/search/course/views/search_form',
'js/search/base/collections/search_collection',
'js/search/course/views/search_results_view'
], function ($, Backbone, SearchApp, SearchRouter, CourseSearchForm, SearchCollection, CourseSearchResultsView) {
'use strict';
var courseId = $('#courseware-search-results').data('courseId');
var app = new SearchApp(
courseId,
SearchRouter,
CourseSearchForm,
SearchCollection,
CourseSearchResultsView
);
Backbone.history.start();
});
;(function (define) { ;(function (define) {
define(['backbone'], function(Backbone) {
'use strict'; 'use strict';
return function (SearchRouter, SearchForm, SearchCollection, SearchListView) { define(['backbone', 'js/search/base/routers/search_router', 'js/search/dashboard/views/search_form',
'js/search/base/collections/search_collection', 'js/search/dashboard/views/search_results_view'],
function(Backbone, SearchRouter, SearchForm, SearchCollection, SearchListView) {
var router = new SearchRouter(); return function () {
var form = new SearchForm();
var collection = new SearchCollection([]);
var results = new SearchListView({ collection: collection });
var dispatcher = _.clone(Backbone.Events);
dispatcher.listenTo(router, 'search', function (query) { var router = new SearchRouter();
form.doSearch(query); var form = new SearchForm();
}); var collection = new SearchCollection([]);
var results = new SearchListView({ collection: collection });
var dispatcher = _.clone(Backbone.Events);
dispatcher.listenTo(form, 'search', function (query) { dispatcher.listenTo(router, 'search', function (query) {
results.showLoadingMessage(); form.doSearch(query);
collection.performSearch(query); });
router.navigate('search/' + query, { replace: true });
});
dispatcher.listenTo(form, 'clear', function () { dispatcher.listenTo(form, 'search', function (query) {
collection.cancelSearch(); results.showLoadingMessage();
results.clear(); collection.performSearch(query);
router.navigate(''); router.navigate('search/' + query, { replace: true });
}); });
dispatcher.listenTo(results, 'next', function () { dispatcher.listenTo(form, 'clear', function () {
collection.loadNextPage(); collection.cancelSearch();
}); results.clear();
router.navigate('');
});
dispatcher.listenTo(results, 'reset', function () { dispatcher.listenTo(results, 'next', function () {
form.resetSearchForm(); collection.loadNextPage();
}); });
dispatcher.listenTo(collection, 'search', function () { dispatcher.listenTo(results, 'reset', function () {
results.render(); form.resetSearchForm();
}); });
dispatcher.listenTo(collection, 'next', function () { dispatcher.listenTo(collection, 'search', function () {
results.renderNext(); results.render();
}); });
dispatcher.listenTo(collection, 'error', function () { dispatcher.listenTo(collection, 'next', function () {
results.showErrorMessage(); results.renderNext();
}); });
}; dispatcher.listenTo(collection, 'error', function () {
results.showErrorMessage();
});
}); };
});
})(define || RequireJS.define); })(define || RequireJS.define);
RequireJS.require([
'backbone',
'js/search/dashboard/search_app',
'js/search/base/routers/search_router',
'js/search/dashboard/views/search_form',
'js/search/base/collections/search_collection',
'js/search/dashboard/views/search_results_view'
], function (Backbone, SearchApp, SearchRouter, DashSearchForm, SearchCollection, DashSearchResultsView) {
'use strict';
var app = new SearchApp(
SearchRouter,
DashSearchForm,
SearchCollection,
DashSearchResultsView
);
Backbone.history.start();
});
define({
org: {
name: 'Organization',
terms: {
edX1: "edX_1"
}
},
modes: {
name: 'Course Type',
terms: {
honor: 'Honor',
verified: 'Verified'
}
},
language: {
en: 'English',
hr: 'Croatian'
}
});
define([ define([
'jquery', 'annotator_1.2.9', 'common/js/spec_helpers/ajax_helpers', 'js/edxnotes/views/visibility_decorator', 'jquery', 'underscore', 'annotator_1.2.9', 'common/js/spec_helpers/ajax_helpers',
'js/edxnotes/views/toggle_notes_factory', 'js/spec/edxnotes/helpers', 'js/edxnotes/views/notes_visibility_factory', 'js/spec/edxnotes/helpers',
'js/spec/edxnotes/custom_matchers', 'jasmine-jquery' 'js/spec/edxnotes/custom_matchers', 'jasmine-jquery'
], function( ], function(
$, Annotator, AjaxHelpers, VisibilityDecorator, ToggleNotesFactory, Helpers, $, _, Annotator, AjaxHelpers, NotesVisibilityFactory, Helpers, customMatchers
customMatchers
) { ) {
'use strict'; 'use strict';
describe('EdxNotes ToggleNotesFactory', function() { describe('EdxNotes ToggleNotesFactory', function() {
...@@ -23,13 +22,13 @@ define([ ...@@ -23,13 +22,13 @@ define([
'js/fixtures/edxnotes/edxnotes_wrapper.html', 'js/fixtures/edxnotes/edxnotes_wrapper.html',
'js/fixtures/edxnotes/toggle_notes.html' 'js/fixtures/edxnotes/toggle_notes.html'
); );
VisibilityDecorator.factory( NotesVisibilityFactory.VisibilityDecorator.factory(
document.getElementById('edx-notes-wrapper-123'), params, true document.getElementById('edx-notes-wrapper-123'), params, true
); );
VisibilityDecorator.factory( NotesVisibilityFactory.VisibilityDecorator.factory(
document.getElementById('edx-notes-wrapper-456'), params, true document.getElementById('edx-notes-wrapper-456'), params, true
); );
this.toggleNotes = ToggleNotesFactory(true, '/test_url'); this.toggleNotes = NotesVisibilityFactory.ToggleVisibilityView(true, '/test_url');
this.button = $('.action-toggle-notes'); this.button = $('.action-toggle-notes');
this.label = this.button.find('.utility-control-label'); this.label = this.button.find('.utility-control-label');
this.toggleMessage = $('.action-toggle-message'); this.toggleMessage = $('.action-toggle-message');
...@@ -37,7 +36,7 @@ define([ ...@@ -37,7 +36,7 @@ define([
}); });
afterEach(function () { afterEach(function () {
VisibilityDecorator._setVisibility(null); NotesVisibilityFactory.VisibilityDecorator._setVisibility(null);
_.invoke(Annotator._instances, 'destroy'); _.invoke(Annotator._instances, 'destroy');
$('.annotator-notice').remove(); $('.annotator-notice').remove();
}); });
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
requirejs.config({ requirejs.config({
paths: { paths: {
'gettext': 'xmodule_js/common_static/js/test/i18n', 'gettext': 'xmodule_js/common_static/js/test/i18n',
'mustache': 'xmodule_js/common_static/js/vendor/mustache',
'codemirror': 'xmodule_js/common_static/js/vendor/CodeMirror/codemirror', 'codemirror': 'xmodule_js/common_static/js/vendor/CodeMirror/codemirror',
'jquery': 'xmodule_js/common_static/js/vendor/jquery.min', 'jquery': 'xmodule_js/common_static/js/vendor/jquery.min',
'jquery.ui': 'xmodule_js/common_static/js/vendor/jquery-ui.min', 'jquery.ui': 'xmodule_js/common_static/js/vendor/jquery-ui.min',
...@@ -61,7 +60,6 @@ ...@@ -61,7 +60,6 @@
// Manually specify LMS files that are not converted to RequireJS // Manually specify LMS files that are not converted to RequireJS
'history': 'js/vendor/history', 'history': 'js/vendor/history',
'js/mustache': 'js/mustache',
'js/staff_debug_actions': 'js/staff_debug_actions', 'js/staff_debug_actions': 'js/staff_debug_actions',
'js/vendor/jquery.qubit': 'js/vendor/jquery.qubit', 'js/vendor/jquery.qubit': 'js/vendor/jquery.qubit',
...@@ -69,18 +67,6 @@ ...@@ -69,18 +67,6 @@
'js/models/notification': 'js/models/notification', 'js/models/notification': 'js/models/notification',
'js/views/file_uploader': 'js/views/file_uploader', 'js/views/file_uploader': 'js/views/file_uploader',
'js/views/notification': 'js/views/notification', 'js/views/notification': 'js/views/notification',
'js/groups/models/cohort': 'js/groups/models/cohort',
'js/groups/models/content_group': 'js/groups/models/content_group',
'js/groups/models/course_cohort_settings': 'js/groups/models/course_cohort_settings',
'js/groups/models/cohort_discussions': 'js/groups/models/cohort_discussions',
'js/groups/views/cohort_discussions': 'js/groups/views/cohort_discussions',
'js/groups/views/cohort_discussions_course_wide': 'js/groups/views/cohort_discussions_course_wide',
'js/groups/views/cohort_discussions_inline': 'js/groups/views/cohort_discussions_inline',
'js/groups/views/course_cohort_settings_notification': 'js/groups/views/course_cohort_settings_notification',
'js/groups/collections/cohort': 'js/groups/collections/cohort',
'js/groups/views/cohort_editor': 'js/groups/views/cohort_editor',
'js/groups/views/cohort_form': 'js/groups/views/cohort_form',
'js/groups/views/cohorts': 'js/groups/views/cohorts',
'js/student_account/account': 'js/student_account/account', 'js/student_account/account': 'js/student_account/account',
'js/student_account/views/FormView': 'js/student_account/views/FormView', 'js/student_account/views/FormView': 'js/student_account/views/FormView',
'js/student_account/models/LoginModel': 'js/student_account/models/LoginModel', 'js/student_account/models/LoginModel': 'js/student_account/models/LoginModel',
...@@ -98,9 +84,7 @@ ...@@ -98,9 +84,7 @@
'js/ccx/schedule': 'js/ccx/schedule', 'js/ccx/schedule': 'js/ccx/schedule',
// edxnotes // edxnotes
'annotator_1.2.9': 'xmodule_js/common_static/js/vendor/edxnotes/annotator-full.min', 'annotator_1.2.9': 'xmodule_js/common_static/js/vendor/edxnotes/annotator-full.min'
'course_discovery_meanings': 'js/spec/discovery/course_discovery_meanings'
}, },
shim: { shim: {
'gettext': { 'gettext': {
...@@ -303,63 +287,6 @@ ...@@ -303,63 +287,6 @@
exports: 'edx.instructor_dashboard.ecommerce.ExpiryCouponView', exports: 'edx.instructor_dashboard.ecommerce.ExpiryCouponView',
deps: ['backbone', 'jquery', 'underscore'] deps: ['backbone', 'jquery', 'underscore']
}, },
'js/groups/models/cohort': {
exports: 'edx.groups.CohortModel',
deps: ['backbone']
},
'js/groups/models/content_group': {
exports: 'edx.groups.ContentGroupModel',
deps: ['backbone']
},
'js/groups/models/course_cohort_settings': {
exports: 'edx.groups.CourseCohortSettingsModel',
deps: ['backbone']
},
'js/groups/models/cohort_discussions': {
exports: 'edx.groups.DiscussionTopicsSettingsModel',
deps: ['backbone']
},
'js/groups/views/cohort_discussions': {
exports: 'edx.groups.CohortDiscussionConfigurationView',
deps: ['backbone']
},
'js/groups/views/cohort_discussions_course_wide': {
exports: 'edx.groups.CourseWideDiscussionsView',
deps: ['backbone', 'js/groups/views/cohort_discussions']
},
'js/groups/views/cohort_discussions_inline': {
exports: 'edx.groups.InlineDiscussionsView',
deps: ['backbone', 'js/groups/views/cohort_discussions', 'js/vendor/jquery.qubit']
},
'js/groups/views/course_cohort_settings_notification': {
exports: 'edx.groups.CourseCohortSettingsNotificationView',
deps: ['backbone']
},
'js/groups/collections/cohort': {
exports: 'edx.groups.CohortCollection',
deps: ['backbone', 'js/groups/models/cohort']
},
'js/groups/views/cohort_form': {
exports: 'edx.groups.CohortFormView',
deps: [
'backbone', 'jquery', 'underscore', 'js/views/notification', 'js/models/notification',
'string_utils'
]
},
'js/groups/views/cohort_editor': {
exports: 'edx.groups.CohortEditorView',
deps: [
'backbone', 'jquery', 'underscore', 'js/views/notification', 'js/models/notification',
'string_utils', 'js/groups/views/cohort_form'
]
},
'js/groups/views/cohorts': {
exports: 'edx.groups.CohortsView',
deps: [
'jquery', 'underscore', 'backbone', 'gettext', 'string_utils', 'js/groups/views/cohort_editor',
'js/views/notification', 'js/models/notification', 'js/views/file_uploader'
]
},
'js/models/notification': { 'js/models/notification': {
exports: 'NotificationModel', exports: 'NotificationModel',
deps: ['backbone'] deps: ['backbone']
...@@ -375,18 +302,6 @@ ...@@ -375,18 +302,6 @@
'js/models/notification', 'jquery.fileupload' 'js/models/notification', 'jquery.fileupload'
] ]
}, },
'js/student_account/enrollment': {
exports: 'edx.student.account.EnrollmentInterface',
deps: ['jquery', 'jquery.cookie']
},
'js/student_account/emailoptin': {
exports: 'edx.student.account.EmailOptInInterface',
deps: ['jquery', 'jquery.cookie']
},
'js/student_account/shoppingcart': {
exports: 'edx.student.account.ShoppingCartInterface',
deps: ['jquery', 'jquery.cookie', 'underscore']
},
// Student account registration/login // Student account registration/login
// Loaded explicitly until these are converted to RequireJS // Loaded explicitly until these are converted to RequireJS
'js/student_account/views/FormView': { 'js/student_account/views/FormView': {
...@@ -665,7 +580,7 @@ ...@@ -665,7 +580,7 @@
'lms/include/js/spec/edxnotes/views/tabs/course_structure_spec.js', 'lms/include/js/spec/edxnotes/views/tabs/course_structure_spec.js',
'lms/include/js/spec/edxnotes/views/tabs/tags_spec.js', 'lms/include/js/spec/edxnotes/views/tabs/tags_spec.js',
'lms/include/js/spec/edxnotes/views/visibility_decorator_spec.js', 'lms/include/js/spec/edxnotes/views/visibility_decorator_spec.js',
'lms/include/js/spec/edxnotes/views/toggle_notes_factory_spec.js', 'lms/include/js/spec/edxnotes/views/notes_visibility_factory_spec.js',
'lms/include/js/spec/edxnotes/models/tab_spec.js', 'lms/include/js/spec/edxnotes/models/tab_spec.js',
'lms/include/js/spec/edxnotes/models/note_spec.js', 'lms/include/js/spec/edxnotes/models/note_spec.js',
'lms/include/js/spec/edxnotes/plugins/accessibility_spec.js', 'lms/include/js/spec/edxnotes/plugins/accessibility_spec.js',
......
...@@ -13,8 +13,8 @@ define([ ...@@ -13,8 +13,8 @@ define([
'js/search/dashboard/views/search_form', 'js/search/dashboard/views/search_form',
'js/search/course/views/search_results_view', 'js/search/course/views/search_results_view',
'js/search/dashboard/views/search_results_view', 'js/search/dashboard/views/search_results_view',
'js/search/course/search_app', 'js/search/course/course_search_factory',
'js/search/dashboard/search_app' 'js/search/dashboard/dashboard_search_factory'
], function( ], function(
$, $,
Sinon, Sinon,
...@@ -30,8 +30,8 @@ define([ ...@@ -30,8 +30,8 @@ define([
DashSearchForm, DashSearchForm,
CourseSearchResultsView, CourseSearchResultsView,
DashSearchResultsView, DashSearchResultsView,
CourseSearchApp, CourseSearchFactory,
DashSearchApp DashboardSearchFactory
) { ) {
'use strict'; 'use strict';
...@@ -681,13 +681,7 @@ define([ ...@@ -681,13 +681,7 @@ define([
this.server = Sinon.fakeServer.create(); this.server = Sinon.fakeServer.create();
var courseId = 'a/b/c'; var courseId = 'a/b/c';
this.app = new CourseSearchApp( CourseSearchFactory(courseId);
courseId,
SearchRouter,
CourseSearchForm,
SearchCollection,
CourseSearchResultsView
);
spyOn(Backbone.history, 'navigate'); spyOn(Backbone.history, 'navigate');
this.$contentElement = $('#course-content'); this.$contentElement = $('#course-content');
this.$searchResults = $('#courseware-search-results'); this.$searchResults = $('#courseware-search-results');
...@@ -718,12 +712,7 @@ define([ ...@@ -718,12 +712,7 @@ define([
loadTemplates.call(this); loadTemplates.call(this);
this.server = Sinon.fakeServer.create(); this.server = Sinon.fakeServer.create();
this.app = new DashSearchApp( DashboardSearchFactory();
SearchRouter,
DashSearchForm,
SearchCollection,
DashSearchResultsView
);
spyOn(Backbone.history, 'navigate'); spyOn(Backbone.history, 'navigate');
this.$contentElement = $('#my-courses'); this.$contentElement = $('#my-courses');
......
...@@ -2,7 +2,7 @@ define(['common/js/spec_helpers/ajax_helpers', 'js/student_account/emailoptin'], ...@@ -2,7 +2,7 @@ define(['common/js/spec_helpers/ajax_helpers', 'js/student_account/emailoptin'],
function( AjaxHelpers, EmailOptInInterface ) { function( AjaxHelpers, EmailOptInInterface ) {
'use strict'; 'use strict';
describe( 'edx.student.account.EmailOptInInterface', function() { describe( 'EmailOptInInterface', function() {
var COURSE_KEY = 'edX/DemoX/Fall', var COURSE_KEY = 'edX/DemoX/Fall',
EMAIL_OPT_IN = 'True', EMAIL_OPT_IN = 'True',
......
...@@ -2,7 +2,7 @@ define(['common/js/spec_helpers/ajax_helpers', 'js/student_account/enrollment'], ...@@ -2,7 +2,7 @@ define(['common/js/spec_helpers/ajax_helpers', 'js/student_account/enrollment'],
function( AjaxHelpers, EnrollmentInterface ) { function( AjaxHelpers, EnrollmentInterface ) {
'use strict'; 'use strict';
describe( 'edx.student.account.EnrollmentInterface', function() { describe( 'EnrollmentInterface', function() {
var COURSE_KEY = 'edX/DemoX/Fall', var COURSE_KEY = 'edX/DemoX/Fall',
ENROLL_URL = '/api/commerce/v0/baskets/', ENROLL_URL = '/api/commerce/v0/baskets/',
......
...@@ -2,7 +2,7 @@ define(['common/js/spec_helpers/ajax_helpers', 'js/student_account/shoppingcart' ...@@ -2,7 +2,7 @@ define(['common/js/spec_helpers/ajax_helpers', 'js/student_account/shoppingcart'
function(AjaxHelpers, ShoppingCartInterface) { function(AjaxHelpers, ShoppingCartInterface) {
'use strict'; 'use strict';
describe( 'edx.student.account.ShoppingCartInterface', function() { describe( 'ShoppingCartInterface', function() {
var COURSE_KEY = "edX/DemoX/Fall", var COURSE_KEY = "edX/DemoX/Fall",
ADD_COURSE_URL = "/shoppingcart/add/course/edX/DemoX/Fall/", ADD_COURSE_URL = "/shoppingcart/add/course/edX/DemoX/Fall/",
......
var edx = edx || {}; ;(function (define) {
(function($) {
'use strict'; 'use strict';
define(['jquery', 'jquery.cookie'], function($) {
edx.student = edx.student || {}; var EmailOptInInterface = {
edx.student.account = edx.student.account || {};
edx.student.account.EmailOptInInterface = { urls: {
emailOptInUrl: '/user_api/v1/preferences/email_opt_in/'
},
urls: { headers: {
emailOptInUrl: '/user_api/v1/preferences/email_opt_in/' 'X-CSRFToken': $.cookie('csrftoken')
}, },
headers: { /**
'X-CSRFToken': $.cookie('csrftoken') * Set the email opt in setting for the organization associated
}, * with this course.
* @param {string} courseKey Slash-separated course key.
* @param {string} emailOptIn The preference to opt in or out of organization emails.
*/
setPreference: function( courseKey, emailOptIn ) {
return $.ajax({
url: this.urls.emailOptInUrl,
type: 'POST',
data: {course_id: courseKey, email_opt_in: emailOptIn},
headers: this.headers
});
}
};
/** return EmailOptInInterface;
* Set the email opt in setting for the organization associated });
* with this course. }).call(this, define || RequireJS.define);
* @param {string} courseKey Slash-separated course key.
* @param {string} emailOptIn The preference to opt in or out of organization emails.
*/
setPreference: function( courseKey, emailOptIn ) {
return $.ajax({
url: this.urls.emailOptInUrl,
type: 'POST',
data: {course_id: courseKey, email_opt_in: emailOptIn},
headers: this.headers
});
}
};
})(jQuery);
var edx = edx || {}; ;(function (define) {
(function($) {
'use strict'; 'use strict';
define(['jquery', 'jquery.cookie'], function($) {
edx.student = edx.student || {}; var EnrollmentInterface = {
edx.student.account = edx.student.account || {};
edx.student.account.EnrollmentInterface = {
urls: { urls: {
baskets: '/api/commerce/v0/baskets/', baskets: '/api/commerce/v0/baskets/',
}, },
headers: { headers: {
'X-CSRFToken': $.cookie('csrftoken') 'X-CSRFToken': $.cookie('csrftoken')
}, },
/** /**
* Enroll a user in a course, then redirect the user. * Enroll a user in a course, then redirect the user.
* @param {string} courseKey Slash-separated course key. * @param {string} courseKey Slash-separated course key.
* @param {string} redirectUrl The URL to redirect to once enrollment completes. * @param {string} redirectUrl The URL to redirect to once enrollment completes.
*/ */
enroll: function( courseKey, redirectUrl ) { enroll: function( courseKey, redirectUrl ) {
var data_obj = {course_id: courseKey}, var data_obj = {course_id: courseKey},
data = JSON.stringify(data_obj); data = JSON.stringify(data_obj);
$.ajax({ $.ajax({
url: this.urls.baskets, url: this.urls.baskets,
type: 'POST', type: 'POST',
contentType: 'application/json; charset=utf-8', contentType: 'application/json; charset=utf-8',
data: data, data: data,
headers: this.headers, headers: this.headers,
context: this context: this
}) }).fail(function( jqXHR ) {
.fail(function( jqXHR ) { var responseData = JSON.parse(jqXHR.responseText);
var responseData = JSON.parse(jqXHR.responseText); if ( jqXHR.status === 403 && responseData.user_message_url ) {
if ( jqXHR.status === 403 && responseData.user_message_url ) { // Check if we've been blocked from the course
// Check if we've been blocked from the course // because of country access rules.
// because of country access rules. // If so, redirect to a page explaining to the user
// If so, redirect to a page explaining to the user // why they were blocked.
// why they were blocked. this.redirect( responseData.user_message_url );
this.redirect( responseData.user_message_url ); } else {
} else { // Otherwise, redirect the user to the next page.
// Otherwise, redirect the user to the next page. if ( redirectUrl ) {
this.redirect( redirectUrl );
}
}
}).done(function() {
// If we successfully enrolled, redirect the user
// to the next page (usually the student dashboard or payment flow)
if ( redirectUrl ) { if ( redirectUrl ) {
this.redirect( redirectUrl ); this.redirect( redirectUrl );
} }
} });
}) },
.done(function() {
// If we successfully enrolled, redirect the user /**
// to the next page (usually the student dashboard or payment flow) * Redirect to a URL. Mainly useful for mocking out in tests.
if ( redirectUrl ) { * @param {string} url The URL to redirect to.
this.redirect( redirectUrl ); */
} redirect: function(url) {
}); window.location.href = url;
}, }
};
/** return EnrollmentInterface;
* Redirect to a URL. Mainly useful for mocking out in tests. });
* @param {string} url The URL to redirect to. }).call(this, define || RequireJS.define);
*/
redirect: function(url) {
window.location.href = url;
}
};
})(jQuery);
/** /**
* Use the shopping cart to purchase courses. * Use the shopping cart to purchase courses.
*/ */
;(function (define) {
var edx = edx || {};
(function($) {
'use strict'; 'use strict';
define(['jquery', 'jquery.cookie'], function($) {
edx.student = edx.student || {};
edx.student.account = edx.student.account || {}; var ShoppingCartInterface = {
urls: {
edx.student.account.ShoppingCartInterface = { viewCart: "/shoppingcart/",
addCourse: "/shoppingcart/add/course/"
urls: { },
viewCart: "/shoppingcart/",
addCourse: "/shoppingcart/add/course/" headers: {
}, 'X-CSRFToken': $.cookie('csrftoken')
},
headers: {
'X-CSRFToken': $.cookie('csrftoken') /**
}, * Add a course to a cart, then redirect to the view cart page.
* @param {string} courseId The slash-separated course ID to add to the cart.
/** */
* Add a course to a cart, then redirect to the view cart page. addCourseToCart: function( courseId ) {
* @param {string} courseId The slash-separated course ID to add to the cart. $.ajax({
*/ url: this.urls.addCourse + courseId + "/",
addCourseToCart: function( courseId ) { type: 'POST',
$.ajax({ data: {},
url: this.urls.addCourse + courseId + "/", headers: this.headers,
type: 'POST', context: this
data: {}, }).always(function() {
headers: this.headers, this.redirect( this.urls.viewCart );
context: this });
}).always(function() { },
this.redirect( this.urls.viewCart );
}); /**
}, * Redirect to a URL. Mainly useful for mocking out in tests.
* @param {string} url The URL to redirect to.
/** */
* Redirect to a URL. Mainly useful for mocking out in tests. redirect: function( url ) {
* @param {string} url The URL to redirect to. window.location.href = url;
*/ }
redirect: function( url ) { };
window.location.href = url;
} return ShoppingCartInterface;
}; });
}).call(this, define || RequireJS.define);
})(jQuery);
...@@ -26,18 +26,14 @@ ...@@ -26,18 +26,14 @@
;(function (define, undefined) { ;(function (define, undefined) {
'use strict'; 'use strict';
define([ define([
'jquery',
'underscore', 'underscore',
'backbone', 'backbone',
'gettext', 'gettext',
'js/student_account/emailoptin', 'js/student_account/emailoptin',
'js/student_account/enrollment', 'js/student_account/enrollment',
'js/student_account/shoppingcart' 'js/student_account/shoppingcart'
], function (_, Backbone, gettext, emailOptInInterface, enrollmentInterface, shoppingCartInterface) { ], function ($, _, Backbone, gettext, emailOptInInterface, enrollmentInterface, shoppingCartInterface) {
// These are not yet converted to requireJS:
var edx = window.edx || {};
emailOptInInterface = emailOptInInterface || edx.student.account.EmailOptInInterface;
enrollmentInterface = enrollmentInterface || edx.student.account.EnrollmentInterface;
shoppingCartInterface = shoppingCartInterface || edx.student.account.ShoppingCartInterface;
var FinishAuthView = Backbone.View.extend({ var FinishAuthView = Backbone.View.extend({
el: '#finish-auth-status', el: '#finish-auth-status',
......
;(function (define, undefined) { ;(function (define, undefined) {
'use strict'; 'use strict';
define([ define([
'gettext', 'jquery', 'underscore', 'backbone', 'js/mustache', 'js/views/fields' 'gettext', 'jquery', 'underscore', 'backbone', 'js/views/fields'
], function (gettext, $, _, Backbone, RequireMustache, FieldViews) { ], function (gettext, $, _, Backbone, FieldViews) {
var AccountSettingsFieldViews = {}; var AccountSettingsFieldViews = {};
......
(function (define) {
'use strict';
define("js/student_account/views/finish_auth_factory",
['jquery', 'underscore', 'backbone', 'js/student_account/views/FinishAuthView', 'utility'],
function ($, _, Backbone, FinishAuthView) {
return function() {
var view = new FinishAuthView({});
view.render();
};
}
);
}).call(this, define || RequireJS.define);
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
'js/student_profile/views/learner_profile_fields', 'js/student_profile/views/learner_profile_fields',
'js/student_profile/views/learner_profile_view', 'js/student_profile/views/learner_profile_view',
'js/student_account/views/account_settings_fields', 'js/student_account/views/account_settings_fields',
'js/views/message_banner' 'js/views/message_banner',
'string_utils'
], function (gettext, $, _, Backbone, Logger, AccountSettingsModel, AccountPreferencesModel, FieldsView, ], function (gettext, $, _, Backbone, Logger, AccountSettingsModel, AccountPreferencesModel, FieldsView,
LearnerProfileFieldsView, LearnerProfileView, AccountSettingsFieldViews, MessageBannerView) { LearnerProfileFieldsView, LearnerProfileView, AccountSettingsFieldViews, MessageBannerView) {
......
;(function (define, undefined) { ;(function (define, undefined) {
'use strict'; 'use strict';
define([ define([
'gettext', 'jquery', 'underscore', 'backbone', 'js/mustache', 'backbone-super' 'gettext', 'jquery', 'underscore', 'backbone', 'backbone-super', 'jquery.fileupload'
], function (gettext, $, _, Backbone, RequireMustache) { ], function (gettext, $, _, Backbone) {
var Mustache = window.Mustache || RequireMustache;
var messageRevertDelay = 6000; var messageRevertDelay = 6000;
var FieldViews = {}; var FieldViews = {};
...@@ -127,7 +125,7 @@ ...@@ -127,7 +125,7 @@
if (xhr.status === 400) { if (xhr.status === 400) {
try { try {
var errors = JSON.parse(xhr.responseText), var errors = JSON.parse(xhr.responseText),
validationErrorMessage = Mustache.escapeHtml( validationErrorMessage = _.escape(
errors.field_errors[this.options.valueAttribute].user_message errors.field_errors[this.options.valueAttribute].user_message
), ),
message = this.indicators.validationError + validationErrorMessage; message = this.indicators.validationError + validationErrorMessage;
...@@ -253,7 +251,7 @@ ...@@ -253,7 +251,7 @@
}, },
updateValueInField: function () { updateValueInField: function () {
this.$('.u-field-value input').val(Mustache.escapeHtml(this.modelValue())); this.$('.u-field-value input').val(_.escape(this.modelValue()));
} }
}); });
...@@ -290,7 +288,7 @@ ...@@ -290,7 +288,7 @@
updateValueInField: function () { updateValueInField: function () {
var value = (_.isUndefined(this.modelValue()) || _.isNull(this.modelValue())) ? '' : this.modelValue(); var value = (_.isUndefined(this.modelValue()) || _.isNull(this.modelValue())) ? '' : this.modelValue();
this.$('.u-field-value input').val(Mustache.escapeHtml(value)); this.$('.u-field-value input').val(_.escape(value));
}, },
saveValue: function () { saveValue: function () {
...@@ -375,7 +373,7 @@ ...@@ -375,7 +373,7 @@
value = this.options.placeholderValue || ''; value = this.options.placeholderValue || '';
} }
this.$('.u-field-value').attr('aria-label', this.options.title); this.$('.u-field-value').attr('aria-label', this.options.title);
this.$('.u-field-value-readonly').html(Mustache.escapeHtml(value)); this.$('.u-field-value-readonly').html(_.escape(value));
if (this.mode === 'display') { if (this.mode === 'display') {
this.updateDisplayModeClass(); this.updateDisplayModeClass();
......
(function () {
'use strict';
var getModulesList = function (modules) {
return modules.map(function (moduleName) {
return { name: moduleName };
});
};
var jsOptimize = process.env.REQUIRE_BUILD_PROFILE_OPTIMIZE !== undefined ?
process.env.REQUIRE_BUILD_PROFILE_OPTIMIZE : 'uglify2';
return {
namespace: "RequireJS",
/**
* List the modules that will be optimized. All their immediate and deep
* dependencies will be included in the module's file when the build is
* done.
*/
modules: getModulesList([
'js/discovery/discovery_factory',
'js/edxnotes/views/notes_visibility_factory',
'js/edxnotes/views/page_factory',
'js/groups/views/cohorts_dashboard_factory',
'js/search/course/course_search_factory',
'js/search/dashboard/dashboard_search_factory',
'js/student_account/views/account_settings_factory',
'js/student_account/views/finish_auth_factory',
'js/student_profile/views/learner_profile_factory',
'teams/js/teams_tab_factory'
]),
/**
* By default all the configuration for optimization happens from the command
* line or by properties in the config file, and configuration that was
* passed to requirejs as part of the app's runtime "main" JS file is *not*
* considered. However, if you prefer the "main" JS file configuration
* to be read for the build so that you do not have to duplicate the values
* in a separate configuration, set this property to the location of that
* main JS file. The first requirejs({}), require({}), requirejs.config({}),
* or require.config({}) call found in that file will be used.
* As of 2.1.10, mainConfigFile can be an array of values, with the last
* value's config take precedence over previous values in the array.
*/
mainConfigFile: 'require-config.js',
/**
* Set paths for modules. If relative paths, set relative to baseUrl above.
* If a special value of "empty:" is used for the path value, then that
* acts like mapping the path to an empty file. It allows the optimizer to
* resolve the dependency to path, but then does not include it in the output.
* Useful to map module names that are to resources on a CDN or other
* http: URL when running in the browser and during an optimization that
* file should be skipped because it has no dependencies.
*/
paths: {
'gettext': 'empty:',
'coffee/src/ajax_prefix': 'empty:',
'jquery': 'empty:',
'jquery.cookie': 'empty:',
'jquery.url': 'empty:',
'backbone': 'empty:',
'underscore': 'empty:',
'logger': 'empty:',
'utility': 'empty:',
'URI': 'empty:',
},
/**
* Inline requireJS text templates.
*/
inlineText: true,
/**
* Stub out requireJS text in the optimized file, but leave available for non-optimized development use.
*/
stubModules: ["text"],
/**
* If shim config is used in the app during runtime, duplicate the config
* here. Necessary if shim config is used, so that the shim's dependencies
* are included in the build. Using "mainConfigFile" is a better way to
* pass this information though, so that it is only listed in one place.
* However, if mainConfigFile is not an option, the shim config can be
* inlined in the build config.
*/
shim: {},
/**
* Introduced in 2.1.2: If using "dir" for an output directory, normally the
* optimize setting is used to optimize the build bundles (the "modules"
* section of the config) and any other JS file in the directory. However, if
* the non-build bundle JS files will not be loaded after a build, you can
* skip the optimization of those files, to speed up builds. Set this value
* to true if you want to skip optimizing those other non-build bundle JS
* files.
*/
skipDirOptimize: true,
/**
* When the optimizer copies files from the source location to the
* destination directory, it will skip directories and files that start
* with a ".". If you want to copy .directories or certain .files, for
* instance if you keep some packages in a .packages directory, or copy
* over .htaccess files, you can set this to null. If you want to change
* the exclusion rules, change it to a different regexp. If the regexp
* matches, it means the directory will be excluded. This used to be
* called dirExclusionRegExp before the 1.0.2 release.
* As of 1.0.3, this value can also be a string that is converted to a
* RegExp via new RegExp().
*/
fileExclusionRegExp: /^\.|spec|spec_helpers/,
/**
* Allow CSS optimizations. Allowed values:
* - "standard": @import inlining and removal of comments, unnecessary
* whitespace and line returns.
* Removing line returns may have problems in IE, depending on the type
* of CSS.
* - "standard.keepLines": like "standard" but keeps line returns.
* - "none": skip CSS optimizations.
* - "standard.keepComments": keeps the file comments, but removes line
* returns. (r.js 1.0.8+)
* - "standard.keepComments.keepLines": keeps the file comments and line
* returns. (r.js 1.0.8+)
* - "standard.keepWhitespace": like "standard" but keeps unnecessary whitespace.
*/
optimizeCss: 'none',
/**
* How to optimize all the JS files in the build output directory.
* Right now only the following values are supported:
* - "uglify": Uses UglifyJS to minify the code.
* - "uglify2": Uses UglifyJS2.
* - "closure": Uses Google's Closure Compiler in simple optimization
* mode to minify the code. Only available if REQUIRE_ENVIRONMENT is "rhino" (the default).
* - "none": No minification will be done.
*/
optimize: jsOptimize,
/**
* Sets the logging level. It is a number:
* TRACE: 0,
* INFO: 1,
* WARN: 2,
* ERROR: 3,
* SILENT: 4
* Default is 0.
*/
logLevel: 1
};
} ())
;(function (require, define) { ;(function (require, define) {
var paths = {}, config;
// jquery, underscore, gettext, URI, tinymce, or jquery.tinymce may already // We do not wish to bundle common libraries (that may also be used by non-RequireJS code on the page
// have been loaded and we do not want to load them a second time. Check if // into the optimized files. Therefore load these libraries through script tags and explicitly define them.
// it is the case and use the global var instead. // Note that when the optimizer executes this code, window will not be defined.
if (window.jQuery) { if (window) {
define("jquery", [], function() {return window.jQuery;}); var defineDependency = function (globalVariable, name, noShim) {
} else { if (window[globalVariable]) {
paths.jquery = "js/vendor/jquery.min"; if (noShim) {
} define(name, {});
if (window._) { }
define("underscore", [], function() {return window._;}); else {
} else { define(name, [], function() {return window[globalVariable];});
paths.jquery = "js/vendor/underscore-min"; }
} }
if (window.gettext) { else {
define("gettext", [], function() {return window.gettext;}); console.error("Expected library to be included on page, but not found on window object: " + name);
} else { }
paths.gettext = "/i18n"; };
} defineDependency("jQuery", "jquery");
if (window.Logger) { defineDependency("_", "underscore");
define("logger", [], function() {return window.Logger;}); defineDependency("gettext", "gettext");
} else { defineDependency("Logger", "logger");
paths.logger = "js/src/logger"; defineDependency("URI", "URI");
} defineDependency("Backbone", "backbone");
if (window.URI) { // utility.js adds two functions to the window object, but does not return anything
define("URI", [], function() {return window.URI;}); defineDependency("isExternal", "utility", true);
} else {
paths.URI = "js/vendor/URI.min";
}
if (window.tinymce) {
define('tinymce', [], function() {return window.tinymce;});
} else {
paths.tinymce = "js/vendor/tinymce/js/tinymce/tinymce.full.min";
}
if (window.jquery && window.jquery.tinymce) {
define("jquery.tinymce", [], function() {return window.jquery.tinymce;});
} else {
paths.tinymce = "js/vendor/tinymce/js/tinymce/jquery.tinymce.min";
} }
config = { require.config({
// NOTE: baseUrl has been previously set in lms/static/templates/main.html // NOTE: baseUrl has been previously set in lms/templates/main.html
waitSeconds: 60, waitSeconds: 60,
paths: { paths: {
"gettext": "/i18n",
"annotator_1.2.9": "js/vendor/edxnotes/annotator-full.min", "annotator_1.2.9": "js/vendor/edxnotes/annotator-full.min",
"date": "js/vendor/date", "date": "js/vendor/date",
"text": 'js/vendor/requirejs/text', "text": "js/vendor/requirejs/text",
"logger": "js/src/logger",
"backbone": "js/vendor/backbone-min", "backbone": "js/vendor/backbone-min",
"backbone-super": "js/vendor/backbone-super", "backbone-super": "js/vendor/backbone-super",
"backbone.paginator": "js/vendor/backbone.paginator.min", "backbone.paginator": "js/vendor/backbone.paginator.min",
"underscore": "js/vendor/underscore-min",
"underscore.string": "js/vendor/underscore.string.min", "underscore.string": "js/vendor/underscore.string.min",
"jquery": "js/vendor/jquery.min",
"jquery.cookie": "js/vendor/jquery.cookie",
"jquery.url": "js/vendor/url.min",
"jquery.ui": "js/vendor/jquery-ui.min",
"jquery.iframe-transport": "js/vendor/jQuery-File-Upload/js/jquery.iframe-transport",
"jquery.fileupload": "js/vendor/jQuery-File-Upload/js/jquery.fileupload",
"URI": "js/vendor/URI.min",
"string_utils": "js/src/string_utils",
"utility": "js/src/utility",
// Files needed by OVA // Files needed by OVA
"annotator": "js/vendor/ova/annotator-full", "annotator": "js/vendor/ova/annotator-full",
"annotator-harvardx": "js/vendor/ova/annotator-full-firebase-auth", "annotator-harvardx": "js/vendor/ova/annotator-full-firebase-auth",
"video.dev": "js/vendor/ova/video.dev", "video.dev": "js/vendor/ova/video.dev",
"vjs.youtube": 'js/vendor/ova/vjs.youtube', "vjs.youtube": "js/vendor/ova/vjs.youtube",
"rangeslider": 'js/vendor/ova/rangeslider', "rangeslider": "js/vendor/ova/rangeslider",
"share-annotator": 'js/vendor/ova/share-annotator', "share-annotator": "js/vendor/ova/share-annotator",
"richText-annotator": 'js/vendor/ova/richText-annotator', "richText-annotator": "js/vendor/ova/richText-annotator",
"reply-annotator": 'js/vendor/ova/reply-annotator', "reply-annotator": "js/vendor/ova/reply-annotator",
"grouping-annotator": 'js/vendor/ova/grouping-annotator', "grouping-annotator": "js/vendor/ova/grouping-annotator",
"tags-annotator": 'js/vendor/ova/tags-annotator', "tags-annotator": "js/vendor/ova/tags-annotator",
"diacritic-annotator": 'js/vendor/ova/diacritic-annotator', "diacritic-annotator": "js/vendor/ova/diacritic-annotator",
"flagging-annotator": 'js/vendor/ova/flagging-annotator', "flagging-annotator": "js/vendor/ova/flagging-annotator",
"jquery-Watch": 'js/vendor/ova/jquery-Watch', "jquery-Watch": "js/vendor/ova/jquery-Watch",
"openseadragon": 'js/vendor/ova/openseadragon', "openseadragon": "js/vendor/ova/openseadragon",
"osda": 'js/vendor/ova/OpenSeaDragonAnnotation', "osda": "js/vendor/ova/OpenSeaDragonAnnotation",
"ova": 'js/vendor/ova/ova', "ova": "js/vendor/ova/ova",
"catch": 'js/vendor/ova/catch/js/catch', "catch": "js/vendor/ova/catch/js/catch",
"handlebars": 'js/vendor/ova/catch/js/handlebars-1.1.2' "handlebars": "js/vendor/ova/catch/js/handlebars-1.1.2",
"tinymce": "js/vendor/tinymce/js/tinymce/tinymce.full.min",
"jquery.tinymce": "js/vendor/tinymce/js/tinymce/jquery.tinymce.min"
// end of files needed by OVA // end of files needed by OVA
}, },
shim: { shim: {
"gettext": {
exports: "gettext"
},
"annotator_1.2.9": { "annotator_1.2.9": {
deps: ["jquery"], deps: ["jquery"],
exports: "Annotator" exports: "Annotator"
...@@ -83,6 +88,22 @@ ...@@ -83,6 +88,22 @@
"jquery": { "jquery": {
exports: "$" exports: "$"
}, },
"jquery.cookie": {
deps: ["jquery"],
exports: "jQuery.fn.cookie"
},
"jquery.url": {
deps: ["jquery"],
exports: "jQuery.url"
},
"jquery.fileupload": {
deps: ["jquery.ui", "jquery.iframe-transport"],
exports: "jQuery.fn.fileupload"
},
"jquery.tinymce": {
deps: ["jquery", "tinymce"],
exports: "jQuery.fn.tinymce"
},
"underscore": { "underscore": {
exports: "_" exports: "_"
}, },
...@@ -97,8 +118,9 @@ ...@@ -97,8 +118,9 @@
"backbone-super": { "backbone-super": {
deps: ["backbone"] deps: ["backbone"]
}, },
"logger": { "string_utils": {
exports: "Logger" deps: ["underscore"],
exports: "interpolate_text"
}, },
// Needed by OVA // Needed by OVA
"video.dev": { "video.dev": {
...@@ -153,15 +175,11 @@ ...@@ -153,15 +175,11 @@
"grouping-annotator", "diacritic-annotator", "openseadragon", "jquery-Watch", "catch", "handlebars", "grouping-annotator", "diacritic-annotator", "openseadragon", "jquery-Watch", "catch", "handlebars",
"URI" "URI"
] ]
},
"tinymce": {
exports: "tinymce"
} }
// End of needed by OVA // End of needed by OVA
} }
}; });
for (var key in paths) {
if ({}.hasOwnProperty.call(paths, key)) {
config.paths[key] = paths[key];
}
}
require.config(config);
}).call(this, require || RequireJS.require, define || RequireJS.define); }).call(this, require || RequireJS.require, define || RequireJS.define);
...@@ -19,9 +19,7 @@ from django.utils.translation import ugettext as _ ...@@ -19,9 +19,7 @@ from django.utils.translation import ugettext as _
</%block> </%block>
<%block name="js_extra"> <%block name="js_extra">
<script src="${static.url('js/vendor/jquery.ajax-retry.js')}"></script> <script src="${static.url('js/vendor/jquery.ajax-retry.js')}"></script>
<script src="${static.url('js/vendor/underscore-min.js')}"></script>
<script src="${static.url('js/vendor/underscore.string.min.js')}"></script> <script src="${static.url('js/vendor/underscore.string.min.js')}"></script>
<script src="${static.url('js/vendor/backbone-min.js')}"></script>
<script src="${static.url('js/src/tooltip_manager.js')}"></script> <script src="${static.url('js/src/tooltip_manager.js')}"></script>
<script src="${static.url('js/commerce/views/receipt_view.js')}"></script> <script src="${static.url('js/commerce/views/receipt_view.js')}"></script>
</%block> </%block>
......
...@@ -2,33 +2,27 @@ ...@@ -2,33 +2,27 @@
import json import json
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from microsite_configuration import microsite from microsite_configuration import microsite
from openedx.core.lib.json_utils import EscapedEdxJSONEncoder
%> %>
<%inherit file="../main.html" /> <%inherit file="../main.html" />
<%namespace name='static' file='../static_content.html'/> <%namespace name='static' file='../static_content.html'/>
% if settings.FEATURES.get('ENABLE_COURSE_DISCOVERY'):
<%block name="header_extras"> <%block name="header_extras">
% if settings.FEATURES.get('ENABLE_COURSE_DISCOVERY'):
% for template_name in ["result_item", "filter_bar", "filter", "search_facets_list", "search_facets_section", "search_facet", "more_less_links"]: % for template_name in ["result_item", "filter_bar", "filter", "search_facets_list", "search_facets_section", "search_facet", "more_less_links"]:
<script type="text/template" id="${template_name}-tpl"> <script type="text/template" id="${template_name}-tpl">
<%static:include path="discovery/${template_name}.underscore" /> <%static:include path="discovery/${template_name}.underscore" />
</script> </script>
% endfor % endfor
<script type="text/javascript">;(function (define) {{ <%static:require_module module_name="js/discovery/discovery_factory" class_name="DiscoveryFactory">
define('course_discovery_meanings', function() {{ DiscoveryFactory(
'use strict'; ${json.dumps(course_discovery_meanings, cls=EscapedEdxJSONEncoder)},
return ${json.dumps(course_discovery_meanings)}; getParameterByName('search_query')
}}); );
}})(define || RequireJS.define); </%static:require_module>
</script>
% endif
</%block>
<%block name="js_extra">
% if settings.FEATURES.get('ENABLE_COURSE_DISCOVERY'):
<%static:js group='discovery'/>
% endif
</%block> </%block>
% endif
<%block name="pagetitle">${_("Courses")}</%block> <%block name="pagetitle">${_("Courses")}</%block>
<% <%
......
...@@ -66,7 +66,10 @@ ${page_title_breadcrumbs(course_name())} ...@@ -66,7 +66,10 @@ ${page_title_breadcrumbs(course_name())}
<%static:js group='courseware'/> <%static:js group='courseware'/>
<%static:js group='discussion'/> <%static:js group='discussion'/>
% if settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH'): % if settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH'):
<%static:js group='courseware_search'/> <%static:require_module module_name="js/search/course/course_search_factory" class_name="CourseSearchFactory">
var courseId = $('#courseware-search-results').data('courseId');
CourseSearchFactory(courseId);
</%static:require_module>
% endif % endif
<%include file="../discussion/_js_body_dependencies.html" /> <%include file="../discussion/_js_body_dependencies.html" />
......
...@@ -45,7 +45,9 @@ from django.core.urlresolvers import reverse ...@@ -45,7 +45,9 @@ from django.core.urlresolvers import reverse
}); });
</script> </script>
% if settings.FEATURES.get('ENABLE_DASHBOARD_SEARCH'): % if settings.FEATURES.get('ENABLE_DASHBOARD_SEARCH'):
<%static:js group='dashboard_search'/> <%static:require_module module_name="js/search/dashboard/dashboard_search_factory" class_name="DashboardSearchFactory">
DashboardSearchFactory();
</%static:require_module>
% endif % endif
</%block> </%block>
......
...@@ -9,9 +9,7 @@ ...@@ -9,9 +9,7 @@
<script type="text/javascript" src="${static.url('js/jquery.autocomplete.js')}"></script> <script type="text/javascript" src="${static.url('js/jquery.autocomplete.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/jquery.timeago.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/jquery.timeago.js')}"></script>
<script type="text/javascript" src="${static.url('js/src/jquery.timeago.locale.js')}"></script> <script type="text/javascript" src="${static.url('js/src/jquery.timeago.locale.js')}"></script>
<script type="text/javascript" src="${static.url('js/mustache.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/mustache.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/URI.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/backbone-min.js')}"></script>
<script type="text/javascript" src="${static.url('js/src/tooltip_manager.js')}"></script> <script type="text/javascript" src="${static.url('js/src/tooltip_manager.js')}"></script>
<link href="${static.url('css/vendor/jquery.autocomplete.css')}" rel="stylesheet" type="text/css"> <link href="${static.url('css/vendor/jquery.autocomplete.css')}" rel="stylesheet" type="text/css">
...@@ -102,17 +102,14 @@ import json ...@@ -102,17 +102,14 @@ import json
</script> </script>
% endfor % endfor
</%block> </%block>
<%block name="js_extra">
% if notes: % if notes:
<script type="text/javascript"> <%block name="js_extra">
(function (require) { <%static:require_module module_name="js/edxnotes/views/page_factory" class_name="NotesPageFactory">
require(['js/edxnotes/views/page_factory'], function (NotesPageFactory) { NotesPageFactory({
var pageView = new NotesPageFactory({ notesList: ${notes if notes is not None else []},
notesList: ${notes}, debugMode: ${debug}
debugMode: ${debug} });
}); </%static:require_module>
}); </%block>
}).call(this, require || RequireJS.require);
</script>
% endif % endif
</%block>
...@@ -3,6 +3,7 @@ import json ...@@ -3,6 +3,7 @@ import json
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
%> %>
<%namespace name='static' file='/static_content.html'/>
<%page args="course"/> <%page args="course"/>
<% <%
...@@ -20,10 +21,7 @@ from django.core.urlresolvers import reverse ...@@ -20,10 +21,7 @@ from django.core.urlresolvers import reverse
% endif % endif
</button> </button>
</div> </div>
<script type="text/javascript">
(function (require) { <%static:require_module module_name="js/edxnotes/views/notes_visibility_factory" class_name="NotesVisibilityFactory">
require(['js/edxnotes/views/toggle_notes_factory'], function(ToggleNotesFactory) { NotesVisibilityFactory.ToggleVisibilityView(${json.dumps(edxnotes_visibility)}, '${edxnotes_visibility_url}');
ToggleNotesFactory(${json.dumps(edxnotes_visibility)}, '${edxnotes_visibility_url}'); </%static:require_module>
});
}).call(this, require || RequireJS.require);
</script>
<%page args="section_data"/> <%page args="section_data"/>
<%namespace name='static' file='../../static_content.html'/>
<%! <%!
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from courseware.courses import get_studio_url from courseware.courses import get_studio_url
...@@ -16,32 +17,23 @@ from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_ ...@@ -16,32 +17,23 @@ from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_
</div> </div>
<%block name="headextra"> <%block name="js_extra">
<%static:require_module module_name="js/groups/views/cohorts_dashboard_factory" class_name="CohortsFactory">
<% <%
cohorted_user_partition = get_cohorted_user_partition(course.id) cohorted_user_partition = get_cohorted_user_partition(course.id)
content_groups = cohorted_user_partition.groups if cohorted_user_partition else [] content_groups = cohorted_user_partition.groups if cohorted_user_partition else []
%> %>
<script type="text/javascript"> var cohortUserPartitionId = ${cohorted_user_partition.id if cohorted_user_partition else 'null'},
$(document).ready(function() { contentGroups = [
% for content_group in content_groups:
var cohortUserPartitionId = ${cohorted_user_partition.id if cohorted_user_partition else 'null'}, {
contentGroups = [ id: ${content_group.id},
% for content_group in content_groups: name: "${content_group.name | h}",
new edx.groups.ContentGroupModel({ user_partition_id: cohortUserPartitionId
id: ${content_group.id}, },
name: "${content_group.name | h}", % endfor
user_partition_id: cohortUserPartitionId ];
}), CohortsFactory(contentGroups, '${get_studio_url(course, 'group_configurations') | h}');
% endfor </%static:require_module>
];
(function (require) {
require(['js/groups/views/cohorts_dashboard_factory'], function (CohortsFactory) {
CohortsFactory(contentGroups, '${get_studio_url(course, 'group_configurations') | h}');
});
}).call(this, require || RequireJS.require);
});
</script>
</%block> </%block>
<div class="cohort-state-message"></div> <div class="cohort-state-message"></div>
...@@ -34,7 +34,6 @@ from django.core.urlresolvers import reverse ...@@ -34,7 +34,6 @@ from django.core.urlresolvers import reverse
window.Range.prototype = { }; window.Range.prototype = { };
} }
</script> </script>
<script type="text/javascript" src="${static.url('js/vendor/backbone-min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/mustache.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/mustache.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/flot/jquery.flot.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/flot/jquery.flot.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/flot/jquery.flot.axislabels.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/flot/jquery.flot.axislabels.js')}"></script>
...@@ -57,22 +56,9 @@ from django.core.urlresolvers import reverse ...@@ -57,22 +56,9 @@ from django.core.urlresolvers import reverse
<%static:js group='application'/> <%static:js group='application'/>
## Backbone classes declared explicitly until RequireJS is supported ## Backbone classes declared explicitly until RequireJS is supported
<script type="text/javascript" src="${static.url('js/instructor_dashboard/cohort_management.js')}"></script>
<script type="text/javascript" src="${static.url('js/models/notification.js')}"></script> <script type="text/javascript" src="${static.url('js/models/notification.js')}"></script>
<script type="text/javascript" src="${static.url('js/views/notification.js')}"></script> <script type="text/javascript" src="${static.url('js/views/notification.js')}"></script>
<script type="text/javascript" src="${static.url('js/views/file_uploader.js')}"></script> <script type="text/javascript" src="${static.url('js/views/file_uploader.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/models/cohort.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/models/content_group.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/models/course_cohort_settings.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/collections/cohort.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/course_cohort_settings_notification.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/models/cohort_discussions.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohort_discussions.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohort_discussions_course_wide.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohort_discussions_inline.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohort_form.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohort_editor.js')}"></script>
<script type="text/javascript" src="${static.url('js/groups/views/cohorts.js')}"></script>
<script type="text/javascript" src="${static.url('js/utils/animation.js')}"></script> <script type="text/javascript" src="${static.url('js/utils/animation.js')}"></script>
</%block> </%block>
......
...@@ -57,7 +57,7 @@ from branding import api as branding_api ...@@ -57,7 +57,7 @@ from branding import api as branding_api
</script> </script>
% endif % endif
<script type="text/javascript" src="/jsi18n/"></script> <script type="text/javascript" src="/i18n.js"></script>
<link rel="icon" type="image/x-icon" href="${static.url(microsite.get_value('favicon_path', settings.FAVICON_PATH))}" /> <link rel="icon" type="image/x-icon" href="${static.url(microsite.get_value('favicon_path', settings.FAVICON_PATH))}" />
...@@ -66,26 +66,22 @@ from branding import api as branding_api ...@@ -66,26 +66,22 @@ from branding import api as branding_api
% if disable_courseware_js: % if disable_courseware_js:
<%static:js group='base_vendor'/> <%static:js group='base_vendor'/>
<%static:js group='base_application'/>
% else: % else:
<%static:js group='main_vendor'/> <%static:js group='main_vendor'/>
<%static:js group='application'/>
<%static:js group='module-js'/>
% endif % endif
<script> <script>
window.baseUrl = "${settings.STATIC_URL}"; window.baseUrl = "${settings.STATIC_URL}";
(function (require) { (function (require) {
% if settings.DEBUG is True:
## Using what amounts to a random number in the Development environment for cache-busting
var urlArgs = "bust=" + (new Date()).getTime();
% else:
var urlArgs = "v=${settings.EDX_PLATFORM_REVISION}";
% endif
require.config({ require.config({
baseUrl: baseUrl, baseUrl: window.baseUrl
urlArgs: urlArgs
}); });
}).call(this, require || RequireJS.require); }).call(this, require || RequireJS.require);
</script> </script>
<script type="text/javascript" src="${static.url("require-config-lms.js")}"></script> <script type="text/javascript" src="${static.url("lms/js/require-config.js")}"></script>
<%block name="headextra"/> <%block name="headextra"/>
...@@ -160,11 +156,6 @@ from branding import api as branding_api ...@@ -160,11 +156,6 @@ from branding import api as branding_api
</div> </div>
% endif % endif
% if not disable_courseware_js:
<%static:js group='application'/>
<%static:js group='module-js'/>
% endif
<%block name="js_extra"/> <%block name="js_extra"/>
<script type="text/javascript" src="${static.url('js/vendor/noreferrer.js')}" charset="utf-8"></script> <script type="text/javascript" src="${static.url('js/vendor/noreferrer.js')}" charset="utf-8"></script>
</body> </body>
......
...@@ -37,21 +37,16 @@ from microsite_configuration import microsite ...@@ -37,21 +37,16 @@ from microsite_configuration import microsite
<%block name="headextra"> <%block name="headextra">
<%static:css group='style-course'/> <%static:css group='style-course'/>
</%block>
<script> <%block name="js_extra">
(function (require) { <%static:require_module module_name="js/student_account/views/account_settings_factory" class_name="AccountSettingsFactory">
require(['js/student_account/views/account_settings_factory'], function(setupAccountSettingsSection) { var fieldsData = ${ json.dumps(fields) };
var authData = ${ json.dumps(auth) };
var fieldsData = ${ json.dumps(fields) }; var platformName = ${ json.dumps(microsite.get_value('platform_name', settings.PLATFORM_NAME))};
var authData = ${ json.dumps(auth) };
var platformName = ${ json.dumps(microsite.get_value('platform_name', settings.PLATFORM_NAME))};
setupAccountSettingsSection(
fieldsData, authData, '${user_accounts_api_url}', '${user_preferences_api_url}', ${user.id},
platformName
);
});
}).call(this, require || RequireJS.require);
</script>
AccountSettingsFactory(
fieldsData, authData, '${user_accounts_api_url}', '${user_preferences_api_url}', ${user.id}, platformName
);
</%static:require_module>
</%block> </%block>
...@@ -4,38 +4,10 @@ ...@@ -4,38 +4,10 @@
<%block name="pagetitle">${_("Please Wait")}</%block> <%block name="pagetitle">${_("Please Wait")}</%block>
<%block name="js_extra">
<script src="${static.url('js/vendor/backbone-min.js')}"></script>
<%static:js group='utility'/>
</%block>
<%block name="headextra"> <%block name="headextra">
<%static:require_module module_name="js/student_account/views/finish_auth_factory" class_name="FinishAuthFactory">
<script> FinishAuthFactory();
(function (require, define) { </%static:require_module>
'use strict';
define("js/student_account/views/finish_auth_factory",
[
'jquery', 'underscore', 'backbone',
'js/student_account/views/FinishAuthView'
],
function ($, _, Backbone, FinishAuthView) {
return function() {
var view = new FinishAuthView({});
view.render();
};
}
);
require(["js/student_account/views/finish_auth_factory"],
function (factory) {
factory();
}
);
}).call(this, require || RequireJS.require, define || RequireJS.define);
</script>
</%block> </%block>
<div class="finish-auth"> <div class="finish-auth">
......
...@@ -6,10 +6,7 @@ ...@@ -6,10 +6,7 @@
<%block name="pagetitle">${_("Sign in or Register")}</%block> <%block name="pagetitle">${_("Sign in or Register")}</%block>
<%block name="js_extra"> <%block name="js_extra">
<script src="${static.url('js/vendor/underscore-min.js')}"></script>
<script src="${static.url('js/vendor/underscore.string.min.js')}"></script> <script src="${static.url('js/vendor/underscore.string.min.js')}"></script>
<script src="${static.url('js/vendor/backbone-min.js')}"></script>
<script src="${static.url('js/vendor/url.min.js')}"></script>
<script src="${static.url('js/vendor/history.js')}"></script> <script src="${static.url('js/vendor/history.js')}"></script>
<%static:js group='student_account'/> <%static:js group='student_account'/>
</%block> </%block>
......
...@@ -34,16 +34,11 @@ from openedx.core.lib.json_utils import EscapedEdxJSONEncoder ...@@ -34,16 +34,11 @@ from openedx.core.lib.json_utils import EscapedEdxJSONEncoder
</div> </div>
<%block name="headextra"> <%block name="headextra">
<%static:css group='style-course'/> <%static:css group='style-course'/>
</%block>
<script type="text/javascript" src="${static.url('js/vendor/jQuery-File-Upload/js/jquery.fileupload.js')}"></script> <%block name="js_extra">
<%static:require_module module_name="js/student_profile/views/learner_profile_factory" class_name="LearnerProfileFactory">
<script> var options = ${ json.dumps(data, cls=EscapedEdxJSONEncoder) };
(function (require) { LearnerProfileFactory(options);
require(['js/student_profile/views/learner_profile_factory'], function(setupLearnerProfile) { </%static:require_module>
var options = ${ json.dumps(data, cls=EscapedEdxJSONEncoder) };
setupLearnerProfile(options);
});
}).call(this, require || RequireJS.require);
</script>
</%block> </%block>
...@@ -18,9 +18,7 @@ from django.utils.translation import ugettext as _ ...@@ -18,9 +18,7 @@ from django.utils.translation import ugettext as _
% endfor % endfor
</%block> </%block>
<%block name="js_extra"> <%block name="js_extra">
<script src="${static.url('js/vendor/underscore-min.js')}"></script>
<script src="${static.url('js/vendor/underscore.string.min.js')}"></script> <script src="${static.url('js/vendor/underscore.string.min.js')}"></script>
<script src="${static.url('js/vendor/backbone-min.js')}"></script>
<script src="${static.url('js/src/tooltip_manager.js')}"></script> <script src="${static.url('js/src/tooltip_manager.js')}"></script>
<%static:js group='incourse_reverify'/> <%static:js group='incourse_reverify'/>
</%block> </%block>
......
...@@ -35,9 +35,7 @@ from verify_student.views import PayAndVerifyView ...@@ -35,9 +35,7 @@ from verify_student.views import PayAndVerifyView
% endfor % endfor
</%block> </%block>
<%block name="js_extra"> <%block name="js_extra">
<script src="${static.url('js/vendor/underscore-min.js')}"></script>
<script src="${static.url('js/vendor/underscore.string.min.js')}"></script> <script src="${static.url('js/vendor/underscore.string.min.js')}"></script>
<script src="${static.url('js/vendor/backbone-min.js')}"></script>
<script src="${static.url('js/src/tooltip_manager.js')}"></script> <script src="${static.url('js/src/tooltip_manager.js')}"></script>
<%static:js group='verify_student'/> <%static:js group='verify_student'/>
</%block> </%block>
......
...@@ -16,9 +16,7 @@ from django.utils.translation import ugettext as _ ...@@ -16,9 +16,7 @@ from django.utils.translation import ugettext as _
% endfor % endfor
</%block> </%block>
<%block name="js_extra"> <%block name="js_extra">
<script src="${static.url('js/vendor/underscore-min.js')}"></script>
<script src="${static.url('js/vendor/underscore.string.min.js')}"></script> <script src="${static.url('js/vendor/underscore.string.min.js')}"></script>
<script src="${static.url('js/vendor/backbone-min.js')}"></script>
<script src="${static.url('js/src/tooltip_manager.js')}"></script> <script src="${static.url('js/src/tooltip_manager.js')}"></script>
<%static:js group='reverify'/> <%static:js group='reverify'/>
</%block> </%block>
......
...@@ -137,7 +137,7 @@ js_info_dict = { ...@@ -137,7 +137,7 @@ js_info_dict = {
urlpatterns += ( urlpatterns += (
# Serve catalog of localized strings to be rendered by Javascript # Serve catalog of localized strings to be rendered by Javascript
url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), url(r'^i18n.js$', 'django.views.i18n.javascript_catalog', js_info_dict),
) )
# sysadmin dashboard, to see what courses are loaded, to delete & load courses # sysadmin dashboard, to see what courses are loaded, to delete & load courses
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment