Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

File upload/import working from notebook browser.

  • Loading branch information...
commit 53c7ec7497b11133bf270668219aedc996429e94 1 parent b0243db
Brian E. Granger ellisonbg authored
6 IPython/frontend/html/notebook/handlers.py
View
@@ -89,8 +89,9 @@ def post(self):
nbm = self.application.notebook_manager
body = self.request.body.strip()
format = self.get_argument('format', default='json')
+ name = self.get_argument('name', default=None)
if body:
- notebook_id = nbm.save_new_notebook(body, format)
+ notebook_id = nbm.save_new_notebook(body, name=name, format=format)
else:
notebook_id = nbm.new_notebook()
self.set_header('Location', '/'+notebook_id)
@@ -120,7 +121,8 @@ def get(self, notebook_id):
def put(self, notebook_id):
nbm = self.application.notebook_manager
format = self.get_argument('format', default='json')
- nbm.save_notebook(notebook_id, self.request.body, format)
+ name = self.get_argument('name', default=None)
+ nbm.save_notebook(notebook_id, self.request.body, name=name, format=format)
self.set_status(204)
self.finish()
45 IPython/frontend/html/notebook/notebookmanager.py
View
@@ -124,30 +124,57 @@ def get_notebook_object(self, notebook_id):
raise web.HTTPError(404)
return last_modified, nb
- def save_new_notebook(self, data, format=u'json'):
- """Save a new notebook and return its notebook_id."""
+ def save_new_notebook(self, data, name=None, format=u'json'):
+ """Save a new notebook and return its notebook_id.
+
+ If a name is passed in, it overrides any values in the notebook data
+ and the value in the data is updated to use that value.
+ """
if format not in self.allowed_formats:
raise web.HTTPError(415)
+
try:
nb = current.reads(data, format)
except:
- raise web.HTTPError(400)
- try:
- name = nb.name
- except AttributeError:
- raise web.HTTPError(400)
+ if format == u'xml':
+ # v1 notebooks might come in with a format='xml' but be json.
+ try:
+ nb = current.reads(data, u'json')
+ except:
+ raise web.HTTPError(400)
+ else:
+ raise web.HTTPError(400)
+
+ if name is None:
+ try:
+ name = nb.name
+ except AttributeError:
+ raise web.HTTPError(400)
+ nb.name = name
+
notebook_id = self.new_notebook_id(name)
self.save_notebook_object(notebook_id, nb)
return notebook_id
- def save_notebook(self, notebook_id, data, format=u'json'):
+ def save_notebook(self, notebook_id, data, name=None, format=u'json'):
"""Save an existing notebook by notebook_id."""
if format not in self.allowed_formats:
raise web.HTTPError(415)
+
try:
nb = current.reads(data, format)
except:
- raise web.HTTPError(400)
+ if format == u'xml':
+ # v1 notebooks might come in with a format='xml' but be json.
+ try:
+ nb = current.reads(data, u'json')
+ except:
+ raise web.HTTPError(400)
+ else:
+ raise web.HTTPError(400)
+
+ if name is not None:
+ nb.name = name
self.save_notebook_object(notebook_id, nb)
def save_notebook_object(self, notebook_id, nb):
20 IPython/frontend/html/notebook/static/css/nbbrowser.css
View
@@ -18,12 +18,22 @@ body {
overflow: auto;
}
+#left_panel {
+}
+
+#drop_zone {
+ height: 200px;
+ width: 200px
+}
+
#content_panel {
width: 600px;
}
#content_toolbar {
- padding: 10px 5px;
+ padding: 10px 5px 5px 5px;
+ height: 25px;
+ line-height: 25px;
}
#header_border {
@@ -35,6 +45,10 @@ body {
width: 100%;
}
+#drag_info {
+ float: left;
+}
+
#notebooks_buttons {
float: right;
}
@@ -59,6 +73,10 @@ body {
float: right;
}
+.item_buttons .upload_button {
+ color: darkred;
+}
+
.highlight_text {
color: blue;
}
7 IPython/frontend/html/notebook/static/js/nbbrowser_main.js
View
@@ -10,14 +10,17 @@ $(document).ready(function () {
$('div#header_border').addClass('border-box-sizing ui-widget ui-widget-content');
$('div#main_app').addClass('border-box-sizing ui-widget');
- $('div#app_hbox').addClass('hbox center');
+ $('div#app_hbox').addClass('hbox');
$('div#content_toolbar').addClass('ui-widget ui-helper-clearfix');
- $('#new_notebook').click(function (e) {
+ $('#new_notebook').button().click(function (e) {
window.open('/new');
});
+ $('div#left_panel').addClass('box-flex');
+ $('div#right_panel').addClass('box-flex');
+
IPython.notebook_list = new IPython.NotebookList('div#notebook_list');
IPython.notebook_list.load_list();
229 IPython/frontend/html/notebook/static/js/notebooklist.js
View
@@ -21,7 +21,35 @@ var IPython = (function (IPython) {
NotebookList.prototype.bind_events = function () {
-
+ var that = this;
+ 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[0];
+ var nbformat = fname[1];
+ if (nbformat === 'ipynb') {nbformat = 'xml';};
+ if (nbformat === 'xml' || 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;
+ });
};
@@ -31,7 +59,7 @@ var IPython = (function (IPython) {
cache : false,
type : "GET",
dataType : "json",
- success : $.proxy(this.list_loaded,this)
+ success : $.proxy(this.list_loaded, this)
};
$.ajax("/notebooks", settings);
};
@@ -39,64 +67,157 @@ var IPython = (function (IPython) {
NotebookList.prototype.list_loaded = function (data, status, xhr) {
var len = data.length;
+ // Todo: remove old children
for (var i=0; i<len; i++) {
var notebook_id = data[i].notebook_id;
var nbname = data[i].name;
+ var item = this.new_notebook_item(i);
+ this.add_link(notebook_id, nbname, item);
+ this.add_delete_button(item);
+ };
+ };
- var item = $('<div/>');
- item.addClass('notebook_item ui-widget ui-widget-content ui-helper-clearfix');
- var item_name = $('<span/>').addClass('item_name').append(
- $('<a/>').attr('href','/'+notebook_id).
- attr('target','_blank').
- text(nbname)
- );
- // Store the nbname and notebook_id on the item for later usage. We have to do this
- // because the loop over elements changes the values of the local nbname and notebook_id
- // variables.
- item.data('notebook_id',notebook_id);
- item.data('nbname',nbname);
-
- var buttons = $('<span/>').addClass('item_buttons');
- var delete_button = $('<button>Delete</button>').button().
- click(function (e) {
- // $(this) is the button that was clicked.
- var that = $(this);
- // We use the nbname and notebook_id from the parent notebook_item element's
- // data because the outer scopes values change as we iterate through the loop.
- var parent_item = that.parents('div.notebook_item');
- var nbname = parent_item.data('nbname');
- var notebook_id = parent_item.data('notebook_id');
- var dialog = $('<div/>');
- dialog.html('Are you sure you want to permanently delete the notebook: ' + nbname + '?');
- parent_item.append(dialog);
- dialog.dialog({
- resizable: false,
- modal: true,
- title: "Delete notebook",
- buttons : {
- "Delete": function () {
- var settings = {
- processData : false,
- cache : false,
- type : "DELETE",
- dataType : "json",
- success : function (data, status, xhr) {
- parent_item.remove();
- }
- };
- $.ajax("/notebooks/" + notebook_id, settings);
- $(this).dialog('close');
- },
- "Cancel": function () {
- $(this).dialog('close');
- }
- }
- });
- });
- buttons.append(delete_button);
- item.append(item_name).append(buttons);
+
+ NotebookList.prototype.new_notebook_item = function (index) {
+ var item = $('<div/>');
+ item.addClass('notebook_item ui-widget ui-widget-content ui-helper-clearfix');
+ var item_name = $('<span/>').addClass('item_name');
+
+ item.append(item_name);
+ if (index === -1) {
this.element.append(item);
+ } else {
+ this.element.children().eq(index).after(item);
}
+ return item;
+ };
+
+
+ NotebookList.prototype.add_link = function (notebook_id, nbname, item) {
+ item.data('nbname', nbname);
+ item.data('notebook_id', notebook_id);
+ var new_item_name = $('<span/>').addClass('item_name');
+ new_item_name.append(
+ $('<a/>').
+ attr('href','/'+notebook_id).
+ attr('target','_blank').
+ text(nbname)
+ );
+ var e = item.find('.item_name');
+ if (e.length === 0) {
+ item.append(new_item_name);
+ } else {
+ e.replaceWith(new_item_name);
+ };
+ };
+
+
+ NotebookList.prototype.add_name_input = function (nbname, item) {
+ item.data('nbname', nbname);
+ var new_item_name = $('<span/>').addClass('item_name');
+ new_item_name.append(
+ $('<input/>').addClass('ui-widget ui-widget-content').
+ attr('value', nbname).
+ attr('size', '30').
+ attr('type', 'text')
+ );
+ var e = item.find('.item_name');
+ if (e.length === 0) {
+ item.append(new_item_name);
+ } else {
+ e.replaceWith(new_item_name);
+ };
+ };
+
+
+ NotebookList.prototype.add_notebook_data = function (data, item) {
+ item.data('nbdata',data);
+ };
+
+
+ NotebookList.prototype.add_delete_button = function (item) {
+ var new_buttons = $('<span/>').addClass('item_buttons');
+ var delete_button = $('<button>Delete</button>').button().
+ click(function (e) {
+ // $(this) is the button that was clicked.
+ var that = $(this);
+ // We use the nbname and notebook_id from the parent notebook_item element's
+ // data because the outer scopes values change as we iterate through the loop.
+ var parent_item = that.parents('div.notebook_item');
+ var nbname = parent_item.data('nbname');
+ var notebook_id = parent_item.data('notebook_id');
+ var dialog = $('<div/>');
+ dialog.html('Are you sure you want to permanently delete the notebook: ' + nbname + '?');
+ parent_item.append(dialog);
+ dialog.dialog({
+ resizable: false,
+ modal: true,
+ title: "Delete notebook",
+ buttons : {
+ "Delete": function () {
+ var settings = {
+ processData : false,
+ cache : false,
+ type : "DELETE",
+ dataType : "json",
+ success : function (data, status, xhr) {
+ parent_item.remove();
+ }
+ };
+ $.ajax("/notebooks/" + notebook_id, settings);
+ $(this).dialog('close');
+ },
+ "Cancel": function () {
+ $(this).dialog('close');
+ }
+ }
+ });
+ });
+ new_buttons.append(delete_button);
+ var e = item.find('.item_buttons');
+ if (e.length === 0) {
+ item.append(new_buttons);
+ } else {
+ e.replaceWith(new_buttons);
+ };
+ };
+
+
+ NotebookList.prototype.add_upload_button = function (item) {
+ var that = this;
+ var new_buttons = $('<span/>').addClass('item_buttons');
+ var upload_button = $('<button>Upload</button>').button().
+ click(function (e) {
+ var nbname = item.find('.item_name > input').attr('value');
+ var nbformat = item.data('nbformat');
+ var nbdata = item.data('nbdata');
+ var settings = {
+ processData : false,
+ cache : false,
+ type : "POST",
+ dataType : "json",
+ data : nbdata,
+ success : function (data, status, xhr) {
+ that.add_link(data, nbname, item);
+ that.add_delete_button(item);
+ }
+ };
+
+ var qs = $.param({name:nbname, format:nbformat});
+ $.ajax("/notebooks?" + qs, settings);
+ });
+ var cancel_button = $('<button>Cancel</button>').button().
+ click(function (e) {
+ item.remove();
+ });
+ upload_button.addClass('upload_button');
+ new_buttons.append(upload_button).append(cancel_button);
+ var e = item.find('.item_buttons');
+ if (e.length === 0) {
+ item.append(new_buttons);
+ } else {
+ e.replaceWith(new_buttons);
+ };
};
9 IPython/frontend/html/notebook/templates/nbbrowser.html
View
@@ -29,11 +29,12 @@
<div id="app_hbox">
-<!-- <div id="left_panel">-->
-<!-- </div>-->
+ <div id="left_panel">
+ </div>
<div id="content_panel">
<div id="content_toolbar">
+ <span id="drag_info">Drag files onto the list to import notebooks.</span>
<span id="notebooks_buttons">
<button id="new_notebook">New Notebook</button>
</span>
@@ -44,8 +45,8 @@
</div>
-<!-- <div id="right_panel">-->
-<!-- </div>-->
+ <div id="right_panel">
+ </div>
</div>
Please sign in to comment.
Something went wrong with that request. Please try again.