mirror of
https://github.com/jupyter/notebook.git
synced 2025-04-12 14:00:27 +08:00
Merge pull request #1739 from Carreau/dashboardImprovement
Dashboard improvement see #1658 #1676 Allow to shutdown the kernels from the dashboard, autorefresh dashboard, add a native upload method, especially for https/chrome/linux that prevent drag and drop
This commit is contained in:
commit
711c2ef6cc
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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();
|
||||
|
@ -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(
|
||||
$('<div style="margin:auto;text-align:center;color:grey"/>')
|
||||
.text('Notebook list empty.')
|
||||
)
|
||||
}
|
||||
|
||||
for (var i=0; i<len; i++) {
|
||||
var notebook_id = data[i].notebook_id;
|
||||
var nbname = data[i].name;
|
||||
var kernel = data[i].kernel_id;
|
||||
var item = this.new_notebook_item(i);
|
||||
this.add_link(notebook_id, nbname, item);
|
||||
if (!IPython.read_only){
|
||||
// hide delete buttons when readonly
|
||||
this.add_delete_button(item);
|
||||
if(kernel == null){
|
||||
this.add_delete_button(item);
|
||||
} else {
|
||||
this.add_shutdown_button(item,kernel);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -164,6 +189,32 @@ var IPython = (function (IPython) {
|
||||
};
|
||||
|
||||
|
||||
NotebookList.prototype.add_shutdown_button = function (item,kernel) {
|
||||
var new_buttons = $('<span/>').addClass('item_buttons');
|
||||
var that = this;
|
||||
var shutdown_button = $('<button>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 = $('<span/>').addClass('item_buttons');
|
||||
var delete_button = $('<button>Delete</button>').button().
|
||||
@ -217,6 +268,7 @@ var IPython = (function (IPython) {
|
||||
var that = this;
|
||||
var new_buttons = $('<span/>').addClass('item_buttons');
|
||||
var upload_button = $('<button>Upload</button>').button().
|
||||
addClass('upload-button').
|
||||
click(function (e) {
|
||||
var nbname = item.find('.item_name > input').attr('value');
|
||||
var nbformat = item.data('nbformat');
|
||||
|
@ -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');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
{% if login_available %}
|
||||
<form action="/login?next={{url_escape(next)}}" method="post">
|
||||
Password: <input type="password" name="password" id="password_input">
|
||||
Password: <input type="password" class='ui-widget ui-widget-content' name="password" id="password_input">
|
||||
<input type="submit" value="Log in" id="login_submit">
|
||||
</form>
|
||||
{% end %}
|
||||
|
@ -65,6 +65,8 @@ data-notebook-id={{notebook_id}}
|
||||
</li>
|
||||
<hr/>
|
||||
<li id="print_notebook"><a href="/{{notebook_id}}/print" target="_blank">Print View</a></li>
|
||||
<hr/>
|
||||
<li id="kill_and_exit"><a href="#" >Close and halt</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#">Edit</a>
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
{% block stylesheet %}
|
||||
<link rel="stylesheet" href="{{static_url("css/projectdashboard.css") }}" type="text/css" />
|
||||
<link rel="stylesheet" href="{{static_url("css/alternateuploadform.css") }}" type="text/css" />
|
||||
{% end %}
|
||||
|
||||
|
||||
@ -30,9 +31,12 @@ data-read-only={{read_only}}
|
||||
<div id="tab1">
|
||||
{% if logged_in or not read_only %}
|
||||
<div id="notebook_toolbar">
|
||||
<span id="drag_info">Drag files onto the list to import
|
||||
notebooks.</span>
|
||||
|
||||
<form id='alternate_upload' class='alternate_upload' >
|
||||
<span id="drag_info" style="position:absolute" >
|
||||
To import a notebook, drag the file onto the listing below or <strong>click here</strong>.
|
||||
</span>
|
||||
<input type="file" name="datafile" class="fileinput" multiple='multiple'>
|
||||
</form>
|
||||
<span id="notebook_buttons">
|
||||
<button id="refresh_notebook_list" title="Refresh notebook list">Refresh</button>
|
||||
<button id="new_notebook" title="Create new notebook">New Notebook</button>
|
||||
|
Loading…
x
Reference in New Issue
Block a user