From 482ea4bb6712c94d80b1f80717baafdd26661a70 Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Sat, 10 Sep 2016 15:26:32 -0400 Subject: [PATCH 1/7] Adds edit and view buttons, #1752 --- notebook/static/tree/js/notebooklist.js | 32 +++++++++++++++++++++++++ notebook/templates/tree.html | 2 ++ 2 files changed, 34 insertions(+) diff --git a/notebook/static/tree/js/notebooklist.js b/notebook/static/tree/js/notebooklist.js index 5203e32cc2..0bc91b1ec0 100644 --- a/notebook/static/tree/js/notebooklist.js +++ b/notebook/static/tree/js/notebooklist.js @@ -139,6 +139,8 @@ define([ $('.download-button').click($.proxy(this.download_selected, this)); $('.shutdown-button').click($.proxy(this.shutdown_selected, this)); $('.duplicate-button').click($.proxy(this.duplicate_selected, this)); + $('.view-button').click($.proxy(this.view_selected, this)); + $('.edit-button').click($.proxy(this.edit_selected, this)); $('.delete-button').click($.proxy(this.delete_selected, this)); // Bind events for selection menu buttons. @@ -597,6 +599,20 @@ define([ $('.delete-button').css('display', 'none'); } + // View is visible when an item is renderable or downloadable + if (selected.length > 0 && !has_directory) { + $('.view-button').css('display', 'inline-block'); + } else { + $('.view-button').css('display', 'none'); + } + + // Edit is visible when an item is editable + if (selected.length > 0 && !has_directory) { + $('.edit-button').css('display', 'inline-block'); + } else { + $('.edit-button').css('display', 'none'); + } + // If all of the items are selected, show the selector as checked. If // some of the items are selected, show it as checked. Otherwise, // uncheck it. @@ -937,6 +953,22 @@ define([ }); }; + NotebookList.prototype.view_selected = function() { + var that = this; + that.selected.forEach(function(item) { + var item_path = item.path; + var w = window.open(utils.url_path_join('/files', item_path)); + }); + } + + NotebookList.prototype.edit_selected = function() { + var that = this; + that.selected.forEach(function(item) { + var item_path = item.path; + var w = window.open(utils.url_path_join('/edit', item_path)); + }); + } + NotebookList.prototype.duplicate_selected = function() { var message; var selected = this.selected.slice(); // Don't let that.selected change out from under us diff --git a/notebook/templates/tree.html b/notebook/templates/tree.html index f42285ab7e..8848512b08 100644 --- a/notebook/templates/tree.html +++ b/notebook/templates/tree.html @@ -33,6 +33,8 @@ + + From a7387b863387ea8a1281b098bb4bf4329a212931 Mon Sep 17 00:00:00 2001 From: Grant Nestor Date: Thu, 17 Nov 2016 14:20:17 -0800 Subject: [PATCH 2/7] Revise https://github.com/jupyter/notebook/pull/1755 --- notebook/static/tree/js/notebooklist.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/notebook/static/tree/js/notebooklist.js b/notebook/static/tree/js/notebooklist.js index 0bc91b1ec0..774756f9a4 100644 --- a/notebook/static/tree/js/notebooklist.js +++ b/notebook/static/tree/js/notebooklist.js @@ -956,18 +956,18 @@ define([ NotebookList.prototype.view_selected = function() { var that = this; that.selected.forEach(function(item) { - var item_path = item.path; - var w = window.open(utils.url_path_join('/files', item_path)); - }); - } + var item_path = utils.encode_uri_components(item.path); + var w = window.open(utils.url_path_join(that.base_url, '/files', utils.encode_uri_components(item_path)), IPython._target); + }); + }; NotebookList.prototype.edit_selected = function() { var that = this; that.selected.forEach(function(item) { - var item_path = item.path; - var w = window.open(utils.url_path_join('/edit', item_path)); - }); - } + var item_path = utils.encode_uri_components(item.path); + var w = window.open(utils.url_path_join(that.base_url, '/edit', utils.encode_uri_components(item_path)), IPython._target); + }); + }; NotebookList.prototype.duplicate_selected = function() { var message; From b7dcae6a56e2b1458e46bde400fe1c7712d1eb7a Mon Sep 17 00:00:00 2001 From: Grant Nestor Date: Fri, 18 Nov 2016 09:42:11 -0800 Subject: [PATCH 3/7] Update View and Edit conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Edit notebook opens a notebook, Edit any other file type open it in a text editor * View only available for HTML files to disambiguate between “viewing” a notebook or text file (which is the same as editing it) and viewing an HTML file --- notebook/static/tree/js/notebooklist.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/notebook/static/tree/js/notebooklist.js b/notebook/static/tree/js/notebooklist.js index 774756f9a4..819d3d732c 100644 --- a/notebook/static/tree/js/notebooklist.js +++ b/notebook/static/tree/js/notebooklist.js @@ -600,7 +600,9 @@ define([ } // View is visible when an item is renderable or downloadable - if (selected.length > 0 && !has_directory) { + if (selected.length > 0 && !has_directory && selected.every(function(el) { + return el.path.match(/html?|jpe?g|png|gif|tiff?|svg|bmp|ico|pdf|doc|xls/); + })) { $('.view-button').css('display', 'inline-block'); } else { $('.view-button').css('display', 'none'); @@ -965,7 +967,8 @@ define([ var that = this; that.selected.forEach(function(item) { var item_path = utils.encode_uri_components(item.path); - var w = window.open(utils.url_path_join(that.base_url, '/edit', utils.encode_uri_components(item_path)), IPython._target); + var item_type = item_path.endsWith('.ipynb') ? 'notebooks' : 'edit'; + var w = window.open(utils.url_path_join(that.base_url, item_type, utils.encode_uri_components(item_path)), IPython._target); }); }; From 0034f2a251a3218bf7190515bd6bd8f3c9dec9da Mon Sep 17 00:00:00 2001 From: Grant Nestor Date: Tue, 24 Jan 2017 19:58:15 -0800 Subject: [PATCH 4/7] Create `/view` route, handler, and template --- notebook/notebookapp.py | 1 + notebook/templates/view.html | 30 ++++++++++++++++++++++++++++++ notebook/view/__init__.py | 0 notebook/view/handlers.py | 26 ++++++++++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 notebook/templates/view.html create mode 100644 notebook/view/__init__.py create mode 100644 notebook/view/handlers.py diff --git a/notebook/notebookapp.py b/notebook/notebookapp.py index 5c754e2a0f..db9cee85cb 100755 --- a/notebook/notebookapp.py +++ b/notebook/notebookapp.py @@ -265,6 +265,7 @@ def init_handlers(self, settings): handlers.extend([(r"/login", settings['login_handler_class'])]) handlers.extend([(r"/logout", settings['logout_handler_class'])]) handlers.extend(load_handlers('files.handlers')) + handlers.extend(load_handlers('view.handlers')) handlers.extend(load_handlers('notebook.handlers')) handlers.extend(load_handlers('nbconvert.handlers')) handlers.extend(load_handlers('bundler.handlers')) diff --git a/notebook/templates/view.html b/notebook/templates/view.html new file mode 100644 index 0000000000..7fd8c38c56 --- /dev/null +++ b/notebook/templates/view.html @@ -0,0 +1,30 @@ + + + + + + {{page_title}} + + + + + +
+ +
+ + + diff --git a/notebook/view/__init__.py b/notebook/view/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/notebook/view/handlers.py b/notebook/view/handlers.py new file mode 100644 index 0000000000..4d7e978442 --- /dev/null +++ b/notebook/view/handlers.py @@ -0,0 +1,26 @@ +#encoding: utf-8 +"""Tornado handlers for viewing HTML files.""" + +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. + +from tornado import web +from ..base.handlers import IPythonHandler, path_regex +from ..utils import url_escape + +class ViewHandler(IPythonHandler): + """Render HTML files within an iframe.""" + @web.authenticated + def get(self, path): + path = path.strip('/') + if not self.contents_manager.file_exists(path): + raise web.HTTPError(404, u'File does not exist: %s' % path) + + basename = path.rsplit('/', 1)[-1] + self.write( + self.render_template('view.html', file_path=url_escape(path), page_title=basename) + ) + +default_handlers = [ + (r"/view%s" % path_regex, ViewHandler), +] From 224294c2743df1df2855ea511ad4f612080472b0 Mon Sep 17 00:00:00 2001 From: Grant Nestor Date: Tue, 24 Jan 2017 19:58:28 -0800 Subject: [PATCH 5/7] Use `/view` route for HTML files --- notebook/static/tree/js/notebooklist.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/notebook/static/tree/js/notebooklist.js b/notebook/static/tree/js/notebooklist.js index 819d3d732c..d68bad122a 100644 --- a/notebook/static/tree/js/notebooklist.js +++ b/notebook/static/tree/js/notebooklist.js @@ -959,7 +959,8 @@ define([ var that = this; that.selected.forEach(function(item) { var item_path = utils.encode_uri_components(item.path); - var w = window.open(utils.url_path_join(that.base_url, '/files', utils.encode_uri_components(item_path)), IPython._target); + var item_type = item_path.endsWith('.html') ? 'view' : 'files'; + var w = window.open(utils.url_path_join(that.base_url, item_type, utils.encode_uri_components(item_path)), IPython._target); }); }; From 3cbb5700ccd62d7d7371f326aa86a36ead3444a9 Mon Sep 17 00:00:00 2001 From: Grant Nestor Date: Tue, 24 Jan 2017 21:26:32 -0800 Subject: [PATCH 6/7] Add `test_view_html` --- notebook/tests/test_files.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/notebook/tests/test_files.py b/notebook/tests/test_files.py index 96c6bf93ae..2568b3991a 100644 --- a/notebook/tests/test_files.py +++ b/notebook/tests/test_files.py @@ -113,6 +113,16 @@ def test_download(self): disposition = r.headers.get('Content-Disposition', '') self.assertIn('attachment', disposition) self.assertIn('filename="test.txt"', disposition) + + def test_view_html(self): + nbdir = self.notebook_dir.name + + html = '
Test test
' + with open(pjoin(nbdir, 'test.html'), 'w') as f: + f.write(html) + + r = self.request('GET', 'view/test.html') + self.assertEqual(r.status_code, 200) def test_old_files_redirect(self): """pre-2.0 'files/' prefixed links are properly redirected""" @@ -145,4 +155,3 @@ def test_old_files_redirect(self): r = self.request('GET', url) self.assertEqual(r.status_code, 200) self.assertEqual(r.text, prefix + '/f3') - From acf4fa8ce5de1ca21449b231796317df3ed1a1c2 Mon Sep 17 00:00:00 2001 From: Grant Nestor Date: Tue, 24 Jan 2017 21:36:22 -0800 Subject: [PATCH 7/7] Clean up --- notebook/static/tree/js/notebooklist.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/notebook/static/tree/js/notebooklist.js b/notebook/static/tree/js/notebooklist.js index d68bad122a..f91ecd39e8 100644 --- a/notebook/static/tree/js/notebooklist.js +++ b/notebook/static/tree/js/notebooklist.js @@ -560,9 +560,9 @@ define([ $('.rename-button').css('display', 'none'); } - // Move is visible iff at least one item is selected, and none of them + // Move is visible if at least one item is selected, and none of them // are a running notebook. - if (selected.length >= 1 && !has_running_notebook) { + if (selected.length > 0 && !has_running_notebook) { $('.move-button').css('display', 'inline-block'); } else { $('.move-button').css('display', 'none'); @@ -601,7 +601,7 @@ define([ // View is visible when an item is renderable or downloadable if (selected.length > 0 && !has_directory && selected.every(function(el) { - return el.path.match(/html?|jpe?g|png|gif|tiff?|svg|bmp|ico|pdf|doc|xls/); + return el.path.match(/html?|json|jpe?g|png|gif|tiff?|svg|bmp|ico|pdf|doc|xls/); })) { $('.view-button').css('display', 'inline-block'); } else { @@ -905,7 +905,7 @@ define([ var item_path = that.selected[0].path; - window.open(utils.url_path_join(that.base_url, 'files', item_path) + '?download=1'); + window.open(utils.url_path_join(that.base_url, 'files', utils.encode_uri_components(item_path)) + '?download=1', IPython._target); }; NotebookList.prototype.delete_selected = function() { @@ -959,8 +959,9 @@ define([ var that = this; that.selected.forEach(function(item) { var item_path = utils.encode_uri_components(item.path); + // Handle HTML files differently var item_type = item_path.endsWith('.html') ? 'view' : 'files'; - var w = window.open(utils.url_path_join(that.base_url, item_type, utils.encode_uri_components(item_path)), IPython._target); + window.open(utils.url_path_join(that.base_url, item_type, utils.encode_uri_components(item_path)), IPython._target); }); }; @@ -968,8 +969,9 @@ define([ var that = this; that.selected.forEach(function(item) { var item_path = utils.encode_uri_components(item.path); + // Handle ipynb files differently var item_type = item_path.endsWith('.ipynb') ? 'notebooks' : 'edit'; - var w = window.open(utils.url_path_join(that.base_url, item_type, utils.encode_uri_components(item_path)), IPython._target); + window.open(utils.url_path_join(that.base_url, item_type, utils.encode_uri_components(item_path)), IPython._target); }); };