Improved labels displayed in charts when visits are highlighted

This commit is contained in:
Alejandro Celaya 2020-05-31 09:07:21 +02:00
parent b6ab9a1bdd
commit 6a372badfa
4 changed files with 23 additions and 9 deletions

View file

@ -13,10 +13,11 @@ const propTypes = {
stats: PropTypes.object,
max: PropTypes.number,
highlightedStats: PropTypes.object,
highlightedLabel: PropTypes.string,
onClick: PropTypes.func,
};
const generateGraphData = (title, isBarChart, labels, data, highlightedData) => ({
const generateGraphData = (title, isBarChart, labels, data, highlightedData, highlightedLabel) => ({
labels,
datasets: [
{
@ -41,7 +42,7 @@ const generateGraphData = (title, isBarChart, labels, data, highlightedData) =>
},
highlightedData && {
title,
label: 'Selected',
label: highlightedLabel || 'Selected',
data: highlightedData,
backgroundColor: 'rgba(247, 127, 40, 0.4)',
borderColor: '#F77F28',
@ -60,7 +61,7 @@ const determineHeight = (isBarChart, labels) => {
return isBarChart && labels.length > 20 ? labels.length * 8 : null;
};
const renderGraph = (title, isBarChart, stats, max, highlightedStats, onClick) => {
const renderGraph = (title, isBarChart, stats, max, highlightedStats, highlightedLabel, onClick) => {
const hasHighlightedStats = highlightedStats && Object.keys(highlightedStats).length > 0;
const Component = isBarChart ? HorizontalBar : Doughnut;
const labels = keys(stats).map(dropLabelIfHidden);
@ -94,7 +95,7 @@ const renderGraph = (title, isBarChart, stats, max, highlightedStats, onClick) =
target.style.cursor = chartElement[0] ? 'pointer' : 'default';
}),
};
const graphData = generateGraphData(title, isBarChart, labels, data, highlightedData);
const graphData = generateGraphData(title, isBarChart, labels, data, highlightedData, highlightedLabel);
const height = determineHeight(isBarChart, labels);
// Provide a key based on the height, so that every time the dataset changes, a new graph is rendered
@ -118,10 +119,10 @@ const renderGraph = (title, isBarChart, stats, max, highlightedStats, onClick) =
);
};
const GraphCard = ({ title, footer, isBarChart, stats, max, highlightedStats, onClick }) => (
const GraphCard = ({ title, footer, isBarChart, stats, max, highlightedStats, highlightedLabel, onClick }) => (
<Card>
<CardHeader className="graph-card__header">{typeof title === 'function' ? title() : title}</CardHeader>
<CardBody>{renderGraph(title, isBarChart, stats, max, highlightedStats, onClick)}</CardBody>
<CardBody>{renderGraph(title, isBarChart, stats, max, highlightedStats, highlightedLabel, onClick)}</CardBody>
{footer && <CardFooter className="graph-card__footer--sticky">{footer}</CardFooter>}
</Card>
);

View file

@ -17,6 +17,7 @@ export default class SortableBarGraph extends React.Component {
static propTypes = {
stats: PropTypes.object.isRequired,
highlightedStats: PropTypes.object,
highlightedLabel: PropTypes.string,
title: PropTypes.string.isRequired,
sortingItems: PropTypes.object.isRequired,
extraHeaderContent: PropTypes.func,

View file

@ -42,6 +42,7 @@ const VisitsStats = ({ processStatsFromVisits, normalizeVisits }, OpenMapModalBt
const [ showTable, toggleTable ] = useToggle();
const [ tableIsSticky, , setSticky, unsetSticky ] = useToggle();
const [ highlightedVisits, setHighlightedVisits ] = useState([]);
const [ highlightedLabel, setHighlightedLabel ] = useState();
const [ isMobileDevice, setIsMobileDevice ] = useState(false);
const determineIsMobileDevice = () => setIsMobileDevice(matchMedia('(max-width: 991px)').matches);
const setSelectedVisits = (selectedVisits) => {
@ -53,9 +54,11 @@ const VisitsStats = ({ processStatsFromVisits, normalizeVisits }, OpenMapModalBt
if (selectedBar === newSelectedBar) {
setHighlightedVisits([]);
setHighlightedLabel(undefined);
selectedBar = undefined;
} else {
setHighlightedVisits(normalizedVisits.filter(propEq(prop, value)));
setHighlightedLabel(value);
selectedBar = newSelectedBar;
}
};
@ -111,7 +114,12 @@ const VisitsStats = ({ processStatsFromVisits, normalizeVisits }, OpenMapModalBt
return (
<div className="row">
<div className="col-12 mt-4">
<LineChartCard title="Visits during time" visits={visits} highlightedVisits={highlightedVisits} />
<LineChartCard
title="Visits during time"
visits={visits}
highlightedVisits={highlightedVisits}
highlightedLabel={highlightedLabel}
/>
</div>
<div className="col-xl-4 col-lg-6 mt-4">
<GraphCard title="Operating systems" stats={os} />
@ -125,6 +133,7 @@ const VisitsStats = ({ processStatsFromVisits, normalizeVisits }, OpenMapModalBt
stats={referrers}
withPagination={false}
highlightedStats={highlightedVisitsToStats(highlightedVisits, 'referer')}
highlightedLabel={highlightedLabel}
sortingItems={{
name: 'Referrer name',
amount: 'Visits amount',
@ -137,6 +146,7 @@ const VisitsStats = ({ processStatsFromVisits, normalizeVisits }, OpenMapModalBt
title="Countries"
stats={countries}
highlightedStats={highlightedVisitsToStats(highlightedVisits, 'country')}
highlightedLabel={highlightedLabel}
sortingItems={{
name: 'Country name',
amount: 'Visits amount',
@ -149,6 +159,7 @@ const VisitsStats = ({ processStatsFromVisits, normalizeVisits }, OpenMapModalBt
title="Cities"
stats={cities}
highlightedStats={highlightedVisitsToStats(highlightedVisits, 'city')}
highlightedLabel={highlightedLabel}
extraHeaderContent={(activeCities) =>
mapLocations.length > 0 &&
<OpenMapModalBtn modalTitle="Cities" locations={mapLocations} activeCities={activeCities} />

View file

@ -21,6 +21,7 @@ import Checkbox from '../../utils/Checkbox';
const propTypes = {
title: PropTypes.string,
highlightedLabel: PropTypes.string,
visits: PropTypes.arrayOf(VisitType),
highlightedVisits: PropTypes.arrayOf(VisitType),
};
@ -91,7 +92,7 @@ const generateDataset = (stats, label, color) => ({
backgroundColor: color,
});
const LineChartCard = ({ title, visits, highlightedVisits }) => {
const LineChartCard = ({ title, visits, highlightedVisits, highlightedLabel = 'Selected' }) => {
const [ step, setStep ] = useState('monthly');
const [ skipNoVisits, toggleSkipNoVisits ] = useToggle(true);
@ -109,7 +110,7 @@ const LineChartCard = ({ title, visits, highlightedVisits }) => {
labels,
datasets: [
generateDataset(groupedVisits, 'Visits', '#4696e5'),
highlightedVisits.length > 0 && generateDataset(groupedHighlighted, 'Selected', '#F77F28'),
highlightedVisits.length > 0 && generateDataset(groupedHighlighted, highlightedLabel, '#F77F28'),
].filter(Boolean),
};
const options = {