Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

Commit

Permalink
Merge pull request #256 from disktnk/feature/result-grandparent-grouping
Browse files Browse the repository at this point in the history
Add aggregation column on result table
  • Loading branch information
ofk authored Feb 1, 2019
2 parents a6544b3 + a359852 commit 5fb1071
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 48 deletions.
7 changes: 5 additions & 2 deletions frontend/src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,14 @@ export const updateTableExpanded = (projectId, expanded) => ({
});

export const TABLE_STATE_COLUMNS_VISIBILITY_UPDATE = 'TABLE_STATE_COLUMNS_VISIBILITY_UPDATE';
export const updateTableColumnsVisibility = (projectId, hiddenLogKeys, hiddenArgKeys) => ({
export const updateTableColumnsVisibility = (
projectId, hiddenLogKeys, hiddenArgKeys, isGrouped
) => ({
type: TABLE_STATE_COLUMNS_VISIBILITY_UPDATE,
projectId,
hiddenLogKeys,
hiddenArgKeys
hiddenArgKeys,
isGrouped
});

export const ASSETS_TABLE_STATE_COLUMNS_VISIBILITY_UPDATE = 'ASSETS_TABLE_STATE_COLUMNS_VISIBILITY_UPDATE';
Expand Down
122 changes: 86 additions & 36 deletions frontend/src/components/ExperimentsTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ReactTable from 'react-table';
import * as uiPropTypes from '../store/uiPropTypes';
import {
argValue2string,
getGrandParentDirectoryName,
getLastLogDict,
sortMethod
} from '../utils';
Expand Down Expand Up @@ -44,6 +45,11 @@ const ExperimentsTable = (props) => {
onResultsConfigSelectUpdate(project.id, resultId, !evt.target.checked);
});
};
const generateHandleGroupedResultsConfigSelectChange = (groupedResultKeys) => (evt) => {
groupedResultKeys.forEach((resultId) => {
onResultsConfigSelectUpdate(project.id, resultId, !evt.target.checked);
});
};

