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

fix: Changes for Deephaven UI embedding widget plugins #1644

Merged
merged 7 commits into from
Nov 20, 2023
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
3 changes: 2 additions & 1 deletion packages/chart/src/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ interface ChartProps {
settings: FormatterSettings;
isActive: boolean;
Plotly: typeof Plotly;
containerRef?: React.RefObject<HTMLDivElement>;
onDisconnect: () => void;
onReconnect: () => void;
onUpdate: (obj: { isLoading: boolean }) => void;
Expand Down Expand Up @@ -145,7 +146,7 @@ export class Chart extends Component<ChartProps, ChartState> {

this.PlotComponent = createPlotlyComponent(props.Plotly);
this.plot = React.createRef();
this.plotWrapper = React.createRef();
this.plotWrapper = props.containerRef ?? React.createRef();
this.columnFormats = [];
this.dateTimeFormatterOptions = {};
this.decimalFormatOptions = {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import type {
} from '@deephaven/jsapi-types';
import { IrisGridUtils } from '@deephaven/iris-grid';
import { getTimeZone, store } from '@deephaven/redux';
import { type WidgetComponentProps } from '@deephaven/plugin';
import { WidgetPanelProps } from '@deephaven/plugin';
import {
ChartPanelMetadata,
GLChartPanelState,
Expand Down Expand Up @@ -113,8 +113,8 @@ async function createChartModel(
);
}

export const ChartPlugin = forwardRef(
(props: WidgetComponentProps, ref: React.Ref<ChartPanel>) => {
export const ChartPanelPlugin = forwardRef(
(props: WidgetPanelProps, ref: React.Ref<ChartPanel>) => {
const dh = useApi();
const chartTheme = useChartTheme();
const connection = useConnection();
Expand Down Expand Up @@ -160,6 +160,6 @@ export const ChartPlugin = forwardRef(
}
);

ChartPlugin.displayName = 'ChartPlugin';
ChartPanelPlugin.displayName = 'ChartPanelPlugin';

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

const ChartPluginConfig: WidgetPlugin = {
name: 'ChartPanel',
title: 'Chart',
type: PluginType.WIDGET_PLUGIN,
component: ChartPlugin,
panelComponent: ChartPlugin,
component: ChartWidgetPlugin,
panelComponent: ChartPanelPlugin,
supportedTypes: 'Figure',
icon: vsGraph,
};
Expand Down
47 changes: 47 additions & 0 deletions packages/dashboard-core-plugins/src/ChartWidgetPlugin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useEffect, useState } from 'react';
import { useApi } from '@deephaven/jsapi-bootstrap';
import {
Chart,
ChartModel,
ChartModelFactory,
useChartTheme,
} from '@deephaven/chart';
import type { Figure } from '@deephaven/jsapi-types';
import { type WidgetComponentProps } from '@deephaven/plugin';

export function ChartWidgetPlugin(
props: WidgetComponentProps
): JSX.Element | null {
const dh = useApi();
const chartTheme = useChartTheme();
const [model, setModel] = useState<ChartModel>();

const { fetch } = props;

useEffect(() => {
let cancelled = false;
async function init() {
const figure = (await fetch()) as unknown as Figure;
const newModel = await ChartModelFactory.makeModel(
dh,
undefined,
figure,
chartTheme
);

if (!cancelled) {
setModel(newModel);
}
}

init();

return () => {
cancelled = true;
};
}, [dh, fetch, chartTheme]);

return model ? <Chart model={model} /> : null;
}

export default ChartWidgetPlugin;
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { forwardRef } from 'react';
import { type WidgetComponentProps } from '@deephaven/plugin';
import { WidgetPanelProps } from '@deephaven/plugin';
import { type Table } from '@deephaven/jsapi-types';
import useHydrateGrid from './useHydrateGrid';
import ConnectedIrisGridPanel, {
type IrisGridPanel,
} from './panels/IrisGridPanel';

export const GridPlugin = forwardRef(
(props: WidgetComponentProps, ref: React.Ref<IrisGridPanel>) => {
export const GridPanelPlugin = forwardRef(
(props: WidgetPanelProps, ref: React.Ref<IrisGridPanel>) => {
const { localDashboardId, fetch } = props;
const hydratedProps = useHydrateGrid(
fetch as unknown as () => Promise<Table>,
Expand All @@ -19,6 +19,6 @@ export const GridPlugin = forwardRef(
}
);

GridPlugin.displayName = 'GridPlugin';
GridPanelPlugin.displayName = 'GridPanelPlugin';

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

const GridPluginConfig: WidgetPlugin = {
name: 'IrisGridPanel',
title: 'Table',
type: PluginType.WIDGET_PLUGIN,
component: GridPlugin,
panelComponent: GridPlugin,
component: GridWidgetPlugin,
panelComponent: GridPanelPlugin,
supportedTypes: ['Table', 'TreeTable', 'HierarchicalTable'],
icon: dhTable,
};
Expand Down
39 changes: 39 additions & 0 deletions packages/dashboard-core-plugins/src/GridWidgetPlugin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useEffect, useState } from 'react';
import { type WidgetComponentProps } from '@deephaven/plugin';
import { type Table } from '@deephaven/jsapi-types';
import { useApi } from '@deephaven/jsapi-bootstrap';
import {
IrisGrid,
IrisGridModelFactory,
type IrisGridModel,
} from '@deephaven/iris-grid';

export function GridWidgetPlugin(
props: WidgetComponentProps
): JSX.Element | null {
const dh = useApi();
const [model, setModel] = useState<IrisGridModel>();

const { fetch } = props;

useEffect(() => {
let cancelled = false;
async function init() {
const table = (await fetch()) as unknown as Table;
const newModel = await IrisGridModelFactory.makeModel(dh, table);
if (!cancelled) {
setModel(newModel);
}
}

init();

return () => {
cancelled = true;
};
}, [dh, fetch]);

return model ? <IrisGrid model={model} /> : null;
}

export default GridWidgetPlugin;
24 changes: 24 additions & 0 deletions packages/dashboard-core-plugins/src/PandasPanelPlugin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { forwardRef } from 'react';
import { WidgetPanelProps } from '@deephaven/plugin';
import { type Table } from '@deephaven/jsapi-types';
import { PandasPanel } from './panels';
import useHydrateGrid from './useHydrateGrid';

export const PandasPanelPlugin = forwardRef(
(props: WidgetPanelProps, ref: React.Ref<PandasPanel>) => {
const { localDashboardId, fetch } = props;
const hydratedProps = useHydrateGrid(
fetch as unknown as () => Promise<Table>,
localDashboardId
);

return (
// eslint-disable-next-line react/jsx-props-no-spreading
<PandasPanel ref={ref} {...props} {...hydratedProps} />
);
}
);

PandasPanelPlugin.displayName = 'PandasPanelPlugin';

export default PandasPanelPlugin;
22 changes: 0 additions & 22 deletions packages/dashboard-core-plugins/src/PandasPlugin.tsx

This file was deleted.

8 changes: 4 additions & 4 deletions packages/dashboard-core-plugins/src/PandasPluginConfig.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { PluginType, WidgetPlugin } from '@deephaven/plugin';
import { dhPandas } from '@deephaven/icons';
import PandasPlugin from './PandasPlugin';
import { PandasWidgetPlugin } from './PandasWidgetPlugin';
import { PandasPanelPlugin } from './PandasPanelPlugin';

const PandasPluginConfig: WidgetPlugin = {
name: 'PandasPanel',
title: 'Pandas',
type: PluginType.WIDGET_PLUGIN,
// TODO: #1573 Replace with actual base component and not just the panel plugin
component: PandasPlugin,
panelComponent: PandasPlugin,
component: PandasWidgetPlugin,
panelComponent: PandasPanelPlugin,
supportedTypes: 'pandas.DataFrame',
icon: dhPandas,
};
Expand Down
65 changes: 65 additions & 0 deletions packages/dashboard-core-plugins/src/PandasWidgetPlugin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { useCallback, useEffect, useState } from 'react';
import { WidgetComponentProps } from '@deephaven/plugin';
import { type Table } from '@deephaven/jsapi-types';
import IrisGrid, {
IrisGridModelFactory,
type IrisGridModel,
} from '@deephaven/iris-grid';
import { useApi } from '@deephaven/jsapi-bootstrap';
import { LoadingOverlay } from '@deephaven/components';
import { PandasReloadButton } from './panels/PandasReloadButton';

export function PandasWidgetPlugin(
props: WidgetComponentProps
): JSX.Element | null {
const dh = useApi();
const [model, setModel] = useState<IrisGridModel>();
const [isLoading, setIsLoading] = useState(true);
const [isLoaded, setIsLoaded] = useState(false);

const { fetch } = props;

const makeModel = useCallback(async () => {
const table = (await fetch()) as unknown as Table;
return IrisGridModelFactory.makeModel(dh, table);
}, [dh, fetch]);

const handleReload = useCallback(async () => {
setIsLoading(true);
const newModel = await makeModel();
setModel(newModel);
setIsLoading(false);
}, [makeModel]);

useEffect(() => {
let cancelled = false;
async function init() {
const newModel = await makeModel();
if (!cancelled) {
setModel(newModel);
setIsLoaded(true);
setIsLoading(false);
}
}

init();
setIsLoading(true);

return () => {
cancelled = true;
};
}, [makeModel]);

return (
<>
<LoadingOverlay isLoaded={isLoaded} isLoading={isLoading} />
{model && (
<IrisGrid model={model}>
<PandasReloadButton onClick={handleReload} />
</IrisGrid>
)}
</>
);
}

export default PandasWidgetPlugin;
9 changes: 6 additions & 3 deletions packages/dashboard-core-plugins/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
export { default as ChartPlugin } from './ChartPlugin';
export { default as ChartPanelPlugin } from './ChartPanelPlugin';
export { default as ChartWidgetPlugin } from './ChartWidgetPlugin';
export { default as ChartPluginConfig } from './ChartPluginConfig';
export { default as ChartBuilderPlugin } from './ChartBuilderPlugin';
export { default as ChartBuilderPluginConfig } from './ChartBuilderPluginConfig';
export { default as ConsolePlugin } from './ConsolePlugin';
export { default as FilterPlugin } from './FilterPlugin';
export { default as FilterPluginConfig } from './FilterPluginConfig';
export { default as GridPlugin } from './GridPlugin';
export { default as GridPanelPlugin } from './GridPanelPlugin';
export { default as GridWidgetPlugin } from './GridWidgetPlugin';
export { default as GridPluginConfig } from './GridPluginConfig';
export { default as LinkerPlugin } from './LinkerPlugin';
export { default as LinkerPluginConfig } from './LinkerPluginConfig';
export { default as MarkdownPlugin } from './MarkdownPlugin';
export { default as MarkdownPluginConfig } from './MarkdownPluginConfig';
export { default as PandasPlugin } from './PandasPlugin';
export { default as PandasPanelPlugin } from './PandasPanelPlugin';
export { default as PandasWidgetPlugin } from './PandasWidgetPlugin';
export { default as PandasPluginConfig } from './PandasPluginConfig';
export { default as WidgetLoaderPlugin } from './WidgetLoaderPlugin';
export { default as WidgetLoaderPluginConfig } from './WidgetLoaderPluginConfig';
Expand Down
6 changes: 4 additions & 2 deletions packages/dashboard-core-plugins/src/panels/ChartPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ interface OwnProps extends DashboardPanelProps {
makeModel: () => Promise<ChartModel>;
localDashboardId: string;
Plotly?: typeof PlotlyType;
/** The panel container div */
/** The plot container div */
containerRef?: RefObject<HTMLDivElement>;

panelState?: GLChartPanelState;
Expand Down Expand Up @@ -236,7 +236,7 @@ export class ChartPanel extends Component<ChartPanelProps, ChartPanelState> {
);
this.handleClearAllFilters = this.handleClearAllFilters.bind(this);

this.panelContainer = props.containerRef ?? React.createRef();
this.panelContainer = React.createRef();
this.pending = new Pending();

const { metadata, panelState } = props;
Expand Down Expand Up @@ -1035,6 +1035,7 @@ export class ChartPanel extends Component<ChartPanelProps, ChartPanelState> {
metadata,
settings,
Plotly,
containerRef,
} = this.props;
const {
columnMap,
Expand Down Expand Up @@ -1117,6 +1118,7 @@ export class ChartPanel extends Component<ChartPanelProps, ChartPanelState> {
onError={this.handleError}
onSettingsChanged={this.handleSettingsChanged}
Plotly={Plotly}
containerRef={containerRef}
/>
)}
</div>
Expand Down
Loading
Loading