mirror of
https://github.com/jupyter/notebook.git
synced 2025-03-07 13:07:22 +08:00
add dialogs for failed save/load
- failed validation doesn't prevent save/load, but the user is now warned about it. - there is now a warning dialog if fromJSON fails, rather than the usual silent failure.
This commit is contained in:
parent
1a4b795870
commit
ddd3aa2a5a
@ -176,6 +176,7 @@ class FileContentsManager(ContentsManager):
|
||||
model['created'] = created
|
||||
model['content'] = None
|
||||
model['format'] = None
|
||||
model['message'] = None
|
||||
return model
|
||||
|
||||
def _dir_model(self, name, path='', content=True):
|
||||
@ -258,6 +259,7 @@ class FileContentsManager(ContentsManager):
|
||||
self.mark_trusted_cells(nb, name, path)
|
||||
model['content'] = nb
|
||||
model['format'] = 'json'
|
||||
self.validate_notebook_model(model)
|
||||
return model
|
||||
|
||||
def get_model(self, name, path='', content=True):
|
||||
@ -366,7 +368,14 @@ class FileContentsManager(ContentsManager):
|
||||
except Exception as e:
|
||||
raise web.HTTPError(400, u'Unexpected error while saving file: %s %s' % (os_path, e))
|
||||
|
||||
validation_message = None
|
||||
if model['type'] == 'notebook':
|
||||
self.validate_notebook_model(model)
|
||||
validation_message = model.get('message', None)
|
||||
|
||||
model = self.get_model(new_name, new_path, content=False)
|
||||
if validation_message:
|
||||
model['message'] = validation_message
|
||||
return model
|
||||
|
||||
def update(self, model, name, path=''):
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
from fnmatch import fnmatch
|
||||
import itertools
|
||||
import json
|
||||
import os
|
||||
|
||||
from tornado.web import HTTPError
|
||||
@ -216,6 +217,16 @@ class ContentsManager(LoggingConfigurable):
|
||||
break
|
||||
return name
|
||||
|
||||
def validate_notebook_model(self, model):
|
||||
"""Add failed-validation message to model"""
|
||||
try:
|
||||
current.validate(model['content'])
|
||||
except current.ValidationError as e:
|
||||
model['message'] = 'Notebook Validation failed: {}:\n{}'.format(
|
||||
e.message, json.dumps(e.instance, indent=1, default=lambda obj: '<UNKNOWN>'),
|
||||
)
|
||||
return model
|
||||
|
||||
def create_file(self, model=None, path='', ext='.ipynb'):
|
||||
"""Create a new file or directory and return its model with no content."""
|
||||
path = path.strip('/')
|
||||
|
@ -1826,6 +1826,7 @@ define([
|
||||
* @param {Object} data JSON representation of a notebook
|
||||
*/
|
||||
Notebook.prototype.fromJSON = function (data) {
|
||||
|
||||
var content = data.content;
|
||||
var ncells = this.ncells();
|
||||
var i;
|
||||
@ -1975,6 +1976,7 @@ define([
|
||||
type : "PUT",
|
||||
data : JSON.stringify(model),
|
||||
headers : {'Content-Type': 'application/json'},
|
||||
dataType : "json",
|
||||
success : $.proxy(this.save_notebook_success, this, start),
|
||||
error : $.proxy(this.save_notebook_error, this)
|
||||
};
|
||||
@ -2004,6 +2006,30 @@ define([
|
||||
*/
|
||||
Notebook.prototype.save_notebook_success = function (start, data, status, xhr) {
|
||||
this.set_dirty(false);
|
||||
if (data.message) {
|
||||
// save succeeded, but validation failed.
|
||||
var body = $("<div>");
|
||||
var title = "Notebook validation failed";
|
||||
|
||||
body.append($("<p>").text(
|
||||
"The save operation succeeded," +
|
||||
" but the notebook does not appear to be valid." +
|
||||
" The validation error was:"
|
||||
)).append($("<div>").addClass("validation-error").append(
|
||||
$("<pre>").text(data.message)
|
||||
));
|
||||
dialog.modal({
|
||||
notebook: this,
|
||||
keyboard_manager: this.keyboard_manager,
|
||||
title: title,
|
||||
body: body,
|
||||
buttons : {
|
||||
OK : {
|
||||
"class" : "btn-primary"
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
this.events.trigger('notebook_saved.Notebook');
|
||||
this._update_autosave_interval(start);
|
||||
if (this._checkpoint_after_save) {
|
||||
@ -2278,7 +2304,57 @@ define([
|
||||
* @param {jqXHR} xhr jQuery Ajax object
|
||||
*/
|
||||
Notebook.prototype.load_notebook_success = function (data, status, xhr) {
|
||||
this.fromJSON(data);
|
||||
var failed;
|
||||
try {
|
||||
this.fromJSON(data);
|
||||
} catch (e) {
|
||||
failed = e;
|
||||
console.log("Notebook failed to load from JSON:", e);
|
||||
}
|
||||
if (failed || data.message) {
|
||||
// *either* fromJSON failed or validation failed
|
||||
var body = $("<div>");
|
||||
var title;
|
||||
if (failed) {
|
||||
title = "Notebook failed to load";
|
||||
body.append($("<p>").text(
|
||||
"The error was: "
|
||||
)).append($("<div>").addClass("js-error").text(
|
||||
failed.toString()
|
||||
)).append($("<p>").text(
|
||||
"See the error console for details."
|
||||
));
|
||||
} else {
|
||||
title = "Notebook validation failed";
|
||||
}
|
||||
|
||||
if (data.message) {
|
||||
var msg;
|
||||
if (failed) {
|
||||
msg = "The notebook also failed validation:"
|
||||
} else {
|
||||
msg = "An invalid notebook may not function properly." +
|
||||
" The validation error was:"
|
||||
}
|
||||
body.append($("<p>").text(
|
||||
msg
|
||||
)).append($("<div>").addClass("validation-error").append(
|
||||
$("<pre>").text(data.message)
|
||||
));
|
||||
}
|
||||
|
||||
dialog.modal({
|
||||
notebook: this,
|
||||
keyboard_manager: this.keyboard_manager,
|
||||
title: title,
|
||||
body: body,
|
||||
buttons : {
|
||||
OK : {
|
||||
"class" : "btn-primary"
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this.ncells() === 0) {
|
||||
this.insert_cell_below('code');
|
||||
this.edit_mode(0);
|
||||
|
Loading…
Reference in New Issue
Block a user