##// END OF EJS Templates
Add directory browsing to the dashboard.
Brian E. Granger -
Show More
@@ -1,404 +1,436 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // NotebookList
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13 "use strict";
14 14
15 15 var utils = IPython.utils;
16 16
17 17 var NotebookList = function (selector) {
18 18 this.selector = selector;
19 19 if (this.selector !== undefined) {
20 20 this.element = $(selector);
21 21 this.style();
22 22 this.bind_events();
23 23 }
24 24 this.notebooks_list = [];
25 25 this.sessions = {};
26 26 };
27 27
28 28 NotebookList.prototype.baseProjectUrl = function () {
29 29 return $('body').data('baseProjectUrl');
30 30 };
31 31
32 32 NotebookList.prototype.notebookPath = function() {
33 33 return $('body').data('notebookPath');
34 34 };
35 35
36 36 NotebookList.prototype.style = function () {
37 37 $('#notebook_toolbar').addClass('list_toolbar');
38 38 $('#drag_info').addClass('toolbar_info');
39 39 $('#notebook_buttons').addClass('toolbar_buttons');
40 40 $('#notebook_list_header').addClass('list_header');
41 41 this.element.addClass("list_container");
42 42 };
43 43
44 44
45 45 NotebookList.prototype.bind_events = function () {
46 46 var that = this;
47 47 $('#refresh_notebook_list').click(function () {
48 48 that.load_list();
49 49 });
50 50 this.element.bind('dragover', function () {
51 51 return false;
52 52 });
53 53 this.element.bind('drop', function(event){
54 54 that.handelFilesUpload(event,'drop');
55 55 return false;
56 56 });
57 57 };
58 58
59 59 NotebookList.prototype.handelFilesUpload = function(event, dropOrForm) {
60 60 var that = this;
61 61 var files;
62 62 if(dropOrForm =='drop'){
63 63 files = event.originalEvent.dataTransfer.files;
64 64 } else
65 65 {
66 66 files = event.originalEvent.target.files;
67 67 }
68 68 for (var i = 0; i < files.length; i++) {
69 69 var f = files[i];
70 70 var reader = new FileReader();
71 71 reader.readAsText(f);
72 72 var name_and_ext = utils.splitext(f.name);
73 73 var nbname = name_and_ext[0];
74 74 var file_ext = name_and_ext[1];
75 75 if (file_ext === '.ipynb') {
76 76 var item = that.new_notebook_item(0);
77 77 that.add_name_input(nbname, item);
78 78 // Store the notebook item in the reader so we can use it later
79 79 // to know which item it belongs to.
80 80 $(reader).data('item', item);
81 81 reader.onload = function (event) {
82 82 var nbitem = $(event.target).data('item');
83 83 that.add_notebook_data(event.target.result, nbitem);
84 84 that.add_upload_button(nbitem);
85 85 };
86 86 } else {
87 87 var dialog = 'Uploaded notebooks must be .ipynb files';
88 88 IPython.dialog.modal({
89 89 title : 'Invalid file type',
90 90 body : dialog,
91 91 buttons : {'OK' : {'class' : 'btn-primary'}}
92 92 });
93 93 }
94 94 }
95 95 // Replace the file input form wth a clone of itself. This is required to
96 96 // reset the form. Otherwise, if you upload a file, delete it and try to
97 97 // upload it again, the changed event won't fire.
98 98 var form = $('input.fileinput');
99 99 form.replaceWith(form.clone(true));
100 100 return false;
101 101 };
102 102
103 103 NotebookList.prototype.clear_list = function () {
104 104 this.element.children('.list_item').remove();
105 105 };
106 106
107 107 NotebookList.prototype.load_sessions = function(){
108 108 var that = this;
109 109 var settings = {
110 110 processData : false,
111 111 cache : false,
112 112 type : "GET",
113 113 dataType : "json",
114 114 success : $.proxy(that.sessions_loaded, this)
115 115 };
116 116 var url = this.baseProjectUrl() + 'api/sessions';
117 117 $.ajax(url,settings);
118 118 };
119 119
120 120
121 121 NotebookList.prototype.sessions_loaded = function(data){
122 122 this.sessions = {};
123 123 var len = data.length;
124 124 if (len > 0) {
125 125 for (var i=0; i<len; i++) {
126 126 var nb_path;
127 127 if (!data[i].notebook.path) {
128 128 nb_path = data[i].notebook.name;
129 129 }
130 130 else {
131 131 nb_path = utils.url_path_join(
132 132 data[i].notebook.path,
133 133 data[i].notebook.name
134 134 );
135 135 }
136 136 this.sessions[nb_path] = data[i].id;
137 137 }
138 138 }
139 139 this.load_list();
140 140 };
141 141
142 142 NotebookList.prototype.load_list = function () {
143 143 var that = this;
144 144 var settings = {
145 145 processData : false,
146 146 cache : false,
147 147 type : "GET",
148 148 dataType : "json",
149 149 success : $.proxy(this.list_loaded, this),
150 150 error : $.proxy( function(){
151 151 that.list_loaded([], null, null, {msg:"Error connecting to server."});
152 152 },this)
153 153 };
154 154
155 155 var url = utils.url_join_encode(
156 156 this.baseProjectUrl(),
157 157 'api',
158 158 'notebooks',
159 159 this.notebookPath()
160 160 );
161 161 $.ajax(url, settings);
162 162 };
163 163
164 164
165 165 NotebookList.prototype.list_loaded = function (data, status, xhr, param) {
166 166 var message = 'Notebook list empty.';
167 167 if (param !== undefined && param.msg) {
168 168 message = param.msg;
169 169 }
170 console.log(data);
171 170 var len = data.length;
172 171 this.clear_list();
173 172 if (len === 0) {
174 173 $(this.new_notebook_item(0))
175 174 .append(
176 175 $('<div style="margin:auto;text-align:center;color:grey"/>')
177 176 .text(message)
178 177 );
179 178 }
179 var path = this.notebookPath();
180 var offset = 0;
181 if (path !== '') {
182 var item = this.new_notebook_item(0);
183 this.add_dir(path, '..', item);
184 offset = 1;
185 }
180 186 for (var i=0; i<len; i++) {
181 var name = data[i].name;
182 var path = this.notebookPath();
183 var nbname = utils.splitext(name)[0];
184 var item = this.new_notebook_item(i);
185 this.add_link(path, nbname, item);
186 name = utils.url_path_join(path, name);
187 if(this.sessions[name] === undefined){
188 this.add_delete_button(item);
187 if (data[i].type === 'directory') {
188 var name = data[i].name;
189 var item = this.new_notebook_item(i+offset);
190 this.add_dir(path, name, item);
189 191 } else {
190 this.add_shutdown_button(item,this.sessions[name]);
192 var name = data[i].name;
193 var nbname = utils.splitext(name)[0];
194 var item = this.new_notebook_item(i+offset);
195 this.add_link(path, nbname, item);
196 name = utils.url_path_join(path, name);
197 if(this.sessions[name] === undefined){
198 this.add_delete_button(item);
199 } else {
200 this.add_shutdown_button(item,this.sessions[name]);
201 }
191 202 }
192 203 }
193 204 };
194 205
195 206
196 207 NotebookList.prototype.new_notebook_item = function (index) {
197 208 var item = $('<div/>').addClass("list_item").addClass("row-fluid");
198 209 // item.addClass('list_item ui-widget ui-widget-content ui-helper-clearfix');
199 210 // item.css('border-top-style','none');
200 211 item.append($("<div/>").addClass("span12").append(
212 $('<i/>').addClass('item_icon')
213 ).append(
201 214 $("<a/>").addClass("item_link").append(
202 215 $("<span/>").addClass("item_name")
203 216 )
204 217 ).append(
205 218 $('<div/>').addClass("item_buttons btn-group pull-right")
206 219 ));
207 220
208 221 if (index === -1) {
209 222 this.element.append(item);
210 223 } else {
211 224 this.element.children().eq(index).after(item);
212 225 }
213 226 return item;
214 227 };
215 228
216 229
230 NotebookList.prototype.add_dir = function (path, name, item) {
231 item.data('name', name);
232 item.data('path', path);
233 item.find(".item_name").text(name);
234 item.find(".item_icon").addClass('icon-folder-open');
235 item.find("a.item_link")
236 .attr('href',
237 utils.url_join_encode(
238 this.baseProjectUrl(),
239 "tree",
240 path,
241 name
242 )
243 );
244 };
245
246
217 247 NotebookList.prototype.add_link = function (path, nbname, item) {
218 248 item.data('nbname', nbname);
219 249 item.data('path', path);
220 item.find(".item_name").text(nbname);
250 item.find(".item_name").text(nbname + '.ipynb');
251 item.find(".item_icon").addClass('icon-book');
221 252 item.find("a.item_link")
222 253 .attr('href',
223 254 utils.url_join_encode(
224 255 this.baseProjectUrl(),
225 256 "notebooks",
226 257 path,
227 258 nbname + ".ipynb"
228 259 )
229 260 ).attr('target','_blank');
230 261 };
231 262
232 263
233 264 NotebookList.prototype.add_name_input = function (nbname, item) {
234 265 item.data('nbname', nbname);
266 item.find(".item_icon").addClass('icon-book');
235 267 item.find(".item_name").empty().append(
236 268 $('<input/>')
237 269 .addClass("nbname_input")
238 270 .attr('value', nbname)
239 271 .attr('size', '30')
240 272 .attr('type', 'text')
241 273 );
242 274 };
243 275
244 276
245 277 NotebookList.prototype.add_notebook_data = function (data, item) {
246 278 item.data('nbdata', data);
247 279 };
248 280
249 281
250 282 NotebookList.prototype.add_shutdown_button = function (item, session) {
251 283 var that = this;
252 284 var shutdown_button = $("<button/>").text("Shutdown").addClass("btn btn-mini").
253 285 click(function (e) {
254 286 var settings = {
255 287 processData : false,
256 288 cache : false,
257 289 type : "DELETE",
258 290 dataType : "json",
259 291 success : function () {
260 292 that.load_sessions();
261 293 }
262 294 };
263 295 var url = utils.url_join_encode(
264 296 that.baseProjectUrl(),
265 297 'api/sessions',
266 298 session
267 299 );
268 300 $.ajax(url, settings);
269 301 return false;
270 302 });
271 303 // var new_buttons = item.find('a'); // shutdown_button;
272 304 item.find(".item_buttons").text("").append(shutdown_button);
273 305 };
274 306
275 307 NotebookList.prototype.add_delete_button = function (item) {
276 308 var new_buttons = $('<span/>').addClass("btn-group pull-right");
277 309 var notebooklist = this;
278 310 var delete_button = $("<button/>").text("Delete").addClass("btn btn-mini").
279 311 click(function (e) {
280 312 // $(this) is the button that was clicked.
281 313 var that = $(this);
282 314 // We use the nbname and notebook_id from the parent notebook_item element's
283 315 // data because the outer scopes values change as we iterate through the loop.
284 316 var parent_item = that.parents('div.list_item');
285 317 var nbname = parent_item.data('nbname');
286 318 var message = 'Are you sure you want to permanently delete the notebook: ' + nbname + '?';
287 319 IPython.dialog.modal({
288 320 title : "Delete notebook",
289 321 body : message,
290 322 buttons : {
291 323 Delete : {
292 324 class: "btn-danger",
293 325 click: function() {
294 326 var settings = {
295 327 processData : false,
296 328 cache : false,
297 329 type : "DELETE",
298 330 dataType : "json",
299 331 success : function (data, status, xhr) {
300 332 parent_item.remove();
301 333 }
302 334 };
303 335 var url = utils.url_join_encode(
304 336 notebooklist.baseProjectUrl(),
305 337 'api/notebooks',
306 338 notebooklist.notebookPath(),
307 339 nbname + '.ipynb'
308 340 );
309 341 $.ajax(url, settings);
310 342 }
311 343 },
312 344 Cancel : {}
313 345 }
314 346 });
315 347 return false;
316 348 });
317 349 item.find(".item_buttons").text("").append(delete_button);
318 350 };
319 351
320 352
321 353 NotebookList.prototype.add_upload_button = function (item) {
322 354 var that = this;
323 355 var upload_button = $('<button/>').text("Upload")
324 356 .addClass('btn btn-primary btn-mini upload_button')
325 357 .click(function (e) {
326 358 var nbname = item.find('.item_name > input').val();
327 359 var path = that.notebookPath();
328 360 var nbdata = item.data('nbdata');
329 361 var content_type = 'application/json';
330 362 var model = {
331 363 content : JSON.parse(nbdata),
332 364 };
333 365 var settings = {
334 366 processData : false,
335 367 cache : false,
336 368 type : 'PUT',
337 369 dataType : 'json',
338 370 data : JSON.stringify(model),
339 371 headers : {'Content-Type': content_type},
340 372 success : function (data, status, xhr) {
341 373 that.add_link(path, nbname, item);
342 374 that.add_delete_button(item);
343 375 },
344 376 error : function (data, status, xhr) {
345 377 console.log(data, status);
346 378 }
347 379 };
348 380
349 381 var url = utils.url_join_encode(
350 382 that.baseProjectUrl(),
351 383 'api/notebooks',
352 384 that.notebookPath(),
353 385 nbname + '.ipynb'
354 386 );
355 387 $.ajax(url, settings);
356 388 return false;
357 389 });
358 390 var cancel_button = $('<button/>').text("Cancel")
359 391 .addClass("btn btn-mini")
360 392 .click(function (e) {
361 393 console.log('cancel click');
362 394 item.remove();
363 395 return false;
364 396 });
365 397 item.find(".item_buttons").empty()
366 398 .append(upload_button)
367 399 .append(cancel_button);
368 400 };
369 401
370 402
371 403 NotebookList.prototype.new_notebook = function(){
372 404 var path = this.notebookPath();
373 405 var base_project_url = this.baseProjectUrl();
374 406 var settings = {
375 407 processData : false,
376 408 cache : false,
377 409 type : "POST",
378 410 dataType : "json",
379 411 async : false,
380 412 success : function (data, status, xhr) {
381 413 var notebook_name = data.name;
382 414 window.open(
383 415 utils.url_join_encode(
384 416 base_project_url,
385 417 'notebooks',
386 418 path,
387 419 notebook_name),
388 420 '_blank'
389 421 );
390 422 }
391 423 };
392 424 var url = utils.url_join_encode(
393 425 base_project_url,
394 426 'api/notebooks',
395 427 path
396 428 );
397 429 $.ajax(url, settings);
398 430 };
399 431
400 432 IPython.NotebookList = NotebookList;
401 433
402 434 return IPython;
403 435
404 436 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now