Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cms/djangoapps/contentstore/views/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,5 @@ def library_blocks_view(library, response_format):
'unit': None,
'component_templates': json.dumps(component_templates),
'xblock_info': xblock_info,
'show_children_previews': library.show_children_previews
})
6 changes: 6 additions & 0 deletions cms/djangoapps/contentstore/views/preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ def handler_url(self, block, handler_name, suffix='', query='', thirdparty=False
def local_resource_url(self, block, uri):
return local_resource_url(block, uri)

def render(self, block, view_name, context=None):
if not context.get('show_preview', True):
return self.wrap_child(block, view_name, Fragment(), context)
else:
return super(PreviewModuleSystem, self).render(block, view_name, context)


class StudioUserService(object):
"""
Expand Down
2 changes: 1 addition & 1 deletion cms/static/coffee/spec/main.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ define([
"js/spec/views/assets_spec",
"js/spec/views/baseview_spec",
"js/spec/views/container_spec",
"js/spec/views/paging_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",
Expand Down

Large diffs are not rendered by default.

60 changes: 53 additions & 7 deletions cms/static/js/spec/views/pages/container_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ define(["jquery", "underscore", "underscore.string", "js/common_helpers/ajax_hel
describe(label + " ContainerPage", function () {
var lastRequest, getContainerPage, renderContainerPage, expectComponents, respondWithHtml,
model, containerPage, requests, initialDisplayName,
mockContainerPage = readFixtures('mock/mock-container-page.underscore'),
mockContainerPage = readFixtures(fixtures.container),
mockContainerXBlockHtml = readFixtures(fixtures.initial),
mockXBlockHtml = readFixtures(fixtures.add_response),
mockBadContainerXBlockHtml = readFixtures('mock/mock-bad-javascript-container-xblock.underscore'),
Expand Down Expand Up @@ -546,17 +546,63 @@ define(["jquery", "underscore", "underscore.string", "js/common_helpers/ajax_hel
});
});
});

if (global_page_options.is_library) {
describe("Previews", function(){

var getButtonIcon, getButtonText;

getButtonIcon = function(containerPage){
return containerPage.$('.action-toggle-preview .preview-arrow');
};

getButtonText = function(containerPage) {
return containerPage.$('.action-toggle-preview .preview-text').text().trim();
};

it('initially shows loading icon and reads "Loading..."', function(){
containerPage = getContainerPage();
expect(getButtonIcon(containerPage)).toHaveClass('icon-refresh');
expect(getButtonText(containerPage)).toBe("${_('Loading...')}");
});

function updatePreviewButtonTest(label, show_previews, expected_icon_class, expected_text){
it('can set preview button to '+label, function (){
containerPage = getContainerPage();
containerPage.updatePreviewButton(show_previews);
expect(getButtonIcon(containerPage)).toHaveClass(expected_icon_class);
expect(getButtonText(containerPage)).toBe(expected_text);
});
}
updatePreviewButtonTest('show previews', true, 'icon-arrow-up', 'Hide Previews');
updatePreviewButtonTest('hide previews', false, 'icon-arrow-down', 'Show Previews');

it('triggers underlying view toggle_previews when preview button clicked', function() {
containerPage = getContainerPage();
containerPage.render();
spyOn(containerPage.xblockView, 'toggle_previews');

containerPage.$('.toggle-preview-button').click();
expect(containerPage.xblockView.toggle_previews).toHaveBeenCalled();
});
});
}
});
}

parameterized_suite("Non paged",
parameterized_suite("Course",
{ enable_paging: false },
{ initial: 'mock/mock-container-xblock.underscore', add_response: 'mock/mock-xblock.underscore' }
{
initial: 'mock/mock-container-xblock.underscore',
add_response: 'mock/mock-xblock.underscore',
container: 'mock/mock-container-page.underscore'
}
);
parameterized_suite("Paged",
{ enable_paging: true, page_size: 42 },
parameterized_suite("Library",
{ is_library: true, page_size: 42 },
{
initial: 'mock/mock-container-paged-xblock.underscore',
add_response: 'mock/mock-container-paged-after-add-xblock.underscore'
initial: 'mock/mock-container-library-xblock.underscore',
add_response: 'mock/mock-container-library-after-add-xblock.underscore',
container: 'mock/mock-container-page-library.underscore'
});
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
define(["jquery", "underscore", "js/views/xblock", "js/utils/module", "gettext", "js/views/feedback_notification",
"js/views/paging_header", "js/views/paging_footer"],
function ($, _, XBlockView, ModuleUtils, gettext, NotificationView, PagingHeader, PagingFooter) {
var PagedContainerView = XBlockView.extend({
var LibraryContainerView = XBlockView.extend({
// Store the request token of the first xblock on the page (which we know was rendered by Studio when
// the page was generated). Use that request token to filter out user-defined HTML in any
// child xblocks within the page.
Expand All @@ -11,9 +11,8 @@ define(["jquery", "underscore", "js/views/xblock", "js/utils/module", "gettext",
var self = this;
XBlockView.prototype.initialize.call(this);
this.page_size = this.options.page_size || 10;
if (options) {
this.page_reload_callback = options.page_reload_callback;
}
this.page_reload_callback = this.options.page_reload_callback || function() {};
this.update_previews_callback = this.options.update_previews_callback || function() {};
// emulating Backbone.paginator interface
this.collection = {
currentPage: 0,
Expand All @@ -22,6 +21,7 @@ define(["jquery", "underscore", "js/views/xblock", "js/utils/module", "gettext",
sortDirection: "desc",
start: 0,
_size: 0,
show_children_previews: true,

bind: function() {}, // no-op
size: function() { return self.collection._size; }
Expand All @@ -40,22 +40,20 @@ define(["jquery", "underscore", "js/views/xblock", "js/utils/module", "gettext",
},

renderPage: function(options){
var self = this,
view = this.view,
xblockInfo = this.model,
xblockUrl = xblockInfo.url();
var self = this;
return $.ajax({
url: decodeURIComponent(xblockUrl) + "/" + view,
url: decodeURIComponent(this.model.url()) + "/" + this.view,
type: 'GET',
cache: false,
data: this.getRenderParameters(options.page_number),
headers: { Accept: 'application/json' },
success: function(fragment) {
self.handleXBlockFragment(fragment, options);
self.processPaging({ requested_page: options.page_number });
if (options.paging && self.page_reload_callback){
if (options.paging) {
self.page_reload_callback(self.$el);
}
self.update_previews_callback(self.collection.show_children_previews);
}
});
},
Expand Down Expand Up @@ -96,15 +94,14 @@ define(["jquery", "underscore", "js/views/xblock", "js/utils/module", "gettext",

processPaging: function(options){
var $element = this.$el.find('.xblock-container-paging-parameters'),
total = $element.data('total'),
displayed = $element.data('displayed'),
start = $element.data('start');
total = $element.data('total');

this.collection.currentPage = options.requested_page;
this.collection.totalCount = total;
this.collection.totalPages = this.getPageCount(total);
this.collection.start = start;
this.collection._size = displayed;
this.collection.start = $element.data('start');
this.collection._size = $element.data('displayed');
this.collection.show_children_previews = $element.data('previews');

this.processPagingHeaderAndFooter();
},
Expand Down Expand Up @@ -157,8 +154,26 @@ define(["jquery", "underscore", "js/views/xblock", "js/utils/module", "gettext",

sortDisplayName: function() {
return "Date added"; // TODO add support for sorting
},

toggle_previews: function(){
var self = this,
runtime = this.xblock && this.xblock.runtime;
if (runtime) {
return $.ajax({
url: runtime.handlerUrl(this.xblock.element, 'trigger_previews'),
type: 'POST',
data: JSON.stringify({ show_children_previews: !this.collection.show_children_previews}),
dataType: 'json'
})
.then(self.render)
.promise();
}
else{
return $.Deferred().resolve(this.collection.show_children_previews).promise();
}
}
});

return PagedContainerView;
return LibraryContainerView;
}); // end define();
39 changes: 32 additions & 7 deletions cms/static/js/views/pages/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
* This page allows the user to understand and manipulate the xblock and its children.
*/
define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views/utils/view_utils",
"js/views/container", "js/views/paged_container", "js/views/xblock", "js/views/components/add_xblock", "js/views/modals/edit_xblock",
"js/views/container", "js/views/library_container", "js/views/xblock", "js/views/components/add_xblock", "js/views/modals/edit_xblock",
"js/models/xblock_info", "js/views/xblock_string_field_editor", "js/views/pages/container_subviews",
"js/views/unit_outline", "js/views/utils/xblock_utils"],
function ($, _, gettext, BasePage, ViewUtils, ContainerView, PagedContainerView, XBlockView, AddXBlockComponent,
function ($, _, gettext, BasePage, ViewUtils, ContainerView, LibraryContainerView, XBlockView, AddXBlockComponent,
EditXBlockModal, XBlockInfo, XBlockStringFieldEditor, ContainerSubviews, UnitOutlineView,
XBlockUtils) {
'use strict';
Expand All @@ -16,7 +16,8 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views
events: {
"click .edit-button": "editXBlock",
"click .duplicate-button": "duplicateXBlock",
"click .delete-button": "deleteXBlock"
"click .delete-button": "deleteXBlock",
"click .toggle-preview-button": "toggleChildrenPreviews"
},

options: {
Expand All @@ -27,8 +28,8 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views

initialize: function(options) {
BasePage.prototype.initialize.call(this, options);
this.enable_paging = options.enable_paging || false;
if (this.enable_paging) {
this.is_library = options.is_library || false;
if (this.is_library) {
this.page_size = options.page_size || 10;
}
this.nameEditor = new XBlockStringFieldEditor({
Expand Down Expand Up @@ -83,15 +84,19 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views
view: this.view
};

if (this.enable_paging) {
if (this.is_library) {
parameters = _.extend(parameters, {
page_size: this.page_size,
children_previews: this.children_previews,
page_reload_callback: function($element) {
self.renderAddXBlockComponents();
self.addButtonActions($element);
},
update_previews_callback: function(show_children_previews) {
self.updatePreviewButton(show_children_previews);
}
});
return new PagedContainerView(parameters);
return new LibraryContainerView(parameters);
}
else {
return new ContainerView(parameters);
Expand All @@ -105,6 +110,10 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views
unitLocationTree = this.$('.unit-location'),
hiddenCss='is-hidden';

if (this.toggle_previews){
this.updatePreviewButton();
}

loadingElement.removeClass(hiddenCss);

// Hide both blocks until we know which one to show
Expand Down Expand Up @@ -160,6 +169,15 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views
});
},

updatePreviewButton: function(show_previews){
var text = (show_previews) ? gettext('Hide Previews') : gettext('Show Previews'),
icon_class = (show_previews) ? 'icon-arrow-up' : 'icon-arrow-down',
button = $('.nav-actions .button-toggle-preview');

this.$(".preview-arrow", button).removeClass("icon-arrow-down icon-arrow-up").addClass(icon_class);
this.$(".preview-text", button).text(text);
},

editXBlock: function(event) {
var xblockElement = this.findXBlockElement(event.target),
self = this,
Expand Down Expand Up @@ -242,6 +260,13 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views
});
},

toggleChildrenPreviews: function(xblockElement) {
// TODO: this ignores xblockElement as it's always a top level control for now. This might change in the future
if (this.xblockView.toggle_previews) {
this.xblockView.toggle_previews();
}
},

onDelete: function(xblockElement) {
// get the parent so we can remove this component from its parent.
var xblockView = this.xblockView,
Expand Down
68 changes: 68 additions & 0 deletions cms/templates/js/mock/mock-container-page-library.underscore
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<div id="content">

<div class="wrapper-mast wrapper" data-location="" data-display-name="" data-category="">
<header class="mast has-actions has-navigation">
<div class="page-header">
<small class="navigation navigation-parents subtitle">
<a href="/unit/TestCourse/branch/draft/block/vertical8eb" class="navigation-item navigation-link navigation-parent">Unit 1</a>
</small>
<div class="wrapper-xblock-field is-editable" data-field="display_name">
<h1 class="page-header-title xblock-field-value">Test Container</h1>
</div>
</div>

<nav class="nav-actions">
<h3 class="sr">${_("Page Actions")}</h3>
<ul>
<li class="action-item action-toggle-preview nav-item">
<a href="#" class="button button-toggle-preview action-button toggle-preview-button">
<i class="icon-refresh preview-arrow"></i>
<span class="action-button-text preview-text">${_('Loading...')}</span>
</a>
</li>
<li class="action-item action-edit nav-item">
<a href="#" class="button edit-button action-button">
<i class="icon-pencil"></i>
<span class="action-button-text">${_("Edit")}</span>
</a>
</li>
</ul>
</nav>
</header>
</div>

<div class="wrapper-content wrapper">
<div class="inner-wrapper">
<section class="content-area">

<article class="content-primary window">
<div class="container-message wrapper-message"></div>
<section class="wrapper-xblock level-page studio-xblock-wrapper" data-locator="locator-container">
</section>
<div class="ui-loading is-hidden">
<p><span class="spin"><i class="icon-refresh"></i></span> <span class="copy">Loading...</span></p>
</div>
</article>
<aside class="content-supplementary" role="complimentary">
<div id="publish-unit" class="window"></div>
<div id="publish-history"></div>
</aside>
<div class="unit-location">
<h4 class="header">${_("Unit Location")}</h4>
<div class="wrapper-unit-id content-bit">
<h5 class="title">Unit Location ID</h5>
<p class="unit-id">
<span class="unit-id-value" id="unit-location-id-input">${unit.location.name}</span>
<span class="tip"><span class="sr">Tip: </span>${_("Use this ID when you create links to this unit from other course content. You enter the ID in the URL field.")}</span>
</p>
</div>
<div class="wrapper-unit-tree-location bar-mod-content">
<h5 class="title">Location in Course Outline</h5>
<div class="wrapper-unit-overview">
</div>
</div>
</div>
</section>
</div>
</div>
</div>
Loading