").text( msg @@ -2192,7 +2186,7 @@ define([ src = " a newer notebook format "; } - var msg = "This notebook has been converted from" + src + + msg = "This notebook has been converted from" + src + "(v"+orig_nbformat+") to the current notebook " + "format (v"+nbmodel.nbformat+"). The next time you save this notebook, the " + "current notebook format will be used."; @@ -2219,7 +2213,7 @@ define([ var that = this; var orig_vs = 'v' + nbmodel.nbformat + '.' + orig_nbformat_minor; var this_vs = 'v' + nbmodel.nbformat + '.' + this.nbformat_minor; - var msg = "This notebook is version " + orig_vs + ", but we only fully support up to " + + msg = "This notebook is version " + orig_vs + ", but we only fully support up to " + this_vs + ". You can still work with this notebook, but some features " + "introduced in later notebook versions may not be available."; @@ -2270,7 +2264,7 @@ define([ Notebook.prototype.load_notebook_error = function (error) { this.events.trigger('notebook_load_failed.Notebook', error); var msg; - if (error.name = utils.XHR_ERROR && error.xhr.status === 500) { + if (error.name === utils.XHR_ERROR && error.xhr.status === 500) { utils.log_ajax_error(error.xhr, error.xhr_status, error.xhr_error); msg = "An unknown error occurred while loading this notebook. " + "This version can load notebook formats " + @@ -2330,10 +2324,10 @@ define([ */ Notebook.prototype.list_checkpoints = function () { var that = this; - this.contents.list_checkpoints(this.notebook_path, this.notebook_name, { + this.contents.list_checkpoints(this.notebook_path, { success: $.proxy(this.list_checkpoints_success, this), error: function(error) { - that.events.trigger('list_checkpoints_failed.Notebook'); + that.events.trigger('list_checkpoints_failed.Notebook', error); } }); }; @@ -2362,10 +2356,10 @@ define([ */ Notebook.prototype.create_checkpoint = function () { var that = this; - this.contents.create_checkpoint(this.notebook_path, this.notebook_name, { + this.contents.create_checkpoint(this.notebook_path, { success: $.proxy(this.create_checkpoint_success, this), error: function (error) { - that.events.trigger('checkpoint_failed.Notebook'); + that.events.trigger('checkpoint_failed.Notebook', error); } }); }; @@ -2432,11 +2426,11 @@ define([ Notebook.prototype.restore_checkpoint = function (checkpoint) { this.events.trigger('notebook_restoring.Notebook', checkpoint); var that = this; - this.contents.restore_checkpoint(this.notebook_path, this.notebook_name, + this.contents.restore_checkpoint(this.notebook_path, checkpoint, { success: $.proxy(this.restore_checkpoint_success, this), error: function (error) { - that.events.trigger('checkpoint_restore_failed.Notebook'); + that.events.trigger('checkpoint_restore_failed.Notebook', error); } }); }; @@ -2448,7 +2442,7 @@ define([ */ Notebook.prototype.restore_checkpoint_success = function () { this.events.trigger('checkpoint_restored.Notebook'); - this.load_notebook(this.notebook_name, this.notebook_path); + this.load_notebook(this.notebook_path); }; /** @@ -2460,7 +2454,7 @@ define([ Notebook.prototype.delete_checkpoint = function (checkpoint) { this.events.trigger('notebook_restoring.Notebook', checkpoint); var that = this; - this.contents.delete_checkpoint(this.notebook_path, this.notebook_name, + this.contents.delete_checkpoint(this.notebook_path, checkpoint, { success: $.proxy(this.delete_checkpoint_success, this), error: function (error) { @@ -2476,7 +2470,7 @@ define([ */ Notebook.prototype.delete_checkpoint_success = function () { this.events.trigger('checkpoint_deleted.Notebook'); - this.load_notebook(this.notebook_name, this.notebook_path); + this.load_notebook(this.notebook_path); }; diff --git a/IPython/html/static/notebook/js/savewidget.js b/IPython/html/static/notebook/js/savewidget.js index 72cddf9..f2cfb5c 100644 --- a/IPython/html/static/notebook/js/savewidget.js +++ b/IPython/html/static/notebook/js/savewidget.js @@ -122,14 +122,12 @@ define([ SaveWidget.prototype.update_address_bar = function(){ var base_url = this.notebook.base_url; - var nbname = this.notebook.notebook_name; var path = this.notebook.notebook_path; - var state = {path : path, name: nbname}; + var state = {path : path}; window.history.replaceState(state, "", utils.url_join_encode( base_url, "notebooks", - path, - nbname) + path) ); }; @@ -199,7 +197,7 @@ define([ $.proxy(that._regularly_update_checkpoint_date, that), t + 1000 ); - } + }; var tdelta = Math.ceil(new Date()-this._checkpoint_date); // update regularly for the first 6hours and show diff --git a/IPython/html/static/services/contents.js b/IPython/html/static/services/contents.js index d229b0b..041a7af 100644 --- a/IPython/html/static/services/contents.js +++ b/IPython/html/static/services/contents.js @@ -29,8 +29,9 @@ define([ // An error representing the result of attempting to delete a non-empty // directory. this.message = 'A directory must be empty before being deleted.'; - } - Contents.DirectoryNotEmptyError.prototype = new Error; + }; + + Contents.DirectoryNotEmptyError.prototype = Object.create(Error.prototype); Contents.DirectoryNotEmptyError.prototype.name = Contents.DIRECTORY_NOT_EMPTY_ERROR; @@ -54,29 +55,28 @@ define([ */ Contents.prototype.create_basic_error_handler = function(callback) { if (!callback) { - return function(xhr, status, error) { }; + return utils.log_ajax_error; } return function(xhr, status, error) { callback(utils.wrap_ajax_error(xhr, status, error)); }; - } + }; /** * File Functions (including notebook operations) */ /** - * Load a file. + * Get a file. * * Calls success with file JSON model, or error with error. * - * @method load_notebook + * @method get * @param {String} path - * @param {String} name * @param {Function} success * @param {Function} error */ - Contents.prototype.load = function (path, name, options) { + Contents.prototype.get = function (path, options) { // We do the call with settings so we can set cache to false. var settings = { processData : false, @@ -86,32 +86,25 @@ define([ success : options.success, error : this.create_basic_error_handler(options.error) }; - var url = this.api_url(path, name); + var url = this.api_url(path); $.ajax(url, settings); }; /** - * Creates a new notebook file at the specified directory path. + * Creates a new file at the specified directory path. * - * @method scroll_to_cell + * @method new * @param {String} path The path to create the new notebook at - * @param {String} name Name for new file. Chosen by server if unspecified. * @param {Object} options: - * ext: file extension to use if name unspecified + * ext: file extension to use */ - Contents.prototype.new = function(path, name, options) { - var method, data; - if (name) { - method = "PUT"; - } else { - method = "POST"; - data = JSON.stringify({ext: options.ext || ".ipynb"}); - } + Contents.prototype.new = function(path, options) { + var data = JSON.stringify({ext: options.ext || ".ipynb"}); var settings = { processData : false, - type : method, + type : "POST", data: data, dataType : "json", success : options.success || function() {}, @@ -123,9 +116,8 @@ define([ $.ajax(this.api_url(path), settings); }; - Contents.prototype.delete = function(name, path, options) { + Contents.prototype.delete = function(path, options) { var error_callback = options.error || function() {}; - var that = this; var settings = { processData : false, type : "DELETE", @@ -140,12 +132,12 @@ define([ error_callback(utils.wrap_ajax_error(xhr, status, error)); } }; - var url = this.api_url(path, name); + var url = this.api_url(path); $.ajax(url, settings); }; - Contents.prototype.rename = function(path, name, new_path, new_name, options) { - var data = {name: new_name, path: new_path}; + Contents.prototype.rename = function(path, new_path, options) { + var data = {path: new_path}; var settings = { processData : false, type : "PATCH", @@ -155,11 +147,11 @@ define([ success : options.success || function() {}, error : this.create_basic_error_handler(options.error) }; - var url = this.api_url(path, name); + var url = this.api_url(path); $.ajax(url, settings); }; - Contents.prototype.save = function(path, name, model, options) { + Contents.prototype.save = function(path, model, options) { // We do the call with settings so we can set cache to false. var settings = { processData : false, @@ -172,24 +164,19 @@ define([ if (options.extra_settings) { $.extend(settings, options.extra_settings); } - var url = this.api_url(path, name); + var url = this.api_url(path); $.ajax(url, settings); }; - Contents.prototype.copy = function(to_path, to_name, from, options) { - var url, method; - if (to_name) { - url = this.api_url(to_path, to_name); - method = "PUT"; - } else { - url = this.api_url(to_path); - method = "POST"; - } + Contents.prototype.copy = function(from_file, to_dir, options) { + // 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); var settings = { processData : false, - type: method, - data: JSON.stringify({copy_from: from}), + type: "POST", + data: JSON.stringify({copy_from: from_file}), dataType : "json", success: options.success || function() {}, error: this.create_basic_error_handler(options.error) @@ -204,8 +191,8 @@ define([ * Checkpointing Functions */ - Contents.prototype.create_checkpoint = function(path, name, options) { - var url = this.api_url(path, name, 'checkpoints'); + Contents.prototype.create_checkpoint = function(path, options) { + var url = this.api_url(path, 'checkpoints'); var settings = { type : "POST", success: options.success || function() {}, @@ -214,8 +201,8 @@ define([ $.ajax(url, settings); }; - Contents.prototype.list_checkpoints = function(path, name, options) { - var url = this.api_url(path, name, 'checkpoints'); + Contents.prototype.list_checkpoints = function(path, options) { + var url = this.api_url(path, 'checkpoints'); var settings = { type : "GET", success: options.success, @@ -224,8 +211,8 @@ define([ $.ajax(url, settings); }; - Contents.prototype.restore_checkpoint = function(path, name, checkpoint_id, options) { - var url = this.api_url(path, name, 'checkpoints', checkpoint_id); + Contents.prototype.restore_checkpoint = function(path, checkpoint_id, options) { + var url = this.api_url(path, 'checkpoints', checkpoint_id); var settings = { type : "POST", success: options.success || function() {}, @@ -234,8 +221,8 @@ define([ $.ajax(url, settings); }; - Contents.prototype.delete_checkpoint = function(path, name, checkpoint_id, options) { - var url = this.api_url(path, name, 'checkpoints', checkpoint_id); + Contents.prototype.delete_checkpoint = function(path, checkpoint_id, options) { + var url = this.api_url(path, 'checkpoints', checkpoint_id); var settings = { type : "DELETE", success: options.success || function() {}, @@ -255,10 +242,8 @@ define([ * representing individual files or directories. Each dictionary has * the keys: * type: "notebook" or "directory" - * name: the name of the file or directory * created: created date * last_modified: last modified dat - * path: the path * @method list_notebooks * @param {String} path The path to list notebooks in * @param {Function} load_callback called with list of notebooks on success diff --git a/IPython/html/static/services/sessions/session.js b/IPython/html/static/services/sessions/session.js index 5b2316d..22ba9fc 100644 --- a/IPython/html/static/services/sessions/session.js +++ b/IPython/html/static/services/sessions/session.js @@ -15,7 +15,6 @@ define([ * all other operations, the kernel object should be used. * * Options should include: - * - notebook_name: the notebook name * - notebook_path: the path (not including name) to the notebook * - kernel_name: the type of kernel (e.g. python3) * - base_url: the root url of the notebook server @@ -28,7 +27,6 @@ define([ var Session = function (options) { this.id = null; this.notebook_model = { - name: options.notebook_name, path: options.notebook_path }; this.kernel_model = { @@ -154,15 +152,11 @@ define([ * undefined, then they will not be changed. * * @function rename_notebook - * @param {string} [name] - new notebook name - * @param {string} [path] - new path to notebook + * @param {string} [path] - new notebook path * @param {function} [success] - function executed on ajax success * @param {function} [error] - functon executed on ajax error */ - Session.prototype.rename_notebook = function (name, path, success, error) { - if (name !== undefined) { - this.notebook_model.name = name; - } + Session.prototype.rename_notebook = function (path, success, error) { if (path !== undefined) { this.notebook_model.path = path; } @@ -208,7 +202,6 @@ define([ * fresh. If options are given, they can include any of the * following: * - * - notebook_name - the name of the notebook * - notebook_path - the path to the notebook * - kernel_name - the name (type) of the kernel * @@ -220,9 +213,6 @@ define([ Session.prototype.restart = function (options, success, error) { var that = this; var start = function () { - if (options && options.notebook_name) { - that.notebook_model.name = options.notebook_name; - } if (options && options.notebook_path) { that.notebook_model.path = options.notebook_path; } @@ -238,8 +228,8 @@ define([ // Helper functions /** - * Get the data model for the session, which includes the notebook - * (name and path) and kernel (name and id). + * Get the data model for the session, which includes the notebook path + * and kernel (name and id). * * @function _get_model * @returns {Object} - the data model @@ -266,7 +256,6 @@ define([ this.session_url = utils.url_join_encode(this.session_service_url, this.id); } if (data && data.notebook) { - this.notebook_model.name = data.notebook.name; this.notebook_model.path = data.notebook.path; } if (data && data.kernel) { diff --git a/IPython/html/static/tree/js/main.js b/IPython/html/static/tree/js/main.js index 2396ad8..8d84917 100644 --- a/IPython/html/static/tree/js/main.js +++ b/IPython/html/static/tree/js/main.js @@ -2,8 +2,9 @@ // Distributed under the terms of the Modified BSD License. require([ - 'base/js/namespace', 'jquery', + 'base/js/namespace', + 'base/js/dialog', 'base/js/events', 'base/js/page', 'base/js/utils', @@ -19,18 +20,20 @@ require([ 'bootstrap', 'custom/custom', ], function( - IPython, - $, + $, + IPython, + dialog, events, - page, - utils, - contents, + page, + utils, + contents_service, notebooklist, clusterlist, sesssionlist, kernellist, terminallist, loginwidget){ + "use strict"; page = new page.Page(); @@ -38,36 +41,37 @@ require([ base_url: utils.get_body_data("baseUrl"), notebook_path: utils.get_body_data("notebookPath"), }; - session_list = new sesssionlist.SesssionList($.extend({ + var session_list = new sesssionlist.SesssionList($.extend({ events: events}, common_options)); - contents = new contents.Contents($.extend({ + var contents = new contents_service.Contents($.extend({ events: events}, common_options)); - notebook_list = new notebooklist.NotebookList('#notebook_list', $.extend({ + var notebook_list = new notebooklist.NotebookList('#notebook_list', $.extend({ contents: contents, session_list: session_list}, common_options)); - cluster_list = new clusterlist.ClusterList('#cluster_list', common_options); - kernel_list = new kernellist.KernelList('#running_list', $.extend({ + var cluster_list = new clusterlist.ClusterList('#cluster_list', common_options); + var kernel_list = new kernellist.KernelList('#running_list', $.extend({ session_list: session_list}, common_options)); + var terminal_list; if (utils.get_body_data("terminalsAvailable") === "True") { terminal_list = new terminallist.TerminalList('#terminal_list', common_options); } - login_widget = new loginwidget.LoginWidget('#login_widget', common_options); + var login_widget = new loginwidget.LoginWidget('#login_widget', common_options); $('#new_notebook').click(function (e) { - contents.new(common_options.notebook_path, null, { + contents.new(common_options.notebook_path, { ext: ".ipynb", extra_settings: {async: false}, // So we can open a new window afterwards success: function (data) { window.open( utils.url_join_encode( common_options.base_url, 'notebooks', - data.path, data.name + data.path ), '_blank'); }, error: function(error) { diff --git a/IPython/html/static/tree/js/notebooklist.js b/IPython/html/static/tree/js/notebooklist.js index b361167..678fceb 100644 --- a/IPython/html/static/tree/js/notebooklist.js +++ b/IPython/html/static/tree/js/notebooklist.js @@ -100,7 +100,7 @@ define([ }; reader.onerror = function (event) { var item = $(event.target).data('item'); - var name = item.data('name') + var name = item.data('name'); item.remove(); dialog.modal({ title : 'Failed to read file', @@ -141,7 +141,7 @@ define([ }; NotebookList.prototype.load_list = function () { - var that = this + var that = this; this.contents.list_contents(that.notebook_path, { success: $.proxy(this.draw_notebook_list, this), error: function(error) { @@ -177,7 +177,7 @@ define([ model = { type: 'directory', name: '..', - path: path, + path: utils.url_path_split(path)[0], }; this.add_link(model, item); offset += 1; @@ -240,8 +240,7 @@ define([ utils.url_join_encode( this.base_url, uri_prefix, - path, - name + path ) ); // directory nav doesn't open new tabs @@ -311,7 +310,6 @@ define([ }; NotebookList.prototype.add_delete_button = function (item) { - var new_buttons = $('').addClass("btn-group pull-right"); var notebooklist = this; var delete_button = $("").text("Delete").addClass("btn btn-default btn-xs"). click(function (e) { @@ -322,7 +320,7 @@ define([ var parent_item = that.parents('div.list_item'); var name = parent_item.data('nbname'); var path = parent_item.data('path'); - var message = 'Are you sure you want to permanently delete the file: ' + nbname + '?'; + var message = 'Are you sure you want to permanently delete the file: ' + name + '?'; dialog.modal({ title : "Delete file", body : message, @@ -330,9 +328,9 @@ define([ Delete : { class: "btn-danger", click: function() { - notebooklist.contents.delete(name, path, { + notebooklist.contents.delete(path, { success: function() { - notebooklist.notebook_deleted(path, name); + notebooklist.notebook_deleted(path); } }); } @@ -345,25 +343,24 @@ define([ item.find(".item_buttons").text("").append(delete_button); }; - NotebookList.prototype.notebook_deleted = function(path, name) { + NotebookList.prototype.notebook_deleted = function(path) { // Remove the deleted notebook. $( ":data(nbname)" ).each(function() { - var element = $( this ); - if (element.data( "nbname" ) == d.name && - element.data( "path" ) == d.path) { + var element = $(this); + if (element.data("path") == path) { element.remove(); } }); - } + }; - NotebookList.prototype.add_upload_button = function (item, type) { + NotebookList.prototype.add_upload_button = function (item) { var that = this; var upload_button = $('').text("Upload") .addClass('btn btn-primary btn-xs upload_button') .click(function (e) { - var path = that.notebook_path; var filename = item.find('.item_name > input').val(); + var path = utils.url_path_join(that.notebook_path, filename); var filedata = item.data('filedata'); var format = 'text'; if (filename.length === 0 || filename[0] === '.') { @@ -385,10 +382,7 @@ define([ filedata = btoa(bytes); format = 'base64'; } - var model = { - path: path, - name: filename - }; + var model = {}; var name_and_ext = utils.splitext(filename); var file_ext = name_and_ext[1]; @@ -418,34 +412,22 @@ define([ model.content = filedata; content_type = 'application/octet-stream'; } - var filedata = item.data('filedata'); + filedata = item.data('filedata'); var settings = { - processData : false, - cache : false, - type : 'PUT', - data : JSON.stringify(model), - contentType: content_type, - success : function (data, status, xhr) { + success : function () { item.removeClass('new-file'); that.add_link(model, item); that.add_delete_button(item); that.session_list.load_sessions(); }, - error : utils.log_ajax_error, }; - - var url = utils.url_join_encode( - that.base_url, - 'api/contents', - that.notebook_path, - filename - ); var exists = false; $.each(that.element.find('.list_item:not(.new-file)'), function(k,v){ if ($(v).data('name') === filename) { exists = true; return false; } }); + if (exists) { dialog.modal({ title : "Replace file", @@ -453,7 +435,9 @@ define([ buttons : { Overwrite : { class: "btn-danger", - click: function() { $.ajax(url, settings); } + click: function () { + that.contents.save(path, model, settings); + } }, Cancel : { click: function() { item.remove(); } @@ -461,7 +445,7 @@ define([ } }); } else { - $.ajax(url, settings); + that.contents.save(path, model, settings); } return false; @@ -478,7 +462,7 @@ define([ }; - // Backwards compatability. + // Backwards compatability. IPython.NotebookList = NotebookList; return {'NotebookList': NotebookList};