##// END OF EJS Templates
Merge pull request #7460 from minrk/kernel-indicator...
Matthias Bussonnier -
r19946:d4e75b36 merge
parent child Browse files
Show More
@@ -1,326 +1,326 b''
1 define([
1 define([
2 'base/js/namespace',
2 'base/js/namespace',
3 'jquery',
3 'jquery',
4 'base/js/utils',
4 'base/js/utils',
5 'base/js/dialog',
5 'base/js/dialog',
6 'base/js/notificationarea',
6 'base/js/notificationarea',
7 'moment'
7 'moment'
8 ], function(IPython, $, utils, dialog, notificationarea, moment) {
8 ], function(IPython, $, utils, dialog, notificationarea, moment) {
9 "use strict";
9 "use strict";
10 var NotificationArea = notificationarea.NotificationArea;
10 var NotificationArea = notificationarea.NotificationArea;
11
11
12 var NotebookNotificationArea = function(selector, options) {
12 var NotebookNotificationArea = function(selector, options) {
13 NotificationArea.apply(this, [selector, options]);
13 NotificationArea.apply(this, [selector, options]);
14 this.save_widget = options.save_widget;
14 this.save_widget = options.save_widget;
15 this.notebook = options.notebook;
15 this.notebook = options.notebook;
16 this.keyboard_manager = options.keyboard_manager;
16 this.keyboard_manager = options.keyboard_manager;
17 }
17 }
18
18
19 NotebookNotificationArea.prototype = Object.create(NotificationArea.prototype);
19 NotebookNotificationArea.prototype = Object.create(NotificationArea.prototype);
20
20
21 /**
21 /**
22 * Initialize the default set of notification widgets.
22 * Initialize the default set of notification widgets.
23 *
23 *
24 * @method init_notification_widgets
24 * @method init_notification_widgets
25 */
25 */
26 NotebookNotificationArea.prototype.init_notification_widgets = function () {
26 NotebookNotificationArea.prototype.init_notification_widgets = function () {
27 this.init_kernel_notification_widget();
27 this.init_kernel_notification_widget();
28 this.init_notebook_notification_widget();
28 this.init_notebook_notification_widget();
29 };
29 };
30
30
31 /**
31 /**
32 * Initialize the notification widget for kernel status messages.
32 * Initialize the notification widget for kernel status messages.
33 *
33 *
34 * @method init_kernel_notification_widget
34 * @method init_kernel_notification_widget
35 */
35 */
36 NotebookNotificationArea.prototype.init_kernel_notification_widget = function () {
36 NotebookNotificationArea.prototype.init_kernel_notification_widget = function () {
37 var that = this;
37 var that = this;
38 var knw = this.new_notification_widget('kernel');
38 var knw = this.new_notification_widget('kernel');
39 var $kernel_ind_icon = $("#kernel_indicator_icon");
39 var $kernel_ind_icon = $("#kernel_indicator_icon");
40 var $modal_ind_icon = $("#modal_indicator");
40 var $modal_ind_icon = $("#modal_indicator");
41 var $body = $('body')
41 var $body = $('body')
42
42
43 // Command/Edit mode
43 // Command/Edit mode
44 this.events.on('edit_mode.Notebook', function () {
44 this.events.on('edit_mode.Notebook', function () {
45 that.save_widget.update_document_title();
45 that.save_widget.update_document_title();
46 $body.addClass('edit_mode');
46 $body.addClass('edit_mode');
47 $body.removeClass('command_mode');
47 $body.removeClass('command_mode');
48 $modal_ind_icon.attr('title','Edit Mode');
48 $modal_ind_icon.attr('title','Edit Mode');
49 });
49 });
50
50
51 this.events.on('command_mode.Notebook', function () {
51 this.events.on('command_mode.Notebook', function () {
52 that.save_widget.update_document_title();
52 that.save_widget.update_document_title();
53 $body.removeClass('edit_mode');
53 $body.removeClass('edit_mode');
54 $body.addClass('command_mode');
54 $body.addClass('command_mode');
55 $modal_ind_icon.attr('title','Command Mode');
55 $modal_ind_icon.attr('title','Command Mode');
56 });
56 });
57
57
58 // Implicitly start off in Command mode, switching to Edit mode will trigger event
58 // Implicitly start off in Command mode, switching to Edit mode will trigger event
59 $modal_ind_icon.addClass('modal_indicator').attr('title','Command Mode');
59 $modal_ind_icon.addClass('modal_indicator').attr('title','Command Mode');
60 $body.addClass('command_mode')
60 $body.addClass('command_mode')
61
61
62 // Kernel events
62 // Kernel events
63
63
64 // this can be either kernel_created.Kernel or kernel_created.Session
64 // this can be either kernel_created.Kernel or kernel_created.Session
65 this.events.on('kernel_created.Kernel kernel_created.Session', function () {
65 this.events.on('kernel_created.Kernel kernel_created.Session', function () {
66 knw.info("Kernel Created", 500);
66 knw.info("Kernel Created", 500);
67 });
67 });
68
68
69 this.events.on('kernel_reconnecting.Kernel', function () {
69 this.events.on('kernel_reconnecting.Kernel', function () {
70 knw.warning("Connecting to kernel");
70 knw.warning("Connecting to kernel");
71 });
71 });
72
72
73 this.events.on('kernel_connection_dead.Kernel', function (evt, info) {
73 this.events.on('kernel_connection_dead.Kernel', function (evt, info) {
74 knw.danger("Not Connected", undefined, function () {
74 knw.danger("Not Connected", undefined, function () {
75 // schedule reconnect a short time in the future, don't reconnect immediately
75 // schedule reconnect a short time in the future, don't reconnect immediately
76 setTimeout($.proxy(info.kernel.reconnect, info.kernel), 500);
76 setTimeout($.proxy(info.kernel.reconnect, info.kernel), 500);
77 }, {title: 'click to reconnect'});
77 }, {title: 'click to reconnect'});
78 });
78 });
79
79
80 this.events.on('kernel_connected.Kernel', function () {
80 this.events.on('kernel_connected.Kernel', function () {
81 knw.info("Connected", 500);
81 knw.info("Connected", 500);
82 });
82 });
83
83
84 this.events.on('kernel_restarting.Kernel', function () {
84 this.events.on('kernel_restarting.Kernel', function () {
85 that.save_widget.update_document_title();
85 that.save_widget.update_document_title();
86 knw.set_message("Restarting kernel", 2000);
86 knw.set_message("Restarting kernel", 2000);
87 });
87 });
88
88
89 this.events.on('kernel_autorestarting.Kernel', function (evt, info) {
89 this.events.on('kernel_autorestarting.Kernel', function (evt, info) {
90 // Only show the dialog on the first restart attempt. This
90 // Only show the dialog on the first restart attempt. This
91 // number gets tracked by the `Kernel` object and passed
91 // number gets tracked by the `Kernel` object and passed
92 // along here, because we don't want to show the user 5
92 // along here, because we don't want to show the user 5
93 // dialogs saying the same thing (which is the number of
93 // dialogs saying the same thing (which is the number of
94 // times it tries restarting).
94 // times it tries restarting).
95 if (info.attempt === 1) {
95 if (info.attempt === 1) {
96
96
97 dialog.kernel_modal({
97 dialog.kernel_modal({
98 notebook: that.notebook,
98 notebook: that.notebook,
99 keyboard_manager: that.keyboard_manager,
99 keyboard_manager: that.keyboard_manager,
100 title: "Kernel Restarting",
100 title: "Kernel Restarting",
101 body: "The kernel appears to have died. It will restart automatically.",
101 body: "The kernel appears to have died. It will restart automatically.",
102 buttons: {
102 buttons: {
103 OK : {
103 OK : {
104 class : "btn-primary"
104 class : "btn-primary"
105 }
105 }
106 }
106 }
107 });
107 });
108 };
108 };
109
109
110 that.save_widget.update_document_title();
110 that.save_widget.update_document_title();
111 knw.danger("Dead kernel");
111 knw.danger("Dead kernel");
112 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
112 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
113 });
113 });
114
114
115 this.events.on('kernel_interrupting.Kernel', function () {
115 this.events.on('kernel_interrupting.Kernel', function () {
116 knw.set_message("Interrupting kernel", 2000);
116 knw.set_message("Interrupting kernel", 2000);
117 });
117 });
118
118
119 this.events.on('kernel_disconnected.Kernel', function () {
119 this.events.on('kernel_disconnected.Kernel', function () {
120 $kernel_ind_icon
120 $kernel_ind_icon
121 .attr('class', 'kernel_disconnected_icon')
121 .attr('class', 'kernel_disconnected_icon')
122 .attr('title', 'No Connection to Kernel');
122 .attr('title', 'No Connection to Kernel');
123 });
123 });
124
124
125 this.events.on('kernel_connection_failed.Kernel', function (evt, info) {
125 this.events.on('kernel_connection_failed.Kernel', function (evt, info) {
126 // only show the dialog if this is the first failed
126 // only show the dialog if this is the first failed
127 // connect attempt, because the kernel will continue
127 // connect attempt, because the kernel will continue
128 // trying to reconnect and we don't want to spam the user
128 // trying to reconnect and we don't want to spam the user
129 // with messages
129 // with messages
130 if (info.attempt === 1) {
130 if (info.attempt === 1) {
131
131
132 var msg = "A connection to the notebook server could not be established." +
132 var msg = "A connection to the notebook server could not be established." +
133 " The notebook will continue trying to reconnect, but" +
133 " The notebook will continue trying to reconnect, but" +
134 " until it does, you will NOT be able to run code. Check your" +
134 " until it does, you will NOT be able to run code. Check your" +
135 " network connection or notebook server configuration.";
135 " network connection or notebook server configuration.";
136
136
137 dialog.kernel_modal({
137 dialog.kernel_modal({
138 title: "Connection failed",
138 title: "Connection failed",
139 body: msg,
139 body: msg,
140 keyboard_manager: that.keyboard_manager,
140 keyboard_manager: that.keyboard_manager,
141 notebook: that.notebook,
141 notebook: that.notebook,
142 buttons : {
142 buttons : {
143 "OK": {}
143 "OK": {}
144 }
144 }
145 });
145 });
146 }
146 }
147 });
147 });
148
148
149 this.events.on('kernel_killed.Kernel kernel_killed.Session', function () {
149 this.events.on('kernel_killed.Kernel kernel_killed.Session', function () {
150 that.save_widget.update_document_title();
150 that.save_widget.update_document_title();
151 knw.danger("Dead kernel");
151 knw.danger("Dead kernel");
152 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
152 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
153 });
153 });
154
154
155 this.events.on('kernel_dead.Kernel', function () {
155 this.events.on('kernel_dead.Kernel', function () {
156
156
157 var showMsg = function () {
157 var showMsg = function () {
158
158
159 var msg = 'The kernel has died, and the automatic restart has failed.' +
159 var msg = 'The kernel has died, and the automatic restart has failed.' +
160 ' It is possible the kernel cannot be restarted.' +
160 ' It is possible the kernel cannot be restarted.' +
161 ' If you are not able to restart the kernel, you will still be able to save' +
161 ' If you are not able to restart the kernel, you will still be able to save' +
162 ' the notebook, but running code will no longer work until the notebook' +
162 ' the notebook, but running code will no longer work until the notebook' +
163 ' is reopened.';
163 ' is reopened.';
164
164
165 dialog.kernel_modal({
165 dialog.kernel_modal({
166 title: "Dead kernel",
166 title: "Dead kernel",
167 body : msg,
167 body : msg,
168 keyboard_manager: that.keyboard_manager,
168 keyboard_manager: that.keyboard_manager,
169 notebook: that.notebook,
169 notebook: that.notebook,
170 buttons : {
170 buttons : {
171 "Manual Restart": {
171 "Manual Restart": {
172 class: "btn-danger",
172 class: "btn-danger",
173 click: function () {
173 click: function () {
174 that.notebook.start_session();
174 that.notebook.start_session();
175 }
175 }
176 },
176 },
177 "Don't restart": {}
177 "Don't restart": {}
178 }
178 }
179 });
179 });
180
180
181 return false;
181 return false;
182 };
182 };
183
183
184 that.save_widget.update_document_title();
184 that.save_widget.update_document_title();
185 knw.danger("Dead kernel", undefined, showMsg);
185 knw.danger("Dead kernel", undefined, showMsg);
186 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
186 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
187
187
188 showMsg();
188 showMsg();
189 });
189 });
190
190
191 this.events.on('kernel_dead.Session', function (evt, info) {
191 this.events.on('kernel_dead.Session', function (evt, info) {
192 var full = info.xhr.responseJSON.message;
192 var full = info.xhr.responseJSON.message;
193 var short = info.xhr.responseJSON.short_message || 'Kernel error';
193 var short = info.xhr.responseJSON.short_message || 'Kernel error';
194 var traceback = info.xhr.responseJSON.traceback;
194 var traceback = info.xhr.responseJSON.traceback;
195
195
196 var showMsg = function () {
196 var showMsg = function () {
197 var msg = $('<div/>').append($('<p/>').text(full));
197 var msg = $('<div/>').append($('<p/>').text(full));
198 var cm, cm_elem, cm_open;
198 var cm, cm_elem, cm_open;
199
199
200 if (traceback) {
200 if (traceback) {
201 cm_elem = $('<div/>')
201 cm_elem = $('<div/>')
202 .css('margin-top', '1em')
202 .css('margin-top', '1em')
203 .css('padding', '1em')
203 .css('padding', '1em')
204 .addClass('output_scroll');
204 .addClass('output_scroll');
205 msg.append(cm_elem);
205 msg.append(cm_elem);
206 cm = CodeMirror(cm_elem.get(0), {
206 cm = CodeMirror(cm_elem.get(0), {
207 mode: "python",
207 mode: "python",
208 readOnly : true
208 readOnly : true
209 });
209 });
210 cm.setValue(traceback);
210 cm.setValue(traceback);
211 cm_open = $.proxy(cm.refresh, cm);
211 cm_open = $.proxy(cm.refresh, cm);
212 }
212 }
213
213
214 dialog.kernel_modal({
214 dialog.kernel_modal({
215 title: "Failed to start the kernel",
215 title: "Failed to start the kernel",
216 body : msg,
216 body : msg,
217 keyboard_manager: that.keyboard_manager,
217 keyboard_manager: that.keyboard_manager,
218 notebook: that.notebook,
218 notebook: that.notebook,
219 open: cm_open,
219 open: cm_open,
220 buttons : {
220 buttons : {
221 "Ok": { class: 'btn-primary' }
221 "Ok": { class: 'btn-primary' }
222 }
222 }
223 });
223 });
224
224
225 return false;
225 return false;
226 };
226 };
227
227
228 that.save_widget.update_document_title();
228 that.save_widget.update_document_title();
229 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
229 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
230 knw.danger(short, undefined, showMsg);
230 knw.danger(short, undefined, showMsg);
231 });
231 });
232
232
233 this.events.on('kernel_starting.Kernel', function () {
233 this.events.on('kernel_starting.Kernel kernel_created.Session', function () {
234 window.document.title='(Starting) '+window.document.title;
234 window.document.title='(Starting) '+window.document.title;
235 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
235 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
236 knw.set_message("Kernel starting, please wait...");
236 knw.set_message("Kernel starting, please wait...");
237 });
237 });
238
238
239 this.events.on('kernel_ready.Kernel', function () {
239 this.events.on('kernel_ready.Kernel', function () {
240 that.save_widget.update_document_title();
240 that.save_widget.update_document_title();
241 $kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle');
241 $kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle');
242 knw.info("Kernel ready", 500);
242 knw.info("Kernel ready", 500);
243 });
243 });
244
244
245 this.events.on('kernel_idle.Kernel', function () {
245 this.events.on('kernel_idle.Kernel', function () {
246 that.save_widget.update_document_title();
246 that.save_widget.update_document_title();
247 $kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle');
247 $kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle');
248 });
248 });
249
249
250 this.events.on('kernel_busy.Kernel', function () {
250 this.events.on('kernel_busy.Kernel', function () {
251 window.document.title='(Busy) '+window.document.title;
251 window.document.title='(Busy) '+window.document.title;
252 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
252 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
253 });
253 });
254
254
255 // Start the kernel indicator in the busy state, and send a kernel_info request.
255 // Start the kernel indicator in the busy state, and send a kernel_info request.
256 // When the kernel_info reply arrives, the kernel is idle.
256 // When the kernel_info reply arrives, the kernel is idle.
257 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
257 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
258 };
258 };
259
259
260 /**
260 /**
261 * Initialize the notification widget for notebook status messages.
261 * Initialize the notification widget for notebook status messages.
262 *
262 *
263 * @method init_notebook_notification_widget
263 * @method init_notebook_notification_widget
264 */
264 */
265 NotebookNotificationArea.prototype.init_notebook_notification_widget = function () {
265 NotebookNotificationArea.prototype.init_notebook_notification_widget = function () {
266 var nnw = this.new_notification_widget('notebook');
266 var nnw = this.new_notification_widget('notebook');
267
267
268 // Notebook events
268 // Notebook events
269 this.events.on('notebook_loading.Notebook', function () {
269 this.events.on('notebook_loading.Notebook', function () {
270 nnw.set_message("Loading notebook",500);
270 nnw.set_message("Loading notebook",500);
271 });
271 });
272 this.events.on('notebook_loaded.Notebook', function () {
272 this.events.on('notebook_loaded.Notebook', function () {
273 nnw.set_message("Notebook loaded",500);
273 nnw.set_message("Notebook loaded",500);
274 });
274 });
275 this.events.on('notebook_saving.Notebook', function () {
275 this.events.on('notebook_saving.Notebook', function () {
276 nnw.set_message("Saving notebook",500);
276 nnw.set_message("Saving notebook",500);
277 });
277 });
278 this.events.on('notebook_saved.Notebook', function () {
278 this.events.on('notebook_saved.Notebook', function () {
279 nnw.set_message("Notebook saved",2000);
279 nnw.set_message("Notebook saved",2000);
280 });
280 });
281 this.events.on('notebook_save_failed.Notebook', function (evt, error) {
281 this.events.on('notebook_save_failed.Notebook', function (evt, error) {
282 nnw.warning(error.message || "Notebook save failed");
282 nnw.warning(error.message || "Notebook save failed");
283 });
283 });
284 this.events.on('notebook_copy_failed.Notebook', function (evt, error) {
284 this.events.on('notebook_copy_failed.Notebook', function (evt, error) {
285 nnw.warning(error.message || "Notebook copy failed");
285 nnw.warning(error.message || "Notebook copy failed");
286 });
286 });
287
287
288 // Checkpoint events
288 // Checkpoint events
289 this.events.on('checkpoint_created.Notebook', function (evt, data) {
289 this.events.on('checkpoint_created.Notebook', function (evt, data) {
290 var msg = "Checkpoint created";
290 var msg = "Checkpoint created";
291 if (data.last_modified) {
291 if (data.last_modified) {
292 var d = new Date(data.last_modified);
292 var d = new Date(data.last_modified);
293 msg = msg + ": " + moment(d).format("HH:mm:ss");
293 msg = msg + ": " + moment(d).format("HH:mm:ss");
294 }
294 }
295 nnw.set_message(msg, 2000);
295 nnw.set_message(msg, 2000);
296 });
296 });
297 this.events.on('checkpoint_failed.Notebook', function () {
297 this.events.on('checkpoint_failed.Notebook', function () {
298 nnw.warning("Checkpoint failed");
298 nnw.warning("Checkpoint failed");
299 });
299 });
300 this.events.on('checkpoint_deleted.Notebook', function () {
300 this.events.on('checkpoint_deleted.Notebook', function () {
301 nnw.set_message("Checkpoint deleted", 500);
301 nnw.set_message("Checkpoint deleted", 500);
302 });
302 });
303 this.events.on('checkpoint_delete_failed.Notebook', function () {
303 this.events.on('checkpoint_delete_failed.Notebook', function () {
304 nnw.warning("Checkpoint delete failed");
304 nnw.warning("Checkpoint delete failed");
305 });
305 });
306 this.events.on('checkpoint_restoring.Notebook', function () {
306 this.events.on('checkpoint_restoring.Notebook', function () {
307 nnw.set_message("Restoring to checkpoint...", 500);
307 nnw.set_message("Restoring to checkpoint...", 500);
308 });
308 });
309 this.events.on('checkpoint_restore_failed.Notebook', function () {
309 this.events.on('checkpoint_restore_failed.Notebook', function () {
310 nnw.warning("Checkpoint restore failed");
310 nnw.warning("Checkpoint restore failed");
311 });
311 });
312
312
313 // Autosave events
313 // Autosave events
314 this.events.on('autosave_disabled.Notebook', function () {
314 this.events.on('autosave_disabled.Notebook', function () {
315 nnw.set_message("Autosave disabled", 2000);
315 nnw.set_message("Autosave disabled", 2000);
316 });
316 });
317 this.events.on('autosave_enabled.Notebook', function (evt, interval) {
317 this.events.on('autosave_enabled.Notebook', function (evt, interval) {
318 nnw.set_message("Saving every " + interval / 1000 + "s", 1000);
318 nnw.set_message("Saving every " + interval / 1000 + "s", 1000);
319 });
319 });
320 };
320 };
321
321
322 // Backwards compatibility.
322 // Backwards compatibility.
323 IPython.NotificationArea = NotebookNotificationArea;
323 IPython.NotificationArea = NotebookNotificationArea;
324
324
325 return {'NotebookNotificationArea': NotebookNotificationArea};
325 return {'NotebookNotificationArea': NotebookNotificationArea};
326 });
326 });
General Comments 0
You need to be logged in to leave comments. Login now