ui/infra-compare/InfraCompareTableControls.jsx (139 lines of code) (raw):
import React from 'react';
import PropTypes from 'prop-types';
import { Container, CustomInput, Label } from 'reactstrap';
import FilterControls from '../shared/FilterControls';
import { filterText } from './constants';
import { convertParams, containsText } from './helpers';
import InfraCompareTable from './InfraCompareTable';
export default class CompareTableControls extends React.Component {
constructor(props) {
super(props);
this.validated = this.props.validated;
this.state = {
showImportant: convertParams(this.validated, 'showOnlyImportant'),
hideUncertain: convertParams(this.validated, 'showOnlyImportant'),
results: new Map(),
filterPercent: 5,
filterText: '',
};
}
componentDidMount() {
this.updateFilteredResults();
}
componentDidUpdate(prevProps) {
const { compareResults } = this.props;
if (prevProps.compareResults !== compareResults) {
this.updateFilteredResults();
}
}
updateFilterText = (filterText) => {
this.setState({ filterText }, () => this.updateFilteredResults());
};
updateFilter = (filter) => {
this.setState(
(prevState) => ({ [filter]: !prevState[filter] }),
() => this.updateFilteredResults(),
);
};
filterResult = (platformName, result, filterPercent) => {
const { filterText, showImportant, hideUncertain } = this.state;
const matchesFilters =
(!showImportant || result.deltaPercentage > filterPercent) &&
(!hideUncertain || result.isCertain);
if (!filterText) return matchesFilters;
const textToSearch = `${platformName} ${result.suite}`;
// searching with filter input and one or more metricFilter buttons on
// will produce different results compared to when all filters are off
return containsText(textToSearch, filterText) && matchesFilters;
};
updateFilteredResults = (filterPercent = this.state.filterPercent) => {
const { filterText, showImportant, hideUncertain } = this.state;
const { compareResults } = this.props;
if (
filterPercent === 0 &&
!filterText &&
!showImportant &&
!hideUncertain
) {
return this.setState({ results: compareResults });
}
const filteredResults = new Map(compareResults);
for (const [platformName, values] of filteredResults) {
const filteredValues = values.filter((result) =>
this.filterResult(platformName, result, filterPercent),
);
if (filteredValues.length) {
filteredResults.set(platformName, filteredValues);
} else {
filteredResults.delete(platformName);
}
}
this.setState({ results: filteredResults });
};
render() {
const { hideUncertain, showImportant, results, filterPercent } = this.state;
const compareFilters = [
{
tooltipText: `Non-trivial changes (${filterPercent}%+)`,
text: filterText.showImportant,
state: showImportant,
stateName: 'showImportant',
},
{
tooltipText: 'Less than 4 datapoints',
text: filterText.hideUncertain,
state: hideUncertain,
stateName: 'hideUncertain',
},
];
return (
<Container fluid className="my-3 px-0">
<FilterControls
dropdownOptions={[]}
filterOptions={compareFilters}
updateFilter={this.updateFilter}
updateFilterText={this.updateFilterText}
/>
<Label for="filterPercent">Filter percentage: {filterPercent}%</Label>
<CustomInput
type="range"
id="filterPercent"
name="customSelect"
min={0}
max={20}
value={filterPercent}
onChange={(e) => {
this.setState({
filterPercent: e.target.value,
});
this.updateFilteredResults(e.target.value);
}}
/>
{results.size > 0 ? (
Array.from(results).map(([platform, data]) => (
<InfraCompareTable
platform={platform}
data={data}
{...this.props}
/>
))
) : (
<p className="lead text-center">No results to show</p>
)}
</Container>
);
}
}
CompareTableControls.propTypes = {
compareResults: PropTypes.shape({}).isRequired,
validated: PropTypes.shape({
showOnlyImportant: PropTypes.string,
hideUncertain: PropTypes.string,
}),
};
CompareTableControls.defaultProps = {
validated: {
showOnlyImportant: undefined,
hideUncertain: undefined,
},
};