From ae83e43f3010f8e1eff28edffa0f1472fc8bfdd1 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Fri, 27 Oct 2023 08:20:44 -0600 Subject: [PATCH] fix: Invalid date error on some non-roman languages. (#30209) Co-authored-by: Tasso Evangelista <2263066+tassoevan@users.noreply.github.com> --- .../omnichannel/analytics/DateRangePicker.tsx | 2 + .../charts/getMomentChartLabelsAndData.js | 14 ----- .../getMomentChartLabelsAndData.spec.ts | 52 +++++++++++++++++++ .../charts/getMomentChartLabelsAndData.ts | 14 +++++ .../charts/getMomentCurrentLabel.js | 7 --- .../charts/getMomentCurrentLabel.spec.ts | 20 +++++++ .../charts/getMomentCurrentLabel.ts | 8 +++ .../charts/useUpdateChartData.js | 11 ---- .../charts/useUpdateChartData.ts | 26 ++++++++++ 9 files changed, 122 insertions(+), 32 deletions(-) delete mode 100644 apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.js create mode 100644 apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.spec.ts create mode 100644 apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.ts delete mode 100644 apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.js create mode 100644 apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.spec.ts create mode 100644 apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.ts delete mode 100644 apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/useUpdateChartData.js create mode 100644 apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/useUpdateChartData.ts diff --git a/apps/meteor/client/views/omnichannel/analytics/DateRangePicker.tsx b/apps/meteor/client/views/omnichannel/analytics/DateRangePicker.tsx index 40644b1f1b048..40c32f4d6980a 100644 --- a/apps/meteor/client/views/omnichannel/analytics/DateRangePicker.tsx +++ b/apps/meteor/client/views/omnichannel/analytics/DateRangePicker.tsx @@ -6,6 +6,8 @@ import moment from 'moment'; import type { ComponentProps } from 'react'; import React, { useState, useMemo, useEffect } from 'react'; +moment.locale('en'); + type DateRangePickerProps = Omit, 'onChange'> & { onChange(range: { start: string; end: string }): void; }; diff --git a/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.js b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.js deleted file mode 100644 index 95d455fb7eb11..0000000000000 --- a/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.js +++ /dev/null @@ -1,14 +0,0 @@ -import moment from 'moment'; - -export const getMomentChartLabelsAndData = () => { - const timingLabels = []; - const initData = []; - const today = moment().startOf('day'); - for (let m = today; m.diff(moment(), 'hours') < 0; m.add(1, 'hours')) { - const hour = m.format('H'); - timingLabels.push(`${moment(hour, ['H']).format('hA')}-${moment((parseInt(hour) + 1) % 24, ['H']).format('hA')}`); - initData.push(0); - } - - return [timingLabels, initData]; -}; diff --git a/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.spec.ts b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.spec.ts new file mode 100644 index 0000000000000..ec5eb12682336 --- /dev/null +++ b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.spec.ts @@ -0,0 +1,52 @@ +import moment from 'moment-timezone'; + +import { getMomentChartLabelsAndData } from './getMomentChartLabelsAndData'; + +moment.tz.setDefault('UTC'); + +describe.each([ + [ + 'en', + [ + '12AM-1AM', + '1AM-2AM', + '2AM-3AM', + '3AM-4AM', + '4AM-5AM', + '5AM-6AM', + '6AM-7AM', + '7AM-8AM', + '8AM-9AM', + '9AM-10AM', + '10AM-11AM', + '11AM-12PM', + ], + ], + /** @see: https://github.com/RocketChat/Rocket.Chat/issues/30191 */ + [ + 'fa', + [ + '۱۲قبل از ظهر-۱قبل از ظهر', + '۱قبل از ظهر-۲قبل از ظهر', + '۲قبل از ظهر-۳قبل از ظهر', + '۳قبل از ظهر-۴قبل از ظهر', + '۴قبل از ظهر-۵قبل از ظهر', + '۵قبل از ظهر-۶قبل از ظهر', + '۶قبل از ظهر-۷قبل از ظهر', + '۷قبل از ظهر-۸قبل از ظهر', + '۸قبل از ظهر-۹قبل از ظهر', + '۹قبل از ظهر-۱۰قبل از ظهر', + '۱۰قبل از ظهر-۱۱قبل از ظهر', + '۱۱قبل از ظهر-۱۲بعد از ظهر', + ], + ], +])(`%p language`, (language, expectedTimingLabels) => { + beforeEach(() => { + moment.locale(language); + }); + + it('should create timing labels from midnight to noon', () => { + const [timingLabels] = getMomentChartLabelsAndData(12 * 60 * 60 * 1000); + expect(timingLabels).toStrictEqual(expectedTimingLabels); + }); +}); diff --git a/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.ts b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.ts new file mode 100644 index 0000000000000..7bf2f7a6553bd --- /dev/null +++ b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentChartLabelsAndData.ts @@ -0,0 +1,14 @@ +import moment from 'moment'; + +export const getMomentChartLabelsAndData = (timestamp = Date.now()) => { + const timingLabels = []; + const initData = []; + const today = moment(timestamp).startOf('day'); + for (let m = today; m.diff(moment(timestamp), 'hours') < 0; m.add(1, 'hours')) { + const n = moment(m).add(1, 'hours'); + timingLabels.push(`${m.format('hA')}-${n.format('hA')}`); + initData.push(0); + } + + return [timingLabels, initData]; +}; diff --git a/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.js b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.js deleted file mode 100644 index 38b942f7b5b02..0000000000000 --- a/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.js +++ /dev/null @@ -1,7 +0,0 @@ -import moment from 'moment'; - -export const getMomentCurrentLabel = () => { - const hour = moment(new Date()).format('H'); - - return `${moment(hour, ['H']).format('hA')}-${moment((parseInt(hour) + 1) % 24, ['H']).format('hA')}`; -}; diff --git a/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.spec.ts b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.spec.ts new file mode 100644 index 0000000000000..d0d98c1c39d92 --- /dev/null +++ b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.spec.ts @@ -0,0 +1,20 @@ +import moment from 'moment-timezone'; + +import { getMomentCurrentLabel } from './getMomentCurrentLabel'; + +moment.tz.setDefault('UTC'); + +describe.each([ + ['en', '12PM-1PM'], + /** @see: https://github.com/RocketChat/Rocket.Chat/issues/30191 */ + ['fa', '۱۲بعد از ظهر-۱بعد از ظهر'], +])(`%p language`, (language, expectedLabel) => { + beforeEach(() => { + moment.locale(language); + }); + + it('should create timing labels from midnight to noon', () => { + const label = getMomentCurrentLabel(12 * 60 * 60 * 1000); + expect(label).toStrictEqual(expectedLabel); + }); +}); diff --git a/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.ts b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.ts new file mode 100644 index 0000000000000..17085a91b0d7c --- /dev/null +++ b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/getMomentCurrentLabel.ts @@ -0,0 +1,8 @@ +import moment from 'moment'; + +export const getMomentCurrentLabel = (timestamp = Date.now()) => { + const m = moment(timestamp); + const n = moment(m).add(1, 'hours'); + + return `${m.format('hA')}-${n.format('hA')}`; +}; diff --git a/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/useUpdateChartData.js b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/useUpdateChartData.js deleted file mode 100644 index f3af5a42624ac..0000000000000 --- a/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/useUpdateChartData.js +++ /dev/null @@ -1,11 +0,0 @@ -import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; - -import { updateChart } from '../../../../../app/livechat/client/lib/chartHandler'; - -export const useUpdateChartData = ({ context, canvas, init, t }) => - useMutableCallback(async (label, data) => { - if (!context.current) { - context.current = await init(canvas.current, context.current, t); - } - await updateChart(context.current, label, data); - }); diff --git a/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/useUpdateChartData.ts b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/useUpdateChartData.ts new file mode 100644 index 0000000000000..805d828a9893f --- /dev/null +++ b/apps/meteor/client/views/omnichannel/realTimeMonitoring/charts/useUpdateChartData.ts @@ -0,0 +1,26 @@ +import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; +import { type Chart } from 'chart.js'; +import { type TFunction } from 'i18next'; +import { type RefObject } from 'react'; + +import { updateChart } from '../../../../../app/livechat/client/lib/chartHandler'; + +type UseUpdateChartDataOptions = { + context: RefObject; + canvas: RefObject; + init: (canvas: HTMLCanvasElement, context: undefined, t: TFunction) => Promise; + t: TFunction; +}; + +export const useUpdateChartData = ({ context: contextRef, canvas: canvasRef, init, t }: UseUpdateChartDataOptions) => + useMutableCallback(async (label: string, data: { [x: string]: number }) => { + const canvas = canvasRef.current; + + if (!canvas) { + return; + } + + const context = contextRef.current ?? (await init(canvas, undefined, t)); + + await updateChart(context, label, data); + });