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

@Carreau
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
@Carreau Carreau alternate notebook upload methods
fixes #1562
334470c
@Carreau Carreau multifile selection f01957f
@Carreau Carreau clean html, style logon form ff6b85d
@Carreau Carreau kernel status 341b864
@Carreau Carreau proof of concept f9c25e3
@Carreau Carreau clean unused command ede97ff
@Carreau 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
@Carreau Carreau test kernel for undefined rather than off b60b6de
@Carreau Carreau rename kernel_status -> kernel_id c2d2e34
@Carreau Carreau space around assignement 7244b9c
@Carreau Carreau Check for null rather than undefined
set kernel id to None/null if not started
a809dd9
@Carreau 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
@Carreau Carreau add 'Close and halt' in notebook filemenu 68c8ac9
@Carreau Carreau remove extra console.log 83c278d
@Carreau Carreau bold click here in dashboard 214f204
@Carreau Carreau remove underscore in filename 98aa620
@Carreau Carreau i,b, in boilerplater.css 7a1e763
@Carreau Carreau replace b by strong for semantic, more change in boilerplate 078e522
@Carreau Carreau do not expose enable/disable autorefresh 04af03c
@Carreau 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
@Carreau 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
@ellisonbg
Owner

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

@fperez
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...

@jenshnielsen

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.

@Carreau
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.

@jenshnielsen

@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.

@Carreau
Owner

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

@takluyver
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.

@fperez
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.

@Carreau
Owner

Ok, changed, merging then.

@Carreau Carreau merged commit 2caea25 into ipython:master
@jenshnielsen

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.

@Carreau
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.

@jenshnielsen

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

@Carreau
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 ?

@fperez
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. @Carreau

    alternate notebook upload methods

    Carreau authored
    fixes #1562
  2. @Carreau

    multifile selection

    Carreau authored
  3. @Carreau

    clean html, style logon form

    Carreau authored
  4. @Carreau

    kernel status

    Carreau authored
  5. @Carreau

    proof of concept

    Carreau authored
  6. @Carreau

    clean unused command

    Carreau authored
  7. @Carreau

    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. @Carreau
  9. @Carreau
  10. @Carreau

    space around assignement

    Carreau authored
  11. @Carreau

    Check for null rather than undefined

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

    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. @Carreau
  14. @Carreau

    remove extra console.log

    Carreau authored
  15. @Carreau

    bold click here in dashboard

    Carreau authored
  16. @Carreau

    remove underscore in filename

    Carreau authored
  17. @Carreau

    i,b, in boilerplater.css

    Carreau authored
  18. @Carreau
  19. @Carreau
  20. @Carreau

    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. @Carreau

    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. @Carreau

    change upload sentense

    Carreau authored
This page is out of date. Refresh to see the latest.
View
3  IPython/frontend/html/notebook/handlers.py
@@ -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
View
23 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;
+}
View
3  IPython/frontend/html/notebook/static/css/boilerplate.css
@@ -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; }
View
4 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();
View
104 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(
+ $('<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');
View
47 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');
+ });
});
View
2  IPython/frontend/html/notebook/templates/login.html
@@ -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 %}
View
2  IPython/frontend/html/notebook/templates/notebook.html
@@ -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>
View
10 IPython/frontend/html/notebook/templates/projectdashboard.html
@@ -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.