From 92f706a642557c5f792e46d7748d7487f833c8d1 Mon Sep 17 00:00:00 2001 From: Chris Rodriguez Date: Mon, 13 Jun 2016 08:23:27 -0400 Subject: [PATCH 01/65] Bumping bok-choy to pick up a11y changes --- requirements/edx/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index dc1f991ce5..e3b660d551 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -142,7 +142,7 @@ django_debug_toolbar==1.3.2 # Used for testing before_after==0.1.3 -bok-choy==0.5.2 +bok-choy==0.5.3 chrono==1.0.2 coverage==4.0.2 ddt==0.8.0 From d20af4a2ba2389b408f0ffa40e6a88fe899abdab Mon Sep 17 00:00:00 2001 From: Greg Martin Date: Wed, 15 Jun 2016 11:47:38 -0400 Subject: [PATCH 02/65] Add VAL "Duplicate" status Added duplicate video failed status for VAL. --- cms/djangoapps/contentstore/views/videos.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cms/djangoapps/contentstore/views/videos.py b/cms/djangoapps/contentstore/views/videos.py index 0c047f8ba1..ec34567f9f 100644 --- a/cms/djangoapps/contentstore/views/videos.py +++ b/cms/djangoapps/contentstore/views/videos.py @@ -44,6 +44,9 @@ class StatusDisplayStrings(object): _COMPLETE = ugettext_noop("Ready") # Translators: This is the status for a video that the servers have failed to process _FAILED = ugettext_noop("Failed") + # Translators: This is the status for a video which has failed + # due to being flagged as a duplicate by an external or internal CMS + _DUPLICATE = ugettext_noop("Failed Duplicate") # Translators: This is the status for a video for which an invalid # processing token was provided in the course settings _INVALID_TOKEN = ugettext_noop("Invalid Token") @@ -61,6 +64,7 @@ class StatusDisplayStrings(object): "file_complete": _COMPLETE, "file_corrupt": _FAILED, "pipeline_error": _FAILED, + "duplicate": _DUPLICATE, "invalid_token": _INVALID_TOKEN, "imported": _IMPORTED, } @@ -311,9 +315,9 @@ def videos_post(course, request): edx_video_id = unicode(uuid4()) key = storage_service_key(bucket, file_name=edx_video_id) for metadata_name, value in [ - ("course_video_upload_token", course_video_upload_token), - ("client_video_id", file_name), - ("course_key", unicode(course.id)), + ("course_video_upload_token", course_video_upload_token), + ("client_video_id", file_name), + ("course_key", unicode(course.id)), ]: key.set_metadata(metadata_name, value) upload_url = key.generate_url( From cd7e79cdcb756ae26ab64a86d0c16ab5a77dee0a Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Thu, 16 Jun 2016 21:28:57 -0400 Subject: [PATCH 03/65] Use the latest version of the transifex client --- requirements/edx/base.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 8667ecf50d..87d5f5ecc9 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -129,7 +129,7 @@ sphinx_rtd_theme==0.1.5 # Used for Internationalization and localization Babel==1.3 -transifex-client==0.11b3 +transifex-client==0.12.1 # Ip network support for Embargo feature ipaddr==2.1.11 @@ -182,4 +182,4 @@ jsonfield==1.0.3 pynliner==0.5.2 # for sailthru integration -sailthru-client==2.2.3 \ No newline at end of file +sailthru-client==2.2.3 From 43ea4e21bb298bb3c58774a06acb99ac8de314ac Mon Sep 17 00:00:00 2001 From: Felipe Montoya Date: Thu, 16 Jun 2016 10:56:25 -0700 Subject: [PATCH 04/65] Converting views/tabs.coffee in the cms to js Linting the compiled file --- cms/static/coffee/src/views/tabs.coffee | 133 ---------------- cms/static/js/factories/edit_tabs.js | 2 +- cms/static/js/views/tabs.js | 203 ++++++++++++++++++++++++ common/djangoapps/terrain/ui_helpers.py | 2 +- 4 files changed, 205 insertions(+), 135 deletions(-) delete mode 100644 cms/static/coffee/src/views/tabs.coffee create mode 100644 cms/static/js/views/tabs.js diff --git a/cms/static/coffee/src/views/tabs.coffee b/cms/static/coffee/src/views/tabs.coffee deleted file mode 100644 index 9d00bd425a..0000000000 --- a/cms/static/coffee/src/views/tabs.coffee +++ /dev/null @@ -1,133 +0,0 @@ -define ["underscore", "jquery", "jquery.ui", "backbone", "common/js/components/views/feedback_prompt", - "common/js/components/views/feedback_notification", "coffee/src/views/module_edit", "js/models/module_info", "js/utils/module"], -(_, $, ui, Backbone, PromptView, NotificationView, ModuleEditView, ModuleModel, ModuleUtils) -> - class TabsEdit extends Backbone.View - - initialize: (options) => - @$('.component').each((idx, element) => - model = new ModuleModel({ - id: $(element).data('locator') - }) - - new ModuleEditView( - el: element, - onDelete: @deleteTab, - model: model - ) - ) - @options = _.extend({}, options) - @options.mast.find('.new-tab').on('click', @addNewTab) - $('.add-pages .new-tab').on('click', @addNewTab) - $('.toggle-checkbox').on('click', @toggleVisibilityOfTab) - @$('.course-nav-list').sortable( - handle: '.drag-handle' - update: @tabMoved - helper: 'clone' - opacity: '0.5' - placeholder: 'component-placeholder' - forcePlaceholderSize: true - axis: 'y' - items: '> .is-movable' - ) - - toggleVisibilityOfTab: (event, ui) => - checkbox_element = event.target - tab_element = $(checkbox_element).parents(".course-tab")[0] - - saving = new NotificationView.Mini({title: gettext("Saving")}) - saving.show() - - $.ajax({ - type:'POST', - url: @model.url(), - data: JSON.stringify({ - tab_id_locator : { - tab_id: $(tab_element).data('tab-id'), - tab_locator: $(tab_element).data('locator') - }, - is_hidden : $(checkbox_element).is(':checked') - }), - contentType: 'application/json' - }).success(=> saving.hide()) - - tabMoved: (event, ui) => - tabs = [] - @$('.course-tab').each((idx, element) => - tabs.push( - { - tab_id: $(element).data('tab-id'), - tab_locator: $(element).data('locator') - } - ) - ) - - analytics.track "Reordered Pages", - course: course_location_analytics - - saving = new NotificationView.Mini({title: gettext("Saving")}) - saving.show() - - $.ajax({ - type:'POST', - url: @model.url(), - data: JSON.stringify({ - tabs : tabs - }), - contentType: 'application/json' - }).success(=> saving.hide()) - - addNewTab: (event) => - event.preventDefault() - - editor = new ModuleEditView( - onDelete: @deleteTab - model: new ModuleModel() - ) - - $('.new-component-item').before(editor.$el) - editor.$el.addClass('course-tab is-movable') - editor.$el.addClass('new') - setTimeout(=> - editor.$el.removeClass('new') - , 1000) - $('html, body').animate {scrollTop: $('.new-component-item').offset().top}, 500 - - - editor.createItem( - @model.get('id'), - {category: 'static_tab'} - ) - - analytics.track "Added Page", - course: course_location_analytics - - deleteTab: (event) => - confirm = new PromptView.Warning - title: gettext('Delete Page Confirmation') - message: gettext('Are you sure you want to delete this page? This action cannot be undone.') - actions: - primary: - text: gettext("OK") - click: (view) -> - view.hide() - $component = $(event.currentTarget).parents('.component') - - analytics.track "Deleted Page", - course: course_location_analytics - id: $component.data('locator') - deleting = new NotificationView.Mini - title: gettext('Deleting') - deleting.show() - $.ajax({ - type: 'DELETE', - url: ModuleUtils.getUpdateUrl($component.data('locator')) - }).success(=> - $component.remove() - deleting.hide() - ) - secondary: [ - text: gettext('Cancel') - click: (view) -> - view.hide() - ] - confirm.show() diff --git a/cms/static/js/factories/edit_tabs.js b/cms/static/js/factories/edit_tabs.js index 34ad04d12a..71ba0f42b6 100644 --- a/cms/static/js/factories/edit_tabs.js +++ b/cms/static/js/factories/edit_tabs.js @@ -1,5 +1,5 @@ define([ - 'js/models/explicit_url', 'coffee/src/views/tabs', 'xmodule', 'coffee/src/main', 'xblock/cms.runtime.v1' + 'js/models/explicit_url', 'js/views/tabs', 'xmodule', 'coffee/src/main', 'xblock/cms.runtime.v1' ], function (TabsModel, TabsEditView, xmoduleLoader) { 'use strict'; return function (courseLocation, explicitUrl) { diff --git a/cms/static/js/views/tabs.js b/cms/static/js/views/tabs.js new file mode 100644 index 0000000000..9f83edeb19 --- /dev/null +++ b/cms/static/js/views/tabs.js @@ -0,0 +1,203 @@ +(function(analytics, course_location_analytics) { + 'use strict'; + + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { + var key; + for (key in parent) { + if (__hasProp.call(parent, key)) { + child[key] = parent[key]; + } + } + function Ctor() { + this.constructor = child; + } + Ctor.prototype = parent.prototype; + child.prototype = new Ctor(); + child.__super__ = parent.prototype; + return child; + }; + + define(['underscore', 'jquery', 'jquery.ui', 'backbone', 'common/js/components/views/feedback_prompt', + 'common/js/components/views/feedback_notification', 'coffee/src/views/module_edit', + 'js/models/module_info', 'js/utils/module'], + function(_, $, ui, Backbone, PromptView, NotificationView, ModuleEditView, ModuleModel, ModuleUtils) { + var TabsEdit; + TabsEdit = (function(_super) { + + __extends(TabsEdit, _super); + + function TabsEdit() { + var self = this; + this.deleteTab = function() { + return TabsEdit.prototype.deleteTab.apply(self, arguments); + }; + this.addNewTab = function() { + return TabsEdit.prototype.addNewTab.apply(self, arguments); + }; + this.tabMoved = function() { + return TabsEdit.prototype.tabMoved.apply(self, arguments); + }; + this.toggleVisibilityOfTab = function() { + return TabsEdit.prototype.toggleVisibilityOfTab.apply(self, arguments); + }; + this.initialize = function() { + return TabsEdit.prototype.initialize.apply(self, arguments); + }; + return TabsEdit.__super__.constructor.apply(this, arguments); + } + + TabsEdit.prototype.initialize = function(options) { + var self = this; + this.$('.component').each(function(idx, element) { + var model; + model = new ModuleModel({ + id: $(element).data('locator') + }); + return new ModuleEditView({ + el: element, + onDelete: self.deleteTab, + model: model + }); + }); + this.options = _.extend({}, options); + this.options.mast.find('.new-tab').on('click', this.addNewTab); + $('.add-pages .new-tab').on('click', this.addNewTab); + $('.toggle-checkbox').on('click', this.toggleVisibilityOfTab); + return this.$('.course-nav-list').sortable({ + handle: '.drag-handle', + update: this.tabMoved, + helper: 'clone', + opacity: '0.5', + placeholder: 'component-placeholder', + forcePlaceholderSize: true, + axis: 'y', + items: '> .is-movable' + }); + }; + + TabsEdit.prototype.toggleVisibilityOfTab = function(event) { + var checkbox_element, saving, tab_element; + checkbox_element = event.target; + tab_element = $(checkbox_element).parents('.course-tab')[0]; + saving = new NotificationView.Mini({ + title: gettext('Saving') + }); + saving.show(); + return $.ajax({ + type: 'POST', + url: this.model.url(), + data: JSON.stringify({ + tab_id_locator: { + tab_id: $(tab_element).data('tab-id'), + tab_locator: $(tab_element).data('locator') + }, + is_hidden: $(checkbox_element).is(':checked') + }), + contentType: 'application/json' + }).success(function() { + return saving.hide(); + }); + }; + + TabsEdit.prototype.tabMoved = function() { + var saving, tabs; + tabs = []; + this.$('.course-tab').each(function(idx, element) { + return tabs.push({ + tab_id: $(element).data('tab-id'), + tab_locator: $(element).data('locator') + }); + }); + analytics.track('Reordered Pages', { + course: course_location_analytics + }); + saving = new NotificationView.Mini({ + title: gettext('Saving') + }); + saving.show(); + return $.ajax({ + type: 'POST', + url: this.model.url(), + data: JSON.stringify({ + tabs: tabs + }), + contentType: 'application/json' + }).success(function() { + return saving.hide(); + }); + }; + + TabsEdit.prototype.addNewTab = function(event) { + var editor; + event.preventDefault(); + editor = new ModuleEditView({ + onDelete: this.deleteTab, + model: new ModuleModel() + }); + $('.new-component-item').before(editor.$el); + editor.$el.addClass('course-tab is-movable'); + editor.$el.addClass('new'); + setTimeout(function() { + return editor.$el.removeClass('new'); + }, 1000); + $('html, body').animate({ + scrollTop: $('.new-component-item').offset().top + }, 500); + editor.createItem(this.model.get('id'), { + category: 'static_tab' + }); + return analytics.track('Added Page', { + course: course_location_analytics + }); + }; + + TabsEdit.prototype.deleteTab = function(event) { + var confirm; + confirm = new PromptView.Warning({ + title: gettext('Delete Page Confirmation'), + message: gettext('Are you sure you want to delete this page? This action cannot be undone.'), + actions: { + primary: { + text: gettext('OK'), + click: function(view) { + var $component, deleting; + view.hide(); + $component = $(event.currentTarget).parents('.component'); + analytics.track('Deleted Page', { + course: course_location_analytics, + id: $component.data('locator') + }); + deleting = new NotificationView.Mini({ + title: gettext('Deleting') + }); + deleting.show(); + return $.ajax({ + type: 'DELETE', + url: ModuleUtils.getUpdateUrl($component.data('locator')) + }).success(function() { + $component.remove(); + return deleting.hide(); + }); + } + }, + secondary: [ + { + text: gettext('Cancel'), + click: function(view) { + return view.hide(); + } + } + ] + } + }); + return confirm.show(); + }; + + return TabsEdit; + + })(Backbone.View); + return TabsEdit; + }); + +}).call(this, analytics, course_location_analytics); //jshint ignore:line diff --git a/common/djangoapps/terrain/ui_helpers.py b/common/djangoapps/terrain/ui_helpers.py index 749a68e122..905b84f096 100644 --- a/common/djangoapps/terrain/ui_helpers.py +++ b/common/djangoapps/terrain/ui_helpers.py @@ -59,7 +59,7 @@ REQUIREJS_WAIT = { # Pages re.compile(r'^Pages \|'): [ - 'js/models/explicit_url', 'coffee/src/views/tabs', + 'js/models/explicit_url', 'js/views/tabs', 'xmodule', 'coffee/src/main', 'xblock/cms.runtime.v1' ], } From 603546a04a070387dcdd5c07ba3e8f0e43d81cf1 Mon Sep 17 00:00:00 2001 From: Ibrahim Date: Fri, 17 Jun 2016 16:26:08 +0500 Subject: [PATCH 05/65] replace references to settings.PLATFORM_NAME in edx-platform with theme overrides --- common/djangoapps/third_party_auth/models.py | 3 ++- lms/djangoapps/bulk_email/tasks.py | 2 +- lms/djangoapps/course_wiki/views.py | 4 +++- lms/djangoapps/courseware/views/views.py | 6 +++--- lms/djangoapps/instructor/views/api.py | 2 +- lms/djangoapps/shoppingcart/models.py | 10 ++++++---- lms/djangoapps/verify_student/views.py | 8 ++++---- openedx/core/djangoapps/api_admin/models.py | 3 ++- openedx/core/djangoapps/api_admin/widgets.py | 3 ++- openedx/core/djangoapps/credit/email_utils.py | 2 +- openedx/core/djangoapps/user_api/views.py | 2 +- 11 files changed, 26 insertions(+), 19 deletions(-) diff --git a/common/djangoapps/third_party_auth/models.py b/common/djangoapps/third_party_auth/models.py index ce76ef20c5..5bd8f22200 100644 --- a/common/djangoapps/third_party_auth/models.py +++ b/common/djangoapps/third_party_auth/models.py @@ -21,6 +21,7 @@ from social.backends.saml import SAMLAuth, SAMLIdentityProvider from .lti import LTIAuthBackend, LTI_PARAMS_KEY from social.exceptions import SocialAuthBaseException from social.utils import module_member +from openedx.core.djangoapps.theming.helpers import get_value as get_themed_value log = logging.getLogger(__name__) @@ -453,7 +454,7 @@ class SAMLConfiguration(ConfigurationModel): other_config = json.loads(self.other_config_str) if name in ("TECHNICAL_CONTACT", "SUPPORT_CONTACT"): contact = { - "givenName": "{} Support".format(settings.PLATFORM_NAME), + "givenName": "{} Support".format(get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME)), "emailAddress": settings.TECH_SUPPORT_EMAIL } contact.update(other_config.get(name, {})) diff --git a/lms/djangoapps/bulk_email/tasks.py b/lms/djangoapps/bulk_email/tasks.py index 3fd044fd94..a7947a6f6b 100644 --- a/lms/djangoapps/bulk_email/tasks.py +++ b/lms/djangoapps/bulk_email/tasks.py @@ -116,7 +116,7 @@ def _get_course_email_context(course): 'course_end_date': course_end_date, 'account_settings_url': 'https://{}{}'.format(settings.SITE_NAME, reverse('account_settings')), 'email_settings_url': 'https://{}{}'.format(settings.SITE_NAME, reverse('dashboard')), - 'platform_name': settings.PLATFORM_NAME, + 'platform_name': theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME), } return email_context diff --git a/lms/djangoapps/course_wiki/views.py b/lms/djangoapps/course_wiki/views.py index 92372e828e..f1681a4e7f 100644 --- a/lms/djangoapps/course_wiki/views.py +++ b/lms/djangoapps/course_wiki/views.py @@ -17,6 +17,7 @@ from wiki.models import URLPath, Article from courseware.courses import get_course_by_id from course_wiki.utils import course_wiki_slug from opaque_keys.edx.locations import SlashSeparatedCourseKey +from openedx.core.djangoapps.theming.helpers import get_value as get_themed_value log = logging.getLogger(__name__) @@ -128,7 +129,8 @@ def get_or_create_root(): pass starting_content = "\n".join(( - _("Welcome to the {platform_name} Wiki").format(platform_name=settings.PLATFORM_NAME), + _("Welcome to the {platform_name} Wiki").format(platform_name=get_themed_value('PLATFORM_NAME', + settings.PLATFORM_NAME)), "===", _("Visit a course wiki to add an article."), )) diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 698f49c1d6..565dbe4617 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -1090,7 +1090,7 @@ def generate_user_cert(request, course_id): log.info(u"Anon user trying to generate certificate for %s", course_id) return HttpResponseBadRequest( _('You must be signed in to {platform_name} to create a certificate.').format( - platform_name=settings.PLATFORM_NAME + platform_name=theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME) ) ) @@ -1206,7 +1206,7 @@ FINANCIAL_ASSISTANCE_HEADER = _( ' financial assistance program.' ).format( percent_sign="%", - platform_name=settings.PLATFORM_NAME + platform_name=theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME) ).split('\n') @@ -1326,7 +1326,7 @@ def financial_assistance_form(request): 'student_faq_url': marketing_link('FAQ'), 'dashboard_url': reverse('dashboard'), 'account_settings_url': reverse('account_settings'), - 'platform_name': settings.PLATFORM_NAME, + 'platform_name': theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME), 'user_details': { 'email': user.email, 'username': user.username, diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index d709d342eb..9f3b8ea674 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -215,7 +215,7 @@ def require_global_staff(func): else: return HttpResponseForbidden( u"Must be {platform_name} staff to perform this action.".format( - platform_name=settings.PLATFORM_NAME + platform_name=theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME) ) ) return wrapped diff --git a/lms/djangoapps/shoppingcart/models.py b/lms/djangoapps/shoppingcart/models.py index 173fd5b96f..2f000babc7 100644 --- a/lms/djangoapps/shoppingcart/models.py +++ b/lms/djangoapps/shoppingcart/models.py @@ -33,6 +33,7 @@ from django.core.mail.message import EmailMessage from xmodule.modulestore.django import modulestore from eventtracking import tracker +from openedx.core.djangoapps.theming.helpers import get_value as get_themed_value from courseware.courses import get_course_by_id from config_models.models import ConfigurationModel from course_modes.models import CourseMode @@ -2185,7 +2186,7 @@ class Donation(OrderItem): u"We greatly appreciate this generous contribution and your support of the {platform_name} mission. " u"This receipt was prepared to support charitable contributions for tax purposes. " u"We confirm that neither goods nor services were provided in exchange for this gift." - ).format(platform_name=settings.PLATFORM_NAME) + ).format(platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME)) @classmethod def _line_item_description(cls, course_id=None): @@ -2218,7 +2219,8 @@ class Donation(OrderItem): # The donation is for the organization as a whole, not a specific course else: - return _(u"Donation for {platform_name}").format(platform_name=settings.PLATFORM_NAME) + return _(u"Donation for {platform_name}").format(platform_name=get_themed_value('PLATFORM_NAME', + settings.PLATFORM_NAME)) @property def single_item_receipt_context(self): @@ -2243,8 +2245,8 @@ class Donation(OrderItem): data['name'] = unicode(self.course_id) data['category'] = unicode(self.course_id.org) else: - data['name'] = settings.PLATFORM_NAME - data['category'] = settings.PLATFORM_NAME + data['name'] = get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME) + data['category'] = get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME) return data @property diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index 21715ba979..a58e89f6ee 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -419,7 +419,7 @@ class PayAndVerifyView(View): 'display_steps': display_steps, 'is_active': json.dumps(request.user.is_active), 'message_key': message, - 'platform_name': settings.PLATFORM_NAME, + 'platform_name': theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME), 'processors': processors, 'requirements': requirements, 'user_full_name': full_name, @@ -1184,7 +1184,7 @@ def _compose_message_reverification_email( context["verification_open"] = verification_open context["due_date"] = get_default_time_display(reverification_block.due) - context['platform_name'] = settings.PLATFORM_NAME + context['platform_name'] = theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME) context["used_attempts"] = used_attempts context["allowed_attempts"] = allowed_attempts context["support_link"] = microsite.get_value('email_from_address', settings.CONTACT_EMAIL) @@ -1384,7 +1384,7 @@ class ReverifyView(View): if status in ["none", "must_reverify", "expired", "pending"]: context = { "user_full_name": request.user.profile.name, - "platform_name": settings.PLATFORM_NAME, + "platform_name": theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME), "capture_sound": staticfiles_storage.url("audio/camera_capture.wav"), } return render_to_response("verify_student/reverify.html", context) @@ -1449,7 +1449,7 @@ class InCourseReverifyView(View): 'course_key': unicode(course_key), 'course_name': course.display_name_with_default_escaped, 'checkpoint_name': checkpoint.checkpoint_name, - 'platform_name': settings.PLATFORM_NAME, + 'platform_name': theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME), 'usage_id': usage_id, 'capture_sound': staticfiles_storage.url("audio/camera_capture.wav"), } diff --git a/openedx/core/djangoapps/api_admin/models.py b/openedx/core/djangoapps/api_admin/models.py index eb5c2600e4..57c16338d4 100644 --- a/openedx/core/djangoapps/api_admin/models.py +++ b/openedx/core/djangoapps/api_admin/models.py @@ -17,6 +17,7 @@ from edxmako.shortcuts import render_to_string from simple_history.models import HistoricalRecords from config_models.models import ConfigurationModel +from openedx.core.djangoapps.theming.helpers import get_value as get_themed_value log = logging.getLogger(__name__) @@ -161,7 +162,7 @@ def _send_decision_email(instance): 'authentication_docs_url': settings.AUTH_DOCUMENTATION_URL, 'api_docs_url': settings.API_DOCUMENTATION_URL, 'support_email_address': settings.API_ACCESS_FROM_EMAIL, - 'platform_name': settings.PLATFORM_NAME + 'platform_name': get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME) } message = render_to_string( diff --git a/openedx/core/djangoapps/api_admin/widgets.py b/openedx/core/djangoapps/api_admin/widgets.py index 0b1e5f4600..f51800f09b 100644 --- a/openedx/core/djangoapps/api_admin/widgets.py +++ b/openedx/core/djangoapps/api_admin/widgets.py @@ -7,6 +7,7 @@ from django.forms.widgets import CheckboxInput from django.utils.encoding import force_text from django.utils.html import format_html from django.utils.translation import ugettext as _ +from openedx.core.djangoapps.theming.helpers import get_value as get_themed_value class TermsOfServiceCheckboxInput(CheckboxInput): @@ -23,7 +24,7 @@ class TermsOfServiceCheckboxInput(CheckboxInput): # Translators: link_start and link_end are HTML tags for a link to the terms of service. # platform_name is the name of this Open edX installation. label = _('I, and my company, accept the {link_start}{platform_name} API Terms of Service{link_end}.').format( - platform_name=settings.PLATFORM_NAME, + platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME), link_start=''.format(url=reverse('api_admin:api-tos')), link_end='', ) diff --git a/openedx/core/djangoapps/credit/email_utils.py b/openedx/core/djangoapps/credit/email_utils.py index 263cee2fce..3cdef8955c 100644 --- a/openedx/core/djangoapps/credit/email_utils.py +++ b/openedx/core/djangoapps/credit/email_utils.py @@ -73,7 +73,7 @@ def send_credit_notifications(username, course_key): providers_string = make_providers_strings(providers_names) context = { 'full_name': user.get_full_name(), - 'platform_name': settings.PLATFORM_NAME, + 'platform_name': theming_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME), 'course_name': course_display_name, 'branded_logo': logo_image_id, 'dashboard_link': dashboard_link, diff --git a/openedx/core/djangoapps/user_api/views.py b/openedx/core/djangoapps/user_api/views.py index 38cfde0ab6..1328863772 100644 --- a/openedx/core/djangoapps/user_api/views.py +++ b/openedx/core/djangoapps/user_api/views.py @@ -586,7 +586,7 @@ class RegistrationView(APIView): # Translators: This phrase appears above a field on the registration form # meant to hold the user's reasons for registering with edX. goals_label = _(u"Tell us why you're interested in {platform_name}").format( - platform_name=settings.PLATFORM_NAME + platform_name=get_themed_value("PLATFORM_NAME", settings.PLATFORM_NAME) ) form_desc.add_field( From fe5e5507c9f94a228aa5fc613db01f0261fd1f7d Mon Sep 17 00:00:00 2001 From: Chris Rodriguez Date: Tue, 14 Jun 2016 15:35:57 -0400 Subject: [PATCH 06/65] Bumping version of a11y custom ruleset --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5588cd19ae..1a560a8208 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "underscore.string": "~3.3.4" }, "devDependencies": { - "edx-custom-a11y-rules": "0.1.1", + "edx-custom-a11y-rules": "0.1.2", "pa11y": "3.6.0", "pa11y-reporter-1.0-json": "1.0.2", "jasmine-core": "^2.4.1", From fff88151d2db23480b674461e9bd844d31af2bf6 Mon Sep 17 00:00:00 2001 From: Andy Armstrong Date: Thu, 16 Jun 2016 10:53:16 -0700 Subject: [PATCH 07/65] Convert XBlock runtime code to JavaScript --- .jshintignore | 2 + cms/static/cms/js/build.js | 10 +- cms/static/cms/js/require-config.js | 431 +++++++++--------- cms/static/cms/js/spec/main.js | 299 ++++++++++++ cms/static/cms/js/spec/main_squire.js | 218 +++++++++ .../js/spec/xblock/cms.runtime.v1_spec.js | 25 +- cms/static/cms/js/xblock/cms.runtime.v1.js | 188 ++++++++ cms/static/coffee/spec/main.coffee | 299 ------------ cms/static/coffee/spec/main_squire.coffee | 218 --------- .../coffee/src/xblock/cms.runtime.v1.coffee | 96 ---- cms/static/karma_cms.conf.js | 6 +- cms/static/karma_cms_squire.conf.js | 2 +- .../coffee/spec/xblock/core_spec.coffee | 96 ---- .../coffee/spec/xblock/runtime.v1_spec.coffee | 21 - .../coffee/src/xblock/runtime.v1.coffee | 14 - common/static/common/js/karma.common.conf.js | 3 +- .../static/common/js/spec/xblock/core_spec.js | 111 +++++ .../common/js/spec/xblock/runtime.v1_spec.js | 28 ++ common/static/{ => common}/js/xblock/core.js | 50 +- common/static/common/js/xblock/runtime.v1.js | 50 ++ common/static/karma_common.conf.js | 15 +- lms/envs/common.py | 26 +- .../coffee/src/xblock/lms.runtime.v1.coffee | 18 - lms/static/karma_lms_coffee.conf.js | 3 +- lms/static/lms/js/require-config.js | 283 ++++++------ lms/static/lms/js/spec/main.js | 5 +- lms/static/lms/js/xblock/lms.runtime.v1.js | 55 +++ 27 files changed, 1387 insertions(+), 1185 deletions(-) create mode 100644 cms/static/cms/js/spec/main.js create mode 100644 cms/static/cms/js/spec/main_squire.js rename cms/static/{ => cms}/js/spec/xblock/cms.runtime.v1_spec.js (79%) create mode 100644 cms/static/cms/js/xblock/cms.runtime.v1.js delete mode 100644 cms/static/coffee/spec/main.coffee delete mode 100644 cms/static/coffee/spec/main_squire.coffee delete mode 100644 cms/static/coffee/src/xblock/cms.runtime.v1.coffee delete mode 100644 common/static/coffee/spec/xblock/core_spec.coffee delete mode 100644 common/static/coffee/spec/xblock/runtime.v1_spec.coffee delete mode 100644 common/static/coffee/src/xblock/runtime.v1.coffee create mode 100644 common/static/common/js/spec/xblock/core_spec.js create mode 100644 common/static/common/js/spec/xblock/runtime.v1_spec.js rename common/static/{ => common}/js/xblock/core.js (78%) create mode 100644 common/static/common/js/xblock/runtime.v1.js delete mode 100644 lms/static/coffee/src/xblock/lms.runtime.v1.coffee create mode 100644 lms/static/lms/js/xblock/lms.runtime.v1.js diff --git a/.jshintignore b/.jshintignore index 26e4c15e1e..0065f2da20 100644 --- a/.jshintignore +++ b/.jshintignore @@ -1,4 +1,6 @@ **/vendor +cms/static/cms/js/build.js +cms/static/cms/js/spec/main.js cms/static/js/i18n/**/*.js lms/static/js/i18n/**/*.js lms/static/lms/js/build.js diff --git a/cms/static/cms/js/build.js b/cms/static/cms/js/build.js index 65e78c3e62..f6a3c1534c 100644 --- a/cms/static/cms/js/build.js +++ b/cms/static/cms/js/build.js @@ -1,8 +1,8 @@ -(function () { +(function() { 'use strict'; var commonLibrariesPath = 'common/js/common_libraries'; - var getModule = function (moduleName, excludeCommonDeps) { + var getModule = function(moduleName, excludeCommonDeps) { var module = { name: moduleName }; @@ -14,7 +14,7 @@ return module; }; - var getModulesList = function (modules) { + var getModulesList = function(modules) { var result = [getModule(commonLibrariesPath)]; return result.concat(modules.map(function (moduleName) { return getModule(moduleName, true); @@ -92,7 +92,7 @@ /** * Stub out requireJS text in the optimized file, but leave available for non-optimized development use. */ - stubModules: ["text"], + stubModules: ['text'], /** * If shim config is used in the app during runtime, duplicate the config @@ -170,4 +170,4 @@ */ logLevel: 1 }; -} ()) +}()) diff --git a/cms/static/cms/js/require-config.js b/cms/static/cms/js/require-config.js index 70e8d61e0b..7cd1f1caf1 100644 --- a/cms/static/cms/js/require-config.js +++ b/cms/static/cms/js/require-config.js @@ -1,5 +1,6 @@ -;(function (require, define) { +;(function(require, define) { 'use strict'; + if (window) { // MathJax Fast Preview was introduced in 2.5. However, it // causes undesirable flashing/font size changes when @@ -16,300 +17,300 @@ // needs to be served. To handle this, we load the correct file in the // rendered template and then use this to ensure that RequireJS knows // how to find it. - define("gettext", function () { return window.gettext; }); + define('gettext', function() { return window.gettext; }); } require.config({ // NOTE: baseUrl has been previously set in cms/static/templates/base.html waitSeconds: 60, paths: { - "domReady": "js/vendor/domReady", - "mustache": "js/vendor/mustache", - "codemirror": "js/vendor/codemirror-compressed", - "codemirror/stex": "js/vendor/CodeMirror/stex", - "jquery": "common/js/vendor/jquery", - "jquery-migrate": "common/js/vendor/jquery-migrate", - "jquery.ui": "js/vendor/jquery-ui.min", - "jquery.form": "js/vendor/jquery.form", - "jquery.markitup": "js/vendor/markitup/jquery.markitup", - "jquery.leanModal": "js/vendor/jquery.leanModal", - "jquery.ajaxQueue": "js/vendor/jquery.ajaxQueue", - "jquery.smoothScroll": "js/vendor/jquery.smooth-scroll.min", - "jquery.timepicker": "js/vendor/timepicker/jquery.timepicker", - "jquery.cookie": "js/vendor/jquery.cookie", - "jquery.qtip": "js/vendor/jquery.qtip.min", - "jquery.scrollTo": "common/js/vendor/jquery.scrollTo", - "jquery.flot": "js/vendor/flot/jquery.flot.min", - "jquery.fileupload": "js/vendor/jQuery-File-Upload/js/jquery.fileupload", - "jquery.fileupload-process": "js/vendor/jQuery-File-Upload/js/jquery.fileupload-process", - "jquery.fileupload-validate": "js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate", - "jquery.iframe-transport": "js/vendor/jQuery-File-Upload/js/jquery.iframe-transport", - "jquery.inputnumber": "js/vendor/html5-input-polyfills/number-polyfill", - "jquery.immediateDescendents": "coffee/src/jquery.immediateDescendents", - "datepair": "js/vendor/timepicker/datepair", - "date": "js/vendor/date", - "moment": "js/vendor/moment.min", - "moment-with-locales": "js/vendor/moment-with-locales.min", - "text": 'js/vendor/requirejs/text', - "underscore": "common/js/vendor/underscore", - "underscore.string": "common/js/vendor/underscore.string", - "backbone": "common/js/vendor/backbone", - "backbone-relational" : "js/vendor/backbone-relational.min", - "backbone.associations": "js/vendor/backbone-associations-min", - "backbone.paginator": "common/js/vendor/backbone.paginator", - "tinymce": "js/vendor/tinymce/js/tinymce/tinymce.full.min", - "jquery.tinymce": "js/vendor/tinymce/js/tinymce/jquery.tinymce.min", - "xmodule": "/xmodule/xmodule", - "xblock/core": "js/xblock/core", - "xblock": "coffee/src/xblock", - "utility": "js/src/utility", - "accessibility": "js/src/accessibility_tools", - "URI": "js/vendor/URI.min", - "ieshim": "js/src/ie_shim", - "tooltip_manager": "js/src/tooltip_manager", - "modernizr": "edx-pattern-library/js/modernizr-custom", - "afontgarde": "edx-pattern-library/js/afontgarde", - "edxicons": "edx-pattern-library/js/edx-icons", - "draggabilly": "js/vendor/draggabilly", + 'domReady': 'js/vendor/domReady', + 'mustache': 'js/vendor/mustache', + 'codemirror': 'js/vendor/codemirror-compressed', + 'codemirror/stex': 'js/vendor/CodeMirror/stex', + 'jquery': 'common/js/vendor/jquery', + 'jquery-migrate': 'common/js/vendor/jquery-migrate', + 'jquery.ui': 'js/vendor/jquery-ui.min', + 'jquery.form': 'js/vendor/jquery.form', + 'jquery.markitup': 'js/vendor/markitup/jquery.markitup', + 'jquery.leanModal': 'js/vendor/jquery.leanModal', + 'jquery.ajaxQueue': 'js/vendor/jquery.ajaxQueue', + 'jquery.smoothScroll': 'js/vendor/jquery.smooth-scroll.min', + 'jquery.timepicker': 'js/vendor/timepicker/jquery.timepicker', + 'jquery.cookie': 'js/vendor/jquery.cookie', + 'jquery.qtip': 'js/vendor/jquery.qtip.min', + 'jquery.scrollTo': 'common/js/vendor/jquery.scrollTo', + 'jquery.flot': 'js/vendor/flot/jquery.flot.min', + 'jquery.fileupload': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload', + 'jquery.fileupload-process': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload-process', + 'jquery.fileupload-validate': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate', + 'jquery.iframe-transport': 'js/vendor/jQuery-File-Upload/js/jquery.iframe-transport', + 'jquery.inputnumber': 'js/vendor/html5-input-polyfills/number-polyfill', + 'jquery.immediateDescendents': 'coffee/src/jquery.immediateDescendents', + 'datepair': 'js/vendor/timepicker/datepair', + 'date': 'js/vendor/date', + 'moment': 'js/vendor/moment.min', + 'moment-with-locales': 'js/vendor/moment-with-locales.min', + 'text': 'js/vendor/requirejs/text', + 'underscore': 'common/js/vendor/underscore', + 'underscore.string': 'common/js/vendor/underscore.string', + 'backbone': 'common/js/vendor/backbone', + 'backbone-relational': 'js/vendor/backbone-relational.min', + 'backbone.associations': 'js/vendor/backbone-associations-min', + 'backbone.paginator': 'common/js/vendor/backbone.paginator', + 'tinymce': 'js/vendor/tinymce/js/tinymce/tinymce.full.min', + 'jquery.tinymce': 'js/vendor/tinymce/js/tinymce/jquery.tinymce.min', + 'xmodule': '/xmodule/xmodule', + 'xblock/cms.runtime.v1': 'cms/js/xblock/cms.runtime.v1', + 'xblock': 'common/js/xblock', + 'utility': 'js/src/utility', + 'accessibility': 'js/src/accessibility_tools', + 'URI': 'js/vendor/URI.min', + 'ieshim': 'js/src/ie_shim', + 'tooltip_manager': 'js/src/tooltip_manager', + 'modernizr': 'edx-pattern-library/js/modernizr-custom', + 'afontgarde': 'edx-pattern-library/js/afontgarde', + 'edxicons': 'edx-pattern-library/js/edx-icons', + 'draggabilly': 'js/vendor/draggabilly', // Files needed for Annotations feature - "annotator": "js/vendor/ova/annotator-full", - "annotator-harvardx": "js/vendor/ova/annotator-full-firebase-auth", - "video.dev": "js/vendor/ova/video.dev", - "vjs.youtube": 'js/vendor/ova/vjs.youtube', - "rangeslider": 'js/vendor/ova/rangeslider', - "share-annotator": 'js/vendor/ova/share-annotator', - "richText-annotator": 'js/vendor/ova/richText-annotator', - "reply-annotator": 'js/vendor/ova/reply-annotator', - "grouping-annotator": 'js/vendor/ova/grouping-annotator', - "tags-annotator": 'js/vendor/ova/tags-annotator', - "diacritic-annotator": 'js/vendor/ova/diacritic-annotator', - "flagging-annotator": 'js/vendor/ova/flagging-annotator', - "jquery-Watch": 'js/vendor/ova/jquery-Watch', - "openseadragon": 'js/vendor/ova/openseadragon', - "osda": 'js/vendor/ova/OpenSeaDragonAnnotation', - "ova": 'js/vendor/ova/ova', - "catch": 'js/vendor/ova/catch/js/catch', - "handlebars": 'js/vendor/ova/catch/js/handlebars-1.1.2', - "lang_edx": "js/src/lang_edx", + 'annotator': 'js/vendor/ova/annotator-full', + 'annotator-harvardx': 'js/vendor/ova/annotator-full-firebase-auth', + 'video.dev': 'js/vendor/ova/video.dev', + 'vjs.youtube': 'js/vendor/ova/vjs.youtube', + 'rangeslider': 'js/vendor/ova/rangeslider', + 'share-annotator': 'js/vendor/ova/share-annotator', + 'richText-annotator': 'js/vendor/ova/richText-annotator', + 'reply-annotator': 'js/vendor/ova/reply-annotator', + 'grouping-annotator': 'js/vendor/ova/grouping-annotator', + 'tags-annotator': 'js/vendor/ova/tags-annotator', + 'diacritic-annotator': 'js/vendor/ova/diacritic-annotator', + 'flagging-annotator': 'js/vendor/ova/flagging-annotator', + 'jquery-Watch': 'js/vendor/ova/jquery-Watch', + 'openseadragon': 'js/vendor/ova/openseadragon', + 'osda': 'js/vendor/ova/OpenSeaDragonAnnotation', + 'ova': 'js/vendor/ova/ova', + 'catch': 'js/vendor/ova/catch/js/catch', + 'handlebars': 'js/vendor/ova/catch/js/handlebars-1.1.2', + 'lang_edx': 'js/src/lang_edx', // end of Annotation tool files // externally hosted files - "mathjax": "//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured", // jshint ignore:line - "youtube": [ - // youtube URL does not end in ".js". We add "?noext" to the path so - // that require.js adds the ".js" to the query component of the URL, + 'mathjax': '//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // jshint ignore:line + 'youtube': [ + // youtube URL does not end in '.js'. We add '?noext' to the path so + // that require.js adds the '.js' to the query component of the URL, // and leaves the path component intact. - "//www.youtube.com/player_api?noext", + '//www.youtube.com/player_api?noext', // if youtube fails to load, fallback on a local file // so that require doesn't fall over - "js/src/youtube_fallback" + 'js/src/youtube_fallback' ] }, shim: { - "gettext": { - exports: "gettext" + 'gettext': { + exports: 'gettext' }, - "date": { - exports: "Date" + 'date': { + exports: 'Date' }, - "jquery-migrate": ['jquery'], - "jquery.ui": { - deps: ["jquery"], - exports: "jQuery.ui" + 'jquery-migrate': ['jquery'], + 'jquery.ui': { + deps: ['jquery'], + exports: 'jQuery.ui' }, - "jquery.form": { - deps: ["jquery"], - exports: "jQuery.fn.ajaxForm" + 'jquery.form': { + deps: ['jquery'], + exports: 'jQuery.fn.ajaxForm' }, - "jquery.markitup": { - deps: ["jquery"], - exports: "jQuery.fn.markitup" + 'jquery.markitup': { + deps: ['jquery'], + exports: 'jQuery.fn.markitup' }, - "jquery.leanmodal": { - deps: ["jquery"], - exports: "jQuery.fn.leanModal" + 'jquery.leanmodal': { + deps: ['jquery'], + exports: 'jQuery.fn.leanModal' }, - "jquery.ajaxQueue": { - deps: ["jquery"], - exports: "jQuery.fn.ajaxQueue" + 'jquery.ajaxQueue': { + deps: ['jquery'], + exports: 'jQuery.fn.ajaxQueue' }, - "jquery.smoothScroll": { - deps: ["jquery"], - exports: "jQuery.fn.smoothScroll" + 'jquery.smoothScroll': { + deps: ['jquery'], + exports: 'jQuery.fn.smoothScroll' }, - "jquery.cookie": { - deps: ["jquery"], - exports: "jQuery.fn.cookie" + 'jquery.cookie': { + deps: ['jquery'], + exports: 'jQuery.fn.cookie' }, - "jquery.qtip": { - deps: ["jquery"], - exports: "jQuery.fn.qtip" + 'jquery.qtip': { + deps: ['jquery'], + exports: 'jQuery.fn.qtip' }, - "jquery.scrollTo": { - deps: ["jquery"], - exports: "jQuery.fn.scrollTo" + 'jquery.scrollTo': { + deps: ['jquery'], + exports: 'jQuery.fn.scrollTo' }, - "jquery.flot": { - deps: ["jquery"], - exports: "jQuery.fn.plot" + 'jquery.flot': { + deps: ['jquery'], + exports: 'jQuery.fn.plot' }, - "jquery.fileupload": { - deps: ["jquery.ui", "jquery.iframe-transport"], - exports: "jQuery.fn.fileupload" + 'jquery.fileupload': { + deps: ['jquery.ui', 'jquery.iframe-transport'], + exports: 'jQuery.fn.fileupload' }, - "jquery.fileupload-process": { - deps: ["jquery.fileupload"] + 'jquery.fileupload-process': { + deps: ['jquery.fileupload'] }, - "jquery.fileupload-validate": { - deps: ["jquery.fileupload"] + 'jquery.fileupload-validate': { + deps: ['jquery.fileupload'] }, - "jquery.inputnumber": { - deps: ["jquery"], - exports: "jQuery.fn.inputNumber" + 'jquery.inputnumber': { + deps: ['jquery'], + exports: 'jQuery.fn.inputNumber' }, - "jquery.tinymce": { - deps: ["jquery", "tinymce"], - exports: "jQuery.fn.tinymce" + 'jquery.tinymce': { + deps: ['jquery', 'tinymce'], + exports: 'jQuery.fn.tinymce' }, - "datepair": { - deps: ["jquery.ui", "jquery.timepicker"] + 'datepair': { + deps: ['jquery.ui', 'jquery.timepicker'] }, - "underscore": { - exports: "_" + 'underscore': { + exports: '_' }, - "backbone": { - deps: ["underscore", "jquery"], - exports: "Backbone" + 'backbone': { + deps: ['underscore', 'jquery'], + exports: 'Backbone' }, - "backbone.associations": { - deps: ["backbone"], - exports: "Backbone.Associations" + 'backbone.associations': { + deps: ['backbone'], + exports: 'Backbone.Associations' }, - "backbone.paginator": { - deps: ["backbone"], - exports: "Backbone.PageableCollection" + 'backbone.paginator': { + deps: ['backbone'], + exports: 'Backbone.PageableCollection' }, - "youtube": { - exports: "YT" + 'youtube': { + exports: 'YT' }, - "codemirror": { - exports: "CodeMirror" + 'codemirror': { + exports: 'CodeMirror' }, - "codemirror/stex": { - deps: ["codemirror"] + 'codemirror/stex': { + deps: ['codemirror'] }, - "tinymce": { - exports: "tinymce" + 'tinymce': { + exports: 'tinymce' }, - "lang_edx": { - deps: ["jquery"] + 'lang_edx': { + deps: ['jquery'] }, - "mathjax": { - exports: "MathJax", + 'mathjax': { + exports: 'MathJax', init: function() { window.MathJax.Hub.Config({ tex2jax: { inlineMath: [ - ["\\(","\\)"], + ['\\(','\\)'], ['[mathjaxinline]','[/mathjaxinline]'] ], displayMath: [ - ["\\[","\\]"], + ['\\[','\\]'], ['[mathjax]','[/mathjax]'] ] } - }); - // In order to eliminate all flashing during interactive - // preview, it is necessary to set processSectionDelay to 0 - // (remove delay between input and output phases). This - // effectively disables fast preview, regardless of - // the fast preview setting as shown in the context menu. - window.MathJax.Hub.processSectionDelay = 0; - window.MathJax.Hub.Configured(); + }); + // In order to eliminate all flashing during interactive + // preview, it is necessary to set processSectionDelay to 0 + // (remove delay between input and output phases). This + // effectively disables fast preview, regardless of + // the fast preview setting as shown in the context menu. + window.MathJax.Hub.processSectionDelay = 0; + window.MathJax.Hub.Configured(); } }, - "URI": { - exports: "URI" + 'URI': { + exports: 'URI' }, - "tooltip_manager": { - deps: ["jquery", "underscore"] + 'tooltip_manager': { + deps: ['jquery', 'underscore'] }, - "jquery.immediateDescendents": { - deps: ["jquery"] + 'jquery.immediateDescendents': { + deps: ['jquery'] }, - "xblock/core": { - exports: "XBlock", - deps: ["jquery", "jquery.immediateDescendents"] + 'xblock/core': { + exports: 'XBlock', + deps: ['jquery', 'jquery.immediateDescendents'] }, - "xblock/runtime.v1": { - exports: "XBlock", - deps: ["xblock/core"] + 'xblock/runtime.v1': { + exports: 'XBlock', + deps: ['xblock/core'] }, - "coffee/src/main": { - deps: ["coffee/src/ajax_prefix"] + 'coffee/src/main': { + deps: ['coffee/src/ajax_prefix'] }, - "js/src/logger": { - exports: "Logger", - deps: ["coffee/src/ajax_prefix"] + 'js/src/logger': { + exports: 'Logger', + deps: ['coffee/src/ajax_prefix'] }, - "modernizr": { - exports: "Modernizr" + 'modernizr': { + exports: 'Modernizr' }, - "afontgarde": { - exports: "AFontGarde" + 'afontgarde': { + exports: 'AFontGarde' }, // the following are all needed for annotation tools - "video.dev": { - exports:"videojs" + 'video.dev': { + exports: 'videojs' }, - "vjs.youtube": { - deps: ["video.dev"] + 'vjs.youtube': { + deps: ['video.dev'] }, - "rangeslider": { - deps: ["video.dev"] + 'rangeslider': { + deps: ['video.dev'] }, - "annotator": { - exports: "Annotator" + 'annotator': { + exports: 'Annotator' }, - "annotator-harvardx":{ - deps: ["annotator"] + 'annotator-harvardx': { + deps: ['annotator'] }, - "share-annotator": { - deps: ["annotator"] + 'share-annotator': { + deps: ['annotator'] }, - "richText-annotator": { - deps: ["annotator", "tinymce"] + 'richText-annotator': { + deps: ['annotator', 'tinymce'] }, - "reply-annotator": { - deps: ["annotator"] + 'reply-annotator': { + deps: ['annotator'] }, - "tags-annotator": { - deps: ["annotator"] + 'tags-annotator': { + deps: ['annotator'] }, - "diacritic-annotator": { - deps: ["annotator"] + 'diacritic-annotator': { + deps: ['annotator'] }, - "flagging-annotator": { - deps: ["annotator"] + 'flagging-annotator': { + deps: ['annotator'] }, - "grouping-annotator": { - deps: ["annotator"] + 'grouping-annotator': { + deps: ['annotator'] }, - "ova":{ - exports: "ova", - deps: ["annotator", "annotator-harvardx", "video.dev", "vjs.youtube", - "rangeslider", "share-annotator", "richText-annotator", "reply-annotator", - "tags-annotator", "flagging-annotator", "grouping-annotator", "diacritic-annotator", - "jquery-Watch", "catch", "handlebars", "URI"] + 'ova': { + exports: 'ova', + deps: ['annotator', 'annotator-harvardx', 'video.dev', 'vjs.youtube', + 'rangeslider', 'share-annotator', 'richText-annotator', 'reply-annotator', + 'tags-annotator', 'flagging-annotator', 'grouping-annotator', 'diacritic-annotator', + 'jquery-Watch', 'catch', 'handlebars', 'URI'] }, - "osda":{ - exports: "osda", - deps: ["annotator", "annotator-harvardx", "video.dev", "vjs.youtube", - "rangeslider", "share-annotator", "richText-annotator", "reply-annotator", - "tags-annotator", "flagging-annotator", "grouping-annotator", "diacritic-annotator", - "openseadragon", "jquery-Watch", "catch", "handlebars", "URI"] + 'osda': { + exports: 'osda', + deps: ['annotator', 'annotator-harvardx', 'video.dev', 'vjs.youtube', + 'rangeslider', 'share-annotator', 'richText-annotator', 'reply-annotator', + 'tags-annotator', 'flagging-annotator', 'grouping-annotator', 'diacritic-annotator', + 'openseadragon', 'jquery-Watch', 'catch', 'handlebars', 'URI'] } // end of annotation tool files } diff --git a/cms/static/cms/js/spec/main.js b/cms/static/cms/js/spec/main.js new file mode 100644 index 0000000000..076c47376c --- /dev/null +++ b/cms/static/cms/js/spec/main.js @@ -0,0 +1,299 @@ +(function(requirejs, requireSerial) { + 'use strict'; + + var i, specHelpers, testFiles; + + requirejs.config({ + baseUrl: '/base/', + paths: { + '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', + 'jquery': 'xmodule_js/common_static/common/js/vendor/jquery', + 'jquery-migrate': 'xmodule_js/common_static/common/js/vendor/jquery-migrate', + 'jquery.ui': 'xmodule_js/common_static/js/vendor/jquery-ui.min', + 'jquery.form': 'xmodule_js/common_static/js/vendor/jquery.form', + 'jquery.markitup': 'xmodule_js/common_static/js/vendor/markitup/jquery.markitup', + 'jquery.leanModal': 'xmodule_js/common_static/js/vendor/jquery.leanModal', + 'jquery.ajaxQueue': 'xmodule_js/common_static/js/vendor/jquery.ajaxQueue', + 'jquery.smoothScroll': 'xmodule_js/common_static/js/vendor/jquery.smooth-scroll.min', + 'jquery.scrollTo': 'common/js/vendor/jquery.scrollTo', + 'jquery.timepicker': 'xmodule_js/common_static/js/vendor/timepicker/jquery.timepicker', + 'jquery.cookie': 'xmodule_js/common_static/js/vendor/jquery.cookie', + 'jquery.qtip': 'xmodule_js/common_static/js/vendor/jquery.qtip.min', + 'jquery.fileupload': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload', + 'jquery.fileupload-process': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process', // jshint ignore:line + 'jquery.fileupload-validate': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate', // jshint ignore:line + 'jquery.iframe-transport': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport', // jshint ignore:line + 'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill', + 'jquery.immediateDescendents': 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents', + 'jquery.simulate': 'xmodule_js/common_static/js/vendor/jquery.simulate', + 'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair', + 'date': 'xmodule_js/common_static/js/vendor/date', + 'moment': 'xmodule_js/common_static/js/vendor/moment.min', + 'moment-with-locales': 'xmodule_js/common_static/js/vendor/moment-with-locales.min', + 'text': 'xmodule_js/common_static/js/vendor/requirejs/text', + 'underscore': 'common/js/vendor/underscore', + 'underscore.string': 'common/js/vendor/underscore.string', + 'backbone': 'common/js/vendor/backbone', + 'backbone.associations': 'xmodule_js/common_static/js/vendor/backbone-associations-min', + 'backbone.paginator': 'common/js/vendor/backbone.paginator', + 'backbone-relational': 'xmodule_js/common_static/js/vendor/backbone-relational.min', + 'tinymce': 'xmodule_js/common_static/js/vendor/tinymce/js/tinymce/tinymce.full.min', + 'jquery.tinymce': 'xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce', + 'xmodule': 'xmodule_js/src/xmodule', + 'xblock/cms.runtime.v1': 'cms/js/xblock/cms.runtime.v1', + 'xblock': 'common/js/xblock', + 'utility': 'xmodule_js/common_static/js/src/utility', + 'accessibility': 'xmodule_js/common_static/js/src/accessibility_tools', + 'sinon': 'xmodule_js/common_static/js/vendor/sinon-1.17.0', + 'squire': 'xmodule_js/common_static/js/vendor/Squire', + 'jasmine-imagediff': 'xmodule_js/common_static/js/vendor/jasmine-imagediff', + 'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly', + 'domReady': 'xmodule_js/common_static/js/vendor/domReady', + 'URI': 'xmodule_js/common_static/js/vendor/URI.min', + 'mock-ajax': 'xmodule_js/common_static/js/vendor/mock-ajax', + 'modernizr': 'edx-pattern-library/js/modernizr-custom', + 'afontgarde': 'edx-pattern-library/js/afontgarde', + 'edxicons': 'edx-pattern-library/js/edx-icons', + 'mathjax': '//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // jshint ignore:line + 'youtube': '//www.youtube.com/player_api?noext', + 'coffee/src/ajax_prefix': 'xmodule_js/common_static/coffee/src/ajax_prefix', + 'js/spec/test_utils': 'js/spec/test_utils' + }, + shim: { + 'gettext': { + exports: 'gettext' + }, + 'date': { + exports: 'Date' + }, + 'jquery-migrate': ['jquery'], + 'jquery.ui': { + deps: ['jquery'], + exports: 'jQuery.ui' + }, + 'jquery.form': { + deps: ['jquery'], + exports: 'jQuery.fn.ajaxForm' + }, + 'jquery.markitup': { + deps: ['jquery'], + exports: 'jQuery.fn.markitup' + }, + 'jquery.leanModal': { + deps: ['jquery'], + exports: 'jQuery.fn.leanModal' + }, + 'jquery.smoothScroll': { + deps: ['jquery'], + exports: 'jQuery.fn.smoothScroll' + }, + 'jquery.ajaxQueue': { + deps: ['jquery'], + exports: 'jQuery.fn.ajaxQueue' + }, + 'jquery.scrollTo': { + deps: ['jquery'], + exports: 'jQuery.fn.scrollTo' + }, + 'jquery.cookie': { + deps: ['jquery'], + exports: 'jQuery.fn.cookie' + }, + 'jquery.qtip': { + deps: ['jquery'], + exports: 'jQuery.fn.qtip' + }, + 'jquery.fileupload': { + deps: ['jquery.ui', 'jquery.iframe-transport'], + exports: 'jQuery.fn.fileupload' + }, + 'jquery.fileupload-process': { + deps: ['jquery.fileupload'] + }, + 'jquery.fileupload-validate': { + deps: ['jquery.fileupload'] + }, + 'jquery.inputnumber': { + deps: ['jquery'], + exports: 'jQuery.fn.inputNumber' + }, + 'jquery.simulate': { + deps: ['jquery'], + exports: 'jQuery.fn.simulate' + }, + 'jquery.tinymce': { + deps: ['jquery', 'tinymce'], + exports: 'jQuery.fn.tinymce' + }, + 'datepair': { + deps: ['jquery.ui', 'jquery.timepicker'] + }, + 'underscore': { + exports: '_' + }, + 'backbone': { + deps: ['underscore', 'jquery'], + exports: 'Backbone' + }, + 'backbone.associations': { + deps: ['backbone'], + exports: 'Backbone.Associations' + }, + 'backbone.paginator': { + deps: ['backbone'], + exports: 'Backbone.PageableCollection' + }, + 'backbone-relational': { + deps: ['backbone'] + }, + 'youtube': { + exports: 'YT' + }, + 'codemirror': { + exports: 'CodeMirror' + }, + 'tinymce': { + exports: 'tinymce' + }, + 'mathjax': { + exports: 'MathJax', + init: function() { + window.MathJax.Hub.Config({ + tex2jax: { + inlineMath: [['\\(', '\\)'], ['[mathjaxinline]', '[/mathjaxinline]']], + displayMath: [['\\[', '\\]'], ['[mathjax]', '[/mathjax]']] + } + }); + return window.MathJax.Hub.Configured(); + } + }, + 'URI': { + exports: 'URI' + }, + 'xmodule': { + exports: 'XModule' + }, + 'sinon': { + exports: 'sinon' + }, + 'jasmine-imagediff': {}, + 'common/js/spec_helpers/jasmine-extensions': { + deps: ['jquery'] + }, + 'common/js/spec_helpers/jasmine-stealth': { + deps: ['underscore', 'underscore.string'] + }, + 'common/js/spec_helpers/jasmine-waituntil': { + deps: ['jquery'] + }, + 'xblock/core': { + exports: 'XBlock', + deps: ['jquery', 'jquery.immediateDescendents'] + }, + 'xblock/runtime.v1': { + exports: 'XBlock', + deps: ['xblock/core'] + }, + 'mock-ajax': { + deps: ['jquery'] + }, + 'coffee/src/main': { + deps: ['coffee/src/ajax_prefix'] + }, + 'coffee/src/ajax_prefix': { + deps: ['jquery'] + }, + 'modernizr': { + exports: 'Modernizr' + }, + 'afontgarde': { + exports: 'AFontGarde' + } + } + }); + + jasmine.getFixtures().fixturesPath += 'coffee/fixtures'; + + testFiles = [ + 'cms/js/spec/xblock/cms.runtime.v1_spec', + 'coffee/spec/main_spec', + 'coffee/spec/models/course_spec', + 'coffee/spec/models/metadata_spec', + 'coffee/spec/models/section_spec', + 'coffee/spec/models/settings_course_grader_spec', + 'coffee/spec/models/settings_grading_spec', + 'coffee/spec/models/textbook_spec', + 'coffee/spec/models/upload_spec', + 'coffee/spec/views/course_info_spec', + 'coffee/spec/views/metadata_edit_spec', + 'coffee/spec/views/module_edit_spec', + 'coffee/spec/views/textbook_spec', + 'coffee/spec/views/upload_spec', + 'js/spec/video/transcripts/utils_spec', + 'js/spec/video/transcripts/editor_spec', + 'js/spec/video/transcripts/videolist_spec', + 'js/spec/video/transcripts/message_manager_spec', + 'js/spec/video/transcripts/file_uploader_spec', + 'js/spec/models/component_template_spec', + 'js/spec/models/explicit_url_spec', + 'js/spec/models/xblock_info_spec', + 'js/spec/models/xblock_validation_spec', + 'js/spec/models/license_spec', + 'js/spec/utils/drag_and_drop_spec', + 'js/spec/utils/handle_iframe_binding_spec', + 'js/spec/utils/module_spec', + 'js/spec/views/active_video_upload_list_spec', + 'js/spec/views/previous_video_upload_spec', + 'js/spec/views/previous_video_upload_list_spec', + 'js/spec/views/assets_spec', + 'js/spec/views/baseview_spec', + 'js/spec/views/container_spec', + 'js/spec/views/paged_container_spec', + 'js/spec/views/group_configuration_spec', + 'js/spec/views/unit_outline_spec', + 'js/spec/views/xblock_spec', + 'js/spec/views/xblock_editor_spec', + 'js/spec/views/xblock_string_field_editor_spec', + 'js/spec/views/xblock_validation_spec', + 'js/spec/views/license_spec', + 'js/spec/views/paging_spec', + 'js/spec/views/login_studio_spec', + 'js/spec/views/pages/container_spec', + 'js/spec/views/pages/container_subviews_spec', + 'js/spec/views/pages/group_configurations_spec', + 'js/spec/views/pages/course_outline_spec', + 'js/spec/views/pages/course_rerun_spec', + 'js/spec/views/pages/index_spec', + 'js/spec/views/pages/library_users_spec', + 'js/spec/views/modals/base_modal_spec', + 'js/spec/views/modals/edit_xblock_spec', + 'js/spec/views/modals/validation_error_modal_spec', + 'js/spec/views/settings/main_spec', + 'js/spec/factories/xblock_validation_spec', + 'js/certificates/spec/models/certificate_spec', + 'js/certificates/spec/views/certificate_details_spec', + 'js/certificates/spec/views/certificate_editor_spec', + 'js/certificates/spec/views/certificates_list_spec', + 'js/certificates/spec/views/certificate_preview_spec' + ]; + + i = 0; + + while (i < testFiles.length) { + testFiles[i] = '/base/' + testFiles[i] + '.js'; + i++; + } + + specHelpers = [ + 'common/js/spec_helpers/jasmine-extensions', + 'common/js/spec_helpers/jasmine-stealth', + 'common/js/spec_helpers/jasmine-waituntil' + ]; + + requireSerial(specHelpers.concat(testFiles), function() { + return window.__karma__.start(); + }); + +}).call(this, requirejs, requireSerial); // jshint ignore:line diff --git a/cms/static/cms/js/spec/main_squire.js b/cms/static/cms/js/spec/main_squire.js new file mode 100644 index 0000000000..8e65cef81b --- /dev/null +++ b/cms/static/cms/js/spec/main_squire.js @@ -0,0 +1,218 @@ +(function(requirejs, requireSerial) { + 'use strict'; + + var i, specHelpers, testFiles; + + requirejs.config({ + baseUrl: '/base/', + paths: { + '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', + 'jquery': 'common/js/vendor/jquery', + 'jquery-migrate': 'common/js/vendor/jquery-migrate', + 'jquery.ui': 'xmodule_js/common_static/js/vendor/jquery-ui.min', + 'jquery.form': 'xmodule_js/common_static/js/vendor/jquery.form', + 'jquery.markitup': 'xmodule_js/common_static/js/vendor/markitup/jquery.markitup', + 'jquery.leanModal': 'xmodule_js/common_static/js/vendor/jquery.leanModal', + 'jquery.smoothScroll': 'xmodule_js/common_static/js/vendor/jquery.smooth-scroll.min', + 'jquery.scrollTo': 'common/js/vendor/jquery.scrollTo', + 'jquery.timepicker': 'xmodule_js/common_static/js/vendor/timepicker/jquery.timepicker', + 'jquery.cookie': 'xmodule_js/common_static/js/vendor/jquery.cookie', + 'jquery.qtip': 'xmodule_js/common_static/js/vendor/jquery.qtip.min', + 'jquery.fileupload': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload', + 'jquery.fileupload-process': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process', // jshint ignore:line + 'jquery.fileupload-validate': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate', // jshint ignore:line + 'jquery.iframe-transport': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport', // jshint ignore:line + 'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill', + 'jquery.immediateDescendents': 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents', + 'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair', + 'date': 'xmodule_js/common_static/js/vendor/date', + 'text': 'xmodule_js/common_static/js/vendor/requirejs/text', + 'underscore': 'common/js/vendor/underscore', + 'underscore.string': 'common/js/vendor/underscore.string', + 'backbone': 'common/js/vendor/backbone', + 'backbone.associations': 'xmodule_js/common_static/js/vendor/backbone-associations-min', + 'backbone.paginator': 'common/js/vendor/backbone.paginator', + 'tinymce': 'xmodule_js/common_static/js/vendor/tinymce/js/tinymce/tinymce.full.min', + 'jquery.tinymce': 'xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce', + 'xmodule': 'xmodule_js/src/xmodule', + 'xblock/cms.runtime.v1': 'cms/js/xblock/cms.runtime.v1', + 'xblock': 'common/js/xblock', + 'utility': 'xmodule_js/common_static/js/src/utility', + 'sinon': 'xmodule_js/common_static/js/vendor/sinon-1.17.0', + 'squire': 'xmodule_js/common_static/js/vendor/Squire', + 'modernizr': 'edx-pattern-library/js/modernizr-custom', + 'afontgarde': 'edx-pattern-library/js/afontgarde', + 'edxicons': 'edx-pattern-library/js/edx-icons', + 'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly', + 'domReady': 'xmodule_js/common_static/js/vendor/domReady', + 'URI': 'xmodule_js/common_static/js/vendor/URI.min', + 'mathjax': '//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // jshint ignore:line + 'youtube': '//www.youtube.com/player_api?noext', + 'coffee/src/ajax_prefix': 'xmodule_js/common_static/coffee/src/ajax_prefix' + }, + shim: { + 'gettext': { + exports: 'gettext' + }, + 'date': { + exports: 'Date' + }, + 'jquery.ui': { + deps: ['jquery'], + exports: 'jQuery.ui' + }, + 'jquery.form': { + deps: ['jquery'], + exports: 'jQuery.fn.ajaxForm' + }, + 'jquery.markitup': { + deps: ['jquery'], + exports: 'jQuery.fn.markitup' + }, + 'jquery.leanModal': { + deps: ['jquery'], + exports: 'jQuery.fn.leanModal' + }, + 'jquery.smoothScroll': { + deps: ['jquery'], + exports: 'jQuery.fn.smoothScroll' + }, + 'jquery.scrollTo': { + deps: ['jquery'], + exports: 'jQuery.fn.scrollTo' + }, + 'jquery.cookie': { + deps: ['jquery'], + exports: 'jQuery.fn.cookie' + }, + 'jquery.qtip': { + deps: ['jquery'], + exports: 'jQuery.fn.qtip' + }, + 'jquery.fileupload': { + deps: ['jquery.ui', 'jquery.iframe-transport'], + exports: 'jQuery.fn.fileupload' + }, + 'jquery.fileupload-process': { + deps: ['jquery.fileupload'] + }, + 'jquery.fileupload-validate': { + deps: ['jquery.fileupload'] + }, + 'jquery.inputnumber': { + deps: ['jquery'], + exports: 'jQuery.fn.inputNumber' + }, + 'jquery.tinymce': { + deps: ['jquery', 'tinymce'], + exports: 'jQuery.fn.tinymce' + }, + 'datepair': { + deps: ['jquery.ui', 'jquery.timepicker'] + }, + 'underscore': { + exports: '_' + }, + 'backbone': { + deps: ['underscore', 'jquery'], + exports: 'Backbone' + }, + 'backbone.associations': { + deps: ['backbone'], + exports: 'Backbone.Associations' + }, + 'backbone.paginator': { + deps: ['backbone'], + exports: 'Backbone.PageableCollection' + }, + 'youtube': { + exports: 'YT' + }, + 'codemirror': { + exports: 'CodeMirror' + }, + 'tinymce': { + exports: 'tinymce' + }, + 'mathjax': { + exports: 'MathJax', + init: function() { + window.MathJax.Hub.Config({ + tex2jax: { + inlineMath: [['\\(', '\\)'], ['[mathjaxinline]', '[/mathjaxinline]']], + displayMath: [['\\[', '\\]'], ['[mathjax]', '[/mathjax]']] + } + }); + window.MathJax.Hub.Configured(); + } + }, + 'URI': { + exports: 'URI' + }, + 'xmodule': { + exports: 'XModule' + }, + 'sinon': { + exports: 'sinon' + }, + 'common/js/spec_helpers/jasmine-extensions': { + deps: ['jquery'] + }, + 'common/js/spec_helpers/jasmine-stealth': { + deps: ['underscore', 'underscore.string'] + }, + 'common/js/spec_helpers/jasmine-waituntil': { + deps: ['jquery'] + }, + 'xblock/core': { + exports: 'XBlock', + deps: ['jquery', 'jquery.immediateDescendents'] + }, + 'xblock/runtime.v1': { + exports: 'XBlock', + deps: ['xblock/core'] + }, + 'coffee/src/main': { + deps: ['coffee/src/ajax_prefix'] + }, + 'coffee/src/ajax_prefix': { + deps: ['jquery'] + }, + 'modernizr': { + exports: 'Modernizr' + }, + 'afontgarde': { + exports: 'AFontGarde' + } + } + }); + + jasmine.getFixtures().fixturesPath += 'coffee/fixtures'; + + testFiles = [ + 'coffee/spec/views/assets_spec', + 'js/spec/video/translations_editor_spec', + 'js/spec/video/file_uploader_editor_spec', + 'js/spec/models/group_configuration_spec' + ]; + + i = 0; + + while (i < testFiles.length) { + testFiles[i] = '/base/' + testFiles[i] + '.js'; + i++; + } + + specHelpers = [ + 'common/js/spec_helpers/jasmine-extensions', + 'common/js/spec_helpers/jasmine-stealth', + 'common/js/spec_helpers/jasmine-waituntil' + ]; + + requireSerial(specHelpers.concat(testFiles), function() { + return window.__karma__.start(); + }); + +}).call(this, requirejs, requireSerial); // jshint ignore:line diff --git a/cms/static/js/spec/xblock/cms.runtime.v1_spec.js b/cms/static/cms/js/spec/xblock/cms.runtime.v1_spec.js similarity index 79% rename from cms/static/js/spec/xblock/cms.runtime.v1_spec.js rename to cms/static/cms/js/spec/xblock/cms.runtime.v1_spec.js index c508c21548..893fe6827a 100644 --- a/cms/static/js/spec/xblock/cms.runtime.v1_spec.js +++ b/cms/static/cms/js/spec/xblock/cms.runtime.v1_spec.js @@ -1,10 +1,11 @@ -define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cms.runtime.v1"], - function (EditHelpers, BaseModal) { +define(['js/spec_helpers/edit_helpers', 'js/views/modals/base_modal', 'xblock/cms.runtime.v1'], + function(EditHelpers, BaseModal) { + 'use strict'; - describe("Studio Runtime v1", function() { + describe('Studio Runtime v1', function() { var runtime; - beforeEach(function () { + beforeEach(function() { EditHelpers.installEditTemplates(); runtime = new window.StudioRuntime.v1(); }); @@ -20,7 +21,7 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm }); it('shows save notifications', function() { - var title = "Mock saving...", + var title = 'Mock saving...', notificationSpy = EditHelpers.createNotificationSpy(); runtime.notify('save', { state: 'start', @@ -34,9 +35,9 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm }); it('shows error messages', function() { - var title = "Mock Error", - message = "This is a mock error.", - notificationSpy = EditHelpers.createNotificationSpy("Error"); + var title = 'Mock Error', + message = 'This is a mock error.', + notificationSpy = EditHelpers.createNotificationSpy('Error'); runtime.notify('error', { title: title, message: message @@ -44,7 +45,7 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm EditHelpers.verifyNotificationShowing(notificationSpy, title); }); - describe("Modal Dialogs", function() { + describe('Modal Dialogs', function() { var MockModal, modal, showMockModal; MockModal = BaseModal.extend({ @@ -55,12 +56,12 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm showMockModal = function() { modal = new MockModal({ - title: "Mock Modal" + title: 'Mock Modal' }); modal.show(); }; - beforeEach(function () { + beforeEach(function() { EditHelpers.installEditTemplates(); }); @@ -68,7 +69,7 @@ define(["js/spec_helpers/edit_helpers", "js/views/modals/base_modal", "xblock/cm EditHelpers.hideModalIfShowing(modal); }); - it('cancels a modal dialog', function () { + it('cancels a modal dialog', function() { showMockModal(); runtime.notify('modal-shown', modal); expect(EditHelpers.isShowingModal(modal)).toBeTruthy(); diff --git a/cms/static/cms/js/xblock/cms.runtime.v1.js b/cms/static/cms/js/xblock/cms.runtime.v1.js new file mode 100644 index 0000000000..6c5e73aaf3 --- /dev/null +++ b/cms/static/cms/js/xblock/cms.runtime.v1.js @@ -0,0 +1,188 @@ +define(['jquery', 'backbone', 'xblock/runtime.v1', 'URI', 'gettext', 'js/utils/modal', + 'common/js/components/views/feedback_notification'], + function($, Backbone, XBlock, URI, gettext, ModalUtils, NotificationView) { + 'use strict'; + + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { + var key; + for (key in parent) { + if (__hasProp.call(parent, key)) { + child[key] = parent[key]; + } + } + function Ctor() { + this.constructor = child; + } + Ctor.prototype = parent.prototype; + child.prototype = new Ctor(); + child.__super__ = parent.prototype; + return child; + }, + BaseRuntime = {}, + PreviewRuntime = {}, + StudioRuntime = {}; + + BaseRuntime.v1 = (function(_super) { + + __extends(v1, _super); + + v1.prototype.handlerUrl = function(element, handlerName, suffix, query) { + var uri; + uri = URI(this.handlerPrefix) + .segment($(element).data('usage-id')) + .segment('handler') + .segment(handlerName); + if (suffix !== null) { + uri.segment(suffix); + } + if (query !== null) { + uri.search(query); + } + return uri.toString(); + }; + + function v1() { + v1.__super__.constructor.call(this); + this.dispatcher = _.clone(Backbone.Events); + this.listenTo('save', this._handleSave); + this.listenTo('cancel', this._handleCancel); + this.listenTo('error', this._handleError); + this.listenTo('modal-shown', function(data) { + this.modal = data; + }); + this.listenTo('modal-hidden', function() { + this.modal = null; + }); + this.listenTo('page-shown', function(data) { + this.page = data; + }); + } + + /** + * Notify the Studio client-side runtime of an event so that it + * can update the UI in a consistent way. + * + * @param {string} name The name of the event. + * @param {object} data A JSON representation of the data to be included with the event. + */ + v1.prototype.notify = function(name, data) { + this.dispatcher.trigger(name, data); + }; + + /** + * Listen to a Studio event and invoke the specified callback when it is triggered. + * + * @param {string} name The name of the event. + * @param {function} callback The callback to be invoked. + */ + v1.prototype.listenTo = function(name, callback) { + this.dispatcher.bind(name, callback, this); + }; + + /** + * Refresh the view for the xblock represented by the specified element. + * + * @param {element} element The element representing the XBlock. + */ + v1.prototype.refreshXBlock = function(element) { + if (this.page) { + this.page.refreshXBlock(element); + } + }; + + v1.prototype._handleError = function(data) { + var message, title; + message = data.message || data.msg; + if (message) { + // TODO: remove 'Open Assessment' specific default title + title = data.title || gettext('OpenAssessment Save Error'); + this.alert = new NotificationView.Error({ + title: title, + message: message, + closeIcon: false, + shown: false + }); + this.alert.show(); + } + }; + + v1.prototype._handleSave = function(data) { + var message; + // Starting to save, so show a notification + if (data.state === 'start') { + message = data.message || gettext('Saving'); + this.notification = new NotificationView.Mini({ + title: message + }); + this.notification.show(); + } else if (data.state === 'end') { + // Finished saving, so hide the notification and refresh appropriately + this._hideAlerts(); + + if (this.modal && this.modal.onSave) { + // Notify the modal that the save has completed so that it can hide itself + // and then refresh the xblock. + this.modal.onSave(); + } else if (data.element) { + // ... else ask it to refresh the newly saved xblock + this.refreshXBlock(data.element); + } + this.notification.hide(); + } + }; + + v1.prototype._handleCancel = function() { + this._hideAlerts(); + if (this.modal) { + this.modal.cancel(); + this.notify('modal-hidden'); + } + }; + + /** + * Hide any alerts that are being shown. + */ + v1.prototype._hideAlerts = function() { + if (this.alert && this.alert.options.shown) { + this.alert.hide(); + } + }; + + return v1; + + })(XBlock.Runtime.v1); + + PreviewRuntime.v1 = (function(_super) { + + __extends(v1, _super); + + function v1() { + return v1.__super__.constructor.apply(this, arguments); + } + + v1.prototype.handlerPrefix = '/preview/xblock'; + + return v1; + + })(BaseRuntime.v1); + + StudioRuntime.v1 = (function(_super) { + + __extends(v1, _super); + + function v1() { + return v1.__super__.constructor.apply(this, arguments); + } + + v1.prototype.handlerPrefix = '/xblock'; + + return v1; + + })(BaseRuntime.v1); + + // Install the runtime's into the global namespace + window.BaseRuntime = BaseRuntime; + window.PreviewRuntime = PreviewRuntime; + window.StudioRuntime = StudioRuntime; + }); diff --git a/cms/static/coffee/spec/main.coffee b/cms/static/coffee/spec/main.coffee deleted file mode 100644 index 3685cf47ac..0000000000 --- a/cms/static/coffee/spec/main.coffee +++ /dev/null @@ -1,299 +0,0 @@ -requirejs.config({ - baseUrl: '/base/', - paths: { - "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", - "jquery": "xmodule_js/common_static/common/js/vendor/jquery", - "jquery-migrate": "xmodule_js/common_static/common/js/vendor/jquery-migrate", - "jquery.ui": "xmodule_js/common_static/js/vendor/jquery-ui.min", - "jquery.form": "xmodule_js/common_static/js/vendor/jquery.form", - "jquery.markitup": "xmodule_js/common_static/js/vendor/markitup/jquery.markitup", - "jquery.leanModal": "xmodule_js/common_static/js/vendor/jquery.leanModal", - "jquery.ajaxQueue": "xmodule_js/common_static/js/vendor/jquery.ajaxQueue", - "jquery.smoothScroll": "xmodule_js/common_static/js/vendor/jquery.smooth-scroll.min", - "jquery.scrollTo": "common/js/vendor/jquery.scrollTo", - "jquery.timepicker": "xmodule_js/common_static/js/vendor/timepicker/jquery.timepicker", - "jquery.cookie": "xmodule_js/common_static/js/vendor/jquery.cookie", - "jquery.qtip": "xmodule_js/common_static/js/vendor/jquery.qtip.min", - "jquery.fileupload": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload", - "jquery.fileupload-process": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process", - "jquery.fileupload-validate": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate", - "jquery.iframe-transport": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport", - "jquery.inputnumber": "xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill", - "jquery.immediateDescendents": "xmodule_js/common_static/coffee/src/jquery.immediateDescendents", - "jquery.simulate": "xmodule_js/common_static/js/vendor/jquery.simulate", - "datepair": "xmodule_js/common_static/js/vendor/timepicker/datepair", - "date": "xmodule_js/common_static/js/vendor/date", - "moment": "xmodule_js/common_static/js/vendor/moment.min", - "moment-with-locales": "xmodule_js/common_static/js/vendor/moment-with-locales.min", - "text": "xmodule_js/common_static/js/vendor/requirejs/text", - "underscore": "common/js/vendor/underscore", - "underscore.string": "common/js/vendor/underscore.string", - "backbone": "common/js/vendor/backbone", - "backbone.associations": "xmodule_js/common_static/js/vendor/backbone-associations-min", - "backbone.paginator": "common/js/vendor/backbone.paginator", - "backbone-relational": "xmodule_js/common_static/js/vendor/backbone-relational.min", - "tinymce": "xmodule_js/common_static/js/vendor/tinymce/js/tinymce/tinymce.full.min", - "jquery.tinymce": "xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce", - "xmodule": "xmodule_js/src/xmodule", - "xblock/cms.runtime.v1": "coffee/src/xblock/cms.runtime.v1", - "xblock/core": "xmodule_js/common_static/js/xblock/core", - "xblock": "xmodule_js/common_static/coffee/src/xblock", - "utility": "xmodule_js/common_static/js/src/utility", - "accessibility": "xmodule_js/common_static/js/src/accessibility_tools", - "sinon": "xmodule_js/common_static/js/vendor/sinon-1.17.0", - "squire": "xmodule_js/common_static/js/vendor/Squire", - "jasmine-imagediff": "xmodule_js/common_static/js/vendor/jasmine-imagediff", - "draggabilly": "xmodule_js/common_static/js/vendor/draggabilly", - "domReady": "xmodule_js/common_static/js/vendor/domReady", - "URI": "xmodule_js/common_static/js/vendor/URI.min", - "mock-ajax": "xmodule_js/common_static/js/vendor/mock-ajax", - "modernizr": "edx-pattern-library/js/modernizr-custom", - "afontgarde": "edx-pattern-library/js/afontgarde", - "edxicons": "edx-pattern-library/js/edx-icons", - - "mathjax": "//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured", - "youtube": "//www.youtube.com/player_api?noext", - - "coffee/src/ajax_prefix": "xmodule_js/common_static/coffee/src/ajax_prefix", - "js/spec/test_utils": "js/spec/test_utils", - } - shim: { - "gettext": { - exports: "gettext" - }, - "date": { - exports: "Date" - }, - "jquery-migrate": ['jquery'], - "jquery.ui": { - deps: ["jquery"], - exports: "jQuery.ui" - }, - "jquery.form": { - deps: ["jquery"], - exports: "jQuery.fn.ajaxForm" - }, - "jquery.markitup": { - deps: ["jquery"], - exports: "jQuery.fn.markitup" - }, - "jquery.leanModal": { - deps: ["jquery"], - exports: "jQuery.fn.leanModal" - }, - "jquery.smoothScroll": { - deps: ["jquery"], - exports: "jQuery.fn.smoothScroll" - }, - "jquery.ajaxQueue": { - deps: ["jquery"], - exports: "jQuery.fn.ajaxQueue" - }, - "jquery.scrollTo": { - deps: ["jquery"], - exports: "jQuery.fn.scrollTo" - }, - "jquery.cookie": { - deps: ["jquery"], - exports: "jQuery.fn.cookie" - }, - "jquery.qtip": { - deps: ["jquery"], - exports: "jQuery.fn.qtip" - }, - "jquery.fileupload": { - deps: ["jquery.ui", "jquery.iframe-transport"], - exports: "jQuery.fn.fileupload" - }, - "jquery.fileupload-process": { - deps: ["jquery.fileupload"] - }, - "jquery.fileupload-validate": { - deps: ["jquery.fileupload"] - }, - "jquery.inputnumber": { - deps: ["jquery"], - exports: "jQuery.fn.inputNumber" - }, - "jquery.simulate": { - deps: ["jquery"], - exports: "jQuery.fn.simulate" - }, - "jquery.tinymce": { - deps: ["jquery", "tinymce"], - exports: "jQuery.fn.tinymce" - }, - "datepair": { - deps: ["jquery.ui", "jquery.timepicker"] - }, - "underscore": { - exports: "_" - }, - "backbone": { - deps: ["underscore", "jquery"], - exports: "Backbone" - }, - "backbone.associations": { - deps: ["backbone"], - exports: "Backbone.Associations" - }, - "backbone.paginator": { - deps: ["backbone"], - exports: "Backbone.PageableCollection" - }, - "backbone-relational": { - deps: ["backbone"], - }, - "youtube": { - exports: "YT" - }, - "codemirror": { - exports: "CodeMirror" - }, - "tinymce": { - exports: "tinymce" - }, - "mathjax": { - exports: "MathJax", - init: -> - MathJax.Hub.Config - tex2jax: - inlineMath: [ - ["\\(", "\\)"], - ['[mathjaxinline]', '[/mathjaxinline]'] - ] - displayMath: [ - ["\\[", "\\]"], - ['[mathjax]', '[/mathjax]'] - ] - MathJax.Hub.Configured() - }, - "URI": { - exports: "URI" - }, - "xmodule": { - exports: "XModule" - }, - "sinon": { - exports: "sinon" - }, - "jasmine-imagediff": {}, - "common/js/spec_helpers/jasmine-extensions": { - deps: ["jquery"] - }, - "common/js/spec_helpers/jasmine-stealth": { - deps: ["underscore", "underscore.string"] - }, - "common/js/spec_helpers/jasmine-waituntil": { - deps: ["jquery"] - }, - "xblock/core": { - exports: "XBlock", - deps: ["jquery", "jquery.immediateDescendents"] - }, - "xblock/runtime.v1": { - exports: "XBlock", - deps: ["xblock/core"] - }, - "mock-ajax": { - deps: ["jquery"] - } - - "coffee/src/main": { - deps: ["coffee/src/ajax_prefix"] - }, - "coffee/src/ajax_prefix": { - deps: ["jquery"] - }, - "modernizr": { - exports: "Modernizr" - }, - "afontgarde": { - exports: "AFontGarde" - } - } -}); - -jasmine.getFixtures().fixturesPath += 'coffee/fixtures' - -testFiles = [ - "coffee/spec/main_spec", - "coffee/spec/models/course_spec", - "coffee/spec/models/metadata_spec", - "coffee/spec/models/section_spec", - "coffee/spec/models/settings_course_grader_spec", - "coffee/spec/models/settings_grading_spec", - "coffee/spec/models/textbook_spec", - "coffee/spec/models/upload_spec", - "coffee/spec/views/course_info_spec", - "coffee/spec/views/metadata_edit_spec", - "coffee/spec/views/module_edit_spec", - "coffee/spec/views/textbook_spec", - "coffee/spec/views/upload_spec", - "js/spec/video/transcripts/utils_spec", - "js/spec/video/transcripts/editor_spec", - "js/spec/video/transcripts/videolist_spec", - "js/spec/video/transcripts/message_manager_spec", - "js/spec/video/transcripts/file_uploader_spec", - "js/spec/models/component_template_spec", - "js/spec/models/explicit_url_spec", - "js/spec/models/xblock_info_spec", - "js/spec/models/xblock_validation_spec", - "js/spec/models/license_spec", - "js/spec/utils/drag_and_drop_spec", - "js/spec/utils/handle_iframe_binding_spec", - "js/spec/utils/module_spec", - "js/spec/views/active_video_upload_list_spec", - "js/spec/views/previous_video_upload_spec", - "js/spec/views/previous_video_upload_list_spec", - "js/spec/views/assets_spec", - "js/spec/views/baseview_spec", - "js/spec/views/container_spec", - "js/spec/views/paged_container_spec", - "js/spec/views/group_configuration_spec", - "js/spec/views/unit_outline_spec", - "js/spec/views/xblock_spec", - "js/spec/views/xblock_editor_spec", - "js/spec/views/xblock_string_field_editor_spec", - "js/spec/views/xblock_validation_spec", - "js/spec/views/license_spec", - "js/spec/views/paging_spec", - "js/spec/views/login_studio_spec", - "js/spec/views/pages/container_spec", - "js/spec/views/pages/container_subviews_spec", - "js/spec/views/pages/group_configurations_spec", - "js/spec/views/pages/course_outline_spec", - "js/spec/views/pages/course_rerun_spec", - "js/spec/views/pages/index_spec", - "js/spec/views/pages/library_users_spec", - "js/spec/views/modals/base_modal_spec", - "js/spec/views/modals/edit_xblock_spec", - "js/spec/views/modals/validation_error_modal_spec", - "js/spec/views/settings/main_spec", - "js/spec/factories/xblock_validation_spec", - "js/spec/xblock/cms.runtime.v1_spec", - "js/certificates/spec/models/certificate_spec", - "js/certificates/spec/views/certificate_details_spec", - "js/certificates/spec/views/certificate_editor_spec", - "js/certificates/spec/views/certificates_list_spec", - "js/certificates/spec/views/certificate_preview_spec" -] - -i = 0 -while i < testFiles.length - testFiles[i] = '/base/' + testFiles[i] + '.js' - i++ - -specHelpers = [ - 'common/js/spec_helpers/jasmine-extensions', - 'common/js/spec_helpers/jasmine-stealth', - 'common/js/spec_helpers/jasmine-waituntil' -] - -# Jasmine has a global stack for creating a tree of specs. We need to load -# spec files one by one, otherwise some end up getting nested under others. -requireSerial specHelpers.concat(testFiles), -> -# start test run, once Require.js is done - window.__karma__.start() diff --git a/cms/static/coffee/spec/main_squire.coffee b/cms/static/coffee/spec/main_squire.coffee deleted file mode 100644 index 3743e9602d..0000000000 --- a/cms/static/coffee/spec/main_squire.coffee +++ /dev/null @@ -1,218 +0,0 @@ -requirejs.config({ - baseUrl: '/base/', - - paths: { - "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", - "jquery": "common/js/vendor/jquery", - "jquery-migrate": "common/js/vendor/jquery-migrate", - "jquery.ui": "xmodule_js/common_static/js/vendor/jquery-ui.min", - "jquery.form": "xmodule_js/common_static/js/vendor/jquery.form", - "jquery.markitup": "xmodule_js/common_static/js/vendor/markitup/jquery.markitup", - "jquery.leanModal": "xmodule_js/common_static/js/vendor/jquery.leanModal", - "jquery.smoothScroll": "xmodule_js/common_static/js/vendor/jquery.smooth-scroll.min", - "jquery.scrollTo": "common/js/vendor/jquery.scrollTo", - "jquery.timepicker": "xmodule_js/common_static/js/vendor/timepicker/jquery.timepicker", - "jquery.cookie": "xmodule_js/common_static/js/vendor/jquery.cookie", - "jquery.qtip": "xmodule_js/common_static/js/vendor/jquery.qtip.min", - "jquery.fileupload": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload", - "jquery.fileupload-process": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-process", - "jquery.fileupload-validate": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate", - "jquery.iframe-transport": "xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport", - "jquery.inputnumber": "xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill", - "jquery.immediateDescendents": "xmodule_js/common_static/coffee/src/jquery.immediateDescendents", - "datepair": "xmodule_js/common_static/js/vendor/timepicker/datepair", - "date": "xmodule_js/common_static/js/vendor/date", - "text": "xmodule_js/common_static/js/vendor/requirejs/text", - "underscore": "common/js/vendor/underscore", - "underscore.string": "common/js/vendor/underscore.string", - "backbone": "common/js/vendor/backbone", - "backbone.associations": "xmodule_js/common_static/js/vendor/backbone-associations-min", - "backbone.paginator": "common/js/vendor/backbone.paginator", - "tinymce": "xmodule_js/common_static/js/vendor/tinymce/js/tinymce/tinymce.full.min", - "jquery.tinymce": "xmodule_js/common_static/js/vendor/tinymce/js/tinymce/jquery.tinymce", - "xmodule": "xmodule_js/src/xmodule", - "xblock/cms.runtime.v1": "coffee/src/xblock/cms.runtime.v1", - "xblock/core": "xmodule_js/common_static/js/xblock/core", - "xblock": "xmodule_js/common_static/coffee/src/xblock", - "utility": "xmodule_js/common_static/js/src/utility", - "sinon": "xmodule_js/common_static/js/vendor/sinon-1.17.0", - "squire": "xmodule_js/common_static/js/vendor/Squire", - "modernizr": "edx-pattern-library/js/modernizr-custom", - "afontgarde": "edx-pattern-library/js/afontgarde", - "edxicons": "edx-pattern-library/js/edx-icons", - "draggabilly": "xmodule_js/common_static/js/vendor/draggabilly", - "domReady": "xmodule_js/common_static/js/vendor/domReady", - "URI": "xmodule_js/common_static/js/vendor/URI.min", - - "mathjax": "//cdn.mathjax.org/mathjax/2.6-latest/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured", - "youtube": "//www.youtube.com/player_api?noext", - - "coffee/src/ajax_prefix": "xmodule_js/common_static/coffee/src/ajax_prefix" - } - shim: { - "gettext": { - exports: "gettext" - }, - "date": { - exports: "Date" - }, - "jquery.ui": { - deps: ["jquery"], - exports: "jQuery.ui" - }, - "jquery.form": { - deps: ["jquery"], - exports: "jQuery.fn.ajaxForm" - }, - "jquery.markitup": { - deps: ["jquery"], - exports: "jQuery.fn.markitup" - }, - "jquery.leanModal": { - deps: ["jquery"], - exports: "jQuery.fn.leanModal" - }, - "jquery.smoothScroll": { - deps: ["jquery"], - exports: "jQuery.fn.smoothScroll" - }, - "jquery.scrollTo": { - deps: ["jquery"], - exports: "jQuery.fn.scrollTo" - }, - "jquery.cookie": { - deps: ["jquery"], - exports: "jQuery.fn.cookie" - }, - "jquery.qtip": { - deps: ["jquery"], - exports: "jQuery.fn.qtip" - }, - "jquery.fileupload": { - deps: ["jquery.ui", "jquery.iframe-transport"], - exports: "jQuery.fn.fileupload" - }, - "jquery.fileupload-process": { - deps: ["jquery.fileupload"] - }, - "jquery.fileupload-validate": { - deps: ["jquery.fileupload"] - }, - "jquery.inputnumber": { - deps: ["jquery"], - exports: "jQuery.fn.inputNumber" - }, - "jquery.tinymce": { - deps: ["jquery", "tinymce"], - exports: "jQuery.fn.tinymce" - }, - "datepair": { - deps: ["jquery.ui", "jquery.timepicker"] - }, - "underscore": { - exports: "_" - }, - "backbone": { - deps: ["underscore", "jquery"], - exports: "Backbone" - }, - "backbone.associations": { - deps: ["backbone"], - exports: "Backbone.Associations" - }, - "backbone.paginator": { - deps: ["backbone"], - exports: "Backbone.PageableCollection" - }, - "youtube": { - exports: "YT" - }, - "codemirror": { - exports: "CodeMirror" - }, - "tinymce": { - exports: "tinymce" - }, - "mathjax": { - exports: "MathJax", - init: -> - MathJax.Hub.Config - tex2jax: - inlineMath: [ - ["\\(","\\)"], - ['[mathjaxinline]','[/mathjaxinline]'] - ] - displayMath: [ - ["\\[","\\]"], - ['[mathjax]','[/mathjax]'] - ] - MathJax.Hub.Configured(); - }, - "URI": { - exports: "URI" - }, - "xmodule": { - exports: "XModule" - }, - "sinon": { - exports: "sinon" - }, - "common/js/spec_helpers/jasmine-extensions": { - deps: ["jquery"] - }, - "common/js/spec_helpers/jasmine-stealth": { - deps: ["underscore", "underscore.string"] - }, - "common/js/spec_helpers/jasmine-waituntil": { - deps: ["jquery"] - }, - "xblock/core": { - exports: "XBlock", - deps: ["jquery", "jquery.immediateDescendents"] - }, - "xblock/runtime.v1": { - exports: "XBlock", - deps: ["xblock/core"] - }, - - "coffee/src/main": { - deps: ["coffee/src/ajax_prefix"] - }, - "coffee/src/ajax_prefix": { - deps: ["jquery"] - }, - "modernizr": { - exports: "Modernizr" - }, - "afontgarde": { - exports: "AFontGarde" - } - } -}); - -jasmine.getFixtures().fixturesPath += 'coffee/fixtures' - -testFiles = [ - 'coffee/spec/views/assets_spec', - 'js/spec/video/translations_editor_spec', - 'js/spec/video/file_uploader_editor_spec', - 'js/spec/models/group_configuration_spec' -] -i = 0 -while i < testFiles.length - testFiles[i] = '/base/' + testFiles[i] + '.js' - i++ - -specHelpers = [ - 'common/js/spec_helpers/jasmine-extensions', - 'common/js/spec_helpers/jasmine-stealth', - 'common/js/spec_helpers/jasmine-waituntil' -] - -# Jasmine has a global stack for creating a tree of specs. We need to load -# spec files one by one, otherwise some end up getting nested under others. -requireSerial specHelpers.concat(testFiles), -> -# start test run, once Require.js is done - window.__karma__.start() diff --git a/cms/static/coffee/src/xblock/cms.runtime.v1.coffee b/cms/static/coffee/src/xblock/cms.runtime.v1.coffee deleted file mode 100644 index 4cbade87bf..0000000000 --- a/cms/static/coffee/src/xblock/cms.runtime.v1.coffee +++ /dev/null @@ -1,96 +0,0 @@ -define [ - "jquery", "backbone", "xblock/runtime.v1", "URI", "gettext", - "js/utils/modal", "common/js/components/views/feedback_notification" -], ($, Backbone, XBlock, URI, gettext, ModalUtils, NotificationView) -> - - @BaseRuntime = {} - - class BaseRuntime.v1 extends XBlock.Runtime.v1 - handlerUrl: (element, handlerName, suffix, query, thirdparty) -> - uri = URI(@handlerPrefix).segment($(element).data('usage-id')) - .segment('handler') - .segment(handlerName) - if suffix? then uri.segment(suffix) - if query? then uri.search(query) - uri.toString() - - constructor: () -> - super() - @dispatcher = _.clone(Backbone.Events) - @listenTo('save', @_handleSave) - @listenTo('cancel', @_handleCancel) - @listenTo('error', @_handleError) - @listenTo('modal-shown', (data) -> - @modal = data) - @listenTo('modal-hidden', () -> - @modal = null) - @listenTo('page-shown', (data) -> - @page = data) - - # Notify the Studio client-side runtime of an event so that it can update the UI in a consistent way. - notify: (name, data) -> - @dispatcher.trigger(name, data) - - # Listen to a Studio event and invoke the specified callback when it is triggered. - listenTo: (name, callback) -> - @dispatcher.bind(name, callback, this) - - # Refresh the view for the xblock represented by the specified element. - refreshXBlock: (element) -> - if @page - @page.refreshXBlock(element) - - _handleError: (data) -> - message = data.message || data.msg - if message - # TODO: remove 'Open Assessment' specific default title - title = data.title || gettext("OpenAssessment Save Error") - @alert = new NotificationView.Error - title: title - message: message - closeIcon: false - shown: false - @alert.show() - - _handleSave: (data) -> - # Starting to save, so show a notification - if data.state == 'start' - message = data.message || gettext('Saving') - @notification = new NotificationView.Mini - title: message - @notification.show() - - # Finished saving, so hide the notification and refresh appropriately - else if data.state == 'end' - @_hideAlerts() - - # Notify the modal that the save has completed so that it can hide itself - # and then refresh the xblock. - if @modal and @modal.onSave - @modal.onSave() - # ... else ask it to refresh the newly saved xblock - else if data.element - @refreshXBlock(data.element) - - @notification.hide() - - _handleCancel: () -> - @_hideAlerts() - if @modal - @modal.cancel() - @notify('modal-hidden') - - _hideAlerts: () -> - # Hide any alerts that are being shown - if @alert && @alert.options.shown - @alert.hide() - - @PreviewRuntime = {} - - class PreviewRuntime.v1 extends BaseRuntime.v1 - handlerPrefix: '/preview/xblock' - - @StudioRuntime = {} - - class StudioRuntime.v1 extends BaseRuntime.v1 - handlerPrefix: '/xblock' diff --git a/cms/static/karma_cms.conf.js b/cms/static/karma_cms.conf.js index edfb65d9f4..f2ef478cd3 100644 --- a/cms/static/karma_cms.conf.js +++ b/cms/static/karma_cms.conf.js @@ -21,11 +21,13 @@ var options = { // Make sure the patterns in sourceFiles and specFiles do not match the same file. // Otherwise Istanbul which is used for coverage tracking will cause tests to not run. sourceFiles: [ + {pattern: 'cms/**/!(*spec|djangojs).js'}, {pattern: 'coffee/src/**/!(*spec).js'}, {pattern: 'js/**/!(*spec|djangojs).js'} ], specFiles: [ + {pattern: 'cms/**/*spec.js'}, {pattern: 'coffee/spec/**/*spec.js'}, {pattern: 'js/certificates/spec/**/*spec.js'}, {pattern: 'js/spec/**/*spec.js'} @@ -37,10 +39,10 @@ var options = { ], runFiles: [ - {pattern: 'coffee/spec/main.js', included: true} + {pattern: 'cms/js/spec/main.js', included: true} ] }; -module.exports = function (config) { +module.exports = function(config) { configModule.configure(config, options); }; diff --git a/cms/static/karma_cms_squire.conf.js b/cms/static/karma_cms_squire.conf.js index 093e51bb55..d8bdda0c98 100644 --- a/cms/static/karma_cms_squire.conf.js +++ b/cms/static/karma_cms_squire.conf.js @@ -36,7 +36,7 @@ var options = { ], runFiles: [ - {pattern: 'coffee/spec/main_squire.js', included: true} + {pattern: 'cms/js/spec/main_squire.js', included: true} ] }; diff --git a/common/static/coffee/spec/xblock/core_spec.coffee b/common/static/coffee/spec/xblock/core_spec.coffee deleted file mode 100644 index e04184710a..0000000000 --- a/common/static/coffee/spec/xblock/core_spec.coffee +++ /dev/null @@ -1,96 +0,0 @@ -describe "XBlock", -> - beforeEach -> - setFixtures """ -
-
-
-
-
-
-
-
- """ - - describe "initializeBlock", -> - beforeEach -> - window.TestRuntime = {} - @runtimeA = {name: 'runtimeA'} - @runtimeZ = {name: 'runtimeZ'} - TestRuntime.vA = jasmine.createSpy().and.returnValue(@runtimeA) - TestRuntime.vZ = jasmine.createSpy().and.returnValue(@runtimeZ) - - window.initFnA = jasmine.createSpy() - window.initFnZ = jasmine.createSpy() - - @fakeChildren = ['list', 'of', 'children'] - spyOn(XBlock, 'initializeXBlocks').and.returnValue(@fakeChildren) - - @vANode = $('#vA')[0] - @vZNode = $('#vZ')[0] - - @vABlock = XBlock.initializeBlock(@vANode, 'req-token-a') - @vZBlock = XBlock.initializeBlock(@vZNode) - @missingVersionBlock = XBlock.initializeBlock($('#missing-version')[0]) - @missingInitBlock = XBlock.initializeBlock($('#missing-init')[0]) - - it "loads the right runtime version", -> - expect(TestRuntime.vA).toHaveBeenCalledWith() - expect(TestRuntime.vZ).toHaveBeenCalledWith() - - it "loads the right init function", -> - expect(window.initFnA).toHaveBeenCalledWith(@runtimeA, @vANode, {}) - expect(window.initFnZ).toHaveBeenCalledWith(@runtimeZ, @vZNode, {}) - - it "loads when missing versions", -> - expect(@missingVersionBlock.element).toBe($('#missing-version')[0]) - expect(@missingVersionBlock.name).toBe('no-version') - - it "loads when missing init fn", -> - expect(@missingInitBlock.element).toBe($('#missing-init')[0]) - expect(@missingInitBlock.name).toBe('no-init') - - it "adds names to blocks", -> - expect(@vABlock.name).toBe('a-name') - - it "leaves leaves missing names undefined", -> - expect(@vZBlock.name).toBeUndefined() - - it "attaches the element to the block", -> - expect(@vABlock.element).toBe(@vANode) - expect(@vZBlock.element).toBe(@vZNode) - expect(@missingVersionBlock.element).toBe($('#missing-version')[0]) - expect(@missingInitBlock.element).toBe($('#missing-init')[0]) - - it "passes through the request token", -> - expect(XBlock.initializeXBlocks).toHaveBeenCalledWith($(@vANode), 'req-token-a') - expect(XBlock.initializeXBlocks).toHaveBeenCalledWith($(@vZNode), 'req-token-z') - - - describe "initializeBlocks", -> - beforeEach -> - spyOn(XBlock, 'initializeBlock') - - @vANode = $('#vA')[0] - @vZNode = $('#vZ')[0] - - it "initializes children", -> - XBlock.initializeBlocks($('#jasmine-fixtures')) - expect(XBlock.initializeBlock).toHaveBeenCalledWith(@vANode, undefined) - expect(XBlock.initializeBlock).toHaveBeenCalledWith(@vZNode, undefined) - - it "only initializes matching request tokens", -> - XBlock.initializeBlocks($('#jasmine-fixtures'), 'req-token-z') - expect(XBlock.initializeBlock).not.toHaveBeenCalledWith(@vANode, jasmine.any(Object)) - expect(XBlock.initializeBlock).toHaveBeenCalledWith(@vZNode, 'req-token-z') diff --git a/common/static/coffee/spec/xblock/runtime.v1_spec.coffee b/common/static/coffee/spec/xblock/runtime.v1_spec.coffee deleted file mode 100644 index 7bad77494d..0000000000 --- a/common/static/coffee/spec/xblock/runtime.v1_spec.coffee +++ /dev/null @@ -1,21 +0,0 @@ -describe "XBlock.Runtime.v1", -> - beforeEach -> - setFixtures """ -
- """ - @children = [ - {name: 'childA'}, - {name: 'childB'} - ] - - @element = $('.xblock')[0] - $(@element).prop('xblock_children', @children) - - @runtime = new XBlock.Runtime.v1(@element) - - it "provides a list of children", -> - expect(@runtime.children(@element)).toBe(@children) - - it "maps children by name", -> - expect(@runtime.childMap(@element, 'childA')).toBe(@children[0]) - expect(@runtime.childMap(@element, 'childB')).toBe(@children[1]) diff --git a/common/static/coffee/src/xblock/runtime.v1.coffee b/common/static/coffee/src/xblock/runtime.v1.coffee deleted file mode 100644 index fbe70dc878..0000000000 --- a/common/static/coffee/src/xblock/runtime.v1.coffee +++ /dev/null @@ -1,14 +0,0 @@ -class XBlock.Runtime.v1 - children: (block) => $(block).prop('xblock_children') - childMap: (block, childName) => - for child in @children(block) - return child if child.name == childName - - # Notify the client-side runtime that an event has occurred. - # This allows the runtime to update the UI in a consistent way - # for different XBlocks. - # `name` is an arbitrary string (for example, "save") - # `data` is an object (for example, {state: 'starting'}) - # The default implementation is a no-op. - # WARNING: This is an interim solution and not officially supported! - notify: (name, data) -> undefined diff --git a/common/static/common/js/karma.common.conf.js b/common/static/common/js/karma.common.conf.js index 36be0d44a5..f816b3ce7c 100644 --- a/common/static/common/js/karma.common.conf.js +++ b/common/static/common/js/karma.common.conf.js @@ -54,8 +54,7 @@ var commonFiles = { ], sourceFiles: [ - {pattern: 'common/js/components/**/*.js'}, - {pattern: 'common/js/utils/**/*.js'} + {pattern: 'common/js/!(spec_helpers)/**/!(*spec).js'} ], specFiles: [ diff --git a/common/static/common/js/spec/xblock/core_spec.js b/common/static/common/js/spec/xblock/core_spec.js new file mode 100644 index 0000000000..9e2a33c363 --- /dev/null +++ b/common/static/common/js/spec/xblock/core_spec.js @@ -0,0 +1,111 @@ +(function() { + 'use strict'; + + describe('XBlock', function() { + beforeEach(function() { + return setFixtures( + '
\n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + '
'); + }); + describe('initializeBlock', function() { + beforeEach(function() { + window.TestRuntime = {}; + this.runtimeA = { + name: 'runtimeA' + }; + this.runtimeZ = { + name: 'runtimeZ' + }; + window.TestRuntime.vA = jasmine.createSpy().and.returnValue(this.runtimeA); + window.TestRuntime.vZ = jasmine.createSpy().and.returnValue(this.runtimeZ); + window.initFnA = jasmine.createSpy(); + window.initFnZ = jasmine.createSpy(); + this.fakeChildren = ['list', 'of', 'children']; + spyOn(XBlock, 'initializeXBlocks').and.returnValue(this.fakeChildren); + this.vANode = $('#vA')[0]; + this.vZNode = $('#vZ')[0]; + this.vABlock = XBlock.initializeBlock(this.vANode, 'req-token-a'); + this.vZBlock = XBlock.initializeBlock(this.vZNode); + this.missingVersionBlock = XBlock.initializeBlock($('#missing-version')[0]); + this.missingInitBlock = XBlock.initializeBlock($('#missing-init')[0]); + }); + + it('loads the right runtime version', function() { + expect(window.TestRuntime.vA).toHaveBeenCalledWith(); + expect(window.TestRuntime.vZ).toHaveBeenCalledWith(); + }); + + it('loads the right init function', function() { + expect(window.initFnA).toHaveBeenCalledWith(this.runtimeA, this.vANode, {}); + expect(window.initFnZ).toHaveBeenCalledWith(this.runtimeZ, this.vZNode, {}); + }); + + it('loads when missing versions', function() { + expect(this.missingVersionBlock.element).toBe($('#missing-version')[0]); + expect(this.missingVersionBlock.name).toBe('no-version'); + }); + + it('loads when missing init fn', function() { + expect(this.missingInitBlock.element).toBe($('#missing-init')[0]); + expect(this.missingInitBlock.name).toBe('no-init'); + }); + + it('adds names to blocks', function() { + expect(this.vABlock.name).toBe('a-name'); + }); + + it('leaves leaves missing names undefined', function() { + expect(this.vZBlock.name).toBeUndefined(); + }); + + it('attaches the element to the block', function() { + expect(this.vABlock.element).toBe(this.vANode); + expect(this.vZBlock.element).toBe(this.vZNode); + expect(this.missingVersionBlock.element).toBe($('#missing-version')[0]); + expect(this.missingInitBlock.element).toBe($('#missing-init')[0]); + }); + + it('passes through the request token', function() { + expect(XBlock.initializeXBlocks).toHaveBeenCalledWith($(this.vANode), 'req-token-a'); + expect(XBlock.initializeXBlocks).toHaveBeenCalledWith($(this.vZNode), 'req-token-z'); + }); + }); + describe('initializeBlocks', function() { + beforeEach(function() { + spyOn(XBlock, 'initializeBlock'); + this.vANode = $('#vA')[0]; + this.vZNode = $('#vZ')[0]; + }); + + it('initializes children', function() { + XBlock.initializeBlocks($('#jasmine-fixtures')); + expect(XBlock.initializeBlock).toHaveBeenCalledWith(this.vANode, void 0); + expect(XBlock.initializeBlock).toHaveBeenCalledWith(this.vZNode, void 0); + }); + + it('only initializes matching request tokens', function() { + XBlock.initializeBlocks($('#jasmine-fixtures'), 'req-token-z'); + expect(XBlock.initializeBlock).not.toHaveBeenCalledWith(this.vANode, jasmine.any(Object)); + expect(XBlock.initializeBlock).toHaveBeenCalledWith(this.vZNode, 'req-token-z'); + }); + }); + }); +}).call(this); diff --git a/common/static/common/js/spec/xblock/runtime.v1_spec.js b/common/static/common/js/spec/xblock/runtime.v1_spec.js new file mode 100644 index 0000000000..49ea310e97 --- /dev/null +++ b/common/static/common/js/spec/xblock/runtime.v1_spec.js @@ -0,0 +1,28 @@ +(function() { + 'use strict'; + + describe('XBlock.Runtime.v1', function() { + beforeEach(function() { + setFixtures('
'); + this.children = [ + { + name: 'childA' + }, { + name: 'childB' + } + ]; + this.element = $('.xblock')[0]; + $(this.element).prop('xblock_children', this.children); + this.runtime = new XBlock.Runtime.v1(this.element); + }); + + it('provides a list of children', function() { + expect(this.runtime.children(this.element)).toBe(this.children); + }); + + it('maps children by name', function() { + expect(this.runtime.childMap(this.element, 'childA')).toBe(this.children[0]); + expect(this.runtime.childMap(this.element, 'childB')).toBe(this.children[1]); + }); + }); +}).call(this); diff --git a/common/static/js/xblock/core.js b/common/static/common/js/xblock/core.js similarity index 78% rename from common/static/js/xblock/core.js rename to common/static/common/js/xblock/core.js index 0cbaac3209..02c6ef31f8 100644 --- a/common/static/js/xblock/core.js +++ b/common/static/common/js/xblock/core.js @@ -1,13 +1,15 @@ (function($, JSON) { - 'use strict'; - function initializeBlockLikes(block_class, initializer, element, requestToken) { - var requestToken = requestToken || $(element).data('request-token'); + var XBlock; + + function initializeBlockLikes(blockClass, initializer, element, requestToken) { + var selector; + requestToken = requestToken || $(element).data('request-token'); if (requestToken) { - var selector = '.' + block_class + '[data-request-token="' + requestToken + '"]'; + selector = '.' + blockClass + '[data-request-token="' + requestToken + '"]'; } else { - var selector = '.' + block_class; + selector = '.' + blockClass; } return $(element).immediateDescendents(selector).map(function(idx, elem) { return initializer(elem, requestToken); @@ -15,17 +17,19 @@ } function elementRuntime(element) { - var $element = $(element); - var runtime = $element.data('runtime-class'); - var version = $element.data('runtime-version'); - var initFnName = $element.data('init'); + var $element = $(element), + runtime = $element.data('runtime-class'), + version = $element.data('runtime-version'), + initFnName = $element.data('init'); if (runtime && version && initFnName) { - return new window[runtime]['v' + version]; + return new window[runtime]['v' + version](); } else { if (runtime || version || initFnName) { - var elementTag = $('
').append($element.clone()).html(); - console.log('Block ' + elementTag + ' is missing data-runtime, data-runtime-version or data-init, and can\'t be initialized'); + console.log( + 'Block ' + $element.outerHTML + ' is missing data-runtime, data-runtime-version or data-init, ' + + 'and can\'t be initialized' + ); } // else this XBlock doesn't have a JS init function. return null; } @@ -42,14 +46,13 @@ * The constructor is called with the arguments 'runtime', 'element', * and then all of 'block_args'. */ - function constructBlock(element, block_args) { + function constructBlock(element, blockArgs) { var block; var $element = $(element); var runtime = elementRuntime(element); - block_args.unshift(element); - block_args.unshift(runtime); - + blockArgs.unshift(element); + blockArgs.unshift(runtime); if (runtime) { @@ -59,7 +62,7 @@ // This create a new constructor that can then apply() the block_args // to the initFn. function Block() { - return initFn.apply(this, block_args); + return initFn.apply(this, blockArgs); } Block.prototype = initFn.prototype; @@ -78,7 +81,7 @@ return block; } - var XBlock = { + XBlock = { Runtime: {}, /** @@ -88,11 +91,12 @@ * the children themselves. */ initializeBlock: function(element, requestToken) { - var $element = $(element); + var $element = $(element), + children, asides; - var requestToken = requestToken || $element.data('request-token'); - var children = XBlock.initializeXBlocks($element, requestToken); - var asides = XBlock.initializeXBlockAsides($element, requestToken); + requestToken = requestToken || $element.data('request-token'); + children = XBlock.initializeXBlocks($element, requestToken); + asides = XBlock.initializeXBlockAsides($element, requestToken); if (asides) { children = children.concat(asides); } @@ -106,7 +110,7 @@ * If requestToken is omitted, use the data-request-token attribute from element, or use * the request-tokens specified on the children themselves. */ - initializeAside: function(element, requestToken) { + initializeAside: function(element) { var blockUsageId = $(element).data('block-id'); var blockElement = $(element).siblings('[data-usage-id="' + blockUsageId + '"]')[0]; return constructBlock(element, [blockElement, initArgs(element)]); diff --git a/common/static/common/js/xblock/runtime.v1.js b/common/static/common/js/xblock/runtime.v1.js new file mode 100644 index 0000000000..1c196cb1ec --- /dev/null +++ b/common/static/common/js/xblock/runtime.v1.js @@ -0,0 +1,50 @@ +(function() { + 'use strict'; + + XBlock.Runtime.v1 = (function() { + + function v1() { + var _this = this; + this.childMap = function() { + return v1.prototype.childMap.apply(_this, arguments); + }; + this.children = function() { + return v1.prototype.children.apply(_this, arguments); + }; + } + + v1.prototype.children = function(block) { + return $(block).prop('xblock_children'); + }; + + v1.prototype.childMap = function(block, childName) { + var child, _i, _len, _ref; + _ref = this.children(block); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + if (child.name === childName) { + return child; + } + } + }; + + /** + * Notify the client-side runtime that an event has occurred. + * + * This allows the runtime to update the UI in a consistent way + * for different XBlocks. + * `name` is an arbitrary string (for example, "save") + * `data` is an object (for example, {state: 'starting'}) + * The default implementation is a no-op. + * + * WARNING: This is an interim solution and not officially supported! + */ + v1.prototype.notify = function() { + // Do nothing + }; + + return v1; + + })(); + +}).call(this); diff --git a/common/static/karma_common.conf.js b/common/static/karma_common.conf.js index cf19a73fd7..9a1c333b9d 100644 --- a/common/static/karma_common.conf.js +++ b/common/static/karma_common.conf.js @@ -11,7 +11,7 @@ var options = { useRequireJs: false, - normalizePathsForCoverageFunc: function (appRoot, pattern) { + normalizePathsForCoverageFunc: function(appRoot, pattern) { return path.join(appRoot, '/common/static/' + pattern); }, @@ -50,16 +50,17 @@ var options = { // Make sure the patterns in sourceFiles and specFiles do not match the same file. // Otherwise Istanbul which is used for coverage tracking will cause tests to not run. sourceFiles: [ - {pattern: 'js/xblock/**/*.js', included: true}, {pattern: 'coffee/src/**/*.js', included: true}, - {pattern: 'js/src/**/*.js', included: true}, - {pattern: 'js/capa/src/**/*.js', included: true} + {pattern: 'common/js/xblock/core.js', included: true}, + {pattern: 'common/js/xblock/runtime.v1.js', included: true}, + {pattern: 'js/capa/src/**/*.js', included: true}, + {pattern: 'js/src/**/*.js', included: true} ], specFiles: [ {pattern: 'coffee/spec/**/*.js', included: true}, - {pattern: 'js/spec/**/*.js', included: true}, - {pattern: 'js/capa/spec/**/*.js', included: true} + {pattern: 'common/js/spec/xblock/*.js', included: true}, + {pattern: 'js/**/*spec.js', included: true} ], fixtureFiles: [ @@ -69,6 +70,6 @@ var options = { ] }; -module.exports = function (config) { +module.exports = function(config) { configModule.configure(config, options); }; diff --git a/lms/envs/common.py b/lms/envs/common.py index 5d8db0c6db..5ea1ecac1d 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1528,9 +1528,14 @@ PIPELINE_CSS = { } -common_js = set(rooted_glob(COMMON_ROOT / 'static', 'coffee/src/**/*.js')) - set(courseware_js + discussion_js + notes_js + instructor_dash_js) # pylint: disable=line-too-long -project_js = set(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/**/*.js')) - set(courseware_js + discussion_js + notes_js + instructor_dash_js) # pylint: disable=line-too-long - +separately_bundled_js = set(courseware_js + discussion_js + notes_js + instructor_dash_js) +common_js = sorted(set(rooted_glob(COMMON_ROOT / 'static', 'coffee/src/**/*.js')) - separately_bundled_js) +xblock_runtime_js = [ + 'common/js/xblock/core.js', + 'common/js/xblock/runtime.v1.js', + 'lms/js/xblock/lms.runtime.v1.js', +] +lms_application_js = sorted(set(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/**/*.js')) - separately_bundled_js) PIPELINE_JS = { 'base_application': { @@ -1539,13 +1544,14 @@ PIPELINE_JS = { }, 'application': { - - # Application will contain all paths not in courseware_only_js - 'source_filenames': ['js/xblock/core.js'] + sorted(common_js) + sorted(project_js) + base_application_js + [ - 'js/sticky_filter.js', - 'js/query-params.js', - 'js/vendor/moment.min.js', - ], + 'source_filenames': ( + common_js + xblock_runtime_js + base_application_js + lms_application_js + + [ + 'js/sticky_filter.js', + 'js/query-params.js', + 'js/vendor/moment.min.js', + ] + ), 'output_filename': 'js/lms-application.js', }, 'proctoring': { diff --git a/lms/static/coffee/src/xblock/lms.runtime.v1.coffee b/lms/static/coffee/src/xblock/lms.runtime.v1.coffee deleted file mode 100644 index f10b1ae1c5..0000000000 --- a/lms/static/coffee/src/xblock/lms.runtime.v1.coffee +++ /dev/null @@ -1,18 +0,0 @@ -@LmsRuntime = {} - -class LmsRuntime.v1 extends XBlock.Runtime.v1 - handlerUrl: (element, handlerName, suffix, query, thirdparty) -> - courseId = $(element).data("course-id") - usageId = $(element).data("usage-id") - handlerAuth = if thirdparty then "handler_noauth" else "handler" - - uri = URI('/courses').segment(courseId) - .segment('xblock') - .segment(usageId) - .segment(handlerAuth) - .segment(handlerName) - - if suffix? then uri.segment(suffix) - if query? then uri.search(query) - - uri.toString() diff --git a/lms/static/karma_lms_coffee.conf.js b/lms/static/karma_lms_coffee.conf.js index aab5894928..78866c684c 100644 --- a/lms/static/karma_lms_coffee.conf.js +++ b/lms/static/karma_lms_coffee.conf.js @@ -29,6 +29,7 @@ var options = { {pattern: 'common/js/vendor/jquery.js', included: true}, {pattern: 'common/js/vendor/jquery-migrate.js', included: true}, {pattern: 'common/js/vendor/underscore.js', included: true}, + {pattern: 'common/js/xblock/*.js', included: true}, {pattern: 'xmodule_js/common_static/js/src/logger.js', included: true}, {pattern: 'xmodule_js/common_static/js/test/i18n.js', included: true}, {pattern: 'xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js', included: true}, @@ -38,8 +39,6 @@ var options = { {pattern: 'xmodule_js/common_static/js/vendor/jquery-ui.min.js', included: true}, {pattern: 'xmodule_js/common_static/js/vendor/URI.min.js', included: true}, - {pattern: 'xmodule_js/common_static/js/xblock/*.js', included: true}, - {pattern: 'xmodule_js/common_static/coffee/src/xblock/*.js', included: true}, {pattern: 'xmodule_js/src/capa/*.js', included: true}, {pattern: 'xmodule_js/src/video/*.js', included: true}, {pattern: 'xmodule_js/src/xmodule.js', included: true}, diff --git a/lms/static/lms/js/require-config.js b/lms/static/lms/js/require-config.js index a1f37133f4..bda10131a4 100644 --- a/lms/static/lms/js/require-config.js +++ b/lms/static/lms/js/require-config.js @@ -1,4 +1,5 @@ -;(function (require, define) { +;(function(require, define) { + 'use strict'; // We do not wish to bundle common libraries (that may also be used by non-RequireJS code on the page // into the optimized files. Therefore load these libraries through script tags and explicitly define them. @@ -24,207 +25,207 @@ } } else { - console.error("Expected library to be included on page, but not found on window object: " + name); + console.error('Expected library to be included on page, but not found on window object: ' + name); } }; - defineDependency("jQuery", "jquery"); - defineDependency("jQuery", "jquery-migrate"); - defineDependency("_", "underscore"); - defineDependency("s", "underscore.string"); - // Underscore.string no longer installs itself directly on "_". For compatibility with existing - // code, add it to "_" with its previous name. + defineDependency('jQuery', 'jquery'); + defineDependency('jQuery', 'jquery-migrate'); + defineDependency('_', 'underscore'); + defineDependency('s', 'underscore.string'); + // Underscore.string no longer installs itself directly on '_'. For compatibility with existing + // code, add it to '_' with its previous name. if (window._ && window.s) { window._.str = window.s; } - defineDependency("gettext", "gettext"); - defineDependency("Logger", "logger"); - defineDependency("URI", "URI"); - defineDependency("Backbone", "backbone"); - defineDependency("Modernizr", "modernizr"); + defineDependency('gettext', 'gettext'); + defineDependency('Logger', 'logger'); + defineDependency('URI', 'URI'); + defineDependency('Backbone', 'backbone'); + defineDependency('Modernizr', 'modernizr'); - // Add the UI Toolkit helper classes that have been installed in the "edx" namespace - defineDependency("edx.HtmlUtils", "edx-ui-toolkit/js/utils/html-utils"); - defineDependency("edx.StringUtils", "edx-ui-toolkit/js/utils/string-utils"); + // Add the UI Toolkit helper classes that have been installed in the 'edx' namespace + defineDependency('edx.HtmlUtils', 'edx-ui-toolkit/js/utils/html-utils'); + defineDependency('edx.StringUtils', 'edx-ui-toolkit/js/utils/string-utils'); // utility.js adds two functions to the window object, but does not return anything - defineDependency("isExternal", "utility", true); + defineDependency('isExternal', 'utility', true); } require.config({ // NOTE: baseUrl has been previously set in lms/templates/main.html waitSeconds: 60, paths: { - "annotator_1.2.9": "js/vendor/edxnotes/annotator-full.min", - "date": "js/vendor/date", - "moment": "js/vendor/moment.min", - "moment-with-locales": "xmodule_js/common_static/js/vendor/moment-with-locales.min", - "text": "js/vendor/requirejs/text", - "logger": "js/src/logger", - "backbone": "common/js/vendor/backbone", - "backbone-super": "js/vendor/backbone-super", - "backbone.paginator": "common/js/vendor/backbone.paginator", - "underscore": "common/js/vendor/underscore", - "underscore.string": "common/js/vendor/underscore.string", + 'annotator_1.2.9': 'js/vendor/edxnotes/annotator-full.min', + 'date': 'js/vendor/date', + 'moment': 'js/vendor/moment.min', + 'moment-with-locales': 'xmodule_js/common_static/js/vendor/moment-with-locales.min', + 'text': 'js/vendor/requirejs/text', + 'logger': 'js/src/logger', + 'backbone': 'common/js/vendor/backbone', + 'backbone-super': 'js/vendor/backbone-super', + 'backbone.paginator': 'common/js/vendor/backbone.paginator', + 'underscore': 'common/js/vendor/underscore', + 'underscore.string': 'common/js/vendor/underscore.string', // The jquery-migrate library was added in upgrading from // jQuery 1.7.x to 2.2.x. This config allows developers - // to depend on "jquery" which opaquely requires both + // to depend on 'jquery' which opaquely requires both // libraries. - "jquery": "common/js/vendor/jquery", - "jquery-migrate": "common/js/vendor/jquery-migrate", - "jquery.scrollTo": "common/js/vendor/jquery.scrollTo", - "jquery.cookie": "js/vendor/jquery.cookie", + 'jquery': 'common/js/vendor/jquery', + 'jquery-migrate': 'common/js/vendor/jquery-migrate', + 'jquery.scrollTo': 'common/js/vendor/jquery.scrollTo', + 'jquery.cookie': 'js/vendor/jquery.cookie', 'jquery.timeago': 'js/vendor/jquery.timeago', - "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", - "modernizr": "edx-pattern-library/js/modernizr-custom", - "afontgarde": "edx-pattern-library/js/afontgarde", - "edxicons": "edx-pattern-library/js/edx-icons", - "draggabilly": "js/vendor/draggabilly", + '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', + 'modernizr': 'edx-pattern-library/js/modernizr-custom', + 'afontgarde': 'edx-pattern-library/js/afontgarde', + 'edxicons': 'edx-pattern-library/js/edx-icons', + 'draggabilly': 'js/vendor/draggabilly', // Files needed by OVA - "annotator": "js/vendor/ova/annotator-full", - "annotator-harvardx": "js/vendor/ova/annotator-full-firebase-auth", - "video.dev": "js/vendor/ova/video.dev", - "vjs.youtube": "js/vendor/ova/vjs.youtube", - "rangeslider": "js/vendor/ova/rangeslider", - "share-annotator": "js/vendor/ova/share-annotator", - "richText-annotator": "js/vendor/ova/richText-annotator", - "reply-annotator": "js/vendor/ova/reply-annotator", - "grouping-annotator": "js/vendor/ova/grouping-annotator", - "tags-annotator": "js/vendor/ova/tags-annotator", - "diacritic-annotator": "js/vendor/ova/diacritic-annotator", - "flagging-annotator": "js/vendor/ova/flagging-annotator", - "jquery-Watch": "js/vendor/ova/jquery-Watch", - "openseadragon": "js/vendor/ova/openseadragon", - "osda": "js/vendor/ova/OpenSeaDragonAnnotation", - "ova": "js/vendor/ova/ova", - "catch": "js/vendor/ova/catch/js/catch", - "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", - "picturefill": "common/js/vendor/picturefill" + 'annotator': 'js/vendor/ova/annotator-full', + 'annotator-harvardx': 'js/vendor/ova/annotator-full-firebase-auth', + 'video.dev': 'js/vendor/ova/video.dev', + 'vjs.youtube': 'js/vendor/ova/vjs.youtube', + 'rangeslider': 'js/vendor/ova/rangeslider', + 'share-annotator': 'js/vendor/ova/share-annotator', + 'richText-annotator': 'js/vendor/ova/richText-annotator', + 'reply-annotator': 'js/vendor/ova/reply-annotator', + 'grouping-annotator': 'js/vendor/ova/grouping-annotator', + 'tags-annotator': 'js/vendor/ova/tags-annotator', + 'diacritic-annotator': 'js/vendor/ova/diacritic-annotator', + 'flagging-annotator': 'js/vendor/ova/flagging-annotator', + 'jquery-Watch': 'js/vendor/ova/jquery-Watch', + 'openseadragon': 'js/vendor/ova/openseadragon', + 'osda': 'js/vendor/ova/OpenSeaDragonAnnotation', + 'ova': 'js/vendor/ova/ova', + 'catch': 'js/vendor/ova/catch/js/catch', + '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', + 'picturefill': 'common/js/vendor/picturefill' // end of files needed by OVA }, shim: { - "annotator_1.2.9": { - deps: ["jquery"], - exports: "Annotator" + 'annotator_1.2.9': { + deps: ['jquery'], + exports: 'Annotator' }, - "date": { - exports: "Date" + 'date': { + exports: 'Date' }, - "jquery": { - exports: "jQuery" + 'jquery': { + exports: 'jQuery' }, - "jquery-migrate": ['jquery'], - "jquery.cookie": { - deps: ["jquery"], - exports: "jQuery.fn.cookie" + 'jquery-migrate': ['jquery'], + 'jquery.cookie': { + deps: ['jquery'], + exports: 'jQuery.fn.cookie' }, - "jquery.timeago": { - deps: ["jquery"], - exports: "jQuery.timeago" + 'jquery.timeago': { + deps: ['jquery'], + exports: 'jQuery.timeago' }, - "jquery.url": { - deps: ["jquery"], - exports: "jQuery.url" + 'jquery.url': { + deps: ['jquery'], + exports: 'jQuery.url' }, - "jquery.fileupload": { - deps: ["jquery.ui", "jquery.iframe-transport"], - exports: "jQuery.fn.fileupload" + 'jquery.fileupload': { + deps: ['jquery.ui', 'jquery.iframe-transport'], + exports: 'jQuery.fn.fileupload' }, - "jquery.tinymce": { - deps: ["jquery", "tinymce"], - exports: "jQuery.fn.tinymce" + 'jquery.tinymce': { + deps: ['jquery', 'tinymce'], + exports: 'jQuery.fn.tinymce' }, - "backbone.paginator": { - deps: ["backbone"], - exports: "Backbone.PageableCollection" + 'backbone.paginator': { + deps: ['backbone'], + exports: 'Backbone.PageableCollection' }, - "backbone-super": { - deps: ["backbone"] + 'backbone-super': { + deps: ['backbone'] }, - "string_utils": { - deps: ["underscore"], - exports: "interpolate_text" + 'string_utils': { + deps: ['underscore'], + exports: 'interpolate_text' }, // Needed by OVA - "video.dev": { - exports:"videojs" + 'video.dev': { + exports: 'videojs' }, - "vjs.youtube": { - deps: ["video.dev"] + 'vjs.youtube': { + deps: ['video.dev'] }, - "rangeslider": { - deps: ["video.dev"] + 'rangeslider': { + deps: ['video.dev'] }, - "annotator": { - exports: "Annotator" + 'annotator': { + exports: 'Annotator' }, - "annotator-harvardx":{ - deps: ["annotator"] + 'annotator-harvardx': { + deps: ['annotator'] }, - "share-annotator": { - deps: ["annotator"] + 'share-annotator': { + deps: ['annotator'] }, - "richText-annotator": { - deps: ["annotator", "tinymce"] + 'richText-annotator': { + deps: ['annotator', 'tinymce'] }, - "reply-annotator": { - deps: ["annotator"] + 'reply-annotator': { + deps: ['annotator'] }, - "tags-annotator": { - deps: ["annotator"] + 'tags-annotator': { + deps: ['annotator'] }, - "diacritic-annotator": { - deps: ["annotator"] + 'diacritic-annotator': { + deps: ['annotator'] }, - "flagging-annotator": { - deps: ["annotator"] + 'flagging-annotator': { + deps: ['annotator'] }, - "grouping-annotator": { - deps: ["annotator"] + 'grouping-annotator': { + deps: ['annotator'] }, - "ova": { - exports: "ova", + 'ova': { + exports: 'ova', deps: [ - "annotator", "annotator-harvardx", "video.dev", "vjs.youtube", "rangeslider", "share-annotator", - "richText-annotator", "reply-annotator", "tags-annotator", "flagging-annotator", - "grouping-annotator", "diacritic-annotator", "jquery-Watch", "catch", "handlebars", "URI" + 'annotator', 'annotator-harvardx', 'video.dev', 'vjs.youtube', 'rangeslider', 'share-annotator', + 'richText-annotator', 'reply-annotator', 'tags-annotator', 'flagging-annotator', + 'grouping-annotator', 'diacritic-annotator', 'jquery-Watch', 'catch', 'handlebars', 'URI' ] }, - "osda": { - exports: "osda", + 'osda': { + exports: 'osda', deps: [ - "annotator", "annotator-harvardx", "video.dev", "vjs.youtube", "rangeslider", "share-annotator", - "richText-annotator", "reply-annotator", "tags-annotator", "flagging-annotator", - "grouping-annotator", "diacritic-annotator", "openseadragon", "jquery-Watch", "catch", "handlebars", - "URI" + 'annotator', 'annotator-harvardx', 'video.dev', 'vjs.youtube', 'rangeslider', 'share-annotator', + 'richText-annotator', 'reply-annotator', 'tags-annotator', 'flagging-annotator', + 'grouping-annotator', 'diacritic-annotator', 'openseadragon', 'jquery-Watch', 'catch', 'handlebars', + 'URI' ] }, - "tinymce": { - exports: "tinymce" + 'tinymce': { + exports: 'tinymce' }, // End of needed by OVA - "moment": { - exports: "moment" + 'moment': { + exports: 'moment' }, - "moment-with-locales": { - exports: "moment" + 'moment-with-locales': { + exports: 'moment' }, - "afontgarde": { - exports: "AFontGarde" + 'afontgarde': { + exports: 'AFontGarde' }, // Because Draggabilly is being used by video code, the namespaced version of // require is not being recognized. Therefore the library is being added to the // global namespace instead of being registered in require. - "draggabilly": { - exports: "Draggabilly" + 'draggabilly': { + exports: 'Draggabilly' } } }); diff --git a/lms/static/lms/js/spec/main.js b/lms/static/lms/js/spec/main.js index 5d397d9295..6d58500cce 100644 --- a/lms/static/lms/js/spec/main.js +++ b/lms/static/lms/js/spec/main.js @@ -56,9 +56,8 @@ 'coffee/src/ajax_prefix': 'xmodule_js/common_static/coffee/src/ajax_prefix', 'coffee/src/instructor_dashboard/student_admin': 'coffee/src/instructor_dashboard/student_admin', 'xmodule_js/common_static/js/test/add_ajax_prefix': 'xmodule_js/common_static/js/test/add_ajax_prefix', - 'xblock/core': 'xmodule_js/common_static/js/xblock/core', - 'xblock/runtime.v1': 'xmodule_js/common_static/coffee/src/xblock/runtime.v1', - 'xblock/lms.runtime.v1': 'coffee/src/xblock/lms.runtime.v1', + 'xblock/lms.runtime.v1': 'lms/js/xblock/lms.runtime.v1', + 'xblock': 'common/js/xblock', 'capa/display': 'xmodule_js/src/capa/display', 'string_utils': 'xmodule_js/common_static/js/src/string_utils', 'logger': 'xmodule_js/common_static/js/src/logger', diff --git a/lms/static/lms/js/xblock/lms.runtime.v1.js b/lms/static/lms/js/xblock/lms.runtime.v1.js new file mode 100644 index 0000000000..50903ccaa3 --- /dev/null +++ b/lms/static/lms/js/xblock/lms.runtime.v1.js @@ -0,0 +1,55 @@ +(function(URI) { + 'use strict'; + + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { + var key; + for (key in parent) { + if (__hasProp.call(parent, key)) { + child[key] = parent[key]; + } + } + function Ctor() { + this.constructor = child; + } + Ctor.prototype = parent.prototype; + child.prototype = new Ctor(); + child.__super__ = parent.prototype; + return child; + }; + + this.LmsRuntime = {}; + + this.LmsRuntime.v1 = (function(_super) { + + __extends(v1, _super); + + function v1() { + return v1.__super__.constructor.apply(this, arguments); + } + + v1.prototype.handlerUrl = function(element, handlerName, suffix, query, thirdparty) { + var courseId, handlerAuth, uri, usageId; + courseId = $(element).data('course-id'); + usageId = $(element).data('usage-id'); + handlerAuth = thirdparty ? 'handler_noauth' : 'handler'; + uri = URI('/courses') + .segment(courseId) + .segment('xblock') + .segment(usageId) + .segment(handlerAuth) + .segment(handlerName); + if (suffix !== null) { + uri.segment(suffix); + } + if (query !== null) { + uri.search(query); + } + return uri.toString(); + }; + + return v1; + + })(XBlock.Runtime.v1); + +}).call(this, URI); // jshint ignore:line From 4e38b2e4e8180631e2c41a5f1d84499e634c568e Mon Sep 17 00:00:00 2001 From: asadiqbal Date: Thu, 16 Jun 2016 16:59:25 +0500 Subject: [PATCH 08/65] WL-515 Update Activate Account message page --- conf/locale/en/LC_MESSAGES/djangojs.po | 16 +++++++++ lms/djangoapps/verify_student/views.py | 1 + .../make_payment_step_view_spec.js | 5 +++ .../js/verify_student/pay_and_verify.js | 1 + .../views/make_payment_step_view.js | 3 +- .../sass/views/_decoupled-verification.scss | 36 +++++++++++++++++++ .../make_payment_step.underscore | 32 ++++++++--------- .../verify_student/pay_and_verify.html | 1 + 8 files changed, 76 insertions(+), 19 deletions(-) diff --git a/conf/locale/en/LC_MESSAGES/djangojs.po b/conf/locale/en/LC_MESSAGES/djangojs.po index fbece76c9c..730d93d20c 100644 --- a/conf/locale/en/LC_MESSAGES/djangojs.po +++ b/conf/locale/en/LC_MESSAGES/djangojs.po @@ -8808,3 +8808,19 @@ msgstr "" #: cms/templates/js/video/transcripts/messages/transcripts-use-existing.underscore msgid "Use Current Transcript" msgstr "" + +#: lms/templates/verify_student/make_payment_step.underscore:47 +msgid "" +"We ask you to activate your account to ensure it is really you creating the " +"account and to prevent fraud." +msgstr "" + +#: lms/templates/verify_student/make_payment_step.underscore:41 +msgid "" +"An email has been sent to {userEmail} with a link for you to activate your " +"account." +msgstr "" + +#: lms/templates/verify_student/make_payment_step.underscore:45 +msgid "Why activate?" +msgstr "" diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index 21715ba979..d5fbaa1ca5 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -418,6 +418,7 @@ class PayAndVerifyView(View): 'disable_courseware_js': True, 'display_steps': display_steps, 'is_active': json.dumps(request.user.is_active), + 'user_email': request.user.email, 'message_key': message, 'platform_name': settings.PLATFORM_NAME, 'processors': processors, diff --git a/lms/static/js/spec/verify_student/make_payment_step_view_spec.js b/lms/static/js/spec/verify_student/make_payment_step_view_spec.js index 31389ed5f3..211dfc76ab 100644 --- a/lms/static/js/spec/verify_student/make_payment_step_view_spec.js +++ b/lms/static/js/spec/verify_student/make_payment_step_view_spec.js @@ -142,6 +142,11 @@ define([ expectPaymentSubmitted( view, {foo: 'bar'} ); }); + it ('view containing user email', function() { + createView({userEmail: 'test@example.com', requirements: {isVisible:true}, isActive: false}); + expect($('p.instruction-info:contains("test@example.com")').length).toEqual(1); + }); + it( 'provides working payment buttons for a single processor', function() { createView({processors: ['cybersource']}); checkPaymentButtons( AjaxHelpers.requests(this), {cybersource: "Checkout"}); diff --git a/lms/static/js/verify_student/pay_and_verify.js b/lms/static/js/verify_student/pay_and_verify.js index 93f271400b..440337c4af 100644 --- a/lms/static/js/verify_student/pay_and_verify.js +++ b/lms/static/js/verify_student/pay_and_verify.js @@ -49,6 +49,7 @@ var edx = edx || {}; requirements: el.data('requirements'), courseKey: el.data('course-key'), courseName: el.data('course-name'), + userEmail: el.data('user-email'), hasVisibleReqs: _.some( el.data('requirements'), function( isVisible ) { return isVisible; } diff --git a/lms/static/js/verify_student/views/make_payment_step_view.js b/lms/static/js/verify_student/views/make_payment_step_view.js index fc809e6da9..65019c7adb 100644 --- a/lms/static/js/verify_student/views/make_payment_step_view.js +++ b/lms/static/js/verify_student/views/make_payment_step_view.js @@ -37,7 +37,8 @@ var edx = edx || {}; alreadyVerified: false, courseModeSlug: 'audit', verificationGoodUntil: '', - isABTesting: false + isABTesting: false, + userEmail: '' }; }, diff --git a/lms/static/sass/views/_decoupled-verification.scss b/lms/static/sass/views/_decoupled-verification.scss index 95d69833b9..2c4346a912 100644 --- a/lms/static/sass/views/_decoupled-verification.scss +++ b/lms/static/sass/views/_decoupled-verification.scss @@ -5,6 +5,20 @@ .title.center-col { padding: 0 calc( ( 100% - 750px ) / 2 ) 10px; } + h2 { + font-size: 16px; + font-weight: 600; + text-transform: unset; + color: #4a4a4a; + margin-bottom: 40px; + + .course-title { + display: block; + font-weight: 100; + font-size: 24px; + margin-top: 5px; + } + } } .instruction { @@ -13,6 +27,28 @@ margin-left: auto; margin-right: auto; } + .instruction-info { + font-size: 24px; + font-weight: 100; + color: #57595a; + margin-bottom: 30px; + + .fa-envelope-o { + color: #b92167; + font-size: 26px; + margin-right: 8px; + } + } + .activate { + font-size: 16px; + font-weight: 600; + color: #4a4a4a; + } + .activate-info { + font-size: 16px; + font-weight: 100; + color: #4a4a4a; + } } .payment-info { diff --git a/lms/templates/verify_student/make_payment_step.underscore b/lms/templates/verify_student/make_payment_step.underscore index 5f327d50c7..9d9b22228e 100644 --- a/lms/templates/verify_student/make_payment_step.underscore +++ b/lms/templates/verify_student/make_payment_step.underscore @@ -1,7 +1,7 @@
<% if ( !upgrade ) { %> -

+

<%= HtmlUtils.interpolateHtml( gettext( "You are enrolling in: {courseName}"), { courseName: HtmlUtils.joinHtml( @@ -27,16 +27,25 @@

<% } %> -
+
<% if ( _.some( requirements, function( isVisible ) { return isVisible; } ) ) { %> -

+

<% if ( verificationDeadline ) { %> <%- _.sprintf( gettext( "You can pay now even if you don't have the following items available, but you will need to have these by %(date)s to qualify to earn a Verified Certificate." ), { date: verificationDeadline } ) %> <% } else if ( !isActive ) { %> - <%- gettext( "You need to activate your account before you can enroll in courses. Check your inbox for an activation email. After you complete activation you can return and refresh this page." ) %> + + <%= HtmlUtils.interpolateHtml( + gettext( "An email has been sent to {userEmail} with a link for you to activate your account."), + {userEmail: userEmail} + ) + %> +

<%- gettext("Why activate?") %>

+
+ <%- gettext("We ask you to activate your account to ensure it is really you creating the account and to prevent fraud.") %> +
<% } else { %> <%- gettext( "You can pay now even if you don't have the following items available, but you will need to have these to qualify to earn a Verified Certificate." ) %> <% } %> @@ -47,20 +56,7 @@ <% if ( requirements['account-activation-required'] || requirements['photo-id-required'] || requirements['webcam-required']) { %>