##// END OF EJS Templates
Report the exact error that occurred
Jessica B. Hamrick -
Show More
@@ -1,307 +1,319 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 'notebook/js/notificationwidget',
9 'notebook/js/notificationwidget',
10 'moment'
10 'moment'
11 ], function(IPython, $, utils, dialog, notificationwidget, moment) {
11 ], function(IPython, $, utils, dialog, notificationwidget, moment) {
12 "use strict";
12 "use strict";
13
13
14 // store reference to the NotificationWidget class
14 // store reference to the NotificationWidget class
15 var NotificationWidget = notificationwidget.NotificationWidget;
15 var NotificationWidget = notificationwidget.NotificationWidget;
16
16
17 /**
17 /**
18 * Construct the NotificationArea object. Options are:
18 * Construct the NotificationArea object. Options are:
19 * events: $(Events) instance
19 * events: $(Events) instance
20 * save_widget: SaveWidget instance
20 * save_widget: SaveWidget instance
21 * notebook: Notebook instance
21 * notebook: Notebook instance
22 * keyboard_manager: KeyboardManager instance
22 * keyboard_manager: KeyboardManager instance
23 *
23 *
24 * @constructor
24 * @constructor
25 * @param {string} selector - a jQuery selector string for the
25 * @param {string} selector - a jQuery selector string for the
26 * notification area element
26 * notification area element
27 * @param {Object} [options] - a dictionary of keyword arguments.
27 * @param {Object} [options] - a dictionary of keyword arguments.
28 */
28 */
29 var NotificationArea = function (selector, options) {
29 var NotificationArea = function (selector, options) {
30 this.selector = selector;
30 this.selector = selector;
31 this.events = options.events;
31 this.events = options.events;
32 this.save_widget = options.save_widget;
32 this.save_widget = options.save_widget;
33 this.notebook = options.notebook;
33 this.notebook = options.notebook;
34 this.keyboard_manager = options.keyboard_manager;
34 this.keyboard_manager = options.keyboard_manager;
35 if (this.selector !== undefined) {
35 if (this.selector !== undefined) {
36 this.element = $(selector);
36 this.element = $(selector);
37 }
37 }
38 this.widget_dict = {};
38 this.widget_dict = {};
39 };
39 };
40
40
41 /**
41 /**
42 * Get a widget by name, creating it if it doesn't exist.
42 * Get a widget by name, creating it if it doesn't exist.
43 *
43 *
44 * @method widget
44 * @method widget
45 * @param {string} name - the widget name
45 * @param {string} name - the widget name
46 */
46 */
47 NotificationArea.prototype.widget = function (name) {
47 NotificationArea.prototype.widget = function (name) {
48 if (this.widget_dict[name] === undefined) {
48 if (this.widget_dict[name] === undefined) {
49 return this.new_notification_widget(name);
49 return this.new_notification_widget(name);
50 }
50 }
51 return this.get_widget(name);
51 return this.get_widget(name);
52 };
52 };
53
53
54 /**
54 /**
55 * Get a widget by name, throwing an error if it doesn't exist.
55 * Get a widget by name, throwing an error if it doesn't exist.
56 *
56 *
57 * @method get_widget
57 * @method get_widget
58 * @param {string} name - the widget name
58 * @param {string} name - the widget name
59 */
59 */
60 NotificationArea.prototype.get_widget = function (name) {
60 NotificationArea.prototype.get_widget = function (name) {
61 if(this.widget_dict[name] === undefined) {
61 if(this.widget_dict[name] === undefined) {
62 throw('no widgets with this name');
62 throw('no widgets with this name');
63 }
63 }
64 return this.widget_dict[name];
64 return this.widget_dict[name];
65 };
65 };
66
66
67 /**
67 /**
68 * Create a new notification widget with the given name. The
68 * Create a new notification widget with the given name. The
69 * widget must not already exist.
69 * widget must not already exist.
70 *
70 *
71 * @method new_notification_widget
71 * @method new_notification_widget
72 * @param {string} name - the widget name
72 * @param {string} name - the widget name
73 */
73 */
74 NotificationArea.prototype.new_notification_widget = function (name) {
74 NotificationArea.prototype.new_notification_widget = function (name) {
75 if (this.widget_dict[name] !== undefined) {
75 if (this.widget_dict[name] !== undefined) {
76 throw('widget with that name already exists!');
76 throw('widget with that name already exists!');
77 }
77 }
78
78
79 // create the element for the notification widget and add it
79 // create the element for the notification widget and add it
80 // to the notification aread element
80 // to the notification aread element
81 var div = $('<div/>').attr('id', 'notification_' + name);
81 var div = $('<div/>').attr('id', 'notification_' + name);
82 $(this.selector).append(div);
82 $(this.selector).append(div);
83
83
84 // create the widget object and return it
84 // create the widget object and return it
85 this.widget_dict[name] = new NotificationWidget('#notification_' + name);
85 this.widget_dict[name] = new NotificationWidget('#notification_' + name);
86 return this.widget_dict[name];
86 return this.widget_dict[name];
87 };
87 };
88
88
89 /**
89 /**
90 * Initialize the default set of notification widgets.
90 * Initialize the default set of notification widgets.
91 *
91 *
92 * @method init_notification_widgets
92 * @method init_notification_widgets
93 */
93 */
94 NotificationArea.prototype.init_notification_widgets = function () {
94 NotificationArea.prototype.init_notification_widgets = function () {
95 this.init_kernel_notification_widget();
95 this.init_kernel_notification_widget();
96 this.init_notebook_notification_widget();
96 this.init_notebook_notification_widget();
97 };
97 };
98
98
99 /**
99 /**
100 * Initialize the notification widget for kernel status messages.
100 * Initialize the notification widget for kernel status messages.
101 *
101 *
102 * @method init_kernel_notification_widget
102 * @method init_kernel_notification_widget
103 */
103 */
104 NotificationArea.prototype.init_kernel_notification_widget = function () {
104 NotificationArea.prototype.init_kernel_notification_widget = function () {
105 var that = this;
105 var that = this;
106 var knw = this.new_notification_widget('kernel');
106 var knw = this.new_notification_widget('kernel');
107 var $kernel_ind_icon = $("#kernel_indicator_icon");
107 var $kernel_ind_icon = $("#kernel_indicator_icon");
108 var $modal_ind_icon = $("#modal_indicator_icon");
108 var $modal_ind_icon = $("#modal_indicator_icon");
109
109
110 // Command/Edit mode
110 // Command/Edit mode
111 this.events.on('edit_mode.Notebook',function () {
111 this.events.on('edit_mode.Notebook',function () {
112 that.save_widget.update_document_title();
112 that.save_widget.update_document_title();
113 $modal_ind_icon.attr('class','edit_mode_icon').attr('title','Edit Mode');
113 $modal_ind_icon.attr('class','edit_mode_icon').attr('title','Edit Mode');
114 });
114 });
115
115
116 this.events.on('command_mode.Notebook',function () {
116 this.events.on('command_mode.Notebook',function () {
117 that.save_widget.update_document_title();
117 that.save_widget.update_document_title();
118 $modal_ind_icon.attr('class','command_mode_icon').attr('title','Command Mode');
118 $modal_ind_icon.attr('class','command_mode_icon').attr('title','Command Mode');
119 });
119 });
120
120
121 // Implicitly start off in Command mode, switching to Edit mode will trigger event
121 // Implicitly start off in Command mode, switching to Edit mode will trigger event
122 $modal_ind_icon.attr('class','command_mode_icon').attr('title','Command Mode');
122 $modal_ind_icon.attr('class','command_mode_icon').attr('title','Command Mode');
123
123
124 // Kernel events
124 // Kernel events
125 this.events.on('status_idle.Kernel',function () {
125 this.events.on('status_idle.Kernel',function () {
126 that.save_widget.update_document_title();
126 that.save_widget.update_document_title();
127 $kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle');
127 $kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle');
128 });
128 });
129
129
130 this.events.on('status_busy.Kernel',function () {
130 this.events.on('status_busy.Kernel',function () {
131 window.document.title='(Busy) '+window.document.title;
131 window.document.title='(Busy) '+window.document.title;
132 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
132 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
133 });
133 });
134
134
135 this.events.on('status_restarting.Kernel',function () {
135 this.events.on('status_restarting.Kernel',function () {
136 that.save_widget.update_document_title();
136 that.save_widget.update_document_title();
137 knw.set_message("Restarting kernel", 2000);
137 knw.set_message("Restarting kernel", 2000);
138 });
138 });
139
139
140 this.events.on('status_dead.Kernel',function () {
140 this.events.on('status_dead.Kernel',function () {
141 that.save_widget.update_document_title();
141 that.save_widget.update_document_title();
142 knw.danger("Dead kernel");
142 knw.danger("Dead kernel");
143 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
143 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
144 });
144 });
145
145
146 this.events.on('status_interrupting.Kernel',function () {
146 this.events.on('status_interrupting.Kernel',function () {
147 knw.set_message("Interrupting kernel", 2000);
147 knw.set_message("Interrupting kernel", 2000);
148 });
148 });
149
149
150 // Start the kernel indicator in the busy state, and send a kernel_info request.
150 // Start the kernel indicator in the busy state, and send a kernel_info request.
151 // When the kernel_info reply arrives, the kernel is idle.
151 // When the kernel_info reply arrives, the kernel is idle.
152 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
152 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
153
153
154 this.events.on('status_started.Kernel', function (evt, data) {
154 this.events.on('status_started.Kernel', function (evt, data) {
155 knw.info("Websockets Connected", 500);
155 knw.info("Websockets Connected", 500);
156 that.events.trigger('status_busy.Kernel');
156 that.events.trigger('status_busy.Kernel');
157 data.kernel.kernel_info(function () {
157 data.kernel.kernel_info(function () {
158 that.events.trigger('status_idle.Kernel');
158 that.events.trigger('status_idle.Kernel');
159 });
159 });
160 });
160 });
161
161
162 this.events.on('status_restart_failed.Kernel',function () {
162 this.events.on('status_restart_failed.Kernel',function () {
163 var msg = 'The kernel has died, and the automatic restart has failed.' +
163 var msg = 'The kernel has died, and the automatic restart has failed.' +
164 ' It is possible the kernel cannot be restarted.' +
164 ' It is possible the kernel cannot be restarted.' +
165 ' If you are not able to restart the kernel, you will still be able to save' +
165 ' If you are not able to restart the kernel, you will still be able to save' +
166 ' the notebook, but running code will no longer work until the notebook' +
166 ' the notebook, but running code will no longer work until the notebook' +
167 ' is reopened.';
167 ' is reopened.';
168
168
169 dialog.modal({
169 dialog.modal({
170 title: "Dead kernel",
170 title: "Dead kernel",
171 body : msg,
171 body : msg,
172 keyboard_manager: that.keyboard_manager,
172 keyboard_manager: that.keyboard_manager,
173 notebook: that.notebook,
173 notebook: that.notebook,
174 buttons : {
174 buttons : {
175 "Manual Restart": {
175 "Manual Restart": {
176 class: "btn-danger",
176 class: "btn-danger",
177 click: function () {
177 click: function () {
178 that.events.trigger('status_restarting.Kernel');
178 that.events.trigger('status_restarting.Kernel');
179 that.notebook.start_kernel();
179 that.notebook.start_kernel();
180 }
180 }
181 },
181 },
182 "Don't restart": {}
182 "Don't restart": {}
183 }
183 }
184 });
184 });
185 });
185 });
186
186
187 this.events.on('start_failed.Session',function () {
187 this.events.on('start_failed.Session',function (session, xhr, status, error) {
188 var msg = 'We were unable to start the kernel. This might ' +
188 var msg = $('<div/>');
189 'happen if the notebook was previously run with a kernel ' +
189 msg.append($('<div/>')
190 'that you do not have installed. Please choose a different kernel, ' +
190 .text('We were unable to start the kernel. This might ' +
191 'or install the needed kernel and then refresh this page.';
191 'happen if the notebook was previously run with a kernel ' +
192 'that you do not have installed. Please choose a different kernel, ' +
193 'or install the needed kernel and then refresh this page.')
194 .css('margin-bottom', '1em'));
195
196 msg.append($('<div/>')
197 .text('The exact error was:')
198 .css('margin-bottom', '1em'));
199
200 msg.append($('<div/>')
201 .attr('class', 'alert alert-danger')
202 .attr('role', 'alert')
203 .text(JSON.parse(status.responseText).message));
192
204
193 dialog.modal({
205 dialog.modal({
194 title: "Failed to start the kernel",
206 title: "Failed to start the kernel",
195 body : msg,
207 body : msg,
196 keyboard_manager: that.keyboard_manager,
208 keyboard_manager: that.keyboard_manager,
197 notebook: that.notebook,
209 notebook: that.notebook,
198 buttons : {
210 buttons : {
199 "Ok": { class: 'btn-primary' }
211 "Ok": { class: 'btn-primary' }
200 }
212 }
201 });
213 });
202 });
214 });
203
215
204 this.events.on('websocket_closed.Kernel', function (event, data) {
216 this.events.on('websocket_closed.Kernel', function (event, data) {
205 var kernel = data.kernel;
217 var kernel = data.kernel;
206 var ws_url = data.ws_url;
218 var ws_url = data.ws_url;
207 var early = data.early;
219 var early = data.early;
208 var msg;
220 var msg;
209
221
210 $kernel_ind_icon
222 $kernel_ind_icon
211 .attr('class', 'kernel_disconnected_icon')
223 .attr('class', 'kernel_disconnected_icon')
212 .attr('title', 'No Connection to Kernel');
224 .attr('title', 'No Connection to Kernel');
213
225
214 if (!early) {
226 if (!early) {
215 knw.warning('Reconnecting');
227 knw.warning('Reconnecting');
216 setTimeout(function () {
228 setTimeout(function () {
217 kernel.start_channels();
229 kernel.start_channels();
218 }, 5000);
230 }, 5000);
219 return;
231 return;
220 }
232 }
221 console.log('WebSocket connection failed: ', ws_url);
233 console.log('WebSocket connection failed: ', ws_url);
222 msg = "A WebSocket connection could not be established." +
234 msg = "A WebSocket connection could not be established." +
223 " You will NOT be able to run code. Check your" +
235 " You will NOT be able to run code. Check your" +
224 " network connection or notebook server configuration.";
236 " network connection or notebook server configuration.";
225 dialog.modal({
237 dialog.modal({
226 title: "WebSocket connection failed",
238 title: "WebSocket connection failed",
227 body: msg,
239 body: msg,
228 keyboard_manager: that.keyboard_manager,
240 keyboard_manager: that.keyboard_manager,
229 notebook: that.notebook,
241 notebook: that.notebook,
230 buttons : {
242 buttons : {
231 "OK": {},
243 "OK": {},
232 "Reconnect": {
244 "Reconnect": {
233 click: function () {
245 click: function () {
234 knw.warning('Reconnecting');
246 knw.warning('Reconnecting');
235 setTimeout(function () {
247 setTimeout(function () {
236 kernel.start_channels();
248 kernel.start_channels();
237 }, 5000);
249 }, 5000);
238 }
250 }
239 }
251 }
240 }
252 }
241 });
253 });
242 });
254 });
243 };
255 };
244
256
245 /**
257 /**
246 * Initialize the notification widget for notebook status messages.
258 * Initialize the notification widget for notebook status messages.
247 *
259 *
248 * @method init_notebook_notification_widget
260 * @method init_notebook_notification_widget
249 */
261 */
250 NotificationArea.prototype.init_notebook_notification_widget = function () {
262 NotificationArea.prototype.init_notebook_notification_widget = function () {
251 var nnw = this.new_notification_widget('notebook');
263 var nnw = this.new_notification_widget('notebook');
252
264
253 // Notebook events
265 // Notebook events
254 this.events.on('notebook_loading.Notebook', function () {
266 this.events.on('notebook_loading.Notebook', function () {
255 nnw.set_message("Loading notebook",500);
267 nnw.set_message("Loading notebook",500);
256 });
268 });
257 this.events.on('notebook_loaded.Notebook', function () {
269 this.events.on('notebook_loaded.Notebook', function () {
258 nnw.set_message("Notebook loaded",500);
270 nnw.set_message("Notebook loaded",500);
259 });
271 });
260 this.events.on('notebook_saving.Notebook', function () {
272 this.events.on('notebook_saving.Notebook', function () {
261 nnw.set_message("Saving notebook",500);
273 nnw.set_message("Saving notebook",500);
262 });
274 });
263 this.events.on('notebook_saved.Notebook', function () {
275 this.events.on('notebook_saved.Notebook', function () {
264 nnw.set_message("Notebook saved",2000);
276 nnw.set_message("Notebook saved",2000);
265 });
277 });
266 this.events.on('notebook_save_failed.Notebook', function (evt, xhr, status, data) {
278 this.events.on('notebook_save_failed.Notebook', function (evt, xhr, status, data) {
267 nnw.warning(data || "Notebook save failed");
279 nnw.warning(data || "Notebook save failed");
268 });
280 });
269
281
270 // Checkpoint events
282 // Checkpoint events
271 this.events.on('checkpoint_created.Notebook', function (evt, data) {
283 this.events.on('checkpoint_created.Notebook', function (evt, data) {
272 var msg = "Checkpoint created";
284 var msg = "Checkpoint created";
273 if (data.last_modified) {
285 if (data.last_modified) {
274 var d = new Date(data.last_modified);
286 var d = new Date(data.last_modified);
275 msg = msg + ": " + moment(d).format("HH:mm:ss");
287 msg = msg + ": " + moment(d).format("HH:mm:ss");
276 }
288 }
277 nnw.set_message(msg, 2000);
289 nnw.set_message(msg, 2000);
278 });
290 });
279 this.events.on('checkpoint_failed.Notebook', function () {
291 this.events.on('checkpoint_failed.Notebook', function () {
280 nnw.warning("Checkpoint failed");
292 nnw.warning("Checkpoint failed");
281 });
293 });
282 this.events.on('checkpoint_deleted.Notebook', function () {
294 this.events.on('checkpoint_deleted.Notebook', function () {
283 nnw.set_message("Checkpoint deleted", 500);
295 nnw.set_message("Checkpoint deleted", 500);
284 });
296 });
285 this.events.on('checkpoint_delete_failed.Notebook', function () {
297 this.events.on('checkpoint_delete_failed.Notebook', function () {
286 nnw.warning("Checkpoint delete failed");
298 nnw.warning("Checkpoint delete failed");
287 });
299 });
288 this.events.on('checkpoint_restoring.Notebook', function () {
300 this.events.on('checkpoint_restoring.Notebook', function () {
289 nnw.set_message("Restoring to checkpoint...", 500);
301 nnw.set_message("Restoring to checkpoint...", 500);
290 });
302 });
291 this.events.on('checkpoint_restore_failed.Notebook', function () {
303 this.events.on('checkpoint_restore_failed.Notebook', function () {
292 nnw.warning("Checkpoint restore failed");
304 nnw.warning("Checkpoint restore failed");
293 });
305 });
294
306
295 // Autosave events
307 // Autosave events
296 this.events.on('autosave_disabled.Notebook', function () {
308 this.events.on('autosave_disabled.Notebook', function () {
297 nnw.set_message("Autosave disabled", 2000);
309 nnw.set_message("Autosave disabled", 2000);
298 });
310 });
299 this.events.on('autosave_enabled.Notebook', function (evt, interval) {
311 this.events.on('autosave_enabled.Notebook', function (evt, interval) {
300 nnw.set_message("Saving every " + interval / 1000 + "s", 1000);
312 nnw.set_message("Saving every " + interval / 1000 + "s", 1000);
301 });
313 });
302 };
314 };
303
315
304 IPython.NotificationArea = NotificationArea;
316 IPython.NotificationArea = NotificationArea;
305
317
306 return {'NotificationArea': NotificationArea};
318 return {'NotificationArea': NotificationArea};
307 });
319 });
General Comments 0
You need to be logged in to leave comments. Login now