UNPKG

jupyterlab-emrys

Version:

A computational environment for Jupyter. Powered by Emrys

541 lines (540 loc) 20.4 kB
// Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. "use strict"; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var phosphor_domutil_1 = require('phosphor-domutil'); var phosphor_signaling_1 = require('phosphor-signaling'); var phosphor_widget_1 = require('phosphor-widget'); var utils_1 = require('../utils'); /** * The class name added to a running widget. */ var RUNNING_CLASS = 'jp-RunningSessions'; /** * The class name added to a running widget header. */ var HEADER_CLASS = 'jp-RunningSessions-header'; /** * The class name added to a running widget header refresh button. */ var REFRESH_CLASS = 'jp-RunningSessions-headerRefresh'; /** * The class name added to the running terminal sessions section. */ var SECTION_CLASS = 'jp-RunningSessions-section'; /** * The class name added to the running terminal sessions section. */ var TERMINALS_CLASS = 'jp-RunningSessions-terminalSection'; /** * The class name added to the running kernel sessions section. */ var SESSIONS_CLASS = 'jp-RunningSessions-sessionsSection'; /** * The class name added to the running sessions section header. */ var SECTION_HEADER_CLASS = 'jp-RunningSessions-sectionHeader'; /** * The class name added to a section container. */ var CONTAINER_CLASS = 'jp-RunningSessions-sectionContainer'; /** * The class name added to the running kernel sessions section list. */ var LIST_CLASS = 'jp-RunningSessions-sectionList'; /** * The class name added to the running sessions items. */ var ITEM_CLASS = 'jp-RunningSessions-item'; /** * The class name added to a running session item icon. */ var ITEM_ICON_CLASS = 'jp-RunningSessions-itemIcon'; /** * The class name added to a running session item label. */ var ITEM_LABEL_CLASS = 'jp-RunningSessions-itemLabel'; /** * The class name added to a running session item kernel name. */ var KERNEL_NAME_CLASS = 'jp-RunningSessions-itemKernelName'; /** * The class name added to a running session item shutdown button. */ var SHUTDOWN_BUTTON_CLASS = 'jp-RunningSessions-itemShutdown'; /** * The class name added to a notebook icon. */ var NOTEBOOK_ICON_CLASS = 'jp-mod-notebook'; /** * The class name added to a file icon. */ var FILE_ICON_CLASS = 'jp-mod-file'; /** * The class name added to a terminal icon. */ var TERMINAL_ICON_CLASS = 'jp-mod-terminal'; /** * The duration of auto-refresh in ms. */ var REFRESH_DURATION = 10000; /** * A class that exposes the running terminal and kernel sessions. */ var RunningSessions = (function (_super) { __extends(RunningSessions, _super); /** * Construct a new running widget. */ function RunningSessions(options) { _super.call(this); this._manager = null; this._renderer = null; this._runningSessions = []; this._runningTerminals = []; this._refreshId = -1; this._manager = options.manager; this._renderer = options.renderer || RunningSessions.defaultRenderer; this.addClass(RUNNING_CLASS); // Populate the terminals section. var termNode = utils_1.findElement(this.node, TERMINALS_CLASS); var termHeader = this._renderer.createTerminalHeaderNode(); termHeader.className = SECTION_HEADER_CLASS; termNode.appendChild(termHeader); var termContainer = document.createElement('div'); termContainer.className = CONTAINER_CLASS; var termList = document.createElement('ul'); termList.className = LIST_CLASS; termContainer.appendChild(termList); termNode.appendChild(termContainer); // Populate the sessions section. var sessionNode = utils_1.findElement(this.node, SESSIONS_CLASS); var sessionHeader = this._renderer.createSessionHeaderNode(); sessionHeader.className = SECTION_HEADER_CLASS; sessionNode.appendChild(sessionHeader); var sessionContainer = document.createElement('div'); sessionContainer.className = CONTAINER_CLASS; var sessionList = document.createElement('ul'); sessionList.className = LIST_CLASS; sessionContainer.appendChild(sessionList); sessionNode.appendChild(sessionContainer); this._manager.terminals.runningChanged.connect(this._onTerminalsChanged, this); this._manager.sessions.runningChanged.connect(this._onSessionsChanged, this); } /** * Create the node for the running widget. */ RunningSessions.createNode = function () { var node = document.createElement('div'); var header = document.createElement('div'); header.className = HEADER_CLASS; var terminals = document.createElement('div'); terminals.className = SECTION_CLASS + " " + TERMINALS_CLASS; var sessions = document.createElement('div'); sessions.className = SECTION_CLASS + " " + SESSIONS_CLASS; var refresh = document.createElement('button'); refresh.className = REFRESH_CLASS; header.appendChild(refresh); node.appendChild(header); node.appendChild(terminals); node.appendChild(sessions); return node; }; Object.defineProperty(RunningSessions.prototype, "sessionOpenRequested", { /** * A signal emitted when a kernel session open is requested. */ get: function () { return Private.sessionOpenRequestedSignal.bind(this); }, enumerable: true, configurable: true }); Object.defineProperty(RunningSessions.prototype, "terminalOpenRequested", { /** * A signal emitted when a terminal session open is requested. */ get: function () { return Private.terminalOpenRequestedSignal.bind(this); }, enumerable: true, configurable: true }); Object.defineProperty(RunningSessions.prototype, "renderer", { /** * The renderer used by the running sessions widget. * * #### Notes * This is a read-only property. */ get: function () { return this._renderer; }, enumerable: true, configurable: true }); Object.defineProperty(RunningSessions.prototype, "isDisposed", { /** * Test whether the widget is disposed. * * #### Notes * This is a read-only property. */ get: function () { return this._manager === null; }, enumerable: true, configurable: true }); /** * Dispose of the resources used by the widget. */ RunningSessions.prototype.dispose = function () { if (this.isDisposed) { return; } this._manager = null; this._runningSessions = null; this._runningTerminals = null; this._renderer = null; }; /** * Refresh the widget. */ RunningSessions.prototype.refresh = function () { var _this = this; var terminals = this._manager.terminals; var sessions = this._manager.sessions; clearTimeout(this._refreshId); return terminals.listRunning().then(function (running) { _this._onTerminalsChanged(terminals, running); return sessions.listRunning(); }).then(function (running) { _this._onSessionsChanged(sessions, running); _this._refreshId = setTimeout(function () { _this.refresh(); }, REFRESH_DURATION); }); }; /** * Handle the DOM events for the widget. * * @param event - The DOM event sent to the widget. * * #### Notes * This method implements the DOM `EventListener` interface and is * called in response to events on the widget's DOM nodes. It should * not be called directly by user code. */ RunningSessions.prototype.handleEvent = function (event) { if (event.type === 'click') { this._evtClick(event); } }; /** * A message handler invoked on an `'after-attach'` message. */ RunningSessions.prototype.onAfterAttach = function (msg) { this.node.addEventListener('click', this); this.refresh(); }; /** * A message handler invoked on a `'before-detach'` message. */ RunningSessions.prototype.onBeforeDetach = function (msg) { this.node.removeEventListener('click', this); }; /** * A message handler invoked on an `'update-request'` message. */ RunningSessions.prototype.onUpdateRequest = function (msg) { // Fetch common variables. var termSection = utils_1.findElement(this.node, TERMINALS_CLASS); var termList = utils_1.findElement(termSection, LIST_CLASS); var sessionSection = utils_1.findElement(this.node, SESSIONS_CLASS); var sessionList = utils_1.findElement(sessionSection, LIST_CLASS); var renderer = this._renderer; var kernelspecs = this._manager.kernelspecs.kernelspecs; // Remove any excess item nodes. while (termList.children.length > this._runningTerminals.length) { termList.removeChild(termList.firstChild); } while (sessionList.children.length > this._runningSessions.length) { sessionList.removeChild(sessionList.firstChild); } // Add any missing item nodes. while (termList.children.length < this._runningTerminals.length) { var node = renderer.createTerminalNode(); node.classList.add(ITEM_CLASS); termList.appendChild(node); } while (sessionList.children.length < this._runningSessions.length) { var node = renderer.createSessionNode(); node.classList.add(ITEM_CLASS); sessionList.appendChild(node); } // Populate the nodes. for (var i = 0; i < this._runningTerminals.length; i++) { var node = termList.children[i]; renderer.updateTerminalNode(node, this._runningTerminals[i]); } for (var i = 0; i < this._runningSessions.length; i++) { var node = sessionList.children[i]; var model = this._runningSessions[i]; var kernelName = kernelspecs[model.kernel.name].spec.display_name; renderer.updateSessionNode(node, model, kernelName); } }; /** * Handle the `'click'` event for the widget. * * #### Notes * This listener is attached to the document node. */ RunningSessions.prototype._evtClick = function (event) { var _this = this; // Fetch common variables. var termSection = utils_1.findElement(this.node, TERMINALS_CLASS); var termList = utils_1.findElement(termSection, LIST_CLASS); var sessionSection = utils_1.findElement(this.node, SESSIONS_CLASS); var sessionList = utils_1.findElement(sessionSection, LIST_CLASS); var refresh = utils_1.findElement(this.node, REFRESH_CLASS); var renderer = this._renderer; var clientX = event.clientX; var clientY = event.clientY; // Check for a refresh. if (phosphor_domutil_1.hitTest(refresh, clientX, clientY)) { this.refresh(); return; } // Check for a terminal item click. var index = utils_1.hitTestNodes(termList.children, clientX, clientY); if (index !== -1) { var node = termList.children[index]; var shutdown = renderer.getTerminalShutdown(node); var model = this._runningTerminals[index]; if (phosphor_domutil_1.hitTest(shutdown, clientX, clientY)) { this._manager.terminals.shutdown(model.name).then(function () { _this.refresh(); }); return; } this.terminalOpenRequested.emit(model); } // Check for a session item click. index = utils_1.hitTestNodes(sessionList.children, clientX, clientY); if (index !== -1) { var node = sessionList.children[index]; var shutdown = renderer.getSessionShutdown(node); var model = this._runningSessions[index]; if (phosphor_domutil_1.hitTest(shutdown, clientX, clientY)) { this._manager.sessions.shutdown(model.id).then(function () { _this.refresh(); }); return; } this.sessionOpenRequested.emit(model); } }; /** * Handle a change to the running sessions. */ RunningSessions.prototype._onSessionsChanged = function (sender, models) { // Strip out non-file backed sessions. this._runningSessions = []; for (var _i = 0, models_1 = models; _i < models_1.length; _i++) { var session = models_1[_i]; var name_1 = session.notebook.path.split('/').pop(); if (name_1.indexOf('.') !== -1) { this._runningSessions.push(session); } } this.update(); }; /** * Handle a change to the running terminals. */ RunningSessions.prototype._onTerminalsChanged = function (sender, models) { this._runningTerminals = models; this.update(); }; return RunningSessions; }(phosphor_widget_1.Widget)); exports.RunningSessions = RunningSessions; /** * The namespace for the `RunningSessions` class statics. */ var RunningSessions; (function (RunningSessions) { /** * The default implementation of `IRenderer`. */ var Renderer = (function () { function Renderer() { } /** * Create a fully populated header node for the terminals section. * * @returns A new node for a running terminal session header. */ Renderer.prototype.createTerminalHeaderNode = function () { var node = document.createElement('div'); node.textContent = 'Terminal Sessions'; return node; }; /** * Create a fully populated header node for the sessions section. * * @returns A new node for a running kernel session header. */ Renderer.prototype.createSessionHeaderNode = function () { var node = document.createElement('div'); node.textContent = 'Kernel Sessions'; return node; }; /** * Create a node for a running terminal session item. * * @returns A new node for a running terminal session item. * * #### Notes * The data in the node should be uninitialized. * * The `updateTerminalNode` method will be called for initialization. */ Renderer.prototype.createTerminalNode = function () { var node = document.createElement('li'); var icon = document.createElement('span'); icon.className = ITEM_ICON_CLASS + " " + TERMINAL_ICON_CLASS; var label = document.createElement('span'); label.className = ITEM_LABEL_CLASS; var shutdown = document.createElement('span'); shutdown.className = SHUTDOWN_BUTTON_CLASS; shutdown.textContent = 'SHUTDOWN'; node.appendChild(icon); node.appendChild(label); node.appendChild(shutdown); return node; }; /** * Create a node for a running kernel session item. * * @returns A new node for a running kernel session item. * * #### Notes * The data in the node should be uninitialized. * * The `updateSessionNode` method will be called for initialization. */ Renderer.prototype.createSessionNode = function () { var node = document.createElement('li'); var icon = document.createElement('span'); icon.className = ITEM_ICON_CLASS; var label = document.createElement('span'); label.className = ITEM_LABEL_CLASS; var kernel = document.createElement('span'); kernel.className = KERNEL_NAME_CLASS; var shutdown = document.createElement('span'); shutdown.className = SHUTDOWN_BUTTON_CLASS; shutdown.textContent = 'SHUTDOWN'; node.appendChild(icon); node.appendChild(label); node.appendChild(kernel); node.appendChild(shutdown); return node; }; /** * Get the shutdown node for a terminal node. * * @param node - A node created by a call to `createTerminalNode`. * * @returns The node representing the shutdown option. * * #### Notes * A click on this node is considered a shutdown request. * A click anywhere else on the node is considered an open request. */ Renderer.prototype.getTerminalShutdown = function (node) { return utils_1.findElement(node, SHUTDOWN_BUTTON_CLASS); }; /** * Get the shutdown node for a session node. * * @param node - A node created by a call to `createSessionNode`. * * @returns The node representing the shutdown option. * * #### Notes * A click on this node is considered a shutdown request. * A click anywhere else on the node is considered an open request. */ Renderer.prototype.getSessionShutdown = function (node) { return utils_1.findElement(node, SHUTDOWN_BUTTON_CLASS); }; /** * Populate a node with running terminal session data. * * @param node - A node created by a call to `createTerminalNode`. * * @param models - The list of terminal session models. * * #### Notes * This method should completely reset the state of the node to * reflect the data for the session models. */ Renderer.prototype.updateTerminalNode = function (node, model) { var label = utils_1.findElement(node, ITEM_LABEL_CLASS); label.textContent = "terminals/" + model.name; }; /** * Populate a node with running kernel session data. * * @param node - A node created by a call to `createSessionNode`. * * @param models - The list of kernel session models. * * @param kernelName - The kernel display name. * * #### Notes * This method should completely reset the state of the node to * reflect the data for the session models. */ Renderer.prototype.updateSessionNode = function (node, model, kernelName) { var icon = utils_1.findElement(node, ITEM_ICON_CLASS); if (model.notebook.path.indexOf('.ipynb') !== -1) { icon.className = ITEM_ICON_CLASS + " " + NOTEBOOK_ICON_CLASS; } else { icon.className = ITEM_ICON_CLASS + " " + FILE_ICON_CLASS; } var label = utils_1.findElement(node, ITEM_LABEL_CLASS); label.textContent = model.notebook.path.split('/').pop(); var kernel = utils_1.findElement(node, KERNEL_NAME_CLASS); kernel.textContent = kernelName; }; return Renderer; }()); RunningSessions.Renderer = Renderer; /** * The default `Renderer` instance. */ RunningSessions.defaultRenderer = new Renderer(); })(RunningSessions = exports.RunningSessions || (exports.RunningSessions = {})); /** * The namespace for the private module data. */ var Private; (function (Private) { /** * A signal emitted when a kernel session open is requested. */ Private.sessionOpenRequestedSignal = new phosphor_signaling_1.Signal(); /** * A signal emitted when a terminal session open is requested. */ Private.terminalOpenRequestedSignal = new phosphor_signaling_1.Signal(); })(Private || (Private = {}));