diff --git a/frontend/src/components/ExperimentsTable.jsx b/frontend/src/components/ExperimentsTable.jsx index 5f4d3586..bcfd83fc 100644 --- a/frontend/src/components/ExperimentsTable.jsx +++ b/frontend/src/components/ExperimentsTable.jsx @@ -18,7 +18,9 @@ const emptyStr = '-'; const ExperimentsTable = (props) => { const { project, - results = {}, stats, + results = {}, + resultsStatus, + stats, projectConfig, globalConfig, onResultsConfigSelectUpdate, @@ -155,9 +157,9 @@ const ExperimentsTable = (props) => { )} getTrProps={(state, rowInfo) => { const resultId = rowInfo && rowInfo.original.id; - const resultConfig = resultsConfig[resultId] || {}; + const resultStatus = resultsStatus[resultId] || {}; return { - className: resultConfig.selected ? 'result-highlight' : null, + className: resultStatus.selected ? 'result-highlight' : null, onMouseEnter: () => { onResultSelect(project.id, resultId, true); }, @@ -173,6 +175,7 @@ const ExperimentsTable = (props) => { ExperimentsTable.propTypes = { project: uiPropTypes.project.isRequired, results: uiPropTypes.results, + resultsStatus: uiPropTypes.resultsStatus, projectConfig: uiPropTypes.projectConfig.isRequired, globalConfig: uiPropTypes.globalConfig.isRequired, stats: uiPropTypes.stats.isRequired, @@ -184,6 +187,7 @@ ExperimentsTable.propTypes = { }; ExperimentsTable.defaultProps = { results: {}, + resultsStatus: {}, stats: { argKeys: [] } diff --git a/frontend/src/components/LogVisualizer.jsx b/frontend/src/components/LogVisualizer.jsx index 6559350b..a161012c 100644 --- a/frontend/src/components/LogVisualizer.jsx +++ b/frontend/src/components/LogVisualizer.jsx @@ -73,6 +73,7 @@ class LogVisualizer extends React.Component { const { project = {}, results = {}, + resultsStatus, projectConfig = {}, globalConfig = {}, onResultSelect, @@ -113,16 +114,16 @@ class LogVisualizer extends React.Component { }); const anySelected = selectedResults.some((resultId) => { - const resultConfig = resultsConfig[resultId]; - return resultConfig && resultConfig.selected; + const resultStatus = resultsStatus[resultId]; + return resultStatus && resultStatus.selected; }); const lineElems = []; Object.keys(axisLines).forEach((axisName) => { axisLines[axisName].forEach((line) => { const { config = {}, resultId, logKey } = line; - const resultConfig = resultsConfig[resultId] || {}; - const selected = resultConfig.selected === true || resultConfig.selected === logKey; + const resultStatus = resultsStatus[resultId] || {}; + const selected = resultStatus.selected === true || resultStatus.selected === logKey; lineElems.push(
( lines[axisName].map((line) => { const { resultId, logKey, config } = line; const result = results[resultId] || {}; - const resultConfig = resultsConfig[resultId] || {}; - const selected = resultConfig.selected === true || resultConfig.selected === logKey; + const resultStatus = resultsStatus[resultId] || {}; + const selected = resultStatus.selected === true || resultStatus.selected === logKey; return (
  • { const { - resultsConfig, project, results, lines, maxHeight, isResultNameAlignRight, onResultSelect + project, results, resultsStatus, lines, maxHeight, isResultNameAlignRight, onResultSelect } = props; return (
      - {renderItems(lines, 'yLeftAxis', project, results, isResultNameAlignRight, resultsConfig, onResultSelect)} - {renderItems(lines, 'yRightAxis', project, results, isResultNameAlignRight, resultsConfig, onResultSelect)} + {renderItems(lines, 'yLeftAxis', project, results, isResultNameAlignRight, resultsStatus, onResultSelect)} + {renderItems(lines, 'yRightAxis', project, results, isResultNameAlignRight, resultsStatus, onResultSelect)}
    @@ -64,9 +64,9 @@ const LogVisualizerTooltip = (props) => { }; LogVisualizerTooltip.propTypes = { - resultsConfig: uiPropTypes.resultsConfig.isRequired, project: uiPropTypes.project.isRequired, results: uiPropTypes.results.isRequired, + resultsStatus: uiPropTypes.resultsStatus.isRequired, lines: PropTypes.objectOf(PropTypes.any), maxHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, isResultNameAlignRight: PropTypes.bool, diff --git a/frontend/src/containers/PlotContainer.jsx b/frontend/src/containers/PlotContainer.jsx index a8c80907..ec8d894c 100644 --- a/frontend/src/containers/PlotContainer.jsx +++ b/frontend/src/containers/PlotContainer.jsx @@ -67,6 +67,7 @@ class PlotContainer extends React.Component { const { project, results, + projectStatus, fetchState, projectConfig, globalConfig, @@ -111,6 +112,7 @@ class PlotContainer extends React.Component { { const { entities, fetchState, + status, config = defaultConfig } = state; const { projects = {}, results = {} } = entities; const project = projects[projectId] || { id: projectId }; + const projectStatus = status.projectsStatus[projectId] || {}; const projectConfig = config.projectsConfig[projectId] || defaultProjectConfig; const globalConfig = config.global; const stats = mapEntitiesToStats(entities); @@ -186,6 +191,7 @@ const mapStateToProps = (state, ownProps) => { project, results, fetchState, + projectStatus, projectConfig, globalConfig, stats @@ -197,6 +203,7 @@ PlotContainer.propTypes = { project: uiPropTypes.project.isRequired, results: uiPropTypes.results.isRequired, fetchState: uiPropTypes.fetchState.isRequired, + projectStatus: uiPropTypes.projectStatus.isRequired, projectConfig: uiPropTypes.projectConfig.isRequired, globalConfig: uiPropTypes.globalConfig.isRequired, stats: uiPropTypes.stats.isRequired, diff --git a/frontend/src/reducers/index.jsx b/frontend/src/reducers/index.jsx index 32979f58..84a7aac0 100644 --- a/frontend/src/reducers/index.jsx +++ b/frontend/src/reducers/index.jsx @@ -157,6 +157,49 @@ const fetchState = (state = {}, action) => { } }; +const resultsStatus = (state = {}, action) => { + const { resultId } = action; + const resultStatus = state[resultId] || {}; + + switch (action.type) { + case ActionTypes.RESULT_SELECT_UPDATE: + if (resultId == null) { + return state; + } + return { + ...state, + [Number(resultId)]: { + ...resultStatus, + selected: action.selected + } + }; + default: + return state; + } +}; + +const projectsStatus = (state = {}, action) => { + const { projectId } = action; + + if (projectId) { + const projectStatus = state[projectId] || {}; + + return { + ...state, + [projectId]: { + ...projectStatus, + resultsStatus: resultsStatus(projectStatus.resultsStatus, action) + } + }; + } + + return state; +}; + +const status = combineReducers({ + projectsStatus +}); + const axes = (state = defaultAxisConfig, action) => { const { @@ -270,14 +313,6 @@ const resultsConfig = (state = {}, action) => { hidden: action.hidden } }; - case ActionTypes.RESULT_SELECT_UPDATE: - return { - ...state, - [Number(resultId)]: { - ...resultConfig, - selected: action.selected - } - }; case ActionTypes.RESULT_UPDATE_SUCCESS: if (action.response && action.response.result) { const { result } = action.response; @@ -425,6 +460,7 @@ const rootReducer = combineReducers({ entities, requests: requestsReducer, fetchState, + status, config: persistReducer(persistConfig, config), routing: routerReducer }); diff --git a/frontend/src/store/uiPropTypes.js b/frontend/src/store/uiPropTypes.js index 36b36b25..c6a0c0ac 100644 --- a/frontend/src/store/uiPropTypes.js +++ b/frontend/src/store/uiPropTypes.js @@ -58,8 +58,7 @@ export const globalConfig = PropTypes.shape({ }); export const resultConfig = PropTypes.shape({ - hidden: PropTypes.bool, - selected: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]) + hidden: PropTypes.bool }); export const resultsConfig = PropTypes.objectOf(resultConfig); @@ -120,3 +119,19 @@ export const snapshots = PropTypes.arrayOf(PropTypes.shape({ iteration: PropTypes.number, name: PropTypes.string })); + +export const resultStatus = PropTypes.shape({ + selected: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]) +}); + +export const resultsStatus = PropTypes.objectOf(resultStatus); + +export const projectStatus = PropTypes.shape({ + resultsStatus +}); + +export const projectsStatus = PropTypes.objectOf(projectStatus); + +export const status = PropTypes.shape({ + projectsStatus +});