##// END OF EJS Templates
link to /edit/ on files
Min RK -
Show More
@@ -1,508 +1,508 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 define([
4 define([
5 'base/js/namespace',
5 'base/js/namespace',
6 'jquery',
6 'jquery',
7 'base/js/utils',
7 'base/js/utils',
8 'base/js/dialog',
8 'base/js/dialog',
9 'base/js/events',
9 'base/js/events',
10 ], function(IPython, $, utils, dialog, events) {
10 ], function(IPython, $, utils, dialog, events) {
11 "use strict";
11 "use strict";
12
12
13 var NotebookList = function (selector, options) {
13 var NotebookList = function (selector, options) {
14 /**
14 /**
15 * Constructor
15 * Constructor
16 *
16 *
17 * Parameters:
17 * Parameters:
18 * selector: string
18 * selector: string
19 * options: dictionary
19 * options: dictionary
20 * Dictionary of keyword arguments.
20 * Dictionary of keyword arguments.
21 * session_list: SessionList instance
21 * session_list: SessionList instance
22 * element_name: string
22 * element_name: string
23 * base_url: string
23 * base_url: string
24 * notebook_path: string
24 * notebook_path: string
25 * contents: Contents instance
25 * contents: Contents instance
26 */
26 */
27 var that = this;
27 var that = this;
28 this.session_list = options.session_list;
28 this.session_list = options.session_list;
29 // allow code re-use by just changing element_name in kernellist.js
29 // allow code re-use by just changing element_name in kernellist.js
30 this.element_name = options.element_name || 'notebook';
30 this.element_name = options.element_name || 'notebook';
31 this.selector = selector;
31 this.selector = selector;
32 if (this.selector !== undefined) {
32 if (this.selector !== undefined) {
33 this.element = $(selector);
33 this.element = $(selector);
34 this.style();
34 this.style();
35 this.bind_events();
35 this.bind_events();
36 }
36 }
37 this.notebooks_list = [];
37 this.notebooks_list = [];
38 this.sessions = {};
38 this.sessions = {};
39 this.base_url = options.base_url || utils.get_body_data("baseUrl");
39 this.base_url = options.base_url || utils.get_body_data("baseUrl");
40 this.notebook_path = options.notebook_path || utils.get_body_data("notebookPath");
40 this.notebook_path = options.notebook_path || utils.get_body_data("notebookPath");
41 this.contents = options.contents;
41 this.contents = options.contents;
42 if (this.session_list && this.session_list.events) {
42 if (this.session_list && this.session_list.events) {
43 this.session_list.events.on('sessions_loaded.Dashboard',
43 this.session_list.events.on('sessions_loaded.Dashboard',
44 function(e, d) { that.sessions_loaded(d); });
44 function(e, d) { that.sessions_loaded(d); });
45 }
45 }
46 };
46 };
47
47
48 NotebookList.prototype.style = function () {
48 NotebookList.prototype.style = function () {
49 var prefix = '#' + this.element_name;
49 var prefix = '#' + this.element_name;
50 $(prefix + '_toolbar').addClass('list_toolbar');
50 $(prefix + '_toolbar').addClass('list_toolbar');
51 $(prefix + '_list_info').addClass('toolbar_info');
51 $(prefix + '_list_info').addClass('toolbar_info');
52 $(prefix + '_buttons').addClass('toolbar_buttons');
52 $(prefix + '_buttons').addClass('toolbar_buttons');
53 $(prefix + '_list_header').addClass('list_header');
53 $(prefix + '_list_header').addClass('list_header');
54 this.element.addClass("list_container");
54 this.element.addClass("list_container");
55 };
55 };
56
56
57
57
58 NotebookList.prototype.bind_events = function () {
58 NotebookList.prototype.bind_events = function () {
59 var that = this;
59 var that = this;
60 $('#refresh_' + this.element_name + '_list').click(function () {
60 $('#refresh_' + this.element_name + '_list').click(function () {
61 that.load_sessions();
61 that.load_sessions();
62 });
62 });
63 this.element.bind('dragover', function () {
63 this.element.bind('dragover', function () {
64 return false;
64 return false;
65 });
65 });
66 this.element.bind('drop', function(event){
66 this.element.bind('drop', function(event){
67 that.handleFilesUpload(event,'drop');
67 that.handleFilesUpload(event,'drop');
68 return false;
68 return false;
69 });
69 });
70 };
70 };
71
71
72 NotebookList.prototype.handleFilesUpload = function(event, dropOrForm) {
72 NotebookList.prototype.handleFilesUpload = function(event, dropOrForm) {
73 var that = this;
73 var that = this;
74 var files;
74 var files;
75 if(dropOrForm =='drop'){
75 if(dropOrForm =='drop'){
76 files = event.originalEvent.dataTransfer.files;
76 files = event.originalEvent.dataTransfer.files;
77 } else
77 } else
78 {
78 {
79 files = event.originalEvent.target.files;
79 files = event.originalEvent.target.files;
80 }
80 }
81 for (var i = 0; i < files.length; i++) {
81 for (var i = 0; i < files.length; i++) {
82 var f = files[i];
82 var f = files[i];
83 var name_and_ext = utils.splitext(f.name);
83 var name_and_ext = utils.splitext(f.name);
84 var file_ext = name_and_ext[1];
84 var file_ext = name_and_ext[1];
85
85
86 var reader = new FileReader();
86 var reader = new FileReader();
87 if (file_ext === '.ipynb') {
87 if (file_ext === '.ipynb') {
88 reader.readAsText(f);
88 reader.readAsText(f);
89 } else {
89 } else {
90 // read non-notebook files as binary
90 // read non-notebook files as binary
91 reader.readAsArrayBuffer(f);
91 reader.readAsArrayBuffer(f);
92 }
92 }
93 var item = that.new_item(0);
93 var item = that.new_item(0);
94 item.addClass('new-file');
94 item.addClass('new-file');
95 that.add_name_input(f.name, item, file_ext == '.ipynb' ? 'notebook' : 'file');
95 that.add_name_input(f.name, item, file_ext == '.ipynb' ? 'notebook' : 'file');
96 // Store the list item in the reader so we can use it later
96 // Store the list item in the reader so we can use it later
97 // to know which item it belongs to.
97 // to know which item it belongs to.
98 $(reader).data('item', item);
98 $(reader).data('item', item);
99 reader.onload = function (event) {
99 reader.onload = function (event) {
100 var item = $(event.target).data('item');
100 var item = $(event.target).data('item');
101 that.add_file_data(event.target.result, item);
101 that.add_file_data(event.target.result, item);
102 that.add_upload_button(item);
102 that.add_upload_button(item);
103 };
103 };
104 reader.onerror = function (event) {
104 reader.onerror = function (event) {
105 var item = $(event.target).data('item');
105 var item = $(event.target).data('item');
106 var name = item.data('name');
106 var name = item.data('name');
107 item.remove();
107 item.remove();
108 dialog.modal({
108 dialog.modal({
109 title : 'Failed to read file',
109 title : 'Failed to read file',
110 body : "Failed to read file '" + name + "'",
110 body : "Failed to read file '" + name + "'",
111 buttons : {'OK' : { 'class' : 'btn-primary' }}
111 buttons : {'OK' : { 'class' : 'btn-primary' }}
112 });
112 });
113 };
113 };
114 }
114 }
115 // Replace the file input form wth a clone of itself. This is required to
115 // Replace the file input form wth a clone of itself. This is required to
116 // reset the form. Otherwise, if you upload a file, delete it and try to
116 // reset the form. Otherwise, if you upload a file, delete it and try to
117 // upload it again, the changed event won't fire.
117 // upload it again, the changed event won't fire.
118 var form = $('input.fileinput');
118 var form = $('input.fileinput');
119 form.replaceWith(form.clone(true));
119 form.replaceWith(form.clone(true));
120 return false;
120 return false;
121 };
121 };
122
122
123 NotebookList.prototype.clear_list = function (remove_uploads) {
123 NotebookList.prototype.clear_list = function (remove_uploads) {
124 /**
124 /**
125 * Clears the navigation tree.
125 * Clears the navigation tree.
126 *
126 *
127 * Parameters
127 * Parameters
128 * remove_uploads: bool=False
128 * remove_uploads: bool=False
129 * Should upload prompts also be removed from the tree.
129 * Should upload prompts also be removed from the tree.
130 */
130 */
131 if (remove_uploads) {
131 if (remove_uploads) {
132 this.element.children('.list_item').remove();
132 this.element.children('.list_item').remove();
133 } else {
133 } else {
134 this.element.children('.list_item:not(.new-file)').remove();
134 this.element.children('.list_item:not(.new-file)').remove();
135 }
135 }
136 };
136 };
137
137
138 NotebookList.prototype.load_sessions = function(){
138 NotebookList.prototype.load_sessions = function(){
139 this.session_list.load_sessions();
139 this.session_list.load_sessions();
140 };
140 };
141
141
142
142
143 NotebookList.prototype.sessions_loaded = function(data){
143 NotebookList.prototype.sessions_loaded = function(data){
144 this.sessions = data;
144 this.sessions = data;
145 this.load_list();
145 this.load_list();
146 };
146 };
147
147
148 NotebookList.prototype.load_list = function () {
148 NotebookList.prototype.load_list = function () {
149 var that = this;
149 var that = this;
150 this.contents.list_contents(that.notebook_path).then(
150 this.contents.list_contents(that.notebook_path).then(
151 $.proxy(this.draw_notebook_list, this),
151 $.proxy(this.draw_notebook_list, this),
152 function(error) {
152 function(error) {
153 that.draw_notebook_list({content: []}, "Server error: " + error.message);
153 that.draw_notebook_list({content: []}, "Server error: " + error.message);
154 }
154 }
155 );
155 );
156 };
156 };
157
157
158 /**
158 /**
159 * Draw the list of notebooks
159 * Draw the list of notebooks
160 * @method draw_notebook_list
160 * @method draw_notebook_list
161 * @param {Array} list An array of dictionaries representing files or
161 * @param {Array} list An array of dictionaries representing files or
162 * directories.
162 * directories.
163 * @param {String} error_msg An error message
163 * @param {String} error_msg An error message
164 */
164 */
165 NotebookList.prototype.draw_notebook_list = function (list, error_msg) {
165 NotebookList.prototype.draw_notebook_list = function (list, error_msg) {
166 var message = error_msg || 'Notebook list empty.';
166 var message = error_msg || 'Notebook list empty.';
167 var item = null;
167 var item = null;
168 var model = null;
168 var model = null;
169 var len = list.content.length;
169 var len = list.content.length;
170 this.clear_list();
170 this.clear_list();
171 var n_uploads = this.element.children('.list_item').length;
171 var n_uploads = this.element.children('.list_item').length;
172 if (len === 0) {
172 if (len === 0) {
173 item = this.new_item(0);
173 item = this.new_item(0);
174 var span12 = item.children().first();
174 var span12 = item.children().first();
175 span12.empty();
175 span12.empty();
176 span12.append($('<div style="margin:auto;text-align:center;color:grey"/>').text(message));
176 span12.append($('<div style="margin:auto;text-align:center;color:grey"/>').text(message));
177 }
177 }
178 var path = this.notebook_path;
178 var path = this.notebook_path;
179 var offset = n_uploads;
179 var offset = n_uploads;
180 if (path !== '') {
180 if (path !== '') {
181 item = this.new_item(offset);
181 item = this.new_item(offset);
182 model = {
182 model = {
183 type: 'directory',
183 type: 'directory',
184 name: '..',
184 name: '..',
185 path: utils.url_path_split(path)[0],
185 path: utils.url_path_split(path)[0],
186 };
186 };
187 this.add_link(model, item);
187 this.add_link(model, item);
188 offset += 1;
188 offset += 1;
189 }
189 }
190 for (var i=0; i<len; i++) {
190 for (var i=0; i<len; i++) {
191 model = list.content[i];
191 model = list.content[i];
192 item = this.new_item(i+offset);
192 item = this.new_item(i+offset);
193 this.add_link(model, item);
193 this.add_link(model, item);
194 }
194 }
195 // Trigger an event when we've finished drawing the notebook list.
195 // Trigger an event when we've finished drawing the notebook list.
196 events.trigger('draw_notebook_list.NotebookList');
196 events.trigger('draw_notebook_list.NotebookList');
197 };
197 };
198
198
199
199
200 NotebookList.prototype.new_item = function (index) {
200 NotebookList.prototype.new_item = function (index) {
201 var item = $('<div/>').addClass("list_item").addClass("row");
201 var item = $('<div/>').addClass("list_item").addClass("row");
202 // item.addClass('list_item ui-widget ui-widget-content ui-helper-clearfix');
202 // item.addClass('list_item ui-widget ui-widget-content ui-helper-clearfix');
203 // item.css('border-top-style','none');
203 // item.css('border-top-style','none');
204 item.append($("<div/>").addClass("col-md-12").append(
204 item.append($("<div/>").addClass("col-md-12").append(
205 $('<i/>').addClass('item_icon')
205 $('<i/>').addClass('item_icon')
206 ).append(
206 ).append(
207 $("<a/>").addClass("item_link").append(
207 $("<a/>").addClass("item_link").append(
208 $("<span/>").addClass("item_name")
208 $("<span/>").addClass("item_name")
209 )
209 )
210 ).append(
210 ).append(
211 $('<div/>').addClass("item_buttons btn-group pull-right")
211 $('<div/>').addClass("item_buttons btn-group pull-right")
212 ));
212 ));
213
213
214 if (index === -1) {
214 if (index === -1) {
215 this.element.append(item);
215 this.element.append(item);
216 } else {
216 } else {
217 this.element.children().eq(index).after(item);
217 this.element.children().eq(index).after(item);
218 }
218 }
219 return item;
219 return item;
220 };
220 };
221
221
222
222
223 NotebookList.icons = {
223 NotebookList.icons = {
224 directory: 'folder_icon',
224 directory: 'folder_icon',
225 notebook: 'notebook_icon',
225 notebook: 'notebook_icon',
226 file: 'file_icon',
226 file: 'file_icon',
227 };
227 };
228
228
229 NotebookList.uri_prefixes = {
229 NotebookList.uri_prefixes = {
230 directory: 'tree',
230 directory: 'tree',
231 notebook: 'notebooks',
231 notebook: 'notebooks',
232 file: 'files',
232 file: 'edit',
233 };
233 };
234
234
235
235
236 NotebookList.prototype.add_link = function (model, item) {
236 NotebookList.prototype.add_link = function (model, item) {
237 var path = model.path,
237 var path = model.path,
238 name = model.name;
238 name = model.name;
239 item.data('name', name);
239 item.data('name', name);
240 item.data('path', path);
240 item.data('path', path);
241 item.find(".item_name").text(name);
241 item.find(".item_name").text(name);
242 var icon = NotebookList.icons[model.type];
242 var icon = NotebookList.icons[model.type];
243 var uri_prefix = NotebookList.uri_prefixes[model.type];
243 var uri_prefix = NotebookList.uri_prefixes[model.type];
244 item.find(".item_icon").addClass(icon).addClass('icon-fixed-width');
244 item.find(".item_icon").addClass(icon).addClass('icon-fixed-width');
245 var link = item.find("a.item_link")
245 var link = item.find("a.item_link")
246 .attr('href',
246 .attr('href',
247 utils.url_join_encode(
247 utils.url_join_encode(
248 this.base_url,
248 this.base_url,
249 uri_prefix,
249 uri_prefix,
250 path
250 path
251 )
251 )
252 );
252 );
253 // directory nav doesn't open new tabs
253 // directory nav doesn't open new tabs
254 // files, notebooks do
254 // files, notebooks do
255 if (model.type !== "directory") {
255 if (model.type !== "directory") {
256 link.attr('target','_blank');
256 link.attr('target','_blank');
257 }
257 }
258 if (model.type !== 'directory') {
258 if (model.type !== 'directory') {
259 this.add_duplicate_button(item);
259 this.add_duplicate_button(item);
260 }
260 }
261 if (model.type == 'file') {
261 if (model.type == 'file') {
262 this.add_delete_button(item);
262 this.add_delete_button(item);
263 } else if (model.type == 'notebook') {
263 } else if (model.type == 'notebook') {
264 if (this.sessions[path] === undefined){
264 if (this.sessions[path] === undefined){
265 this.add_delete_button(item);
265 this.add_delete_button(item);
266 } else {
266 } else {
267 this.add_shutdown_button(item, this.sessions[path]);
267 this.add_shutdown_button(item, this.sessions[path]);
268 }
268 }
269 }
269 }
270 };
270 };
271
271
272
272
273 NotebookList.prototype.add_name_input = function (name, item, icon_type) {
273 NotebookList.prototype.add_name_input = function (name, item, icon_type) {
274 item.data('name', name);
274 item.data('name', name);
275 item.find(".item_icon").addClass(NotebookList.icons[icon_type]).addClass('icon-fixed-width');
275 item.find(".item_icon").addClass(NotebookList.icons[icon_type]).addClass('icon-fixed-width');
276 item.find(".item_name").empty().append(
276 item.find(".item_name").empty().append(
277 $('<input/>')
277 $('<input/>')
278 .addClass("filename_input")
278 .addClass("filename_input")
279 .attr('value', name)
279 .attr('value', name)
280 .attr('size', '30')
280 .attr('size', '30')
281 .attr('type', 'text')
281 .attr('type', 'text')
282 .keyup(function(event){
282 .keyup(function(event){
283 if(event.keyCode == 13){item.find('.upload_button').click();}
283 if(event.keyCode == 13){item.find('.upload_button').click();}
284 else if(event.keyCode == 27){item.remove();}
284 else if(event.keyCode == 27){item.remove();}
285 })
285 })
286 );
286 );
287 };
287 };
288
288
289
289
290 NotebookList.prototype.add_file_data = function (data, item) {
290 NotebookList.prototype.add_file_data = function (data, item) {
291 item.data('filedata', data);
291 item.data('filedata', data);
292 };
292 };
293
293
294
294
295 NotebookList.prototype.add_shutdown_button = function (item, session) {
295 NotebookList.prototype.add_shutdown_button = function (item, session) {
296 var that = this;
296 var that = this;
297 var shutdown_button = $("<button/>").text("Shutdown").addClass("btn btn-xs btn-danger").
297 var shutdown_button = $("<button/>").text("Shutdown").addClass("btn btn-xs btn-danger").
298 click(function (e) {
298 click(function (e) {
299 var settings = {
299 var settings = {
300 processData : false,
300 processData : false,
301 cache : false,
301 cache : false,
302 type : "DELETE",
302 type : "DELETE",
303 dataType : "json",
303 dataType : "json",
304 success : function () {
304 success : function () {
305 that.load_sessions();
305 that.load_sessions();
306 },
306 },
307 error : utils.log_ajax_error,
307 error : utils.log_ajax_error,
308 };
308 };
309 var url = utils.url_join_encode(
309 var url = utils.url_join_encode(
310 that.base_url,
310 that.base_url,
311 'api/sessions',
311 'api/sessions',
312 session
312 session
313 );
313 );
314 $.ajax(url, settings);
314 $.ajax(url, settings);
315 return false;
315 return false;
316 });
316 });
317 item.find(".item_buttons").append(shutdown_button);
317 item.find(".item_buttons").append(shutdown_button);
318 };
318 };
319
319
320 NotebookList.prototype.add_duplicate_button = function (item) {
320 NotebookList.prototype.add_duplicate_button = function (item) {
321 var notebooklist = this;
321 var notebooklist = this;
322 var duplicate_button = $("<button/>").text("Duplicate").addClass("btn btn-default btn-xs").
322 var duplicate_button = $("<button/>").text("Duplicate").addClass("btn btn-default btn-xs").
323 click(function (e) {
323 click(function (e) {
324 // $(this) is the button that was clicked.
324 // $(this) is the button that was clicked.
325 var that = $(this);
325 var that = $(this);
326 var name = item.data('name');
326 var name = item.data('name');
327 var path = item.data('path');
327 var path = item.data('path');
328 var message = 'Are you sure you want to duplicate ' + name + '?';
328 var message = 'Are you sure you want to duplicate ' + name + '?';
329 var copy_from = {copy_from : path};
329 var copy_from = {copy_from : path};
330 IPython.dialog.modal({
330 IPython.dialog.modal({
331 title : "Duplicate " + name,
331 title : "Duplicate " + name,
332 body : message,
332 body : message,
333 buttons : {
333 buttons : {
334 Duplicate : {
334 Duplicate : {
335 class: "btn-primary",
335 class: "btn-primary",
336 click: function() {
336 click: function() {
337 notebooklist.contents.copy(path, notebooklist.notebook_path).then(function () {
337 notebooklist.contents.copy(path, notebooklist.notebook_path).then(function () {
338 notebooklist.load_list();
338 notebooklist.load_list();
339 });
339 });
340 }
340 }
341 },
341 },
342 Cancel : {}
342 Cancel : {}
343 }
343 }
344 });
344 });
345 return false;
345 return false;
346 });
346 });
347 item.find(".item_buttons").append(duplicate_button);
347 item.find(".item_buttons").append(duplicate_button);
348 };
348 };
349
349
350 NotebookList.prototype.add_delete_button = function (item) {
350 NotebookList.prototype.add_delete_button = function (item) {
351 var notebooklist = this;
351 var notebooklist = this;
352 var delete_button = $("<button/>").text("Delete").addClass("btn btn-default btn-xs").
352 var delete_button = $("<button/>").text("Delete").addClass("btn btn-default btn-xs").
353 click(function (e) {
353 click(function (e) {
354 // $(this) is the button that was clicked.
354 // $(this) is the button that was clicked.
355 var that = $(this);
355 var that = $(this);
356 // We use the filename from the parent list_item element's
356 // We use the filename from the parent list_item element's
357 // data because the outer scope's values change as we iterate through the loop.
357 // data because the outer scope's values change as we iterate through the loop.
358 var parent_item = that.parents('div.list_item');
358 var parent_item = that.parents('div.list_item');
359 var name = parent_item.data('name');
359 var name = parent_item.data('name');
360 var path = parent_item.data('path');
360 var path = parent_item.data('path');
361 var message = 'Are you sure you want to permanently delete the file: ' + name + '?';
361 var message = 'Are you sure you want to permanently delete the file: ' + name + '?';
362 dialog.modal({
362 dialog.modal({
363 title : "Delete file",
363 title : "Delete file",
364 body : message,
364 body : message,
365 buttons : {
365 buttons : {
366 Delete : {
366 Delete : {
367 class: "btn-danger",
367 class: "btn-danger",
368 click: function() {
368 click: function() {
369 notebooklist.contents.delete(path).then(
369 notebooklist.contents.delete(path).then(
370 function() {
370 function() {
371 notebooklist.notebook_deleted(path);
371 notebooklist.notebook_deleted(path);
372 }
372 }
373 );
373 );
374 }
374 }
375 },
375 },
376 Cancel : {}
376 Cancel : {}
377 }
377 }
378 });
378 });
379 return false;
379 return false;
380 });
380 });
381 item.find(".item_buttons").append(delete_button);
381 item.find(".item_buttons").append(delete_button);
382 };
382 };
383
383
384 NotebookList.prototype.notebook_deleted = function(path) {
384 NotebookList.prototype.notebook_deleted = function(path) {
385 /**
385 /**
386 * Remove the deleted notebook.
386 * Remove the deleted notebook.
387 */
387 */
388 $( ":data(path)" ).each(function() {
388 $( ":data(path)" ).each(function() {
389 var element = $(this);
389 var element = $(this);
390 if (element.data("path") == path) {
390 if (element.data("path") == path) {
391 element.remove();
391 element.remove();
392 events.trigger('notebook_deleted.NotebookList');
392 events.trigger('notebook_deleted.NotebookList');
393 }
393 }
394 });
394 });
395 };
395 };
396
396
397
397
398 NotebookList.prototype.add_upload_button = function (item) {
398 NotebookList.prototype.add_upload_button = function (item) {
399 var that = this;
399 var that = this;
400 var upload_button = $('<button/>').text("Upload")
400 var upload_button = $('<button/>').text("Upload")
401 .addClass('btn btn-primary btn-xs upload_button')
401 .addClass('btn btn-primary btn-xs upload_button')
402 .click(function (e) {
402 .click(function (e) {
403 var filename = item.find('.item_name > input').val();
403 var filename = item.find('.item_name > input').val();
404 var path = utils.url_path_join(that.notebook_path, filename);
404 var path = utils.url_path_join(that.notebook_path, filename);
405 var filedata = item.data('filedata');
405 var filedata = item.data('filedata');
406 var format = 'text';
406 var format = 'text';
407 if (filename.length === 0 || filename[0] === '.') {
407 if (filename.length === 0 || filename[0] === '.') {
408 dialog.modal({
408 dialog.modal({
409 title : 'Invalid file name',
409 title : 'Invalid file name',
410 body : "File names must be at least one character and not start with a dot",
410 body : "File names must be at least one character and not start with a dot",
411 buttons : {'OK' : { 'class' : 'btn-primary' }}
411 buttons : {'OK' : { 'class' : 'btn-primary' }}
412 });
412 });
413 return false;
413 return false;
414 }
414 }
415 if (filedata instanceof ArrayBuffer) {
415 if (filedata instanceof ArrayBuffer) {
416 // base64-encode binary file data
416 // base64-encode binary file data
417 var bytes = '';
417 var bytes = '';
418 var buf = new Uint8Array(filedata);
418 var buf = new Uint8Array(filedata);
419 var nbytes = buf.byteLength;
419 var nbytes = buf.byteLength;
420 for (var i=0; i<nbytes; i++) {
420 for (var i=0; i<nbytes; i++) {
421 bytes += String.fromCharCode(buf[i]);
421 bytes += String.fromCharCode(buf[i]);
422 }
422 }
423 filedata = btoa(bytes);
423 filedata = btoa(bytes);
424 format = 'base64';
424 format = 'base64';
425 }
425 }
426 var model = {};
426 var model = {};
427
427
428 var name_and_ext = utils.splitext(filename);
428 var name_and_ext = utils.splitext(filename);
429 var file_ext = name_and_ext[1];
429 var file_ext = name_and_ext[1];
430 var content_type;
430 var content_type;
431 if (file_ext === '.ipynb') {
431 if (file_ext === '.ipynb') {
432 model.type = 'notebook';
432 model.type = 'notebook';
433 model.format = 'json';
433 model.format = 'json';
434 try {
434 try {
435 model.content = JSON.parse(filedata);
435 model.content = JSON.parse(filedata);
436 } catch (e) {
436 } catch (e) {
437 dialog.modal({
437 dialog.modal({
438 title : 'Cannot upload invalid Notebook',
438 title : 'Cannot upload invalid Notebook',
439 body : "The error was: " + e,
439 body : "The error was: " + e,
440 buttons : {'OK' : {
440 buttons : {'OK' : {
441 'class' : 'btn-primary',
441 'class' : 'btn-primary',
442 click: function () {
442 click: function () {
443 item.remove();
443 item.remove();
444 }
444 }
445 }}
445 }}
446 });
446 });
447 return false;
447 return false;
448 }
448 }
449 content_type = 'application/json';
449 content_type = 'application/json';
450 } else {
450 } else {
451 model.type = 'file';
451 model.type = 'file';
452 model.format = format;
452 model.format = format;
453 model.content = filedata;
453 model.content = filedata;
454 content_type = 'application/octet-stream';
454 content_type = 'application/octet-stream';
455 }
455 }
456 filedata = item.data('filedata');
456 filedata = item.data('filedata');
457
457
458 var on_success = function () {
458 var on_success = function () {
459 item.removeClass('new-file');
459 item.removeClass('new-file');
460 that.add_link(model, item);
460 that.add_link(model, item);
461 that.add_delete_button(item);
461 that.add_delete_button(item);
462 that.session_list.load_sessions();
462 that.session_list.load_sessions();
463 };
463 };
464
464
465 var exists = false;
465 var exists = false;
466 $.each(that.element.find('.list_item:not(.new-file)'), function(k,v){
466 $.each(that.element.find('.list_item:not(.new-file)'), function(k,v){
467 if ($(v).data('name') === filename) { exists = true; return false; }
467 if ($(v).data('name') === filename) { exists = true; return false; }
468 });
468 });
469
469
470 if (exists) {
470 if (exists) {
471 dialog.modal({
471 dialog.modal({
472 title : "Replace file",
472 title : "Replace file",
473 body : 'There is already a file named ' + filename + ', do you want to replace it?',
473 body : 'There is already a file named ' + filename + ', do you want to replace it?',
474 buttons : {
474 buttons : {
475 Overwrite : {
475 Overwrite : {
476 class: "btn-danger",
476 class: "btn-danger",
477 click: function () {
477 click: function () {
478 that.contents.save(path, model).then(on_success);
478 that.contents.save(path, model).then(on_success);
479 }
479 }
480 },
480 },
481 Cancel : {
481 Cancel : {
482 click: function() { item.remove(); }
482 click: function() { item.remove(); }
483 }
483 }
484 }
484 }
485 });
485 });
486 } else {
486 } else {
487 that.contents.save(path, model).then(on_success);
487 that.contents.save(path, model).then(on_success);
488 }
488 }
489
489
490 return false;
490 return false;
491 });
491 });
492 var cancel_button = $('<button/>').text("Cancel")
492 var cancel_button = $('<button/>').text("Cancel")
493 .addClass("btn btn-default btn-xs")
493 .addClass("btn btn-default btn-xs")
494 .click(function (e) {
494 .click(function (e) {
495 item.remove();
495 item.remove();
496 return false;
496 return false;
497 });
497 });
498 item.find(".item_buttons").empty()
498 item.find(".item_buttons").empty()
499 .append(upload_button)
499 .append(upload_button)
500 .append(cancel_button);
500 .append(cancel_button);
501 };
501 };
502
502
503
503
504 // Backwards compatability.
504 // Backwards compatability.
505 IPython.NotebookList = NotebookList;
505 IPython.NotebookList = NotebookList;
506
506
507 return {'NotebookList': NotebookList};
507 return {'NotebookList': NotebookList};
508 });
508 });
General Comments 0
You need to be logged in to leave comments. Login now