const defaultStyle = {
textAlign: 'right'
Expand All @@ -53,9 +59,78 @@ const ExperimentsTable = (props) => {
const expanded = resultList.length === 0 ? {} : tableState.expanded;
const {
hiddenLogKeys = [],
hiddenArgKeys = []
hiddenArgKeys = [],
isGrouped = false
} = tableState;

const nameColumns = [
{
Header: <VisibilityCheckbox
className="fa-xs"
checked={visibleResultCount > 0}
indeterminate={isPartialSelect}
onChange={handleResultsConfigSelectChange}
/>,
Cell: (p) => {
const { original } = p;
if (!original) {
return {};
}
const { id } = original;
return (<ToggleResult
project={project}
result={original}
resultConfig={resultsConfig[id]}
onResultsConfigSelectUpdate={onResultsConfigSelectUpdate}
/>);
},
className: 'text-center',
sortable: false,
minWidth: 40,
Aggregated: (row) => {
const groupedResultKeys = row.subRows.map((r) => {
const { _original } = r;
return _original.id;
});
const groupedVisibleResultCount = groupedResultKeys.filter(
(resultId) => !(resultsConfig[resultId] || {}).hidden).length;
const isGroupedPartialSelect = groupedVisibleResultCount > 0 &&
visibleResultCount < groupedResultKeys.length;
return <VisibilityCheckbox
className="fa-xs"
checked={groupedVisibleResultCount > 0}
indeterminate={isGroupedPartialSelect}
onChange={generateHandleGroupedResultsConfigSelectChange(groupedResultKeys)}
/>;
}
},
{
Header: 'name',
id: 'name',
Cell: (p) => {
const { original } = p;
if (original) {
return (<ResultName
project={project}
result={original}
isResultNameAlignRight={globalConfig.isResultNameAlignRight}
onResultUpdate={onResultUpdate}
/>);
}
return null;
},
minWidth: 250
}
];
if (isGrouped) {
nameColumns.unshift({
Header: '',
id: 'group',
accessor: (p) => getGrandParentDirectoryName(p)
});
}
const groupedKey = isGrouped ? ['group'] : [];

const logs = logKeys.map((logKey) => ({
Header: logKey,
id: `logKey${logKey}`,
Expand All @@ -67,7 +142,8 @@ const ExperimentsTable = (props) => {
return lastLogDict[logKey];
},
style: defaultStyle,
show: !hiddenLogKeys.find((k) => k === logKey)
show: !hiddenLogKeys.find((k) => k === logKey),
aggregate: () => ''
}));

const argsList = argKeys.map((argKey) => ({
Expand All @@ -82,44 +158,14 @@ const ExperimentsTable = (props) => {
return argValue2string(argDict[argKey]);
},
style: defaultStyle,
show: !hiddenArgKeys.find((k) => k === argKey)
show: !hiddenArgKeys.find((k) => k === argKey),
aggregate: () => ''
}));

const columns = [
{
Header: <VisibilityCheckbox
className="fa-xs"
checked={visibleResultCount > 0}
indeterminate={isPartialSelect}
onChange={handleResultsConfigSelectChange}
/>,
Cell: (p) => {
const { original } = p;
const { id } = original;
return (<ToggleResult
project={project}
result={original}
resultConfig={resultsConfig[id]}
onResultsConfigSelectUpdate={onResultsConfigSelectUpdate}
/>);
},
className: 'text-center',
sortable: false,
minWidth: 40
},
{
Header: 'name',
id: 'name',
Cell: (p) => {
const { original } = p;
return (<ResultName
project={project}
result={original}
isResultNameAlignRight={globalConfig.isResultNameAlignRight}
onResultUpdate={onResultUpdate}
/>);
},
minWidth: 250
Header: ' ', // To prevent from showing "Pivoted" on default (=''), set space on purpose.
columns: nameColumns
},
{
Header: 'last logs',
Expand All @@ -146,6 +192,7 @@ const ExperimentsTable = (props) => {
id: 'result_id'
}
]}
pivotBy={groupedKey}
freezeWhenExpanded={expanded === {}}
SubComponent={(p) => (
<SubComponent
Expand All @@ -157,6 +204,9 @@ const ExperimentsTable = (props) => {
/>
)}
getTrProps={(state, rowInfo) => {
if (rowInfo && !rowInfo.original) {
return {};
}
const resultId = rowInfo && rowInfo.original.id;
const resultStatus = resultsStatus[resultId] || {};
return {
Expand Down
36 changes: 29 additions & 7 deletions frontend/src/components/ExperimentsTableConfigurator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class ExperimentsTableConfigurator extends React.Component {
this.handleModalShow = this.handleModalShow.bind(this);
this.handleModalHide = this.handleModalHide.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleIsGrouped = this.handleIsGrouped.bind(this);

this.state = {
showModal: false
Expand All @@ -42,7 +43,8 @@ class ExperimentsTableConfigurator extends React.Component {
const { tableState } = projectConfig;
const {
hiddenLogKeys = [],
hiddenArgKeys = []
hiddenArgKeys = [],
isGrouped = false
} = tableState;

if (prefix === 'logKey') {
Expand All @@ -51,31 +53,51 @@ class ExperimentsTableConfigurator extends React.Component {
: hiddenLogKeys.filter((vk) => vk !== event.target.name);

this.props.onTableColumnsVisibilityUpdate(
this.props.project.id, nextHiddenLogKeys, hiddenArgKeys);
this.props.project.id, nextHiddenLogKeys, hiddenArgKeys, isGrouped);
} else {
const nextHiddenArgKeys = !event.target.checked
? hiddenArgKeys.concat(event.target.name)
: hiddenArgKeys.filter((vk) => vk !== event.target.name);

this.props.onTableColumnsVisibilityUpdate(
this.props.project.id, hiddenLogKeys, nextHiddenArgKeys);
this.props.project.id, hiddenLogKeys, nextHiddenArgKeys, isGrouped);
}
}

handleIsGrouped(event) {
const { tableState } = this.props.projectConfig;

this.props.onTableColumnsVisibilityUpdate(
this.props.project.id, tableState.hiddenLogKeys, tableState.hiddenArgKeys,
event.target.checked
);
}

render() {
const { stats, projectConfig } = this.props;
const { logKeys, argKeys } = stats;
const { tableState } = projectConfig;
const {
hiddenLogKeys = [],
hiddenArgKeys = []
hiddenArgKeys = [],
isGrouped = false
} = tableState;

return (
<div>
<Button color="secondary" className="my-2" onClick={this.handleModalShow}>
Table settings
</Button>
<div className="form-inline">
<Button color="secondary" className="my-2" onClick={this.handleModalShow}>
Table settings
</Button>
<Check
type="checkbox"
className="ml-2"
checked={isGrouped}
onChange={this.handleIsGrouped}
>
Grouping
</Check>
</div>

<Modal isOpen={this.state.showModal} toggle={this.handleModalHide}>
<ModalHeader>
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/reducers/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,8 @@ const tableStateReducer = (state = {}, action) => {
const {
expanded = {},
hiddenLogKeys = [],
hiddenArgKeys = []
hiddenArgKeys = [],
isGrouped = false
} = action;
switch (action.type) {
case ActionTypes.TABLE_STATE_EXPANDED_UPDATE:
Expand All @@ -438,7 +439,8 @@ const tableStateReducer = (state = {}, action) => {
return {
...state,
hiddenLogKeys,
hiddenArgKeys
hiddenArgKeys,
isGrouped
};
default:
return state;
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/store/uiPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const result = PropTypes.shape({
id: resultId,
pathName: PropTypes.string,
name: PropTypes.string,
group: PropTypes.string,
isUnregistered: PropTypes.bool,
logs,
args,
Expand Down Expand Up @@ -138,7 +139,8 @@ export const projectConfig = PropTypes.shape({
PropTypes.bool, PropTypes.object
]),
hiddenLogKeys: PropTypes.arrayOf(PropTypes.string),
hiddenArgKeys: PropTypes.arrayOf(PropTypes.string)
hiddenArgKeys: PropTypes.arrayOf(PropTypes.string),
isGrouped: PropTypes.bool
}).isRequired,
resultsConfig: resultsConfig.isRequired,
lines: lines.isRequired
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ export const getRelativeResultPathName = (project = {}, result = {}) => (
path.relative(project.pathName || '', result.pathName || '')
);

export const getGrandParentDirectoryName = (result = {}) => (
path.basename(path.resolve(result.pathName, '..'))
);

export const displayResultNameFull = (project = {}, result = {}) => (
result.name || getRelativeResultPathName(project, result)
);
Expand Down

0 comments on commit 5fb1071

Please sign in to comment.