Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Dashboard improvement (necessary merge of #1658 and #1676 + fix #1492) #1739

Merged
merged 22 commits into from

5 participants

Matthias Bussonnier Brian E. Granger Fernando Perez Jens Hedegaard Nielsen Thomas Kluyver
Matthias Bussonnier
Owner

This is merge of #1658 (alternate upload) and #1676 (shutdown fron dashboard) that were conflicting, because #1658 (alternate upload) is necessary for #1676 (shutdown fron dashboard), otherwise you can't upload file as dashbord refresh just after drag and drop...

In addition :

One small bug fix of #1658.

fixes #1492 ( bigger drag target when no notebook), it show "list is empty" when no notebooks.

finally on master.

Carreau added some commits
Matthias Bussonnier Carreau alternate notebook upload methods
fixes #1562
334470c
Matthias Bussonnier Carreau multifile selection f01957f
Matthias Bussonnier Carreau clean html, style logon form ff6b85d
Matthias Bussonnier Carreau kernel status 341b864
Matthias Bussonnier Carreau proof of concept f9c25e3
Matthias Bussonnier Carreau clean unused command ede97ff
Matthias Bussonnier Carreau dashboard autorefresh
refresh notebook list and cluster list when :
- page get focus
- every 60 sec when page is on focus

stop refreshing every 60 sec when page loose focus
bd82968
Matthias Bussonnier Carreau test kernel for undefined rather than off b60b6de
Matthias Bussonnier Carreau rename kernel_status -> kernel_id c2d2e34
Matthias Bussonnier Carreau space around assignement 7244b9c
Matthias Bussonnier Carreau Check for null rather than undefined
set kernel id to None/null if not started
a809dd9
Matthias Bussonnier Carreau prevent autorefresh when pending upload
don't clear list if 'upload' button are present to avoid clearing the
list and the upload form
7f9bda0
Matthias Bussonnier Carreau add 'Close and halt' in notebook filemenu 68c8ac9
Matthias Bussonnier Carreau remove extra console.log 83c278d
Matthias Bussonnier Carreau bold click here in dashboard 214f204
Matthias Bussonnier Carreau remove underscore in filename 98aa620
Matthias Bussonnier Carreau i,b, in boilerplater.css 7a1e763
Matthias Bussonnier Carreau replace b by strong for semantic, more change in boilerplate 078e522
Matthias Bussonnier Carreau do not expose enable/disable autorefresh 04af03c
Matthias Bussonnier Carreau Drag target bigger for empty notebook dashboard
When no notebooks, show "Notebook list empty", which increase the size
of the drag target.

fixes #1492
f4a9b71
Matthias Bussonnier Carreau fix upload button selection by class
superseed #1676 #1658 (and correct bug in 1676 where one con't upload
notebook because of refresh)
df90df6
Brian E. Granger
Owner

@fperez, can you test this branch on Linux to see if this fixes the uploadability of notebooks? (in your vast spare time ;-)

Fernando Perez
Owner

I greatly appreciate the subtle sense of humor, @ellisonbg ;)

Sure, I'll try to take this for a spin tomorrow; I'm fried for the day. Thanks for reminding me...

Jens Hedegaard Nielsen

I have tested uploading notebooks via both the button and drag and drop on linux (ubuntu 12.04) in Firefox and Chromium and it appears to be working fine in all cases.
The shutdown button also works as expected and is a great feature. One small issue that I see is that if you keep a notebook open
but shut it down from the dash and try to execute code in the notebook afterwards the restart kernel dialog pops up as expected but if you press restart the cell is not actually executed until you rerun it but it appears busy i.e it shows up as "In [*]:" until you rerun it.

Matthias Bussonnier
Owner

I think this is a larger issue, this appends also if the kernel dies by itself.
Even more, you can save notebook with running prompt, and load them afterwards. They will still show cells with running prompt even if the new kernel is, of course, idle.

Jens Hedegaard Nielsen

@Carreau Yes you are right this change only makes it easier to expose the bug and I don't think that this
should hold back the merge of this pull request.

Matthias Bussonnier
Owner

I'll merge in a few hours if nobody as objection as it only adds some functionality and seem to work in linux.

Thomas Kluyver
Owner

@Carreau : Let's give people about a day, to make sure people in California have had a chance to look at it, though I expect it will be all OK.

Fernando Perez
Owner

I've confirmed that it works on Linux, and that indeed it allows uploading into Chrome when SSL is on. I double-checked that situation, and it looks like it's a chrome-specific thing (and could be just on linux), because with Firefox the d'n'd upload works fine. So this is a most welcome fix! Since it has already had good review otherwise, go for it.

My only suggestion would be to change the phrase in the dashboard

"Drag files onto the list, or click here, to import notebooks"

to

"To import a notebook, drag the file onto the listing below or click here."

I just think it reads better, that's all.

Matthias Bussonnier
Owner

