From b31ba9d041062e35d2a72295bf71e600c94355aa Mon Sep 17 00:00:00 2001 From: Ehtesham Date: Mon, 2 May 2016 21:22:07 +0500 Subject: [PATCH] upgrade Pagingcollection to edx-ui-toolkit's PagingCollection --- cms/static/cms/js/require-config.js | 4 +- cms/static/coffee/spec/main.coffee | 4 +- cms/static/coffee/spec/main_squire.coffee | 4 +- .../coffee/spec/views/assets_spec.coffee | 6 +- cms/static/js/collections/asset.js | 101 +++---- cms/static/js/spec/views/assets_spec.js | 31 +- .../js/spec/views/paged_container_spec.js | 2 +- cms/static/js/spec/views/paging_spec.js | 57 ++-- cms/static/js/views/assets.js | 81 ++++-- cms/static/js/views/paged_container.js | 28 +- cms/static/js/views/paging.js | 7 +- cms/static/js/views/paging_header.js | 111 ++++--- cms/templates/js/paging-header.underscore | 2 +- .../collections/paging_collection.js | 273 ------------------ .../js/components/views/paginated_view.js | 8 +- .../js/components/views/paging_footer.js | 32 +- .../js/components/views/paging_header.js | 46 ++- .../js/components/views/search_field.js | 26 +- .../js/spec/components/paginated_view_spec.js | 67 +++-- .../spec/components/paging_collection_spec.js | 256 ---------------- .../js/spec/components/paging_footer_spec.js | 21 +- .../js/spec/components/paging_header_spec.js | 6 +- .../js/spec/components/search_field_spec.js | 65 +++-- .../static/common/js/spec/main_requirejs.js | 5 +- .../components/paging-header.underscore | 6 +- .../components/search-field.underscore | 8 +- .../js/vendor/backbone.paginator.min.js | 4 - .../teams/static/teams/js/collections/base.js | 37 ++- .../static/teams/js/collections/my_teams.js | 21 +- .../teams/static/teams/js/collections/team.js | 49 +++- .../static/teams/js/collections/topic.js | 32 +- .../spec/collections/topic_collection_spec.js | 2 +- .../teams/js/spec/views/my_teams_spec.js | 3 +- .../teams/js/spec/views/teams_tab_spec.js | 4 +- .../js/spec_helpers/team_spec_helpers.js | 7 +- .../static/teams/js/views/team_profile.js | 53 ++-- .../teams/static/teams/js/views/teams.js | 2 +- .../teams/static/teams/js/views/teams_tab.js | 65 ++--- .../teams/static/teams/js/views/topics.js | 4 +- .../teams/templates/team-profile.underscore | 10 +- .../js/bookmarks/collections/bookmarks.js | 33 +-- .../js/bookmarks/views/bookmarks_list.js | 11 +- .../bookmarks/views/bookmarks_list_button.js | 5 +- lms/static/js/edxnotes/collections/notes.js | 18 +- lms/static/js/edxnotes/views/search_box.js | 44 +-- lms/static/js/edxnotes/views/tab_view.js | 16 +- .../js/edxnotes/views/tabs/search_results.js | 2 +- .../courseware/bookmarks_list_view_spec.js | 7 +- .../js/spec/edxnotes/views/search_box_spec.js | 13 +- .../js/spec/edxnotes/views/tab_view_spec.js | 18 +- .../views/tabs/recent_activity_spec.js | 12 +- lms/static/js/spec/main.js | 7 +- .../badge_list_container_spec.js | 36 ++- .../student_profile/badge_list_view_spec.js | 11 +- .../learner_profile_factory_spec.js | 1 - .../learner_profile_view_spec.js | 16 +- .../views/badge_list_container.js | 20 +- .../student_profile/views/badge_list_view.js | 49 +++- .../views/learner_profile_factory.js | 21 +- lms/static/lms/js/require-config.js | 4 +- package.json | 2 +- pavelib/assets.py | 1 + 62 files changed, 809 insertions(+), 1088 deletions(-) delete mode 100644 common/static/common/js/components/collections/paging_collection.js delete mode 100644 common/static/common/js/spec/components/paging_collection_spec.js delete mode 100644 common/static/js/vendor/backbone.paginator.min.js diff --git a/cms/static/cms/js/require-config.js b/cms/static/cms/js/require-config.js index b5f4cf3955..70e8d61e0b 100644 --- a/cms/static/cms/js/require-config.js +++ b/cms/static/cms/js/require-config.js @@ -56,7 +56,7 @@ "backbone": "common/js/vendor/backbone", "backbone-relational" : "js/vendor/backbone-relational.min", "backbone.associations": "js/vendor/backbone-associations-min", - "backbone.paginator": "js/vendor/backbone.paginator.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", @@ -188,7 +188,7 @@ }, "backbone.paginator": { deps: ["backbone"], - exports: "Backbone.Paginator" + exports: "Backbone.PageableCollection" }, "youtube": { exports: "YT" diff --git a/cms/static/coffee/spec/main.coffee b/cms/static/coffee/spec/main.coffee index d9c3f91265..3685cf47ac 100644 --- a/cms/static/coffee/spec/main.coffee +++ b/cms/static/coffee/spec/main.coffee @@ -32,7 +32,7 @@ requirejs.config({ "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": "xmodule_js/common_static/js/vendor/backbone.paginator.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", @@ -141,7 +141,7 @@ requirejs.config({ }, "backbone.paginator": { deps: ["backbone"], - exports: "Backbone.Paginator" + exports: "Backbone.PageableCollection" }, "backbone-relational": { deps: ["backbone"], diff --git a/cms/static/coffee/spec/main_squire.coffee b/cms/static/coffee/spec/main_squire.coffee index 5bea6ba849..3743e9602d 100644 --- a/cms/static/coffee/spec/main_squire.coffee +++ b/cms/static/coffee/spec/main_squire.coffee @@ -29,7 +29,7 @@ requirejs.config({ "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": "xmodule_js/common_static/js/vendor/backbone.paginator.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", @@ -124,7 +124,7 @@ requirejs.config({ }, "backbone.paginator": { deps: ["backbone"], - exports: "Backbone.Paginator" + exports: "Backbone.PageableCollection" }, "youtube": { exports: "YT" diff --git a/cms/static/coffee/spec/views/assets_spec.coffee b/cms/static/coffee/spec/views/assets_spec.coffee index 012539ac7c..eea73055c5 100644 --- a/cms/static/coffee/spec/views/assets_spec.coffee +++ b/cms/static/coffee/spec/views/assets_spec.coffee @@ -230,7 +230,7 @@ define ["jquery", "common/js/spec_helpers/ajax_helpers", "squire"], describe "Basic", -> # Separate setup method to work-around mis-parenting of beforeEach methods setup = (requests) -> - @view.pagingView.setPage(0) + @view.pagingView.setPage(1) AjaxHelpers.respondWithJson(requests, @mockAssetsResponse) $.fn.fileupload = -> @@ -274,7 +274,7 @@ define ["jquery", "common/js/spec_helpers/ajax_helpers", "squire"], {view: @view, requests: requests} = @createAssetsView(this) appendSetFixtures('
') expect($('.ui-loading').is(':visible')).toBe(true) - @view.pagingView.setPage(0) + @view.pagingView.setPage(1) AjaxHelpers.respondWithError(requests) expect($('.ui-loading').is(':visible')).toBe(false) @@ -323,7 +323,7 @@ define ["jquery", "common/js/spec_helpers/ajax_helpers", "squire"], describe "Sorting", -> # Separate setup method to work-around mis-parenting of beforeEach methods setup = (requests) -> - @view.pagingView.setPage(0) + @view.pagingView.setPage(1) AjaxHelpers.respondWithJson(requests, @mockAssetsResponse) it "should have the correct default sort order", -> diff --git a/cms/static/js/collections/asset.js b/cms/static/js/collections/asset.js index 04320b33b1..7e31a3c4f7 100644 --- a/cms/static/js/collections/asset.js +++ b/cms/static/js/collections/asset.js @@ -1,77 +1,50 @@ -define(["backbone.paginator", "js/models/asset"], function(BackbonePaginator, AssetModel) { - var AssetCollection = BackbonePaginator.requestPager.extend({ +define([ + "underscore", + "edx-ui-toolkit/js/pagination/paging-collection", + "js/models/asset" +], function(_, PagingCollection, AssetModel) { + 'use strict'; + + var AssetCollection = PagingCollection.extend({ assetType: '', model : AssetModel, - paginator_core: { - type: 'GET', - accepts: 'application/json', - dataType: 'json', - url: function() { return this.url; } - }, - paginator_ui: { + + state: { 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; }, - 'asset_type': function() { return this.assetType; }, - 'format': 'json' + pageSize: 50, + sortKey: 'sort', + order: null, + currentPage: null, + totalRecords: null, + totalCount: null }, - 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.assets; + queryParams: { + currentPage: 'page', + pageSize: 'page_size', + sortKey: 'sort', + order: 'direction', + directions: { + asc: 'asc', + desc: 'desc' + }, + asset_type: function() { return this.assetType; } }, - setPage: function (page) { - var oldPage = this.currentPage, - self = this; - this.goTo(page - 1, { - reset: true, - success: function () { - self.trigger('page_changed'); - }, - error: function () { - self.currentPage = oldPage; - } - }); + parse: function(response, options) { + response.results = response.assets; + delete response.assets; + return PagingCollection.prototype.parse.call(this, response, options); }, - nextPage: function () { - if (this.currentPage < this.totalPages - 1) { - this.setPage(this.getPage() + 1); - } - }, - - previousPage: function () { - if (this.currentPage > 0) { - this.setPage(this.getPage() - 1); - } - }, - - getPage: function () { - return this.currentPage + 1; - }, - - hasPreviousPage: function () { - return this.currentPage > 0; - }, - - hasNextPage: function () { - return this.currentPage < this.totalPages - 1; + /* jshint unused:false */ + parseState: function (response, queryParams, state, options) { + return { + totalRecords: response[0].totalCount, + totalPages: Math.ceil(response[0].totalCount / response[0].pageSize) + }; } }); + return AssetCollection; }); diff --git a/cms/static/js/spec/views/assets_spec.js b/cms/static/js/spec/views/assets_spec.js index 921c2b77cb..a72379b965 100644 --- a/cms/static/js/spec/views/assets_spec.js +++ b/cms/static/js/spec/views/assets_spec.js @@ -18,7 +18,13 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/asset spyOn($.fn, "fileupload").and.returnValue(""); - var collection = new AssetCollection(); + var TestAssetsCollection = AssetCollection.extend({ + state: { + firstPage: 0, + pageSize: 2 + } + }); + var collection = new TestAssetsCollection(); collection.url = "assets-url"; assetsView = new AssetsView({ collection: collection, @@ -43,7 +49,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/asset start: 0, end: 0, page: 0, - pageSize: 5, + pageSize: 2, totalCount: 0 }; @@ -134,11 +140,10 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/asset var setup; setup = function(responseData) { var requests = AjaxHelpers.requests(this); - assetsView.pagingView.setPage(0); + assetsView.pagingView.setPage(1); if (!responseData){ AjaxHelpers.respondWithJson(requests, mockEmptyAssetsResponse); - } - else{ + } else { AjaxHelpers.respondWithJson(requests, responseData); } return requests; @@ -184,7 +189,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/asset spyOn(assetsView, "addAsset").and.callFake(function () { assetsView.collection.add(mockAssetUploadResponse.asset); assetsView.pagingView.renderPageItems(); - assetsView.pagingView.setPage(0); + assetsView.pagingView.setPage(1); }); $('a:contains("Upload your first asset")').click(); @@ -269,7 +274,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/asset var requests = AjaxHelpers.requests(this); $.each(assetsView.pagingView.filterableColumns, function(columnID, columnData){ var $typeColumn = $('#' + columnID); - assetsView.pagingView.setPage(0); + assetsView.pagingView.setPage(1); respondWithMockAssets(requests); var assetsNumber = assetsView.collection.length; assetsView._toggleFilterColumn('Images', 'Images'); @@ -302,7 +307,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/asset assetsView.pagingView.registerSortableColumn('name-col', 'Name Column', 'nameField', 'asc'); assetsView.pagingView.registerFilterableColumn('js-asset-type-col', gettext('Type'), 'asset_type'); assetsView.pagingView.setInitialSortColumn('name-col'); - assetsView.pagingView.setPage(0); + assetsView.pagingView.setPage(1); respondWithMockAssets(requests); var sortInfo = assetsView.pagingView.sortableColumnInfo('name-col'); expect(sortInfo.defaultSortDirection).toBe('asc'); @@ -318,7 +323,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/asset expect(assetsView).toBeDefined(); var requests = AjaxHelpers.requests(this); $.each(assetsView.pagingView.filterableColumns, function(columnID, columnData) { - assetsView.pagingView.setPage(0); + assetsView.pagingView.setPage(1); respondWithMockAssets(requests); var $typeColumn = $('#' + columnID); expect($typeColumn).toBeVisible(); @@ -410,7 +415,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/asset it('can move forward a page using the next page button', function () { var requests = AjaxHelpers.requests(this); - assetsView.pagingView.setPage(0); + assetsView.pagingView.setPage(1); AjaxHelpers.respondWithJson(requests, firstPageAssets); expect(assetsView.pagingView.pagingFooter).toBeDefined(); expect(assetsView.pagingView.pagingFooter.$('button.next-page-link')) @@ -423,7 +428,7 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/asset it('can move back a page using the previous page button', function () { var requests = AjaxHelpers.requests(this); - assetsView.pagingView.setPage(1); + assetsView.pagingView.setPage(2); AjaxHelpers.respondWithJson(requests, secondPageAssets); expect(assetsView.pagingView.pagingFooter).toBeDefined(); expect(assetsView.pagingView.pagingFooter.$('button.previous-page-link')) @@ -436,12 +441,12 @@ define([ "jquery", "common/js/spec_helpers/ajax_helpers", "URI", "js/views/asset it('can set the current page using the page number input', function () { var requests = AjaxHelpers.requests(this); - assetsView.pagingView.setPage(0); + assetsView.pagingView.setPage(1); AjaxHelpers.respondWithJson(requests, firstPageAssets); assetsView.pagingView.pagingFooter.$('#page-number-input').val('2'); assetsView.pagingView.pagingFooter.$('#page-number-input').trigger('change'); AjaxHelpers.respondWithJson(requests, secondPageAssets); - expect(assetsView.collection.currentPage).toBe(1); + expect(assetsView.collection.getPageNumber()).toBe(2); expect(assetsView.pagingView.pagingFooter.$('button.previous-page-link')) .not.toHaveClass('is-disabled'); }); diff --git a/cms/static/js/spec/views/paged_container_spec.js b/cms/static/js/spec/views/paged_container_spec.js index 282ae3358b..653e283fbb 100644 --- a/cms/static/js/spec/views/paged_container_spec.js +++ b/cms/static/js/spec/views/paged_container_spec.js @@ -81,7 +81,7 @@ define(["jquery", "underscore", "common/js/spec_helpers/ajax_helpers", "URI", "j }); describe("Container", function () { - describe("rendering", function(){ + describe("rendering", function() { it('should set show_previews', function() { var requests = AjaxHelpers.requests(this); diff --git a/cms/static/js/spec/views/paging_spec.js b/cms/static/js/spec/views/paging_spec.js index 19e1dfedec..8e5c42d37d 100644 --- a/cms/static/js/spec/views/paging_spec.js +++ b/cms/static/js/spec/views/paging_spec.js @@ -1,11 +1,11 @@ define([ "jquery", - "common/js/spec_helpers/ajax_helpers", "URI", + "common/js/spec_helpers/ajax_helpers", + "edx-ui-toolkit/js/pagination/paging-collection", "js/views/paging", - "js/views/paging_header", - "common/js/components/collections/paging_collection" -], function ($, AjaxHelpers, URI, PagingView, PagingHeader, PagingCollection) { + "js/views/paging_header" +], function ($, URI, AjaxHelpers, PagingCollection, PagingView, PagingHeader) { var createPageableItem = function(index) { var id = 'item_' + index; @@ -24,7 +24,6 @@ define([ ], num_pages: 2, page_size: 3, - current_page: 0, count: 4, page: 0, start: 0 @@ -35,16 +34,14 @@ define([ ], num_pages: 2, page_size: 3, - current_page: 1, - count: 4, page: 1, + count: 4, start: 3 }; var mockEmptyPage = { results: [], num_pages: 1, page_size: 3, - current_page: 0, count: 0, page: 0, start: 0 @@ -69,11 +66,18 @@ define([ }); describe("Paging", function() { - var pagingView; + var pagingView, + TestPagingCollection = PagingCollection.extend({ + state: { + firstPage: 0, + currentPage: null, + pageSize: 3 + } + }); beforeEach(function () { - var collection = new PagingCollection(); - collection.isZeroIndexed = true; + var collection = new TestPagingCollection(); + collection.url = '/dummy/'; pagingView = new MockPagingView({collection: collection}); }); @@ -83,10 +87,10 @@ define([ var requests = AjaxHelpers.requests(this); pagingView.setPage(1); respondWithMockItems(requests); - expect(pagingView.collection.currentPage).toBe(0); + expect(pagingView.collection.getPageNumber()).toBe(1); pagingView.setPage(2); respondWithMockItems(requests); - expect(pagingView.collection.currentPage).toBe(1); + expect(pagingView.collection.getPageNumber()).toBe(2); }); it('should not change page after a server error', function () { @@ -95,7 +99,9 @@ define([ respondWithMockItems(requests); pagingView.setPage(2); requests[1].respond(500); - expect(pagingView.collection.currentPage).toBe(0); + + /* PagingCollection sets the currentPage to the old page in case of failure */ + expect(pagingView.collection.getPageNumber()).toBe(1); }); }); @@ -106,7 +112,7 @@ define([ respondWithMockItems(requests); pagingView.nextPage(); requests[1].respond(500); - expect(pagingView.collection.currentPage).toBe(0); + expect(pagingView.collection.getPageNumber()).toBe(1); }); it('can move to the next page', function () { @@ -115,7 +121,9 @@ define([ respondWithMockItems(requests); pagingView.nextPage(); respondWithMockItems(requests); - expect(pagingView.collection.currentPage).toBe(1); + + /* PagingCollection now returns the normalized page number; adds one if zero indexed */ + expect(pagingView.collection.getPageNumber()).toBe(2); }); it('can not move forward from the final page', function () { @@ -128,14 +136,13 @@ define([ }); describe("previousPage", function () { - it('can move back a page', function () { var requests = AjaxHelpers.requests(this); pagingView.setPage(2); respondWithMockItems(requests); pagingView.previousPage(); respondWithMockItems(requests); - expect(pagingView.collection.currentPage).toBe(0); + expect(pagingView.collection.getPageNumber()).toBe(1); }); it('can not move back from the first page', function () { @@ -152,12 +159,11 @@ define([ respondWithMockItems(requests); pagingView.previousPage(); requests[1].respond(500); - expect(pagingView.collection.currentPage).toBe(1); + expect(pagingView.collection.getPageNumber()).toBe(2); }); }); describe("toggleSortOrder", function () { - it('can toggle direction of the current sort', function () { var requests = AjaxHelpers.requests(this); expect(pagingView.collection.sortDirection).toBe('desc'); @@ -220,7 +226,8 @@ define([ respondWithMockItems(requests); pagingHeader.$('.next-page-link').click(); requests[1].respond(500); - expect(pagingView.collection.currentPage).toBe(0); + expect(pagingView.collection.state.currentPage).toBe(0); + expect(pagingView.collection.getPageNumber()).toBe(1); }); it('can move to the next page', function () { @@ -229,7 +236,7 @@ define([ respondWithMockItems(requests); pagingHeader.$('.next-page-link').click(); respondWithMockItems(requests); - expect(pagingView.collection.currentPage).toBe(1); + expect(pagingView.collection.getPageNumber()).toBe(2); }); it('should be enabled when there is at least one more page', function () { @@ -248,7 +255,7 @@ define([ it('should be disabled on an empty page', function () { var requests = AjaxHelpers.requests(this); - pagingView.setPage(0); + pagingView.setPage(1); AjaxHelpers.respondWithJson(requests, mockEmptyPage); expect(pagingHeader.$('.next-page-link')).toHaveClass('is-disabled'); }); @@ -267,7 +274,7 @@ define([ respondWithMockItems(requests); pagingHeader.$('.previous-page-link').click(); requests[1].respond(500); - expect(pagingView.collection.currentPage).toBe(1); + expect(pagingView.collection.getPageNumber()).toBe(2); }); it('can go back a page', function () { @@ -276,7 +283,7 @@ define([ respondWithMockItems(requests); pagingHeader.$('.previous-page-link').click(); respondWithMockItems(requests); - expect(pagingView.collection.currentPage).toBe(0); + expect(pagingView.collection.getPageNumber()).toBe(1); }); it('should be disabled on the first page', function () { diff --git a/cms/static/js/views/assets.js b/cms/static/js/views/assets.js index f9694096d3..0b3b4e8ab5 100644 --- a/cms/static/js/views/assets.js +++ b/cms/static/js/views/assets.js @@ -1,9 +1,22 @@ -define(["jquery", "underscore", "gettext", "js/views/baseview", "js/models/asset", "js/views/paging", - "js/views/asset", "js/views/paging_header", "common/js/components/views/paging_footer", - "js/utils/modal", "common/js/components/utils/view_utils", "common/js/components/views/feedback_notification", +define([ + "jquery", + "underscore", + "gettext", + "edx-ui-toolkit/js/utils/html-utils", + "js/views/baseview", + "js/models/asset", + "js/views/paging", + "js/views/asset", + "js/views/paging_header", + "common/js/components/views/paging_footer", + "js/utils/modal", + "common/js/components/utils/view_utils", + "common/js/components/views/feedback_notification", "text!templates/asset-library.underscore", - "jquery.fileupload-process", "jquery.fileupload-validate"], - function($, _, gettext, BaseView, AssetModel, PagingView, AssetView, PagingHeader, PagingFooter, + "jquery.fileupload-process", + "jquery.fileupload-validate" + ], + function($, _, gettext, HtmlUtils, BaseView, AssetModel, PagingView, AssetView, PagingHeader, PagingFooter, ModalUtils, ViewUtils, NotificationView, asset_library_template) { var CONVERSION_FACTOR_MBS_TO_BYTES = 1000 * 1000; @@ -67,7 +80,10 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/models/asset ViewUtils.hideLoadingIndicator(); // Create the table - this.$el.html(_.template(asset_library_template)({typeData: this.typeData})); + HtmlUtils.setHtml( + this.$el, + HtmlUtils.template(asset_library_template)({typeData: this.typeData}) + ); tableBody = this.$('#asset-table-body'); this.tableBody = tableBody; this.pagingHeader = new PagingHeader({view: this, el: $('#asset-paging-header')}); @@ -97,7 +113,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/models/asset pagingView.registerFilterableColumn('js-asset-type-col', gettext('Type'), 'asset_type'); pagingView.setInitialSortColumn('js-asset-date-col'); pagingView.setInitialFilterColumn('js-asset-type-col'); - pagingView.setPage(0); + pagingView.setPage(1); return pagingView; }, @@ -106,7 +122,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/models/asset return this; }, - afterRender: function(){ + afterRender: function() { // Bind events with html elements $('li a.upload-button').on('click', _.bind(this.showUploadModal, this)); $('.upload-modal .close-button').on('click', _.bind(this.hideModal, this)); @@ -127,7 +143,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/models/asset // so that the new asset is shown at the top of the page. this.pagingView.setInitialSortColumn('js-asset-date-col'); this.pagingView.setInitialFilterColumn('js-asset-type-col'); - this.pagingView.setPage(0); + this.pagingView.setPage(1); analytics.track('Uploaded a File', { 'course': course_location_analytics, @@ -217,9 +233,10 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/models/asset startUpload: function (event) { var file = event.target.value; + if (!this.largeFileErrorMsg) { $('.upload-modal h1').text(gettext('Uploading')); - $('.upload-modal .file-name').html(file.substring(file.lastIndexOf("\\") + 1)); + $('.upload-modal .file-name').text(file.substring(file.lastIndexOf('\\') + 1)); $('.upload-modal .choose-file-button').hide(); $('.upload-modal .progress-bar').removeClass('loaded').show(); } @@ -228,13 +245,16 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/models/asset resetUploadModal: function () { // Reset modal so it no longer displays information about previously // completed uploads. - var percentVal = '0%'; - $('.upload-modal .progress-fill').width(percentVal); - $('.upload-modal .progress-fill').html(percentVal); + var percentVal = '0%', + $progressFill = $('.upload-modal .progress-fill'), + $fileName = $('.upload-modal .file-name'); + + $progressFill.width(percentVal); + $progressFill.text(percentVal); $('.upload-modal .progress-bar').hide(); - $('.upload-modal .file-name').show(); - $('.upload-modal .file-name').html(''); + $fileName.show(); + $fileName.text(''); $('.upload-modal .choose-file-button').text(gettext('Choose File')); $('.upload-modal .embeddable-xml-input').val(''); $('.upload-modal .embeddable').hide(); @@ -243,9 +263,11 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/models/asset }, showUploadFeedback: function (event, percentComplete) { - var percentVal = percentComplete + '%'; - $('.upload-modal .progress-fill').width(percentVal); - $('.upload-modal .progress-fill').html(percentVal); + var percentVal = percentComplete + '%', + $progressFill = $('.upload-modal .progress-fill'); + + $progressFill.width(percentVal); + $progressFill.text(percentVal); }, openFilterColumn: function($this) { @@ -285,12 +307,12 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/models/asset var filterColumn = this.$el.find('.filterable-column'); var resetFilter = filterColumn.find('.reset-filter'); var title = filterColumn.find('.title'); - if(assettype === this.allLabel) { + + if (assettype === this.allLabel) { collection.assetType = ''; resetFilter.hide(); title.removeClass('column-selected-link'); - } - else { + } else { collection.assetType = assettype; resetFilter.show(); title.addClass('column-selected-link'); @@ -302,35 +324,38 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/models/asset '.column-filter-link[data-assetfilter="' + assettype + '"]')); }, - closeFilterPopup: function(element){ + closeFilterPopup: function(element) { var $menu = element.parents('.nav-dd > .nav-item'); this.toggleFilterColumnState($menu, element); }, displayFinishedUpload: function (resp) { - var asset = resp.asset; + var asset = resp.asset, + $progressFill = $('.upload-modal .progress-fill'); $('.upload-modal h1').text(gettext('Upload New File')); $('.upload-modal .embeddable-xml-input').val(asset.portable_url).show(); $('.upload-modal .embeddable').show(); $('.upload-modal .file-name').hide(); - $('.upload-modal .progress-fill').html(resp.msg); + $progressFill.text(resp.msg); $('.upload-modal .choose-file-button').text(gettext('Load Another File')).show(); - $('.upload-modal .progress-fill').width('100%'); + $progressFill.width('100%'); this.addAsset(new AssetModel(asset)); }, displayFailedUpload: function (resp) { + var $progressFill = $('.upload-modal .progress-fill'); + $('.upload-modal h1').text(gettext('Upload New File')); $('.upload-modal .embeddable-xml-input').hide(); $('.upload-modal .embeddable').hide(); $('.upload-modal .file-name').hide(); - $('.upload-modal .progress-fill').html(resp.msg); + $progressFill.text(resp.msg); $('.upload-modal .choose-file-button').text(gettext('Load Another File')).show(); - $('.upload-modal .progress-fill').width('0%'); + $progressFill.width('0%'); } }); return AssetsView; - }); // end define(); + }); diff --git a/cms/static/js/views/paged_container.js b/cms/static/js/views/paged_container.js index 7b836fc7e7..837868dd3a 100644 --- a/cms/static/js/views/paged_container.js +++ b/cms/static/js/views/paged_container.js @@ -2,7 +2,8 @@ define(["jquery", "underscore", "common/js/components/utils/view_utils", "js/vie "common/js/components/views/feedback_notification", "js/views/paging_header", "common/js/components/views/paging_footer"], function ($, _, ViewUtils, ContainerView, ModuleUtils, gettext, NotificationView, PagingHeader, PagingFooter) { var PagedContainerView = ContainerView.extend({ - initialize: function(options){ + + initialize: function(options) { var self = this; ContainerView.prototype.initialize.call(this); this.page_size = this.options.page_size; @@ -52,6 +53,22 @@ define(["jquery", "underscore", "common/js/components/utils/view_utils", "js/vie hasNextPage: function () { return self.collection.currentPage < self.collection.totalPages - 1; + }, + + getTotalPages: function () { + return this.totalPages; + }, + + getPageNumber: function () { + return this.getPage(); + }, + + getTotalRecords: function () { + return this.totalCount; + }, + + getPageSize: function () { + return self.page_size; } }; }, @@ -66,11 +83,12 @@ define(["jquery", "underscore", "common/js/components/utils/view_utils", "js/vie return this.renderPage(options); }, - renderPage: function(options){ + renderPage: function(options) { var self = this, view = this.view, xblockInfo = this.model, xblockUrl = xblockInfo.url(); + return $.ajax({ url: decodeURIComponent(xblockUrl) + "/" + view, type: 'GET', @@ -101,8 +119,10 @@ define(["jquery", "underscore", "common/js/components/utils/view_utils", "js/vie }; }, - getPageCount: function(total_count){ - if (total_count===0) return 1; + getPageCount: function(total_count) { + if (total_count === 0) { + return 1; + } return Math.ceil(total_count / this.page_size); }, diff --git a/cms/static/js/views/paging.js b/cms/static/js/views/paging.js index 86972c7ea4..e0eb8fa499 100644 --- a/cms/static/js/views/paging.js +++ b/cms/static/js/views/paging.js @@ -116,12 +116,15 @@ sortInfo = this.sortableColumnInfo(sortColumn), sortField = sortInfo.fieldName, defaultSortDirection = sortInfo.defaultSortDirection; + if (collection.sortField === sortField) { collection.sortDirection = collection.sortDirection === 'asc' ? 'desc' : 'asc'; } else { collection.sortField = sortField; collection.sortDirection = defaultSortDirection; } + + collection.setSorting(sortField, collection.sortDirection); this.sortColumn = sortColumn; this.collection.setPage(1); }, @@ -129,8 +132,8 @@ selectFilter: function(filterColumn) { var collection = this.collection, filterInfo = this.filterableColumnInfo(filterColumn), - filterField = filterInfo.fieldName, - defaultFilterKey = false; + filterField = filterInfo.fieldName; + if (collection.filterField !== filterField) { collection.filterField = filterField; } diff --git a/cms/static/js/views/paging_header.js b/cms/static/js/views/paging_header.js index 662faf2139..0a544e73a8 100644 --- a/cms/static/js/views/paging_header.js +++ b/cms/static/js/views/paging_header.js @@ -1,10 +1,17 @@ -define(["underscore", "backbone", "gettext", "text!templates/paging-header.underscore"], - function(_, Backbone, gettext, paging_header_template) { - +define([ + 'underscore', + 'backbone', + 'gettext', + 'edx-ui-toolkit/js/utils/html-utils', + 'edx-ui-toolkit/js/utils/string-utils', + 'text!templates/paging-header.underscore' +], function(_, Backbone, gettext, HtmlUtils, StringUtils, pagingHeaderTemplate) { + 'use strict'; + /* jshint maxlen:false */ var PagingHeader = Backbone.View.extend({ events : { - "click .next-page-link": "nextPage", - "click .previous-page-link": "previousPage" + 'click .next-page-link': 'nextPage', + 'click .previous-page-link': 'previousPage' }, initialize: function(options) { @@ -19,83 +26,99 @@ define(["underscore", "backbone", "gettext", "text!templates/paging-header.under 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); + currentPage = collection.getPageNumber(), + lastPage = collection.getTotalPages(), + messageHtml = this.messageHtml(), + isNextDisabled = lastPage === 0 || currentPage === lastPage; + + HtmlUtils.setHtml(this.$el, HtmlUtils.template(pagingHeaderTemplate)({messageHtml: messageHtml})); + this.$('.previous-page-link') + .toggleClass('is-disabled', currentPage === 1) + .attr('aria-disabled', currentPage === 1); + this.$('.next-page-link') + .toggleClass('is-disabled', isNextDisabled) + .attr('aria-disabled', isNextDisabled); + return this; }, messageHtml: function() { - var message = ''; - var asset_type = false; + var message = '', + assetType = 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'); + message = gettext('Showing {currentItemRange} out of {totalItemsCount}, filtered by {assetType}, sorted by {sortName} 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'); + message = gettext('Showing {currentItemRange} out of {totalItemsCount}, filtered by {assetType}, sorted by {sortName} descending'); } - asset_type = this.filterNameLabel(); - } - else { + assetType = 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'); + message = gettext('Showing {currentItemRange} out of {totalItemsCount}, sorted by {sortName} 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'); + message = gettext('Showing {currentItemRange} out of {totalItemsCount}, sorted by {sortName} descending'); } } - return '

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

