Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
a3b28096
Commit
a3b28096
authored
10 years ago
by
Andy Armstrong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix duplicate save and cancel buttons in Studio
STUD-1531 Also add support for refreshing the modal on custom save
parent
b95b595e
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
277 additions
and
192 deletions
+277
-192
cms/djangoapps/contentstore/views/item.py
+0
-4
cms/djangoapps/contentstore/views/tests/test_item.py
+0
-31
cms/static/coffee/spec/views/module_edit_spec.coffee
+0
-1
cms/static/coffee/src/views/module_edit.coffee
+0
-1
cms/static/coffee/src/xblock/cms.runtime.v1.coffee
+59
-57
cms/static/js/spec/views/modals/edit_xblock_spec.js
+50
-8
cms/static/js/spec/views/pages/container_spec.js
+24
-1
cms/static/js/spec/views/xblock_editor_spec.js
+0
-14
cms/static/js/spec_helpers/edit_helpers.js
+6
-10
cms/static/js/spec_helpers/modal_helpers.js
+1
-1
cms/static/js/views/modals/base_modal.js
+19
-3
cms/static/js/views/modals/edit_xblock.js
+48
-10
cms/static/js/views/xblock_editor.js
+30
-17
cms/static/sass/elements/_modal-window.scss
+18
-1
cms/templates/component.html
+0
-26
cms/templates/container.html
+0
-3
cms/templates/edit-tabs.html
+0
-2
cms/templates/js/basic-modal.underscore
+1
-1
cms/templates/js/mock/mock-xblock-editor-with-custom-buttons.underscore
+20
-0
cms/templates/unit.html
+0
-1
common/static/coffee/src/xblock/core.coffee
+1
-0
No files found.
cms/djangoapps/contentstore/views/item.py
View file @
a3b28096
...
...
@@ -246,10 +246,6 @@ def xblock_view_handler(request, package_id, view_name, tag=None, branch=None, v
fragment
.
content
=
render_to_string
(
'component.html'
,
{
'preview'
:
fragment
.
content
,
'label'
:
component
.
display_name
or
component
.
scope_ids
.
block_type
,
# Native XBlocks are responsible for persisting their own data,
# so they are also responsible for providing save/cancel buttons.
'show_save_cancel'
:
isinstance
(
component
,
xmodule
.
x_module
.
XModuleDescriptor
),
})
else
:
raise
Http404
...
...
This diff is collapsed.
Click to expand it.
cms/djangoapps/contentstore/views/tests/test_item.py
View file @
a3b28096
...
...
@@ -765,34 +765,3 @@ class TestComponentHandler(TestCase):
self
.
descriptor
.
handle
=
create_response
self
.
assertEquals
(
component_handler
(
self
.
request
,
self
.
usage_id
,
'dummy_handler'
)
.
status_code
,
status_code
)
@ddt.ddt
class
TestNativeXBlock
(
ItemTest
):
"""
Test a "native" XBlock (not an XModule shim).
"""
@ddt.data
((
'problem'
,
True
),
(
'acid'
,
False
))
@ddt.unpack
def
test_save_cancel_buttons
(
self
,
category
,
include_buttons
):
"""
Native XBlocks handle their own persistence, so Studio
should not render Save/Cancel buttons for them.
"""
# Create the XBlock
resp
=
self
.
create_xblock
(
category
=
category
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
native_loc
=
json
.
loads
(
resp
.
content
)[
'locator'
]
# Render the XBlock
view_url
=
'/xblock/{locator}/student_view'
.
format
(
locator
=
native_loc
)
resp
=
self
.
client
.
get
(
view_url
,
HTTP_ACCEPT
=
'application/json'
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
# Check that the save and cancel buttons are hidden for native XBlocks,
# but shown for XModule shim XBlocks
resp_html
=
json
.
loads
(
resp
.
content
)[
'html'
]
assert_func
=
self
.
assertIn
if
include_buttons
else
self
.
assertNotIn
assert_func
(
'save-button'
,
resp_html
)
assert_func
(
'cancel-button'
,
resp_html
)
This diff is collapsed.
Click to expand it.
cms/static/coffee/spec/views/module_edit_spec.coffee
View file @
a3b28096
...
...
@@ -25,7 +25,6 @@ define ["jquery", "js/spec_helpers/edit_helpers", "coffee/src/views/module_edit"
</section>
</li>
</ul>
<div class="edit-xblock-modal"/>
"""
edit_helpers
.
installEditTemplates
(
true
);
spyOn
(
$
,
'ajax'
).
andReturn
(
@
moduleData
)
...
...
This diff is collapsed.
Click to expand it.
cms/static/coffee/src/views/module_edit.coffee
View file @
a3b28096
...
...
@@ -47,7 +47,6 @@ define ["jquery", "underscore", "gettext", "xblock/runtime.v1",
clickEditButton
:
(
event
)
->
event
.
preventDefault
()
modal
=
new
EditXBlockModal
({
el
:
$
(
'.edit-xblock-modal'
),
view
:
'student_view'
});
modal
.
edit
(
this
.
$el
,
self
.
model
,
{
refresh
:
_
.
bind
(
@
render
,
this
)
})
This diff is collapsed.
Click to expand it.
cms/static/coffee/src/xblock/cms.runtime.v1.coffee
View file @
a3b28096
...
...
@@ -5,74 +5,76 @@ define [
@
PreviewRuntime
=
{}
class
PreviewRuntime
.
v1
extends
XBlock
.
Runtime
.
v1
handlerUrl
:
(
element
,
handlerName
,
suffix
,
query
,
thirdparty
)
->
uri
=
URI
(
"/preview/xblock"
).
segment
(
$
(
element
).
data
(
'usage-id'
))
.
segment
(
'handler'
)
.
segment
(
handlerName
)
if
suffix
?
then
uri
.
segment
(
suffix
)
if
query
?
then
uri
.
search
(
query
)
uri
.
toString
()
handlerUrl
:
(
element
,
handlerName
,
suffix
,
query
,
thirdparty
)
->
uri
=
URI
(
"/preview/xblock"
).
segment
(
$
(
element
).
data
(
'usage-id'
))
.
segment
(
'handler'
)
.
segment
(
handlerName
)
if
suffix
?
then
uri
.
segment
(
suffix
)
if
query
?
then
uri
.
search
(
query
)
uri
.
toString
()
@
StudioRuntime
=
{}
class
StudioRuntime
.
v1
extends
XBlock
.
Runtime
.
v1
constructor
:
()
->
super
()
@
savingNotification
=
new
NotificationView
.
Mini
title
:
gettext
(
'Saving…'
)
@
alert
=
new
NotificationView
.
Error
title
:
"OpenAssessment Save Error"
,
closeIcon
:
false
,
shown
:
false
constructor
:
()
->
super
()
@
savingNotification
=
new
NotificationView
.
Mini
title
:
gettext
(
'Saving…'
)
@
alert
=
new
NotificationView
.
Error
title
:
"OpenAssessment Save Error"
,
closeIcon
:
false
,
shown
:
false
handlerUrl
:
(
element
,
handlerName
,
suffix
,
query
,
thirdparty
)
->
uri
=
URI
(
"/xblock"
).
segment
(
$
(
element
).
data
(
'usage-id'
))
.
segment
(
'handler'
)
.
segment
(
handlerName
)
if
suffix
?
then
uri
.
segment
(
suffix
)
if
query
?
then
uri
.
search
(
query
)
uri
.
toString
()
handlerUrl
:
(
element
,
handlerName
,
suffix
,
query
,
thirdparty
)
->
uri
=
URI
(
"/xblock"
).
segment
(
$
(
element
).
data
(
'usage-id'
))
.
segment
(
'handler'
)
.
segment
(
handlerName
)
if
suffix
?
then
uri
.
segment
(
suffix
)
if
query
?
then
uri
.
search
(
query
)
uri
.
toString
()
# Notify the Studio client-side runtime so it can update
# the UI in a consistent way. Currently, this is used
# for save / cancel when editing an XBlock.
# Although native XBlocks should handle their own persistence,
# Studio still needs to update the UI in a consistent way
# (showing the "Saving..." notification, closing the modal editing dialog, etc.)
notify
:
(
name
,
data
)
->
if
name
==
'save'
if
'state'
of
data
# Notify the Studio client-side runtime so it can update
# the UI in a consistent way. Currently, this is used
# for save / cancel when editing an XBlock.
# Although native XBlocks should handle their own persistence,
# Studio still needs to update the UI in a consistent way
# (showing the "Saving..." notification, closing the modal editing dialog, etc.)
notify
:
(
name
,
data
)
->
if
name
==
'save'
if
'state'
of
data
# Starting to save, so show the "Saving..." notification
if
data
.
state
==
'start'
@
savingNotification
.
show
()
# Starting to save, so show the "Saving..." notification
if
data
.
state
==
'start'
@
savingNotification
.
show
()
# Finished saving, so hide the "Saving..." notification
else
if
data
.
state
==
'end'
# Finished saving, so hide the "Saving..." notification
else
if
data
.
state
==
'end'
@
_hideAlerts
()
# Hide the editor *after* we finish saving in case there are validation
# errors that the user needs to correct.
@
_hideEditor
()
# Notify the modal that the save has completed so that it can hide itself
# and then refresh the xblock.
if
@
modal
@
modal
.
onSave
()
$
(
'.component.editing'
).
removeClass
(
'editing'
)
@
savingNotification
.
hide
()
@
savingNotification
.
hide
()
else
if
name
==
'cancel
'
@
_hideEditor
()
else
if
name
==
'edit-modal-shown
'
@
modal
=
data
else
if
name
==
'error'
if
'msg'
of
data
@
alert
.
options
.
message
=
data
.
msg
@
alert
.
show
()
else
if
name
==
'edit-modal-hidden'
@
modal
=
null
_hideEditor
:
()
->
# This will close all open component editors, which works
# if we assume that <= 1 are open at a time.
el
=
$
(
'.component.editing'
)
el
.
removeClass
(
'editing'
)
el
.
find
(
'.component-editor'
).
slideUp
(
150
)
ModalUtils
.
hideModalCover
()
else
if
name
==
'cancel'
@
_hideAlerts
()
if
@
modal
@
modal
.
cancel
()
# Hide any alerts that are being shown
if
@
alert
.
options
.
shown
@
alert
.
hide
()
else
if
name
==
'error'
if
'msg'
of
data
@
alert
.
options
.
message
=
data
.
msg
@
alert
.
show
()
_hideAlerts
:
()
->
# Hide any alerts that are being shown
if
@
alert
.
options
.
shown
@
alert
.
hide
()
This diff is collapsed.
Click to expand it.
cms/static/js/spec/views/modals/edit_xblock_spec.js
View file @
a3b28096
...
...
@@ -5,9 +5,9 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
describe
(
"EditXBlockModal"
,
function
()
{
var
model
,
modal
,
showModal
;
showModal
=
function
(
requests
,
mockHtml
)
{
showModal
=
function
(
requests
,
mockHtml
,
options
)
{
var
xblockElement
=
$
(
'.xblock'
);
return
edit_helpers
.
showEditModal
(
requests
,
xblockElement
,
model
,
mockHtml
);
return
edit_helpers
.
showEditModal
(
requests
,
xblockElement
,
model
,
mockHtml
,
options
);
};
beforeEach
(
function
()
{
...
...
@@ -45,6 +45,13 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
expect
(
edit_helpers
.
isShowingModal
(
modal
)).
toBeFalsy
();
});
it
(
'does not show the "Save" button'
,
function
()
{
var
requests
=
create_sinon
.
requests
(
this
);
modal
=
showModal
(
requests
,
mockXBlockEditorHtml
);
expect
(
modal
.
$
(
'.action-save'
)).
not
.
toBeVisible
();
expect
(
modal
.
$
(
'.action-cancel'
).
text
()).
toBe
(
'OK'
);
});
it
(
'shows the correct title'
,
function
()
{
var
requests
=
create_sinon
.
requests
(
this
);
modal
=
showModal
(
requests
,
mockXBlockEditorHtml
);
...
...
@@ -56,6 +63,43 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
modal
=
showModal
(
requests
,
mockXBlockEditorHtml
);
expect
(
modal
.
$
(
'.editor-modes a'
).
length
).
toBe
(
0
);
});
it
(
'hides itself and refreshes after save notification'
,
function
()
{
var
requests
=
create_sinon
.
requests
(
this
),
refreshed
=
false
,
refresh
=
function
()
{
refreshed
=
true
;
};
modal
=
showModal
(
requests
,
mockXBlockEditorHtml
,
{
refresh
:
refresh
});
modal
.
runtime
.
notify
(
'save'
,
{
state
:
'start'
});
modal
.
runtime
.
notify
(
'save'
,
{
state
:
'end'
});
expect
(
edit_helpers
.
isShowingModal
(
modal
)).
toBeFalsy
();
expect
(
refreshed
).
toBeTruthy
();
});
it
(
'hides itself and does not refresh after cancel notification'
,
function
()
{
var
requests
=
create_sinon
.
requests
(
this
),
refreshed
=
false
,
refresh
=
function
()
{
refreshed
=
true
;
};
modal
=
showModal
(
requests
,
mockXBlockEditorHtml
,
{
refresh
:
refresh
});
modal
.
runtime
.
notify
(
'cancel'
);
expect
(
edit_helpers
.
isShowingModal
(
modal
)).
toBeFalsy
();
expect
(
refreshed
).
toBeFalsy
();
});
describe
(
"Custom Buttons"
,
function
()
{
var
mockCustomButtonsHtml
;
mockCustomButtonsHtml
=
readFixtures
(
'mock/mock-xblock-editor-with-custom-buttons.underscore'
);
it
(
'hides the modal
\'
s button bar'
,
function
()
{
var
requests
=
create_sinon
.
requests
(
this
);
modal
=
showModal
(
requests
,
mockCustomButtonsHtml
);
expect
(
modal
.
$
(
'.modal-actions'
)).
toBeHidden
();
});
});
});
describe
(
"XModule Editor"
,
function
()
{
...
...
@@ -64,12 +108,11 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
mockXModuleEditorHtml
=
readFixtures
(
'mock/mock-xmodule-editor.underscore'
);
beforeEach
(
function
()
{
// Mock the VerticalDescriptor so that the module can be rendered
window
.
VerticalDescriptor
=
XModule
.
Descriptor
;
edit_helpers
.
installMockXModule
();
});
afterEach
(
function
()
{
window
.
VerticalDescriptor
=
null
;
edit_helpers
.
uninstallMockXModule
()
;
});
it
(
'can render itself'
,
function
()
{
...
...
@@ -140,12 +183,11 @@ define(["jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helpers
mockXModuleEditorHtml
=
readFixtures
(
'mock/mock-xmodule-settings-only-editor.underscore'
);
beforeEach
(
function
()
{
// Mock the VerticalDescriptor so that the module can be rendered
window
.
VerticalDescriptor
=
XModule
.
Descriptor
;
edit_helpers
.
installMockXModule
();
});
afterEach
(
function
()
{
window
.
VerticalDescriptor
=
null
;
edit_helpers
.
uninstallMockXModule
()
;
});
it
(
'can render itself'
,
function
()
{
...
...
This diff is collapsed.
Click to expand it.
cms/static/js/spec/views/pages/container_spec.js
View file @
a3b28096
...
...
@@ -107,6 +107,29 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
});
expect
(
edit_helpers
.
isShowingModal
()).
toBeTruthy
();
});
});
describe
(
"Editing an xmodule"
,
function
()
{
var
mockContainerXBlockHtml
,
mockXModuleEditor
,
newDisplayName
=
'New Display Name'
;
beforeEach
(
function
()
{
edit_helpers
.
installMockXModule
({
data
:
"<p>Some HTML</p>"
,
metadata
:
{
display_name
:
newDisplayName
}
});
});
afterEach
(
function
()
{
edit_helpers
.
uninstallMockXModule
();
edit_helpers
.
cancelModalIfShowing
();
});
mockContainerXBlockHtml
=
readFixtures
(
'mock/mock-container-xblock.underscore'
);
mockXModuleEditor
=
readFixtures
(
'mock/mock-xmodule-editor.underscore'
);
it
(
'can save changes to settings'
,
function
()
{
var
editButtons
,
modal
,
mockUpdatedXBlockHtml
;
...
...
@@ -117,7 +140,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/edit_helpers"
expect
(
editButtons
.
length
).
toBe
(
6
);
editButtons
.
first
().
click
();
create_sinon
.
respondWithJson
(
requests
,
{
html
:
mockX
BlockEditorHtml
,
html
:
mockX
ModuleEditor
,
resources
:
[]
});
...
...
This diff is collapsed.
Click to expand it.
cms/static/js/spec/views/xblock_editor_spec.js
View file @
a3b28096
...
...
@@ -49,20 +49,6 @@ define([ "jquery", "underscore", "js/spec_helpers/create_sinon", "js/spec_helper
expect
(
editor
.
$el
.
select
(
'.xblock-header'
)).
toBeTruthy
();
expect
(
editor
.
getMode
()).
toEqual
(
'settings'
);
});
it
(
'saves any custom metadata'
,
function
()
{
var
requests
=
create_sinon
.
requests
(
this
),
request
,
response
;
editor
.
render
();
create_sinon
.
respondWithJson
(
requests
,
{
html
:
mockXBlockEditorHtml
,
resources
:
[]
});
editor
.
save
();
request
=
requests
[
requests
.
length
-
1
];
response
=
JSON
.
parse
(
request
.
requestBody
);
expect
(
response
.
metadata
.
display_name
).
toBe
(
testDisplayName
);
expect
(
response
.
metadata
.
custom_field
).
toBe
(
'Custom Value'
);
});
});
describe
(
"Editing an xmodule"
,
function
()
{
...
...
This diff is collapsed.
Click to expand it.
cms/static/js/spec_helpers/edit_helpers.js
View file @
a3b28096
/**
* 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"
],
function
(
$
,
create_sinon
,
modal_helpers
,
EditXBlockModal
)
{
define
([
"jquery"
,
"
underscore"
,
"js/spec_helpers/create_sinon"
,
"js/spec_helpers/modal_helpers
"
,
"
js/views/modals/edit_xblock"
,
"
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'
),
...
...
@@ -12,19 +12,15 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/modal_helpers
editorModeButtonTemplate
=
readFixtures
(
'editor-mode-button.underscore'
),
installMockXBlock
,
uninstallMockXBlock
,
hasSavedMockXBlock
,
installMockXModule
,
uninstallMockXModule
,
hasSavedMockXModule
,
installEditTemplates
,
showEditModal
;
installMockXBlock
=
function
(
mockResult
)
{
window
.
MockXBlock
=
function
(
runtime
,
element
)
{
return
{
save
:
function
()
{
return
mockResult
;
}
runtime
:
runtime
};
};
};
...
...
@@ -58,9 +54,9 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/modal_helpers
appendSetFixtures
(
$
(
"<script>"
,
{
id
:
"metadata-string-entry"
,
type
:
"text/template"
}).
text
(
stringEntryTemplate
));
};
showEditModal
=
function
(
requests
,
xblockElement
,
model
,
mockHtml
)
{
showEditModal
=
function
(
requests
,
xblockElement
,
model
,
mockHtml
,
options
)
{
var
modal
=
new
EditXBlockModal
({});
modal
.
edit
(
xblockElement
,
model
);
modal
.
edit
(
xblockElement
,
model
,
options
);
create_sinon
.
respondWithJson
(
requests
,
{
html
:
mockHtml
,
"resources"
:
[]
...
...
This diff is collapsed.
Click to expand it.
cms/static/js/spec_helpers/modal_helpers.js
View file @
a3b28096
...
...
@@ -47,7 +47,7 @@ define(["jquery"],
cancelModal
=
function
(
modal
)
{
var
modalElement
,
cancelButton
;
modalElement
=
getModalElement
(
modal
);
cancelButton
=
modalElement
.
find
(
'.action-cancel'
);
cancelButton
=
modalElement
.
find
(
'.action-cancel
:visible
'
);
expect
(
cancelButton
.
length
).
toBe
(
1
);
cancelButton
.
click
();
};
...
...
This diff is collapsed.
Click to expand it.
cms/static/js/views/modals/base_modal.js
View file @
a3b28096
...
...
@@ -71,8 +71,10 @@ define(["jquery", "underscore", "gettext", "js/views/baseview"],
},
cancel
:
function
(
event
)
{
event
.
preventDefault
();
event
.
stopPropagation
();
// Make sure parent modals don't see the click
if
(
event
)
{
event
.
preventDefault
();
event
.
stopPropagation
();
// Make sure parent modals don't see the click
}
this
.
hide
();
},
...
...
@@ -98,7 +100,21 @@ define(["jquery", "underscore", "gettext", "js/views/baseview"],
name
:
name
,
isPrimary
:
isPrimary
});
this
.
$
(
'.modal-actions ul'
).
append
(
html
);
this
.
getActionBar
().
find
(
'ul'
).
append
(
html
);
},
/**
* Returns the action bar that contains the modal's action buttons.
*/
getActionBar
:
function
()
{
return
this
.
$
(
'.modal-window > div > .modal-actions'
);
},
/**
* Returns the action button of the specified type.
*/
getActionButton
:
function
(
type
)
{
return
this
.
getActionBar
().
find
(
'.action-'
+
type
);
},
resize
:
function
()
{
...
...
This diff is collapsed.
Click to expand it.
cms/static/js/views/modals/edit_xblock.js
View file @
a3b28096
...
...
@@ -37,6 +37,10 @@ define(["jquery", "underscore", "gettext", "js/views/modals/base_modal",
this
.
editOptions
=
options
;
this
.
render
();
this
.
show
();
// Hide the action bar until we know which buttons we want
this
.
getActionBar
().
hide
();
// Display the xblock after the modal is shown as there are some xblocks
// that depend upon being visible when they initialize, e.g. the problem xmodule.
this
.
displayXBlock
();
...
...
@@ -60,7 +64,17 @@ define(["jquery", "underscore", "gettext", "js/views/modals/base_modal",
onDisplayXBlock
:
function
()
{
var
editorView
=
this
.
editorView
,
title
=
this
.
getTitle
();
title
=
this
.
getTitle
(),
xblock
=
editorView
.
xblock
,
runtime
=
xblock
.
runtime
;
// Notify the runtime that the modal has been shown
if
(
runtime
)
{
this
.
runtime
=
runtime
;
runtime
.
notify
(
"edit-modal-shown"
,
this
);
}
// Update the modal's header
if
(
editorView
.
hasCustomTabs
())
{
// Hide the modal's header as the custom editor provides its own
this
.
$
(
'.modal-header'
).
hide
();
...
...
@@ -74,9 +88,28 @@ define(["jquery", "underscore", "gettext", "js/views/modals/base_modal",
this
.
selectMode
(
editorView
.
mode
);
}
}
// If the xblock is not using custom buttons then choose which buttons to show
if
(
!
editorView
.
hasCustomButtons
())
{
// If the xblock does not support save then disable the save button
if
(
!
xblock
.
save
)
{
this
.
disableSave
();
}
this
.
getActionBar
().
show
();
}
// Resize the modal to fit the window
this
.
resize
();
},
disableSave
:
function
()
{
var
saveButton
=
this
.
getActionButton
(
'save'
),
cancelButton
=
this
.
getActionButton
(
'cancel'
);
saveButton
.
hide
();
cancelButton
.
text
(
gettext
(
'OK'
));
cancelButton
.
addClass
(
'action-primary'
);
},
getTitle
:
function
()
{
var
displayName
=
this
.
xblockElement
.
find
(
'.xblock-header .header-details'
).
text
().
trim
();
// If not found, try the old unit page style rendering
...
...
@@ -117,23 +150,28 @@ define(["jquery", "underscore", "gettext", "js/views/modals/base_modal",
},
save
:
function
(
event
)
{
var
self
=
this
,
xblockInfo
=
this
.
xblockInfo
,
refresh
=
self
.
editOptions
.
refresh
;
event
.
preventDefault
();
this
.
editorView
.
save
({
success
:
function
()
{
self
.
hide
();
if
(
refresh
)
{
refresh
(
xblockInfo
);
}
}
success
:
_
.
bind
(
this
.
onSave
,
this
)
});
},
onSave
:
function
()
{
var
refresh
=
this
.
editOptions
.
refresh
;
this
.
hide
();
if
(
refresh
)
{
refresh
(
this
.
xblockInfo
);
}
},
hide
:
function
()
{
BaseModal
.
prototype
.
hide
.
call
(
this
);
// Notify the runtime that the modal has been hidden
if
(
this
.
runtime
)
{
this
.
runtime
.
notify
(
'edit-modal-hidden'
);
}
// Completely clear the contents of the modal
this
.
undelegateEvents
();
this
.
$el
.
html
(
""
);
...
...
This diff is collapsed.
Click to expand it.
cms/static/js/views/xblock_editor.js
View file @
a3b28096
...
...
@@ -49,6 +49,10 @@ define(["jquery", "underscore", "gettext", "js/views/feedback_notification", "js
return
this
.
$
(
'.editor-with-tabs'
).
length
>
0
;
},
hasCustomButtons
:
function
()
{
return
this
.
$
(
'.editor-with-buttons'
).
length
>
0
;
},
createMetadataEditor
:
function
()
{
var
metadataEditor
,
metadataData
,
...
...
@@ -88,27 +92,36 @@ define(["jquery", "underscore", "gettext", "js/views/feedback_notification", "js
var
xblockInfo
=
this
.
model
,
data
,
saving
;
data
=
this
.
getXBlockData
();
saving
=
new
NotificationView
.
Mini
({
title
:
gettext
(
'Saving…'
)
});
saving
.
show
();
return
xblockInfo
.
save
(
data
).
done
(
function
()
{
var
success
=
options
.
success
;
saving
.
hide
();
if
(
success
)
{
success
();
}
});
data
=
this
.
getXModuleData
();
if
(
data
)
{
saving
=
new
NotificationView
.
Mini
({
title
:
gettext
(
'Saving…'
)
});
saving
.
show
();
return
xblockInfo
.
save
(
data
).
done
(
function
()
{
var
success
=
options
.
success
;
saving
.
hide
();
if
(
success
)
{
success
();
}
});
}
},
getXBlockData
:
function
()
{
/**
* Returns the data saved for the xmodule. Note that this *does not* work for XBlocks.
*/
getXModuleData
:
function
()
{
var
xblock
=
this
.
xblock
,
metadataEditor
=
this
.
getMetadataEditor
(),
data
;
data
=
xblock
.
save
();
if
(
metadataEditor
)
{
data
.
metadata
=
_
.
extend
(
data
.
metadata
||
{},
this
.
getChangedMetadata
());
data
=
null
;
if
(
xblock
.
save
)
{
data
=
xblock
.
save
();
if
(
metadataEditor
)
{
data
.
metadata
=
_
.
extend
(
data
.
metadata
||
{},
this
.
getChangedMetadata
());
}
}
else
{
console
.
error
(
'Cannot save xblock as it has no save method'
);
}
return
data
;
},
...
...
This diff is collapsed.
Click to expand it.
cms/static/sass/elements/_modal-window.scss
View file @
a3b28096
...
...
@@ -18,7 +18,6 @@
.modal-content
{
position
:
relative
;
box-shadow
:
0
0
3px
$shadow-d1
;
background-color
:
$white
;
padding
:
5%
;
}
...
...
@@ -52,7 +51,9 @@
}
}
// TODO: need to sync up (alongside general editing mode) with xblocks.scss UI
.modal-chin
,
.xblock-actions
,
.modal-actions
{
padding
:
(
$baseline
*
0
.75
)
2%
(
$baseline
/
2
)
2%
;
...
...
@@ -190,6 +191,22 @@
}
}
// xblock custom actions
.modal-window
.editor-with-buttons
{
margin-bottom
:
(
$baseline
*
3
);
// TODO: need to sync up (alongside general editing mode) with xblocks.scss UI
.xblock-actions
{
background-color
:
$gray-l4
;
position
:
absolute
;
width
:
100%
;
bottom
:
0
;
}
}
// special overrides for video module editor/hidden tab editors
.modal-lg.modal-type-video
{
...
...
This diff is collapsed.
Click to expand it.
cms/templates/component.html
View file @
a3b28096
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
%
>
<
%
namespace
name=
'static'
file=
'static_content.html'
/>
<div
class=
"wrapper wrapper-component-editor"
>
<div
class=
"component-editor"
>
<div
class=
"component-edit-header"
>
<span
class=
"component-name"
></span>
<ul
class=
"nav-edit-modes"
>
<li
id=
"editor-mode"
class=
"mode active-mode"
aria-controls=
"editor-tab"
role=
"tab"
>
<a
href=
"#"
>
${_("Editor")}
</a>
</li>
<li
id=
"settings-mode"
class=
"mode active-mode"
aria-controls=
"settings-tab"
role=
"tab"
>
<a
href=
"#"
>
${_("Settings")}
</a>
</li>
</ul>
</div>
<!-- Editor Header -->
<div
class=
"component-edit-modes"
>
<div
class=
"module-editor"
/>
</div>
## Native XBlocks render their own save/cancel buttons
% if show_save_cancel:
<div
class=
"row module-actions"
>
<a
href=
"#"
class=
"save-button action-primary action"
>
${_("Save")}
</a>
<a
href=
"#"
class=
"cancel-button action-secondary action"
>
${_("Cancel")}
</a>
</div>
<!-- Module Actions-->
% endif
</div>
</div>
<div
class=
"wrapper wrapper-component-action-header"
>
<div
class=
"component-header"
>
${label}
...
...
This diff is collapsed.
Click to expand it.
cms/templates/container.html
View file @
a3b28096
...
...
@@ -130,7 +130,4 @@ main_xblock_info = {
</section>
</div>
</div>
<div
class=
"edit-xblock-modal"
></div>
</
%
block>
This diff is collapsed.
Click to expand it.
cms/templates/edit-tabs.html
View file @
a3b28096
...
...
@@ -178,6 +178,4 @@
<span
class=
"label"
>
${_("close modal")}
</span>
</a>
</div>
<div
class=
"edit-xblock-modal"
></div>
</
%
block>
This diff is collapsed.
Click to expand it.
cms/templates/js/basic-modal.underscore
View file @
a3b28096
...
...
@@ -5,7 +5,7 @@
role="dialog">
<div class="modal-window-overlay"></div>
<div class="modal-window confirm modal-editor modal-<%= size %> modal-type-<%= type %>">
<div class="<%= name %>-modal"
action="#"
>
<div class="<%= name %>-modal">
<div class="modal-header">
<h2 class="title modal-window-title"><%= title %></h2>
<ul class="editor-modes action-list action-modes">
...
...
This diff is collapsed.
Click to expand it.
cms/templates/js/mock/mock-xblock-editor-with-custom-buttons.underscore
0 → 100644
View file @
a3b28096
<div class="xblock xblock-studio_view" data-runtime-version="1" data-usage-id="i4x:;_;_edX;_mock"
data-init="MockXBlock" data-runtime-class="StudioRuntime" data-block-type="mock" tabindex="0">
<div class="mock-xblock editor-with-buttons">
<h3>Mock XBlock Editor</h3>
<div class="modal-actions">
<h3 class="sr">Actions</h3>
<ul>
<li class="action-item">
<a href="#" class="button action-primary action-save">Save</a>
</li>
<li class="action-item">
<a href="#" class="button action-cancel">Cancel</a>
</li>
</ul>
</div>
</div>
</div>
This diff is collapsed.
Click to expand it.
cms/templates/unit.html
View file @
a3b28096
...
...
@@ -225,5 +225,4 @@ require(["domReady!", "jquery", "js/models/module_info", "coffee/src/views/unit"
</div>
</div>
</div>
<div
class=
"edit-xblock-modal"
></div>
</
%
block>
This diff is collapsed.
Click to expand it.
common/static/coffee/src/xblock/core.coffee
View file @
a3b28096
...
...
@@ -12,6 +12,7 @@
runtime
=
new
window
[
runtime
][
"v
#{
version
}
"
]
initFn
=
window
[
initFnName
]
block
=
initFn
(
runtime
,
element
)
?
{}
block
.
runtime
=
runtime
else
elementTag
=
$
(
'<div>'
).
append
(
$element
.
clone
()).
html
();
console
.
log
(
"Block
#{
elementTag
}
is missing data-runtime, data-runtime-version or data-init, and can't be initialized"
)
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment