From 16890041898dccdd96ec962a93090920d988a580 Mon Sep 17 00:00:00 2001 From: Andy Armstrong Date: Mon, 8 Jun 2015 13:58:13 -0400 Subject: [PATCH 1/4] Create a common paginated list view TNL-2384 Refactored Studio's PagingView to use RequireJS Text and moved it to common so that it can also be used by LMS. --- .../contentstore/views/component.py | 6 +- cms/djangoapps/contentstore/views/library.py | 4 +- cms/envs/common.py | 1 + cms/envs/devstack.py | 10 + cms/static/build.js | 4 +- cms/static/coffee/spec/main.coffee | 3 +- cms/static/coffee/spec/main_spec.coffee | 2 +- cms/static/coffee/spec/main_squire.coffee | 1 + .../coffee/spec/models/section_spec.coffee | 2 +- .../coffee/spec/views/assets_spec.coffee | 26 ++- .../coffee/spec/views/course_info_spec.coffee | 2 +- .../coffee/spec/views/textbook_spec.coffee | 2 +- .../coffee/spec/views/upload_spec.coffee | 2 +- cms/static/common | 1 + .../spec/views/certificate_details_spec.js | 4 +- .../spec/views/certificate_editor_spec.js | 4 +- .../spec/views/certificates_list_spec.js | 4 +- .../certificates/views/certificates_page.js | 3 +- cms/static/js/common_helpers | 1 - cms/static/js/factories/common_deps.js | 2 +- .../spec/factories/xblock_validation_spec.js | 2 +- .../js/spec/utils/drag_and_drop_spec.js | 2 +- .../spec/video/file_uploader_editor_spec.js | 2 +- .../js/spec/video/translations_editor_spec.js | 2 +- .../views/active_video_upload_list_spec.js | 2 +- cms/static/js/spec/views/assets_spec.js | 40 ++-- cms/static/js/spec/views/container_spec.js | 2 +- .../js/spec/views/group_configuration_spec.js | 2 +- cms/static/js/spec/views/license_spec.js | 2 +- .../js/spec/views/modals/edit_xblock_spec.js | 2 +- .../js/spec/views/paged_container_spec.js | 15 +- .../js/spec/views/pages/container_spec.js | 4 +- .../views/pages/container_subviews_spec.js | 4 +- .../spec/views/pages/course_outline_spec.js | 4 +- .../js/spec/views/pages/course_rerun_spec.js | 2 +- .../views/pages/group_configurations_spec.js | 2 +- cms/static/js/spec/views/pages/index_spec.js | 2 +- .../js/spec/views/pages/library_users_spec.js | 2 +- .../views/previous_video_upload_list_spec.js | 2 +- .../spec/views/previous_video_upload_spec.js | 2 +- .../js/spec/views/settings/main_spec.js | 2 +- cms/static/js/spec/views/unit_outline_spec.js | 2 +- .../js/spec/views/xblock_editor_spec.js | 2 +- cms/static/js/spec/views/xblock_spec.js | 2 +- .../views/xblock_string_field_editor_spec.js | 2 +- .../js/spec/views/xblock_validation_spec.js | 2 +- .../js/spec_helpers/assertion_helpers.js | 2 +- cms/static/js/spec_helpers/edit_helpers.js | 2 +- cms/static/js/spec_helpers/modal_helpers.js | 2 +- .../js/spec_helpers/validation_helpers.js | 2 +- cms/static/js/spec_helpers/view_helpers.js | 4 +- cms/static/js/views/assets.js | 173 ++++++++++-------- cms/static/js/views/paged_container.js | 3 +- cms/static/js_test.yml | 7 +- cms/static/js_test_squire.yml | 5 +- cms/static/require-config.js | 1 + cms/static/templates | 1 + cms/templates/asset_index.html | 2 +- cms/templates/container.html | 3 + .../mock-container-paged-xblock.underscore | 33 ---- .../mock-paged-container-xblock.underscore | 33 ---- cms/templates/library.html | 3 + .../discussion/discussion_spec_helper.coffee | 2 +- .../common/js/components}/views/paging.js | 8 +- .../js/components}/views/paging_footer.js | 0 .../js/components}/views/paging_header.js | 0 .../js/components}/views/paging_mixin.js | 0 .../js/spec_helpers/ajax_helpers.js | 0 .../js/spec_helpers/page_helpers.js | 0 .../js/spec_helpers/template_helpers.js | 0 .../components}/paging-footer.underscore | 0 .../components}/paging-header.underscore | 0 .../discussion/thread-show.underscore | 0 .../common/templates}/image-modal.underscore | 0 .../js/spec/common/components}/paging_spec.js | 6 +- common/static/js/vendor/requirejs/text.js | 14 +- common/static/js_test.yml | 2 +- common/static/templates/discussion | 1 - lms/envs/common.py | 3 +- lms/static/common | 1 + lms/static/js/common_helpers | 1 - lms/static/js/spec/ccx/schedule_spec.js | 2 +- lms/static/js/spec/dashboard/donation.js | 2 +- .../js/spec/discovery/discovery_spec.js | 4 +- .../js/spec/edxnotes/plugins/events_spec.js | 2 +- .../js/spec/edxnotes/views/note_item_spec.js | 4 +- .../spec/edxnotes/views/notes_factory_spec.js | 2 +- .../js/spec/edxnotes/views/notes_page_spec.js | 4 +- .../js/spec/edxnotes/views/search_box_spec.js | 2 +- .../js/spec/edxnotes/views/tab_item_spec.js | 2 +- .../js/spec/edxnotes/views/tab_view_spec.js | 2 +- .../views/tabs/course_structure_spec.js | 2 +- .../views/tabs/recent_activity_spec.js | 2 +- .../views/tabs/search_results_spec.js | 2 +- .../js/spec/edxnotes/views/tabs/tags_spec.js | 2 +- .../js/spec/edxnotes/views/tabs_list_spec.js | 2 +- .../views/toggle_notes_factory_spec.js | 2 +- .../js/spec/groups/views/cohorts_spec.js | 2 +- .../student_admin_spec.js | 2 +- lms/static/js/spec/search/search_spec.js | 2 +- .../js/spec/shoppingcart/shoppingcart_spec.js | 2 +- .../js/spec/student_account/access_spec.js | 4 +- .../account_settings_factory_spec.js | 2 +- .../account_settings_fields_helpers.js | 2 +- .../account_settings_fields_spec.js | 2 +- .../account_settings_view_spec.js | 2 +- .../spec/student_account/emailoptin_spec.js | 2 +- .../spec/student_account/enrollment_spec.js | 2 +- .../js/spec/student_account/login_spec.js | 4 +- .../student_account/password_reset_spec.js | 4 +- .../js/spec/student_account/register_spec.js | 4 +- .../spec/student_account/shoppingcart_spec.js | 2 +- .../learner_profile_factory_spec.js | 2 +- .../learner_profile_fields_spec.js | 2 +- .../learner_profile_view_spec.js | 2 +- .../spec/verify_student/image_input_spec.js | 4 +- .../make_payment_step_view_spec.js | 4 +- .../pay_and_verify_view_spec.js | 2 +- .../review_photos_step_view_spec.js | 4 +- .../verify_student/webcam_photo_view_spec.js | 4 +- lms/static/js/spec/views/fields_helpers.js | 2 +- lms/static/js/spec/views/fields_spec.js | 2 +- .../js/spec/views/file_uploader_spec.js | 4 +- lms/static/js/spec/views/notification_spec.js | 2 +- lms/static/js_test.yml | 3 +- .../courseware/courseware-chromeless.html | 2 +- lms/templates/courseware/courseware.html | 2 +- .../discussion/_underscore_templates.html | 2 +- .../studio_render_paged_children_view.html | 6 - 129 files changed, 292 insertions(+), 340 deletions(-) create mode 120000 cms/static/common delete mode 120000 cms/static/js/common_helpers create mode 120000 cms/static/templates rename {cms/static/js => common/static/common/js/components}/views/paging.js (95%) rename {cms/static/js => common/static/common/js/components}/views/paging_footer.js (100%) rename {cms/static/js => common/static/common/js/components}/views/paging_header.js (100%) rename {cms/static/js => common/static/common/js/components}/views/paging_mixin.js (100%) rename common/static/{ => common}/js/spec_helpers/ajax_helpers.js (100%) rename common/static/{ => common}/js/spec_helpers/page_helpers.js (100%) rename common/static/{ => common}/js/spec_helpers/template_helpers.js (100%) rename {cms/templates/js => common/static/common/templates/components}/paging-footer.underscore (100%) rename {cms/templates/js => common/static/common/templates/components}/paging-header.underscore (100%) rename common/{templates/js => static/common/templates}/discussion/thread-show.underscore (100%) rename common/{templates/js => static/common/templates}/image-modal.underscore (100%) rename {cms/static/js/spec/views => common/static/js/spec/common/components}/paging_spec.js (98%) delete mode 120000 common/static/templates/discussion create mode 120000 lms/static/common delete mode 120000 lms/static/js/common_helpers diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py index a3fadaad2a..cd670e8243 100644 --- a/cms/djangoapps/contentstore/views/component.py +++ b/cms/djangoapps/contentstore/views/component.py @@ -58,9 +58,9 @@ ADVANCED_COMPONENT_POLICY_KEY = 'advanced_modules' ADVANCED_PROBLEM_TYPES = settings.ADVANCED_PROBLEM_TYPES -CONTAINER_TEMPATES = [ +CONTAINER_TEMPLATES = [ "basic-modal", "modal-button", "edit-xblock-modal", - "editor-mode-button", "upload-dialog", "image-modal", + "editor-mode-button", "upload-dialog", "add-xblock-component", "add-xblock-component-button", "add-xblock-component-menu", "add-xblock-component-menu-problem", "xblock-string-field-editor", "publish-xblock", "publish-history", "unit-outline", "container-message", "license-selector", @@ -217,7 +217,7 @@ def container_handler(request, usage_key_string): 'xblock_info': xblock_info, 'draft_preview_link': preview_lms_link, 'published_preview_link': lms_link, - 'templates': CONTAINER_TEMPATES + 'templates': CONTAINER_TEMPLATES }) else: return HttpResponseBadRequest("Only supports HTML requests") diff --git a/cms/djangoapps/contentstore/views/library.py b/cms/djangoapps/contentstore/views/library.py index 7bb3cc1e1a..12987bfe0b 100644 --- a/cms/djangoapps/contentstore/views/library.py +++ b/cms/djangoapps/contentstore/views/library.py @@ -26,7 +26,7 @@ from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore from .user import user_with_role -from .component import get_component_templates, CONTAINER_TEMPATES +from .component import get_component_templates, CONTAINER_TEMPLATES from student.auth import ( STUDIO_VIEW_USERS, STUDIO_EDIT_ROLES, get_user_permissions, has_studio_read_access, has_studio_write_access ) @@ -197,7 +197,7 @@ def library_blocks_view(library, user, response_format): 'context_library': library, 'component_templates': json.dumps(component_templates), 'xblock_info': xblock_info, - 'templates': CONTAINER_TEMPATES, + 'templates': CONTAINER_TEMPLATES, }) diff --git a/cms/envs/common.py b/cms/envs/common.py index 04dfd04fdc..2ec4a0c15c 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -205,6 +205,7 @@ MAKO_TEMPLATES['main'] = [ COMMON_ROOT / 'templates', COMMON_ROOT / 'djangoapps' / 'pipeline_mako' / 'templates', COMMON_ROOT / 'djangoapps' / 'pipeline_js' / 'templates', + COMMON_ROOT / 'static', # required to statically include common Underscore templates ] for namespace, template_dirs in lms.envs.common.MAKO_TEMPLATES.iteritems(): diff --git a/cms/envs/devstack.py b/cms/envs/devstack.py index 0f0028d9a3..0260b5311f 100644 --- a/cms/envs/devstack.py +++ b/cms/envs/devstack.py @@ -30,6 +30,11 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' LMS_BASE = "localhost:8000" FEATURES['PREVIEW_LMS_BASE'] = "preview." + LMS_BASE +########################### PIPELINE ################################# + +# Skip RequireJS optimizer in development +STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage' + ############################# ADVANCED COMPONENTS ############################# # Make it easier to test advanced components in local dev @@ -92,6 +97,11 @@ FEATURES['ENABLE_COURSEWARE_INDEX'] = True FEATURES['ENABLE_LIBRARY_INDEX'] = True SEARCH_ENGINE = "search.elastic.ElasticSearchEngine" +################################# DJANGO-REQUIRE ############################### + +# Whether to run django-require in debug mode. +REQUIRE_DEBUG = DEBUG + ############################################################################### # See if the developer has any local overrides. try: diff --git a/cms/static/build.js b/cms/static/build.js index 6103b8afe7..bb890bee5c 100644 --- a/cms/static/build.js +++ b/cms/static/build.js @@ -118,7 +118,7 @@ * As of 1.0.3, this value can also be a string that is converted to a * RegExp via new RegExp(). */ - fileExclusionRegExp: /^\.|spec/, + fileExclusionRegExp: /^\.|spec|spec_helpers/, /** * Allow CSS optimizations. Allowed values: * - "standard": @import inlining and removal of comments, unnecessary @@ -153,6 +153,6 @@ * SILENT: 4 * Default is 0. */ - logLevel: 4 + logLevel: 1 }; } ()) diff --git a/cms/static/coffee/spec/main.coffee b/cms/static/coffee/spec/main.coffee index 6052f95412..14907cbc86 100644 --- a/cms/static/coffee/spec/main.coffee +++ b/cms/static/coffee/spec/main.coffee @@ -23,6 +23,7 @@ requirejs.config({ "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", + "text": "xmodule_js/common_static/js/vendor/requirejs/text", "underscore": "xmodule_js/common_static/js/vendor/underscore-min", "underscore.string": "xmodule_js/common_static/js/vendor/underscore.string.min", "backbone": "xmodule_js/common_static/js/vendor/backbone-min", @@ -240,13 +241,11 @@ define([ "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/paging_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/paging_spec", "js/spec/views/unit_outline_spec", "js/spec/views/xblock_spec", "js/spec/views/xblock_editor_spec", diff --git a/cms/static/coffee/spec/main_spec.coffee b/cms/static/coffee/spec/main_spec.coffee index db442b15ed..2de4869dbe 100644 --- a/cms/static/coffee/spec/main_spec.coffee +++ b/cms/static/coffee/spec/main_spec.coffee @@ -1,4 +1,4 @@ -require ["jquery", "backbone", "coffee/src/main", "js/common_helpers/ajax_helpers", "jasmine-stealth", "jquery.cookie"], +require ["jquery", "backbone", "coffee/src/main", "common/js/spec_helpers/ajax_helpers", "jasmine-stealth", "jquery.cookie"], ($, Backbone, main, AjaxHelpers) -> describe "CMS", -> it "should initialize URL", -> diff --git a/cms/static/coffee/spec/main_squire.coffee b/cms/static/coffee/spec/main_squire.coffee index 7698e8b34b..1feee91414 100644 --- a/cms/static/coffee/spec/main_squire.coffee +++ b/cms/static/coffee/spec/main_squire.coffee @@ -21,6 +21,7 @@ requirejs.config({ "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": "xmodule_js/common_static/js/vendor/underscore-min", "underscore.string": "xmodule_js/common_static/js/vendor/underscore.string.min", "backbone": "xmodule_js/common_static/js/vendor/backbone-min", diff --git a/cms/static/coffee/spec/models/section_spec.coffee b/cms/static/coffee/spec/models/section_spec.coffee index 491cb340ec..95d26e43d4 100644 --- a/cms/static/coffee/spec/models/section_spec.coffee +++ b/cms/static/coffee/spec/models/section_spec.coffee @@ -1,4 +1,4 @@ -define ["js/models/section", "js/common_helpers/ajax_helpers", "js/utils/module"], (Section, AjaxHelpers, ModuleUtils) -> +define ["js/models/section", "common/js/spec_helpers/ajax_helpers", "js/utils/module"], (Section, AjaxHelpers, ModuleUtils) -> describe "Section", -> describe "basic", -> beforeEach -> diff --git a/cms/static/coffee/spec/views/assets_spec.coffee b/cms/static/coffee/spec/views/assets_spec.coffee index 038ad63b73..72bccbe396 100644 --- a/cms/static/coffee/spec/views/assets_spec.coffee +++ b/cms/static/coffee/spec/views/assets_spec.coffee @@ -1,11 +1,9 @@ -define ["jquery", "jasmine", "js/common_helpers/ajax_helpers", "squire"], +define ["jquery", "jasmine", "common/js/spec_helpers/ajax_helpers", "squire"], ($, jasmine, AjaxHelpers, Squire) -> feedbackTpl = readFixtures('system-feedback.underscore') assetLibraryTpl = readFixtures('asset-library.underscore') assetTpl = readFixtures('asset.underscore') - pagingHeaderTpl = readFixtures('paging-header.underscore') - pagingFooterTpl = readFixtures('paging-footer.underscore') describe "Asset view", -> beforeEach -> @@ -141,8 +139,6 @@ define ["jquery", "jasmine", "js/common_helpers/ajax_helpers", "squire"], beforeEach -> setFixtures($(" diff --git a/cms/templates/container.html b/cms/templates/container.html index b93ada88c9..4f2cc15da9 100644 --- a/cms/templates/container.html +++ b/cms/templates/container.html @@ -24,6 +24,9 @@ from django.utils.translation import ugettext as _ <%static:include path="js/${template_name}.underscore" /> % endfor + diff --git a/cms/templates/js/mock/mock-container-paged-xblock.underscore b/cms/templates/js/mock/mock-container-paged-xblock.underscore index e3c1470558..78c26468d9 100644 --- a/cms/templates/js/mock/mock-container-paged-xblock.underscore +++ b/cms/templates/js/mock/mock-container-paged-xblock.underscore @@ -13,39 +13,6 @@
- - -
diff --git a/cms/templates/js/mock/mock-paged-container-xblock.underscore b/cms/templates/js/mock/mock-paged-container-xblock.underscore index e3c1470558..78c26468d9 100644 --- a/cms/templates/js/mock/mock-paged-container-xblock.underscore +++ b/cms/templates/js/mock/mock-paged-container-xblock.underscore @@ -13,39 +13,6 @@
- - -
diff --git a/cms/templates/library.html b/cms/templates/library.html index fd7b93b1ac..91a65d0d61 100644 --- a/cms/templates/library.html +++ b/cms/templates/library.html @@ -17,6 +17,9 @@ from django.utils.translation import ugettext as _ <%static:include path="js/${template_name}.underscore" /> % endfor + <%block name="requirejs"> diff --git a/common/static/coffee/spec/discussion/discussion_spec_helper.coffee b/common/static/coffee/spec/discussion/discussion_spec_helper.coffee index 629ee06457..8d094c49d0 100644 --- a/common/static/coffee/spec/discussion/discussion_spec_helper.coffee +++ b/common/static/coffee/spec/discussion/discussion_spec_helper.coffee @@ -38,7 +38,7 @@ class @DiscussionSpecHelper @setUnderscoreFixtures = -> for templateName in ['thread-show'] - templateFixture = readFixtures('templates/discussion/' + templateName + '.underscore') + templateFixture = readFixtures('common/templates/discussion/' + templateName + '.underscore') appendSetFixtures($(' % endfor <% diff --git a/lms/templates/courseware/courseware.html b/lms/templates/courseware/courseware.html index 966a712ae6..b953e86a76 100644 --- a/lms/templates/courseware/courseware.html +++ b/lms/templates/courseware/courseware.html @@ -22,7 +22,7 @@ ${page_title_breadcrumbs(course_name())} <%block name="header_extras"> % for template_name in ["image-modal"]: % endfor diff --git a/lms/templates/discussion/_underscore_templates.html b/lms/templates/discussion/_underscore_templates.html index f7ec63a655..cab9ef174c 100644 --- a/lms/templates/discussion/_underscore_templates.html +++ b/lms/templates/discussion/_underscore_templates.html @@ -50,7 +50,7 @@ from django_comment_client.permissions import has_permission % for template_name in ['thread-show']: % endfor diff --git a/lms/templates/studio_render_paged_children_view.html b/lms/templates/studio_render_paged_children_view.html index 7d6dff0d9a..46921168fc 100644 --- a/lms/templates/studio_render_paged_children_view.html +++ b/lms/templates/studio_render_paged_children_view.html @@ -2,12 +2,6 @@ <%namespace name='static' file='static_content.html'/> -% for template_name in ["paging-header", "paging-footer"]: - -% endfor -
Date: Fri, 12 Jun 2015 16:34:20 -0400 Subject: [PATCH 2/4] Convert to RequireJS text for templates --- .../js/components/views/paging_footer.js | 118 +++++----- .../js/components/views/paging_header.js | 210 +++++++++--------- 2 files changed, 164 insertions(+), 164 deletions(-) diff --git a/common/static/common/js/components/views/paging_footer.js b/common/static/common/js/components/views/paging_footer.js index a897e8275a..8700a66191 100644 --- a/common/static/common/js/components/views/paging_footer.js +++ b/common/static/common/js/components/views/paging_footer.js @@ -1,65 +1,65 @@ -define(["underscore", "js/views/baseview"], function(_, BaseView) { +define(["underscore", "backbone", "text!common/templates/components/paging-footer.underscore"], + function(_, Backbone, paging_footer_template) { - var PagingFooter = BaseView.extend({ - events : { - "click .next-page-link": "nextPage", - "click .previous-page-link": "previousPage", - "change .page-number-input": "changePage" - }, + var PagingFooter = Backbone.View.extend({ + events : { + "click .next-page-link": "nextPage", + "click .previous-page-link": "previousPage", + "change .page-number-input": "changePage" + }, - initialize: function(options) { - var view = options.view, - collection = view.collection; - this.view = view; - this.template = this.loadTemplate('paging-footer'); - collection.bind('add', _.bind(this.render, this)); - collection.bind('remove', _.bind(this.render, this)); - collection.bind('reset', _.bind(this.render, this)); - this.render(); - }, + initialize: function(options) { + var view = options.view, + collection = view.collection; + this.view = view; + collection.bind('add', _.bind(this.render, this)); + collection.bind('remove', _.bind(this.render, this)); + collection.bind('reset', _.bind(this.render, this)); + this.render(); + }, - render: function() { - var view = this.view, - collection = view.collection, - currentPage = collection.currentPage, - lastPage = collection.totalPages - 1; - this.$el.html(this.template({ - current_page: collection.currentPage, - total_pages: collection.totalPages - })); - this.$(".previous-page-link").toggleClass("is-disabled", currentPage === 0).attr('aria-disabled', currentPage === 0);; - this.$(".next-page-link").toggleClass("is-disabled", currentPage === lastPage).attr('aria-disabled', currentPage === lastPage); - return this; - }, + render: function() { + var view = this.view, + collection = view.collection, + currentPage = collection.currentPage, + lastPage = collection.totalPages - 1; + this.$el.html(_.template(paging_footer_template, { + current_page: collection.currentPage, + total_pages: collection.totalPages + })); + this.$(".previous-page-link").toggleClass("is-disabled", currentPage === 0).attr('aria-disabled', currentPage === 0);; + this.$(".next-page-link").toggleClass("is-disabled", currentPage === lastPage).attr('aria-disabled', currentPage === lastPage); + return this; + }, - changePage: function() { - var view = this.view, - collection = view.collection, - currentPage = collection.currentPage + 1, - pageInput = this.$("#page-number-input"), - pageNumber = parseInt(pageInput.val(), 10); - if (pageNumber > collection.totalPages) { - pageNumber = false; + changePage: function() { + var view = this.view, + collection = view.collection, + currentPage = collection.currentPage + 1, + pageInput = this.$("#page-number-input"), + pageNumber = parseInt(pageInput.val(), 10); + if (pageNumber > collection.totalPages) { + pageNumber = false; + } + if (pageNumber <= 0) { + pageNumber = false; + } + // If we still have a page number by this point, + // and it's not the current page, load it. + if (pageNumber && pageNumber !== currentPage) { + view.setPage(pageNumber - 1); + } + pageInput.val(""); // Clear the value as the label will show beneath it + }, + + nextPage: function() { + this.view.nextPage(); + }, + + previousPage: function() { + this.view.previousPage(); } - if (pageNumber <= 0) { - pageNumber = false; - } - // If we still have a page number by this point, - // and it's not the current page, load it. - if (pageNumber && pageNumber !== currentPage) { - view.setPage(pageNumber - 1); - } - pageInput.val(""); // Clear the value as the label will show beneath it - }, + }); - nextPage: function() { - this.view.nextPage(); - }, - - previousPage: function() { - this.view.previousPage(); - } - }); - - return PagingFooter; -}); // end define(); + return PagingFooter; + }); // end define(); diff --git a/common/static/common/js/components/views/paging_header.js b/common/static/common/js/components/views/paging_header.js index 204270dc98..dc544e0298 100644 --- a/common/static/common/js/components/views/paging_header.js +++ b/common/static/common/js/components/views/paging_header.js @@ -1,113 +1,113 @@ -define(["underscore", "gettext", "js/views/baseview"], function(_, gettext, BaseView) { +define(["underscore", "backbone", "gettext", "text!common/templates/components/paging-header.underscore"], + function(_, Backbone, gettext, paging_header_template) { - var PagingHeader = BaseView.extend({ - events : { - "click .next-page-link": "nextPage", - "click .previous-page-link": "previousPage" - }, + var PagingHeader = Backbone.View.extend({ + events : { + "click .next-page-link": "nextPage", + "click .previous-page-link": "previousPage" + }, - initialize: function(options) { - var view = options.view, - collection = view.collection; - this.view = view; - this.template = this.loadTemplate('paging-header'); - collection.bind('add', _.bind(this.render, this)); - collection.bind('remove', _.bind(this.render, this)); - collection.bind('reset', _.bind(this.render, this)); - }, + initialize: function(options) { + var view = options.view, + collection = view.collection; + this.view = view; + collection.bind('add', _.bind(this.render, this)); + collection.bind('remove', _.bind(this.render, this)); + collection.bind('reset', _.bind(this.render, this)); + }, - render: function() { - var view = this.view, - collection = view.collection, - currentPage = collection.currentPage, - lastPage = collection.totalPages - 1, - messageHtml = this.messageHtml(); - this.$el.html(this.template({ - messageHtml: messageHtml - })); - this.$(".previous-page-link").toggleClass("is-disabled", currentPage === 0).attr('aria-disabled', currentPage === 0); - this.$(".next-page-link").toggleClass("is-disabled", currentPage === lastPage).attr('aria-disabled', currentPage === lastPage); - return this; - }, + render: function() { + var view = this.view, + collection = view.collection, + currentPage = collection.currentPage, + lastPage = collection.totalPages - 1, + messageHtml = this.messageHtml(); + this.$el.html(_.template(paging_header_template, { + messageHtml: messageHtml + })); + this.$(".previous-page-link").toggleClass("is-disabled", currentPage === 0).attr('aria-disabled', currentPage === 0); + this.$(".next-page-link").toggleClass("is-disabled", currentPage === lastPage).attr('aria-disabled', currentPage === lastPage); + return this; + }, - messageHtml: function() { - var message = ''; - var asset_type = false; - if (this.view.collection.assetType) { - if (this.view.collection.sortDirection === 'asc') { - // Translators: sample result: - // "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added ascending" - message = gettext('Showing %(current_item_range)s out of %(total_items_count)s, filtered by %(asset_type)s, sorted by %(sort_name)s ascending'); - } else { - // Translators: sample result: - // "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added descending" - message = gettext('Showing %(current_item_range)s out of %(total_items_count)s, filtered by %(asset_type)s, sorted by %(sort_name)s descending'); + messageHtml: function() { + var message = ''; + var asset_type = false; + if (this.view.collection.assetType) { + if (this.view.collection.sortDirection === 'asc') { + // Translators: sample result: + // "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added ascending" + message = gettext('Showing %(current_item_range)s out of %(total_items_count)s, filtered by %(asset_type)s, sorted by %(sort_name)s ascending'); + } else { + // Translators: sample result: + // "Showing 0-9 out of 25 total, filtered by Images, sorted by Date Added descending" + message = gettext('Showing %(current_item_range)s out of %(total_items_count)s, filtered by %(asset_type)s, sorted by %(sort_name)s descending'); + } + asset_type = this.filterNameLabel(); } - asset_type = this.filterNameLabel(); - } - else { - if (this.view.collection.sortDirection === 'asc') { - // Translators: sample result: - // "Showing 0-9 out of 25 total, sorted by Date Added ascending" - message = gettext('Showing %(current_item_range)s out of %(total_items_count)s, sorted by %(sort_name)s ascending'); - } else { - // Translators: sample result: - // "Showing 0-9 out of 25 total, sorted by Date Added descending" - message = gettext('Showing %(current_item_range)s out of %(total_items_count)s, sorted by %(sort_name)s descending'); + else { + if (this.view.collection.sortDirection === 'asc') { + // Translators: sample result: + // "Showing 0-9 out of 25 total, sorted by Date Added ascending" + message = gettext('Showing %(current_item_range)s out of %(total_items_count)s, sorted by %(sort_name)s ascending'); + } else { + // Translators: sample result: + // "Showing 0-9 out of 25 total, sorted by Date Added descending" + message = gettext('Showing %(current_item_range)s out of %(total_items_count)s, sorted by %(sort_name)s descending'); + } } + + return '

' + interpolate(message, { + current_item_range: this.currentItemRangeLabel(), + total_items_count: this.totalItemsCountLabel(), + asset_type: asset_type, + sort_name: this.sortNameLabel() + }, true) + "

"; + }, + + currentItemRangeLabel: function() { + var view = this.view, + collection = view.collection, + start = collection.start, + count = collection.size(), + end = start + count; + return interpolate('%(start)s-%(end)s', { + start: Math.min(start + 1, end), + end: end + }, true); + }, + + totalItemsCountLabel: function() { + var totalItemsLabel; + // Translators: turns into "25 total" to be used in other sentences, e.g. "Showing 0-9 out of 25 total". + totalItemsLabel = interpolate(gettext('%(total_items)s total'), { + total_items: this.view.collection.totalCount + }, true); + return interpolate('%(total_items_label)s', { + total_items_label: totalItemsLabel + }, true); + }, + + sortNameLabel: function() { + return interpolate('%(sort_name)s', { + sort_name: this.view.sortDisplayName() + }, true); + }, + + filterNameLabel: function() { + return interpolate('%(filter_name)s', { + filter_name: this.view.filterDisplayName() + }, true); + }, + + nextPage: function() { + this.view.nextPage(); + }, + + previousPage: function() { + this.view.previousPage(); } + }); - return '

' + interpolate(message, { - current_item_range: this.currentItemRangeLabel(), - total_items_count: this.totalItemsCountLabel(), - asset_type: asset_type, - sort_name: this.sortNameLabel() - }, true) + "

"; - }, - - currentItemRangeLabel: function() { - var view = this.view, - collection = view.collection, - start = collection.start, - count = collection.size(), - end = start + count; - return interpolate('%(start)s-%(end)s', { - start: Math.min(start + 1, end), - end: end - }, true); - }, - - totalItemsCountLabel: function() { - var totalItemsLabel; - // Translators: turns into "25 total" to be used in other sentences, e.g. "Showing 0-9 out of 25 total". - totalItemsLabel = interpolate(gettext('%(total_items)s total'), { - total_items: this.view.collection.totalCount - }, true); - return interpolate('%(total_items_label)s', { - total_items_label: totalItemsLabel - }, true); - }, - - sortNameLabel: function() { - return interpolate('%(sort_name)s', { - sort_name: this.view.sortDisplayName() - }, true); - }, - - filterNameLabel: function() { - return interpolate('%(filter_name)s', { - filter_name: this.view.filterDisplayName() - }, true); - }, - - nextPage: function() { - this.view.nextPage(); - }, - - previousPage: function() { - this.view.previousPage(); - } - }); - - return PagingHeader; -}); // end define(); + return PagingHeader; + }); // end define(); From 4c39132f703d0fe8934d6d2adfe570f2f635418e Mon Sep 17 00:00:00 2001 From: cahrens Date: Fri, 12 Jun 2015 11:32:00 -0400 Subject: [PATCH 3/4] Correct issue for RequireJS optimizer. --- common/static/js/vendor/requirejs/text.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/common/static/js/vendor/requirejs/text.js b/common/static/js/vendor/requirejs/text.js index 1430c43135..3d6576d525 100644 --- a/common/static/js/vendor/requirejs/text.js +++ b/common/static/js/vendor/requirejs/text.js @@ -8,9 +8,6 @@ define, window, process, Packages, java, location, Components, FileUtils */ -// Added by edX: we namespace requirejs and its associated functions. -var namespaced_define = define !== undefined ? define : RequireJS.define; - var requirejs_text_function = function (module) { 'use strict'; @@ -210,7 +207,7 @@ var requirejs_text_function = function (module) { if (buildMap.hasOwnProperty(moduleName)) { var content = text.jsEscape(buildMap[moduleName]); write.asModule(pluginName + "!" + moduleName, - "namespaced_define(function () { return '" + + "define(function () { return '" + content + "';});\n"); } From 5fbad148c9caca4fefb9e3a462649fb20cccd8aa Mon Sep 17 00:00:00 2001 From: cahrens Date: Fri, 12 Jun 2015 14:18:05 -0400 Subject: [PATCH 4/4] Jasmine test runner for files in common using RequireJS. --- .../js/spec/components/paging_collection.js | 38 +++++ .../js/spec}/components/paging_spec.js | 142 ++++++++------- common/static/js/spec/main_requirejs.js | 161 ++++++++++++++++++ common/static/js_test_requirejs.yml | 76 +++++++++ pavelib/utils/envs.py | 2 + 5 files changed, 344 insertions(+), 75 deletions(-) create mode 100644 common/static/common/js/spec/components/paging_collection.js rename common/static/{js/spec/common => common/js/spec}/components/paging_spec.js (85%) create mode 100644 common/static/js/spec/main_requirejs.js create mode 100644 common/static/js_test_requirejs.yml diff --git a/common/static/common/js/spec/components/paging_collection.js b/common/static/common/js/spec/components/paging_collection.js new file mode 100644 index 0000000000..b83f4f2d86 --- /dev/null +++ b/common/static/common/js/spec/components/paging_collection.js @@ -0,0 +1,38 @@ +define(["backbone.paginator", "backbone"], function(BackbonePaginator, Backbone) { + // This code was adapted from collections/asset.js. + var PagingCollection = BackbonePaginator.requestPager.extend({ + model : Backbone.Model, + paginator_core: { + type: 'GET', + accepts: 'application/json', + dataType: 'json', + url: function() { return this.url; } + }, + paginator_ui: { + firstPage: 0, + currentPage: 0, + perPage: 50 + }, + server_api: { + 'page': function() { return this.currentPage; }, + 'page_size': function() { return this.perPage; }, + 'sort': function() { return this.sortField; }, + 'direction': function() { return this.sortDirection; }, + 'format': 'json' + }, + + parse: function(response) { + var totalCount = response.totalCount, + start = response.start, + currentPage = response.page, + pageSize = response.pageSize, + totalPages = Math.ceil(totalCount / pageSize); + this.totalCount = totalCount; + this.totalPages = Math.max(totalPages, 1); // Treat an empty collection as having 1 page... + this.currentPage = currentPage; + this.start = start; + return response.items; + } + }); + return PagingCollection; +}); diff --git a/common/static/js/spec/common/components/paging_spec.js b/common/static/common/js/spec/components/paging_spec.js similarity index 85% rename from common/static/js/spec/common/components/paging_spec.js rename to common/static/common/js/spec/components/paging_spec.js index c633aaf967..8355adadde 100644 --- a/common/static/js/spec/common/components/paging_spec.js +++ b/common/static/common/js/spec/components/paging_spec.js @@ -1,10 +1,10 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", - "js/views/paging", "js/views/paging_header", "js/views/paging_footer", - "js/models/asset", "js/collections/asset" ], - function ($, AjaxHelpers, URI, PagingView, PagingHeader, PagingFooter, AssetModel, AssetCollection) { + "common/js/components/views/paging", "common/js/components/views/paging_header", + "common/js/components/views/paging_footer", "common/js/spec/components/paging_collection"], + function ($, AjaxHelpers, URI, PagingView, PagingHeader, PagingFooter, PagingCollection) { - var createMockAsset = function(index) { - var id = 'asset_' + index; + var createPageableItem = function(index) { + var id = 'item_' + index; return { id: id, display_name: id, @@ -13,10 +13,10 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", }; var mockFirstPage = { - assets: [ - createMockAsset(1), - createMockAsset(2), - createMockAsset(3) + items: [ + createPageableItem(1), + createPageableItem(2), + createPageableItem(3) ], pageSize: 3, totalCount: 4, @@ -25,8 +25,8 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", end: 2 }; var mockSecondPage = { - assets: [ - createMockAsset(4) + items: [ + createPageableItem(4) ], pageSize: 3, totalCount: 4, @@ -35,7 +35,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", end: 4 }; var mockEmptyPage = { - assets: [], + items: [], pageSize: 3, totalCount: 0, page: 0, @@ -43,7 +43,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", end: 0 }; - var respondWithMockAssets = function(requests) { + var respondWithMockItems = function(requests) { var requestIndex = requests.length - 1; var request = requests[requestIndex]; var url = new URI(request.url); @@ -58,9 +58,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", initialize : function() { this.registerSortableColumn('name-col', 'Name', 'name', 'asc'); this.registerSortableColumn('date-col', 'Date', 'date', 'desc'); - this.registerFilterableColumn('js-asset-type-col', gettext('Type'), 'asset_type'); this.setInitialSortColumn('date-col'); - this.setInitialFilterColumn('js-asset-type-col'); } }); @@ -68,30 +66,25 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", var pagingView; beforeEach(function () { - var assets = new AssetCollection(); - assets.url = "assets_url"; - var feedbackTpl = readFixtures('system-feedback.underscore'); - setFixtures($("