Skip to content

Commit

Permalink
feat: Add embed-widget (#1668)
Browse files Browse the repository at this point in the history
- Loads the widget and displays it if there is a widget plugin that
matches
- Displays an error if no plugin is found that can display the type of
widget, or a widget with that name is not found
- Fixes #1629

Tested by installing the matplotlib, plotly-express python plugins, but
only installing the plotly-express JS plugin (not the matplotlib JS
plugin). Then ran the following snippet:
```python
from deephaven.column import int_col, string_col
from deephaven.plot import Figure, express as dx
from deephaven import new_table
import matplotlib.pyplot as plt

t = new_table([
    string_col("Categories", ["A", "B", "C"]),
    int_col("Values", [1, 3, 5]),
])

t_rollup = t.rollup(aggs=[], by=["Categories"], include_constituents=True)

fig = Figure().plot_cat(series_name="Test", t=t, category="Categories", y="Values").show()

dx_fig = dx.bar(table=t, x="Categories", y="Values")

import matplotlib.pyplot as plt

mpl_fig = plt.figure()
ax = mpl_fig.subplots()
ax.plot([1, 2, 3, 4], [4, 2, 6, 7])
```

Then opened up pages to the following URLs to make sure the appeared
correctly:
1. http://localhost:4030/?name=t - Table displayed correctly
2. http://localhost:4030/?name=t_rollup - Tree Table displayed correctly
3. http://localhost:4030/?name=fig - Deephaven Figure displayed
correctly
4. http://localhost:4030/?name=dx_fig - Plotly-express figure displayed
correctly
5. http://localhost:4030/?name=mpl_fig - Error displayed correctly about
unknown type
6. http://localhost:4030/?name=err - Timeout error displayed
7. http://localhost:4030/ - Error saying no name provided

---------

Co-authored-by: Matthew Runyon <mattrunyonstuff@gmail.com>
  • Loading branch information
mofojed and mattrunyon authored Dec 7, 2023
1 parent bdc764e commit 1b06675
Show file tree
Hide file tree
Showing 47 changed files with 700 additions and 164 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ We use Chrome for development with the React and Redux extensions.
## Scripts

- `npm install` : Install all dependencies and automatically bootstrap packages. Should be run before any of the other steps.
- `npm start`: Start building all packages and watching them (when possible). Use when you're developing, and your changes will be picked up automatically.
- `npm start`: Start building all packages and watching them (when possible). Use when you're developing, and your changes will be picked up automatically. Servers will open up for code-studio, embed-grid, embed-chart, and embed-widget. These will open on localhost on ports 4000, 4010, 4020, and 4030 respectively.
- `npm test`: Start running tests in all packages and watching (when possible). Use when you're developing, and any breaking changes will be printed out automatically. See [Unit tests](#unit-tests) for more details.
- `npm run build`: Create a production build of all packages. Mainly used by CI when packaging up a production version of the app.
- `npm run preview`: Runs the Vite preview server for the built code-studio, embed-grid, and embed-chart. These will open on ports 4000, 4010, and 4020.
- `npm run preview`: Runs the Vite preview server for the built code-studio, embed-grid, embed-chart, and embed-widget. These will open on ports 4000, 4010, 4020, and 4030 respectively.
- `npm run e2e`: Runs the Playwright end-to-end tests locally. See [E2E Tests](#e2e-tests) for more details.

If your DHC address is different from the default `http://localhost:10000`, edit `.env.local` in each package to point to your local DHC. This is needed for the session websocket and for things like notebooks to be proxied correctly by Vite.
Expand Down Expand Up @@ -134,6 +134,7 @@ Note that log messages from other sources such as react prop types will still be
If you want to collect coverage locally, run `npm test -- --coverage`

### Debugging Unit Tests

Unit tests can be debugged by running jest with the `--inspect-brk` flag and attaching to the node process in vscode's debugger. There are 2 launch configs that make this easier:

- Debug Jest Tests - This will prompt you for a test name or pattern and will then run tests in watch mode with an attached debugger.
Expand All @@ -152,6 +153,7 @@ Snapshots are used by end-to-end tests to visually verify the output. Snapshots
Once you are satisfied with the snapshots and everything is passing locally, you need to use the docker image to update snapshots for CI (unless you are running the same platform as CI (Ubuntu)). Run `npm run e2e:update-ci-snapshots` to update the CI snapshots. The snapshots will be written to your local directories. The Linux snapshots should be committed to git (non-Linux snapshots should be automatically ignored by git).

### Differences in CI vs Local Docker Environments

Note that while both the GH actions and docker configuration use Ubuntu 22.04 images, their configurations are not identical. One known difference is the available system fonts. In some cases this can cause snapshots to differ when running locally vs in CI such as when rendering unicode characters. To mitigate this, some of our e2e tests have been configured to ensure a consistent unicode font fallback.

- The `DejaVu Sans` font gets installed via the [Dockerfile](tests/docker-scripts/Dockerfile). It already exists in the CI environment.
Expand Down
53 changes: 51 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,23 @@
"types": "tsc --build",
"watch:types": "tsc --build --watch --preserveWatchOutput",
"build": "run-s build:necessary types build:packages build:apps",
"build:apps": "lerna run --scope=@deephaven/{code-studio,embed-chart,embed-grid} build",
"build:apps": "lerna run --scope=@deephaven/{code-studio,embed-chart,embed-grid,embed-widget} build",
"build:app": "lerna run --scope=@deephaven/code-studio build",
"build:embed-chart": "lerna run --scope=@deephaven/embed-chart build",
"build:embed-grid": "lerna run --scope=@deephaven/embed-grid build",
"build:packages": "lerna run --ignore=@deephaven/{code-studio,embed-chart,embed-grid} build --stream",
"build:embed-widget": "lerna run --scope=@deephaven/embed-widget build",
"build:packages": "lerna run --ignore=@deephaven/{code-studio,embed-chart,embed-grid,embed-widget} build --stream",
"build:profile": "lerna run build --stream --profile",
"build:necessary": "lerna run build --scope=@deephaven/icons",
"analyze": "lerna run analyze",
"preview": "lerna run --scope=@deephaven/{code-studio,embed-chart,embed-grid} preview --stream",
"preview": "lerna run --scope=@deephaven/{code-studio,embed-chart,embed-grid,embed-widget} preview --stream",
"preview:app": "lerna run --scope=@deephaven/code-studio preview --stream",
"prestart": "npm run build:necessary",
"start": "run-p watch:types start:*",
"start:app": "lerna run start --scope=@deephaven/code-studio --stream",
"start:embed-chart": "lerna run start --scope=@deephaven/embed-chart --stream",
"start:embed-grid": "lerna run start --scope=@deephaven/embed-grid --stream",
"start:embed-widget": "lerna run start --scope=@deephaven/embed-widget --stream",
"pretest": "npm run build:necessary",
"test": "jest --watch --changedSince origin/main",
"test:debug": "node --inspect-brk node_modules/.bin/jest --config jest.config.unit.cjs --runInBand --watch",
Expand Down Expand Up @@ -162,6 +164,7 @@
"@deephaven/dashboard-core-plugins": "file:packages/dashboard-core-plugins",
"@deephaven/embed-chart": "file:packages/embed-chart",
"@deephaven/embed-grid": "file:packages/embed-grid",
"@deephaven/embed-widget": "file:packages/embed-widget",
"@deephaven/file-explorer": "file:packages/file-explorer",
"@deephaven/filters": "file:packages/filters",
"@deephaven/golden-layout": "file:packages/golden-layout",
Expand Down
26 changes: 1 addition & 25 deletions packages/code-studio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ To start the Code Studio, run `npm install` and `npm start` in the root director
Project specific settings are stored in the `.env` file. There is also an `.env.development` file which is only
loaded in development builds, and `.env.development.local` which is only for local builds. For local development,
you should be modifying `.env.development.local`.
For more information on `.env`, see https://create-react-app.dev/docs/adding-custom-environment-variables#adding-development-environment-variables-in-env
For more information on `.env`, see [Vite docs](https://vitejs.dev/guide/env-and-mode.html).
Below are some of the common properties which are configurable in the `.env` file.

### VITE_CORE_API_URL
Expand Down Expand Up @@ -88,30 +88,6 @@ You can learn more in the [Vite documentation](https://vitejs.dev/guide/).

To learn React, check out the [React documentation](https://reactjs.org/).

### Code Splitting

This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting

### Analyzing the Bundle Size

This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size

### Making a Progressive Web App

This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app

### Advanced Configuration

This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration

### Deployment

This section has moved here: https://facebook.github.io/create-react-app/docs/deployment

### `yarn build` fails to minify

This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify

# Legal Notices

Deephaven Data Labs and any contributors grant you a license to the content of this repository under the Apache 2.0 License, see the [LICENSE](../../LICENSE) file.
6 changes: 1 addition & 5 deletions packages/code-studio/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<base href="%BASE_URL%" />
Expand All @@ -9,10 +9,6 @@
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#2d2a2e" />
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="/manifest.json" />
<link rel="icon" href="%VITE_FAVICON%" />
<title>Deephaven</title>
Expand Down
4 changes: 0 additions & 4 deletions packages/code-studio/src/styleguide/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#2d2a2e" />
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="/manifest.json" />
<link rel="icon" href="%VITE_FAVICON%" />
<title>Deephaven Styleguide</title>
Expand Down
39 changes: 39 additions & 0 deletions packages/components/src/ErrorBoundary.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { render } from '@testing-library/react';
import ErrorBoundary, { ErrorBoundaryProps } from './ErrorBoundary';

function ThrowComponent(): JSX.Element {
throw new Error('Test error');
}

function makeWrapper({
children = 'Hello World',
className,
onError = jest.fn(),
fallback,
}: Partial<ErrorBoundaryProps> = {}) {
return render(
<ErrorBoundary className={className} fallback={fallback} onError={onError}>
{children}
</ErrorBoundary>
);
}

it('should render the children if there is no error', () => {
const onError = jest.fn();
const { getByText } = makeWrapper({ onError });
expect(getByText('Hello World')).toBeInTheDocument();
expect(onError).not.toHaveBeenCalled();
});

it('should render the fallback if there is an error', () => {
const onError = jest.fn();
const error = new Error('Test error');
const { getByText } = makeWrapper({
children: <ThrowComponent />,
fallback: <div>Fallback</div>,
onError,
});
expect(getByText('Fallback')).toBeInTheDocument();
expect(onError).toHaveBeenCalledWith(error, expect.anything());
});
70 changes: 70 additions & 0 deletions packages/components/src/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import Log from '@deephaven/log';
import React, { Component, ReactNode } from 'react';
import LoadingOverlay from './LoadingOverlay';

const log = Log.module('ErrorBoundary');

export interface ErrorBoundaryProps {
/** Children to catch errors from */
children: ReactNode;

/** Classname to wrap the error message with */
className?: string;

/** Callback for when an error occurs */
onError?: (error: Error, errorInfo: React.ErrorInfo) => void;

/** Custom fallback element */
fallback?: ReactNode;
}

export interface ErrorBoundaryState {
error?: Error;
}

/**
* Error boundary for catching render errors in React. Displays an error message if an error is caught by default, or you can specify a fallback component to render.
* https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary
*/
export class ErrorBoundary extends Component<
ErrorBoundaryProps,
ErrorBoundaryState
> {
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
return { error };
}

constructor(props: ErrorBoundaryProps) {
super(props);
this.state = { error: undefined };
}

componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
const { onError } = this.props;
log.error('Error caught by ErrorBoundary', error, errorInfo);
onError?.(error, errorInfo);
}

render(): ReactNode {
const { children, className, fallback } = this.props;
const { error } = this.state;
if (error != null) {
if (fallback != null) {
return fallback;
}

return (
<div className={className}>
<LoadingOverlay
errorMessage={`${error}`}
isLoading={false}
isLoaded={false}
/>
</div>
);
}
return children;
}
}

export default ErrorBoundary;
1 change: 1 addition & 0 deletions packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export { default as DraggableItemList } from './DraggableItemList';
export * from './DraggableItemList';
export { default as DragUtils } from './DragUtils';
export { default as EditableItemList } from './EditableItemList';
export * from './ErrorBoundary';
export { default as HierarchicalCheckboxMenu } from './HierarchicalCheckboxMenu';
export * from './HierarchicalCheckboxMenu';
export * from './ItemList';
Expand Down
2 changes: 1 addition & 1 deletion packages/dashboard-core-plugins/src/ChartPanelPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export const ChartPanelPlugin = forwardRef(
chartTheme,
connection,
metadata as ChartPanelMetadata,
fetch as unknown as () => Promise<Figure>,
fetch as () => Promise<Figure>,
panelState
);
},
Expand Down
2 changes: 1 addition & 1 deletion packages/dashboard-core-plugins/src/GridPanelPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const GridPanelPlugin = forwardRef(
(props: WidgetPanelProps, ref: React.Ref<IrisGridPanel>) => {
const { localDashboardId, fetch } = props;
const hydratedProps = useHydrateGrid(
fetch as unknown as () => Promise<Table>,
fetch as () => Promise<Table>,
localDashboardId
);

Expand Down
2 changes: 1 addition & 1 deletion packages/dashboard-core-plugins/src/PandasPanelPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const PandasPanelPlugin = forwardRef(
(props: WidgetPanelProps, ref: React.Ref<PandasPanel>) => {
const { localDashboardId, fetch } = props;
const hydratedProps = useHydrateGrid(
fetch as unknown as () => Promise<Table>,
fetch as () => Promise<Table>,
localDashboardId
);

Expand Down
1 change: 0 additions & 1 deletion packages/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"dependencies": {
"@deephaven/components": "file:../components",
"@deephaven/golden-layout": "file:../golden-layout",
"@deephaven/jsapi-bootstrap": "file:../jsapi-bootstrap",
"@deephaven/log": "file:../log",
"@deephaven/react-hooks": "file:../react-hooks",
"@deephaven/redux": "file:../redux",
Expand Down
1 change: 0 additions & 1 deletion packages/dashboard/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"references": [
{ "path": "../components" },
{ "path": "../golden-layout" },
{ "path": "../jsapi-bootstrap" },
{ "path": "../log" },
{ "path": "../react-hooks" },
{ "path": "../redux" },
Expand Down
Loading

0 comments on commit 1b06675

Please sign in to comment.