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