Address the next round of review comments.

This commit is contained in:
Andy Armstrong
2014-04-08 15:15:35 -04:00
parent 88d95d119c
commit a6aae729b7
34 changed files with 173 additions and 220 deletions

View File

@@ -6,6 +6,7 @@ from nose.tools import assert_equal, assert_in # pylint: disable=E0611
from terrain.steps import reload_the_page
from common import type_in_codemirror
from selenium.webdriver.common.keys import Keys
from cms.envs.common import FEATURES
@world.absorb
@@ -54,6 +55,11 @@ def click_new_component_button(step, component_button_css):
world.css_click(component_button_css)
if FEATURES['USE_CONTAINER_PAGE_FOR_TESTING']:
unit_url = world.browser.url
container_url = unit_url.replace('/unit/', '/container/')
world.visit(container_url)
def _click_advanced():
css = 'ul.problem-type-tabs a[href="#tab2"]'

View File

@@ -7,6 +7,9 @@ from xmodule.modulestore.django import loc_mapper, modulestore
__all__ = ['edge', 'event', 'landing']
EDITING_TEMPLATES = [
"basic-modal", "modal-button", "edit-xblock-modal", "editor-mode-button", "upload-dialog", "image-modal"
]
# points to the temporary course landing page with log in and sign up
def landing(request, org, course, coursename):

View File

@@ -99,6 +99,9 @@ FEATURES = {
# Turn off Advanced Security by default
'ADVANCED_SECURITY': False,
# Switch acceptance tests to use the container page instead of the unit page
'USE_CONTAINER_PAGE_FOR_TESTING': False,
}
ENABLE_JASMINE = False

View File

