From e1b4562585fd6ea07efe085fe7ae5128a689ce37 Mon Sep 17 00:00:00 2001 From: Vlad Babich Date: Fri, 26 Jan 2024 08:57:48 -0700 Subject: [PATCH] feat: Add pluginDataMap to redux, add useDashboardPluginData hook (#1737) Add `useDashboardPluginData` hook for accessing plugin data in redux --- packages/dashboard/src/redux/actions.ts | 27 ++++++++++++++++++-- packages/dashboard/src/redux/hooks.ts | 28 +++++++++++++++++++++ packages/dashboard/src/redux/index.ts | 1 + packages/dashboard/src/redux/selectors.ts | 30 ++++++++++++++++++++++- packages/redux/src/store.ts | 9 ++++++- 5 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 packages/dashboard/src/redux/hooks.ts diff --git a/packages/dashboard/src/redux/actions.ts b/packages/dashboard/src/redux/actions.ts index 1fd9b14225..7347efebd3 100644 --- a/packages/dashboard/src/redux/actions.ts +++ b/packages/dashboard/src/redux/actions.ts @@ -1,8 +1,8 @@ -import { DashboardData, RootState } from '@deephaven/redux'; +import { DashboardData, PluginData, RootState } from '@deephaven/redux'; import type { Action } from 'redux'; import type { ThunkAction } from 'redux-thunk'; import { SET_DASHBOARD_DATA } from './actionTypes'; -import { getDashboardData } from './selectors'; +import { getDashboardData, getPluginDataMapForDashboard } from './selectors'; /** * Action to replace the dashboard data for a dashboard @@ -41,3 +41,26 @@ export const updateDashboardData = ...data, }) ); + +/** + * Action to update the dashboard data. Will combine the update with any existing dashboard data. + * @param id The id of the dashboard to set the data on + * @param pluginId The id of the plugin to set the data on + * @param data The data to replace the existing plugin data with + * @returns + */ +export const setDashboardPluginData = + ( + id: string, + pluginId: string, + data: PluginData + ): ThunkAction> => + (dispatch, getState) => + dispatch( + setDashboardData(id, { + ...getDashboardData(getState(), id), + pluginDataMap: new Map( + getPluginDataMapForDashboard(getState(), id) + ).set(pluginId, data), + }) + ); diff --git a/packages/dashboard/src/redux/hooks.ts b/packages/dashboard/src/redux/hooks.ts new file mode 100644 index 0000000000..a0cffe7c3b --- /dev/null +++ b/packages/dashboard/src/redux/hooks.ts @@ -0,0 +1,28 @@ +import { useCallback } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { PluginData, RootState } from '@deephaven/redux'; +import { getPluginDataForDashboard } from './selectors'; +import { setDashboardPluginData } from './actions'; + +/** + * Custom hook that provides access to plugin data for a specific dashboard and plugin. + * @param dashboardId - The ID of the dashboard. + * @param pluginId - The ID of the plugin. + * @returns A tuple containing the plugin data and a function to update the plugin data. + */ +export function useDashboardPluginData( + dashboardId: string, + pluginId: string +): [PluginData, (data: PluginData) => void] { + const dispatch = useDispatch(); + const data = useSelector((store: RootState) => + getPluginDataForDashboard(store, dashboardId, pluginId) + ); + const setData = useCallback( + newData => dispatch(setDashboardPluginData(dashboardId, pluginId, newData)), + [dashboardId, pluginId, dispatch] + ); + return [data, setData]; +} + +export default { useDashboardPluginData }; diff --git a/packages/dashboard/src/redux/index.ts b/packages/dashboard/src/redux/index.ts index 9072744bcc..3087c32659 100644 --- a/packages/dashboard/src/redux/index.ts +++ b/packages/dashboard/src/redux/index.ts @@ -8,4 +8,5 @@ Object.entries(reducers).map(([name, reducer]) => export { reducers }; export * from './actions'; export * from './actionTypes'; +export * from './hooks'; export * from './selectors'; diff --git a/packages/dashboard/src/redux/selectors.ts b/packages/dashboard/src/redux/selectors.ts index 67dde9cf77..506013d37d 100644 --- a/packages/dashboard/src/redux/selectors.ts +++ b/packages/dashboard/src/redux/selectors.ts @@ -1,4 +1,9 @@ -import { DashboardData, RootState } from '@deephaven/redux'; +import { + DashboardData, + PluginData, + PluginDataMap, + RootState, +} from '@deephaven/redux'; import { ClosedPanels, OpenedPanelMap } from '../PanelManager'; const EMPTY_MAP = new Map(); @@ -50,3 +55,26 @@ export const getOpenedPanelMapForDashboard = ( ): OpenedPanelMap => (getDashboardData(store, dashboardId).openedMap ?? EMPTY_MAP) as OpenedPanelMap; + +/** + * @param store The redux store + * @param dashboardId The dashboard ID to get data for + * @returns The map of plugin IDs to data for all plugins on the dashboard + */ +export const getPluginDataMapForDashboard = ( + store: RootState, + dashboardId: string +): PluginDataMap => + getDashboardData(store, dashboardId).pluginDataMap ?? EMPTY_MAP; + +/** + * @param store The redux store + * @param dashboardId The dashboard ID to get data for + * @param pluginId The plugin ID to get data for + * @returns The plugin data + */ +export const getPluginDataForDashboard = ( + store: RootState, + dashboardId: string, + pluginId: string +): PluginData => getPluginDataMapForDashboard(store, dashboardId).get(pluginId); diff --git a/packages/redux/src/store.ts b/packages/redux/src/store.ts index 6462d81162..e8e88d3624 100644 --- a/packages/redux/src/store.ts +++ b/packages/redux/src/store.ts @@ -77,7 +77,14 @@ export interface CustomizableWorkspace { export interface Workspace { data: WorkspaceData; } -export type DashboardData = Record; + +export type PluginData = unknown; + +export type PluginDataMap = Map; + +export type DashboardData = Record & { + pluginDataMap?: PluginDataMap; +}; export type WorkspaceStorageLoadOptions = { isConsoleAvailable: boolean;