Fix STUD-1316

This bug affected unpublishing content (and would trigger an error
message in studio). The fix was to uncouple the rendering of the studio_view
of an xblock with the student_view, so that content that wasn't in
draft mode already wouldn't be modified by early rendering of the
studio_view.

[STUD-1316]
This commit is contained in:
Calen Pennington
2014-02-18 14:15:19 -05:00
parent ab938c094b
commit 1eec47a604
11 changed files with 170 additions and 92 deletions

View File

@@ -55,6 +55,7 @@ define ["jquery", "coffee/src/views/module_edit", "js/models/module_info", "xmod
describe "render", ->
beforeEach ->
spyOn(@moduleEdit, 'loadDisplay')
spyOn(@moduleEdit, 'loadEdit')
spyOn(@moduleEdit, 'delegateEvents')
spyOn($.fn, 'append')
spyOn($, 'getScript')
@@ -74,15 +75,58 @@ define ["jquery", "coffee/src/views/module_edit", "js/models/module_info", "xmod
]
)
it "loads the module preview and editor via ajax on the view element", ->
it "loads the module preview via ajax on the view element", ->
expect($.ajax).toHaveBeenCalledWith(
url: "/xblock/#{@moduleEdit.model.id}"
url: "/xblock/#{@moduleEdit.model.id}/student_view"
type: "GET"
headers:
Accept: 'application/x-fragment+json'
success: jasmine.any(Function)
)
expect($.ajax).not.toHaveBeenCalledWith(
url: "/xblock/#{@moduleEdit.model.id}/studio_view"
type: "GET"
headers:
Accept: 'application/x-fragment+json'
success: jasmine.any(Function)
)
expect(@moduleEdit.loadDisplay).toHaveBeenCalled()
expect(@moduleEdit.loadEdit).not.toHaveBeenCalled()
expect(@moduleEdit.delegateEvents).toHaveBeenCalled()
it "loads the editing view via ajax on demand", ->
expect($.ajax).not.toHaveBeenCalledWith(
url: "/xblock/#{@moduleEdit.model.id}/studio_view"
type: "GET"
headers:
Accept: 'application/x-fragment+json'
success: jasmine.any(Function)
)
expect(@moduleEdit.loadEdit).not.toHaveBeenCalled()
@moduleEdit.clickEditButton({'preventDefault': jasmine.createSpy('event.preventDefault')})
$.ajax.mostRecentCall.args[0].success(
html: '<div>Response html</div>'
resources: [
['hash1', {kind: 'text', mimetype: 'text/css', data: 'inline-css'}],
['hash2', {kind: 'url', mimetype: 'text/css', data: 'css-url'}],
['hash3', {kind: 'text', mimetype: 'application/javascript', data: 'inline-js'}],
['hash4', {kind: 'url', mimetype: 'application/javascript', data: 'js-url'}],
['hash5', {placement: 'head', mimetype: 'text/html', data: 'head-html'}],
['hash6', {placement: 'not-head', mimetype: 'text/html', data: 'not-head-html'}],
]
)
expect($.ajax).toHaveBeenCalledWith(
url: "/xblock/#{@moduleEdit.model.id}/studio_view"
type: "GET"
headers:
Accept: 'application/x-fragment+json'
success: jasmine.any(Function)
)
expect(@moduleEdit.loadEdit).toHaveBeenCalled()
expect(@moduleEdit.delegateEvents).toHaveBeenCalled()
it "loads inline css from fragments", ->

View File

