diff --git a/src/visits/helpers/DefaultChart.js b/src/visits/helpers/DefaultChart.js index 40fbc0da..3fbf150c 100644 --- a/src/visits/helpers/DefaultChart.js +++ b/src/visits/helpers/DefaultChart.js @@ -1,8 +1,10 @@ -import React from 'react'; +import React, { useRef } from 'react'; import PropTypes from 'prop-types'; import { Doughnut, HorizontalBar } from 'react-chartjs-2'; import { keys, values } from 'ramda'; +import classNames from 'classnames'; import { fillTheGaps } from '../../utils/helpers/visits'; +import './DefaultChart.scss'; const propTypes = { title: PropTypes.oneOfType([ PropTypes.string, PropTypes.func ]), @@ -58,6 +60,39 @@ const determineHeight = (isBarChart, labels) => { return isBarChart && labels.length > 20 ? labels.length * 8 : null; }; +/* eslint-disable react/prop-types */ +const renderPieChartLegend = ({ config }) => { + const { labels, datasets } = config.data; + const { defaultColor } = config.options; + const [{ backgroundColor: colors }] = datasets; + + return ( + + ); +}; +/* eslint-enable react/prop-types */ + +const chartElementAtEvent = (onClick) => ([ chart ]) => { + if (!onClick || !chart) { + return; + } + + const { _index, _chart: { data } } = chart; + const { labels } = data; + + onClick(labels[_index]); +}; + const DefaultChart = ({ title, isBarChart, stats, max, highlightedStats, highlightedLabel, onClick }) => { const hasHighlightedStats = highlightedStats && Object.keys(highlightedStats).length > 0; const Component = isBarChart ? HorizontalBar : Doughnut; @@ -70,9 +105,11 @@ const DefaultChart = ({ title, isBarChart, stats, max, highlightedStats, highlig return acc; }, { ...stats })); const highlightedData = hasHighlightedStats && fillTheGaps(highlightedStats, labels); + const chartRef = useRef(); const options = { - legend: isBarChart ? { display: false } : { position: 'right' }, + legend: { display: false }, + legendCallback: !isBarChart && renderPieChartLegend, scales: isBarChart && { xAxes: [ { @@ -97,22 +134,23 @@ const DefaultChart = ({ title, isBarChart, stats, max, highlightedStats, highlig // Provide a key based on the height, so that every time the dataset changes, a new graph is rendered return ( - { - if (!onClick || !chart) { - return; - } - - const { _index, _chart: { data } } = chart; - const { labels } = data; - - onClick(labels[_index]); - }} - /> +
+
+ +
+ {!isBarChart && ( +
+ {chartRef.current && chartRef.current.chartInstance.generateLegend()} +
+ )} +
); }; diff --git a/src/visits/helpers/DefaultChart.scss b/src/visits/helpers/DefaultChart.scss new file mode 100644 index 00000000..e7a0bd9f --- /dev/null +++ b/src/visits/helpers/DefaultChart.scss @@ -0,0 +1,29 @@ +@import '../../utils/base'; + +.default-chart__pie-chart-legend { + list-style-type: none; + padding: 0; + margin: 0; + + @media (max-width: $smMax) { + margin-top: 1rem; + } +} + +.default-chart__pie-chart-legend-item:not(:first-child) { + margin-top: .3rem; +} + +.default-chart__pie-chart-legend-item-color { + width: 20px; + min-width: 20px; + height: 20px; + margin-right: 5px; + border-radius: 10px; +} + +.default-chart__pie-chart-legend-item-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/test/visits/helpers/DefaultChart.js b/test/visits/helpers/DefaultChart.test.js similarity index 86% rename from test/visits/helpers/DefaultChart.js rename to test/visits/helpers/DefaultChart.test.js index 7bff35e9..387fd0ed 100644 --- a/test/visits/helpers/DefaultChart.js +++ b/test/visits/helpers/DefaultChart.test.js @@ -17,13 +17,14 @@ describe('', () => { wrapper = shallow(); const doughnut = wrapper.find(Doughnut); const horizontal = wrapper.find(HorizontalBar); + const cols = wrapper.find('.col-sm-12'); expect(doughnut).toHaveLength(1); expect(horizontal).toHaveLength(0); const { labels, datasets } = doughnut.prop('data'); const [{ title, data, backgroundColor, borderColor }] = datasets; - const { legend, scales } = doughnut.prop('options'); + const { legend, legendCallback, scales } = doughnut.prop('options'); expect(title).toEqual('The chart'); expect(labels).toEqual(keys(stats)); @@ -43,24 +44,28 @@ describe('', () => { '#463730', ]); expect(borderColor).toEqual('white'); - expect(legend).toEqual({ position: 'right' }); + expect(legend).toEqual({ display: false }); + expect(typeof legendCallback).toEqual('function'); expect(scales).toBeUndefined(); + expect(cols).toHaveLength(2); }); it('renders HorizontalBar when is not a bar chart', () => { wrapper = shallow(); const doughnut = wrapper.find(Doughnut); const horizontal = wrapper.find(HorizontalBar); + const cols = wrapper.find('.col-sm-12'); expect(doughnut).toHaveLength(0); expect(horizontal).toHaveLength(1); const { datasets: [{ backgroundColor, borderColor }] } = horizontal.prop('data'); - const { legend, scales } = horizontal.prop('options'); + const { legend, legendCallback, scales } = horizontal.prop('options'); expect(backgroundColor).toEqual('rgba(70, 150, 229, 0.4)'); expect(borderColor).toEqual('rgba(70, 150, 229, 1)'); expect(legend).toEqual({ display: false }); + expect(legendCallback).toEqual(false); expect(scales).toEqual({ xAxes: [ { @@ -70,6 +75,7 @@ describe('', () => { ], yAxes: [{ stacked: true }], }); + expect(cols).toHaveLength(1); }); it.each([