diff --git a/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/README.md b/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/README.md new file mode 100644 index 000000000..a018914d9 --- /dev/null +++ b/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/README.md @@ -0,0 +1,32 @@ +# Exception Notifier + +While working on our code in Jupyter Notebook we tend to forget after a while that we working, actually running some code, but there was an exception that interrupted the long running task. :angry::cry: + +COMEON!!!!!! NOT FARE + +We again run it and have to wait and watch for another iteration to check if the fix worked or did it not. + +Such a pain. :worried: + +Why don't we think about a exception notifier. Wait, What?! Don't we already have a notifier? Ahh yes we do, but not an exception notifier. + +Well we can use them in each the cells and all that, but that's a mess in the notebook. + +We can have an extension, in the notebook where if there was an exception we will be notified like a normal notifier does. + +## Installation: + +``` +pip install jupyter +``` + +``` +pip install jupyter_contrib_nbextensions && jupyter contrib nbextensions install +``` + +Start up a Jupyter Notebook and navigate to the new Nbextensions tab: + +![Exception Notifier Screenshot](exception_notifier_screenshot.png) + +Enable the extension 'Exception Notifier' enjoy the productivity benefits. +(If you don’t see a tab, open a notebook and click Edit > nbextensions config) \ No newline at end of file diff --git a/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/exception_notifier.js b/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/exception_notifier.js new file mode 100644 index 000000000..b39aca10a --- /dev/null +++ b/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/exception_notifier.js @@ -0,0 +1,90 @@ +define([ + 'require', + 'jquery', + 'moment', + 'base/js/namespace', + 'base/js/events', + 'notebook/js/codecell', + 'notebook/js/outputarea', + 'services/config', + ], function ( + requirejs, + $, + moment, + Jupyter, + events, + outputarea, + codecell) { + + "use strict"; + + var CodeCell = codecell.CodeCell; + + var params = { + sticky: true, + play_sound: true + }; + var audio_file = "./notify.mp3"; + + var current_time = function() { + return new Date().getTime() / 1000; + }; + + var play_notification_sound = function(opts) { + try { + var audio = new Audio(requirejs.toUrl(audio_file)); + audio.play(); + } catch(e) { + console.log('HTML5 Audio not supported in browser.'); + } + }; + + var notify = function () { + var opts = { + body: "Exception", + icon: Jupyter.notebook.base_url + "static/base/images/favicon.ico", + requireInteraction: params.sticky + }; + if (params.play_sound) { + play_notification_sound(opts); + } + }; + + function showNotification(evalue) { + notify(); + const notification = new Notification("Exception Occurred", { + body: evalue, + icon: "https://www.iconfinder.com/data/icons/miscellaneous-67-mix/168/objection_convulsions_exception_slander_exclusion_denigration_mudslinging-512.png" + }); + } + function checkPermission() { + if (Notification.permission === "granted") { + events.on('execute.CodeCell', function(evt, data) { + var outputs = data.cell.output_area.outputs; + setTimeout(function() { + if ("traceback" in outputs[0]) { + showNotification(data.cell.output_area.outputs[0].evalue); + } + }, 1000); + }); + } else if (Notification.permission !== "denied") { + Notification.requestPermission().then(permission => { + if (permission === "granted") { + showNotification(); + } + console.log(permission); + }); + } + } + var load_ipython_extension = function () { + return Jupyter.notebook.config.loaded.then(function() { + $.extend(true, params, Jupyter.notebook.config.data.notify); + checkPermission(); + }); + }; + + return { + load_ipython_extension : load_ipython_extension + }; + + }); \ No newline at end of file diff --git a/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/exception_notifier.yaml b/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/exception_notifier.yaml new file mode 100644 index 000000000..72bc434aa --- /dev/null +++ b/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/exception_notifier.yaml @@ -0,0 +1,16 @@ +Type: IPython Notebook Extension +Compatibility: 3.x, 4.x, 5.x, 6.x +Name: Exception Notifier +Main: exception_notifier.js +Link: README.md +Description: > + While running all cells or each cell in the notebook, if an exception occurs, you will get a notification +Parameters: +- name: notify.sticky + description: Require interactions on notifications to dismiss them + input_type: checkbox + default: true +- name: notify.play_sound + description: Play notification sound + input_type: checkbox + default: true \ No newline at end of file diff --git a/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/exception_notifier_screenshot.png b/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/exception_notifier_screenshot.png new file mode 100644 index 000000000..06ac1219d Binary files /dev/null and b/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/exception_notifier_screenshot.png differ diff --git a/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/notify.mp3 b/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/notify.mp3 new file mode 100644 index 000000000..9dc804464 Binary files /dev/null and b/src/jupyter_contrib_nbextensions/nbextensions/exception_notifier/notify.mp3 differ