From 9fbe39a4fa007b92c8f79600d5b4a0a811bd9ae2 Mon Sep 17 00:00:00 2001 From: Matt Seddon Date: Mon, 15 Jan 2024 11:33:54 +1100 Subject: [PATCH 1/5] swap setup webview feed store switch statement for enum --- webview/src/setup/components/App.tsx | 88 +++++++++------------------- 1 file changed, 27 insertions(+), 61 deletions(-) diff --git a/webview/src/setup/components/App.tsx b/webview/src/setup/components/App.tsx index 6df301ecba..0984a7ecc6 100644 --- a/webview/src/setup/components/App.tsx +++ b/webview/src/setup/components/App.tsx @@ -59,6 +59,26 @@ const getStudioStatusIcon = (cliCompatible: boolean, isConnected: boolean) => { return isConnected ? TooltipIconType.PASSED : TooltipIconType.WARNING } +const actionToDispatch = { + canGitInitialize: updateCanGitInitialize, + cliCompatible: updateCliCompatible, + dvcCliDetails: updateDvcCliDetails, + hasData: updateExperimentsHasData, + isAboveLatestTestedVersion: updateIsAboveLatestTestedVersion, + isPythonEnvironmentGlobal: updateIsPythonEnvironmentGlobal, + isPythonExtensionInstalled: updateIsPythonExtensionInstalled, + isPythonExtensionUsed: updateIsPythonExtensionUsed, + isStudioConnected: updateIsStudioConnected, + needsGitCommit: updateNeedsGitCommit, + needsGitInitialized: updateNeedsGitInitialized, + projectInitialized: updateProjectInitialized, + pythonBinPath: updatePythonBinPath, + remoteList: updateRemoteList, + sectionCollapsed: updateSectionCollapsed, + selfHostedStudioUrl: updateSelfHostedStudioUrl, + shareLiveToStudio: updateShareLiveToStudio +} as const + export const feedStore = ( data: MessageToWebview, dispatch: SetupDispatch @@ -67,69 +87,15 @@ export const feedStore = ( return } dispatch(updateWebviewHasData()) - for (const key of Object.keys(data.data)) { - switch (key) { - case 'canGitInitialize': - dispatch(updateCanGitInitialize(data.data.canGitInitialize)) - continue - case 'cliCompatible': - dispatch(updateCliCompatible(data.data.cliCompatible)) - continue - case 'dvcCliDetails': - dispatch(updateDvcCliDetails(data.data.dvcCliDetails)) - continue - case 'hasData': - dispatch(updateExperimentsHasData(data.data.hasData)) - continue - case 'isPythonEnvironmentGlobal': - dispatch( - updateIsPythonEnvironmentGlobal(data.data.isPythonEnvironmentGlobal) - ) - continue - case 'isPythonExtensionInstalled': - dispatch( - updateIsPythonExtensionInstalled(data.data.isPythonExtensionInstalled) - ) - continue - case 'isPythonExtensionUsed': - dispatch(updateIsPythonExtensionUsed(data.data.isPythonExtensionUsed)) - continue - case 'isAboveLatestTestedVersion': - dispatch( - updateIsAboveLatestTestedVersion(data.data.isAboveLatestTestedVersion) - ) - continue - case 'isStudioConnected': - dispatch(updateIsStudioConnected(data.data.isStudioConnected)) - continue - case 'needsGitCommit': - dispatch(updateNeedsGitCommit(data.data.needsGitCommit)) - continue - case 'needsGitInitialized': - dispatch(updateNeedsGitInitialized(data.data.needsGitInitialized)) - continue - case 'projectInitialized': - dispatch(updateProjectInitialized(data.data.projectInitialized)) - continue - case 'pythonBinPath': - dispatch(updatePythonBinPath(data.data.pythonBinPath)) - continue - case 'sectionCollapsed': - dispatch(updateSectionCollapsed(data.data.sectionCollapsed)) - continue - case 'shareLiveToStudio': - dispatch(updateShareLiveToStudio(data.data.shareLiveToStudio)) - continue - case 'selfHostedStudioUrl': - dispatch(updateSelfHostedStudioUrl(data.data.selfHostedStudioUrl)) - continue - case 'remoteList': - dispatch(updateRemoteList(data.data.remoteList)) - continue - default: - continue + for (const key of Object.keys(data.data)) { + const tKey = key as keyof typeof data.data + const action = actionToDispatch[tKey] + const value = data.data[tKey] + if (!action) { + continue } + dispatch(action(value as never)) } } From dbd2eea3811de169c733ff35327708ba29d18813 Mon Sep 17 00:00:00 2001 From: Matt Seddon Date: Mon, 15 Jan 2024 12:21:18 +1100 Subject: [PATCH 2/5] swap plots webview feed store switch statement for enum --- webview/src/plots/components/App.tsx | 88 ++++++++++--------------- webview/src/setup/components/App.tsx | 7 +- webview/src/setup/state/webviewSlice.ts | 8 +-- 3 files changed, 42 insertions(+), 61 deletions(-) diff --git a/webview/src/plots/components/App.tsx b/webview/src/plots/components/App.tsx index cfb94cdaac..ca83f3910f 100644 --- a/webview/src/plots/components/App.tsx +++ b/webview/src/plots/components/App.tsx @@ -1,13 +1,10 @@ import React, { useCallback } from 'react' import { useDispatch } from 'react-redux' import { - CustomPlotsData, - PlotsComparisonData, PlotsData, PlotsDataKeys, PlotsSection, - SectionCollapsed, - TemplatePlotsData + SectionCollapsed } from 'dvc/src/plots/webview/contract' import { MessageToWebview } from 'dvc/src/webview/contract' import { Plots } from './Plots' @@ -49,59 +46,46 @@ const dispatchCollapsedSections = ( } } +const actionToDispatch = { + [PlotsDataKeys.CLI_ERROR]: updateCliError, + [PlotsDataKeys.CUSTOM]: updateCustomPlots, + [PlotsDataKeys.COMPARISON]: updateComparisonTable, + [PlotsDataKeys.TEMPLATE]: updateTemplatePlots, + [PlotsDataKeys.HAS_PLOTS]: updateHasPlots, + [PlotsDataKeys.HAS_UNSELECTED_PLOTS]: updateHasUnselectedPlots, + [PlotsDataKeys.PLOT_ERRORS]: updatePlotErrors, + [PlotsDataKeys.SELECTED_REVISIONS]: updateSelectedRevisions, + [PlotsDataKeys.SHOW_TOO_MANY_TEMPLATE_PLOTS]: + updateShouldShowTooManyTemplatesMessage, + [PlotsDataKeys.SHOW_TOO_MANY_COMPARISON_IMAGES]: + updateShouldShowTooManyImagesMessage +} as const + export const feedStore = ( data: MessageToWebview, dispatch: PlotsDispatch ) => { - if (data.data) { - dispatch(initialize()) - const keys = Object.keys(data.data) as PlotsDataKeys[] - for (const key of keys) { - switch (key) { - case PlotsDataKeys.CLI_ERROR: - dispatch(updateCliError(data.data[key])) - continue - case PlotsDataKeys.CUSTOM: - dispatch(updateCustomPlots(data.data[key] as CustomPlotsData)) - continue - case PlotsDataKeys.COMPARISON: - dispatch(updateComparisonTable(data.data[key] as PlotsComparisonData)) - continue - case PlotsDataKeys.TEMPLATE: - dispatch(updateTemplatePlots(data.data[key] as TemplatePlotsData)) - continue - case PlotsDataKeys.SECTION_COLLAPSED: - dispatchCollapsedSections( - data.data[key] as SectionCollapsed, - dispatch - ) - continue - case PlotsDataKeys.HAS_PLOTS: - dispatch(updateHasPlots(!!data.data[key])) - continue - case PlotsDataKeys.HAS_UNSELECTED_PLOTS: - dispatch(updateHasUnselectedPlots(!!data.data[key])) - continue - case PlotsDataKeys.PLOT_ERRORS: - dispatch(updatePlotErrors(data.data[key])) - continue - case PlotsDataKeys.SELECTED_REVISIONS: - dispatch(updateSelectedRevisions(data.data[key])) - continue - case PlotsDataKeys.SHOW_TOO_MANY_TEMPLATE_PLOTS: - dispatch( - updateShouldShowTooManyTemplatesMessage(data.data[key] as boolean) - ) - continue - case PlotsDataKeys.SHOW_TOO_MANY_COMPARISON_IMAGES: - dispatch( - updateShouldShowTooManyImagesMessage(data.data[key] as boolean) - ) - continue - default: - continue - } + if (!data?.data) { + return + } + dispatch(initialize()) + + const keys = Object.keys(data.data) as PlotsDataKeys[] + for (const key of keys) { + if (key === PlotsDataKeys.SECTION_COLLAPSED) { + dispatchCollapsedSections( + data.data[PlotsDataKeys.SECTION_COLLAPSED] as SectionCollapsed, + dispatch + ) + continue + } + + const action = actionToDispatch[key as keyof typeof actionToDispatch] + const value = data.data[key] + if (!action) { + continue } + dispatch(action(value as never)) } } diff --git a/webview/src/setup/components/App.tsx b/webview/src/setup/components/App.tsx index 0984a7ecc6..5a679f9575 100644 --- a/webview/src/setup/components/App.tsx +++ b/webview/src/setup/components/App.tsx @@ -10,10 +10,7 @@ import { Remotes } from './remotes/Remotes' import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging' import { TooltipIconType } from '../../shared/components/sectionContainer/InfoTooltip' import { SetupDispatch, SetupState } from '../store' -import { - updateSectionCollapsed, - updateHasData as updateWebviewHasData -} from '../state/webviewSlice' +import { initialize, updateSectionCollapsed } from '../state/webviewSlice' import { updateCanGitInitialize, updateCliCompatible, @@ -86,7 +83,7 @@ export const feedStore = ( if (!data?.data) { return } - dispatch(updateWebviewHasData()) + dispatch(initialize()) for (const key of Object.keys(data.data)) { const tKey = key as keyof typeof data.data diff --git a/webview/src/setup/state/webviewSlice.ts b/webview/src/setup/state/webviewSlice.ts index 4c875042f9..75e950ee6b 100644 --- a/webview/src/setup/state/webviewSlice.ts +++ b/webview/src/setup/state/webviewSlice.ts @@ -19,6 +19,9 @@ export const webviewSlice = createSlice({ initialState: webviewInitialState, name: 'webview', reducers: { + initialize: state => { + state.hasData = true + }, toggleSectionCollapsed: (state, action: PayloadAction) => { const section = action.payload state.sectionCollapsed = { @@ -26,9 +29,6 @@ export const webviewSlice = createSlice({ [section]: !state.sectionCollapsed[section] } }, - updateHasData: state => { - state.hasData = true - }, updateSectionCollapsed: ( state, action: PayloadAction @@ -40,7 +40,7 @@ export const webviewSlice = createSlice({ } }) -export const { updateHasData, updateSectionCollapsed, toggleSectionCollapsed } = +export const { initialize, updateSectionCollapsed, toggleSectionCollapsed } = webviewSlice.actions export default webviewSlice.reducer From 0a52fe9996742a0d0a00eee458d7b626000cdbfb Mon Sep 17 00:00:00 2001 From: Matt Seddon Date: Mon, 15 Jan 2024 12:46:12 +1100 Subject: [PATCH 3/5] swap experiments webview feed store switch statement for enum --- webview/src/experiments/components/App.tsx | 112 ++++++++------------- 1 file changed, 42 insertions(+), 70 deletions(-) diff --git a/webview/src/experiments/components/App.tsx b/webview/src/experiments/components/App.tsx index c8296d0f8d..1b4c5149e7 100644 --- a/webview/src/experiments/components/App.tsx +++ b/webview/src/experiments/components/App.tsx @@ -27,6 +27,47 @@ import { updateShowOnlyChanged } from '../state/tableDataSlice' import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging' +import { ExperimentsDispatch } from '../store' + +const actionToDispatch = { + changes: updateChanges, + cliError: updateCliError, + columnOrder: updateColumnOrder, + columnWidths: updateColumnWidths, + columns: updateColumns, + filters: updateFilters, + hasBranchesToSelect: updateHasBranchesToSelect, + hasCheckpoints: updateHasCheckpoints, + hasConfig: updateHasConfig, + hasMoreCommits: updateHasMoreCommits, + hasRunningWorkspaceExperiment: updateHasRunningWorkspaceExperiment, + isShowingMoreCommits: updateIsShowingMoreCommits, + rows: updateRows, + selectedBranches: updateSelectedBranches, + selectedForPlotsCount: updateSelectedForPlotsCount, + showOnlyChanged: updateShowOnlyChanged, + sorts: updateSorts +} as const + +const feedStore = ( + data: MessageToWebview, + dispatch: ExperimentsDispatch +) => { + if (data?.type !== MessageToWebviewType.SET_DATA) { + return + } + dispatch(update(!!data.data)) + + for (const key of Object.keys(data.data)) { + const tKey = key as keyof typeof data.data + const action = actionToDispatch[tKey] + const value = data.data[tKey] + if (!action) { + continue + } + dispatch(action(value as never)) + } +} export const App: React.FC> = () => { const dispatch = useDispatch() @@ -34,76 +75,7 @@ export const App: React.FC> = () => { useVsCodeMessaging( useCallback( ({ data }: { data: MessageToWebview }) => { - if (data.type === MessageToWebviewType.SET_DATA) { - dispatch(update(!!data.data)) - for (const key of Object.keys(data.data)) { - switch (key) { - case 'changes': - dispatch(updateChanges(data.data.changes)) - continue - case 'cliError': - dispatch(updateCliError(data.data.cliError)) - continue - case 'columnOrder': - dispatch(updateColumnOrder(data.data.columnOrder)) - continue - case 'columns': - dispatch(updateColumns(data.data.columns)) - continue - case 'columnsWidths': - dispatch(updateColumnWidths(data.data.columnWidths)) - continue - case 'filters': - dispatch(updateFilters(data.data.filters)) - continue - case 'hasBranchesToSelect': - dispatch( - updateHasBranchesToSelect(data.data.hasBranchesToSelect) - ) - continue - case 'hasCheckpoints': - dispatch(updateHasCheckpoints(data.data.hasCheckpoints)) - continue - case 'hasConfig': - dispatch(updateHasConfig(data.data.hasConfig)) - continue - case 'hasMoreCommits': - dispatch(updateHasMoreCommits(data.data.hasMoreCommits)) - continue - case 'hasRunningWorkspaceExperiment': - dispatch( - updateHasRunningWorkspaceExperiment( - data.data.hasRunningWorkspaceExperiment - ) - ) - continue - case 'isShowingMoreCommits': - dispatch( - updateIsShowingMoreCommits(data.data.isShowingMoreCommits) - ) - continue - case 'rows': - dispatch(updateRows(data.data.rows)) - continue - case 'selectedBranches': - dispatch(updateSelectedBranches(data.data.selectedBranches)) - continue - case 'selectedForPlotsCount': - dispatch( - updateSelectedForPlotsCount(data.data.selectedForPlotsCount) - ) - continue - case 'showOnlyChanged': - dispatch(updateShowOnlyChanged(data.data.showOnlyChanged)) - continue - case 'sorts': - dispatch(updateSorts(data.data.sorts)) - continue - default: - continue - } - } - } + feedStore(data, dispatch) }, [dispatch] ) From 3d929f1a21b25d6e16659466256aa11698c8d395 Mon Sep 17 00:00:00 2001 From: Matt Seddon Date: Mon, 15 Jan 2024 14:08:12 +1100 Subject: [PATCH 4/5] reduce duplication and refactor --- webview/src/experiments/components/App.tsx | 69 +-------- webview/src/plots/components/App.tsx | 82 ++--------- webview/src/setup/components/App.tsx | 70 +-------- webview/src/shared/dispatchAction.ts | 139 ++++++++++++++++++ .../src/shared/hooks/useVsCodeMessaging.ts | 20 ++- 5 files changed, 188 insertions(+), 192 deletions(-) create mode 100644 webview/src/shared/dispatchAction.ts diff --git a/webview/src/experiments/components/App.tsx b/webview/src/experiments/components/App.tsx index 1b4c5149e7..da5c0dd30a 100644 --- a/webview/src/experiments/components/App.tsx +++ b/webview/src/experiments/components/App.tsx @@ -1,53 +1,14 @@ -import React, { useCallback } from 'react' -import { useDispatch } from 'react-redux' +import React from 'react' import { MessageToWebview, MessageToWebviewType } from 'dvc/src/webview/contract' import { TableData } from 'dvc/src/experiments/webview/contract' import Experiments from './Experiments' -import { - update, - updateSelectedBranches, - updateChanges, - updateCliError, - updateColumnOrder, - updateColumns, - updateColumnWidths, - updateFilters, - updateHasBranchesToSelect, - updateHasCheckpoints, - updateHasConfig, - updateHasMoreCommits, - updateHasRunningWorkspaceExperiment, - updateIsShowingMoreCommits, - updateRows, - updateSelectedForPlotsCount, - updateSorts, - updateShowOnlyChanged -} from '../state/tableDataSlice' +import { update } from '../state/tableDataSlice' import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging' import { ExperimentsDispatch } from '../store' - -const actionToDispatch = { - changes: updateChanges, - cliError: updateCliError, - columnOrder: updateColumnOrder, - columnWidths: updateColumnWidths, - columns: updateColumns, - filters: updateFilters, - hasBranchesToSelect: updateHasBranchesToSelect, - hasCheckpoints: updateHasCheckpoints, - hasConfig: updateHasConfig, - hasMoreCommits: updateHasMoreCommits, - hasRunningWorkspaceExperiment: updateHasRunningWorkspaceExperiment, - isShowingMoreCommits: updateIsShowingMoreCommits, - rows: updateRows, - selectedBranches: updateSelectedBranches, - selectedForPlotsCount: updateSelectedForPlotsCount, - showOnlyChanged: updateShowOnlyChanged, - sorts: updateSorts -} as const +import { dispatchAction } from '../../shared/dispatchAction' const feedStore = ( data: MessageToWebview, @@ -56,30 +17,14 @@ const feedStore = ( if (data?.type !== MessageToWebviewType.SET_DATA) { return } - dispatch(update(!!data.data)) + const stateUpdate = data?.data + dispatch(update(!!stateUpdate)) - for (const key of Object.keys(data.data)) { - const tKey = key as keyof typeof data.data - const action = actionToDispatch[tKey] - const value = data.data[tKey] - if (!action) { - continue - } - dispatch(action(value as never)) - } + dispatchAction('experiments', stateUpdate, dispatch) } export const App: React.FC> = () => { - const dispatch = useDispatch() - - useVsCodeMessaging( - useCallback( - ({ data }: { data: MessageToWebview }) => { - feedStore(data, dispatch) - }, - [dispatch] - ) - ) + useVsCodeMessaging(feedStore) return } diff --git a/webview/src/plots/components/App.tsx b/webview/src/plots/components/App.tsx index ca83f3910f..602be7ddd3 100644 --- a/webview/src/plots/components/App.tsx +++ b/webview/src/plots/components/App.tsx @@ -1,5 +1,4 @@ -import React, { useCallback } from 'react' -import { useDispatch } from 'react-redux' +import React from 'react' import { PlotsData, PlotsDataKeys, @@ -8,30 +7,13 @@ import { } from 'dvc/src/plots/webview/contract' import { MessageToWebview } from 'dvc/src/webview/contract' import { Plots } from './Plots' -import { - setCollapsed as setCustomPlotsCollapsed, - update as updateCustomPlots -} from './customPlots/customPlotsSlice' -import { - setCollapsed as setComparisonTableCollapsed, - updateShouldShowTooManyPlotsMessage as updateShouldShowTooManyImagesMessage, - update as updateComparisonTable -} from './comparisonTable/comparisonTableSlice' -import { - setCollapsed as setTemplatePlotsCollapsed, - updateShouldShowTooManyPlotsMessage as updateShouldShowTooManyTemplatesMessage, - update as updateTemplatePlots -} from './templatePlots/templatePlotsSlice' -import { - initialize, - updateCliError, - updateHasPlots, - updateHasUnselectedPlots, - updatePlotErrors, - updateSelectedRevisions -} from './webviewSlice' +import { setCollapsed as setCustomPlotsCollapsed } from './customPlots/customPlotsSlice' +import { setCollapsed as setComparisonTableCollapsed } from './comparisonTable/comparisonTableSlice' +import { setCollapsed as setTemplatePlotsCollapsed } from './templatePlots/templatePlotsSlice' +import { initialize } from './webviewSlice' import { PlotsDispatch } from '../store' import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging' +import { dispatchAction } from '../../shared/dispatchAction' const dispatchCollapsedSections = ( sections: SectionCollapsed, @@ -46,60 +28,28 @@ const dispatchCollapsedSections = ( } } -const actionToDispatch = { - [PlotsDataKeys.CLI_ERROR]: updateCliError, - [PlotsDataKeys.CUSTOM]: updateCustomPlots, - [PlotsDataKeys.COMPARISON]: updateComparisonTable, - [PlotsDataKeys.TEMPLATE]: updateTemplatePlots, - [PlotsDataKeys.HAS_PLOTS]: updateHasPlots, - [PlotsDataKeys.HAS_UNSELECTED_PLOTS]: updateHasUnselectedPlots, - [PlotsDataKeys.PLOT_ERRORS]: updatePlotErrors, - [PlotsDataKeys.SELECTED_REVISIONS]: updateSelectedRevisions, - [PlotsDataKeys.SHOW_TOO_MANY_TEMPLATE_PLOTS]: - updateShouldShowTooManyTemplatesMessage, - [PlotsDataKeys.SHOW_TOO_MANY_COMPARISON_IMAGES]: - updateShouldShowTooManyImagesMessage -} as const - export const feedStore = ( data: MessageToWebview, dispatch: PlotsDispatch ) => { - if (!data?.data) { + const stateUpdate = data?.data + if (!stateUpdate) { return } dispatch(initialize()) - const keys = Object.keys(data.data) as PlotsDataKeys[] - for (const key of keys) { - if (key === PlotsDataKeys.SECTION_COLLAPSED) { - dispatchCollapsedSections( - data.data[PlotsDataKeys.SECTION_COLLAPSED] as SectionCollapsed, - dispatch - ) - continue - } - - const action = actionToDispatch[key as keyof typeof actionToDispatch] - const value = data.data[key] - if (!action) { - continue - } - dispatch(action(value as never)) + const keys = Object.keys(stateUpdate) as PlotsDataKeys[] + if (keys.includes(PlotsDataKeys.SECTION_COLLAPSED)) { + dispatchCollapsedSections( + stateUpdate[PlotsDataKeys.SECTION_COLLAPSED] as SectionCollapsed, + dispatch + ) } + dispatchAction('plots', stateUpdate, dispatch) } export const App = () => { - const dispatch = useDispatch() - - useVsCodeMessaging( - useCallback( - ({ data }: { data: MessageToWebview }) => { - feedStore(data, dispatch) - }, - [dispatch] - ) - ) + useVsCodeMessaging(feedStore) return } diff --git a/webview/src/setup/components/App.tsx b/webview/src/setup/components/App.tsx index 5a679f9575..f45b2c0523 100644 --- a/webview/src/setup/components/App.tsx +++ b/webview/src/setup/components/App.tsx @@ -1,6 +1,6 @@ import { SetupSection, SetupData } from 'dvc/src/setup/webview/contract' import { MessageToWebview } from 'dvc/src/webview/contract' -import React, { useCallback } from 'react' +import React from 'react' import { useDispatch, useSelector } from 'react-redux' import { Dvc } from './dvc/Dvc' import { Experiments } from './experiments/Experiments' @@ -10,30 +10,10 @@ import { Remotes } from './remotes/Remotes' import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging' import { TooltipIconType } from '../../shared/components/sectionContainer/InfoTooltip' import { SetupDispatch, SetupState } from '../store' -import { initialize, updateSectionCollapsed } from '../state/webviewSlice' -import { - updateCanGitInitialize, - updateCliCompatible, - updateDvcCliDetails, - updateIsAboveLatestTestedVersion, - updateIsPythonEnvironmentGlobal, - updateIsPythonExtensionInstalled, - updateIsPythonExtensionUsed, - updateNeedsGitInitialized, - updateProjectInitialized, - updatePythonBinPath -} from '../state/dvcSlice' -import { - updateHasData as updateExperimentsHasData, - updateNeedsGitCommit -} from '../state/experimentsSlice' -import { updateRemoteList } from '../state/remoteSlice' -import { - updateIsStudioConnected, - updateSelfHostedStudioUrl, - updateShareLiveToStudio -} from '../state/studioSlice' +import { initialize } from '../state/webviewSlice' +import { updateShareLiveToStudio } from '../state/studioSlice' import { setStudioShareExperimentsLive } from '../util/messages' +import { dispatchAction } from '../../shared/dispatchAction' const getDvcStatusIcon = ( isDvcSetup: boolean, @@ -56,44 +36,17 @@ const getStudioStatusIcon = (cliCompatible: boolean, isConnected: boolean) => { return isConnected ? TooltipIconType.PASSED : TooltipIconType.WARNING } -const actionToDispatch = { - canGitInitialize: updateCanGitInitialize, - cliCompatible: updateCliCompatible, - dvcCliDetails: updateDvcCliDetails, - hasData: updateExperimentsHasData, - isAboveLatestTestedVersion: updateIsAboveLatestTestedVersion, - isPythonEnvironmentGlobal: updateIsPythonEnvironmentGlobal, - isPythonExtensionInstalled: updateIsPythonExtensionInstalled, - isPythonExtensionUsed: updateIsPythonExtensionUsed, - isStudioConnected: updateIsStudioConnected, - needsGitCommit: updateNeedsGitCommit, - needsGitInitialized: updateNeedsGitInitialized, - projectInitialized: updateProjectInitialized, - pythonBinPath: updatePythonBinPath, - remoteList: updateRemoteList, - sectionCollapsed: updateSectionCollapsed, - selfHostedStudioUrl: updateSelfHostedStudioUrl, - shareLiveToStudio: updateShareLiveToStudio -} as const - export const feedStore = ( data: MessageToWebview, dispatch: SetupDispatch ) => { - if (!data?.data) { + const stateUpdate = data?.data + if (!stateUpdate) { return } dispatch(initialize()) - for (const key of Object.keys(data.data)) { - const tKey = key as keyof typeof data.data - const action = actionToDispatch[tKey] - const value = data.data[tKey] - if (!action) { - continue - } - dispatch(action(value as never)) - } + dispatchAction('setup', stateUpdate, dispatch) } export const App: React.FC = () => { @@ -110,14 +63,7 @@ export const App: React.FC = () => { const dispatch = useDispatch() - useVsCodeMessaging( - useCallback( - ({ data }: { data: MessageToWebview }) => { - feedStore(data, dispatch) - }, - [dispatch] - ) - ) + useVsCodeMessaging(feedStore) const setShareLiveToStudio = (shouldShareLive: boolean) => { dispatch(updateShareLiveToStudio(shouldShareLive)) diff --git a/webview/src/shared/dispatchAction.ts b/webview/src/shared/dispatchAction.ts new file mode 100644 index 0000000000..0e43d0396b --- /dev/null +++ b/webview/src/shared/dispatchAction.ts @@ -0,0 +1,139 @@ +import { UnknownAction } from '@reduxjs/toolkit' +import { TableData } from 'dvc/src/experiments/webview/contract' +import { PlotsData, PlotsDataKeys } from 'dvc/src/plots/webview/contract' +import { SetupData } from 'dvc/src/setup/webview/contract' +import { + updateChanges, + updateColumnOrder, + updateColumnWidths, + updateColumns, + updateFilters, + updateHasBranchesToSelect, + updateHasCheckpoints, + updateHasConfig, + updateHasMoreCommits, + updateHasRunningWorkspaceExperiment, + updateIsShowingMoreCommits, + updateRows, + updateSelectedBranches, + updateSelectedForPlotsCount, + updateShowOnlyChanged, + updateSorts, + updateCliError as updateTableCliError +} from '../experiments/state/tableDataSlice' +import { ExperimentsDispatch } from '../experiments/store' +import { + update as updateComparisonTable, + updateShouldShowTooManyPlotsMessage as updateShouldShowTooManyImagesMessage +} from '../plots/components/comparisonTable/comparisonTableSlice' +import { update as updateCustomPlots } from '../plots/components/customPlots/customPlotsSlice' +import { + updateShouldShowTooManyPlotsMessage as updateShouldShowTooManyTemplatesMessage, + update as updateTemplatePlots +} from '../plots/components/templatePlots/templatePlotsSlice' +import { + updateHasPlots, + updateHasUnselectedPlots, + updatePlotErrors, + updateCliError as updatePlotsCliError, + updateSelectedRevisions +} from '../plots/components/webviewSlice' +import { PlotsDispatch } from '../plots/store' +import { + updateCanGitInitialize, + updateCliCompatible, + updateDvcCliDetails, + updateIsAboveLatestTestedVersion, + updateIsPythonEnvironmentGlobal, + updateIsPythonExtensionInstalled, + updateIsPythonExtensionUsed, + updateNeedsGitInitialized, + updateProjectInitialized, + updatePythonBinPath +} from '../setup/state/dvcSlice' +import { + updateHasData as updateExperimentsHasData, + updateNeedsGitCommit +} from '../setup/state/experimentsSlice' +import { updateRemoteList } from '../setup/state/remoteSlice' +import { + updateIsStudioConnected, + updateSelfHostedStudioUrl, + updateShareLiveToStudio +} from '../setup/state/studioSlice' +import { updateSectionCollapsed } from '../setup/state/webviewSlice' +import { SetupDispatch } from '../setup/store' + +const actionToDispatch = { + experiments: { + changes: updateChanges, + cliError: updateTableCliError, + columnOrder: updateColumnOrder, + columnWidths: updateColumnWidths, + columns: updateColumns, + filters: updateFilters, + hasBranchesToSelect: updateHasBranchesToSelect, + hasCheckpoints: updateHasCheckpoints, + hasConfig: updateHasConfig, + hasMoreCommits: updateHasMoreCommits, + hasRunningWorkspaceExperiment: updateHasRunningWorkspaceExperiment, + isShowingMoreCommits: updateIsShowingMoreCommits, + rows: updateRows, + selectedBranches: updateSelectedBranches, + selectedForPlotsCount: updateSelectedForPlotsCount, + showOnlyChanged: updateShowOnlyChanged, + sorts: updateSorts + }, + plots: { + [PlotsDataKeys.CLI_ERROR]: updatePlotsCliError, + [PlotsDataKeys.CUSTOM]: updateCustomPlots, + [PlotsDataKeys.COMPARISON]: updateComparisonTable, + [PlotsDataKeys.TEMPLATE]: updateTemplatePlots, + [PlotsDataKeys.HAS_PLOTS]: updateHasPlots, + [PlotsDataKeys.HAS_UNSELECTED_PLOTS]: updateHasUnselectedPlots, + [PlotsDataKeys.PLOT_ERRORS]: updatePlotErrors, + [PlotsDataKeys.SELECTED_REVISIONS]: updateSelectedRevisions, + [PlotsDataKeys.SHOW_TOO_MANY_TEMPLATE_PLOTS]: + updateShouldShowTooManyTemplatesMessage, + [PlotsDataKeys.SHOW_TOO_MANY_COMPARISON_IMAGES]: + updateShouldShowTooManyImagesMessage + }, + setup: { + canGitInitialize: updateCanGitInitialize, + cliCompatible: updateCliCompatible, + dvcCliDetails: updateDvcCliDetails, + hasData: updateExperimentsHasData, + isAboveLatestTestedVersion: updateIsAboveLatestTestedVersion, + isPythonEnvironmentGlobal: updateIsPythonEnvironmentGlobal, + isPythonExtensionInstalled: updateIsPythonExtensionInstalled, + isPythonExtensionUsed: updateIsPythonExtensionUsed, + isStudioConnected: updateIsStudioConnected, + needsGitCommit: updateNeedsGitCommit, + needsGitInitialized: updateNeedsGitInitialized, + projectInitialized: updateProjectInitialized, + pythonBinPath: updatePythonBinPath, + remoteList: updateRemoteList, + sectionCollapsed: updateSectionCollapsed, + selfHostedStudioUrl: updateSelfHostedStudioUrl, + shareLiveToStudio: updateShareLiveToStudio + } +} as const + +export const dispatchAction = ( + type: keyof typeof actionToDispatch, + stateUpdate: NonNullable, + dispatch: ExperimentsDispatch | PlotsDispatch | SetupDispatch +) => { + const actions = actionToDispatch[type] + + for (const key of Object.keys(stateUpdate)) { + const tKey = key as keyof typeof stateUpdate + const value = stateUpdate[tKey] + const action = actions[tKey] as (input: typeof value) => UnknownAction + + if (!action) { + continue + } + dispatch(action(value)) + } +} diff --git a/webview/src/shared/hooks/useVsCodeMessaging.ts b/webview/src/shared/hooks/useVsCodeMessaging.ts index 052c8cdd21..70cdb861a1 100644 --- a/webview/src/shared/hooks/useVsCodeMessaging.ts +++ b/webview/src/shared/hooks/useVsCodeMessaging.ts @@ -3,15 +3,31 @@ import { MessageToWebview, WebviewData } from 'dvc/src/webview/contract' -import { useEffect } from 'react' +import { useCallback, useEffect } from 'react' +import { useDispatch } from 'react-redux' import { sendMessage } from '../vscode' +import { ExperimentsDispatch } from '../../experiments/store' +import { SetupDispatch } from '../../setup/store' +import { PlotsDispatch } from '../../plots/store' const signalInitialized = () => sendMessage({ type: MessageFromWebviewType.INITIALIZED }) export function useVsCodeMessaging( - handler?: (event: { data: MessageToWebview }) => void + feedStore: ( + data: MessageToWebview, + dispatch: PlotsDispatch | ExperimentsDispatch | SetupDispatch + ) => void ) { + const dispatch = useDispatch() + + const handler = useCallback( + ({ data }: { data: MessageToWebview }) => { + feedStore(data, dispatch) + }, + [dispatch, feedStore] + ) + useEffect(() => { signalInitialized() }, []) From c7dbea10f139f2e895766e9ec6b2509af0f44d2b Mon Sep 17 00:00:00 2001 From: Matt Seddon Date: Mon, 15 Jan 2024 14:30:40 +1100 Subject: [PATCH 5/5] move reducers back into apps --- webview/src/experiments/components/App.tsx | 51 +++++++- webview/src/plots/components/App.tsx | 49 ++++++-- webview/src/setup/components/App.tsx | 59 +++++++-- webview/src/shared/dispatchAction.ts | 139 --------------------- webview/src/shared/dispatchActions.ts | 29 +++++ 5 files changed, 168 insertions(+), 159 deletions(-) delete mode 100644 webview/src/shared/dispatchAction.ts create mode 100644 webview/src/shared/dispatchActions.ts diff --git a/webview/src/experiments/components/App.tsx b/webview/src/experiments/components/App.tsx index da5c0dd30a..469a14a37b 100644 --- a/webview/src/experiments/components/App.tsx +++ b/webview/src/experiments/components/App.tsx @@ -1,14 +1,55 @@ -import React from 'react' +import { TableData } from 'dvc/src/experiments/webview/contract' import { MessageToWebview, MessageToWebviewType } from 'dvc/src/webview/contract' -import { TableData } from 'dvc/src/experiments/webview/contract' +import React from 'react' import Experiments from './Experiments' -import { update } from '../state/tableDataSlice' +import { dispatchActions } from '../../shared/dispatchActions' import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging' +import { + update, + updateChanges, + updateCliError, + updateColumnOrder, + updateColumnWidths, + updateColumns, + updateFilters, + updateHasBranchesToSelect, + updateHasCheckpoints, + updateHasConfig, + updateHasMoreCommits, + updateHasRunningWorkspaceExperiment, + updateIsShowingMoreCommits, + updateRows, + updateSelectedBranches, + updateSelectedForPlotsCount, + updateShowOnlyChanged, + updateSorts +} from '../state/tableDataSlice' import { ExperimentsDispatch } from '../store' -import { dispatchAction } from '../../shared/dispatchAction' + +const actionToDispatch = { + changes: updateChanges, + cliError: updateCliError, + columnOrder: updateColumnOrder, + columnWidths: updateColumnWidths, + columns: updateColumns, + filters: updateFilters, + hasBranchesToSelect: updateHasBranchesToSelect, + hasCheckpoints: updateHasCheckpoints, + hasConfig: updateHasConfig, + hasMoreCommits: updateHasMoreCommits, + hasRunningWorkspaceExperiment: updateHasRunningWorkspaceExperiment, + isShowingMoreCommits: updateIsShowingMoreCommits, + rows: updateRows, + selectedBranches: updateSelectedBranches, + selectedForPlotsCount: updateSelectedForPlotsCount, + showOnlyChanged: updateShowOnlyChanged, + sorts: updateSorts +} + +export type ExperimentsActions = typeof actionToDispatch const feedStore = ( data: MessageToWebview, @@ -20,7 +61,7 @@ const feedStore = ( const stateUpdate = data?.data dispatch(update(!!stateUpdate)) - dispatchAction('experiments', stateUpdate, dispatch) + dispatchActions(actionToDispatch, stateUpdate, dispatch) } export const App: React.FC> = () => { diff --git a/webview/src/plots/components/App.tsx b/webview/src/plots/components/App.tsx index 602be7ddd3..bb2ac9afd3 100644 --- a/webview/src/plots/components/App.tsx +++ b/webview/src/plots/components/App.tsx @@ -1,4 +1,3 @@ -import React from 'react' import { PlotsData, PlotsDataKeys, @@ -6,14 +5,33 @@ import { SectionCollapsed } from 'dvc/src/plots/webview/contract' import { MessageToWebview } from 'dvc/src/webview/contract' +import React from 'react' import { Plots } from './Plots' -import { setCollapsed as setCustomPlotsCollapsed } from './customPlots/customPlotsSlice' -import { setCollapsed as setComparisonTableCollapsed } from './comparisonTable/comparisonTableSlice' -import { setCollapsed as setTemplatePlotsCollapsed } from './templatePlots/templatePlotsSlice' -import { initialize } from './webviewSlice' +import { + setCollapsed as setComparisonTableCollapsed, + update as updateComparisonTable, + updateShouldShowTooManyPlotsMessage as updateShouldShowTooManyImagesMessage +} from './comparisonTable/comparisonTableSlice' +import { + setCollapsed as setCustomPlotsCollapsed, + update as updateCustomPlots +} from './customPlots/customPlotsSlice' +import { + setCollapsed as setTemplatePlotsCollapsed, + updateShouldShowTooManyPlotsMessage as updateShouldShowTooManyTemplatesMessage, + update as updateTemplatePlots +} from './templatePlots/templatePlotsSlice' +import { + initialize, + updateCliError, + updateHasPlots, + updateHasUnselectedPlots, + updatePlotErrors, + updateSelectedRevisions +} from './webviewSlice' import { PlotsDispatch } from '../store' import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging' -import { dispatchAction } from '../../shared/dispatchAction' +import { dispatchActions } from '../../shared/dispatchActions' const dispatchCollapsedSections = ( sections: SectionCollapsed, @@ -28,6 +46,23 @@ const dispatchCollapsedSections = ( } } +const actionToDispatch = { + [PlotsDataKeys.CLI_ERROR]: updateCliError, + [PlotsDataKeys.CUSTOM]: updateCustomPlots, + [PlotsDataKeys.COMPARISON]: updateComparisonTable, + [PlotsDataKeys.TEMPLATE]: updateTemplatePlots, + [PlotsDataKeys.HAS_PLOTS]: updateHasPlots, + [PlotsDataKeys.HAS_UNSELECTED_PLOTS]: updateHasUnselectedPlots, + [PlotsDataKeys.PLOT_ERRORS]: updatePlotErrors, + [PlotsDataKeys.SELECTED_REVISIONS]: updateSelectedRevisions, + [PlotsDataKeys.SHOW_TOO_MANY_TEMPLATE_PLOTS]: + updateShouldShowTooManyTemplatesMessage, + [PlotsDataKeys.SHOW_TOO_MANY_COMPARISON_IMAGES]: + updateShouldShowTooManyImagesMessage +} as const + +export type PlotsActions = typeof actionToDispatch + export const feedStore = ( data: MessageToWebview, dispatch: PlotsDispatch @@ -45,7 +80,7 @@ export const feedStore = ( dispatch ) } - dispatchAction('plots', stateUpdate, dispatch) + dispatchActions(actionToDispatch, stateUpdate, dispatch) } export const App = () => { diff --git a/webview/src/setup/components/App.tsx b/webview/src/setup/components/App.tsx index f45b2c0523..39368d84d6 100644 --- a/webview/src/setup/components/App.tsx +++ b/webview/src/setup/components/App.tsx @@ -1,19 +1,40 @@ -import { SetupSection, SetupData } from 'dvc/src/setup/webview/contract' +import { SetupData, SetupSection } from 'dvc/src/setup/webview/contract' import { MessageToWebview } from 'dvc/src/webview/contract' import React from 'react' import { useDispatch, useSelector } from 'react-redux' +import { SetupContainer } from './SetupContainer' import { Dvc } from './dvc/Dvc' import { Experiments } from './experiments/Experiments' -import { Studio } from './studio/Studio' -import { SetupContainer } from './SetupContainer' import { Remotes } from './remotes/Remotes' -import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging' +import { Studio } from './studio/Studio' import { TooltipIconType } from '../../shared/components/sectionContainer/InfoTooltip' +import { dispatchActions } from '../../shared/dispatchActions' +import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging' +import { + updateCanGitInitialize, + updateCliCompatible, + updateDvcCliDetails, + updateIsAboveLatestTestedVersion, + updateIsPythonEnvironmentGlobal, + updateIsPythonExtensionInstalled, + updateIsPythonExtensionUsed, + updateNeedsGitInitialized, + updateProjectInitialized, + updatePythonBinPath +} from '../state/dvcSlice' +import { + updateHasData as updateExperimentsHasData, + updateNeedsGitCommit +} from '../state/experimentsSlice' +import { updateRemoteList } from '../state/remoteSlice' +import { + updateIsStudioConnected, + updateSelfHostedStudioUrl, + updateShareLiveToStudio +} from '../state/studioSlice' +import { initialize, updateSectionCollapsed } from '../state/webviewSlice' import { SetupDispatch, SetupState } from '../store' -import { initialize } from '../state/webviewSlice' -import { updateShareLiveToStudio } from '../state/studioSlice' import { setStudioShareExperimentsLive } from '../util/messages' -import { dispatchAction } from '../../shared/dispatchAction' const getDvcStatusIcon = ( isDvcSetup: boolean, @@ -36,6 +57,28 @@ const getStudioStatusIcon = (cliCompatible: boolean, isConnected: boolean) => { return isConnected ? TooltipIconType.PASSED : TooltipIconType.WARNING } +const actionToDispatch = { + canGitInitialize: updateCanGitInitialize, + cliCompatible: updateCliCompatible, + dvcCliDetails: updateDvcCliDetails, + hasData: updateExperimentsHasData, + isAboveLatestTestedVersion: updateIsAboveLatestTestedVersion, + isPythonEnvironmentGlobal: updateIsPythonEnvironmentGlobal, + isPythonExtensionInstalled: updateIsPythonExtensionInstalled, + isPythonExtensionUsed: updateIsPythonExtensionUsed, + isStudioConnected: updateIsStudioConnected, + needsGitCommit: updateNeedsGitCommit, + needsGitInitialized: updateNeedsGitInitialized, + projectInitialized: updateProjectInitialized, + pythonBinPath: updatePythonBinPath, + remoteList: updateRemoteList, + sectionCollapsed: updateSectionCollapsed, + selfHostedStudioUrl: updateSelfHostedStudioUrl, + shareLiveToStudio: updateShareLiveToStudio +} as const + +export type SetupActions = typeof actionToDispatch + export const feedStore = ( data: MessageToWebview, dispatch: SetupDispatch @@ -46,7 +89,7 @@ export const feedStore = ( } dispatch(initialize()) - dispatchAction('setup', stateUpdate, dispatch) + dispatchActions(actionToDispatch, stateUpdate, dispatch) } export const App: React.FC = () => { diff --git a/webview/src/shared/dispatchAction.ts b/webview/src/shared/dispatchAction.ts deleted file mode 100644 index 0e43d0396b..0000000000 --- a/webview/src/shared/dispatchAction.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { UnknownAction } from '@reduxjs/toolkit' -import { TableData } from 'dvc/src/experiments/webview/contract' -import { PlotsData, PlotsDataKeys } from 'dvc/src/plots/webview/contract' -import { SetupData } from 'dvc/src/setup/webview/contract' -import { - updateChanges, - updateColumnOrder, - updateColumnWidths, - updateColumns, - updateFilters, - updateHasBranchesToSelect, - updateHasCheckpoints, - updateHasConfig, - updateHasMoreCommits, - updateHasRunningWorkspaceExperiment, - updateIsShowingMoreCommits, - updateRows, - updateSelectedBranches, - updateSelectedForPlotsCount, - updateShowOnlyChanged, - updateSorts, - updateCliError as updateTableCliError -} from '../experiments/state/tableDataSlice' -import { ExperimentsDispatch } from '../experiments/store' -import { - update as updateComparisonTable, - updateShouldShowTooManyPlotsMessage as updateShouldShowTooManyImagesMessage -} from '../plots/components/comparisonTable/comparisonTableSlice' -import { update as updateCustomPlots } from '../plots/components/customPlots/customPlotsSlice' -import { - updateShouldShowTooManyPlotsMessage as updateShouldShowTooManyTemplatesMessage, - update as updateTemplatePlots -} from '../plots/components/templatePlots/templatePlotsSlice' -import { - updateHasPlots, - updateHasUnselectedPlots, - updatePlotErrors, - updateCliError as updatePlotsCliError, - updateSelectedRevisions -} from '../plots/components/webviewSlice' -import { PlotsDispatch } from '../plots/store' -import { - updateCanGitInitialize, - updateCliCompatible, - updateDvcCliDetails, - updateIsAboveLatestTestedVersion, - updateIsPythonEnvironmentGlobal, - updateIsPythonExtensionInstalled, - updateIsPythonExtensionUsed, - updateNeedsGitInitialized, - updateProjectInitialized, - updatePythonBinPath -} from '../setup/state/dvcSlice' -import { - updateHasData as updateExperimentsHasData, - updateNeedsGitCommit -} from '../setup/state/experimentsSlice' -import { updateRemoteList } from '../setup/state/remoteSlice' -import { - updateIsStudioConnected, - updateSelfHostedStudioUrl, - updateShareLiveToStudio -} from '../setup/state/studioSlice' -import { updateSectionCollapsed } from '../setup/state/webviewSlice' -import { SetupDispatch } from '../setup/store' - -const actionToDispatch = { - experiments: { - changes: updateChanges, - cliError: updateTableCliError, - columnOrder: updateColumnOrder, - columnWidths: updateColumnWidths, - columns: updateColumns, - filters: updateFilters, - hasBranchesToSelect: updateHasBranchesToSelect, - hasCheckpoints: updateHasCheckpoints, - hasConfig: updateHasConfig, - hasMoreCommits: updateHasMoreCommits, - hasRunningWorkspaceExperiment: updateHasRunningWorkspaceExperiment, - isShowingMoreCommits: updateIsShowingMoreCommits, - rows: updateRows, - selectedBranches: updateSelectedBranches, - selectedForPlotsCount: updateSelectedForPlotsCount, - showOnlyChanged: updateShowOnlyChanged, - sorts: updateSorts - }, - plots: { - [PlotsDataKeys.CLI_ERROR]: updatePlotsCliError, - [PlotsDataKeys.CUSTOM]: updateCustomPlots, - [PlotsDataKeys.COMPARISON]: updateComparisonTable, - [PlotsDataKeys.TEMPLATE]: updateTemplatePlots, - [PlotsDataKeys.HAS_PLOTS]: updateHasPlots, - [PlotsDataKeys.HAS_UNSELECTED_PLOTS]: updateHasUnselectedPlots, - [PlotsDataKeys.PLOT_ERRORS]: updatePlotErrors, - [PlotsDataKeys.SELECTED_REVISIONS]: updateSelectedRevisions, - [PlotsDataKeys.SHOW_TOO_MANY_TEMPLATE_PLOTS]: - updateShouldShowTooManyTemplatesMessage, - [PlotsDataKeys.SHOW_TOO_MANY_COMPARISON_IMAGES]: - updateShouldShowTooManyImagesMessage - }, - setup: { - canGitInitialize: updateCanGitInitialize, - cliCompatible: updateCliCompatible, - dvcCliDetails: updateDvcCliDetails, - hasData: updateExperimentsHasData, - isAboveLatestTestedVersion: updateIsAboveLatestTestedVersion, - isPythonEnvironmentGlobal: updateIsPythonEnvironmentGlobal, - isPythonExtensionInstalled: updateIsPythonExtensionInstalled, - isPythonExtensionUsed: updateIsPythonExtensionUsed, - isStudioConnected: updateIsStudioConnected, - needsGitCommit: updateNeedsGitCommit, - needsGitInitialized: updateNeedsGitInitialized, - projectInitialized: updateProjectInitialized, - pythonBinPath: updatePythonBinPath, - remoteList: updateRemoteList, - sectionCollapsed: updateSectionCollapsed, - selfHostedStudioUrl: updateSelfHostedStudioUrl, - shareLiveToStudio: updateShareLiveToStudio - } -} as const - -export const dispatchAction = ( - type: keyof typeof actionToDispatch, - stateUpdate: NonNullable, - dispatch: ExperimentsDispatch | PlotsDispatch | SetupDispatch -) => { - const actions = actionToDispatch[type] - - for (const key of Object.keys(stateUpdate)) { - const tKey = key as keyof typeof stateUpdate - const value = stateUpdate[tKey] - const action = actions[tKey] as (input: typeof value) => UnknownAction - - if (!action) { - continue - } - dispatch(action(value)) - } -} diff --git a/webview/src/shared/dispatchActions.ts b/webview/src/shared/dispatchActions.ts new file mode 100644 index 0000000000..ad951ae35c --- /dev/null +++ b/webview/src/shared/dispatchActions.ts @@ -0,0 +1,29 @@ +import { UnknownAction } from '@reduxjs/toolkit' +import { TableData } from 'dvc/src/experiments/webview/contract' +import { PlotsData } from 'dvc/src/plots/webview/contract' +import { SetupData } from 'dvc/src/setup/webview/contract' +import type { ExperimentsActions } from '../experiments/components/App' +import type { ExperimentsDispatch } from '../experiments/store' +import type { PlotsActions } from '../plots/components/App' +import type { PlotsDispatch } from '../plots/store' +import type { SetupActions } from '../setup/components/App' +import type { SetupDispatch } from '../setup/store' + +export const dispatchActions = ( + actionToDispatch: ExperimentsActions | PlotsActions | SetupActions, + stateUpdate: NonNullable, + dispatch: ExperimentsDispatch | PlotsDispatch | SetupDispatch +) => { + for (const key of Object.keys(stateUpdate)) { + const tKey = key as keyof typeof stateUpdate + const value = stateUpdate[tKey] + const action = actionToDispatch[tKey] as ( + input: typeof value + ) => UnknownAction + + if (!action) { + continue + } + dispatch(action(value)) + } +}