Ok, changed, merging then.

Matthias Bussonnier Carreau merged commit 2caea25 into from
Jens Hedegaard Nielsen

Thanks for this improvement. I think a small bug appeared when the text was changed.
To me it seems like you only moved the test but did not change the position where one has to click
to open the file dialog. I have to click on either the or listing now to open the file dialog.

Matthias Bussonnier
Owner

Can you try to flush your browser cache,(css is often cached longer that html). I did change the size of the click area.
Actually you should be able to to click anywhere on the whole sentence to have the dialog opening.

Thanks.

Jens Hedegaard Nielsen

Yes I see. It works correctly in chrome. In firefox neither clearing the cache nor using a different user profile seems to work.

Matthias Bussonnier
Owner

hum... right, no idea why, the firefox css inspector does say that the fileinput have the right size, but dont correctly respond to click.

@fperez , should we then get back to
"Drag files onto the list, or click here, to import notebooks"
to be more aligned with FF ?

Fernando Perez
Owner

Mmh, I don't particularly like having to keep a contorted sentence to satisfy a bizarre browser bug... I guess if it's broken we do need to fix it, but in that case please open an issue about this so that we can return later to the problem (or somebody who knows more about browsers can). I find it truly strange that word order can affect clicking response...

From experimenting a bit with FF, it seems that it only responds to clicks in the area from the start of the sentence up to around 260 pixels, which is ~58% of the 447px input area.

So I suggest instead the following wording:

"To import a notebook, click here or drag a file onto the list below:"

Hopefully that will work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 15, 2012
  1. Matthias Bussonnier

    alternate notebook upload methods

    Carreau authored
    fixes #1562
  2. Matthias Bussonnier

    multifile selection

    Carreau authored
  3. Matthias Bussonnier

    clean html, style logon form

    Carreau authored
  4. Matthias Bussonnier

    kernel status

    Carreau authored
  5. Matthias Bussonnier

    proof of concept

    Carreau authored
  6. Matthias Bussonnier

    clean unused command

    Carreau authored
  7. Matthias Bussonnier

    dashboard autorefresh

    Carreau authored
    refresh notebook list and cluster list when :
    - page get focus
    - every 60 sec when page is on focus
    
    stop refreshing every 60 sec when page loose focus
  8. Matthias Bussonnier
  9. Matthias Bussonnier
  10. Matthias Bussonnier

    space around assignement

    Carreau authored
  11. Matthias Bussonnier

    Check for null rather than undefined

    Carreau authored
    set kernel id to None/null if not started
  12. Matthias Bussonnier

    prevent autorefresh when pending upload

    Carreau authored
    don't clear list if 'upload' button are present to avoid clearing the
    list and the upload form
  13. Matthias Bussonnier
  14. Matthias Bussonnier

    remove extra console.log

    Carreau authored
  15. Matthias Bussonnier

    bold click here in dashboard

    Carreau authored
  16. Matthias Bussonnier

    remove underscore in filename

    Carreau authored
  17. Matthias Bussonnier

    i,b, in boilerplater.css

    Carreau authored
  18. Matthias Bussonnier
  19. Matthias Bussonnier
  20. Matthias Bussonnier

    Drag target bigger for empty notebook dashboard

    Carreau authored
    When no notebooks, show "Notebook list empty", which increase the size
    of the drag target.
    
    fixes #1492
  21. Matthias Bussonnier

    fix upload button selection by class

    Carreau authored
    superseed #1676 #1658 (and correct bug in 1676 where one con't upload
    notebook because of refresh)
Commits on May 31, 2012
  1. Matthias Bussonnier

    change upload sentense

    Carreau authored
This page is out of date. Refresh to see the latest.
3  IPython/frontend/html/notebook/handlers.py
View
@@ -590,7 +590,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
23 IPython/frontend/html/notebook/static/css/alternateuploadform.css
View
@@ -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;
+}
3  IPython/frontend/html/notebook/static/css/boilerplate.css
View
@@ -70,4 +70,5 @@ select, input, textarea, button { font:99% sans-serif; }
en.wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome */
pre, code, kbd, samp { font-family: monospace, sans-serif; }
-
+em,i { font-style: italic; }
+b,strong { font-weight: bold; }
4 IPython/frontend/html/notebook/static/js/menubar.js
View
@@ -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();
104 IPython/frontend/html/notebook/static/js/notebooklist.js
View
@@ -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');
47 IPython/frontend/html/notebook/static/js/projectdashboardmain.js
View
@@ -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');
+ });
});
2  IPython/frontend/html/notebook/templates/login.html
View
@@ -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 %}
2  IPython/frontend/html/notebook/templates/notebook.html
View
@@ -65,6 +65,8 @@
</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>
10 IPython/frontend/html/notebook/templates/projectdashboard.html
View
@@ -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 @@
<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>
Something went wrong with that request. Please try again.