diff --git a/IPython/frontend/html/notebook/handlers.py b/IPython/frontend/html/notebook/handlers.py index 92752a555..bc5dc9e1f 100644 --- a/IPython/frontend/html/notebook/handlers.py +++ b/IPython/frontend/html/notebook/handlers.py @@ -591,7 +591,10 @@ class NotebookRootHandler(AuthenticatedHandler): @authenticate_unless_readonly def get(self): nbm = self.application.notebook_manager + km = self.application.kernel_manager files = nbm.list_notebooks() + for f in files : + f['kernel_id'] = km.kernel_for_notebook(f['notebook_id']) self.finish(jsonapi.dumps(files)) @web.authenticated diff --git a/IPython/frontend/html/notebook/static/css/alternateuploadform.css b/IPython/frontend/html/notebook/static/css/alternateuploadform.css new file mode 100644 index 000000000..72dbb870a --- /dev/null +++ b/IPython/frontend/html/notebook/static/css/alternateuploadform.css @@ -0,0 +1,23 @@ +/* We need an invisible input field on top of the sentense*/ +/* "Drag file onto the list ..." */ + +.alternate_upload +{ + background-color:none; + display: inline; +} + +.alternate_upload.form +{ + padding: 0; + margin:0; +} + +.alternate_upload input.fileinput +{ + background-color:red; + position:relative; + opacity: 0; + z-index: 2; + width: 447px; +} diff --git a/IPython/frontend/html/notebook/static/js/menubar.js b/IPython/frontend/html/notebook/static/js/menubar.js index e7da9208f..a809cfd15 100644 --- a/IPython/frontend/html/notebook/static/js/menubar.js +++ b/IPython/frontend/html/notebook/static/js/menubar.js @@ -68,6 +68,10 @@ var IPython = (function (IPython) { this.element.find('button#print_notebook').click(function () { IPython.print_widget.print_notebook(); }); + this.element.find('#kill_and_exit').click(function () { + IPython.notebook.kernel.kill(); + setTimeout(function(){window.close();}, 200); + }); // Edit this.element.find('#cut_cell').click(function () { IPython.notebook.cut_cell(); diff --git a/IPython/frontend/html/notebook/static/js/notebooklist.js b/IPython/frontend/html/notebook/static/js/notebooklist.js index a7e98ee64..436325c7b 100644 --- a/IPython/frontend/html/notebook/static/js/notebooklist.js +++ b/IPython/frontend/html/notebook/static/js/notebooklist.js @@ -43,33 +43,44 @@ var IPython = (function (IPython) { this.element.bind('dragover', function () { return false; }); - this.element.bind('drop', function (event) { - var files = event.originalEvent.dataTransfer.files; - for (var i = 0, f; f = files[i]; i++) { - var reader = new FileReader(); - reader.readAsText(f); - var fname = f.name.split('.'); - var nbname = fname.slice(0,-1).join('.'); - var nbformat = fname.slice(-1)[0]; - if (nbformat === 'ipynb') {nbformat = 'json';}; - if (nbformat === 'py' || nbformat === 'json') { - var item = that.new_notebook_item(0); - that.add_name_input(nbname, item); - item.data('nbformat', nbformat); - // Store the notebook item in the reader so we can use it later - // to know which item it belongs to. - $(reader).data('item', item); - reader.onload = function (event) { - var nbitem = $(event.target).data('item'); - that.add_notebook_data(event.target.result, nbitem); - that.add_upload_button(nbitem); - }; - }; - } + this.element.bind('drop', function(event){ + that.handelFilesUpload(event,'drop'); return false; }); }; + NotebookList.prototype.handelFilesUpload = function(event, dropOrForm) { + var that = this; + var files; + if(dropOrForm =='drop'){ + files = event.originalEvent.dataTransfer.files; + } else + { + files = event.originalEvent.target.files + } + for (var i = 0, f; f = files[i]; i++) { + var reader = new FileReader(); + reader.readAsText(f); + var fname = f.name.split('.'); + var nbname = fname.slice(0,-1).join('.'); + var nbformat = fname.slice(-1)[0]; + if (nbformat === 'ipynb') {nbformat = 'json';}; + if (nbformat === 'py' || nbformat === 'json') { + var item = that.new_notebook_item(0); + that.add_name_input(nbname, item); + item.data('nbformat', nbformat); + // Store the notebook item in the reader so we can use it later + // to know which item it belongs to. + $(reader).data('item', item); + reader.onload = function (event) { + var nbitem = $(event.target).data('item'); + that.add_notebook_data(event.target.result, nbitem); + that.add_upload_button(nbitem); + }; + }; + } + return false; + }; NotebookList.prototype.clear_list = function () { this.element.children('.list_item').remove(); @@ -77,7 +88,6 @@ var IPython = (function (IPython) { NotebookList.prototype.load_list = function () { - this.clear_list(); var settings = { processData : false, cache : false, @@ -92,15 +102,30 @@ var IPython = (function (IPython) { NotebookList.prototype.list_loaded = function (data, status, xhr) { var len = data.length; - // Todo: remove old children + this.clear_list(); + + if(len == 0) + { + $(this.new_notebook_item(0)) + .append( + $('
') + .text('Notebook list empty.') + ) + } + for (var i=0; i').addClass('item_buttons'); + var that = this; + var shutdown_button = $('').button(). + click(function (e) { + var settings = { + processData : false, + cache : false, + type : "DELETE", + dataType : "json", + success : function (data, status, xhr) { + that.load_list(); + } + }; + var url = $('body').data('baseProjectUrl') + 'kernels/'+kernel; + $.ajax(url, settings); + }); + new_buttons.append(shutdown_button); + var e = item.find('.item_buttons'); + if (e.length === 0) { + item.append(new_buttons); + } else { + e.replaceWith(new_buttons); + }; + }; + NotebookList.prototype.add_delete_button = function (item) { var new_buttons = $('').addClass('item_buttons'); var delete_button = $('').button(). @@ -217,6 +268,7 @@ var IPython = (function (IPython) { var that = this; var new_buttons = $('').addClass('item_buttons'); var upload_button = $('').button(). + addClass('upload-button'). click(function (e) { var nbname = item.find('.item_name > input').attr('value'); var nbformat = item.data('nbformat'); diff --git a/IPython/frontend/html/notebook/static/js/projectdashboardmain.js b/IPython/frontend/html/notebook/static/js/projectdashboardmain.js index 1f6a69f26..b593302ed 100644 --- a/IPython/frontend/html/notebook/static/js/projectdashboardmain.js +++ b/IPython/frontend/html/notebook/static/js/projectdashboardmain.js @@ -30,10 +30,53 @@ $(document).ready(function () { IPython.cluster_list = new IPython.ClusterList('div#cluster_list'); IPython.login_widget = new IPython.LoginWidget('span#login_widget'); - IPython.notebook_list.load_list(); - IPython.cluster_list.load_list(); + var interval_id=0; + // auto refresh every xx secondes, no need to be fast, + // update is done at least when page get focus + var time_refresh = 60; // in sec + + var enable_autorefresh = function(){ + //refresh immediately , then start interval + if($('.upload_button').length == 0) + { + IPython.notebook_list.load_list(); + IPython.cluster_list.load_list(); + } + if (!interval_id){ + interval_id = setInterval(function(){ + if($('.upload_button').length == 0) + { + IPython.notebook_list.load_list(); + IPython.cluster_list.load_list(); + } + }, time_refresh*1000); + } + } + + var disable_autorefresh = function(){ + clearInterval(interval_id); + interval_id = 0; + } + + // stop autorefresh when page lose focus + $(window).blur(function() { + disable_autorefresh(); + }) + + //re-enable when page get focus back + $(window).focus(function() { + enable_autorefresh(); + }); + + // finally start it, it will refresh immediately + enable_autorefresh(); IPython.page.show(); + + // bound the upload method to the on change of the file select list + $("#alternate_upload").change(function (event){ + IPython.notebook_list.handelFilesUpload(event,'form'); + }); }); diff --git a/IPython/frontend/html/notebook/templates/login.html b/IPython/frontend/html/notebook/templates/login.html index b99dc0866..34f2a0e1d 100644 --- a/IPython/frontend/html/notebook/templates/login.html +++ b/IPython/frontend/html/notebook/templates/login.html @@ -17,7 +17,7 @@ {% if login_available %}
- Password: + Password:
{% end %} diff --git a/IPython/frontend/html/notebook/templates/notebook.html b/IPython/frontend/html/notebook/templates/notebook.html index 7a6e3e9ed..89d2ab704 100644 --- a/IPython/frontend/html/notebook/templates/notebook.html +++ b/IPython/frontend/html/notebook/templates/notebook.html @@ -65,6 +65,8 @@ data-notebook-id={{notebook_id}}
+
+
  • Close and halt
  • Edit diff --git a/IPython/frontend/html/notebook/templates/projectdashboard.html b/IPython/frontend/html/notebook/templates/projectdashboard.html index 42aefb478..9d91be3ea 100644 --- a/IPython/frontend/html/notebook/templates/projectdashboard.html +++ b/IPython/frontend/html/notebook/templates/projectdashboard.html @@ -4,6 +4,7 @@ {% block stylesheet %} + {% end %} @@ -30,9 +31,12 @@ data-read-only={{read_only}}
    {% if logged_in or not read_only %}
    - Drag files onto the list to import - notebooks. - +
    + + To import a notebook, drag the file onto the listing below or click here. + + +