diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py
index 67f1dc268e..e46d83d70b 100644
--- a/cms/djangoapps/contentstore/views/item.py
+++ b/cms/djangoapps/contentstore/views/item.py
@@ -237,12 +237,28 @@ def xblock_view_handler(request, usage_key_string, view_name):
if view_name == 'reorderable_container_child_preview':
reorderable_items.add(xblock.location)
+ paging = None
+ try:
+ if request.REQUEST.get('enable_paging', 'false') == 'true':
+ paging = {
+ 'page_number': int(request.REQUEST.get('page_number', 0)),
+ 'page_size': int(request.REQUEST.get('page_size', 0)),
+ }
+ except ValueError:
+ log.exception(
+ "Couldn't parse paging parameters: enable_paging: %s, page_number: %s, page_size: %s",
+ request.REQUEST.get('enable_paging', 'false'),
+ request.REQUEST.get('page_number', 0),
+ request.REQUEST.get('page_size', 0)
+ )
+
# Set up the context to be passed to each XBlock's render method.
context = {
'is_pages_view': is_pages_view, # This setting disables the recursive wrapping of xblocks
'is_unit_page': is_unit(xblock),
'root_xblock': xblock if (view_name == 'container_preview') else None,
- 'reorderable_items': reorderable_items
+ 'reorderable_items': reorderable_items,
+ 'paging': paging
}
fragment = get_preview_fragment(request, xblock, context)
diff --git a/cms/static/coffee/spec/main.coffee b/cms/static/coffee/spec/main.coffee
index 3a7b2c046a..1bd1177264 100644
--- a/cms/static/coffee/spec/main.coffee
+++ b/cms/static/coffee/spec/main.coffee
@@ -239,6 +239,7 @@ define([
"js/spec/views/assets_spec",
"js/spec/views/baseview_spec",
"js/spec/views/container_spec",
+ "js/spec/views/library_container_spec",
"js/spec/views/group_configuration_spec",
"js/spec/views/paging_spec",
"js/spec/views/unit_outline_spec",
diff --git a/cms/static/js/factories/container.js b/cms/static/js/factories/container.js
index 93cdeb8fd9..ea48bb2a98 100644
--- a/cms/static/js/factories/container.js
+++ b/cms/static/js/factories/container.js
@@ -1,22 +1,20 @@
define([
- 'jquery', 'js/models/xblock_info', 'js/views/pages/container',
+ 'jquery', 'underscore', 'js/models/xblock_info', 'js/views/pages/container',
'js/collections/component_template', 'xmodule', 'coffee/src/main',
'xblock/cms.runtime.v1'
],
-function($, XBlockInfo, ContainerPage, ComponentTemplates, xmoduleLoader) {
+function($, _, XBlockInfo, ContainerPage, ComponentTemplates, xmoduleLoader) {
'use strict';
- return function (componentTemplates, XBlockInfoJson, action, isUnitPage) {
- var templates = new ComponentTemplates(componentTemplates, {parse: true}),
- mainXBlockInfo = new XBlockInfo(XBlockInfoJson, {parse: true});
+ return function (componentTemplates, XBlockInfoJson, action, options) {
+ var main_options = {
+ el: $('#content'),
+ model: new XBlockInfo(XBlockInfoJson, {parse: true}),
+ action: action,
+ templates: new ComponentTemplates(componentTemplates, {parse: true})
+ };
xmoduleLoader.done(function () {
- var view = new ContainerPage({
- el: $('#content'),
- model: mainXBlockInfo,
- action: action,
- templates: templates,
- isUnitPage: isUnitPage
- });
+ var view = new ContainerPage(_.extend(main_options, options));
view.render();
});
};
diff --git a/cms/static/js/factories/library.js b/cms/static/js/factories/library.js
index 2729a3cf27..e7834f60ef 100644
--- a/cms/static/js/factories/library.js
+++ b/cms/static/js/factories/library.js
@@ -1,22 +1,20 @@
define([
- 'jquery', 'js/models/xblock_info', 'js/views/pages/container',
+ 'jquery', 'underscore', 'js/models/xblock_info', 'js/views/pages/container',
'js/collections/component_template', 'xmodule', 'coffee/src/main',
'xblock/cms.runtime.v1'
],
-function($, XBlockInfo, ContainerPage, ComponentTemplates, xmoduleLoader) {
+function($, _, XBlockInfo, ContainerPage, ComponentTemplates, xmoduleLoader) {
'use strict';
- return function (componentTemplates, XBlockInfoJson) {
- var templates = new ComponentTemplates(componentTemplates, {parse: true}),
- mainXBlockInfo = new XBlockInfo(XBlockInfoJson, {parse: true});
+ return function (componentTemplates, XBlockInfoJson, options) {
+ var main_options = {
+ el: $('#content'),
+ model: new XBlockInfo(XBlockInfoJson, {parse: true}),
+ templates: new ComponentTemplates(componentTemplates, {parse: true}),
+ action: 'view'
+ };
xmoduleLoader.done(function () {
- var view = new ContainerPage({
- el: $('#content'),
- model: mainXBlockInfo,
- action: "view",
- templates: templates,
- isUnitPage: false
- });
+ var view = new ContainerPage(_.extend(main_options, options));
view.render();
});
};
diff --git a/cms/static/js/spec/views/library_container_spec.js b/cms/static/js/spec/views/library_container_spec.js
new file mode 100644
index 0000000000..2d39cdc358
--- /dev/null
+++ b/cms/static/js/spec/views/library_container_spec.js
@@ -0,0 +1,489 @@
+define([ "jquery", "underscore", "js/common_helpers/ajax_helpers", "URI", "js/models/xblock_info",
+ "js/views/library_container", "js/views/paging_header", "js/views/paging_footer"],
+ function ($, _, AjaxHelpers, URI, XBlockInfo, PagedContainer, PagingContainer, PagingFooter) {
+
+ var htmlResponseTpl = _.template('' +
+ '
'
+ );
+
+ function getResponseHtml(options){
+ return '' +
+ '' +
+ htmlResponseTpl(options) +
+ '' +
+ '
'
+ }
+
+ var PAGE_SIZE = 3;
+
+ var mockFirstPage = {
+ resources: [],
+ html: getResponseHtml({
+ start: 0,
+ displayed: PAGE_SIZE,
+ total: PAGE_SIZE + 1
+ })
+ };
+
+ var mockSecondPage = {
+ resources: [],
+ html: getResponseHtml({
+ start: PAGE_SIZE,
+ displayed: 1,
+ total: PAGE_SIZE + 1
+ })
+ };
+
+ var mockEmptyPage = {
+ resources: [],
+ html: getResponseHtml({
+ start: 0,
+ displayed: 0,
+ total: 0
+ })
+ };
+
+ var respondWithMockPage = function(requests) {
+ var requestIndex = requests.length - 1;
+ var request = requests[requestIndex];
+ var url = new URI(request.url);
+ var queryParameters = url.query(true); // Returns an object with each query parameter stored as a value
+ var page = queryParameters.page_number;
+ var response = page === "0" ? mockFirstPage : mockSecondPage;
+ AjaxHelpers.respondWithJson(requests, response, requestIndex);
+ };
+
+ var MockPagingView = PagedContainer.extend({
+ view: 'container_preview',
+ el: $(""),
+ model: new XBlockInfo({}, {parse: true})
+ });
+
+ describe("Paging Container", function() {
+ var pagingContainer;
+
+ beforeEach(function () {
+ var feedbackTpl = readFixtures('system-feedback.underscore');
+ setFixtures($("
+
+
+
+
+
+
+
diff --git a/cms/templates/js/mock/mock-container-paged-xblock.underscore b/cms/templates/js/mock/mock-container-paged-xblock.underscore
new file mode 100644
index 0000000000..2314bb8925
--- /dev/null
+++ b/cms/templates/js/mock/mock-container-paged-xblock.underscore
@@ -0,0 +1,257 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cms/templates/library.html b/cms/templates/library.html
index 70bd836bad..dc9baa5736 100644
--- a/cms/templates/library.html
+++ b/cms/templates/library.html
@@ -22,8 +22,12 @@ from django.utils.translation import ugettext as _
<%block name="requirejs">
require(["js/factories/library"], function(LibraryFactory) {
LibraryFactory(
- ${component_templates | n},
- ${json.dumps(xblock_info) | n}
+ ${component_templates | n}, ${json.dumps(xblock_info) | n},
+ {
+ isUnitPage: false,
+ enable_paging: true,
+ page_size: 10
+ }
);
});
%block>
diff --git a/common/lib/xmodule/xmodule/library_root_xblock.py b/common/lib/xmodule/xmodule/library_root_xblock.py
index dc00aaa97f..497a145b79 100644
--- a/common/lib/xmodule/xmodule/library_root_xblock.py
+++ b/common/lib/xmodule/xmodule/library_root_xblock.py
@@ -3,10 +3,10 @@
"""
import logging
-from .studio_editable import StudioEditableModule
from xblock.core import XBlock
from xblock.fields import Scope, String, List
from xblock.fragment import Fragment
+from xmodule.studio_editable import StudioEditableModule
log = logging.getLogger(__name__)
@@ -42,29 +42,55 @@ class LibraryRoot(XBlock):
def author_view(self, context):
"""
- Renders the Studio preview view, which supports drag and drop.
+ Renders the Studio preview view.
"""
fragment = Fragment()
+ self.render_children(context, fragment, can_reorder=False, can_add=True)
+ return fragment
+
+ def render_children(self, context, fragment, can_reorder=False, can_add=False): # pylint: disable=unused-argument
+ """
+ Renders the children of the module with HTML appropriate for Studio. If can_reorder is True,
+ then the children will be rendered to support drag and drop.
+ """
contents = []
- for child_key in self.children: # pylint: disable=E1101
- context['reorderable_items'].add(child_key)
+ paging = context.get('paging', None)
+
+ children_count = len(self.children) # pylint: disable=no-member
+ item_start, item_end = 0, children_count
+
+ # TODO sort children
+ if paging:
+ page_number = paging.get('page_number', 0)
+ raw_page_size = paging.get('page_size', None)
+ page_size = raw_page_size if raw_page_size is not None else children_count
+ item_start, item_end = page_size * page_number, page_size * (page_number + 1)
+
+ children_to_show = self.children[item_start:item_end] # pylint: disable=no-member
+
+ for child_key in children_to_show: # pylint: disable=E1101
child = self.runtime.get_block(child_key)
- rendered_child = self.runtime.render_child(child, StudioEditableModule.get_preview_view_name(child), context)
+ child_view_name = StudioEditableModule.get_preview_view_name(child)
+ rendered_child = self.runtime.render_child(child, child_view_name, context)
fragment.add_frag_resources(rendered_child)
contents.append({
- 'id': unicode(child_key),
- 'content': rendered_child.content,
+ 'id': child.location.to_deprecated_string(),
+ 'content': rendered_child.content
})
- fragment.add_content(self.runtime.render_template("studio_render_children_view.html", {
- 'items': contents,
- 'xblock_context': context,
- 'can_add': True,
- 'can_reorder': True,
- }))
- return fragment
+ fragment.add_content(
+ self.runtime.render_template("studio_render_paged_children_view.html", {
+ 'items': contents,
+ 'xblock_context': context,
+ 'can_add': can_add,
+ 'can_reorder': False,
+ 'first_displayed': item_start,
+ 'total_children': children_count,
+ 'displayed_children': len(children_to_show)
+ })
+ )
@property
def display_org_with_default(self):
diff --git a/common/lib/xmodule/xmodule/video_module/video_handlers.py b/common/lib/xmodule/xmodule/video_module/video_handlers.py
index 9e9db860ca..1ba427c357 100644
--- a/common/lib/xmodule/xmodule/video_module/video_handlers.py
+++ b/common/lib/xmodule/xmodule/video_module/video_handlers.py
@@ -155,7 +155,6 @@ class VideoStudentViewHandlers(object):
if transcript_name:
# Get the asset path for course
- asset_path = None
course = self.descriptor.runtime.modulestore.get_course(self.course_id)
if course.static_asset_path:
asset_path = course.static_asset_path
diff --git a/lms/templates/studio_render_paged_children_view.html b/lms/templates/studio_render_paged_children_view.html
new file mode 100644
index 0000000000..fe5b5403e1
--- /dev/null
+++ b/lms/templates/studio_render_paged_children_view.html
@@ -0,0 +1,23 @@
+<%! from django.utils.translation import ugettext as _ %>
+
+<%namespace name='static' file='static_content.html'/>
+
+% for template_name in ["paging-header", "paging-footer"]:
+
+% endfor
+
+
+
+
+
+% for item in items:
+ ${item['content']}
+% endfor
+
+% if can_add:
+
+% endif
+
+