Commit a6aae729 by Andy Armstrong

Address the next round of review comments.

parent 88d95d11
......@@ -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"]'
......
......@@ -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):
......
......@@ -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
......
......@@ -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",
......
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"
......
......@@ -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() {
......
......@@ -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);
});
......
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');
......
......@@ -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;
});
......
......@@ -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'
});
......
......@@ -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
});
});
......@@ -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
};
});
......@@ -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",
......
......@@ -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');
......
......@@ -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);
}
});
......
......@@ -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() {
......
......@@ -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() {
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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 &&
......
......@@ -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);
},
......
......@@ -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;
......
......@@ -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()
......
......@@ -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');
},
/**
......
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));
......
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() {
......
......@@ -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();
},
......
......@@ -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
......
......@@ -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
});
......
<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>
<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>
</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">
</nav>
</header>
</div>
<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 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>
<div id="page-notification"></div>
<div id="page-notification"></div>
</div>
\ No newline at end of file
<%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>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment