Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server mode for Jupyterlab PerspectiveWidget #1195

Merged
merged 5 commits into from
Sep 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/perspective-jupyterlab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"bench:run": "echo \"No Benchmarks\"",
"clean:screenshots": "rimraf \"screenshots/**/*.@(failed|diff).png\"",
"test:build": "cpx \"test/html/*\" dist/umd && cpx \"test/csv/*\" dist/umd && cpx \"test/css/*\" dist/umd && webpack --color --config src/config/webpack.config.js",
"test:run": "jest --rootDir=. --config=../perspective-test/jest.config.js --color --verbose",
"test:run": "jest --rootDir=. --config=test/config/jest.config.js --color --verbose",
"test": "npm-run-all test:build test:run",
"build": "webpack --color --config src/config/plugin.config.js",
"clean": "rimraf dist",
Expand All @@ -43,14 +43,15 @@
"devDependencies": {
"@finos/perspective-test": "^0.5.3",
"@finos/perspective-webpack-plugin": "^0.5.3",
"@jupyter-widgets/base-manager": "^1.0.0-alpha.0",
"@types/jest": "^23.3.9",
"@types/node": "^11.11.0",
"file-loader": "^0.11.1",
"identity-obj-proxy": "^3.0.0",
"isomorphic-fetch": "^2.2.1",
"jest-transform-css": "^2.0.0",
"source-map-support": "^0.5.9",
"ts-jest": "^24.1.0",
"ts-jest": "^25.1.0",
"typescript": "^3.7.4"
},
"jupyterlab": {
Expand Down
17 changes: 12 additions & 5 deletions packages/perspective-jupyterlab/src/less/index.less
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
@import "~@finos/perspective-viewer/src/less/fonts.less";
@import (reference) "~@finos/perspective-viewer/src/themes/material.less";
@import (reference) "~@finos/perspective-viewer/src/themes/material.dark.less";
@import (reference) "~@finos/perspective-viewer/src/themes/material-dense.less";
@import (reference) "~@finos/perspective-viewer/src/themes/material-dense.dark.less";

div.PSPContainer,
div.PSPContainer-dark {
overflow: auto;
resize: both;
padding-right: 5px;
padding-bottom: 5px;
height: 500px;
height: 100%;
flex: 1;
}

.jp-NotebookPanel-notebook div.PSPContainer,
.jp-NotebookPanel-notebook div.PSPContainer-dark {
height: 520px;
}

div.PSPContainer perspective-viewer {
.perspective-viewer-material();
.perspective-viewer-material-dense();
--plugin--border: 1px solid #e0e0e0;
}

div.PSPContainer-dark perspective-viewer {
.perspective-viewer-material-dark();
.perspective-viewer-material-dense-dark();
--plugin--border: 1px solid #333333;
}

div.PSPContainer perspective-viewer,
Expand Down
36 changes: 30 additions & 6 deletions packages/perspective-jupyterlab/src/ts/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,35 @@ export class PerspectiveJupyterClient extends Client {
* @param msg {any} the message to pass to the `PerspectiveManager`.
*/
send(msg: any): void {
const serialized = JSON.stringify(msg);
this.view.send({
id: msg.id,
type: "cmd",
data: serialized
});
// Handle calls to `update` with a binary by setting `is_transferable`
// to true, so the kernel knows to handle the arraybuffer properly.
if (msg.method === "update" && msg.args.length === 2 && msg.args[0] instanceof ArrayBuffer) {
msg.is_transferable = true;
const buffers = [msg.args[0]];

// Remove the arraybuffer from the message args, so it can be
// passed along in `buffers`.
msg.args.shift();

const serialized = JSON.stringify(msg);

// Send the first update message over the Jupyter comm with
// `is_transferable` set, so the kernel knows the expect the arrow.
this.view.send({
id: msg.id,
type: "cmd",
data: serialized
});

// Send the second message with buffers.
this.view.send({}, buffers);
} else {
// Send the message over the Jupyter comm.
this.view.send({
id: msg.id,
type: "cmd",
data: JSON.stringify(msg)
});
}
}
}
2 changes: 2 additions & 0 deletions packages/perspective-jupyterlab/src/ts/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {PERSPECTIVE_VERSION} from "./version";
* TODO: document
*/
export class PerspectiveModel extends DOMWidgetModel {
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
defaults() {
return {
...super.defaults(),
Expand All @@ -35,6 +36,7 @@ export class PerspectiveModel extends DOMWidgetModel {
plugin_config: {},
dark: false,
editable: false,
server: false,
client: false
};
}
Expand Down
32 changes: 28 additions & 4 deletions packages/perspective-jupyterlab/src/ts/psp_widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import "@finos/perspective-viewer";

import {Table, TableData, TableOptions} from "@finos/perspective";
import {Table, TableData, TableOptions, View} from "@finos/perspective";
import {Message} from "@lumino/messaging";
import {Widget} from "@lumino/widgets";
import {MIME_TYPE, PSP_CLASS, PSP_CONTAINER_CLASS, PSP_CONTAINER_CLASS_DARK} from "./utils";
Expand All @@ -23,6 +23,7 @@ let _increment = 0;
export interface PerspectiveWidgetOptions extends PerspectiveViewerOptions {
dark?: boolean;
client?: boolean;
server?: boolean;
title?: string;
bindto?: HTMLElement;
plugin_config?: PerspectiveViewerOptions;
Expand Down Expand Up @@ -69,9 +70,11 @@ export class PerspectiveWidget extends Widget {
const plugin_config: PerspectiveViewerOptions = options.plugin_config || {};
const dark: boolean = options.dark || false;
const editable: boolean = options.editable || false;
const server: boolean = options.server || false;
const client: boolean = options.client || false;
const selectable: boolean = options.selectable || false;

this.server = server;
this.client = client;
this.dark = dark;
this.editable = editable;
Expand Down Expand Up @@ -139,7 +142,7 @@ export class PerspectiveWidget extends Widget {
*
* @param table a `perspective.table` object.
*/
load(table: TableData | Table, options?: TableOptions): void {
load(table: TableData | Table | View, options?: TableOptions): void {
this.viewer.load(table, options);
}

Expand Down Expand Up @@ -180,15 +183,23 @@ export class PerspectiveWidget extends Widget {
* @param {boolean} delete_table Whether `delete()` should be called on the
* underlying `Table`.
*/
delete(delete_table = true) {
delete(delete_table = true): void {
this.viewer.delete(delete_table || this.client);
}

/**
* Returns a promise that resolves to the element's edit port ID, used
* internally when edits are made using datagrid in client/server mode.
*/
async getEditPort(): Promise<number> {
return await this.viewer.getEditPort();
}

get table(): Table {
return this.viewer.table;
}

/******************************************************************************
/***************************************************************************
*
* Getters
*
Expand Down Expand Up @@ -311,6 +322,18 @@ export class PerspectiveWidget extends Widget {
this._client = client;
}

/**
* True if the widget is in server-only mode, i.e. the Python backend has
* full ownership of the widget's data, and the widget does not have a
* `perspective.Table` of its own.
*/
get server(): boolean {
return this._server;
}
set server(server: boolean) {
this._server = server;
}

/**
* Enable or disable dark mode by re-rendering the viewer.
*/
Expand Down Expand Up @@ -397,6 +420,7 @@ export class PerspectiveWidget extends Widget {
private _viewer: HTMLPerspectiveViewerElement;
private _plugin_config: PerspectiveViewerOptions;
private _client: boolean;
private _server: boolean;
private _dark: boolean;
private _editable: boolean;
}
Loading