##// END OF EJS Templates
use one-off notification widget for match notification...
Min RK -
Show More
@@ -1,318 +1,324 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 'jquery',
5 'jquery',
6 'base/js/namespace',
6 'base/js/namespace',
7 'base/js/dialog',
7 'base/js/dialog',
8 'base/js/utils',
8 'base/js/utils',
9 ], function($, IPython, dialog, utils) {
9 ], function($, IPython, dialog, utils) {
10 "use strict";
10 "use strict";
11
11
12 var KernelSelector = function(selector, notebook) {
12 var KernelSelector = function(selector, notebook) {
13 var that = this;
13 var that = this;
14 this.selector = selector;
14 this.selector = selector;
15 this.notebook = notebook;
15 this.notebook = notebook;
16 this.notebook.set_kernelselector(this);
16 this.notebook.set_kernelselector(this);
17 this.events = notebook.events;
17 this.events = notebook.events;
18 this.current_selection = null;
18 this.current_selection = null;
19 this.kernelspecs = {};
19 this.kernelspecs = {};
20 if (this.selector !== undefined) {
20 if (this.selector !== undefined) {
21 this.element = $(selector);
21 this.element = $(selector);
22 this.request_kernelspecs();
22 this.request_kernelspecs();
23 }
23 }
24 this.bind_events();
24 this.bind_events();
25 // Make the object globally available for user convenience & inspection
25 // Make the object globally available for user convenience & inspection
26 IPython.kernelselector = this;
26 IPython.kernelselector = this;
27 this._finish_load = null;
27 this._finish_load = null;
28 this._loaded = false;
28 this._loaded = false;
29 this.loaded = new Promise(function(resolve) {
29 this.loaded = new Promise(function(resolve) {
30 that._finish_load = resolve;
30 that._finish_load = resolve;
31 });
31 });
32
32
33 Object.seal(this);
33 Object.seal(this);
34 };
34 };
35
35
36 KernelSelector.prototype.request_kernelspecs = function() {
36 KernelSelector.prototype.request_kernelspecs = function() {
37 var url = utils.url_join_encode(this.notebook.base_url, 'api/kernelspecs');
37 var url = utils.url_join_encode(this.notebook.base_url, 'api/kernelspecs');
38 utils.promising_ajax(url).then($.proxy(this._got_kernelspecs, this));
38 utils.promising_ajax(url).then($.proxy(this._got_kernelspecs, this));
39 };
39 };
40
40
41 var _sorted_names = function(kernelspecs) {
41 var _sorted_names = function(kernelspecs) {
42 // sort kernel names
42 // sort kernel names
43 return Object.keys(kernelspecs).sort(function (a, b) {
43 return Object.keys(kernelspecs).sort(function (a, b) {
44 // sort by display_name
44 // sort by display_name
45 var da = kernelspecs[a].spec.display_name;
45 var da = kernelspecs[a].spec.display_name;
46 var db = kernelspecs[b].spec.display_name;
46 var db = kernelspecs[b].spec.display_name;
47 if (da === db) {
47 if (da === db) {
48 return 0;
48 return 0;
49 } else if (da > db) {
49 } else if (da > db) {
50 return 1;
50 return 1;
51 } else {
51 } else {
52 return -1;
52 return -1;
53 }
53 }
54 });
54 });
55 };
55 };
56
56
57 KernelSelector.prototype._got_kernelspecs = function(data) {
57 KernelSelector.prototype._got_kernelspecs = function(data) {
58 var that = this;
58 var that = this;
59 this.kernelspecs = data.kernelspecs;
59 this.kernelspecs = data.kernelspecs;
60 var change_kernel_submenu = $("#menu-change-kernel-submenu");
60 var change_kernel_submenu = $("#menu-change-kernel-submenu");
61 var new_notebook_submenu = $("#menu-new-notebook-submenu");
61 var new_notebook_submenu = $("#menu-new-notebook-submenu");
62 var keys = _sorted_names(data.kernelspecs);
62 var keys = _sorted_names(data.kernelspecs);
63
63
64 keys.map(function (key) {
64 keys.map(function (key) {
65 // Create the Kernel > Change kernel submenu
65 // Create the Kernel > Change kernel submenu
66 var ks = data.kernelspecs[key];
66 var ks = data.kernelspecs[key];
67 change_kernel_submenu.append(
67 change_kernel_submenu.append(
68 $("<li>").attr("id", "kernel-submenu-"+ks.name).append(
68 $("<li>").attr("id", "kernel-submenu-"+ks.name).append(
69 $('<a>')
69 $('<a>')
70 .attr('href', '#')
70 .attr('href', '#')
71 .click( function () {
71 .click( function () {
72 that.set_kernel(ks.name);
72 that.set_kernel(ks.name);
73 })
73 })
74 .text(ks.spec.display_name)
74 .text(ks.spec.display_name)
75 )
75 )
76 );
76 );
77 // Create the File > New Notebook submenu
77 // Create the File > New Notebook submenu
78 new_notebook_submenu.append(
78 new_notebook_submenu.append(
79 $("<li>").attr("id", "new-notebook-submenu-"+ks.name).append(
79 $("<li>").attr("id", "new-notebook-submenu-"+ks.name).append(
80 $('<a>')
80 $('<a>')
81 .attr('href', '#')
81 .attr('href', '#')
82 .click( function () {
82 .click( function () {
83 that.new_notebook(ks.name);
83 that.new_notebook(ks.name);
84 })
84 })
85 .text(ks.spec.display_name)
85 .text(ks.spec.display_name)
86 )
86 )
87 );
87 );
88
88
89 });
89 });
90 // trigger loaded promise
90 // trigger loaded promise
91 this._loaded = true;
91 this._loaded = true;
92 this._finish_load();
92 this._finish_load();
93 };
93 };
94
94
95 KernelSelector.prototype._spec_changed = function (event, ks) {
95 KernelSelector.prototype._spec_changed = function (event, ks) {
96 /** event handler for spec_changed */
96 /** event handler for spec_changed */
97
97
98 // update selection
98 // update selection
99 this.current_selection = ks.name;
99 this.current_selection = ks.name;
100
100
101 // put the current kernel at the top of File > New Notebook
101 // put the current kernel at the top of File > New Notebook
102 var cur_kernel_entry = $("#new-notebook-submenu-" + ks.name);
102 var cur_kernel_entry = $("#new-notebook-submenu-" + ks.name);
103 var parent = cur_kernel_entry.parent();
103 var parent = cur_kernel_entry.parent();
104 // do something only if there is more than one kernel
104 // do something only if there is more than one kernel
105 if (parent.children().length > 1) {
105 if (parent.children().length > 1) {
106 // first, sort back the submenu
106 // first, sort back the submenu
107 parent.append(
107 parent.append(
108 parent.children("li[class!='divider']").sort(
108 parent.children("li[class!='divider']").sort(
109 function (a,b) {
109 function (a,b) {
110 var da = $("a",a).text();
110 var da = $("a",a).text();
111 var db = $("a",b).text();
111 var db = $("a",b).text();
112 if (da === db) {
112 if (da === db) {
113 return 0;
113 return 0;
114 } else if (da > db) {
114 } else if (da > db) {
115 return 1;
115 return 1;
116 } else {
116 } else {
117 return -1;
117 return -1;
118 }}));
118 }}));
119 // then, if there is no divider yet, add one
119 // then, if there is no divider yet, add one
120 if (!parent.children("li[class='divider']").length) {
120 if (!parent.children("li[class='divider']").length) {
121 parent.prepend($("<li>").attr("class","divider"));
121 parent.prepend($("<li>").attr("class","divider"));
122 }
122 }
123 // finally, put the current kernel at the top
123 // finally, put the current kernel at the top
124 parent.prepend(cur_kernel_entry);
124 parent.prepend(cur_kernel_entry);
125 }
125 }
126
126
127 // load logo
127 // load logo
128 var logo_img = this.element.find("img.current_kernel_logo");
128 var logo_img = this.element.find("img.current_kernel_logo");
129 $("#kernel_indicator").find('.kernel_indicator_name').text(ks.spec.display_name);
129 $("#kernel_indicator").find('.kernel_indicator_name').text(ks.spec.display_name);
130 if (ks.resources['logo-64x64']) {
130 if (ks.resources['logo-64x64']) {
131 logo_img.attr("src", ks.resources['logo-64x64']);
131 logo_img.attr("src", ks.resources['logo-64x64']);
132 logo_img.show();
132 logo_img.show();
133 } else {
133 } else {
134 logo_img.hide();
134 logo_img.hide();
135 }
135 }
136
136
137 // load kernel css
137 // load kernel css
138 var css_url = ks.resources['kernel.css'];
138 var css_url = ks.resources['kernel.css'];
139 if (css_url) {
139 if (css_url) {
140 $('#kernel-css').attr('href', css_url);
140 $('#kernel-css').attr('href', css_url);
141 } else {
141 } else {
142 $('#kernel-css').attr('href', '');
142 $('#kernel-css').attr('href', '');
143 }
143 }
144
144
145 // load kernel js
145 // load kernel js
146 if (ks.resources['kernel.js']) {
146 if (ks.resources['kernel.js']) {
147 require([ks.resources['kernel.js']],
147 require([ks.resources['kernel.js']],
148 function (kernel_mod) {
148 function (kernel_mod) {
149 if (kernel_mod && kernel_mod.onload) {
149 if (kernel_mod && kernel_mod.onload) {
150 kernel_mod.onload();
150 kernel_mod.onload();
151 } else {
151 } else {
152 console.warn("Kernel " + ks.name + " has a kernel.js file that does not contain "+
152 console.warn("Kernel " + ks.name + " has a kernel.js file that does not contain "+
153 "any asynchronous module definition. This is undefined behavior "+
153 "any asynchronous module definition. This is undefined behavior "+
154 "and not recommended.");
154 "and not recommended.");
155 }
155 }
156 }, function (err) {
156 }, function (err) {
157 console.warn("Failed to load kernel.js from ", ks.resources['kernel.js'], err);
157 console.warn("Failed to load kernel.js from ", ks.resources['kernel.js'], err);
158 }
158 }
159 );
159 );
160 }
160 }
161 };
161 };
162
162
163 KernelSelector.prototype.set_kernel = function (selected) {
163 KernelSelector.prototype.set_kernel = function (selected) {
164 /** set the kernel by name, ensuring kernelspecs have been loaded, first
164 /** set the kernel by name, ensuring kernelspecs have been loaded, first
165
165
166 kernel can be just a kernel name, or a notebook kernelspec metadata
166 kernel can be just a kernel name, or a notebook kernelspec metadata
167 (name, language, display_name).
167 (name, language, display_name).
168 */
168 */
169 var that = this;
169 var that = this;
170 if (typeof selected === 'string') {
170 if (typeof selected === 'string') {
171 selected = {
171 selected = {
172 name: selected
172 name: selected
173 };
173 };
174 }
174 }
175 if (this._loaded) {
175 if (this._loaded) {
176 this._set_kernel(selected);
176 this._set_kernel(selected);
177 } else {
177 } else {
178 return this.loaded.then(function () {
178 return this.loaded.then(function () {
179 that._set_kernel(selected);
179 that._set_kernel(selected);
180 });
180 });
181 }
181 }
182 };
182 };
183
183
184 KernelSelector.prototype._set_kernel = function (selected) {
184 KernelSelector.prototype._set_kernel = function (selected) {
185 /** Actually set the kernel (kernelspecs have been loaded) */
185 /** Actually set the kernel (kernelspecs have been loaded) */
186 if (selected.name === this.current_selection) {
186 if (selected.name === this.current_selection) {
187 // only trigger event if value changed
187 // only trigger event if value changed
188 return;
188 return;
189 }
189 }
190 var kernelspecs = this.kernelspecs;
190 var kernelspecs = this.kernelspecs;
191 var ks = kernelspecs[selected.name];
191 var ks = kernelspecs[selected.name];
192 if (ks === undefined) {
192 if (ks === undefined) {
193 var available = _sorted_names(kernelspecs);
193 var available = _sorted_names(kernelspecs);
194 var matches = [];
194 var matches = [];
195 if (selected.language && selected.language.length > 0) {
195 if (selected.language && selected.language.length > 0) {
196 available.map(function (name) {
196 available.map(function (name) {
197 if (kernelspecs[name].spec.language.toLowerCase() === selected.language.toLowerCase()) {
197 if (kernelspecs[name].spec.language.toLowerCase() === selected.language.toLowerCase()) {
198 matches.push(name);
198 matches.push(name);
199 }
199 }
200 });
200 });
201 }
201 }
202 if (matches.length === 1) {
202 if (matches.length === 1) {
203 ks = kernelspecs[matches[0]];
203 ks = kernelspecs[matches[0]];
204 console.log("No exact match found for " + selected.name +
205 ", using only kernel that matches language=" + selected.language, ks);
206 this.events.trigger("spec_match_found.Kernel", {
207 selected: selected,
208 found: ks,
209 });
204 }
210 }
205 // if still undefined, trigger failure event
211 // if still undefined, trigger failure event
206 if (ks === undefined) {
212 if (ks === undefined) {
207 this.events.trigger("spec_not_found.Kernel", {
213 this.events.trigger("spec_not_found.Kernel", {
208 selected: selected,
214 selected: selected,
209 matches: matches,
215 matches: matches,
210 available: available,
216 available: available,
211 });
217 });
212 return;
218 return;
213 }
219 }
214 }
220 }
215 if (this.notebook._session_starting) {
221 if (this.notebook._session_starting) {
216 console.error("Cannot change kernel while waiting for pending session start.");
222 console.error("Cannot change kernel while waiting for pending session start.");
217 return;
223 return;
218 }
224 }
219 this.current_selection = ks.name;
225 this.current_selection = ks.name;
220 this.events.trigger('spec_changed.Kernel', ks);
226 this.events.trigger('spec_changed.Kernel', ks);
221 };
227 };
222
228
223 KernelSelector.prototype._spec_not_found = function (event, data) {
229 KernelSelector.prototype._spec_not_found = function (event, data) {
224 var that = this;
230 var that = this;
225 var select = $("<select>").addClass('form-control');
231 var select = $("<select>").addClass('form-control');
226 console.warn("Kernelspec not found:", data);
232 console.warn("Kernelspec not found:", data);
227 var names;
233 var names;
228 if (data.matches.length > 1) {
234 if (data.matches.length > 1) {
229 names = data.matches;
235 names = data.matches;
230 } else {
236 } else {
231 names = data.available;
237 names = data.available;
232 }
238 }
233 names.map(function (name) {
239 names.map(function (name) {
234 var ks = that.kernelspecs[name];
240 var ks = that.kernelspecs[name];
235 select.append(
241 select.append(
236 $('<option/>').attr('value', ks.name).text(ks.spec.display_name || ks.name)
242 $('<option/>').attr('value', ks.name).text(ks.spec.display_name || ks.name)
237 );
243 );
238 });
244 });
239
245
240 var body = $("<form>").addClass("form-inline").append(
246 var body = $("<form>").addClass("form-inline").append(
241 $("<span>").text(
247 $("<span>").text(
242 "I couldn't find a kernel matching " + (data.selected.display_name || data.name) + "." +
248 "I couldn't find a kernel matching " + (data.selected.display_name || data.name) + "." +
243 " Please select a kernel:"
249 " Please select a kernel:"
244 )
250 )
245 ).append(select);
251 ).append(select);
246
252
247 dialog.modal({
253 dialog.modal({
248 title : 'Kernel not found',
254 title : 'Kernel not found',
249 body : body,
255 body : body,
250 buttons : {
256 buttons : {
251 'Continue without kernel' : {
257 'Continue without kernel' : {
252 class : 'btn-danger',
258 class : 'btn-danger',
253 click : function () {
259 click : function () {
254 that.events.trigger('no_kernel.Kernel');
260 that.events.trigger('no_kernel.Kernel');
255 }
261 }
256 },
262 },
257 OK : {
263 OK : {
258 class : 'btn-primary',
264 class : 'btn-primary',
259 click : function () {
265 click : function () {
260 that.set_kernel(select.val());
266 that.set_kernel(select.val());
261 }
267 }
262 }
268 }
263 }
269 }
264 });
270 });
265 };
271 };
266
272
267 KernelSelector.prototype.new_notebook = function (kernel_name) {
273 KernelSelector.prototype.new_notebook = function (kernel_name) {
268
274
269 var w = window.open();
275 var w = window.open();
270 // Create a new notebook in the same path as the current
276 // Create a new notebook in the same path as the current
271 // notebook's path.
277 // notebook's path.
272 var that = this;
278 var that = this;
273 var parent = utils.url_path_split(that.notebook.notebook_path)[0];
279 var parent = utils.url_path_split(that.notebook.notebook_path)[0];
274 that.notebook.contents.new_untitled(parent, {type: "notebook"}).then(
280 that.notebook.contents.new_untitled(parent, {type: "notebook"}).then(
275 function (data) {
281 function (data) {
276 var url = utils.url_join_encode(
282 var url = utils.url_join_encode(
277 that.notebook.base_url, 'notebooks', data.path
283 that.notebook.base_url, 'notebooks', data.path
278 );
284 );
279 url += "?kernel_name=" + kernel_name;
285 url += "?kernel_name=" + kernel_name;
280 w.location = url;
286 w.location = url;
281 },
287 },
282 function(error) {
288 function(error) {
283 w.close();
289 w.close();
284 dialog.modal({
290 dialog.modal({
285 title : 'Creating Notebook Failed',
291 title : 'Creating Notebook Failed',
286 body : "The error was: " + error.message,
292 body : "The error was: " + error.message,
287 buttons : {'OK' : {'class' : 'btn-primary'}}
293 buttons : {'OK' : {'class' : 'btn-primary'}}
288 });
294 });
289 }
295 }
290 );
296 );
291 };
297 };
292
298
293 KernelSelector.prototype.lock_switch = function() {
299 KernelSelector.prototype.lock_switch = function() {
294 // should set a flag and display warning+reload if user want to
300 // should set a flag and display warning+reload if user want to
295 // re-change kernel. As UI discussion never finish
301 // re-change kernel. As UI discussion never finish
296 // making that a separate PR.
302 // making that a separate PR.
297 console.warn('switching kernel is not guaranteed to work !');
303 console.warn('switching kernel is not guaranteed to work !');
298 };
304 };
299
305
300 KernelSelector.prototype.bind_events = function() {
306 KernelSelector.prototype.bind_events = function() {
301 var that = this;
307 var that = this;
302 this.events.on('spec_changed.Kernel', $.proxy(this._spec_changed, this));
308 this.events.on('spec_changed.Kernel', $.proxy(this._spec_changed, this));
303 this.events.on('spec_not_found.Kernel', $.proxy(this._spec_not_found, this));
309 this.events.on('spec_not_found.Kernel', $.proxy(this._spec_not_found, this));
304 this.events.on('kernel_created.Session', function (event, data) {
310 this.events.on('kernel_created.Session', function (event, data) {
305 that.set_kernel(data.kernel.name);
311 that.set_kernel(data.kernel.name);
306 });
312 });
307
313
308 var logo_img = this.element.find("img.current_kernel_logo");
314 var logo_img = this.element.find("img.current_kernel_logo");
309 logo_img.on("load", function() {
315 logo_img.on("load", function() {
310 logo_img.show();
316 logo_img.show();
311 });
317 });
312 logo_img.on("error", function() {
318 logo_img.on("error", function() {
313 logo_img.hide();
319 logo_img.hide();
314 });
320 });
315 };
321 };
316
322
317 return {'KernelSelector': KernelSelector};
323 return {'KernelSelector': KernelSelector};
318 });
324 });
@@ -1,330 +1,337 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.warning("No kernel");
151 knw.warning("No kernel");
152 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel is not running');
152 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel is not running');
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("no_kernel.Kernel", function (evt, data) {
191 this.events.on("no_kernel.Kernel", function (evt, data) {
192 $("#kernel_indicator").find('.kernel_indicator_name').text("No Kernel");
192 $("#kernel_indicator").find('.kernel_indicator_name').text("No Kernel");
193 });
193 });
194
194
195 this.events.on('kernel_dead.Session', function (evt, info) {
195 this.events.on('kernel_dead.Session', function (evt, info) {
196 var full = info.xhr.responseJSON.message;
196 var full = info.xhr.responseJSON.message;
197 var short = info.xhr.responseJSON.short_message || 'Kernel error';
197 var short = info.xhr.responseJSON.short_message || 'Kernel error';
198 var traceback = info.xhr.responseJSON.traceback;
198 var traceback = info.xhr.responseJSON.traceback;
199
199
200 var showMsg = function () {
200 var showMsg = function () {
201 var msg = $('<div/>').append($('<p/>').text(full));
201 var msg = $('<div/>').append($('<p/>').text(full));
202 var cm, cm_elem, cm_open;
202 var cm, cm_elem, cm_open;
203
203
204 if (traceback) {
204 if (traceback) {
205 cm_elem = $('<div/>')
205 cm_elem = $('<div/>')
206 .css('margin-top', '1em')
206 .css('margin-top', '1em')
207 .css('padding', '1em')
207 .css('padding', '1em')
208 .addClass('output_scroll');
208 .addClass('output_scroll');
209 msg.append(cm_elem);
209 msg.append(cm_elem);
210 cm = CodeMirror(cm_elem.get(0), {
210 cm = CodeMirror(cm_elem.get(0), {
211 mode: "python",
211 mode: "python",
212 readOnly : true
212 readOnly : true
213 });
213 });
214 cm.setValue(traceback);
214 cm.setValue(traceback);
215 cm_open = $.proxy(cm.refresh, cm);
215 cm_open = $.proxy(cm.refresh, cm);
216 }
216 }
217
217
218 dialog.kernel_modal({
218 dialog.kernel_modal({
219 title: "Failed to start the kernel",
219 title: "Failed to start the kernel",
220 body : msg,
220 body : msg,
221 keyboard_manager: that.keyboard_manager,
221 keyboard_manager: that.keyboard_manager,
222 notebook: that.notebook,
222 notebook: that.notebook,
223 open: cm_open,
223 open: cm_open,
224 buttons : {
224 buttons : {
225 "Ok": { class: 'btn-primary' }
225 "Ok": { class: 'btn-primary' }
226 }
226 }
227 });
227 });
228
228
229 return false;
229 return false;
230 };
230 };
231
231
232 that.save_widget.update_document_title();
232 that.save_widget.update_document_title();
233 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
233 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
234 knw.danger(short, undefined, showMsg);
234 knw.danger(short, undefined, showMsg);
235 });
235 });
236
236
237 this.events.on('kernel_starting.Kernel kernel_created.Session', function () {
237 this.events.on('kernel_starting.Kernel kernel_created.Session', function () {
238 window.document.title='(Starting) '+window.document.title;
238 window.document.title='(Starting) '+window.document.title;
239 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
239 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
240 knw.set_message("Kernel starting, please wait...");
240 knw.set_message("Kernel starting, please wait...");
241 });
241 });
242
242
243 this.events.on('kernel_ready.Kernel', function () {
243 this.events.on('kernel_ready.Kernel', function () {
244 that.save_widget.update_document_title();
244 that.save_widget.update_document_title();
245 $kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle');
245 $kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle');
246 knw.info("Kernel ready", 500);
246 knw.info("Kernel ready", 500);
247 });
247 });
248
248
249 this.events.on('kernel_idle.Kernel', function () {
249 this.events.on('kernel_idle.Kernel', function () {
250 that.save_widget.update_document_title();
250 that.save_widget.update_document_title();
251 $kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle');
251 $kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle');
252 });
252 });
253
253
254 this.events.on('kernel_busy.Kernel', function () {
254 this.events.on('kernel_busy.Kernel', function () {
255 window.document.title='(Busy) '+window.document.title;
255 window.document.title='(Busy) '+window.document.title;
256 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
256 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
257 });
257 });
258
258
259 this.events.on('spec_match_found.Kernel', function (evt, data) {
260 that.widget('kernelspec').info("Using kernel: " + data.found.spec.display_name, 3000, undefined, {
261 title: "Only candidate for language: " + data.selected.language + " was " + data.found.spec.display_name
262 });
263 });
264
265
259 // Start the kernel indicator in the busy state, and send a kernel_info request.
266 // Start the kernel indicator in the busy state, and send a kernel_info request.
260 // When the kernel_info reply arrives, the kernel is idle.
267 // When the kernel_info reply arrives, the kernel is idle.
261 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
268 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
262 };
269 };
263
270
264 /**
271 /**
265 * Initialize the notification widget for notebook status messages.
272 * Initialize the notification widget for notebook status messages.
266 *
273 *
267 * @method init_notebook_notification_widget
274 * @method init_notebook_notification_widget
268 */
275 */
269 NotebookNotificationArea.prototype.init_notebook_notification_widget = function () {
276 NotebookNotificationArea.prototype.init_notebook_notification_widget = function () {
270 var nnw = this.new_notification_widget('notebook');
277 var nnw = this.new_notification_widget('notebook');
271
278
272 // Notebook events
279 // Notebook events
273 this.events.on('notebook_loading.Notebook', function () {
280 this.events.on('notebook_loading.Notebook', function () {
274 nnw.set_message("Loading notebook",500);
281 nnw.set_message("Loading notebook",500);
275 });
282 });
276 this.events.on('notebook_loaded.Notebook', function () {
283 this.events.on('notebook_loaded.Notebook', function () {
277 nnw.set_message("Notebook loaded",500);
284 nnw.set_message("Notebook loaded",500);
278 });
285 });
279 this.events.on('notebook_saving.Notebook', function () {
286 this.events.on('notebook_saving.Notebook', function () {
280 nnw.set_message("Saving notebook",500);
287 nnw.set_message("Saving notebook",500);
281 });
288 });
282 this.events.on('notebook_saved.Notebook', function () {
289 this.events.on('notebook_saved.Notebook', function () {
283 nnw.set_message("Notebook saved",2000);
290 nnw.set_message("Notebook saved",2000);
284 });
291 });
285 this.events.on('notebook_save_failed.Notebook', function (evt, error) {
292 this.events.on('notebook_save_failed.Notebook', function (evt, error) {
286 nnw.warning(error.message || "Notebook save failed");
293 nnw.warning(error.message || "Notebook save failed");
287 });
294 });
288 this.events.on('notebook_copy_failed.Notebook', function (evt, error) {
295 this.events.on('notebook_copy_failed.Notebook', function (evt, error) {
289 nnw.warning(error.message || "Notebook copy failed");
296 nnw.warning(error.message || "Notebook copy failed");
290 });
297 });
291
298
292 // Checkpoint events
299 // Checkpoint events
293 this.events.on('checkpoint_created.Notebook', function (evt, data) {
300 this.events.on('checkpoint_created.Notebook', function (evt, data) {
294 var msg = "Checkpoint created";
301 var msg = "Checkpoint created";
295 if (data.last_modified) {
302 if (data.last_modified) {
296 var d = new Date(data.last_modified);
303 var d = new Date(data.last_modified);
297 msg = msg + ": " + moment(d).format("HH:mm:ss");
304 msg = msg + ": " + moment(d).format("HH:mm:ss");
298 }
305 }
299 nnw.set_message(msg, 2000);
306 nnw.set_message(msg, 2000);
300 });
307 });
301 this.events.on('checkpoint_failed.Notebook', function () {
308 this.events.on('checkpoint_failed.Notebook', function () {
302 nnw.warning("Checkpoint failed");
309 nnw.warning("Checkpoint failed");
303 });
310 });
304 this.events.on('checkpoint_deleted.Notebook', function () {
311 this.events.on('checkpoint_deleted.Notebook', function () {
305 nnw.set_message("Checkpoint deleted", 500);
312 nnw.set_message("Checkpoint deleted", 500);
306 });
313 });
307 this.events.on('checkpoint_delete_failed.Notebook', function () {
314 this.events.on('checkpoint_delete_failed.Notebook', function () {
308 nnw.warning("Checkpoint delete failed");
315 nnw.warning("Checkpoint delete failed");
309 });
316 });
310 this.events.on('checkpoint_restoring.Notebook', function () {
317 this.events.on('checkpoint_restoring.Notebook', function () {
311 nnw.set_message("Restoring to checkpoint...", 500);
318 nnw.set_message("Restoring to checkpoint...", 500);
312 });
319 });
313 this.events.on('checkpoint_restore_failed.Notebook', function () {
320 this.events.on('checkpoint_restore_failed.Notebook', function () {
314 nnw.warning("Checkpoint restore failed");
321 nnw.warning("Checkpoint restore failed");
315 });
322 });
316
323
317 // Autosave events
324 // Autosave events
318 this.events.on('autosave_disabled.Notebook', function () {
325 this.events.on('autosave_disabled.Notebook', function () {
319 nnw.set_message("Autosave disabled", 2000);
326 nnw.set_message("Autosave disabled", 2000);
320 });
327 });
321 this.events.on('autosave_enabled.Notebook', function (evt, interval) {
328 this.events.on('autosave_enabled.Notebook', function (evt, interval) {
322 nnw.set_message("Saving every " + interval / 1000 + "s", 1000);
329 nnw.set_message("Saving every " + interval / 1000 + "s", 1000);
323 });
330 });
324 };
331 };
325
332
326 // Backwards compatibility.
333 // Backwards compatibility.
327 IPython.NotificationArea = NotebookNotificationArea;
334 IPython.NotificationArea = NotebookNotificationArea;
328
335
329 return {'NotebookNotificationArea': NotebookNotificationArea};
336 return {'NotebookNotificationArea': NotebookNotificationArea};
330 });
337 });
General Comments 0
You need to be logged in to leave comments. Login now