UNPKG

7.67 kBTypeScriptView Raw
1// Copyright (c) Jupyter Development Team.
2// Distributed under the terms of the Modified BSD License.
3
4import { Session } from '@jupyterlab/services';
5import { TextItem } from '@jupyterlab/statusbar';
6import {
7 ITranslator,
8 nullTranslator,
9 TranslationBundle
10} from '@jupyterlab/translation';
11import { VDomModel, VDomRenderer } from '@jupyterlab/ui-components';
12import { JSONArray, JSONExt } from '@lumino/coreutils';
13import React from 'react';
14import { ISessionContext } from './sessioncontext';
15
16/**
17 * Helper function to translate kernel statuses mapping by using
18 * input translator.
19 *
20 * @param translator - Language translator.
21 * @return The translated kernel status mapping.
22 */
23export function translateKernelStatuses(
24 translator?: ITranslator
25): Record<ISessionContext.KernelDisplayStatus, string> {
26 translator = translator || nullTranslator;
27 const trans = translator.load('jupyterlab');
28 const translated: Record<ISessionContext.KernelDisplayStatus, string> = {
29 unknown: trans.__('Unknown'),
30 starting: trans.__('Starting'),
31 idle: trans.__('Idle'),
32 busy: trans.__('Busy'),
33 terminating: trans.__('Terminating'),
34 restarting: trans.__('Restarting'),
35 autorestarting: trans.__('Autorestarting'),
36 dead: trans.__('Dead'),
37 connected: trans.__('Connected'),
38 connecting: trans.__('Connecting'),
39 disconnected: trans.__('Disconnected'),
40 initializing: trans.__('Initializing'),
41 '': ''
42 };
43 return translated;
44}
45
46/**
47 * A pure functional component for rendering kernel status.
48 */
49function KernelStatusComponent(
50 props: KernelStatusComponent.IProps
51): React.ReactElement<KernelStatusComponent.IProps> {
52 const translator = props.translator || nullTranslator;
53 const trans = translator.load('jupyterlab');
54 let statusText = '';
55 if (props.status) {
56 statusText = ` | ${props.status}`;
57 }
58 return (
59 <TextItem
60 onClick={props.handleClick}
61 source={`${props.kernelName}${statusText}`}
62 title={trans.__('Change kernel for %1', props.activityName)}
63 />
64 );
65}
66
67/**
68 * A namespace for KernelStatusComponent statics.
69 */
70namespace KernelStatusComponent {
71 /**
72 * Props for the kernel status component.
73 */
74 export interface IProps {
75 /**
76 * A click handler for the kernel status component. By default
77 * we have it bring up the kernel change dialog.
78 */
79 handleClick: () => void;
80
81 /**
82 * The name the kernel.
83 */
84 kernelName: string;
85
86 /**
87 * The name of the activity using the kernel.
88 */
89 activityName: string;
90
91 /**
92 * The status of the kernel.
93 */
94 status?: string;
95
96 /**
97 * The application language translator.
98 */
99 translator?: ITranslator;
100 }
101}
102
103/**
104 * A VDomRenderer widget for displaying the status of a kernel.
105 */
106export class KernelStatus extends VDomRenderer<KernelStatus.Model> {
107 /**
108 * Construct the kernel status widget.
109 */
110 constructor(opts: KernelStatus.IOptions, translator?: ITranslator) {
111 super(new KernelStatus.Model(translator));
112 this.translator = translator || nullTranslator;
113 this._handleClick = opts.onClick;
114 this.addClass('jp-mod-highlighted');
115 }
116
117 /**
118 * Render the kernel status item.
119 */
120 render(): JSX.Element | null {
121 if (this.model === null) {
122 return null;
123 } else {
124 return (
125 <KernelStatusComponent
126 status={this.model.status}
127 kernelName={this.model.kernelName}
128 activityName={this.model.activityName}
129 handleClick={this._handleClick}
130 translator={this.translator}
131 />
132 );
133 }
134 }
135
136 translator: ITranslator;
137 private _handleClick: () => void;
138}
139
140/**
141 * A namespace for KernelStatus statics.
142 */
143export namespace KernelStatus {
144 /**
145 * A VDomModel for the kernel status indicator.
146 */
147 export class Model extends VDomModel {
148 constructor(translator?: ITranslator) {
149 super();
150 translator = translator ?? nullTranslator;
151 this._trans = translator.load('jupyterlab');
152 this._statusNames = translateKernelStatuses(translator);
153 }
154
155 /**
156 * The name of the kernel.
157 */
158 get kernelName(): string {
159 return this._kernelName;
160 }
161
162 /**
163 * The current status of the kernel.
164 */
165 get status(): string | undefined {
166 return this._kernelStatus
167 ? this._statusNames[this._kernelStatus]
168 : undefined;
169 }
170
171 /**
172 * A display name for the activity.
173 */
174 get activityName(): string {
175 return this._activityName;
176 }
177 set activityName(val: string) {
178 const oldVal = this._activityName;
179 if (oldVal === val) {
180 return;
181 }
182 this._activityName = val;
183 this.stateChanged.emit();
184 }
185
186 /**
187 * The current client session associated with the kernel status indicator.
188 */
189 get sessionContext(): ISessionContext | null {
190 return this._sessionContext;
191 }
192 set sessionContext(sessionContext: ISessionContext | null) {
193 this._sessionContext?.statusChanged.disconnect(
194 this._onKernelStatusChanged,
195 this
196 );
197 this._sessionContext?.connectionStatusChanged.disconnect(
198 this._onKernelStatusChanged,
199 this
200 );
201 this._sessionContext?.kernelChanged.disconnect(
202 this._onKernelChanged,
203 this
204 );
205
206 const oldState = this._getAllState();
207 this._sessionContext = sessionContext;
208 this._kernelStatus = sessionContext?.kernelDisplayStatus;
209 this._kernelName =
210 sessionContext?.kernelDisplayName ?? this._trans.__('No Kernel');
211 sessionContext?.statusChanged.connect(this._onKernelStatusChanged, this);
212 sessionContext?.connectionStatusChanged.connect(
213 this._onKernelStatusChanged,
214 this
215 );
216 sessionContext?.kernelChanged.connect(this._onKernelChanged, this);
217 this._triggerChange(oldState, this._getAllState());
218 }
219
220 /**
221 * React to changes to the kernel status.
222 */
223 private _onKernelStatusChanged() {
224 this._kernelStatus = this._sessionContext?.kernelDisplayStatus;
225 this.stateChanged.emit(void 0);
226 }
227
228 /**
229 * React to changes in the kernel.
230 */
231 private _onKernelChanged(
232 _sessionContext: ISessionContext,
233 change: Session.ISessionConnection.IKernelChangedArgs
234 ) {
235 const oldState = this._getAllState();
236
237 // sync setting of status and display name
238 this._kernelStatus = this._sessionContext?.kernelDisplayStatus;
239 this._kernelName = _sessionContext.kernelDisplayName;
240 this._triggerChange(oldState, this._getAllState());
241 }
242
243 private _getAllState(): Private.State {
244 return [this._kernelName, this._kernelStatus, this._activityName];
245 }
246
247 private _triggerChange(oldState: Private.State, newState: Private.State) {
248 if (JSONExt.deepEqual(oldState as JSONArray, newState as JSONArray)) {
249 this.stateChanged.emit(void 0);
250 }
251 }
252
253 protected translation: ITranslator;
254 private _trans: TranslationBundle;
255 private _activityName: string = '';
256 private _kernelName: string = '';
257 private _kernelStatus: ISessionContext.KernelDisplayStatus | undefined = '';
258 private _sessionContext: ISessionContext | null = null;
259 private readonly _statusNames: Record<
260 ISessionContext.KernelDisplayStatus,
261 string
262 >;
263 }
264
265 /**
266 * Options for creating a KernelStatus object.
267 */
268 export interface IOptions {
269 /**
270 * A click handler for the item. By default
271 * we launch a kernel selection dialog.
272 */
273 onClick: () => void;
274 }
275}
276
277namespace Private {
278 export type State = [string, string | undefined, string];
279}