jupyter-specta 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/app.js +1 -1
- package/lib/components/cellSkeleton.d.ts +6 -0
- package/lib/components/cellSkeleton.js +19 -0
- package/lib/components/divider.d.ts +2 -0
- package/lib/components/divider.js +4 -0
- package/lib/components/icon/gear.d.ts +2 -0
- package/lib/components/icon/gear.js +17 -0
- package/lib/components/iconButton.d.ts +8 -0
- package/lib/components/iconButton.js +4 -0
- package/lib/document/factory.d.ts +5 -1
- package/lib/document/factory.js +12 -3
- package/lib/document/plugin.js +5 -1
- package/lib/extension_plugins.js +7 -1
- package/lib/layout/article.d.ts +12 -0
- package/lib/layout/article.js +35 -0
- package/lib/layout/default.js +2 -5
- package/lib/layout/layout_registry.d.ts +1 -0
- package/lib/layout/layout_registry.js +6 -0
- package/lib/layout/plugin.js +5 -0
- package/lib/shell.js +0 -1
- package/lib/specta_cell_output.d.ts +9 -2
- package/lib/specta_cell_output.js +20 -1
- package/lib/specta_model.d.ts +1 -2
- package/lib/specta_model.js +74 -12
- package/lib/specta_widget.d.ts +5 -1
- package/lib/specta_widget.js +23 -7
- package/lib/specta_widget_factory.d.ts +2 -1
- package/lib/specta_widget_factory.js +6 -2
- package/lib/token.d.ts +13 -0
- package/lib/tool.d.ts +3 -1
- package/lib/tool.js +5 -16
- package/lib/topbar/kernelStatus.d.ts +28 -0
- package/lib/topbar/kernelStatus.js +20 -0
- package/lib/topbar/plugin.d.ts +5 -0
- package/lib/topbar/plugin.js +32 -0
- package/lib/topbar/settingDialog.d.ts +7 -0
- package/lib/topbar/settingDialog.js +73 -0
- package/lib/topbar/widget.d.ts +9 -0
- package/lib/topbar/widget.js +41 -0
- package/package.json +18 -11
- package/style/article.css +314 -0
- package/style/base.css +125 -0
- package/style/index.css +2 -0
- package/style/index.js +3 -1
- package/style/skeleton.css +87 -0
- package/style/style.css +9 -4
package/lib/app.js
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export function SkeletonBarChart({ bars = 5 }) {
|
|
3
|
+
return (React.createElement("div", { className: "skeleton-bar-chart vertical" },
|
|
4
|
+
React.createElement("div", { className: "skeleton-label" }, "Executing cell"),
|
|
5
|
+
Array.from({ length: bars }).map((_, i) => (React.createElement("div", { key: i, className: "bar vertical-bar", style: { animationDelay: `${i * 0.4}s` } })))));
|
|
6
|
+
}
|
|
7
|
+
export function SkeletonLineChart() {
|
|
8
|
+
return (React.createElement("div", { className: "skeleton-line-chart" },
|
|
9
|
+
React.createElement("div", { className: "skeleton-label" }, "Executing cell"),
|
|
10
|
+
React.createElement("svg", { viewBox: "0 0 100 40", preserveAspectRatio: "none" },
|
|
11
|
+
React.createElement("polyline", { points: "0,30 20,20 40,25 60,15 80,10 100,20" }))));
|
|
12
|
+
}
|
|
13
|
+
export function RandomSkeleton() {
|
|
14
|
+
const random = Math.random();
|
|
15
|
+
if (random < 0.5) {
|
|
16
|
+
return React.createElement(SkeletonLineChart, null);
|
|
17
|
+
}
|
|
18
|
+
return React.createElement(SkeletonBarChart, null);
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React from 'react';
|
|
13
|
+
export const GearIcon = (_a) => {
|
|
14
|
+
var props = __rest(_a, []);
|
|
15
|
+
return (React.createElement("svg", Object.assign({ xmlns: "http://www.w3.org/2000/svg", height: "24px", viewBox: "0 -960 960 960", width: "24px" }, props),
|
|
16
|
+
React.createElement("path", { d: "m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" })));
|
|
17
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare const IconButton: React.ForwardRefExoticComponent<{
|
|
3
|
+
icon: JSX.Element;
|
|
4
|
+
onClick: () => void;
|
|
5
|
+
title?: string | undefined;
|
|
6
|
+
disabled?: boolean | undefined;
|
|
7
|
+
className?: string | undefined;
|
|
8
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
export const IconButton = forwardRef(({ icon, onClick, title, disabled, className }, ref) => {
|
|
3
|
+
return (React.createElement("button", { ref: ref, className: `jp-Button specta-icon-button ${className !== null && className !== void 0 ? className : ''}`, title: title, disabled: disabled, onClick: onClick }, icon));
|
|
4
|
+
});
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { IThemeManager } from '@jupyterlab/apputils';
|
|
1
2
|
import { ABCWidgetFactory, DocumentRegistry } from '@jupyterlab/docregistry';
|
|
2
|
-
import { NotebookSpectaDocWidget } from './widget';
|
|
3
3
|
import { INotebookModel } from '@jupyterlab/notebook';
|
|
4
4
|
import { SpectaWidgetFactory } from '../specta_widget_factory';
|
|
5
|
+
import { ISpectaLayoutRegistry } from '../token';
|
|
6
|
+
import { NotebookSpectaDocWidget } from './widget';
|
|
5
7
|
interface IOptions extends DocumentRegistry.IWidgetFactoryOptions {
|
|
6
8
|
spectaWidgetFactory: SpectaWidgetFactory;
|
|
9
|
+
layoutRegistry?: ISpectaLayoutRegistry;
|
|
10
|
+
themeManager?: IThemeManager;
|
|
7
11
|
}
|
|
8
12
|
export declare class NotebookGridWidgetFactory extends ABCWidgetFactory<NotebookSpectaDocWidget, INotebookModel> {
|
|
9
13
|
constructor(options: IOptions);
|
package/lib/document/factory.js
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
import { ABCWidgetFactory } from '@jupyterlab/docregistry';
|
|
2
|
+
import { ReactWidget } from '@jupyterlab/ui-components';
|
|
3
|
+
import { Panel } from '@lumino/widgets';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { isSpectaApp } from '../tool';
|
|
6
|
+
import { TopbarElement } from '../topbar/widget';
|
|
2
7
|
import { NotebookSpectaDocWidget } from './widget';
|
|
3
|
-
import { Widget } from '@lumino/widgets';
|
|
4
8
|
export class NotebookGridWidgetFactory extends ABCWidgetFactory {
|
|
5
9
|
constructor(options) {
|
|
6
10
|
super(options);
|
|
7
11
|
this._spectaWidgetFactory = options.spectaWidgetFactory;
|
|
8
12
|
}
|
|
9
13
|
createNewWidget(context) {
|
|
10
|
-
const content = new
|
|
14
|
+
const content = new Panel();
|
|
11
15
|
content.addClass('jp-specta-notebook-panel');
|
|
16
|
+
if (!isSpectaApp()) {
|
|
17
|
+
// Not a specta app, add topbar to document widget
|
|
18
|
+
const topbar = ReactWidget.create(React.createElement(TopbarElement, null));
|
|
19
|
+
content.addWidget(topbar);
|
|
20
|
+
}
|
|
12
21
|
context.ready.then(async () => {
|
|
13
22
|
const spectaWidget = await this._spectaWidgetFactory.createNew({
|
|
14
23
|
context
|
|
15
24
|
});
|
|
16
25
|
if (spectaWidget) {
|
|
17
|
-
|
|
26
|
+
content.addWidget(spectaWidget);
|
|
18
27
|
}
|
|
19
28
|
});
|
|
20
29
|
const widget = new NotebookSpectaDocWidget({
|
package/lib/document/plugin.js
CHANGED
|
@@ -6,9 +6,12 @@ import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
|
6
6
|
import { createFileBrowser, hideAppLoadingIndicator, isSpectaApp, registerDocumentFactory } from '../tool';
|
|
7
7
|
import { ISpectaDocTracker, ISpectaLayoutRegistry } from '../token';
|
|
8
8
|
import { IKernelSpecManager } from '@jupyterlab/services';
|
|
9
|
+
import { PageConfig } from '@jupyterlab/coreutils';
|
|
9
10
|
const activate = (app, rendermime, tracker, editorServices, contentFactory, spectaLayoutRegistry) => {
|
|
11
|
+
var _a;
|
|
10
12
|
const namespace = 'specta';
|
|
11
13
|
const spectaTracker = new WidgetTracker({ namespace });
|
|
14
|
+
const spectaConfig = JSON.parse((_a = PageConfig.getOption('spectaConfig')) !== null && _a !== void 0 ? _a : '{}');
|
|
12
15
|
registerDocumentFactory({
|
|
13
16
|
factoryName: 'specta',
|
|
14
17
|
app,
|
|
@@ -17,7 +20,8 @@ const activate = (app, rendermime, tracker, editorServices, contentFactory, spec
|
|
|
17
20
|
editorServices,
|
|
18
21
|
contentFactory,
|
|
19
22
|
spectaTracker,
|
|
20
|
-
spectaLayoutRegistry
|
|
23
|
+
spectaLayoutRegistry,
|
|
24
|
+
spectaConfig
|
|
21
25
|
});
|
|
22
26
|
return spectaTracker;
|
|
23
27
|
};
|
package/lib/extension_plugins.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { spectaDocument, spectaOpener } from './document/plugin';
|
|
2
2
|
import { spectaLayoutRegistry } from './layout/plugin';
|
|
3
|
+
import { topbarPlugin } from './topbar/plugin';
|
|
3
4
|
export * from './tool';
|
|
4
5
|
export * from './token';
|
|
5
|
-
export default [
|
|
6
|
+
export default [
|
|
7
|
+
spectaDocument,
|
|
8
|
+
spectaOpener,
|
|
9
|
+
spectaLayoutRegistry,
|
|
10
|
+
topbarPlugin
|
|
11
|
+
];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Panel } from '@lumino/widgets';
|
|
2
|
+
import { SpectaCellOutput } from '../specta_cell_output';
|
|
3
|
+
import * as nbformat from '@jupyterlab/nbformat';
|
|
4
|
+
import { ISpectaLayout } from '../token';
|
|
5
|
+
export declare class ArticleLayout implements ISpectaLayout {
|
|
6
|
+
render(options: {
|
|
7
|
+
host: Panel;
|
|
8
|
+
items: SpectaCellOutput[];
|
|
9
|
+
notebook: nbformat.INotebookContent;
|
|
10
|
+
readyCallback: () => Promise<void>;
|
|
11
|
+
}): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Panel } from '@lumino/widgets';
|
|
2
|
+
class HostPanel extends Panel {
|
|
3
|
+
constructor() {
|
|
4
|
+
super();
|
|
5
|
+
this.addClass('specta-article-host-widget');
|
|
6
|
+
this._outputs = new Panel();
|
|
7
|
+
this._outputs.addClass('specta-article-outputs-panel');
|
|
8
|
+
this.addWidget(this._outputs);
|
|
9
|
+
}
|
|
10
|
+
addOutput(widget) {
|
|
11
|
+
this._outputs.addWidget(widget);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class ArticleLayout {
|
|
15
|
+
async render(options) {
|
|
16
|
+
const { host, items, readyCallback } = options;
|
|
17
|
+
const hostPanel = new HostPanel();
|
|
18
|
+
for (const el of items) {
|
|
19
|
+
const cellModel = el.info.cellModel;
|
|
20
|
+
const info = el.info;
|
|
21
|
+
if ((cellModel === null || cellModel === void 0 ? void 0 : cellModel.cell_type) === 'code') {
|
|
22
|
+
if (!info.hidden) {
|
|
23
|
+
hostPanel.addOutput(el);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
if (!info.hidden) {
|
|
28
|
+
hostPanel.addOutput(el);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
host.addWidget(hostPanel);
|
|
33
|
+
await readyCallback();
|
|
34
|
+
}
|
|
35
|
+
}
|
package/lib/layout/default.js
CHANGED
|
@@ -2,14 +2,11 @@ export class DefaultLayout {
|
|
|
2
2
|
async render(options) {
|
|
3
3
|
const { host, items, readyCallback } = options;
|
|
4
4
|
for (const el of items) {
|
|
5
|
-
const outputNode = el.cellOutput.node;
|
|
6
5
|
const cellModel = el.info.cellModel;
|
|
7
6
|
const info = el.info;
|
|
8
7
|
if ((cellModel === null || cellModel === void 0 ? void 0 : cellModel.cell_type) === 'code') {
|
|
9
|
-
if (
|
|
10
|
-
|
|
11
|
-
host.addWidget(el);
|
|
12
|
-
}
|
|
8
|
+
if (!info.hidden) {
|
|
9
|
+
host.addWidget(el);
|
|
13
10
|
}
|
|
14
11
|
}
|
|
15
12
|
else {
|
|
@@ -12,6 +12,7 @@ export declare class SpectaLayoutRegistry implements ISpectaLayoutRegistry {
|
|
|
12
12
|
layout: ISpectaLayout;
|
|
13
13
|
}>;
|
|
14
14
|
get(name: string): ISpectaLayout | undefined;
|
|
15
|
+
getDefaultLayout(): ISpectaLayout;
|
|
15
16
|
setSelectedLayout(name: string): void;
|
|
16
17
|
register(name: string, layout: ISpectaLayout): void;
|
|
17
18
|
allLayouts(): string[];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Signal } from '@lumino/signaling';
|
|
2
2
|
import { DefaultLayout } from './default';
|
|
3
|
+
import { ArticleLayout } from './article';
|
|
3
4
|
export class SpectaLayoutRegistry {
|
|
4
5
|
constructor() {
|
|
5
6
|
this._registry = new Map();
|
|
@@ -8,6 +9,7 @@ export class SpectaLayoutRegistry {
|
|
|
8
9
|
const defaultLayout = new DefaultLayout();
|
|
9
10
|
this._registry = new Map();
|
|
10
11
|
this._registry.set('default', defaultLayout);
|
|
12
|
+
this._registry.set('article', new ArticleLayout());
|
|
11
13
|
this._selectedLayout = {
|
|
12
14
|
name: 'default',
|
|
13
15
|
layout: defaultLayout
|
|
@@ -25,11 +27,15 @@ export class SpectaLayoutRegistry {
|
|
|
25
27
|
get(name) {
|
|
26
28
|
return this._registry.get(name);
|
|
27
29
|
}
|
|
30
|
+
getDefaultLayout() {
|
|
31
|
+
return this._registry.get('default');
|
|
32
|
+
}
|
|
28
33
|
setSelectedLayout(name) {
|
|
29
34
|
if (!this._registry.has(name)) {
|
|
30
35
|
throw new Error(`Layout with name ${name} does not exist`);
|
|
31
36
|
}
|
|
32
37
|
this._selectedLayout = { name, layout: this._registry.get(name) };
|
|
38
|
+
this._selectedLayoutChanged.emit(this._selectedLayout);
|
|
33
39
|
}
|
|
34
40
|
register(name, layout) {
|
|
35
41
|
if (this._registry.has(name)) {
|
package/lib/layout/plugin.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { SpectaLayoutRegistry } from './layout_registry';
|
|
2
2
|
import { ISpectaLayoutRegistry } from '../token';
|
|
3
|
+
import { PageConfig } from '@jupyterlab/coreutils';
|
|
3
4
|
export const spectaLayoutRegistry = {
|
|
4
5
|
id: 'specta:layout-registry',
|
|
5
6
|
autoStart: true,
|
|
6
7
|
provides: ISpectaLayoutRegistry,
|
|
7
8
|
activate: (app) => {
|
|
9
|
+
var _a, _b;
|
|
8
10
|
const layoutRegistry = new SpectaLayoutRegistry();
|
|
11
|
+
const spectaConfig = JSON.parse((_a = PageConfig.getOption('spectaConfig')) !== null && _a !== void 0 ? _a : '{}');
|
|
12
|
+
const defaultLayout = (_b = spectaConfig.layout) !== null && _b !== void 0 ? _b : 'default';
|
|
13
|
+
layoutRegistry.setSelectedLayout(defaultLayout);
|
|
9
14
|
return layoutRegistry;
|
|
10
15
|
}
|
|
11
16
|
};
|
package/lib/shell.js
CHANGED
|
@@ -30,7 +30,6 @@ export class SpectaShell extends Widget {
|
|
|
30
30
|
topHandler.panel.id = 'specta-top-panel';
|
|
31
31
|
topHandler.panel.node.setAttribute('role', 'banner');
|
|
32
32
|
BoxLayout.setStretch(topHandler.panel, 0);
|
|
33
|
-
topHandler.panel.hide();
|
|
34
33
|
rootLayout.addWidget(topHandler.panel);
|
|
35
34
|
const hboxPanel = (this._mainPanel = new BoxPanel());
|
|
36
35
|
hboxPanel.id = 'jp-main-content-panel';
|
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
import { Panel, Widget } from '@lumino/widgets';
|
|
2
1
|
import * as nbformat from '@jupyterlab/nbformat';
|
|
2
|
+
import { Panel, Widget } from '@lumino/widgets';
|
|
3
3
|
export interface ICellInfo {
|
|
4
4
|
hidden?: boolean;
|
|
5
5
|
cellModel?: nbformat.ICell;
|
|
6
6
|
}
|
|
7
7
|
export declare class SpectaCellOutput extends Panel {
|
|
8
|
-
constructor(cellIdentity
|
|
8
|
+
constructor({ cellIdentity, cell, sourceCell, info }: {
|
|
9
|
+
cellIdentity: string;
|
|
10
|
+
cell: Widget;
|
|
11
|
+
sourceCell?: Widget;
|
|
12
|
+
info: ICellInfo;
|
|
13
|
+
});
|
|
9
14
|
readonly cellIdentity: string;
|
|
10
15
|
get cellOutput(): Widget;
|
|
11
16
|
get info(): ICellInfo;
|
|
17
|
+
removePlaceholder(): void;
|
|
12
18
|
private _info;
|
|
13
19
|
private _cellOutput;
|
|
20
|
+
private _placeholder?;
|
|
14
21
|
}
|
|
@@ -1,19 +1,32 @@
|
|
|
1
|
+
import { ReactWidget } from '@jupyterlab/ui-components';
|
|
1
2
|
import { Panel } from '@lumino/widgets';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { RandomSkeleton } from './components/cellSkeleton';
|
|
2
5
|
export class SpectaCellOutput extends Panel {
|
|
3
|
-
constructor(cellIdentity, cell, info) {
|
|
6
|
+
constructor({ cellIdentity, cell, sourceCell, info }) {
|
|
7
|
+
var _a;
|
|
4
8
|
super();
|
|
5
9
|
this._info = {};
|
|
10
|
+
this._placeholder = undefined;
|
|
6
11
|
this.removeClass('lm-Widget');
|
|
7
12
|
this.removeClass('p-Widget');
|
|
8
13
|
this.addClass('specta-cell-output');
|
|
9
14
|
const content = new Panel();
|
|
10
15
|
content.addClass('specta-cell-content');
|
|
11
16
|
cell.addClass('specta-item-widget');
|
|
17
|
+
if (sourceCell) {
|
|
18
|
+
content.addWidget(sourceCell);
|
|
19
|
+
}
|
|
12
20
|
content.addWidget(cell);
|
|
13
21
|
this.addWidget(content);
|
|
14
22
|
this._cellOutput = cell;
|
|
15
23
|
this.cellIdentity = cellIdentity;
|
|
16
24
|
this._info = info !== null && info !== void 0 ? info : {};
|
|
25
|
+
if (((_a = info.cellModel) === null || _a === void 0 ? void 0 : _a.cell_type) === 'code') {
|
|
26
|
+
this._placeholder = ReactWidget.create(React.createElement(RandomSkeleton, null));
|
|
27
|
+
this._placeholder.addClass('specta-cell-placeholder');
|
|
28
|
+
this.addWidget(this._placeholder);
|
|
29
|
+
}
|
|
17
30
|
}
|
|
18
31
|
get cellOutput() {
|
|
19
32
|
return this._cellOutput;
|
|
@@ -21,4 +34,10 @@ export class SpectaCellOutput extends Panel {
|
|
|
21
34
|
get info() {
|
|
22
35
|
return this._info;
|
|
23
36
|
}
|
|
37
|
+
removePlaceholder() {
|
|
38
|
+
var _a;
|
|
39
|
+
if (this._placeholder) {
|
|
40
|
+
(_a = this._placeholder) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
24
43
|
}
|
package/lib/specta_model.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { ICellModel } from '@jupyterlab/cells';
|
|
|
2
2
|
import { IEditorMimeTypeService, IEditorServices } from '@jupyterlab/codeeditor';
|
|
3
3
|
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
|
4
4
|
import { CellList, INotebookModel, INotebookTracker, NotebookPanel, StaticNotebook } from '@jupyterlab/notebook';
|
|
5
|
-
import { SimplifiedOutputArea } from '@jupyterlab/outputarea';
|
|
6
5
|
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
7
6
|
import { ServiceManager } from '@jupyterlab/services';
|
|
8
7
|
import { IExecuteReplyMsg } from '@jupyterlab/services/lib/kernel/messages';
|
|
@@ -22,7 +21,7 @@ export declare class AppModel {
|
|
|
22
21
|
get panel(): NotebookPanel | undefined;
|
|
23
22
|
initialize(): Promise<void>;
|
|
24
23
|
createCell(cellModel: ICellModel): SpectaCellOutput;
|
|
25
|
-
executeCell(cell: ICellModel,
|
|
24
|
+
executeCell(cell: ICellModel, outputWrapper: SpectaCellOutput): Promise<IExecuteReplyMsg | undefined>;
|
|
26
25
|
private _notebookPanel?;
|
|
27
26
|
private _context;
|
|
28
27
|
private _isDisposed;
|
package/lib/specta_model.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { MarkdownCell, RawCell } from '@jupyterlab/cells';
|
|
1
|
+
import { CodeCell, MarkdownCell, RawCell } from '@jupyterlab/cells';
|
|
2
2
|
import { OutputAreaModel, SimplifiedOutputArea } from '@jupyterlab/outputarea';
|
|
3
3
|
import { createNotebookPanel } from './create_notebook_panel';
|
|
4
4
|
import { SpectaCellOutput } from './specta_cell_output';
|
|
5
|
+
import { PromiseDelegate } from '@lumino/coreutils';
|
|
6
|
+
import { SPECTA_CELL_VISIBLE_TAG } from './tool';
|
|
5
7
|
export const VIEW = 'grid_default';
|
|
6
8
|
export class AppModel {
|
|
7
9
|
constructor(options) {
|
|
@@ -38,16 +40,40 @@ export class AppModel {
|
|
|
38
40
|
return this._notebookPanel;
|
|
39
41
|
}
|
|
40
42
|
async initialize() {
|
|
41
|
-
var _a;
|
|
43
|
+
var _a, _b;
|
|
44
|
+
const pd = new PromiseDelegate();
|
|
42
45
|
await ((_a = this._context) === null || _a === void 0 ? void 0 : _a.sessionContext.ready);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
const connectKernel = () => {
|
|
47
|
+
pd.resolve();
|
|
48
|
+
this._notebookPanel = createNotebookPanel({
|
|
49
|
+
context: this._context,
|
|
50
|
+
rendermime: this.options.rendermime,
|
|
51
|
+
editorServices: this.options.editorServices
|
|
52
|
+
});
|
|
53
|
+
this.options.tracker.widgetAdded.emit(this._notebookPanel);
|
|
54
|
+
};
|
|
55
|
+
const kernel = (_b = this._context.sessionContext.session) === null || _b === void 0 ? void 0 : _b.kernel;
|
|
56
|
+
if (kernel) {
|
|
57
|
+
const status = kernel.status;
|
|
58
|
+
if (status !== 'unknown') {
|
|
59
|
+
// Connected to an existing kernel.
|
|
60
|
+
connectKernel();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
this._context.sessionContext.connectionStatusChanged.connect((_, status) => {
|
|
65
|
+
var _a;
|
|
66
|
+
if (status === 'connected') {
|
|
67
|
+
const kernel = (_a = this._context.sessionContext.session) === null || _a === void 0 ? void 0 : _a.kernel;
|
|
68
|
+
if (kernel) {
|
|
69
|
+
connectKernel();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}, this);
|
|
73
|
+
return pd.promise;
|
|
49
74
|
}
|
|
50
75
|
createCell(cellModel) {
|
|
76
|
+
var _a, _b;
|
|
51
77
|
let item;
|
|
52
78
|
const cellModelJson = cellModel.toJSON();
|
|
53
79
|
const info = {
|
|
@@ -55,12 +81,35 @@ export class AppModel {
|
|
|
55
81
|
};
|
|
56
82
|
switch (cellModel.type) {
|
|
57
83
|
case 'code': {
|
|
84
|
+
cellModel.setMetadata('editable', false);
|
|
85
|
+
const codeCell = new CodeCell({
|
|
86
|
+
model: cellModel,
|
|
87
|
+
rendermime: this.options.rendermime,
|
|
88
|
+
contentFactory: this.options.contentFactory,
|
|
89
|
+
editorConfig: {
|
|
90
|
+
lineNumbers: false,
|
|
91
|
+
lineWrap: false,
|
|
92
|
+
tabFocusable: false,
|
|
93
|
+
editable: false
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
codeCell.loadEditableState();
|
|
58
97
|
const outputareamodel = new OutputAreaModel({ trusted: true });
|
|
59
98
|
const out = new SimplifiedOutputArea({
|
|
60
99
|
model: outputareamodel,
|
|
61
100
|
rendermime: this.options.rendermime
|
|
62
101
|
});
|
|
63
|
-
|
|
102
|
+
const tags = ((_b = (_a = cellModel === null || cellModel === void 0 ? void 0 : cellModel.metadata) === null || _a === void 0 ? void 0 : _a.tags) !== null && _b !== void 0 ? _b : []);
|
|
103
|
+
let sourceCell;
|
|
104
|
+
if (tags.includes(SPECTA_CELL_VISIBLE_TAG)) {
|
|
105
|
+
sourceCell = codeCell;
|
|
106
|
+
}
|
|
107
|
+
item = new SpectaCellOutput({
|
|
108
|
+
cellIdentity: cellModel.id,
|
|
109
|
+
cell: out,
|
|
110
|
+
sourceCell,
|
|
111
|
+
info
|
|
112
|
+
});
|
|
64
113
|
break;
|
|
65
114
|
}
|
|
66
115
|
case 'markdown': {
|
|
@@ -70,11 +119,16 @@ export class AppModel {
|
|
|
70
119
|
contentFactory: this.options.contentFactory,
|
|
71
120
|
editorConfig: this.options.editorConfig.markdown
|
|
72
121
|
});
|
|
122
|
+
markdownCell.initializeState();
|
|
73
123
|
markdownCell.inputHidden = false;
|
|
74
124
|
markdownCell.rendered = true;
|
|
75
125
|
Private.removeElements(markdownCell.node, 'jp-Collapser');
|
|
76
126
|
Private.removeElements(markdownCell.node, 'jp-InputPrompt');
|
|
77
|
-
item = new SpectaCellOutput(
|
|
127
|
+
item = new SpectaCellOutput({
|
|
128
|
+
cellIdentity: cellModel.id,
|
|
129
|
+
cell: markdownCell,
|
|
130
|
+
info
|
|
131
|
+
});
|
|
78
132
|
break;
|
|
79
133
|
}
|
|
80
134
|
default: {
|
|
@@ -86,18 +140,26 @@ export class AppModel {
|
|
|
86
140
|
rawCell.inputHidden = false;
|
|
87
141
|
Private.removeElements(rawCell.node, 'jp-Collapser');
|
|
88
142
|
Private.removeElements(rawCell.node, 'jp-InputPrompt');
|
|
89
|
-
item = new SpectaCellOutput(
|
|
143
|
+
item = new SpectaCellOutput({
|
|
144
|
+
cellIdentity: cellModel.id,
|
|
145
|
+
cell: rawCell,
|
|
146
|
+
info
|
|
147
|
+
});
|
|
90
148
|
break;
|
|
91
149
|
}
|
|
92
150
|
}
|
|
93
151
|
return item;
|
|
94
152
|
}
|
|
95
|
-
async executeCell(cell,
|
|
153
|
+
async executeCell(cell, outputWrapper) {
|
|
96
154
|
if (cell.type !== 'code' || !this._context) {
|
|
97
155
|
return;
|
|
98
156
|
}
|
|
157
|
+
const output = outputWrapper.cellOutput;
|
|
99
158
|
const source = cell.sharedModel.source;
|
|
100
159
|
const rep = await SimplifiedOutputArea.execute(source, output, this._context.sessionContext);
|
|
160
|
+
output.future.done.then(() => {
|
|
161
|
+
outputWrapper.removePlaceholder();
|
|
162
|
+
});
|
|
101
163
|
return rep;
|
|
102
164
|
}
|
|
103
165
|
}
|
package/lib/specta_widget.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Message } from '@lumino/messaging';
|
|
2
2
|
import { Panel } from '@lumino/widgets';
|
|
3
3
|
import { AppModel } from './specta_model';
|
|
4
|
-
import { ISpectaLayoutRegistry } from './token';
|
|
4
|
+
import { ISpectaAppConfig, ISpectaLayoutRegistry } from './token';
|
|
5
5
|
export declare class AppWidget extends Panel {
|
|
6
6
|
constructor(options: AppWidget.IOptions);
|
|
7
7
|
/**
|
|
@@ -13,11 +13,14 @@ export declare class AppWidget extends Panel {
|
|
|
13
13
|
dispose(): void;
|
|
14
14
|
render(): Promise<void>;
|
|
15
15
|
protected onCloseRequest(msg: Message): void;
|
|
16
|
+
private _onSelectedLayoutChanged;
|
|
16
17
|
private _model;
|
|
17
18
|
private _ready;
|
|
18
19
|
private _host;
|
|
19
20
|
private _layoutRegistry;
|
|
20
21
|
private _loaderHost?;
|
|
22
|
+
private _outputs;
|
|
23
|
+
private _spectaAppConfig;
|
|
21
24
|
}
|
|
22
25
|
export declare namespace AppWidget {
|
|
23
26
|
interface IOptions {
|
|
@@ -25,5 +28,6 @@ export declare namespace AppWidget {
|
|
|
25
28
|
label: string;
|
|
26
29
|
model: AppModel;
|
|
27
30
|
layoutRegistry: ISpectaLayoutRegistry;
|
|
31
|
+
spectaConfig: ISpectaAppConfig;
|
|
28
32
|
}
|
|
29
33
|
}
|
package/lib/specta_widget.js
CHANGED
|
@@ -5,12 +5,13 @@ export class AppWidget extends Panel {
|
|
|
5
5
|
constructor(options) {
|
|
6
6
|
super();
|
|
7
7
|
this._ready = new PromiseDelegate();
|
|
8
|
+
this._outputs = [];
|
|
8
9
|
this.node.id = options.id;
|
|
9
10
|
this.title.label = options.label;
|
|
10
11
|
this.title.closable = true;
|
|
11
12
|
this._model = options.model;
|
|
13
|
+
this._spectaAppConfig = options.spectaConfig;
|
|
12
14
|
this._layoutRegistry = options.layoutRegistry;
|
|
13
|
-
this.node.style.padding = '5px';
|
|
14
15
|
this._host = new Panel();
|
|
15
16
|
this._host.addClass('specta-output-host');
|
|
16
17
|
this.addWidget(this._host);
|
|
@@ -24,6 +25,7 @@ export class AppWidget extends Panel {
|
|
|
24
25
|
.catch(console.error)
|
|
25
26
|
.then(() => window.dispatchEvent(new Event('resize')));
|
|
26
27
|
});
|
|
28
|
+
this._layoutRegistry.selectedLayoutChanged.connect(this._onSelectedLayoutChanged, this);
|
|
27
29
|
}
|
|
28
30
|
/**
|
|
29
31
|
* A promise that is fulfilled when the model is ready.
|
|
@@ -54,17 +56,17 @@ export class AppWidget extends Panel {
|
|
|
54
56
|
super.dispose();
|
|
55
57
|
}
|
|
56
58
|
async render() {
|
|
57
|
-
var _a;
|
|
59
|
+
var _a, _b, _c, _d;
|
|
58
60
|
const cellList = (_a = this._model.cells) !== null && _a !== void 0 ? _a : [];
|
|
59
|
-
const
|
|
61
|
+
const layout = (_c = (_b = this._spectaAppConfig) === null || _b === void 0 ? void 0 : _b.layout) !== null && _c !== void 0 ? _c : 'default';
|
|
60
62
|
for (const cell of cellList) {
|
|
61
63
|
const src = cell.sharedModel.source;
|
|
62
64
|
if (src.length === 0) {
|
|
63
65
|
continue;
|
|
64
66
|
}
|
|
65
67
|
const el = this._model.createCell(cell);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
this._model.executeCell(cell, el);
|
|
69
|
+
this._outputs.push(el);
|
|
68
70
|
}
|
|
69
71
|
const readyCallback = async () => {
|
|
70
72
|
if (this._loaderHost) {
|
|
@@ -78,9 +80,10 @@ export class AppWidget extends Panel {
|
|
|
78
80
|
hideAppLoadingIndicator();
|
|
79
81
|
}
|
|
80
82
|
};
|
|
81
|
-
|
|
83
|
+
const spectaLayout = (_d = this._layoutRegistry.get(layout)) !== null && _d !== void 0 ? _d : this._layoutRegistry.getDefaultLayout();
|
|
84
|
+
await spectaLayout.render({
|
|
82
85
|
host: this._host,
|
|
83
|
-
items:
|
|
86
|
+
items: this._outputs,
|
|
84
87
|
notebook: this._model.context.model.toJSON(),
|
|
85
88
|
readyCallback
|
|
86
89
|
});
|
|
@@ -89,4 +92,17 @@ export class AppWidget extends Panel {
|
|
|
89
92
|
this._model.dispose();
|
|
90
93
|
super.onCloseRequest(msg);
|
|
91
94
|
}
|
|
95
|
+
_onSelectedLayoutChanged(sender, args) {
|
|
96
|
+
const currentEls = [...this._host.widgets];
|
|
97
|
+
currentEls.forEach(el => {
|
|
98
|
+
var _a;
|
|
99
|
+
(_a = this._host.layout) === null || _a === void 0 ? void 0 : _a.removeWidget(el);
|
|
100
|
+
});
|
|
101
|
+
args.layout.render({
|
|
102
|
+
host: this._host,
|
|
103
|
+
items: this._outputs,
|
|
104
|
+
notebook: this._model.context.model.toJSON(),
|
|
105
|
+
readyCallback: async () => { }
|
|
106
|
+
});
|
|
107
|
+
}
|
|
92
108
|
}
|