diff --git a/IPython/html/notebook/handlers.py b/IPython/html/notebook/handlers.py index c3a8cfd..1fe0d08 100644 --- a/IPython/html/notebook/handlers.py +++ b/IPython/html/notebook/handlers.py @@ -58,7 +58,9 @@ class NamedNotebookHandler(IPythonHandler): else: project = self.project + '/' + path +'/'+ name if not nbm.notebook_exists(notebook_path): - raise web.HTTPError(404, u'Notebook does not exist: %s' % name) + raise web.HTTPError(404, u'Notebook does not exist: %s' % name) + path = nbm.url_encode(path) + name = nbm.url_encode(name) self.write(self.render_template('notebook.html', project=project, notebook_path=path, diff --git a/IPython/html/services/notebooks/handlers.py b/IPython/html/services/notebooks/handlers.py index 1e2e92b..5c9175c 100644 --- a/IPython/html/services/notebooks/handlers.py +++ b/IPython/html/services/notebooks/handlers.py @@ -45,8 +45,8 @@ class NotebookRootHandler(IPythonHandler): model = nbm.notebook_model(notebook_name) self.set_header('Location', '{0}api/notebooks/{1}'.format(self.base_project_url, notebook_name)) self.finish(jsonapi.dumps(model)) - - + + class NotebookRootRedirect(IPythonHandler): @authenticate_unless_readonly diff --git a/IPython/html/services/notebooks/nbmanager.py b/IPython/html/services/notebooks/nbmanager.py index d51e865..439c614 100644 --- a/IPython/html/services/notebooks/nbmanager.py +++ b/IPython/html/services/notebooks/nbmanager.py @@ -20,6 +20,7 @@ import os import uuid from tornado import web +from urllib import quote, unquote from IPython.config.configurable import LoggingConfigurable from IPython.nbformat import current @@ -62,7 +63,23 @@ class NotebookManager(LoggingConfigurable): name = None path = notebook_path+'/' return name, path - + + def url_encode(self, path): + parts = path.split('/') + path="" + for part in parts: + part = quote(part) + path = os.path.join(path,part) + return path + + def url_decode(self, path): + parts = path.split('/') + path="" + for part in parts: + part = unquote(part) + path = os.path.join(path,part) + return path + def _notebook_dir_changed(self, new): """do a bit of validation of the notebook dir""" if not os.path.isabs(new): @@ -114,7 +131,7 @@ class NotebookManager(LoggingConfigurable): def notebook_exists(self, notebook_path): """Does a notebook exist?""" - + def notebook_model(self, notebook_name, notebook_path=None, content=True): """ Creates the standard notebook model """ last_modified, contents = self.read_notebook_object(notebook_name, notebook_path) diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js index 6df07a2..cc8fac1 100644 --- a/IPython/html/static/notebook/js/notebook.js +++ b/IPython/html/static/notebook/js/notebook.js @@ -78,6 +78,11 @@ var IPython = (function (IPython) { return this._baseProjectUrl || $('body').data('baseProjectUrl'); }; + Notebook.prototype.notebookName = function() { + var name = $('body').data('notebookName'); + return name; + }; + Notebook.prototype.notebookPath = function() { var path = $('body').data('notebookPath'); if (path != 'None') { diff --git a/IPython/html/static/notebook/js/savewidget.js b/IPython/html/static/notebook/js/savewidget.js index 1d99d08..c421457 100644 --- a/IPython/html/static/notebook/js/savewidget.js +++ b/IPython/html/static/notebook/js/savewidget.js @@ -47,6 +47,8 @@ var IPython = (function (IPython) { that.update_document_title(); }); $([IPython.events]).on('notebook_renamed.Notebook', function () { + that.update_notebook_name(); + that.update_document_title(); that.update_address_bar(); }); $([IPython.events]).on('notebook_save_failed.Notebook', function () { @@ -126,7 +128,8 @@ var IPython = (function (IPython) { SaveWidget.prototype.update_address_bar = function(){ var nbname = IPython.notebook.notebook_name; var path = IPython.notebook.notebookPath(); - window.location = path + nbname; + var state = {"path": path+nbname} + window.history.pushState(state, "", "/notebook/" + path+nbname); } diff --git a/IPython/html/static/tree/js/notebooklist.js b/IPython/html/static/tree/js/notebooklist.js index c7de4f7..257a78d 100644 --- a/IPython/html/static/tree/js/notebooklist.js +++ b/IPython/html/static/tree/js/notebooklist.js @@ -25,7 +25,7 @@ var IPython = (function (IPython) { NotebookList.prototype.baseProjectUrl = function () { return $('body').data('baseProjectUrl'); }; - + NotebookList.prototype.notebookPath = function() { var path = $('body').data('notebookPath'); if (path != "") { diff --git a/IPython/html/tree/handlers.py b/IPython/html/tree/handlers.py index 0ceabad..4fb53cd 100644 --- a/IPython/html/tree/handlers.py +++ b/IPython/html/tree/handlers.py @@ -43,11 +43,9 @@ class ProjectPathDashboardHandler(IPythonHandler): nbm = self.notebook_manager name, path = nbm.named_notebook_path(notebook_path) if name != None: - if path == None: - self.redirect(self.base_project_url + 'notebooks/' + quote(name)) - else: - self.redirect(self.base_project_url + 'notebooks/' + path + quote(name)) + self.redirect(self.base_project_url + 'notebooks/' + notebook_path) else: + path = nbm.url_encode(path) project = self.project + '/' + notebook_path self.write(self.render_template('tree.html', project=project,