UNPKG

8.29 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, { KeyboardEvent } 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 onKeyDown={props.handleKeyDown}
62 source={`${props.kernelName}${statusText}`}
63 title={trans.__('Change kernel for %1', props.activityName)}
64 tabIndex={0}
65 />
66 );
67}
68
69/**
70 * A namespace for KernelStatusComponent statics.
71 */
72namespace KernelStatusComponent {
73 /**
74 * Props for the kernel status component.
75 */
76 export interface IProps {
77 /**
78 * A click handler for the kernel status component. By default
79 * we have it bring up the kernel change dialog.
80 */
81 handleClick: () => void;
82
83 /**
84 * A key down handler for the kernel status component. By default
85 * we have it bring up the kernel change dialog.
86 */
87 handleKeyDown: (event: KeyboardEvent<HTMLImageElement>) => void;
88
89 /**
90 * The name the kernel.
91 */
92 kernelName: string;
93
94 /**
95 * The name of the activity using the kernel.
96 */
97 activityName: string;
98
99 /**
100 * The status of the kernel.
101 */
102 status?: string;
103
104 /**
105 * The application language translator.
106 */
107 translator?: ITranslator;
108 }
109}
110
111/**
112 * A VDomRenderer widget for displaying the status of a kernel.
113 */
114export class KernelStatus extends VDomRenderer<KernelStatus.Model> {
115 /**
116 * Construct the kernel status widget.
117 */
118 constructor(opts: KernelStatus.IOptions, translator?: ITranslator) {
119 super(new KernelStatus.Model(translator));
120 this.translator = translator || nullTranslator;
121 this._handleClick = opts.onClick;
122 this._handleKeyDown = opts.onKeyDown;
123 this.addClass('jp-mod-highlighted');
124 }
125
126 /**
127 * Render the kernel status item.
128 */
129 render(): JSX.Element | null {
130 if (this.model === null) {
131 return null;
132 } else {
133 return (
134 <KernelStatusComponent
135 status={this.model.status}
136 kernelName={this.model.kernelName}
137 activityName={this.model.activityName}
138 handleClick={this._handleClick}
139 handleKeyDown={this._handleKeyDown}
140 translator={this.translator}
141 />
142 );
143 }
144 }
145
146 translator: ITranslator;
147 private _handleClick: () => void;
148 private _handleKeyDown: (event: KeyboardEvent<HTMLImageElement>) => void;
149}
150
151/**
152 * A namespace for KernelStatus statics.
153 */
154export namespace KernelStatus {
155 /**
156 * A VDomModel for the kernel status indicator.
157 */
158 export class Model extends VDomModel {
159 constructor(translator?: ITranslator) {
160 super();
161 translator = translator ?? nullTranslator;
162 this._trans = translator.load('jupyterlab');
163 this._statusNames = translateKernelStatuses(translator);
164 }
165
166 /**
167 * The name of the kernel.
168 */
169 get kernelName(): string {
170 return this._kernelName;
171 }
172
173 /**
174 * The current status of the kernel.
175 */
176 get status(): string | undefined {
177 return this._kernelStatus
178 ? this._statusNames[this._kernelStatus]
179 : undefined;
180 }
181
182 /**
183 * A display name for the activity.
184 */
185 get activityName(): string {
186 return this._activityName;
187 }
188 set activityName(val: string) {
189 const oldVal = this._activityName;
190 if (oldVal === val) {
191 return;
192 }
193 this._activityName = val;
194 this.stateChanged.emit();
195 }
196
197 /**
198 * The current client session associated with the kernel status indicator.
199 */
200 get sessionContext(): ISessionContext | null {
201 return this._sessionContext;
202 }
203 set sessionContext(sessionContext: ISessionContext | null) {
204 this._sessionContext?.statusChanged.disconnect(
205 this._onKernelStatusChanged,
206 this
207 );
208 this._sessionContext?.connectionStatusChanged.disconnect(
209 this._onKernelStatusChanged,
210 this
211 );
212 this._sessionContext?.kernelChanged.disconnect(
213 this._onKernelChanged,
214 this
215 );
216
217 const oldState = this._getAllState();
218 this._sessionContext = sessionContext;
219 this._kernelStatus = sessionContext?.kernelDisplayStatus;
220 this._kernelName =
221 sessionContext?.kernelDisplayName ?? this._trans.__('No Kernel');
222 sessionContext?.statusChanged.connect(this._onKernelStatusChanged, this);
223 sessionContext?.connectionStatusChanged.connect(
224 this._onKernelStatusChanged,
225 this
226 );
227 sessionContext?.kernelChanged.connect(this._onKernelChanged, this);
228 this._triggerChange(oldState, this._getAllState());
229 }
230
231 /**
232 * React to changes to the kernel status.
233 */
234 private _onKernelStatusChanged() {
235 this._kernelStatus = this._sessionContext?.kernelDisplayStatus;
236 this.stateChanged.emit(void 0);
237 }
238
239 /**
240 * React to changes in the kernel.
241 */
242 private _onKernelChanged(
243 _sessionContext: ISessionContext,
244 change: Session.ISessionConnection.IKernelChangedArgs
245 ) {
246 const oldState = this._getAllState();
247
248 // sync setting of status and display name
249 this._kernelStatus = this._sessionContext?.kernelDisplayStatus;
250 this._kernelName = _sessionContext.kernelDisplayName;
251 this._triggerChange(oldState, this._getAllState());
252 }
253
254 private _getAllState(): Private.State {
255 return [this._kernelName, this._kernelStatus, this._activityName];
256 }
257
258 private _triggerChange(oldState: Private.State, newState: Private.State) {
259 if (JSONExt.deepEqual(oldState as JSONArray, newState as JSONArray)) {
260 this.stateChanged.emit(void 0);
261 }
262 }
263
264 protected translation: ITranslator;
265 private _trans: TranslationBundle;
266 private _activityName: string = '';
267 private _kernelName: string = '';
268 private _kernelStatus: ISessionContext.KernelDisplayStatus | undefined = '';
269 private _sessionContext: ISessionContext | null = null;
270 private readonly _statusNames: Record<
271 ISessionContext.KernelDisplayStatus,
272 string
273 >;
274 }
275
276 /**
277 * Options for creating a KernelStatus object.
278 */
279 export interface IOptions {
280 /**
281 * A click handler for the item. By default
282 * we launch a kernel selection dialog.
283 */
284 onClick: () => void;
285
286 /**
287 * A key press handler for the item. By default
288 * we launch a kernel selection dialog.
289 */
290 onKeyDown: (event: KeyboardEvent<HTMLImageElement>) => void;
291 }
292}
293
294namespace Private {
295 export type State = [string, string | undefined, string];
296}