Skip to content

Commit 2f59e71

Browse files
fix: Real-time monitoring displaying incorrect data (RocketChat#37103)
1 parent fef8715 commit 2f59e71

10 files changed

Lines changed: 199 additions & 129 deletions

File tree

.changeset/rare-schools-laugh.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@rocket.chat/meteor": patch
3+
---
4+
5+
Fixes real-time monitoring displaying incorrect data

apps/meteor/app/livechat/client/lib/chartHandler.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,12 @@ export const updateChart = async <TChartType extends chartjs.ChartType>(
209209

210210
chart.update();
211211
};
212+
213+
export const resetChart = <TChartType extends chartjs.ChartType>(chart: chartjs.Chart<TChartType>): void => {
214+
chart.data.labels = [];
215+
chart.data.datasets.forEach((dataset) => {
216+
dataset.data = [];
217+
});
218+
219+
chart.update();
220+
};

apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/AgentStatusChart.tsx

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useRef, useEffect } from 'react';
99
import { useTranslation } from 'react-i18next';
1010

1111
import Chart from './Chart';
12+
import { useChartContext } from './useChartContext';
1213
import { useUpdateChartData } from './useUpdateChartData';
1314
import { drawDoughnutChart } from '../../../../../app/livechat/client/lib/chartHandler';
1415
import { omnichannelQueryKeys } from '../../../../lib/queryKeys';
@@ -39,40 +40,41 @@ const AgentStatusChart = ({ departmentId, ...props }: AgentStatusChartsProps) =>
3940
const { t } = useTranslation();
4041

4142
const canvas: MutableRefObject<HTMLCanvasElement | null> = useRef(null);
42-
const context: MutableRefObject<chartjs.Chart<'doughnut'> | undefined> = useRef();
43-
44-
const updateChartData = useUpdateChartData({
45-
context,
46-
canvas,
47-
t,
48-
init,
49-
});
5043

5144
const getAgentStatus = useEndpoint('GET', '/v1/livechat/analytics/dashboards/charts/agents-status');
5245
const { isSuccess, data: { offline = 0, available = 0, away = 0, busy = 0 } = initialData } = useQuery({
5346
queryKey: omnichannelQueryKeys.analytics.agentsStatus(departmentId),
5447
queryFn: () => getAgentStatus({ departmentId }),
48+
gcTime: 0,
5549
});
5650

57-
useEffect(() => {
58-
const initChart = async () => {
59-
if (!canvas.current) {
60-
return;
61-
}
51+
const context = useChartContext({
52+
canvas,
53+
init,
54+
t,
55+
});
6256

63-
context.current = await init(canvas.current, context.current, t);
64-
};
65-
initChart();
66-
}, [t]);
57+
const updateChartData = useUpdateChartData({
58+
context,
59+
canvas,
60+
init,
61+
t,
62+
});
6763

6864
useEffect(() => {
69-
if (!isSuccess) return;
65+
if (!context) {
66+
return;
67+
}
68+
69+
if (!isSuccess) {
70+
return;
71+
}
7072

7173
updateChartData(t('Offline'), [offline]);
7274
updateChartData(t('Available'), [available]);
7375
updateChartData(t('Away'), [away]);
7476
updateChartData(t('Busy'), [busy]);
75-
}, [available, away, busy, offline, isSuccess, t, updateChartData]);
77+
}, [context, available, away, busy, offline, isSuccess, t, updateChartData]);
7678

7779
return <Chart canvasRef={canvas} {...props} />;
7880
};

apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/ChatDurationChart.tsx

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { useTranslation } from 'react-i18next';
1111
import Chart from './Chart';
1212
import { getMomentChartLabelsAndData } from './getMomentChartLabelsAndData';
1313
import { getMomentCurrentLabel } from './getMomentCurrentLabel';
14+
import { useChartContext } from './useChartContext';
1415
import { useUpdateChartData } from './useUpdateChartData';
1516
import { drawLineChart } from '../../../../../app/livechat/client/lib/chartHandler';
1617
import { secondsToHHMMSS } from '../../../../../lib/utils/secondsToHHMMSS';
@@ -48,19 +49,25 @@ const ChatDurationChart = ({ departmentId, dateRange, ...props }: ChatDurationCh
4849
const { t } = useTranslation();
4950

5051
const canvas = useRef<HTMLCanvasElement | null>(null);
51-
const context = useRef<chartjs.Chart<'line'>>();
52-
53-
const updateChartData = useUpdateChartData({
54-
context,
55-
canvas,
56-
t,
57-
init,
58-
});
5952

6053
const getTimings = useEndpoint('GET', '/v1/livechat/analytics/dashboards/charts/timings');
6154
const { isSuccess, data } = useQuery({
6255
queryKey: omnichannelQueryKeys.analytics.timings(departmentId, dateRange),
6356
queryFn: () => getTimings({ departmentId, ...dateRange }),
57+
gcTime: 0,
58+
});
59+
60+
const context = useChartContext({
61+
canvas,
62+
init,
63+
t,
64+
});
65+
66+
const updateChartData = useUpdateChartData({
67+
context,
68+
canvas,
69+
init,
70+
t,
6471
});
6572

6673
const {
@@ -73,22 +80,17 @@ const ChatDurationChart = ({ departmentId, dateRange, ...props }: ChatDurationCh
7380
};
7481

7582
useEffect(() => {
76-
const initChart = async () => {
77-
if (!canvas.current) {
78-
return;
79-
}
83+
if (!context) {
84+
return;
85+
}
8086

81-
context.current = await init(canvas.current, context.current, t);
82-
};
83-
initChart();
84-
}, [t]);
85-
86-
useEffect(() => {
87-
if (!isSuccess) return;
87+
if (!isSuccess) {
88+
return;
89+
}
8890

8991
const label = getMomentCurrentLabel();
9092
updateChartData(label, [avg, longest]);
91-
}, [avg, longest, isSuccess, t, updateChartData]);
93+
}, [context, avg, longest, isSuccess, t, updateChartData]);
9294

