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)) + } +}