"; + return HtmlUtils.interpolateHtml(message, { + currentItemRange: this.currentItemRangeLabel(), + totalItemsCount: this.totalItemsCountLabel(), + assetType: assetType, + sortName: this.sortNameLabel() + }); }, currentItemRangeLabel: function() { var view = this.view, collection = view.collection, - start = collection.start, + start = (collection.getPageNumber() - 1) * collection.getPageSize(), count = collection.size(), - end = start + count; - return interpolate('%(start)s-%(end)s', { + end = start + count, + htmlMessage = HtmlUtils.HTML('{start}-{end}'); + + return HtmlUtils.interpolateHtml(htmlMessage, { start: Math.min(start + 1, end), end: end - }, true); + }); }, totalItemsCountLabel: function() { - var totalItemsLabel; + var totalItemsLabel, + htmlMessage = HtmlUtils.HTML('{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); + totalItemsLabel = StringUtils.interpolate(gettext('{totalItems} total'), { + totalItems: this.view.collection.getTotalRecords() + }); + + return HtmlUtils.interpolateHtml(htmlMessage, { + totalItemsLabel: totalItemsLabel + }); }, sortNameLabel: function() { - return interpolate('%(sort_name)s', { - sort_name: this.view.sortDisplayName() - }, true); + var htmlMessage = HtmlUtils.HTML('{sortName}'); + + return HtmlUtils.interpolateHtml(htmlMessage, { + sortName: this.view.sortDisplayName() + }); }, filterNameLabel: function() { - return interpolate('%(filter_name)s', { - filter_name: this.view.filterDisplayName() - }, true); + var htmlMessage = HtmlUtils.HTML('{filterName}'); + + return HtmlUtils.interpolateHtml(htmlMessage, { + filterName: this.view.filterDisplayName() + }); }, nextPage: function() { @@ -108,4 +131,4 @@ define(["underscore", "backbone", "gettext", "text!templates/paging-header.under }); return PagingHeader; - }); // end define(); + }); diff --git a/cms/templates/js/paging-header.underscore b/cms/templates/js/paging-header.underscore index 4496497fa1..14bbe57c02 100644 --- a/cms/templates/js/paging-header.underscore +++ b/cms/templates/js/paging-header.underscore @@ -1,6 +1,6 @@
- <%= messageHtml %> +

<%= HtmlUtils.ensureHtml(messageHtml) %>