9395
return <Chart canvasRef={canvas} {...props} />;
9496
};

apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/ChatsChart.tsx

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useRef, useEffect } from 'react';
99
import { useTranslation } from 'react-i18next';
1010

1111
import Chart from './Chart';
12+
import { useChartContext } from './useChartContext';
1213
import { useUpdateChartData } from './useUpdateChartData';
1314
import { drawDoughnutChart } from '../../../../../app/livechat/client/lib/chartHandler';
1415
import { omnichannelQueryKeys } from '../../../../lib/queryKeys';
@@ -40,41 +41,43 @@ const ChatsChart = ({ departmentId, dateRange, ...props }: ChatsChartProps) => {
4041
const { t } = useTranslation();
4142

4243
const canvas: MutableRefObject<HTMLCanvasElement | null> = useRef(null);
43-
const context: MutableRefObject<chartjs.Chart<'doughnut'> | undefined> = useRef();
44-
45-
const updateChartData = useUpdateChartData({
46-
context,
47-
canvas,
48-
t,
49-
init,
50-
});
5144

5245
const getChats = useEndpoint('GET', '/v1/livechat/analytics/dashboards/charts/chats');
5346
const { isSuccess, data } = useQuery({
5447
queryKey: omnichannelQueryKeys.analytics.chats(departmentId, dateRange),
5548
queryFn: () => getChats({ departmentId, ...dateRange }),
49+
gcTime: 0,
50+
});
51+
52+
const context = useChartContext({
53+
canvas,
54+
init,
55+
t,
56+
});
57+
58+
const updateChartData = useUpdateChartData({
59+
context,
60+
canvas,
61+
init,
62+
t,
5663
});
5764

5865
const { open, queued, closed, onhold } = data ?? initialData;
5966

6067
useEffect(() => {
61-
const initChart = async () => {
62-
if (!canvas.current) {
63-
return;
64-
}
65-
context.current = await init(canvas.current, context.current, t);
66-
};
67-
initChart();
68-
}, [t]);
68+
if (!context) {
69+
return;
70+
}
6971

70-
useEffect(() => {
71-
if (!isSuccess) return;
72+
if (!isSuccess) {
73+
return;
74+
}
7275

7376
updateChartData(t('Open'), [open]);
7477
updateChartData(t('Closed'), [closed]);
7578
updateChartData(t('On_Hold_Chats'), [onhold]);
7679
updateChartData(t('Queued'), [queued]);
77-
}, [closed, open, queued, onhold, isSuccess, t, updateChartData]);
80+
}, [context, closed, open, queued, onhold, isSuccess, t, updateChartData]);
7881

7982
return <Chart canvasRef={canvas} {...props} />;
8083
};

apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/ChatsPerAgentChart.tsx

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import { useRef, useEffect } from 'react';
99
import { useTranslation } from 'react-i18next';
1010

1111
import Chart from './Chart';
12+
import { useChartContext } from './useChartContext';
1213
import { useUpdateChartData } from './useUpdateChartData';
13-
import { drawLineChart } from '../../../../../app/livechat/client/lib/chartHandler';
14+
import { drawLineChart, resetChart } from '../../../../../app/livechat/client/lib/chartHandler';
1415
import { omnichannelQueryKeys } from '../../../../lib/queryKeys';
1516

