Updated GraphCard so that it automatically calculates the proper aspect ration for bar chart graphs

This commit is contained in:
Alejandro Celaya 2018-10-19 20:27:25 +02:00
parent 812e391e34
commit 0e8631ae9d
2 changed files with 44 additions and 9 deletions

View file

@ -8,14 +8,18 @@ const propTypes = {
title: PropTypes.string,
isBarChart: PropTypes.bool,
stats: PropTypes.object,
matchMedia: PropTypes.func,
};
const defaultProps = {
matchMedia: global.window ? global.window.matchMedia : () => {},
};
const generateGraphData = (title, isBarChart, stats) => ({
labels: keys(stats),
const generateGraphData = (title, isBarChart, labels, data) => ({
labels,
datasets: [
{
title,
data: values(stats),
data,
backgroundColor: isBarChart ? 'rgba(70, 150, 229, 0.4)' : [
'#97BBCD',
'#DCDCDC',
@ -31,9 +35,38 @@ const generateGraphData = (title, isBarChart, stats) => ({
],
});
const renderGraph = (title, isBarChart, stats) => {
const determineGraphAspectRatio = (barsCount, isBarChart, matchMedia) => {
const determineAspectRationModifier = () => {
switch (true) {
case matchMedia('(max-width: 1200px)').matches:
return 1.5; // eslint-disable-line no-magic-numbers
case matchMedia('(max-width: 992px)').matches:
return 1.75; // eslint-disable-line no-magic-numbers
case matchMedia('(max-width: 768px)').matches:
return 2; // eslint-disable-line no-magic-numbers
case matchMedia('(max-width: 576px)').matches:
return 2.25; // eslint-disable-line no-magic-numbers
default:
return 1;
}
};
const MAX_BARS_WITHOUT_HEIGHT = 20;
const DEFAULT_ASPECT_RATION = 2;
const shouldCalculateAspectRatio = isBarChart && barsCount > MAX_BARS_WITHOUT_HEIGHT;
return shouldCalculateAspectRatio
? MAX_BARS_WITHOUT_HEIGHT / determineAspectRationModifier() * DEFAULT_ASPECT_RATION / barsCount
: DEFAULT_ASPECT_RATION;
};
const renderGraph = (title, isBarChart, stats, matchMedia) => {
const Component = isBarChart ? HorizontalBar : Doughnut;
const labels = keys(stats);
const data = values(stats);
const aspectRatio = determineGraphAspectRatio(labels.length, isBarChart, matchMedia);
const options = {
aspectRatio,
legend: isBarChart ? { display: false } : { position: 'right' },
scales: isBarChart ? {
xAxes: [
@ -44,16 +77,17 @@ const renderGraph = (title, isBarChart, stats) => {
} : null,
};
return <Component data={generateGraphData(title, isBarChart, stats)} options={options} />;
return <Component data={generateGraphData(title, isBarChart, labels, data)} options={options} height={null} />;
};
const GraphCard = ({ title, isBarChart, stats }) => (
const GraphCard = ({ title, isBarChart, stats, matchMedia }) => (
<Card className="mt-4">
<CardHeader>{title}</CardHeader>
<CardBody>{renderGraph(title, isBarChart, stats)}</CardBody>
<CardBody>{renderGraph(title, isBarChart, stats, matchMedia)}</CardBody>
</Card>
);
GraphCard.propTypes = propTypes;
GraphCard.defaultProps = defaultProps;
export default GraphCard;

View file

@ -10,6 +10,7 @@ describe('<GraphCard />', () => {
foo: 123,
bar: 456,
};
const matchMedia = () => ({ matches: false });
afterEach(() => {
if (wrapper) {
@ -18,7 +19,7 @@ describe('<GraphCard />', () => {
});
it('renders Doughnut when is not a bar chart', () => {
wrapper = shallow(<GraphCard title="The chart" stats={stats} />);
wrapper = shallow(<GraphCard matchMedia={matchMedia} title="The chart" stats={stats} />);
const doughnut = wrapper.find(Doughnut);
const horizontal = wrapper.find(HorizontalBar);
@ -46,7 +47,7 @@ describe('<GraphCard />', () => {
});
it('renders HorizontalBar when is not a bar chart', () => {
wrapper = shallow(<GraphCard isBarChart title="The chart" stats={stats} />);
wrapper = shallow(<GraphCard matchMedia={matchMedia} isBarChart title="The chart" stats={stats} />);
const doughnut = wrapper.find(Doughnut);
const horizontal = wrapper.find(HorizontalBar);