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