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

Add period chat counts to chart legend (#323) #336

Merged
merged 8 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions GUI/src/components/BarGraph/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import React, { useEffect, useRef, useState } from 'react';
import { BarChart, CartesianGrid, YAxis, Tooltip, Legend, Bar, Label, XAxis } from 'recharts';
import { chartDataKey, dateFormatter, formatDate, getColor, getKeys, getTicks, round } from '../../util/charts-utils';
import {
chartDataKey,
dateFormatter,
formatDate,
formatTotalPeriodCount,
getColor,
getKeys,
getTicks,
round,
} from '../../util/charts-utils';
import { GroupByPeriod } from '../MetricAndPeriodOptions/types';
import { useTranslation } from 'react-i18next';
import { useTotalPeriodCounts } from '../../hooks/ useTotalPeriodCounts';

type Props = {
data: any;
Expand All @@ -14,6 +24,8 @@ type Props = {

const BarGraph: React.FC<Props> = ({ startDate, endDate, data, unit, groupByPeriod }) => {
const [width, setWidth] = useState<number | null>(null);
const totalPeriodCounts = useTotalPeriodCounts(data.chartData, unit);

const ref = useRef<HTMLDivElement>(null);
const { t } = useTranslation();

Expand Down Expand Up @@ -84,7 +96,10 @@ const BarGraph: React.FC<Props> = ({ startDate, endDate, data, unit, groupByPeri
}}
cursor={false}
/>
<Legend wrapperStyle={{ position: 'relative', marginTop: '20px' }} />
<Legend
wrapperStyle={{ position: 'relative', marginTop: '20px' }}
formatter={(value) => `${value}${formatTotalPeriodCount(totalPeriodCounts, value)}`}
/>
{data?.chartData?.length > 0 &&
getKeys(data.chartData).map((k, i) => {
const isCount = k === t('chats.totalCount');
Expand Down
18 changes: 16 additions & 2 deletions GUI/src/components/LineGraph/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import React, { useEffect, useRef, useState } from 'react';
import { LineChart, XAxis, Line, CartesianGrid, YAxis, Tooltip, Legend, Label } from 'recharts';
import { chartDataKey, dateFormatter, formatDate, getColor, getKeys, getTicks, round } from '../../util/charts-utils';
import {
chartDataKey,
dateFormatter,
formatDate,
formatTotalPeriodCount,
getColor,
getKeys,
getTicks,
round,
} from '../../util/charts-utils';
import { useTotalPeriodCounts } from '../../hooks/ useTotalPeriodCounts';

type Props = {
data: any;
Expand All @@ -12,6 +22,7 @@ type Props = {
const LineGraph = ({ data, startDate, endDate, unit }: Props) => {
const [width, setWidth] = useState<number | null>(null);
const ref = useRef<HTMLDivElement>(null);
const totalPeriodCounts = useTotalPeriodCounts(data.chartData, unit);

useEffect(() => {
const handleResize = () => {
Expand Down Expand Up @@ -73,7 +84,10 @@ const LineGraph = ({ data, startDate, endDate, unit }: Props) => {
value={unit}
/>
</YAxis>
<Legend wrapperStyle={{ position: 'relative', marginTop: '20px' }} />
<Legend
wrapperStyle={{ position: 'relative', marginTop: '20px' }}
formatter={(value) => `${value}${formatTotalPeriodCount(totalPeriodCounts, value)}`}
/>
<CartesianGrid stroke="#f5f5f5" />
{data?.chartData?.length > 0 &&
getKeys(data.chartData).map((k, i) => {
Expand Down
7 changes: 6 additions & 1 deletion GUI/src/components/MetricsCharts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ const MetricsCharts = ({ title, data, startDate, endDate, unit, groupByPeriod }:

const buildChart = () => {
if (selectedChart === 'pieChart') {
return <PieGraph data={data} />;
return (
<PieGraph
data={data}
unit={unit}
/>
);
} else if (selectedChart === 'lineChart') {
return (
<LineGraph
Expand Down
37 changes: 20 additions & 17 deletions GUI/src/components/PieGraph/PieCharLegends.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import React from 'react';
import { getColor } from '../../util/charts-utils';
import { formatTotalPeriodCount, getColor } from '../../util/charts-utils';
import Track from '../Track';
import './PieGraph.scss';
import { useTotalPeriodCounts } from '../../hooks/ useTotalPeriodCounts';

type Props = {
data: any;
percentages: any;
unit?: string;
};

const PieCharLegends = ({ data, percentages }: Props) => {
const PieCharLegends = ({ data, percentages, unit }: Props) => {
const totalPeriodCounts = useTotalPeriodCounts(data.chartData, unit);

return (
<Track
direction="vertical"
Expand All @@ -17,22 +21,21 @@ const PieCharLegends = ({ data, percentages }: Props) => {
isFlex
isMultiline
>
{
percentages?.map((e: any) => {
const color = getColor(data, e.name);
{percentages?.map((e: any) => {
const color = getColor(data, e.name);

return (
<Track key={`track-${e.name}`}>
<div
className="legend_circle"
style={{ backgroundColor: color }}
/>
<label style={{ color, maxLines: 1 }}>
{`${e.name}: ${e.value} %`}
</label>
</Track>
)})
}
return (
<Track key={`track-${e.name}`}>
<div
className="legend_circle"
style={{ backgroundColor: color }}
/>
<label style={{ color, maxLines: 1 }}>
{`${e.name}: ${e.value} %${formatTotalPeriodCount(totalPeriodCounts, e.name)}`}
</label>
</Track>
);
})}
</Track>
);
};
Expand Down
47 changes: 26 additions & 21 deletions GUI/src/components/PieGraph/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ import './PieGraph.scss';

type Props = {
data: any;
unit?: string;
};

const PieGraph = ({ data }: Props) => {
const PieGraph = ({ data, unit }: Props) => {
const [width, setWidth] = useState<number | null>(null);
const ref = useRef<HTMLDivElement>(null);
const { t } = useTranslation();

const percentages = useMemo(() => calculatePercentagesFromResponse(data?.chartData ?? []), [data?.chartData]);

useEffect(() => {
const handleResize = () => {
setWidth(ref.current?.clientWidth ?? 0);
Expand All @@ -38,28 +39,32 @@ const PieGraph = ({ data }: Props) => {
data={data.chartData}
margin={{ top: 20, right: 30, left: 20, bottom: 5 }}
>
<Pie
data={percentages}
cx="50%"
cy="50%"
outerRadius='100%'
fill="#8884d8"
dataKey="value"
nameKey="name"
>
{percentages.map((e: any) =>
<Cell
key={`cell-${e['name']}`}
type="monotone"
stroke={getColor(data, e['name'])}
fill={getColor(data, e['name'])}
/>
)}
</Pie>
<Pie
data={percentages}
cx="50%"
cy="50%"
outerRadius="100%"
fill="#8884d8"
dataKey="value"
nameKey="name"
>
{percentages.map((e: any) => (
<Cell
key={`cell-${e['name']}`}
type="monotone"
stroke={getColor(data, e['name'])}
fill={getColor(data, e['name'])}
/>
))}
</Pie>
<Tooltip content={data?.percentages ? <PercentageToolTip /> : <ChartToolTip />} />
</PieChart>
{percentages.length === 0 && <span>{t('chart.noDataToPlot')}</span>}
<PieCharLegends data={data} percentages={percentages} />
<PieCharLegends
data={data}
percentages={percentages}
unit={unit}
/>
</Track>
</div>
);
Expand Down
27 changes: 27 additions & 0 deletions GUI/src/hooks/ useTotalPeriodCounts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';

export const useTotalPeriodCounts = (chartData: Record<string, number>[] | undefined, unit: string | undefined) => {
const [totalPeriodCounts, setTotalPeriodCounts] = useState<Record<string, number>>({});
const { t } = useTranslation();

useEffect(() => {
if (!chartData?.length || unit !== t('units.chats')) return;

setTotalPeriodCounts(getPeriodTotalCounts(chartData));
}, [chartData, unit, t]);

return totalPeriodCounts;
};

const getPeriodTotalCounts = (chartData: Record<string, number>[]) => {
const totals: Record<string, number> = {};

chartData.forEach((entry) => {
Object.entries(entry).forEach(([key, value]) => {
if (key !== 'dateTime') totals[key] = (totals[key] ?? 0) + value;
});
});

return totals;
};
3 changes: 3 additions & 0 deletions GUI/src/util/charts-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,6 @@ export const chartDataKey = 'dateTime';
export const round = (value: any) => Math.round(Number(value) * 100) / 100;

export const getKeys = (data: any[]) => Array.from(new Set(data.flatMap((obj: any) => Object.keys(obj))));

export const formatTotalPeriodCount = (totalPeriodCounts: Record<string, number>, metric: string) =>
`${totalPeriodCounts[metric] ? ` (${totalPeriodCounts[metric]})` : ''}`;