Skip to content

Commit b6eeb30

Browse files
authored
fix: Changes for Deephaven UI embedding widget plugins (#1644)
These changes are needed so Deephaven UI can embed widget plugins. This also creates a difference between the widget component and the widget panel component. Tested the panels still function as intended for grid, chart, and dataframe.
1 parent f9f62db commit b6eeb30

16 files changed

Lines changed: 258 additions & 77 deletions

packages/chart/src/Chart.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ interface ChartProps {
4949
settings: FormatterSettings;
5050
isActive: boolean;
5151
Plotly: typeof Plotly;
52+
containerRef?: React.RefObject<HTMLDivElement>;
5253
onDisconnect: () => void;
5354
onReconnect: () => void;
5455
onUpdate: (obj: { isLoading: boolean }) => void;
@@ -145,7 +146,7 @@ export class Chart extends Component<ChartProps, ChartState> {
145146

146147
this.PlotComponent = createPlotlyComponent(props.Plotly);
147148
this.plot = React.createRef();
148-
this.plotWrapper = React.createRef();
149+
this.plotWrapper = props.containerRef ?? React.createRef();
149150
this.columnFormats = [];
150151
this.dateTimeFormatterOptions = {};
151152
this.decimalFormatOptions = {};

packages/dashboard-core-plugins/src/ChartPlugin.tsx renamed to packages/dashboard-core-plugins/src/ChartPanelPlugin.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import type {
1414
} from '@deephaven/jsapi-types';
1515
import { IrisGridUtils } from '@deephaven/iris-grid';
1616
import { getTimeZone, store } from '@deephaven/redux';
17-
import { type WidgetComponentProps } from '@deephaven/plugin';
17+
import { WidgetPanelProps } from '@deephaven/plugin';
1818
import {
1919
ChartPanelMetadata,
2020
GLChartPanelState,
@@ -113,8 +113,8 @@ async function createChartModel(
113113
);
114114
}
115115

116-
export const ChartPlugin = forwardRef(
117-
(props: WidgetComponentProps, ref: React.Ref<ChartPanel>) => {
116+
export const ChartPanelPlugin = forwardRef(
117+
(props: WidgetPanelProps, ref: React.Ref<ChartPanel>) => {
118118
const dh = useApi();
119119
const chartTheme = useChartTheme();
120120
const connection = useConnection();
@@ -160,6 +160,6 @@ export const ChartPlugin = forwardRef(
160160
}
161161
);
162162

163-
ChartPlugin.displayName = 'ChartPlugin';
163+
ChartPanelPlugin.displayName = 'ChartPanelPlugin';
164164

165-
export default ChartPlugin;
165+
export default ChartPanelPlugin;

packages/dashboard-core-plugins/src/ChartPluginConfig.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { PluginType, type WidgetPlugin } from '@deephaven/plugin';
22
import { vsGraph } from '@deephaven/icons';
3-
import ChartPlugin from './ChartPlugin';
3+
import { ChartWidgetPlugin } from './ChartWidgetPlugin';
4+
import { ChartPanelPlugin } from './ChartPanelPlugin';
45

56
const ChartPluginConfig: WidgetPlugin = {
67
name: 'ChartPanel',
78
title: 'Chart',
89
type: PluginType.WIDGET_PLUGIN,
9-
component: ChartPlugin,
10-
panelComponent: ChartPlugin,
10+
component: ChartWidgetPlugin,
11+
panelComponent: ChartPanelPlugin,
1112
supportedTypes: 'Figure',
1213
icon: vsGraph,
1314
};
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { useEffect, useState } from 'react';
2+
import { useApi } from '@deephaven/jsapi-bootstrap';
3+
import {
4+
Chart,
5+
ChartModel,
6+
ChartModelFactory,
7+
useChartTheme,
8+
} from '@deephaven/chart';
9+
import type { Figure } from '@deephaven/jsapi-types';
10+
import { type WidgetComponentProps } from '@deephaven/plugin';
11+
12+
export function ChartWidgetPlugin(
13+
props: WidgetComponentProps
14+
): JSX.Element | null {
15+
const dh = useApi();
16+
const chartTheme = useChartTheme();
17+
const [model, setModel] = useState<ChartModel>();
18+
19+
const { fetch } = props;
20+
21+
useEffect(() => {
22+
let cancelled = false;
23+
async function init() {
24+
const figure = (await fetch()) as unknown as Figure;
25+
const newModel = await ChartModelFactory.makeModel(
26+
dh,
27+
undefined,
28+
figure,
29+
chartTheme
30+
);
31+
32+
if (!cancelled) {
33+
setModel(newModel);
34+
}
35+
}
36+
37+
init();
38+
39+
return () => {
40+
cancelled = true;
41+
};
42+
}, [dh, fetch, chartTheme]);
43+
44+
return model ? <Chart model={model} /> : null;
45+
}
46+
47+
export default ChartWidgetPlugin;
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { forwardRef } from 'react';
2-
import { type WidgetComponentProps } from '@deephaven/plugin';
2+
import { WidgetPanelProps } from '@deephaven/plugin';
33
import { type Table } from '@deephaven/jsapi-types';
44
import useHydrateGrid from './useHydrateGrid';
55
import ConnectedIrisGridPanel, {
66
type IrisGridPanel,
77
} from './panels/IrisGridPanel';
88

9-
export const GridPlugin = forwardRef(
10-
(props: WidgetComponentProps, ref: React.Ref<IrisGridPanel>) => {
9+
export const GridPanelPlugin = forwardRef(
10+
(props: WidgetPanelProps, ref: React.Ref<IrisGridPanel>) => {
1111
const { localDashboardId, fetch } = props;
1212
const hydratedProps = useHydrateGrid(
1313
fetch as unknown as () => Promise<Table>,
@@ -19,6 +19,6 @@ export const GridPlugin = forwardRef(
1919
}
2020
);
2121

22-
GridPlugin.displayName = 'GridPlugin';
22+
GridPanelPlugin.displayName = 'GridPanelPlugin';
2323

24-
export default GridPlugin;
24+
export default GridPanelPlugin;

packages/dashboard-core-plugins/src/GridPluginConfig.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { PluginType, type WidgetPlugin } from '@deephaven/plugin';
22
import { dhTable } from '@deephaven/icons';
3-
import GridPlugin from './GridPlugin';
3+
import { GridWidgetPlugin } from './GridWidgetPlugin';
4+
import { GridPanelPlugin } from './GridPanelPlugin';
45

56
const GridPluginConfig: WidgetPlugin = {
67
name: 'IrisGridPanel',
78
title: 'Table',
89
type: PluginType.WIDGET_PLUGIN,
9-
component: GridPlugin,
10-
panelComponent: GridPlugin,
10+
component: GridWidgetPlugin,
11+
panelComponent: GridPanelPlugin,
1112
supportedTypes: ['Table', 'TreeTable', 'HierarchicalTable'],
1213
icon: dhTable,
1314
};
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { useEffect, useState } from 'react';
2+
import { type WidgetComponentProps } from '@deephaven/plugin';
3+
import { type Table } from '@deephaven/jsapi-types';
4+
import { useApi } from '@deephaven/jsapi-bootstrap';
5+
import {
6+
IrisGrid,
7+
IrisGridModelFactory,
8+
type IrisGridModel,
9+
} from '@deephaven/iris-grid';
10+
11+
export function GridWidgetPlugin(
12+
props: WidgetComponentProps
13+
): JSX.Element | null {
14+
const dh = useApi();
15+
const [model, setModel] = useState<IrisGridModel>();
16+
17+
const { fetch } = props;
18+
19+
useEffect(() => {
20+
let cancelled = false;
21+
async function init() {
22+
const table = (await fetch()) as unknown as Table;
23+
const newModel = await IrisGridModelFactory.makeModel(dh, table);
24+
if (!cancelled) {
25+
setModel(newModel);
26+
}
27+
}
28+
29+
init();
30+
31+
return () => {
32+
cancelled = true;
33+
};
34+
}, [dh, fetch]);
35+
36+
return model ? <IrisGrid model={model} /> : null;
37+
}
38+
39+
export default GridWidgetPlugin;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { forwardRef } from 'react';
2+
import { WidgetPanelProps } from '@deephaven/plugin';
3+
import { type Table } from '@deephaven/jsapi-types';
4+
import { PandasPanel } from './panels';
5+
import useHydrateGrid from './useHydrateGrid';
6+
7+
export const PandasPanelPlugin = forwardRef(
8+
(props: WidgetPanelProps, ref: React.Ref<PandasPanel>) => {
9+
const { localDashboardId, fetch } = props;
10+
const hydratedProps = useHydrateGrid(
11+
fetch as unknown as () => Promise<Table>,
12+
localDashboardId
13+
);
14+
15+
return (
16+
// eslint-disable-next-line react/jsx-props-no-spreading
17+
<PandasPanel ref={ref} {...props} {...hydratedProps} />
18+
);
19+
}
20+
);
21+
22+
PandasPanelPlugin.displayName = 'PandasPanelPlugin';
23+
24+
export default PandasPanelPlugin;

packages/dashboard-core-plugins/src/PandasPlugin.tsx

Lines changed: 0 additions & 22 deletions
This file was deleted.

packages/dashboard-core-plugins/src/PandasPluginConfig.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { PluginType, WidgetPlugin } from '@deephaven/plugin';
22
import { dhPandas } from '@deephaven/icons';
3-
import PandasPlugin from './PandasPlugin';
3+
import { PandasWidgetPlugin } from './PandasWidgetPlugin';
4+
import { PandasPanelPlugin } from './PandasPanelPlugin';
45

56
const PandasPluginConfig: WidgetPlugin = {
67
name: 'PandasPanel',
78
title: 'Pandas',
89
type: PluginType.WIDGET_PLUGIN,
9-
// TODO: #1573 Replace with actual base component and not just the panel plugin
10-
component: PandasPlugin,
11-
panelComponent: PandasPlugin,
10+
component: PandasWidgetPlugin,
11+
panelComponent: PandasPanelPlugin,
1212
supportedTypes: 'pandas.DataFrame',
1313
icon: dhPandas,
1414
};

0 commit comments

Comments
 (0)