jupyter-specta 0.1.2 → 0.1.4
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/create_notebook_panel.d.ts +7 -1
- package/lib/create_notebook_panel.js +37 -1
- package/lib/document/factory.d.ts +5 -1
- package/lib/document/factory.js +13 -3
- package/lib/extension_plugins.js +11 -2
- 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/{plugin.js → index.js} +5 -0
- package/lib/layout/layout_registry.d.ts +1 -0
- package/lib/layout/layout_registry.js +6 -0
- package/lib/metadata/index.d.ts +3 -0
- package/lib/metadata/index.js +14 -0
- package/lib/shell.js +0 -1
- package/lib/specta_cell_output.d.ts +11 -2
- package/lib/specta_cell_output.js +22 -1
- package/lib/specta_model.d.ts +6 -4
- package/lib/specta_model.js +89 -13
- package/lib/specta_widget.d.ts +5 -1
- package/lib/specta_widget.js +25 -8
- package/lib/specta_widget_factory.js +7 -2
- package/lib/token.d.ts +18 -0
- package/lib/tool.d.ts +5 -1
- package/lib/tool.js +40 -6
- package/lib/topbar/index.d.ts +5 -0
- package/lib/topbar/index.js +30 -0
- package/lib/topbar/kernelStatus.d.ts +28 -0
- package/lib/topbar/kernelStatus.js +20 -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 +23 -13
- package/schema/app-meta.json +39 -0
- package/schema/cell-meta.json +37 -0
- 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/layout/{plugin.d.ts → index.d.ts} +0 -0
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,7 +1,13 @@
|
|
|
1
|
+
import { ISessionContext } from '@jupyterlab/apputils';
|
|
1
2
|
import { IEditorServices } from '@jupyterlab/codeeditor';
|
|
2
|
-
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
|
3
|
+
import { Context, DocumentRegistry } from '@jupyterlab/docregistry';
|
|
3
4
|
import { INotebookModel, NotebookPanel } from '@jupyterlab/notebook';
|
|
4
5
|
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
6
|
+
import { ServiceManager } from '@jupyterlab/services';
|
|
7
|
+
export declare function createNotebookContext(options: {
|
|
8
|
+
manager: ServiceManager.IManager;
|
|
9
|
+
kernelPreference: ISessionContext.IKernelPreference;
|
|
10
|
+
}): Promise<Context<INotebookModel>>;
|
|
5
11
|
export declare function createNotebookPanel(options: {
|
|
6
12
|
context: DocumentRegistry.IContext<INotebookModel>;
|
|
7
13
|
rendermime: IRenderMimeRegistry;
|
|
@@ -1,4 +1,40 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Context } from '@jupyterlab/docregistry';
|
|
2
|
+
import { Notebook, NotebookModelFactory, NotebookPanel } from '@jupyterlab/notebook';
|
|
3
|
+
import { UUID } from '@lumino/coreutils';
|
|
4
|
+
class CustomContext extends Context {
|
|
5
|
+
/**
|
|
6
|
+
* Save the document contents to disk.
|
|
7
|
+
*/
|
|
8
|
+
async save() {
|
|
9
|
+
await this.ready;
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
async saveAs() {
|
|
13
|
+
await this.ready;
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
async revert() {
|
|
17
|
+
await this.ready;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function createNotebookContext(options) {
|
|
22
|
+
const factory = new NotebookModelFactory({
|
|
23
|
+
disableDocumentWideUndoRedo: false
|
|
24
|
+
});
|
|
25
|
+
const { manager, kernelPreference } = options;
|
|
26
|
+
const path = UUID.uuid4() + '.ipynb';
|
|
27
|
+
await manager.ready;
|
|
28
|
+
await manager.kernelspecs.ready;
|
|
29
|
+
const context = new CustomContext({
|
|
30
|
+
manager,
|
|
31
|
+
factory,
|
|
32
|
+
path,
|
|
33
|
+
kernelPreference: kernelPreference
|
|
34
|
+
});
|
|
35
|
+
await context.sessionContext.initialize();
|
|
36
|
+
return context;
|
|
37
|
+
}
|
|
2
38
|
export function createNotebookPanel(options) {
|
|
3
39
|
const { context, rendermime, editorServices } = options;
|
|
4
40
|
const editorFactory = editorServices.factoryService.newInlineEditor;
|
|
@@ -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,30 @@
|
|
|
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, readSpectaConfig } 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
|
+
const spectaConfig = readSpectaConfig(context.model.metadata);
|
|
17
|
+
if (!isSpectaApp() && !spectaConfig.hideTopbar) {
|
|
18
|
+
// Not a specta app, add topbar to document widget
|
|
19
|
+
const topbar = ReactWidget.create(React.createElement(TopbarElement, null));
|
|
20
|
+
content.addWidget(topbar);
|
|
21
|
+
}
|
|
12
22
|
context.ready.then(async () => {
|
|
13
23
|
const spectaWidget = await this._spectaWidgetFactory.createNew({
|
|
14
24
|
context
|
|
15
25
|
});
|
|
16
26
|
if (spectaWidget) {
|
|
17
|
-
|
|
27
|
+
content.addWidget(spectaWidget);
|
|
18
28
|
}
|
|
19
29
|
});
|
|
20
30
|
const widget = new NotebookSpectaDocWidget({
|
package/lib/extension_plugins.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { spectaDocument, spectaOpener } from './document/plugin';
|
|
2
|
-
import { spectaLayoutRegistry } from './layout
|
|
2
|
+
import { spectaLayoutRegistry } from './layout';
|
|
3
|
+
import { appMeta, cellMeta } from './metadata';
|
|
4
|
+
import { topbarPlugin } from './topbar';
|
|
3
5
|
export * from './tool';
|
|
4
6
|
export * from './token';
|
|
5
|
-
export default [
|
|
7
|
+
export default [
|
|
8
|
+
spectaDocument,
|
|
9
|
+
spectaOpener,
|
|
10
|
+
spectaLayoutRegistry,
|
|
11
|
+
topbarPlugin,
|
|
12
|
+
appMeta,
|
|
13
|
+
cellMeta
|
|
14
|
+
];
|
|
@@ -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 {
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { SpectaLayoutRegistry } from './layout_registry';
|
|
2
2
|
import { ISpectaLayoutRegistry } from '../token';
|
|
3
|
+
import { readSpectaConfig } from '../tool';
|
|
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;
|
|
8
10
|
const layoutRegistry = new SpectaLayoutRegistry();
|
|
11
|
+
const spectaConfig = readSpectaConfig();
|
|
12
|
+
const defaultLayout = (_a = spectaConfig.defaultLayout) !== null && _a !== void 0 ? _a : 'default';
|
|
13
|
+
layoutRegistry.setSelectedLayout(defaultLayout);
|
|
9
14
|
return layoutRegistry;
|
|
10
15
|
}
|
|
11
16
|
};
|
|
@@ -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/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,23 @@
|
|
|
1
|
-
import { Panel, Widget } from '@lumino/widgets';
|
|
2
1
|
import * as nbformat from '@jupyterlab/nbformat';
|
|
2
|
+
import { Panel, Widget } from '@lumino/widgets';
|
|
3
|
+
import { ISpectaCellConfig } from './token';
|
|
3
4
|
export interface ICellInfo {
|
|
4
5
|
hidden?: boolean;
|
|
5
6
|
cellModel?: nbformat.ICell;
|
|
6
7
|
}
|
|
7
8
|
export declare class SpectaCellOutput extends Panel {
|
|
8
|
-
constructor(cellIdentity
|
|
9
|
+
constructor({ cellIdentity, cell, sourceCell, info, cellConfig }: {
|
|
10
|
+
cellIdentity: string;
|
|
11
|
+
cell: Widget;
|
|
12
|
+
sourceCell?: Widget;
|
|
13
|
+
info: ICellInfo;
|
|
14
|
+
cellConfig: Required<ISpectaCellConfig>;
|
|
15
|
+
});
|
|
9
16
|
readonly cellIdentity: string;
|
|
10
17
|
get cellOutput(): Widget;
|
|
11
18
|
get info(): ICellInfo;
|
|
19
|
+
removePlaceholder(): void;
|
|
12
20
|
private _info;
|
|
13
21
|
private _cellOutput;
|
|
22
|
+
private _placeholder?;
|
|
14
23
|
}
|
|
@@ -1,19 +1,34 @@
|
|
|
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, cellConfig }) {
|
|
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
|
+
if (cellConfig.showOutput) {
|
|
27
|
+
this._placeholder = ReactWidget.create(React.createElement(RandomSkeleton, null));
|
|
28
|
+
this._placeholder.addClass('specta-cell-placeholder');
|
|
29
|
+
this.addWidget(this._placeholder);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
17
32
|
}
|
|
18
33
|
get cellOutput() {
|
|
19
34
|
return this._cellOutput;
|
|
@@ -21,4 +36,10 @@ export class SpectaCellOutput extends Panel {
|
|
|
21
36
|
get info() {
|
|
22
37
|
return this._info;
|
|
23
38
|
}
|
|
39
|
+
removePlaceholder() {
|
|
40
|
+
var _a;
|
|
41
|
+
if (this._placeholder) {
|
|
42
|
+
(_a = this._placeholder) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
24
45
|
}
|
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';
|
|
@@ -18,14 +17,17 @@ export declare class AppModel {
|
|
|
18
17
|
dispose(): void;
|
|
19
18
|
get rendermime(): IRenderMimeRegistry;
|
|
20
19
|
get cells(): CellList | undefined;
|
|
21
|
-
get context(): DocumentRegistry.IContext<INotebookModel
|
|
20
|
+
get context(): DocumentRegistry.IContext<INotebookModel> | undefined;
|
|
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
|
-
private _context
|
|
26
|
+
private _context?;
|
|
27
|
+
private _notebookModelJson;
|
|
28
28
|
private _isDisposed;
|
|
29
|
+
private _manager;
|
|
30
|
+
private _kernelPreference;
|
|
29
31
|
}
|
|
30
32
|
export declare namespace AppModel {
|
|
31
33
|
interface IOptions {
|
package/lib/specta_model.js
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
|
-
import { MarkdownCell, RawCell } from '@jupyterlab/cells';
|
|
1
|
+
import { CodeCell, MarkdownCell, RawCell } from '@jupyterlab/cells';
|
|
2
2
|
import { OutputAreaModel, SimplifiedOutputArea } from '@jupyterlab/outputarea';
|
|
3
|
-
import { createNotebookPanel } from './create_notebook_panel';
|
|
3
|
+
import { createNotebookContext, createNotebookPanel } from './create_notebook_panel';
|
|
4
4
|
import { SpectaCellOutput } from './specta_cell_output';
|
|
5
|
+
import { PromiseDelegate } from '@lumino/coreutils';
|
|
6
|
+
import { readCellConfig } from './tool';
|
|
5
7
|
export const VIEW = 'grid_default';
|
|
6
8
|
export class AppModel {
|
|
7
9
|
constructor(options) {
|
|
8
10
|
this.options = options;
|
|
9
11
|
this._isDisposed = false;
|
|
10
|
-
this.
|
|
12
|
+
this._notebookModelJson = options.context.model.toJSON();
|
|
13
|
+
this._kernelPreference = {
|
|
14
|
+
shouldStart: true,
|
|
15
|
+
canStart: true,
|
|
16
|
+
shutdownOnDispose: true,
|
|
17
|
+
name: options.context.model.defaultKernelName,
|
|
18
|
+
autoStartDefault: true,
|
|
19
|
+
language: options.context.model.defaultKernelLanguage
|
|
20
|
+
};
|
|
21
|
+
this._manager = options.manager;
|
|
11
22
|
}
|
|
12
23
|
/**
|
|
13
24
|
* Whether the handler is disposed.
|
|
@@ -39,13 +50,40 @@ export class AppModel {
|
|
|
39
50
|
}
|
|
40
51
|
async initialize() {
|
|
41
52
|
var _a;
|
|
42
|
-
|
|
43
|
-
this.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
editorServices: this.options.editorServices
|
|
53
|
+
const pd = new PromiseDelegate();
|
|
54
|
+
this._context = await createNotebookContext({
|
|
55
|
+
manager: this._manager,
|
|
56
|
+
kernelPreference: this._kernelPreference
|
|
47
57
|
});
|
|
48
|
-
this.
|
|
58
|
+
this._context.model.fromJSON(this._notebookModelJson);
|
|
59
|
+
const connectKernel = () => {
|
|
60
|
+
pd.resolve();
|
|
61
|
+
this._notebookPanel = createNotebookPanel({
|
|
62
|
+
context: this._context,
|
|
63
|
+
rendermime: this.options.rendermime,
|
|
64
|
+
editorServices: this.options.editorServices
|
|
65
|
+
});
|
|
66
|
+
this.options.tracker.widgetAdded.emit(this._notebookPanel);
|
|
67
|
+
};
|
|
68
|
+
const kernel = (_a = this._context.sessionContext.session) === null || _a === void 0 ? void 0 : _a.kernel;
|
|
69
|
+
if (kernel) {
|
|
70
|
+
const status = kernel.status;
|
|
71
|
+
if (status !== 'unknown') {
|
|
72
|
+
// Connected to an existing kernel.
|
|
73
|
+
connectKernel();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
this._context.sessionContext.connectionStatusChanged.connect((_, status) => {
|
|
78
|
+
var _a;
|
|
79
|
+
if (status === 'connected') {
|
|
80
|
+
const kernel = (_a = this._context.sessionContext.session) === null || _a === void 0 ? void 0 : _a.kernel;
|
|
81
|
+
if (kernel) {
|
|
82
|
+
connectKernel();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}, this);
|
|
86
|
+
return pd.promise;
|
|
49
87
|
}
|
|
50
88
|
createCell(cellModel) {
|
|
51
89
|
let item;
|
|
@@ -53,14 +91,37 @@ export class AppModel {
|
|
|
53
91
|
const info = {
|
|
54
92
|
cellModel: cellModelJson
|
|
55
93
|
};
|
|
94
|
+
const cellConfig = readCellConfig(cellModelJson);
|
|
56
95
|
switch (cellModel.type) {
|
|
57
96
|
case 'code': {
|
|
97
|
+
let sourceCell;
|
|
98
|
+
if (cellConfig.showSource) {
|
|
99
|
+
sourceCell = new CodeCell({
|
|
100
|
+
model: cellModel,
|
|
101
|
+
rendermime: this.options.rendermime,
|
|
102
|
+
contentFactory: this.options.contentFactory,
|
|
103
|
+
editorConfig: {
|
|
104
|
+
lineNumbers: false,
|
|
105
|
+
lineWrap: false,
|
|
106
|
+
tabFocusable: false,
|
|
107
|
+
editable: false
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
sourceCell.syncEditable = false;
|
|
111
|
+
sourceCell.readOnly = true;
|
|
112
|
+
}
|
|
58
113
|
const outputareamodel = new OutputAreaModel({ trusted: true });
|
|
59
114
|
const out = new SimplifiedOutputArea({
|
|
60
115
|
model: outputareamodel,
|
|
61
116
|
rendermime: this.options.rendermime
|
|
62
117
|
});
|
|
63
|
-
item = new SpectaCellOutput(
|
|
118
|
+
item = new SpectaCellOutput({
|
|
119
|
+
cellIdentity: cellModel.id,
|
|
120
|
+
cell: out,
|
|
121
|
+
sourceCell,
|
|
122
|
+
cellConfig,
|
|
123
|
+
info
|
|
124
|
+
});
|
|
64
125
|
break;
|
|
65
126
|
}
|
|
66
127
|
case 'markdown': {
|
|
@@ -70,11 +131,17 @@ export class AppModel {
|
|
|
70
131
|
contentFactory: this.options.contentFactory,
|
|
71
132
|
editorConfig: this.options.editorConfig.markdown
|
|
72
133
|
});
|
|
134
|
+
markdownCell.initializeState();
|
|
73
135
|
markdownCell.inputHidden = false;
|
|
74
136
|
markdownCell.rendered = true;
|
|
75
137
|
Private.removeElements(markdownCell.node, 'jp-Collapser');
|
|
76
138
|
Private.removeElements(markdownCell.node, 'jp-InputPrompt');
|
|
77
|
-
item = new SpectaCellOutput(
|
|
139
|
+
item = new SpectaCellOutput({
|
|
140
|
+
cellIdentity: cellModel.id,
|
|
141
|
+
cell: markdownCell,
|
|
142
|
+
info,
|
|
143
|
+
cellConfig
|
|
144
|
+
});
|
|
78
145
|
break;
|
|
79
146
|
}
|
|
80
147
|
default: {
|
|
@@ -86,18 +153,27 @@ export class AppModel {
|
|
|
86
153
|
rawCell.inputHidden = false;
|
|
87
154
|
Private.removeElements(rawCell.node, 'jp-Collapser');
|
|
88
155
|
Private.removeElements(rawCell.node, 'jp-InputPrompt');
|
|
89
|
-
item = new SpectaCellOutput(
|
|
156
|
+
item = new SpectaCellOutput({
|
|
157
|
+
cellIdentity: cellModel.id,
|
|
158
|
+
cell: rawCell,
|
|
159
|
+
info,
|
|
160
|
+
cellConfig
|
|
161
|
+
});
|
|
90
162
|
break;
|
|
91
163
|
}
|
|
92
164
|
}
|
|
93
165
|
return item;
|
|
94
166
|
}
|
|
95
|
-
async executeCell(cell,
|
|
167
|
+
async executeCell(cell, outputWrapper) {
|
|
96
168
|
if (cell.type !== 'code' || !this._context) {
|
|
97
169
|
return;
|
|
98
170
|
}
|
|
171
|
+
const output = outputWrapper.cellOutput;
|
|
99
172
|
const source = cell.sharedModel.source;
|
|
100
173
|
const rep = await SimplifiedOutputArea.execute(source, output, this._context.sessionContext);
|
|
174
|
+
output.future.done.then(() => {
|
|
175
|
+
outputWrapper.removePlaceholder();
|
|
176
|
+
});
|
|
101
177
|
return rep;
|
|
102
178
|
}
|
|
103
179
|
}
|