1617
const init = (canvas: HTMLCanvasElement, context: chartjs.Chart<'line'> | undefined, t: TFunction) =>
@@ -29,42 +30,41 @@ const ChatsPerAgentChart = ({ departmentId, dateRange, ...props }: ChatsPerAgent
2930
const { t } = useTranslation();
3031

3132
const canvas = useRef<HTMLCanvasElement | null>(null);
32-
const context = useRef<chartjs.Chart<'line'>>();
33-
34-
const updateChartData = useUpdateChartData({
35-
context,
36-
canvas,
37-
t,
38-
init,
39-
});
4033

4134
const getChatsPerAgent = useEndpoint('GET', '/v1/livechat/analytics/dashboards/charts/chats-per-agent');
4235
const { isSuccess, data } = useQuery({
4336
queryKey: omnichannelQueryKeys.analytics.chatsPerAgent(departmentId, dateRange),
4437
queryFn: () => getChatsPerAgent({ departmentId, ...dateRange }),
38+
select: ({ success: _, ...data }) => Object.entries(data),
39+
gcTime: 0,
4540
});
4641

47-
useEffect(() => {
48-
const initChart = async () => {
49-
if (!canvas.current) {
50-
return;
51-
}
52-
context.current = await init(canvas.current, context.current, t);
53-
};
54-
initChart();
55-
}, [t]);
42+
const context = useChartContext({
43+
canvas,
44+
init,
45+
t,
46+
});
47+
48+
const updateChartData = useUpdateChartData({
49+
context,
50+
canvas,
51+
init,
52+
t,
53+
});
5654

5755
useEffect(() => {
58-
if (!isSuccess) return;
56+
if (!context) return;
57+
58+
if (!isSuccess) {
59+
return;
60+
}
5961

60-
Object.entries(data).forEach(([name, value]) => {
61-
if (name === 'success') {
62-
return;
63-
}
62+
resetChart(context);
6463

64+
data.forEach(([name, value]) => {
6565
updateChartData(name, [value.open, value.closed, value.onhold]);
6666
});
67-
}, [data, isSuccess, t, updateChartData]);
67+
}, [context, data, isSuccess, t, updateChartData]);
6868

6969
return <Chart canvasRef={canvas} {...props} />;
7070
};

apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/ChatsPerDepartmentChart.tsx

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import { useRef, useEffect } from 'react';
99
import { useTranslation } from 'react-i18next';
1010

1111
import Chart from './Chart';
12+
import { useChartContext } from './useChartContext';
1213
import { useUpdateChartData } from './useUpdateChartData';
13-
import { drawLineChart } from '../../../../../app/livechat/client/lib/chartHandler';
14+
import { drawLineChart, resetChart } from '../../../../../app/livechat/client/lib/chartHandler';
1415
import { omnichannelQueryKeys } from '../../../../lib/queryKeys';
1516

1617
const init = (canvas: HTMLCanvasElement, context: chartjs.Chart<'line'> | undefined, t: TFunction) =>
@@ -29,41 +30,43 @@ const ChatsPerDepartmentChart = ({ departmentId, dateRange, ...props }: ChatsPer
2930
const { t } = useTranslation();
3031

3132
const canvas = useRef<HTMLCanvasElement | null>(null);
32-
const context = useRef<chartjs.Chart<'line'>>();
33-
34-
const updateChartData = useUpdateChartData({
35-
context,
36-
canvas,
37-
t,
38-
init,
39-
});
4033

4134
const getChatsPerDepartment = useEndpoint('GET', '/v1/livechat/analytics/dashboards/charts/chats-per-department');
4235
const { isSuccess, data } = useQuery({
4336
queryKey: omnichannelQueryKeys.analytics.chatsPerDepartment(departmentId, dateRange),
4437
queryFn: () => getChatsPerDepartment({ departmentId, ...dateRange }),
38+
select: ({ success: _, ...data }) => Object.entries(data),
39+
gcTime: 0,
4540
});
4641

47-
useEffect(() => {
48-
const initChart = async () => {
49-
if (!canvas.current) {
50-
return;
51-
}
52-
context.current = await init(canvas.current, context.current, t);
53-
};
54-
initChart();
55-
}, [t]);
42+
const context = useChartContext({
43+
canvas,
44+
init,
45+
t,
46+
});
47+
48+
const updateChartData = useUpdateChartData({
49+
context,
50+
canvas,
51+
init,
52+
t,
53+
});
5654

5755
useEffect(() => {
58-
if (!isSuccess) return;
59-
Object.entries(data).forEach(([name, value]) => {
60-
if (name === 'success') {
61-
return;
62-
}
56+
if (!context) {
57+
return;
58+
}
59+
60+
if (!isSuccess) {
61+
return;
62+
}
63+
64+
resetChart(context);
6365

66+
data.forEach(([name, value]) => {
6467
updateChartData(name, [value.open, value.closed]);
6568
});
66-
}, [data, isSuccess, t, updateChartData]);
69+
}, [context, data, isSuccess, t, updateChartData]);
6770

6871
return <Chart canvasRef={canvas} {...props} />;
6972
};

0 commit comments

Comments
 (0)