Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance table #982

Merged
merged 10 commits into from
Sep 2, 2022
Merged
6 changes: 4 additions & 2 deletions dashboard/src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
"carbon-icons": "^7.0.7",
"plotly.js": "^2.12.1",
"plotly.js-cartesian-dist-min": "^2.12.1",
"react": "16.14.0",
"react": "18.2.0",
"react-bootstrap": "^1.6.5",
"react-dom": "16.14.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "18.2.0",
"react-plotly.js": "^2.5.1",
"react-router-dom": "5.3.3",
"react-scripts": "5.0.1",
Expand Down
163 changes: 2 additions & 161 deletions dashboard/src/src/experiments/content/DatabasePage/DatabasePage.js
Original file line number Diff line number Diff line change
@@ -1,167 +1,8 @@
import React from 'react';
import { Backend, DEFAULT_BACKEND } from '../../../utils/queryServer';
import { DEFAULT_BACKEND } from '../../../utils/queryServer';
import { FeaturedTable } from './FeaturedTable';
import { BackendContext } from '../../BackendContext';
import { Column, Grid, Row } from 'carbon-components-react';
import { flattenObject } from '../../../utils/flattenObject';

/**
* Component to pretty display an object (JSON dictionary) into data table.
* Used to render trial parameters and statistics.
*/
class ObjectToGrid extends React.Component {
render() {
const object = this.props.object;
const keys = Object.keys(object);
if (!keys.length) return '';
keys.sort();
return (
<Grid condensed fullWidth className="object-to-grid">
{keys.map(key => (
<Row key={key}>
<Column className="object-to-grid-key">
<strong>
<em>{key}</em>
</strong>
</Column>
<Column>
{Array.isArray(object[key])
? object[key].map((value, i) => (
<div key={i}>{value.toString()}</div>
))
: object[key].toString()}
</Column>
</Row>
))}
</Grid>
);
}
}

/**
* Utility class to provide and cache experiment trials.
*/
class TrialsProvider {
constructor(address) {
this.backend = new Backend(address);
this.trials = {};
}
async get(experiment) {
if (!this.trials.hasOwnProperty(experiment)) {
const queryTrials = await this.backend.query(`trials/${experiment}`);
const trialIndices = queryTrials.map(trial => trial.id);
trialIndices.sort();
const trials = [];
/**
* Map to check whether each param column is sortable.
* Array params are not considered sortable,
* except if they contains only 1 element.
*/
const sortableParamCols = {};
for (let trialID of trialIndices) {
const rawTrial = await this.backend.query(
`trials/${experiment}/${trialID}`
);
// Flatten parameters
const flattenedParameters = flattenObject(
rawTrial.parameters,
// Add prefix `params`
// to prevent collision with existing keys in trial object
'params'
);
// Prepare rendering for array parameters
for (let key of Object.keys(flattenedParameters)) {
let sortableCell = true;
if (Array.isArray(flattenedParameters[key])) {
if (flattenedParameters[key].length === 1) {
// Array contains only 1 element.
// Flatten it and assume element is displayable as-is.
flattenedParameters[key] = flattenedParameters[key][0];
} else {
// Real array with many values.
// Render it immediately and mark cell as not sortable.
flattenedParameters[key] = flattenedParameters[
key
].map((value, i) => <div key={i}>{value.toString()}</div>);
sortableCell = false;
}
}
// Param column is sortable if all its cells are sortable.
if (sortableParamCols.hasOwnProperty(key)) {
sortableParamCols[key] = sortableParamCols[key] && sortableCell;
} else {
sortableParamCols[key] = sortableCell;
}
}
// Save flattened keys in specific property `paramKeys` for later
rawTrial.paramKeys = Object.keys(flattenedParameters);
const trial = { ...rawTrial, ...flattenedParameters };
// Save statistics as already rendered components.
trial.statistics = <ObjectToGrid object={trial.statistics} />;
trials.push(trial);
}
// Prepare headers for this experiment using `paramKeys` from first trial
// We assume paramKeys is the same for all trials
const paramKeys = trials[0].paramKeys.slice();
paramKeys.sort();
const headers = [
{
accessorKey: 'id',
header: 'ID',
sortingFn: 'text',
cell: info =>
info.getValue().length > 7 ? (
<span title={info.getValue()}>
{info.getValue().substr(0, 7)}...
</span>
) : (
info.getValue()
),
},
{
// Grouped parameters columns
header: 'Parameters',
columns: paramKeys.map(k => {
const p = { accessorFn: r => r[k], header: k.substr(7) };
if (!sortableParamCols[k]) {
// column not sortable
p.cell = props => props.getValue();
p.enableSorting = false;
}
return p;
}),
},
{
accessorKey: 'submitTime',
header: 'Submit time',
},
{
accessorKey: 'startTime',
header: 'Start time',
},
{
accessorKey: 'endTime',
header: 'End time',
},
{
accessorKey: 'objective',
header: 'Objective',
},
{
// not sortable
accessorKey: 'statistics',
header: 'Statistics',
cell: props => props.getValue(),
},
];
this.trials[experiment] = {
headers: headers,
trials: trials,
};
}
return this.trials[experiment];
}
}
import { TrialsProvider } from './TrialsProvider';

/**
* Singleton to provide experiment trials.
Expand Down
Loading