jupyterlab-emrys
Version:
A computational environment for Jupyter. Powered by Emrys
541 lines (540 loc) • 20.4 kB
JavaScript
// 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 = {}));