@@ -18,37 +18,37 @@ define ["backbone", "jquery", "underscore", "gettext", "xblock/runtime.v1",
@onDelete = @options.onDelete
@render()
$component_editor: => @$el.find('.component-editor')
$componentEditor: => @$el.find('.component-editor')
$moduleEditor: => @$componentEditor().find('.module-editor')
loadDisplay: ->
XBlock.initializeBlock(@$el.find('.xblock-student_view'))
loadEdit: ->
if not @module
@module = XBlock.initializeBlock(@$el.find('.xblock-studio_view'))
# At this point, metadata-edit.html will be loaded, and the metadata (as JSON) is available.
metadataEditor = @$el.find('.metadata_edit')
metadataData = metadataEditor.data('metadata')
models = [];
for key of metadataData
models.push(metadataData[key])
@metadataEditor = new MetadataView.Editor({
el: metadataEditor,
collection: new MetadataCollection(models)
})
@module = XBlock.initializeBlock(@$el.find('.xblock-studio_view'))
# At this point, metadata-edit.html will be loaded, and the metadata (as JSON) is available.
metadataEditor = @$el.find('.metadata_edit')
metadataData = metadataEditor.data('metadata')
models = [];
for key of metadataData
models.push(metadataData[key])
@metadataEditor = new MetadataView.Editor({
el: metadataEditor,
collection: new MetadataCollection(models)
})
@module.setMetadataEditor(@metadataEditor) if @module.setMetadataEditor
@module.setMetadataEditor(@metadataEditor) if @module.setMetadataEditor
# Need to update set "active" class on data editor if there is one.
# If we are only showing settings, hide the data editor controls and update settings accordingly.
if @hasDataEditor()
@selectMode(@editorMode)
else
@hideDataEditor()
# Need to update set "active" class on data editor if there is one.
# If we are only showing settings, hide the data editor controls and update settings accordingly.
if @hasDataEditor()
@selectMode(@editorMode)
else
@hideDataEditor()
title = interpolate(gettext('<em>Editing:</em> %s'),
[@metadataEditor.getDisplayName()])
@$el.find('.component-name').html(title)
title = interpolate(gettext('<em>Editing:</em> %s'),
[@metadataEditor.getDisplayName()])
@$el.find('.component-name').html(title)
customMetadata: ->
# Hack to support metadata fields that aren't part of the metadata editor (ie, LaTeX high level source).
@@ -56,7 +56,7 @@ define ["backbone", "jquery", "underscore", "gettext", "xblock/runtime.v1",
# build up an object to pass back to the server on the subsequent POST.
# Note that these values will always be sent back on POST, even if they did not actually change.
_metadata = {}
_metadata[$(el).data("metadata-name")] = el.value for el in $('[data-metadata-name]', @$component_editor())
_metadata[$(el).data("metadata-name")] = el.value for el in $('[data-metadata-name]', @$componentEditor())
return _metadata
changedMetadata: ->
@@ -73,15 +73,15 @@ define ["backbone", "jquery", "underscore", "gettext", "xblock/runtime.v1",
@render()
).success(callback)
render: ->
loadView: (viewName, target, callback) ->
if @model.id
$.ajax(
url: @model.url()
url: "#{decodeURIComponent(@model.url())}/#{viewName}"
type: 'GET'
headers:
Accept: 'application/x-fragment+json'
success: (data) =>
@$el.html(data.html)
$(target).html(data.html)
for value in data.resources
do (value) =>
@@ -104,10 +104,14 @@ define ["backbone", "jquery", "underscore", "gettext", "xblock/runtime.v1",
switch resource.placement
when "head" then $('head').append(resource.data)
window.loadedXBlockResources.push(hash)
@loadDisplay()
@delegateEvents()
callback()
)
render: -> @loadView('student_view', @$el, =>
@loadDisplay()
@delegateEvents()
)
clickSaveButton: (event) =>
event.preventDefault()
data = @module.save()
@@ -122,7 +126,6 @@ define ["backbone", "jquery", "underscore", "gettext", "xblock/runtime.v1",
title: gettext('Saving&hellip;')
saving.show()
@model.save(data).done( =>
@module = null
@render()
@$el.removeClass('editing')
saving.hide()
@@ -131,15 +134,18 @@ define ["backbone", "jquery", "underscore", "gettext", "xblock/runtime.v1",
clickCancelButton: (event) ->
event.preventDefault()
@$el.removeClass('editing')
@$component_editor().slideUp(150)
@$componentEditor().slideUp(150)
ModalUtils.hideModalCover()
clickEditButton: (event) ->
event.preventDefault()
@$el.addClass('editing')
ModalUtils.showModalCover(true)
@$component_editor().slideDown(150)
@loadEdit()
@loadView('studio_view', @$moduleEditor(), =>
@$componentEditor().slideDown(150)
@loadEdit()
@delegateEvents()
)
clickModeButton: (event) ->
event.preventDefault()