notificationarea.js
377 lines
| 14.2 KiB
| application/javascript
|
JavascriptLexer
Jonathan Frederic
|
r17198 | // Copyright (c) IPython Development Team. | ||
// Distributed under the terms of the Modified BSD License. | ||||
define([ | ||||
'base/js/namespace', | ||||
Jonathan Frederic
|
r17200 | 'jquery', | ||
Jonathan Frederic
|
r17198 | 'base/js/utils', | ||
'base/js/dialog', | ||||
Jonathan Frederic
|
r17200 | 'notebook/js/notificationwidget', | ||
Matthias BUSSONNIER
|
r17474 | 'moment' | ||
], function(IPython, $, utils, dialog, notificationwidget, moment) { | ||||
Matthias BUSSONNIER
|
r8011 | "use strict"; | ||
Jessica B. Hamrick
|
r18004 | // store reference to the NotificationWidget class | ||
var NotificationWidget = notificationwidget.NotificationWidget; | ||||
/** | ||||
* Construct the NotificationArea object. Options are: | ||||
* events: $(Events) instance | ||||
* save_widget: SaveWidget instance | ||||
* notebook: Notebook instance | ||||
* keyboard_manager: KeyboardManager instance | ||||
* | ||||
* @constructor | ||||
* @param {string} selector - a jQuery selector string for the | ||||
* notification area element | ||||
* @param {Object} [options] - a dictionary of keyword arguments. | ||||
*/ | ||||
jon
|
r17210 | var NotificationArea = function (selector, options) { | ||
Matthias BUSSONNIER
|
r8011 | this.selector = selector; | ||
jon
|
r17210 | this.events = options.events; | ||
this.save_widget = options.save_widget; | ||||
this.notebook = options.notebook; | ||||
Jonathan Frederic
|
r17212 | this.keyboard_manager = options.keyboard_manager; | ||
Matthias BUSSONNIER
|
r8011 | if (this.selector !== undefined) { | ||
this.element = $(selector); | ||||
} | ||||
Matthias BUSSONNIER
|
r8074 | this.widget_dict = {}; | ||
Matthias BUSSONNIER
|
r8011 | }; | ||
Jessica B. Hamrick
|
r18004 | /** | ||
* Get a widget by name, creating it if it doesn't exist. | ||||
* | ||||
* @method widget | ||||
* @param {string} name - the widget name | ||||
*/ | ||||
NotificationArea.prototype.widget = function (name) { | ||||
if (this.widget_dict[name] === undefined) { | ||||
Matthias BUSSONNIER
|
r8204 | return this.new_notification_widget(name); | ||
Matthias BUSSONNIER
|
r8074 | } | ||
Mikhail Korobov
|
r8839 | return this.get_widget(name); | ||
Matthias BUSSONNIER
|
r8204 | }; | ||
Matthias BUSSONNIER
|
r8074 | |||
Jessica B. Hamrick
|
r18004 | /** | ||
* Get a widget by name, throwing an error if it doesn't exist. | ||||
* | ||||
* @method get_widget | ||||
* @param {string} name - the widget name | ||||
*/ | ||||
NotificationArea.prototype.get_widget = function (name) { | ||||
Paul Ivanov
|
r15847 | if(this.widget_dict[name] === undefined) { | ||
Matthias BUSSONNIER
|
r8074 | throw('no widgets with this name'); | ||
} | ||||
return this.widget_dict[name]; | ||||
Matthias BUSSONNIER
|
r8204 | }; | ||
Matthias BUSSONNIER
|
r8074 | |||
Jessica B. Hamrick
|
r18004 | /** | ||
* Create a new notification widget with the given name. The | ||||
* widget must not already exist. | ||||
* | ||||
* @method new_notification_widget | ||||
* @param {string} name - the widget name | ||||
*/ | ||||
NotificationArea.prototype.new_notification_widget = function (name) { | ||||
if (this.widget_dict[name] !== undefined) { | ||||
throw('widget with that name already exists!'); | ||||
Matthias BUSSONNIER
|
r8074 | } | ||
Jessica B. Hamrick
|
r18004 | |||
// create the element for the notification widget and add it | ||||
// to the notification aread element | ||||
var div = $('<div/>').attr('id', 'notification_' + name); | ||||
Matthias BUSSONNIER
|
r8204 | $(this.selector).append(div); | ||
Jessica B. Hamrick
|
r18004 | |||
// create the widget object and return it | ||||
this.widget_dict[name] = new NotificationWidget('#notification_' + name); | ||||
Matthias BUSSONNIER
|
r8074 | return this.widget_dict[name]; | ||
Matthias BUSSONNIER
|
r8204 | }; | ||
Matthias BUSSONNIER
|
r8074 | |||
Jessica B. Hamrick
|
r18004 | /** | ||
* Initialize the default set of notification widgets. | ||||
* | ||||
* @method init_notification_widgets | ||||
*/ | ||||
NotificationArea.prototype.init_notification_widgets = function () { | ||||
this.init_kernel_notification_widget(); | ||||
this.init_notebook_notification_widget(); | ||||
}; | ||||
/** | ||||
* Initialize the notification widget for kernel status messages. | ||||
* | ||||
* @method init_kernel_notification_widget | ||||
*/ | ||||
NotificationArea.prototype.init_kernel_notification_widget = function () { | ||||
Jonathan Frederic
|
r17198 | var that = this; | ||
Matthias BUSSONNIER
|
r8074 | var knw = this.new_notification_widget('kernel'); | ||
Brian E. Granger
|
r15115 | var $kernel_ind_icon = $("#kernel_indicator_icon"); | ||
var $modal_ind_icon = $("#modal_indicator_icon"); | ||||
// Command/Edit mode | ||||
Jessica B. Hamrick
|
r18230 | this.events.on('edit_mode.Notebook', function () { | ||
Jonathan Frederic
|
r17198 | that.save_widget.update_document_title(); | ||
Paul Ivanov
|
r15847 | $modal_ind_icon.attr('class','edit_mode_icon').attr('title','Edit Mode'); | ||
Brian E. Granger
|
r15115 | }); | ||
Jessica B. Hamrick
|
r18230 | this.events.on('command_mode.Notebook', function () { | ||
Jonathan Frederic
|
r17198 | that.save_widget.update_document_title(); | ||
Paul Ivanov
|
r15847 | $modal_ind_icon.attr('class','command_mode_icon').attr('title','Command Mode'); | ||
Brian E. Granger
|
r15115 | }); | ||
Matthias BUSSONNIER
|
r8074 | |||
Paul Ivanov
|
r15809 | // Implicitly start off in Command mode, switching to Edit mode will trigger event | ||
Matthias BUSSONNIER
|
r17433 | $modal_ind_icon.attr('class','command_mode_icon').attr('title','Command Mode'); | ||
Paul Ivanov
|
r15809 | |||
Jessica B. Hamrick
|
r18207 | // Kernel events | ||
Jessica B. Hamrick
|
r18220 | |||
Jessica B. Hamrick
|
r18230 | // this can be either kernel_created.Kernel or kernel_created.Session | ||
this.events.on('kernel_created.Kernel kernel_created.Session', function () { | ||||
knw.info("Kernel Created", 500); | ||||
Matthias BUSSONNIER
|
r15042 | }); | ||
Matthias BUSSONNIER
|
r8074 | |||
Jessica B. Hamrick
|
r18220 | this.events.on('status_reconnecting.Kernel', function () { | ||
knw.warning("Connecting to kernel"); | ||||
}); | ||||
Jessica B. Hamrick
|
r18207 | this.events.on('status_connected.Kernel', function () { | ||
Jessica B. Hamrick
|
r18220 | knw.info("Connected", 500); | ||
Matthias BUSSONNIER
|
r8074 | }); | ||
Jessica B. Hamrick
|
r18230 | this.events.on('status_restarting.Kernel', function () { | ||
Jonathan Frederic
|
r17198 | that.save_widget.update_document_title(); | ||
MinRK
|
r10316 | knw.set_message("Restarting kernel", 2000); | ||
Matthias BUSSONNIER
|
r8074 | }); | ||
Jessica B. Hamrick
|
r18233 | this.events.on('status_autorestarting.Kernel', function (evt, info) { | ||
Jessica B. Hamrick
|
r18235 | // Only show the dialog on the first restart attempt. This | ||
// number gets tracked by the `Kernel` object and passed | ||||
// along here, because we don't want to show the user 5 | ||||
// dialogs saying the same thing (which is the number of | ||||
// times it tries restarting). | ||||
if (info.attempt === 1) { | ||||
Jessica B. Hamrick
|
r18237 | dialog.kernel_modal({ | ||
Jessica B. Hamrick
|
r18233 | notebook: that.notebook, | ||
keyboard_manager: that.keyboard_manager, | ||||
title: "Kernel Restarting", | ||||
body: "The kernel appears to have died. It will restart automatically.", | ||||
buttons: { | ||||
OK : { | ||||
class : "btn-primary" | ||||
} | ||||
Jessica B. Hamrick
|
r18220 | } | ||
Jessica B. Hamrick
|
r18233 | }); | ||
}; | ||||
Jessica B. Hamrick
|
r18230 | |||
that.save_widget.update_document_title(); | ||||
knw.danger("Dead kernel"); | ||||
$kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead'); | ||||
Jessica B. Hamrick
|
r18220 | }); | ||
Jessica B. Hamrick
|
r18230 | this.events.on('status_interrupting.Kernel', function () { | ||
Brian E. Granger
|
r14816 | knw.set_message("Interrupting kernel", 2000); | ||
Matthias BUSSONNIER
|
r8074 | }); | ||
MinRK
|
r15737 | |||
Jessica B. Hamrick
|
r18207 | this.events.on('status_disconnected.Kernel', function () { | ||
$kernel_ind_icon | ||||
.attr('class', 'kernel_disconnected_icon') | ||||
.attr('title', 'No Connection to Kernel'); | ||||
Jessica B. Hamrick
|
r18202 | }); | ||
Jessica B. Hamrick
|
r18236 | this.events.on('connection_failed.Kernel', function (evt, info) { | ||
// only show the dialog if this is the first failed | ||||
// connect attempt, because the kernel will continue | ||||
// trying to reconnect and we don't want to spam the user | ||||
// with messages | ||||
if (info.attempt === 1) { | ||||
var msg = "A connection to the notebook server could not be established." + | ||||
" The notebook will continue trying to reconnect, but" + | ||||
" until it does, you will NOT be able to run code. Check your" + | ||||
" network connection or notebook server configuration."; | ||||
Jessica B. Hamrick
|
r18237 | dialog.kernel_modal({ | ||
Jessica B. Hamrick
|
r18236 | title: "Connection failed", | ||
body: msg, | ||||
keyboard_manager: that.keyboard_manager, | ||||
notebook: that.notebook, | ||||
buttons : { | ||||
"OK": {} | ||||
Jessica B. Hamrick
|
r18207 | } | ||
Jessica B. Hamrick
|
r18236 | }); | ||
} | ||||
MinRK
|
r15737 | }); | ||
Matthias BUSSONNIER
|
r8074 | |||
Jessica B. Hamrick
|
r18233 | this.events.on('status_killed.Kernel status_killed.Session', function () { | ||
Jessica B. Hamrick
|
r18207 | that.save_widget.update_document_title(); | ||
knw.danger("Dead kernel"); | ||||
$kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead'); | ||||
}); | ||||
Jessica B. Hamrick
|
r18220 | this.events.on('kernel_dead.Kernel', function () { | ||
MinRK
|
r10895 | |||
Jessica B. Hamrick
|
r18233 | var showMsg = function () { | ||
var msg = 'The kernel has died, and the automatic restart has failed.' + | ||||
' It is possible the kernel cannot be restarted.' + | ||||
' If you are not able to restart the kernel, you will still be able to save' + | ||||
' the notebook, but running code will no longer work until the notebook' + | ||||
' is reopened.'; | ||||
Jessica B. Hamrick
|
r18237 | dialog.kernel_modal({ | ||
Jessica B. Hamrick
|
r18233 | title: "Dead kernel", | ||
body : msg, | ||||
keyboard_manager: that.keyboard_manager, | ||||
notebook: that.notebook, | ||||
buttons : { | ||||
"Manual Restart": { | ||||
class: "btn-danger", | ||||
click: function () { | ||||
that.notebook.start_session(); | ||||
} | ||||
}, | ||||
MinRK
|
r10895 | "Don't restart": {} | ||
Jessica B. Hamrick
|
r18233 | } | ||
}); | ||||
return false; | ||||
}; | ||||
that.save_widget.update_document_title(); | ||||
knw.danger("Dead kernel", undefined, showMsg); | ||||
$kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead'); | ||||
showMsg(); | ||||
Matthias BUSSONNIER
|
r8074 | }); | ||
Jessica B. Hamrick
|
r18227 | this.events.on('kernel_dead.Session', function (evt, info) { | ||
var full = info.xhr.responseJSON.message; | ||||
var short = info.xhr.responseJSON.short_message || 'Kernel error'; | ||||
var traceback = info.xhr.responseJSON.traceback; | ||||
Jessica B. Hamrick
|
r18060 | |||
Jessica B. Hamrick
|
r18066 | var showMsg = function () { | ||
Jessica B. Hamrick
|
r18108 | var msg = $('<div/>').append($('<p/>').text(full)); | ||
Jessica B. Hamrick
|
r18229 | var cm, cm_elem, cm_open; | ||
Jessica B. Hamrick
|
r18108 | |||
if (traceback) { | ||||
cm_elem = $('<div/>') | ||||
.css('margin-top', '1em') | ||||
.css('padding', '1em') | ||||
.addClass('output_scroll'); | ||||
msg.append(cm_elem); | ||||
cm = CodeMirror(cm_elem.get(0), { | ||||
mode: "python", | ||||
readOnly : true | ||||
}); | ||||
cm.setValue(traceback); | ||||
Jessica B. Hamrick
|
r18229 | cm_open = $.proxy(cm.refresh, cm); | ||
Jessica B. Hamrick
|
r18108 | } | ||
Jessica B. Hamrick
|
r18237 | dialog.kernel_modal({ | ||
Jessica B. Hamrick
|
r18063 | title: "Failed to start the kernel", | ||
Jessica B. Hamrick
|
r18066 | body : msg, | ||
Jessica B. Hamrick
|
r18063 | keyboard_manager: that.keyboard_manager, | ||
notebook: that.notebook, | ||||
Jessica B. Hamrick
|
r18229 | open: cm_open, | ||
Jessica B. Hamrick
|
r18063 | buttons : { | ||
"Ok": { class: 'btn-primary' } | ||||
} | ||||
}); | ||||
Jessica B. Hamrick
|
r18108 | |||
Jessica B. Hamrick
|
r18063 | return false; | ||
Jessica B. Hamrick
|
r18066 | }; | ||
that.save_widget.update_document_title(); | ||||
$kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead'); | ||||
knw.danger(short, undefined, showMsg); | ||||
Jessica B. Hamrick
|
r18060 | }); | ||
Jessica B. Hamrick
|
r18230 | this.events.on('status_starting.Kernel', function () { | ||
window.document.title='(Starting) '+window.document.title; | ||||
$kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy'); | ||||
knw.set_message("Kernel starting, please wait..."); | ||||
}); | ||||
this.events.on('status_ready.Kernel', function () { | ||||
that.save_widget.update_document_title(); | ||||
$kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle'); | ||||
knw.info("Kernel ready", 500); | ||||
}); | ||||
this.events.on('status_idle.Kernel', function () { | ||||
Jessica B. Hamrick
|
r18207 | that.save_widget.update_document_title(); | ||
$kernel_ind_icon.attr('class','kernel_idle_icon').attr('title','Kernel Idle'); | ||||
}); | ||||
MinRK
|
r17676 | |||
Jessica B. Hamrick
|
r18230 | this.events.on('status_busy.Kernel', function () { | ||
Jessica B. Hamrick
|
r18207 | window.document.title='(Busy) '+window.document.title; | ||
$kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy'); | ||||
Brian E. Granger
|
r9222 | }); | ||
Jessica B. Hamrick
|
r18207 | |||
// Start the kernel indicator in the busy state, and send a kernel_info request. | ||||
// When the kernel_info reply arrives, the kernel is idle. | ||||
$kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy'); | ||||
Jessica B. Hamrick
|
r18004 | }; | ||
Brian E. Granger
|
r9222 | |||
Jessica B. Hamrick
|
r18004 | /** | ||
* Initialize the notification widget for notebook status messages. | ||||
* | ||||
* @method init_notebook_notification_widget | ||||
*/ | ||||
NotificationArea.prototype.init_notebook_notification_widget = function () { | ||||
Matthias BUSSONNIER
|
r8074 | var nnw = this.new_notification_widget('notebook'); | ||
// Notebook events | ||||
Jonathan Frederic
|
r17198 | this.events.on('notebook_loading.Notebook', function () { | ||
Matthias BUSSONNIER
|
r8074 | nnw.set_message("Loading notebook",500); | ||
}); | ||||
Jonathan Frederic
|
r17198 | this.events.on('notebook_loaded.Notebook', function () { | ||
Matthias BUSSONNIER
|
r8074 | nnw.set_message("Notebook loaded",500); | ||
}); | ||||
Jonathan Frederic
|
r17198 | this.events.on('notebook_saving.Notebook', function () { | ||
Matthias BUSSONNIER
|
r8074 | nnw.set_message("Saving notebook",500); | ||
}); | ||||
Jonathan Frederic
|
r17198 | this.events.on('notebook_saved.Notebook', function () { | ||
Matthias BUSSONNIER
|
r8074 | nnw.set_message("Notebook saved",2000); | ||
}); | ||||
Jonathan Frederic
|
r17198 | this.events.on('notebook_save_failed.Notebook', function (evt, xhr, status, data) { | ||
Matthias BUSSONNIER
|
r17368 | nnw.warning(data || "Notebook save failed"); | ||
Matthias BUSSONNIER
|
r8074 | }); | ||
MinRK
|
r10502 | |||
// Checkpoint events | ||||
Jonathan Frederic
|
r17198 | this.events.on('checkpoint_created.Notebook', function (evt, data) { | ||
MinRK
|
r10502 | var msg = "Checkpoint created"; | ||
if (data.last_modified) { | ||||
var d = new Date(data.last_modified); | ||||
Matthias BUSSONNIER
|
r17474 | msg = msg + ": " + moment(d).format("HH:mm:ss"); | ||
MinRK
|
r10502 | } | ||
nnw.set_message(msg, 2000); | ||||
}); | ||||
Jonathan Frederic
|
r17198 | this.events.on('checkpoint_failed.Notebook', function () { | ||
Matthias BUSSONNIER
|
r17368 | nnw.warning("Checkpoint failed"); | ||
MinRK
|
r10502 | }); | ||
Jonathan Frederic
|
r17198 | this.events.on('checkpoint_deleted.Notebook', function () { | ||
MinRK
|
r10502 | nnw.set_message("Checkpoint deleted", 500); | ||
}); | ||||
Jonathan Frederic
|
r17198 | this.events.on('checkpoint_delete_failed.Notebook', function () { | ||
Matthias BUSSONNIER
|
r17368 | nnw.warning("Checkpoint delete failed"); | ||
MinRK
|
r10502 | }); | ||
Jonathan Frederic
|
r17198 | this.events.on('checkpoint_restoring.Notebook', function () { | ||
MinRK
|
r10502 | nnw.set_message("Restoring to checkpoint...", 500); | ||
}); | ||||
Jonathan Frederic
|
r17198 | this.events.on('checkpoint_restore_failed.Notebook', function () { | ||
Matthias BUSSONNIER
|
r17368 | nnw.warning("Checkpoint restore failed"); | ||
MinRK
|
r10502 | }); | ||
Matthias BUSSONNIER
|
r8074 | |||
MinRK
|
r10505 | // Autosave events | ||
Jonathan Frederic
|
r17198 | this.events.on('autosave_disabled.Notebook', function () { | ||
MinRK
|
r10505 | nnw.set_message("Autosave disabled", 2000); | ||
}); | ||||
Jonathan Frederic
|
r17198 | this.events.on('autosave_enabled.Notebook', function (evt, interval) { | ||
MinRK
|
r10505 | nnw.set_message("Saving every " + interval / 1000 + "s", 1000); | ||
}); | ||||
Matthias BUSSONNIER
|
r8204 | }; | ||
Matthias BUSSONNIER
|
r8048 | |||
Matthias BUSSONNIER
|
r8011 | IPython.NotificationArea = NotificationArea; | ||
Jonathan Frederic
|
r17201 | return {'NotificationArea': NotificationArea}; | ||
Jonathan Frederic
|
r17198 | }); | ||