@@ -218,9 +218,10 @@ define([
"js/spec/views/unit_spec",
"js/spec/views/xblock_spec",
"js/spec/views/xblock_container_spec",
"js/spec/views/xblock_editor_spec",
"js/spec/views/pages/container_spec",
"js/spec/views/modals/base_modal_spec",
"js/spec/views/modals/edit_xblock_spec",

View File

@@ -1,7 +1,7 @@
define ["js/models/textbook", "js/models/chapter", "js/collections/chapter", "js/models/course",
"js/collections/textbook", "js/views/show_textbook", "js/views/edit_textbook", "js/views/list_textbooks",
"js/views/edit_chapter", "js/views/feedback_prompt", "js/views/feedback_notification",
"js/spec_helpers/create_sinon", "jasmine-stealth"],
"js/spec_helpers/create_sinon", "js/spec_helpers/modal_helpers", "jasmine-stealth"],
(Textbook, Chapter, ChapterSet, Course, TextbookSet, ShowTextbook, EditTextbook, ListTexbook, EditChapter, Prompt, Notification, create_sinon) ->
feedbackTpl = readFixtures('system-feedback.underscore')
@@ -272,8 +272,8 @@ define ["js/models/textbook", "js/models/chapter", "js/collections/chapter", "js
tpl = readFixtures("edit-chapter.underscore")
beforeEach ->
setFixtures($("<script>", {id: "edit-chapter-tpl", type: "text/template"}).text(tpl))
appendSetFixtures($("<script>", {id: "system-feedback-tpl", type: "text/template"}).text(feedbackTpl))
modal_helpers.installModalTemplates()
appendSetFixtures($("<script>", {id: "edit-chapter-tpl", type: "text/template"}).text(tpl))
@model = new Chapter
name: "Chapter 1"
asset_path: "/ch1.pdf"

View File

@@ -22,9 +22,7 @@ define(["jquery", "underscore", "js/views/modals/base_modal", "js/spec_helpers/m
});
afterEach(function() {
if (modal && modal_helpers.isShowingModal(modal)) {
modal.hide();
}
modal_helpers.hideModalIfShowing(modal);
});
describe("Single Modal", function() {

View File

@@ -14,16 +14,14 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
edit_helpers.installEditTemplates();
appendSetFixtures('<div class="xblock" data-locator="mock-xblock" data-display-name="Mock XBlock"></div>');
model = new XBlockInfo({
id: 'testCourse/branch/published/block/verticalFFF',
id: 'testCourse/branch/draft/block/verticalFFF',
display_name: 'Test Unit',
category: 'vertical'
});
});
afterEach(function() {
if (modal && edit_helpers.isShowingModal(modal)) {
edit_helpers.cancelModal(modal);
}
edit_helpers.cancelModalIfShowing();
});
describe("XBlock Editor", function() {
@@ -161,9 +159,7 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
});
it('does not show any mode buttons', function() {
var requests = create_sinon.requests(this),
editorButton,
settingsButton;
var requests = create_sinon.requests(this);
modal = showModal(requests, mockXModuleEditorHtml);
expect(modal.$('.editor-modes li').length).toBe(0);
});

View File

@@ -1,22 +1,22 @@
define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers",
"js/views/xblock_container", "js/models/xblock_info"],
function ($, create_sinon, edit_helpers, XBlockContainerView, XBlockInfo) {
"js/views/pages/container", "js/models/xblock_info"],
function ($, create_sinon, edit_helpers, XBlockContainerPage, XBlockInfo) {
describe("XBlockContainerView", function() {
var model, containerView, respondWithMockXBlockEditorFragment, mockContainerView;
var model, containerView, respondWithMockXBlockEditorFragment, mockContainerPage;
mockContainerView = readFixtures('mock/mock-container-view.underscore');
mockContainerPage = readFixtures('mock/mock-container-page.underscore');
beforeEach(function () {
edit_helpers.installEditTemplates();
appendSetFixtures(mockContainerView);
appendSetFixtures(mockContainerPage);
model = new XBlockInfo({
id: 'testCourse/branch/published/block/verticalFFF',
id: 'testCourse/branch/draft/block/verticalFFF',
display_name: 'Test Unit',
category: 'vertical'
});
containerView = new XBlockContainerView({
containerView = new XBlockContainerPage({
model: model,
el: $('#content')
});
@@ -59,7 +59,8 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
describe("Editing an xblock", function() {
var mockContainerXBlockHtml,
mockXBlockEditorHtml,
saved;
saved,
newDisplayName = 'New Display Name';
beforeEach(function () {
saved = false;
@@ -67,6 +68,12 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
return {
save: function() {
saved = true;
return {
data: "<p>Some HTML</p>",
metadata: {
display_name: newDisplayName
}
};
}
};
};
@@ -74,9 +81,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
afterEach(function() {
window.MockXBlock = null;
if (edit_helpers.isShowingModal()) {
edit_helpers.cancelModal();
}
edit_helpers.cancelModalIfShowing();
});
mockContainerXBlockHtml = readFixtures('mock/mock-container-xblock.underscore');

View File

@@ -6,8 +6,9 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers
var model, editor;
beforeEach(function () {
edit_helpers.installEditTemplates();
model = new XBlockInfo({
id: 'testCourse/branch/published/block/verticalFFF',
id: 'testCourse/branch/draft/block/verticalFFF',
display_name: 'Test Unit',
category: 'vertical'
});
@@ -50,8 +51,6 @@ define([ "jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers
mockXModuleEditorHtml = readFixtures('mock/mock-xmodule-editor.underscore');
beforeEach(function() {
edit_helpers.installEditTemplates();
// Mock the VerticalDescriptor so that the module can be rendered
window.VerticalDescriptor = XModule.Descriptor;
});

View File

@@ -7,7 +7,7 @@ define([ "jquery", "js/spec_helpers/create_sinon", "URI", "js/views/xblock", "js
beforeEach(function () {
model = new XBlockInfo({
id: 'testCourse/branch/published/block/verticalFFF',
id: 'testCourse/branch/draft/block/verticalFFF',
display_name: 'Test Unit',
category: 'vertical'
});

View File

@@ -2,13 +2,12 @@
* Provides helper methods for invoking Studio editors in Jasmine tests.
*/
define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/modal_helpers", "js/views/modals/edit_xblock",
"xmodule", "coffee/src/main", "xblock/cms.runtime.v1"],
"xmodule", "coffee/src/main", "xblock/cms.runtime.v1"],
function($, create_sinon, modal_helpers, EditXBlockModal) {
var editorTemplate = readFixtures('metadata-editor.underscore'),
numberEntryTemplate = readFixtures('metadata-number-entry.underscore'),
stringEntryTemplate = readFixtures('metadata-string-entry.underscore'),
feedbackTemplate = readFixtures('system-feedback.underscore'),
editXBlockModalTemplate = readFixtures('edit-xblock-modal.underscore'),
editorModeButtonTemplate = readFixtures('editor-mode-button.underscore'),
installEditTemplates,
@@ -37,10 +36,8 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/modal_helpers
return modal;
};
return {
return $.extend(modal_helpers, {
'installEditTemplates': installEditTemplates,
'showEditModal': showEditModal,
'isShowingModal': modal_helpers.isShowingModal,
'cancelModal': modal_helpers.cancelModal
};
'showEditModal': showEditModal
});
});

View File

@@ -7,8 +7,11 @@ define(["jquery"],
modalButtonTemplate = readFixtures('modal-button.underscore'),
feedbackTemplate = readFixtures('system-feedback.underscore'),
installModalTemplates,
getModalElement,
isShowingModal,
cancelModal;
hideModalIfShowing,
cancelModal,
cancelModalIfShowing;
installModalTemplates = function(append) {
if (append) {
@@ -20,31 +23,46 @@ define(["jquery"],
appendSetFixtures($("<script>", { id: "modal-button-tpl", type: "text/template" }).text(modalButtonTemplate));
};
isShowingModal = function(modal) {
getModalElement = function(modal) {
var modalElement;
if (modal) {
modalElement = modal.$('.wrapper-modal-window');
} else {
modalElement = $('.wrapper-modal-window');
}
return modalElement;
};
isShowingModal = function(modal) {
var modalElement = getModalElement(modal);
return modalElement.length > 0;
};
hideModalIfShowing = function(modal) {
if (isShowingModal(modal)) {
modal.hide();
}
};
cancelModal = function(modal) {
var modalElement, cancelButton;
if (modal) {
modalElement = modal.$('.wrapper-modal-window');
} else {
modalElement = $('.wrapper-modal-window');
}
modalElement = getModalElement(modal);
cancelButton = modalElement.find('.action-cancel');
expect(cancelButton.length).toBe(1);
cancelButton.click();
};
cancelModalIfShowing = function(modal) {
if (isShowingModal(modal)) {
cancelModal(modal);
}
};
return {
'installModalTemplates': installModalTemplates,
'isShowingModal': isShowingModal,
'cancelModal': cancelModal
'hideModalIfShowing': hideModalIfShowing,
'cancelModal': cancelModal,
'cancelModalIfShowing': cancelModalIfShowing
};
});

View File

@@ -2,7 +2,7 @@ define(["js/views/baseview", "underscore", "gettext", "js/views/feedback_prompt"
function(BaseView, _, gettext, PromptView, NotificationView) {
var AssetView = BaseView.extend({
initialize: function() {
this.template = _.template($("#asset-tpl").text());
this.template = this.loadTemplate("asset");
this.listenTo(this.model, "change:locked", this.updateLockState);
},
tagName: "tr",

View File

@@ -11,7 +11,7 @@ define(["jquery", "underscore", "gettext", "js/views/paging", "js/views/asset",
initialize : function() {
PagingView.prototype.initialize.call(this);
var collection = this.collection;
this.template = _.template($("#asset-library-tpl").text());
this.template = this.loadTemplate("asset-library");
this.listenTo(collection, 'destroy', this.handleDestroy);
this.registerSortableColumn('js-asset-name-col', gettext('Name'), 'display_name', 'asc');
this.registerSortableColumn('js-asset-date-col', gettext('Date Added'), 'date_added', 'desc');

View File

@@ -58,6 +58,20 @@ define(["jquery", "underscore", "backbone", "js/utils/handle_iframe_binding"],
hideLoadingIndicator: function() {
$('.ui-loading').hide();
},
/**
* Loads the named template from the page, or logs an error if it fails.
* @param name The name of the template.
* @returns The loaded template.
*/
loadTemplate: function(name) {
var templateSelector = "#" + name + "-tpl",
templateText = $(templateSelector).text();
if (!templateText) {
console.error("Failed to load " + name + " template");
}
return _.template(templateText);
}
});

View File

@@ -10,7 +10,7 @@ define(["js/views/baseview", "underscore", "jquery"], function(BaseView, _, $) {
initialize : function() {
var self = this;
this.template = _.template($("#checklist-tpl").text());
this.template = this.loadTemplate('checklist');
this.collection.fetch({
reset: true,
complete: function() {

View File

@@ -11,7 +11,7 @@ define(["js/views/baseview", "underscore", "codemirror", "js/views/feedback_noti
},
initialize: function() {
this.template = _.template($("#course_info_handouts-tpl").text());
this.template = this.loadTemplate('course_info_handouts');
var self = this;
this.model.fetch({
complete: function() {

View File

@@ -13,7 +13,7 @@ define(["js/views/baseview", "underscore", "codemirror", "js/models/course_updat
},
initialize: function() {
this.template = _.template($("#course_info_update-tpl").text());
this.template = this.loadTemplate('course_info_update');
this.render();
// when the client refetches the updates as a whole, re-render them
this.listenTo(this.collection, 'reset', this.render);

View File

@@ -3,7 +3,7 @@ define(["js/views/baseview", "underscore", "underscore.string", "jquery", "gette
_.str = str; // used in template
var EditChapter = BaseView.extend({
initialize: function() {
this.template = _.template($("#edit-chapter-tpl").text());
this.template = this.loadTemplate('edit-chapter');
this.listenTo(this.model, "change", this.render);
},
tagName: "li",
@@ -54,7 +54,7 @@ define(["js/views/baseview", "underscore", "underscore.string", "jquery", "gette
var msg = new FileUploadModel({
title: _.template(gettext("Upload a new PDF to “<%= name %>”"),
{name: course.escape('name')}),
message: "Please select a PDF file to upload.",
message: gettext("Please select a PDF file to upload."),
mimeTypes: ['application/pdf']
});
var that = this;

View File

@@ -2,7 +2,7 @@ define(["js/views/baseview", "underscore", "jquery", "js/views/edit_chapter", "j
function(BaseView, _, $, EditChapterView, NotificationView) {
var EditTextbook = BaseView.extend({
initialize: function() {
this.template = _.template($("#edit-textbook-tpl").text());
this.template = this.loadTemplate('edit-textbook');
this.listenTo(this.model, "invalid", this.render);
var chapters = this.model.get('chapters');
this.listenTo(chapters, "add", this.addOne);

View File

@@ -48,11 +48,7 @@ define(["js/views/baseview", "underscore", "underscore.string", "jquery"], funct
throw "SystemFeedback: intent required (given " +
JSON.stringify(this.options) + ")";
}
var tpl = $("#system-feedback-tpl").text();
if(!tpl) {
console.error("Couldn't load system-feedback template");
}
this.template = _.template(tpl);
this.template = this.loadTemplate("system-feedback");
this.setElement($("#page-"+this.options.type));
// handle single "secondary" action
if (this.options.actions && this.options.actions.secondary &&

View File

@@ -2,7 +2,7 @@ define(["js/views/baseview", "underscore", "jquery", "js/views/edit_textbook", "
function(BaseView, _, $, EditTextbookView, ShowTextbookView) {
var ListTextbooks = BaseView.extend({
initialize: function() {
this.emptyTemplate = _.template($("#no-textbooks-tpl").text());
this.emptyTemplate = this.loadTemplate('no-textbooks');
this.listenTo(this.collection, 'all', this.render);
this.listenTo(this.collection, 'destroy', this.handleDestroy);
},

View File

@@ -11,11 +11,7 @@ function(BaseView, _, MetadataModel, AbstractEditor, VideoList, VideoTranslation
// Model is CMS.Models.MetadataCollection,
initialize : function() {
var tpl = $("#metadata-editor-tpl").text();
if(!tpl) {
console.error("Couldn't load metadata editor template");
}
this.template = _.template(tpl);
this.template = this.loadTemplate('metadata-editor');
this.$el.html(this.template({numEntries: this.collection.length}));
var counter = 0;

View File

@@ -5,24 +5,24 @@ define(["jquery", "underscore", "gettext", "js/views/baseview"],
function($, _, gettext, BaseView) {
var BaseModal = BaseView.extend({
events : {
"click .action-cancel": "cancel"
'click .action-cancel': 'cancel'
},
options: $.extend({}, BaseView.prototype.options, {
type: "prompt",
type: 'prompt',
closeIcon: false,
icon: false,
modalName: 'basic',
modalType: 'generic',
modalSize: 'lg',
title: ""
title: ''
}),
initialize: function() {
var parent = this.options.parent,
parentElement = this.options.parentElement;
this.modalTemplate = _.template($("#basic-modal-tpl").text());
this.buttonTemplate = _.template($("#modal-button-tpl").text());
this.modalTemplate = this.loadTemplate('basic-modal');
this.buttonTemplate = this.loadTemplate('modal-button');
if (parent) {
parentElement = parent.$el;
} else if (!parentElement) {
@@ -55,19 +55,16 @@ define(["jquery", "underscore", "gettext", "js/views/baseview"],
* Returns the content to be shown in the modal.
*/
getContentHtml: function() {
return "";
return '';
},
show: function() {
this.render();
this.resize();
this.lastPosition = $(document).scrollTop();
$(window).resize(_.bind(this.resize, this));
},
hide: function() {
$(document).scrollTop(this.lastPosition);
// Completely remove the modal from the DOM
this.undelegateEvents();
this.$el.html('');
@@ -84,9 +81,9 @@ define(["jquery", "underscore", "gettext", "js/views/baseview"],
*/
addActionButtons: function() {
if (this.options.addSaveButton) {
this.addActionButton('save', gettext("Save"), true);
this.addActionButton('save', gettext('Save'), true);
}
this.addActionButton('cancel', gettext("Cancel"));
this.addActionButton('cancel', gettext('Cancel'));
},
/**
@@ -119,8 +116,6 @@ define(["jquery", "underscore", "gettext", "js/views/baseview"],
left = (availableWidth - modalWidth) / 2;
top = (availableHeight - modalHeight) / 2;
// modalWindow.width(modalWidth);
// modalWindow.height(modalHeight);
modalWindow.css({
top: top + $(window).scrollTop(),
left: left + $(window).scrollLeft()

View File

@@ -20,8 +20,8 @@ define(["jquery", "underscore", "gettext", "js/views/modals/base_modal",
initialize: function() {
BaseModal.prototype.initialize.call(this);
this.events = _.extend({}, BaseModal.prototype.events, this.events);
this.template = _.template($("#edit-xblock-modal-tpl").text());
this.editorModeButtonTemplate = _.template($("#editor-mode-button-tpl").text());
this.template = this.loadTemplate('edit-xblock-modal');
this.editorModeButtonTemplate = this.loadTemplate('editor-mode-button');
},
/**

View File

@@ -1,6 +1,6 @@
define(["backbone", "underscore"], function(Backbone, _) {
define(["underscore", "js/views/baseview"], function(_, BaseView) {
var PagingFooter = Backbone.View.extend({
var PagingFooter = BaseView.extend({
events : {
"click .next-page-link": "nextPage",
"click .previous-page-link": "previousPage",
@@ -11,7 +11,7 @@ define(["backbone", "underscore"], function(Backbone, _) {
var view = options.view,
collection = view.collection;
this.view = view;
this.template = _.template($("#paging-footer-tpl").text());
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));

View File

@@ -1,6 +1,6 @@
define(["backbone", "underscore", "gettext"], function(Backbone, _, gettext) {
define(["underscore", "gettext", "js/views/baseview"], function(_, gettext, BaseView) {
var PagingHeader = Backbone.View.extend({
var PagingHeader = BaseView.extend({
events : {
"click .next-page-link": "nextPage",
"click .previous-page-link": "previousPage"
@@ -10,7 +10,7 @@ define(["backbone", "underscore", "gettext"], function(Backbone, _, gettext) {
var view = options.view,
collection = view.collection;
this.view = view;
this.template = _.template($("#paging-header-tpl").text());
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));
@@ -42,16 +42,16 @@ define(["backbone", "underscore", "gettext"], function(Backbone, _, gettext) {
fmts = gettext('Showing %(current_span)s%(start)s-%(end)s%(end_span)s out of %(total_span)s%(total)s total%(end_span)s, sorted by %(order_span)s%(sort_order)s%(end_span)s %(sort_direction)s');
return '<p>' + interpolate(fmts, {
start: Math.min(start + 1, end),
end: end,
total: total,
sort_order: sortName,
sort_direction: sortDirectionName,
current_span: '<span class="count-current-shown">',
total_span: '<span class="count-total">',
order_span: '<span class="sort-order">',
end_span: '</span>'
}, true) + "</p>";
start: Math.min(start + 1, end),
end: end,
total: total,
sort_order: sortName,
sort_direction: sortDirectionName,
current_span: '<span class="count-current-shown">',
total_span: '<span class="count-total">',
order_span: '<span class="sort-order">',
end_span: '</span>'
}, true) + "</p>";
},
nextPage: function() {

View File

@@ -9,7 +9,7 @@ define(["js/views/baseview", "underscore", "js/views/feedback_prompt", "js/views
return this;
},
initialize: function() {
this.template = _.template($("#section-name-edit-tpl").text());
this.template = this.loadTemplate('section-name-edit');
this.listenTo(this.model, "invalid", this.showInvalidMessage);
this.render();
},

View File

@@ -15,7 +15,7 @@ define(["jquery", "underscore", "gettext", "js/views/modals/base_modal", "jquery
initialize: function() {
BaseModal.prototype.initialize.call(this);
this.events = _.extend({}, BaseModal.prototype.events, this.events);
this.template = _.template($("#upload-dialog-tpl").text());
this.template = this.loadTemplate("upload-dialog");
this.listenTo(this.model, "change", this.renderContents);
this.options.title = this.model.get('title');
},
@@ -81,7 +81,7 @@ define(["jquery", "underscore", "gettext", "js/views/modals/base_modal", "jquery
});
},
progress: function(event, position, total, percentComplete) {
progress: function(event, position, total) {
this.model.set({
"uploadedBytes": position,
"totalBytes": total

View File

@@ -3,7 +3,7 @@
import json
from contentstore.utils import PublishState
from contentstore.views.helpers import xblock_studio_url
from contentstore.views.helpers import xblock_studio_url, EDITING_TEMPLATES
from django.utils.translation import ugettext as _
%>
<%block name="title">${_("Container")}</%block>
@@ -14,7 +14,7 @@ from django.utils.translation import ugettext as _
<%block name="header_extras">
% for template_name in ["basic-modal", "modal-button", "edit-xblock-modal", "editor-mode-button"]:
% for template_name in EDITING_TEMPLATES:
<script type="text/template" id="${template_name}-tpl">
<%static:include path="js/${template_name}.underscore" />
</script>
@@ -30,14 +30,14 @@ main_xblock_info = {
};
%>
<script type='text/javascript'>
require(["domReady!", "jquery", "js/models/xblock_info", "js/views/xblock_container",
require(["domReady!", "jquery", "js/models/xblock_info", "js/views/pages/container",
"xmodule", "coffee/src/main", "xblock/cms.runtime.v1"],
function(doc, $, XBlockInfo, XBlockContainerView) {
function(doc, $, XBlockInfo, XBlockContainerPage) {
var view, mainXBlockInfo;
mainXBlockInfo = new XBlockInfo(${json.dumps(main_xblock_info) | n});
view = new XBlockContainerView({
view = new XBlockContainerPage({
el: $('#content'),
model: mainXBlockInfo
});

View File

@@ -0,0 +1,42 @@
<div id="content">
<div class="wrapper-mast wrapper" data-location="" data-display-name="" data-category="">
<header class="mast has-actions has-navigation">
<h1 class="page-header">
<small class="navigation navigation-parents">
<a href="/unit/TestCourse/branch/draft/block/vertical8eb" class="navigation-link navigation-parent">Unit 1</a>
<a href="#" class="navigation-link navigation-current">Nested Vertical Test</a>
</small>
</h1>
<nav class="nav-actions">
<h3 class="sr">Page Actions</h3>
<ul>
</ul>
</nav>
</header>
</div>
<div class="wrapper-content wrapper">
<div class="inner-wrapper">
<section class="content-area">
<article class="content-primary window">
<section class="wrapper-xblock level-page" data-locator="TestCourse/branch/draft/block/vertical131">
</section>
<div class="no-container-content is-hidden">
<p>This page has no content yet.</p>
</div>
<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">
</aside>
</section>
</div>
</div>
<div id="page-notification"></div>
</div>

View File

@@ -1,117 +0,0 @@
<div id="content">
<div class="wrapper-mast wrapper" data-location="" data-display-name="" data-category="">
<header class="mast has-actions has-navigation">
<h1 class="page-header">
<small class="navigation navigation-parents">
<a href="/unit/TestCourse/branch/draft/block/vertical8eb" class="navigation-link navigation-parent">Unit 1</a>
<a href="#" class="navigation-link navigation-current">Nested Vertical Test</a>
</small>
</h1>
<nav class="nav-actions">
<h3 class="sr">Page Actions</h3>
<ul>
</ul>
</nav>
</header>
</div>
<div class="wrapper-content wrapper">
<div class="inner-wrapper">
<section class="content-area">
<article class="content-primary window">
<section class="wrapper-xblock level-page" data-locator="TestCourse/branch/draft/block/vertical131">
</section>
<div class="no-container-content is-hidden">
<p>This page has no content yet.</p>
</div>
<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 class="bit-publishing">
<h3 class="title-3">Publishing Status</h3>
<p class="copy">
This content is published with unit <a href="/unit/TestCourse/branch/draft/block/vertical8eb">Unit 1</a>.
Say something useful about <a href="/unit/TestCourse/branch/draft/block/vertical8eb">Unit 1</a> being in draft or private mode.
</p>
</div>
<div class="bit">
<h3 class="title-3">What can I do on this page?</h3>
<ul class="list-details">
<li class="item-detail">You can view course components that contain other components on this page. In the case of experiment blocks, this allows you to confirm that you have properly configured your experiment groups.</li>
</ul>
</div>
</aside>
</section>
</div>
</div>
<script type="text/javascript">
require(['js/sock']);
</script>
<div class="wrapper-sock wrapper">
<ul class="list-actions list-cta">
<li class="action-item">
<a href="#sock" class="cta cta-show-sock"><i class="icon-question-sign"></i> <span class="copy">Looking for Help with Studio?</span></a>
</li>
</ul>
<div class="wrapper-inner wrapper">
<section class="sock" id="sock">
<header>
<h2 class="title sr">edX Studio Help</h2>
</header>
<div class="support">
<h3 class="title">Studio Support</h3>
<div class="copy">
<p>Need help with Studio? Creating a course is complex, so we're here to help. Take advantage of our documentation, help center, as well as our edX101 introduction course for course authors.</p>
</div>
<ul class="list-actions">
<li class="action-item">
<a href="http://files.edx.org/Getting_Started_with_Studio.pdf" class="action action-primary" title="This is a PDF Document">Download Studio Documentation</a>
<span class="tip">How to use Studio to build your course</span>
</li>
<li class="action-item">
<a href="http://help.edge.edx.org/" rel="external" class="action action-primary" title="This link will open in a new browser window/tab">Studio Help Center</a>
<span class="tip">Studio Help Center</span>
</li>
<li class="action-item">
<a href="https://edge.edx.org/courses/edX/edX101/How_to_Create_an_edX_Course/about" rel="external" class="action action-primary" title="This link will open in a new browser window/tab">Enroll in edX101</a>
<span class="tip">How to use Studio to build your course</span>
</li>
</ul>
</div>
<div class="feedback">
<h3 class="title">Contact us about Studio</h3>
<div class="copy">
<p>Have problems, questions, or suggestions about Studio? We're also here to listen to any feedback you want to share.</p>
</div>
<ul class="list-actions">
<li class="action-item">
<a href="http://help.edge.edx.org/discussion/new" class="action action-primary show-tender" title="Use our feedback tool, Tender, to share your feedback"><i class="icon-comments"></i>Contact Us</a>
</li>
</ul>
</div>
</section>
</div>
</div>
<div id="page-notification"></div>
</div>

View File

@@ -1,6 +1,7 @@
<%inherit file="base.html" />
<%!
from django.core.urlresolvers import reverse
from contentstore.views.helpers import EDITING_TEMPLATES
from django.utils.translation import ugettext as _
from xmodule.modulestore.django import loc_mapper
%>
@@ -10,7 +11,7 @@ from xmodule.modulestore.django import loc_mapper
<%block name="bodyclass">is-signedin course unit view-unit feature-upload</%block>
<%block name="header_extras">
% for template_name in ["image-modal", "basic-modal", "modal-button", "edit-xblock-modal", "editor-mode-button", "upload-dialog"]:
% for template_name in EDITING_TEMPLATES:
<script type="text/template" id="${template_name}-tpl">
<%static:include path="js/${template_name}.underscore" />
</script>