Skip to content

Commit a260842

Browse files
authored
feat: Convert DashboardPlugins to WidgetPlugins (#1598)
Fixes #1573
1 parent e0bbdf0 commit a260842

12 files changed

Lines changed: 137 additions & 127 deletions

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

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
1-
import { useCallback } from 'react';
2-
import {
3-
assertIsDashboardPluginProps,
4-
DashboardPluginComponentProps,
5-
DehydratedDashboardPanelProps,
6-
useDashboardPanel,
7-
} from '@deephaven/dashboard';
1+
import { forwardRef, useMemo } from 'react';
82
import { useApi } from '@deephaven/jsapi-bootstrap';
93
import { useConnection } from '@deephaven/jsapi-components';
104
import { ChartModel, ChartModelFactory } from '@deephaven/chart';
115
import type { dh as DhType, IdeConnection } from '@deephaven/jsapi-types';
126
import { IrisGridUtils } from '@deephaven/iris-grid';
137
import { getTimeZone, store } from '@deephaven/redux';
8+
import { type WidgetComponentProps } from '@deephaven/plugin';
149
import {
15-
ChartPanel,
1610
ChartPanelMetadata,
1711
GLChartPanelState,
1812
isChartPanelDehydratedProps,
1913
isChartPanelTableMetadata,
2014
} from './panels';
15+
import ConnectedChartPanel, {
16+
type ChartPanel,
17+
type ChartPanelProps,
18+
} from './panels/ChartPanel';
2119

2220
async function createChartModel(
2321
dh: DhType,
@@ -86,41 +84,41 @@ async function createChartModel(
8684
return ChartModelFactory.makeModelFromSettings(dh, settings as any, table);
8785
}
8886

89-
export function ChartPlugin(
90-
props: DashboardPluginComponentProps
91-
): JSX.Element | null {
92-
assertIsDashboardPluginProps(props);
93-
const dh = useApi();
94-
const connection = useConnection();
87+
export const ChartPlugin = forwardRef(
88+
(props: WidgetComponentProps, ref: React.Ref<ChartPanel>) => {
89+
const dh = useApi();
90+
const connection = useConnection();
9591

96-
const hydrate = useCallback(
97-
(hydrateProps: DehydratedDashboardPanelProps, id: string) => ({
98-
...hydrateProps,
99-
localDashboardId: id,
100-
makeModel: () => {
101-
const { metadata } = hydrateProps;
102-
const panelState = isChartPanelDehydratedProps(hydrateProps)
103-
? hydrateProps.panelState
104-
: undefined;
105-
if (metadata == null) {
106-
throw new Error('Metadata is required for chart panel');
107-
}
92+
const hydratedProps = useMemo(
93+
() => ({
94+
...(props as unknown as ChartPanelProps),
95+
metadata: props.metadata as ChartPanelMetadata,
96+
localDashboardId: props.localDashboardId,
97+
makeModel: () => {
98+
const { metadata } = props;
99+
const panelState = isChartPanelDehydratedProps(props)
100+
? (props as unknown as ChartPanelProps).panelState
101+
: undefined;
102+
if (metadata == null) {
103+
throw new Error('Metadata is required for chart panel');
104+
}
108105

109-
return createChartModel(dh, connection, metadata, panelState);
110-
},
111-
}),
112-
[dh, connection]
113-
);
106+
return createChartModel(
107+
dh,
108+
connection,
109+
metadata as ChartPanelMetadata,
110+
panelState
111+
);
112+
},
113+
}),
114+
[dh, connection, props]
115+
);
114116

115-
useDashboardPanel({
116-
dashboardProps: props,
117-
componentName: ChartPanel.COMPONENT,
118-
component: ChartPanel,
119-
supportedTypes: dh.VariableType.FIGURE,
120-
hydrate,
121-
});
117+
// eslint-disable-next-line react/jsx-props-no-spreading
118+
return <ConnectedChartPanel ref={ref} {...hydratedProps} />;
119+
}
120+
);
122121

123-
return null;
124-
}
122+
ChartPlugin.displayName = 'ChartPlugin';
125123

126124
export default ChartPlugin;
Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import { PluginType, DashboardPlugin } from '@deephaven/plugin';
1+
import { PluginType, type WidgetPlugin } from '@deephaven/plugin';
2+
import { vsGraph } from '@deephaven/icons';
23
import ChartPlugin from './ChartPlugin';
34

4-
const ChartPluginConfig: DashboardPlugin = {
5-
name: 'ChartPlugin',
6-
type: PluginType.DASHBOARD_PLUGIN,
5+
const ChartPluginConfig: WidgetPlugin = {
6+
name: 'ChartPanel',
7+
title: 'Chart',
8+
type: PluginType.WIDGET_PLUGIN,
79
component: ChartPlugin,
10+
panelComponent: ChartPlugin,
11+
supportedTypes: 'Figure',
12+
icon: vsGraph,
813
};
914

1015
export default ChartPluginConfig;
Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,33 @@
1-
import { useMemo } from 'react';
2-
import {
3-
assertIsDashboardPluginProps,
4-
DashboardPluginComponentProps,
5-
useDashboardPanel,
6-
} from '@deephaven/dashboard';
7-
import { useApi } from '@deephaven/jsapi-bootstrap';
8-
import { IrisGridPanel } from './panels';
1+
import { forwardRef, useMemo } from 'react';
2+
import { type WidgetComponentProps } from '@deephaven/plugin';
3+
import { type DashboardPanelProps } from '@deephaven/dashboard';
94
import useHydrateGrid from './useHydrateGrid';
5+
import ConnectedIrisGridPanel, {
6+
IrisGridPanelProps,
7+
type IrisGridPanel,
8+
} from './panels/IrisGridPanel';
109

11-
export function GridPlugin(
12-
props: DashboardPluginComponentProps
13-
): JSX.Element | null {
14-
assertIsDashboardPluginProps(props);
15-
const dh = useApi();
16-
const hydrate = useHydrateGrid();
10+
export const GridPlugin = forwardRef(
11+
(props: WidgetComponentProps, ref: React.Ref<IrisGridPanel>) => {
12+
const hydrate = useHydrateGrid<
13+
DashboardPanelProps & Pick<IrisGridPanelProps, 'panelState'>
14+
>();
15+
const { localDashboardId } = props;
16+
const hydratedProps = useMemo(
17+
() =>
18+
hydrate(
19+
props as WidgetComponentProps &
20+
Pick<IrisGridPanelProps, 'panelState'>,
21+
localDashboardId
22+
),
23+
[hydrate, props, localDashboardId]
24+
);
1725

18-
const supportedTypes = useMemo(
19-
() => [
20-
dh.VariableType.TABLE,
21-
dh.VariableType.TREETABLE,
22-
dh.VariableType.HIERARCHICALTABLE,
23-
],
24-
[dh]
25-
);
26+
// eslint-disable-next-line react/jsx-props-no-spreading
27+
return <ConnectedIrisGridPanel ref={ref} {...hydratedProps} />;
28+
}
29+
);
2630

27-
useDashboardPanel({
28-
dashboardProps: props,
29-
componentName: IrisGridPanel.COMPONENT,
30-
component: IrisGridPanel,
31-
supportedTypes,
32-
hydrate,
33-
});
34-
35-
return null;
36-
}
31+
GridPlugin.displayName = 'GridPlugin';
3732

3833
export default GridPlugin;
Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import { PluginType, DashboardPlugin } from '@deephaven/plugin';
1+
import { PluginType, type WidgetPlugin } from '@deephaven/plugin';
2+
import { dhTable } from '@deephaven/icons';
23
import GridPlugin from './GridPlugin';
34

4-
const GridPluginConfig: DashboardPlugin = {
5-
name: 'GridPlugin',
6-
type: PluginType.DASHBOARD_PLUGIN,
5+
const GridPluginConfig: WidgetPlugin = {
6+
name: 'IrisGridPanel',
7+
title: 'Table',
8+
type: PluginType.WIDGET_PLUGIN,
79
component: GridPlugin,
10+
panelComponent: GridPlugin,
11+
supportedTypes: ['Table', 'TreeTable', 'HierarchicalTable'],
12+
icon: dhTable,
813
};
914

1015
export default GridPluginConfig;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { dhPandas } from '@deephaven/icons';
33
import PandasPlugin from './PandasPlugin';
44

55
const PandasPluginConfig: WidgetPlugin = {
6-
name: 'PandasPlugin',
6+
name: 'PandasPanel',
77
title: 'Pandas',
88
type: PluginType.WIDGET_PLUGIN,
99
// TODO: #1573 Replace with actual base component and not just the panel plugin

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ export function WrapWidgetPlugin(
7272
{...props}
7373
/>
7474
)}
75-
)
7675
</WidgetPanel>
7776
);
7877
}

packages/dashboard-core-plugins/src/index.test.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ import { type IdeConnection } from '@deephaven/jsapi-types';
99
import { ConnectionContext } from '@deephaven/jsapi-components';
1010
import { PluginsContext } from '@deephaven/plugin';
1111
import {
12-
ChartPlugin,
1312
ConsolePlugin,
1413
FilterPlugin,
15-
GridPlugin,
1614
LinkerPlugin,
1715
MarkdownPlugin,
1816
WidgetLoaderPlugin,
@@ -36,8 +34,6 @@ it('handles mounting and unmount core plugins properly', () => {
3634
<Provider store={store}>
3735
<Dashboard>
3836
<FilterPlugin />
39-
<GridPlugin hydrate={() => undefined} />
40-
<ChartPlugin hydrate={() => undefined} />
4137
<ConsolePlugin />
4238
<LinkerPlugin />
4339
<MarkdownPlugin />

packages/dashboard-core-plugins/src/panels/ChartPanel.tsx

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export interface ChartPanelFigureMetadata extends PanelMetadata {
8181
* @deprecated use `name` instead
8282
*/
8383
figure?: string;
84+
sourcePanelId: never;
8485
}
8586

8687
export interface ChartPanelTableMetadata extends PanelMetadata {
@@ -118,28 +119,34 @@ export interface GLChartPanelState {
118119
table?: string;
119120
figure?: string;
120121
}
121-
export interface ChartPanelProps extends DashboardPanelProps {
122+
interface OwnProps extends DashboardPanelProps {
122123
metadata: ChartPanelMetadata;
123124
/** Function to build the ChartModel used by this ChartPanel. Can return a promise. */
124125
makeModel: () => Promise<ChartModel>;
126+
localDashboardId: string;
127+
Plotly?: typeof PlotlyType;
128+
/** The panel container div */
129+
containerRef?: RefObject<HTMLDivElement>;
130+
131+
panelState: GLChartPanelState;
132+
}
133+
134+
interface StateProps {
125135
inputFilters: InputFilter[];
126136
links: Link[];
127-
localDashboardId: string;
128137
isLinkerActive: boolean;
129138
source?: TableTemplate;
130139
sourcePanel?: PanelComponent;
131140
columnSelectionValidator?: ColumnSelectionValidator;
141+
settings: Partial<WorkspaceSettings>;
142+
}
143+
144+
interface DispatchProps {
132145
setActiveTool: (tool: string) => void;
133146
setDashboardIsolatedLinkerPanelId: (
134147
id: string,
135148
secondParam: undefined
136149
) => void;
137-
Plotly?: typeof PlotlyType;
138-
/** The panel container div */
139-
containerRef?: RefObject<HTMLDivElement>;
140-
141-
panelState: GLChartPanelState;
142-
settings: Partial<WorkspaceSettings>;
143150
}
144151

145152
interface ChartPanelState {
@@ -178,6 +185,11 @@ function hasPanelState(
178185
return (panel as { panelState: IrisGridPanelState }).panelState != null;
179186
}
180187

188+
export type ChartPanelProps = OwnProps &
189+
StateProps &
190+
DispatchProps &
191+
React.RefAttributes<ChartPanel>;
192+
181193
export class ChartPanel extends Component<ChartPanelProps, ChartPanelState> {
182194
static defaultProps = {
183195
columnSelectionValidator: null,
@@ -1046,7 +1058,7 @@ export class ChartPanel extends Component<ChartPanelProps, ChartPanelState> {
10461058
if (isChartPanelTableMetadata(metadata)) {
10471059
name = metadata.table;
10481060
} else {
1049-
name = metadata.figure;
1061+
name = metadata.name ?? metadata.figure;
10501062
}
10511063
const inputFilterMap = this.getInputFilterColumnMap(
10521064
columnMap,
@@ -1157,23 +1169,10 @@ export class ChartPanel extends Component<ChartPanelProps, ChartPanelState> {
11571169
}
11581170
}
11591171

1160-
const mapStateToProps = (
1161-
state: RootState,
1162-
ownProps: { localDashboardId: string; metadata: { sourcePanelId?: string } }
1163-
): Omit<
1164-
ChartPanelProps,
1165-
| 'glContainer'
1166-
| 'glEventHub'
1167-
| 'localDashboardId'
1168-
| 'makeModel'
1169-
| 'metadata'
1170-
| 'panelState'
1171-
| 'setActiveTool'
1172-
| 'setDashboardIsolatedLinkerPanelId'
1173-
> => {
1172+
const mapStateToProps = (state: RootState, ownProps: OwnProps): StateProps => {
11741173
const { localDashboardId, metadata } = ownProps;
11751174

1176-
let sourcePanelId;
1175+
let sourcePanelId: string | undefined;
11771176
if (metadata != null) {
11781177
sourcePanelId = metadata.sourcePanelId;
11791178
}
@@ -1207,7 +1206,7 @@ const ConnectedChartPanel = connect(
12071206
{
12081207
setActiveTool: setActiveToolAction,
12091208
setDashboardIsolatedLinkerPanelId: setDashboardIsolatedLinkerPanelIdAction,
1210-
},
1209+
} satisfies DispatchProps,
12111210
null,
12121211
{ forwardRef: true }
12131212
)(ChartPanel);

0 commit comments

Comments
 (0)