diff --git a/IPython/html/static/base/js/utils.js b/IPython/html/static/base/js/utils.js index a974166..013389c 100644 --- a/IPython/html/static/base/js/utils.js +++ b/IPython/html/static/base/js/utils.js @@ -591,6 +591,21 @@ define([ return wrapped_error; }; + var promising_ajax = function(url, settings) { + // Like $.ajax, but returning an ES6 promise. success and error settings + // will be ignored. + return new Promise(function(resolve, reject) { + settings.success = function(data, status, jqXHR) { + resolve(data); + }; + settings.error = function(jqXHR, status, error) { + log_ajax_error(jqXHR, status, error); + reject(wrap_ajax_error(jqXHR, status, error)); + }; + $.ajax(url, settings); + }); + }; + var utils = { regex_split : regex_split, uuid : uuid, @@ -618,7 +633,8 @@ define([ log_ajax_error : log_ajax_error, requireCodeMirrorMode : requireCodeMirrorMode, XHR_ERROR : XHR_ERROR, - wrap_ajax_error : wrap_ajax_error + wrap_ajax_error : wrap_ajax_error, + promising_ajax : promising_ajax, }; // Backwards compatability. diff --git a/IPython/html/static/components b/IPython/html/static/components index f8f0c3b..ba94581 160000 --- a/IPython/html/static/components +++ b/IPython/html/static/components @@ -1 +1 @@ -Subproject commit f8f0c3b8958b1f91a888b5f15d2b17404a476016 +Subproject commit ba94581b824a62ee630dd0b92a5aea8678248a24 diff --git a/IPython/html/static/notebook/js/menubar.js b/IPython/html/static/notebook/js/menubar.js index 8d42dc0..5992e0f 100644 --- a/IPython/html/static/notebook/js/menubar.js +++ b/IPython/html/static/notebook/js/menubar.js @@ -90,14 +90,13 @@ define([ // Create a new notebook in the same path as the current // notebook's path. var parent = utils.url_path_split(that.notebook.notebook_path)[0]; - that.contents.new_untitled(parent, { - type: "notebook", - success: function (data) { + that.contents.new_untitled(parent, {type: "notebook"}).then( + function (data) { w.location = utils.url_join_encode( that.base_url, 'notebooks', data.path ); - }, - error: function(error) { + }, + function(error) { w.close(); dialog.modal({ title : 'Creating Notebook Failed', @@ -105,7 +104,7 @@ define([ buttons : {'OK' : {'class' : 'btn-primary'}} }); } - }); + ); }); this.element.find('#open_notebook').click(function () { var parent = utils.url_path_split(that.notebook.notebook_path)[0]; diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js index e71f451..643818d 100644 --- a/IPython/html/static/notebook/js/notebook.js +++ b/IPython/html/static/notebook/js/notebook.js @@ -1902,12 +1902,12 @@ define([ var start = new Date().getTime(); var that = this; - this.contents.save(this.notebook_path, model, { - success: $.proxy(this.save_notebook_success, this, start), - error: function (error) { + this.contents.save(this.notebook_path, model).then( + $.proxy(this.save_notebook_success, this, start), + function (error) { that.events.trigger('notebook_save_failed.Notebook', error); } - }); + ); }; /** @@ -2025,17 +2025,17 @@ define([ var base_url = this.base_url; var w = window.open(); var parent = utils.url_path_split(this.notebook_path)[0]; - this.contents.copy(this.notebook_path, parent, { - success: function (data) { + this.contents.copy(this.notebook_path, parent).then( + function (data) { w.location = utils.url_join_encode( base_url, 'notebooks', data.path ); }, - error : function(error) { + function(error) { w.close(); console.log(error); - }, - }); + } + ); }; Notebook.prototype.rename = function (new_name) { @@ -2046,15 +2046,15 @@ define([ var that = this; var parent = utils.url_path_split(this.notebook_path)[0]; var new_path = utils.url_path_join(parent, new_name); - this.contents.rename(this.notebook_path, new_path, { - success: function (json) { + this.contents.rename(this.notebook_path, new_path).then( + function (json) { that.notebook_name = json.name; that.notebook_path = json.path; that.session.rename_notebook(json.path); that.events.trigger('notebook_renamed.Notebook', json); }, - error: $.proxy(this.rename_error, this) - }); + $.proxy(this.rename_error, this) + ); }; Notebook.prototype.delete = function () { @@ -2103,11 +2103,10 @@ define([ this.notebook_path = notebook_path; this.notebook_name = utils.url_path_split(this.notebook_path)[1]; this.events.trigger('notebook_loading.Notebook'); - this.contents.get(notebook_path, { - type: 'notebook', - success: $.proxy(this.load_notebook_success, this), - error: $.proxy(this.load_notebook_error, this) - }); + this.contents.get(notebook_path, {type: 'notebook'}).then( + $.proxy(this.load_notebook_success, this), + $.proxy(this.load_notebook_error, this) + ); }; /** @@ -2327,12 +2326,12 @@ define([ */ Notebook.prototype.list_checkpoints = function () { var that = this; - this.contents.list_checkpoints(this.notebook_path, { - success: $.proxy(this.list_checkpoints_success, this), - error: function(error) { + this.contents.list_checkpoints(this.notebook_path).then( + $.proxy(this.list_checkpoints_success, this), + function(error) { that.events.trigger('list_checkpoints_failed.Notebook', error); } - }); + ); }; /** @@ -2342,7 +2341,6 @@ define([ * @param {Object} data JSON representation of a checkpoint */ Notebook.prototype.list_checkpoints_success = function (data) { - data = $.parseJSON(data); this.checkpoints = data; if (data.length) { this.last_checkpoint = data[data.length - 1]; @@ -2359,12 +2357,12 @@ define([ */ Notebook.prototype.create_checkpoint = function () { var that = this; - this.contents.create_checkpoint(this.notebook_path, { - success: $.proxy(this.create_checkpoint_success, this), - error: function (error) { + this.contents.create_checkpoint(this.notebook_path).then( + $.proxy(this.create_checkpoint_success, this), + function (error) { that.events.trigger('checkpoint_failed.Notebook', error); } - }); + ); }; /** @@ -2374,7 +2372,6 @@ define([ * @param {Object} data JSON representation of a checkpoint */ Notebook.prototype.create_checkpoint_success = function (data) { - data = $.parseJSON(data); this.add_checkpoint(data); this.events.trigger('checkpoint_created.Notebook', data); }; @@ -2429,13 +2426,12 @@ define([ Notebook.prototype.restore_checkpoint = function (checkpoint) { this.events.trigger('notebook_restoring.Notebook', checkpoint); var that = this; - this.contents.restore_checkpoint(this.notebook_path, - checkpoint, { - success: $.proxy(this.restore_checkpoint_success, this), - error: function (error) { + this.contents.restore_checkpoint(this.notebook_path, checkpoint).then( + $.proxy(this.restore_checkpoint_success, this), + function (error) { that.events.trigger('checkpoint_restore_failed.Notebook', error); } - }); + ); }; /** @@ -2457,13 +2453,12 @@ define([ Notebook.prototype.delete_checkpoint = function (checkpoint) { this.events.trigger('notebook_restoring.Notebook', checkpoint); var that = this; - this.contents.delete_checkpoint(this.notebook_path, - checkpoint, { - success: $.proxy(this.delete_checkpoint_success, this), - error: function (error) { + this.contents.delete_checkpoint(this.notebook_path, checkpoint).then( + $.proxy(this.delete_checkpoint_success, this), + function (error) { that.events.trigger('checkpoint_delete_failed.Notebook', error); } - }); + ); }; /** diff --git a/IPython/html/static/services/contents.js b/IPython/html/static/services/contents.js index c52bd0d..7600560 100644 --- a/IPython/html/static/services/contents.js +++ b/IPython/html/static/services/contents.js @@ -73,8 +73,9 @@ define([ * * @method get * @param {String} path - * @param {Function} success - * @param {Function} error + * @param {Object} options + * type : 'notebook', 'file', or 'directory' + * format: 'text' or 'base64'; only relevant for type: 'file' */ Contents.prototype.get = function (path, options) { // We do the call with settings so we can set cache to false. @@ -83,14 +84,12 @@ define([ cache : false, type : "GET", dataType : "json", - success : options.success, - error : this.create_basic_error_handler(options.error) }; var url = this.api_url(path); params = {}; if (options.type) { params.type = options.type; } if (options.format) { params.format = options.format; } - $.ajax(url + '?' + $.param(params), settings); + return utils.promising_ajax(url + '?' + $.param(params), settings); }; @@ -114,33 +113,31 @@ define([ type : "POST", data: data, dataType : "json", - success : options.success || function() {}, - error : this.create_basic_error_handler(options.error) }; - $.ajax(this.api_url(path), settings); + return utils.promising_ajax(this.api_url(path), settings); }; - Contents.prototype.delete = function(path, options) { - var error_callback = options.error || function() {}; + Contents.prototype.delete = function(path) { var settings = { processData : false, type : "DELETE", dataType : "json", - success : options.success || function() {}, - error : function(xhr, status, error) { + }; + var url = this.api_url(path); + return utils.promising_ajax(url, settings).catch( + // Translate certain errors to more specific ones. + function(error) { // TODO: update IPEP27 to specify errors more precisely, so // that error types can be detected here with certainty. - if (xhr.status === 400) { - error_callback(new Contents.DirectoryNotEmptyError()); + if (error.xhr.status === 400) { + throw new Contents.DirectoryNotEmptyError(); } - error_callback(utils.wrap_ajax_error(xhr, status, error)); + throw error; } - }; - var url = this.api_url(path); - $.ajax(url, settings); + ); }; - Contents.prototype.rename = function(path, new_path, options) { + Contents.prototype.rename = function(path, new_path) { var data = {path: new_path}; var settings = { processData : false, @@ -148,28 +145,24 @@ define([ data : JSON.stringify(data), dataType: "json", contentType: 'application/json', - success : options.success || function() {}, - error : this.create_basic_error_handler(options.error) }; var url = this.api_url(path); - $.ajax(url, settings); + return utils.promising_ajax(url, settings); }; - Contents.prototype.save = function(path, model, options) { + Contents.prototype.save = function(path, model) { // We do the call with settings so we can set cache to false. var settings = { processData : false, type : "PUT", data : JSON.stringify(model), contentType: 'application/json', - success : options.success || function() {}, - error : this.create_basic_error_handler(options.error) }; var url = this.api_url(path); - $.ajax(url, settings); + return utils.promising_ajax(url, settings); }; - Contents.prototype.copy = function(from_file, to_dir, options) { + Contents.prototype.copy = function(from_file, to_dir) { // Copy a file into a given directory via POST // The server will select the name of the copied file var url = this.api_url(to_dir); @@ -179,54 +172,47 @@ define([ type: "POST", data: JSON.stringify({copy_from: from_file}), dataType : "json", - success: options.success || function() {}, - error: this.create_basic_error_handler(options.error) }; - $.ajax(url, settings); + return utils.promising_ajax(url, settings); }; /** * Checkpointing Functions */ - Contents.prototype.create_checkpoint = function(path, options) { + Contents.prototype.create_checkpoint = function(path) { var url = this.api_url(path, 'checkpoints'); var settings = { type : "POST", - success: options.success || function() {}, - error : this.create_basic_error_handler(options.error) + dataType : "json", }; - $.ajax(url, settings); + return utils.promising_ajax(url, settings); }; - Contents.prototype.list_checkpoints = function(path, options) { + Contents.prototype.list_checkpoints = function(path) { var url = this.api_url(path, 'checkpoints'); var settings = { type : "GET", - success: options.success, - error : this.create_basic_error_handler(options.error) + cache: false, + dataType: "json", }; - $.ajax(url, settings); + return utils.promising_ajax(url, settings); }; - Contents.prototype.restore_checkpoint = function(path, checkpoint_id, options) { + Contents.prototype.restore_checkpoint = function(path, checkpoint_id) { var url = this.api_url(path, 'checkpoints', checkpoint_id); var settings = { type : "POST", - success: options.success || function() {}, - error : this.create_basic_error_handler(options.error) }; - $.ajax(url, settings); + return utils.promising_ajax(url, settings); }; - Contents.prototype.delete_checkpoint = function(path, checkpoint_id, options) { + Contents.prototype.delete_checkpoint = function(path, checkpoint_id) { var url = this.api_url(path, 'checkpoints', checkpoint_id); var settings = { type : "DELETE", - success: options.success || function() {}, - error : this.create_basic_error_handler(options.error) }; - $.ajax(url, settings); + return utils.promising_ajax(url, settings); }; /** @@ -244,11 +230,9 @@ define([ * last_modified: last modified dat * @method list_notebooks * @param {String} path The path to list notebooks in - * @param {Object} options including success and error callbacks */ - Contents.prototype.list_contents = function(path, options) { - options.type = 'directory'; - this.get(path, options); + Contents.prototype.list_contents = function(path) { + return this.get(path, {type: 'directory'}); }; diff --git a/IPython/html/static/tree/js/main.js b/IPython/html/static/tree/js/main.js index 53d2ca9..f55c480 100644 --- a/IPython/html/static/tree/js/main.js +++ b/IPython/html/static/tree/js/main.js @@ -65,14 +65,13 @@ require([ $('#new_notebook').click(function (e) { var w = window.open(); - contents.new_untitled(common_options.notebook_path, { - type: "notebook", - success: function (data) { + contents.new_untitled(common_options.notebook_path, {type: "notebook"}).then( + function (data) { w.location = utils.url_join_encode( common_options.base_url, 'notebooks', data.path ); - }, - error: function(error) { + }, + function(error) { w.close(); dialog.modal({ title : 'Creating Notebook Failed', @@ -80,7 +79,7 @@ require([ buttons : {'OK' : {'class' : 'btn-primary'}} }); } - }); + ); }); var interval_id=0; diff --git a/IPython/html/static/tree/js/notebooklist.js b/IPython/html/static/tree/js/notebooklist.js index fbc0091..8e727f5 100644 --- a/IPython/html/static/tree/js/notebooklist.js +++ b/IPython/html/static/tree/js/notebooklist.js @@ -142,12 +142,12 @@ define([ NotebookList.prototype.load_list = function () { var that = this; - this.contents.list_contents(that.notebook_path, { - success: $.proxy(this.draw_notebook_list, this), - error: function(error) { + this.contents.list_contents(that.notebook_path).then( + $.proxy(this.draw_notebook_list, this), + function(error) { that.draw_notebook_list({content: []}, "Server error: " + error.message); } - }); + ); }; /** @@ -328,11 +328,11 @@ define([ Delete : { class: "btn-danger", click: function() { - notebooklist.contents.delete(path, { - success: function() { + notebooklist.contents.delete(path).then( + function() { notebooklist.notebook_deleted(path); } - }); + ); } }, Cancel : {} @@ -414,13 +414,11 @@ define([ } filedata = item.data('filedata'); - var settings = { - success : function () { - item.removeClass('new-file'); - that.add_link(model, item); - that.add_delete_button(item); - that.session_list.load_sessions(); - }, + var on_success = function () { + item.removeClass('new-file'); + that.add_link(model, item); + that.add_delete_button(item); + that.session_list.load_sessions(); }; var exists = false; @@ -436,8 +434,8 @@ define([ Overwrite : { class: "btn-danger", click: function () { - that.contents.save(path, model, settings); - } + that.contents.save(path, model).then(on_success); + } }, Cancel : { click: function() { item.remove(); } @@ -445,7 +443,7 @@ define([ } }); } else { - that.contents.save(path, model, settings); + that.contents.save(path, model).then(on_success); } return false; diff --git a/IPython/html/templates/page.html b/IPython/html/templates/page.html index f729405..404c6b5 100644 --- a/IPython/html/templates/page.html +++ b/IPython/html/templates/page.html @@ -14,6 +14,7 @@ {% endblock %} +