Skip to content

Commit

Permalink
feat: Convert DashboardPlugins to WidgetPlugins (deephaven#1598)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattrunyon authored Oct 30, 2023
1 parent e0bbdf0 commit a260842
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 127 deletions.
78 changes: 38 additions & 40 deletions packages/dashboard-core-plugins/src/ChartPlugin.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
import { useCallback } from 'react';
import {
assertIsDashboardPluginProps,
DashboardPluginComponentProps,
DehydratedDashboardPanelProps,
useDashboardPanel,
} from '@deephaven/dashboard';
import { forwardRef, useMemo } from 'react';
import { useApi } from '@deephaven/jsapi-bootstrap';
import { useConnection } from '@deephaven/jsapi-components';
import { ChartModel, ChartModelFactory } from '@deephaven/chart';
import type { dh as DhType, IdeConnection } from '@deephaven/jsapi-types';
import { IrisGridUtils } from '@deephaven/iris-grid';
import { getTimeZone, store } from '@deephaven/redux';
import { type WidgetComponentProps } from '@deephaven/plugin';
import {
ChartPanel,
ChartPanelMetadata,
GLChartPanelState,
isChartPanelDehydratedProps,
isChartPanelTableMetadata,
} from './panels';
import ConnectedChartPanel, {
type ChartPanel,
type ChartPanelProps,
} from './panels/ChartPanel';

async function createChartModel(
dh: DhType,
Expand Down Expand Up @@ -86,41 +84,41 @@ async function createChartModel(
return ChartModelFactory.makeModelFromSettings(dh, settings as any, table);
}

export function ChartPlugin(
props: DashboardPluginComponentProps
): JSX.Element | null {
assertIsDashboardPluginProps(props);
const dh = useApi();
const connection = useConnection();
export const ChartPlugin = forwardRef(
(props: WidgetComponentProps, ref: React.Ref<ChartPanel>) => {
const dh = useApi();
const connection = useConnection();

const hydrate = useCallback(
(hydrateProps: DehydratedDashboardPanelProps, id: string) => ({
...hydrateProps,
localDashboardId: id,
makeModel: () => {
const { metadata } = hydrateProps;
const panelState = isChartPanelDehydratedProps(hydrateProps)
? hydrateProps.panelState
: undefined;
if (metadata == null) {
throw new Error('Metadata is required for chart panel');
}
const hydratedProps = useMemo(
() => ({
...(props as unknown as ChartPanelProps),
metadata: props.metadata as ChartPanelMetadata,
localDashboardId: props.localDashboardId,
makeModel: () => {
const { metadata } = props;
const panelState = isChartPanelDehydratedProps(props)
? (props as unknown as ChartPanelProps).panelState
: undefined;
if (metadata == null) {
throw new Error('Metadata is required for chart panel');
}

return createChartModel(dh, connection, metadata, panelState);
},
}),
[dh, connection]
);
return createChartModel(
dh,
connection,
metadata as ChartPanelMetadata,
panelState
);
},
}),
[dh, connection, props]
);

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

return null;
}
ChartPlugin.displayName = 'ChartPlugin';

export default ChartPlugin;
13 changes: 9 additions & 4 deletions packages/dashboard-core-plugins/src/ChartPluginConfig.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { PluginType, DashboardPlugin } from '@deephaven/plugin';
import { PluginType, type WidgetPlugin } from '@deephaven/plugin';
import { vsGraph } from '@deephaven/icons';
import ChartPlugin from './ChartPlugin';

const ChartPluginConfig: DashboardPlugin = {
name: 'ChartPlugin',
type: PluginType.DASHBOARD_PLUGIN,
const ChartPluginConfig: WidgetPlugin = {
name: 'ChartPanel',
title: 'Chart',
type: PluginType.WIDGET_PLUGIN,
component: ChartPlugin,
panelComponent: ChartPlugin,
supportedTypes: 'Figure',
icon: vsGraph,
};

export default ChartPluginConfig;
59 changes: 27 additions & 32 deletions packages/dashboard-core-plugins/src/GridPlugin.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,33 @@
import { useMemo } from 'react';
import {
assertIsDashboardPluginProps,
DashboardPluginComponentProps,
useDashboardPanel,
} from '@deephaven/dashboard';
import { useApi } from '@deephaven/jsapi-bootstrap';
import { IrisGridPanel } from './panels';
import { forwardRef, useMemo } from 'react';
import { type WidgetComponentProps } from '@deephaven/plugin';
import { type DashboardPanelProps } from '@deephaven/dashboard';
import useHydrateGrid from './useHydrateGrid';
import ConnectedIrisGridPanel, {
IrisGridPanelProps,
type IrisGridPanel,
} from './panels/IrisGridPanel';

export function GridPlugin(
props: DashboardPluginComponentProps
): JSX.Element | null {
assertIsDashboardPluginProps(props);
const dh = useApi();
const hydrate = useHydrateGrid();
export const GridPlugin = forwardRef(
(props: WidgetComponentProps, ref: React.Ref<IrisGridPanel>) => {
const hydrate = useHydrateGrid<
DashboardPanelProps & Pick<IrisGridPanelProps, 'panelState'>
>();
const { localDashboardId } = props;
const hydratedProps = useMemo(
() =>
hydrate(
props as WidgetComponentProps &
Pick<IrisGridPanelProps, 'panelState'>,
localDashboardId
),
[hydrate, props, localDashboardId]
);

const supportedTypes = useMemo(
() => [
dh.VariableType.TABLE,
dh.VariableType.TREETABLE,
dh.VariableType.HIERARCHICALTABLE,
],
[dh]
);
// eslint-disable-next-line react/jsx-props-no-spreading
return <ConnectedIrisGridPanel ref={ref} {...hydratedProps} />;
}
);

useDashboardPanel({
dashboardProps: props,
componentName: IrisGridPanel.COMPONENT,
component: IrisGridPanel,
supportedTypes,
hydrate,
});

return null;
}
GridPlugin.displayName = 'GridPlugin';

export default GridPlugin;
13 changes: 9 additions & 4 deletions packages/dashboard-core-plugins/src/GridPluginConfig.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { PluginType, DashboardPlugin } from '@deephaven/plugin';
import { PluginType, type WidgetPlugin } from '@deephaven/plugin';
import { dhTable } from '@deephaven/icons';
import GridPlugin from './GridPlugin';

const GridPluginConfig: DashboardPlugin = {
name: 'GridPlugin',
type: PluginType.DASHBOARD_PLUGIN,
const GridPluginConfig: WidgetPlugin = {
name: 'IrisGridPanel',
title: 'Table',
type: PluginType.WIDGET_PLUGIN,
component: GridPlugin,
panelComponent: GridPlugin,
supportedTypes: ['Table', 'TreeTable', 'HierarchicalTable'],
icon: dhTable,
};

export default GridPluginConfig;
2 changes: 1 addition & 1 deletion packages/dashboard-core-plugins/src/PandasPluginConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { dhPandas } from '@deephaven/icons';
import PandasPlugin from './PandasPlugin';

const PandasPluginConfig: WidgetPlugin = {
name: 'PandasPlugin',
name: 'PandasPanel',
title: 'Pandas',
type: PluginType.WIDGET_PLUGIN,
// TODO: #1573 Replace with actual base component and not just the panel plugin
Expand Down
1 change: 0 additions & 1 deletion packages/dashboard-core-plugins/src/WidgetLoaderPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ export function WrapWidgetPlugin(
{...props}
/>
)}
)
</WidgetPanel>
);
}
Expand Down
4 changes: 0 additions & 4 deletions packages/dashboard-core-plugins/src/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import { type IdeConnection } from '@deephaven/jsapi-types';
import { ConnectionContext } from '@deephaven/jsapi-components';
import { PluginsContext } from '@deephaven/plugin';
import {
ChartPlugin,
ConsolePlugin,
FilterPlugin,
GridPlugin,
LinkerPlugin,
MarkdownPlugin,
WidgetLoaderPlugin,
Expand All @@ -36,8 +34,6 @@ it('handles mounting and unmount core plugins properly', () => {
<Provider store={store}>
<Dashboard>
<FilterPlugin />
<GridPlugin hydrate={() => undefined} />
<ChartPlugin hydrate={() => undefined} />
<ConsolePlugin />
<LinkerPlugin />
<MarkdownPlugin />
Expand Down
49 changes: 24 additions & 25 deletions packages/dashboard-core-plugins/src/panels/ChartPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export interface ChartPanelFigureMetadata extends PanelMetadata {
* @deprecated use `name` instead
*/
figure?: string;
sourcePanelId: never;
}

export interface ChartPanelTableMetadata extends PanelMetadata {
Expand Down Expand Up @@ -118,28 +119,34 @@ export interface GLChartPanelState {
table?: string;
figure?: string;
}
export interface ChartPanelProps extends DashboardPanelProps {
interface OwnProps extends DashboardPanelProps {
metadata: ChartPanelMetadata;
/** Function to build the ChartModel used by this ChartPanel. Can return a promise. */
makeModel: () => Promise<ChartModel>;
localDashboardId: string;
Plotly?: typeof PlotlyType;
/** The panel container div */
containerRef?: RefObject<HTMLDivElement>;

panelState: GLChartPanelState;
}

interface StateProps {
inputFilters: InputFilter[];
links: Link[];
localDashboardId: string;
isLinkerActive: boolean;
source?: TableTemplate;
sourcePanel?: PanelComponent;
columnSelectionValidator?: ColumnSelectionValidator;
settings: Partial<WorkspaceSettings>;
}

interface DispatchProps {
setActiveTool: (tool: string) => void;
setDashboardIsolatedLinkerPanelId: (
id: string,
secondParam: undefined
) => void;
Plotly?: typeof PlotlyType;
/** The panel container div */
containerRef?: RefObject<HTMLDivElement>;

panelState: GLChartPanelState;
settings: Partial<WorkspaceSettings>;
}

interface ChartPanelState {
Expand Down Expand Up @@ -178,6 +185,11 @@ function hasPanelState(
return (panel as { panelState: IrisGridPanelState }).panelState != null;
}

export type ChartPanelProps = OwnProps &
StateProps &
DispatchProps &
React.RefAttributes<ChartPanel>;

export class ChartPanel extends Component<ChartPanelProps, ChartPanelState> {
static defaultProps = {
columnSelectionValidator: null,
Expand Down Expand Up @@ -1046,7 +1058,7 @@ export class ChartPanel extends Component<ChartPanelProps, ChartPanelState> {
if (isChartPanelTableMetadata(metadata)) {
name = metadata.table;
} else {
name = metadata.figure;
name = metadata.name ?? metadata.figure;
}
const inputFilterMap = this.getInputFilterColumnMap(
columnMap,
Expand Down Expand Up @@ -1157,23 +1169,10 @@ export class ChartPanel extends Component<ChartPanelProps, ChartPanelState> {
}
}

const mapStateToProps = (
state: RootState,
ownProps: { localDashboardId: string; metadata: { sourcePanelId?: string } }
): Omit<
ChartPanelProps,
| 'glContainer'
| 'glEventHub'
| 'localDashboardId'
| 'makeModel'
| 'metadata'
| 'panelState'
| 'setActiveTool'
| 'setDashboardIsolatedLinkerPanelId'
> => {
const mapStateToProps = (state: RootState, ownProps: OwnProps): StateProps => {
const { localDashboardId, metadata } = ownProps;

let sourcePanelId;
let sourcePanelId: string | undefined;
if (metadata != null) {
sourcePanelId = metadata.sourcePanelId;
}
Expand Down Expand Up @@ -1207,7 +1206,7 @@ const ConnectedChartPanel = connect(
{
setActiveTool: setActiveToolAction,
setDashboardIsolatedLinkerPanelId: setDashboardIsolatedLinkerPanelIdAction,
},
} satisfies DispatchProps,
null,
{ forwardRef: true }
)(ChartPanel);
Expand Down
Loading

0 comments on commit a260842

Please sign in to comment.