Skip to content

Commit

Permalink
Merge pull request #2693 from glific/dayjs_migration
Browse files Browse the repository at this point in the history
momentjs/date-fns to dayjs
  • Loading branch information
mdshamoon authored Jan 13, 2024
2 parents b4d8668 + 4c48cda commit b403eeb
Show file tree
Hide file tree
Showing 37 changed files with 222 additions and 171 deletions.
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@appsignal/plugin-path-decorator": "^1.0.16",
"@appsignal/plugin-window-events": "^1.0.20",
"@appsignal/react": "^1.0.23",
"@date-io/date-fns": "^2.17.0",
"@date-io/dayjs": "^2.17.0",
"@draft-js-plugins/editor": "^4.1.4",
"@draft-js-plugins/mention": "^5.2.2",
"@emoji-mart/data": "^1.1.2",
Expand All @@ -31,7 +31,7 @@
"apollo-link-token-refresh": "^0.6.1",
"axios": "^1.6.4",
"buffer": "^6.0.3",
"date-fns": "2.30.0",
"dayjs": "^1.11.10",
"draft-js": "^0.11.7",
"emoji-mart": "^5.5.2",
"formik": "^2.4.5",
Expand All @@ -41,7 +41,6 @@
"i18next-browser-languagedetector": "^7.2.0",
"interweave": "^13.1.0",
"interweave-autolink": "^5.1.1",
"moment": "^2.30.1",
"pino": "^8.17.2",
"pino-logflare": "^0.4.2",
"react": "^18.2.0",
Expand Down
26 changes: 18 additions & 8 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
import moment from 'moment';
import dayjs from 'dayjs';
import * as Yup from 'yup';

export const SIDE_DRAWER_WIDTH = 233;
export const DATE_FORMAT = 'DD/MM/YY';
export const FULL_DATE_FORMAT = 'DD/MM/YYYY';
export const TIME_FORMAT = 'HH:mm';
export const DATE_TIME_FORMAT = 'DD/MM/YYYY, HH:mm:ss';
export const SHORT_DATE_FORMAT = 'DD/MM/YY';
export const LONG_DATE_FORMAT = 'DD/MM/YYYY';
export const ISO_DATE_FORMAT = 'YYYY-MM-DD';
export const ISO_DATE_FORMAT_SHORT = 'YY-MM-DD';
export const MONTH_DATE_FORMAT = 'MM/DD/YYYY';
export const DATE_FORMAT_WITH_MONTH = 'DD MMM YYYY';
export const SHORT_TIME_FORMAT = 'HH:mm';
export const LONG_TIME_FORMAT = 'HH:mm:ss';
export const EXTENDED_TIME_FORMAT = 'THH:mm:ss';
export const STANDARD_DATE_TIME_FORMAT = 'DD/MM/YYYY, HH:mm:ss';
export const SHORT_DATE_TIME_FORMAT = 'DD/MM/YYYY, HH:mm';
export const EXTENDED_DATE_TIME_FORMAT = 'MMMM DD, YYYY, [at] HH:mm:ss';
export const EXTENDED_DATE_TIME_FORMAT_WITH_AMPM = 'DD/MM/YYYY_hh:mmA';
export const DATE_TIME_FORMAT_WITH_AMPM_SHORT = 'DD/MM/YYYY hh:mm a';
export const DATE_TIME_FORMAT_WITH_AMPM_LONG = 'DD MMM YYYY hh:mm a';
export const SIMULATOR_CONTACT = '9876543210';
export const FLOW_STATUS_PUBLISHED = 'published';
export const SIMULATOR_NUMBER_START = '9876543210';
export const GUPSHUP_ENTERPRISE_SHORTCODE = 'gupshup_enterprise';
export const VALID_URL_REGEX =
'https?://(www.)?[-a-zA-Z0-9@:%._+~#=]{2,256}.[a-z]{2,4}([-a-zA-Z0-9@:%_+.~#?&\/=]*)';
'https?://(www.)?[-a-zA-Z0-9@:%._+~#=]{2,256}.[a-z]{2,4}([-a-zA-Z0-9@:%_+.~#?&/=]*)';
// to find variables in message
export const pattern = /[^{}]+(?=})/g;

Expand Down Expand Up @@ -112,8 +123,7 @@ export const setVariables = (
},
});

export const is24HourWindowOver = (time: any) =>
moment.duration(moment(new Date()).diff(moment(time))).asHours() > 24;
export const is24HourWindowOver = (time: any) => dayjs().diff(dayjs(time), 'hours') > 24;

// connection retry attempt configuration
export const CONNECTION_RECONNECT_ATTEMPTS = 5;
Expand Down
3 changes: 2 additions & 1 deletion src/components/UI/Form/Calendar/Calendar.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { backspace } from 'common/test-utils';
import { Calendar } from './Calendar';
import { MONTH_DATE_FORMAT } from 'common/constants';

const setFieldValueMock = vi.fn();
describe('<Calendar />', () => {
Expand Down Expand Up @@ -29,7 +30,7 @@ describe('<Calendar />', () => {
it('test empty date event', async () => {
render(wrapper);
const input = screen.getByRole('textbox');
expect(input).toHaveValue('MM/DD/YYYY');
expect(input).toHaveValue(MONTH_DATE_FORMAT);
});

it('test date change event', async () => {
Expand Down
8 changes: 4 additions & 4 deletions src/components/UI/Form/Calendar/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useState } from 'react';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider, DatePicker } from '@mui/x-date-pickers';
import 'date-fns';
import { getIn } from 'formik';
import styles from './Calendar.module.css';
import { MONTH_DATE_FORMAT } from 'common/constants';

export interface CalendarProps {
variant?: any;
Expand All @@ -17,7 +17,7 @@ export interface CalendarProps {
}

export const Calendar = ({
format = 'MM/dd/yyyy',
format = MONTH_DATE_FORMAT,
field,
disabled = false,
form: { setFieldValue, errors, touched },
Expand All @@ -41,7 +41,7 @@ export const Calendar = ({
};

return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<div className={styles.Calendar} data-testid="date-picker-inline">
<DatePicker
label={placeholder}
Expand Down
19 changes: 12 additions & 7 deletions src/components/UI/Form/DateTimePicker/DateTimePicker.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { render, screen, fireEvent } from '@testing-library/react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';

import { DateTimePicker } from './DateTimePicker';
import dayjs from 'dayjs';
import { userEvent } from '@testing-library/user-event';

describe('<DateTimePicker />', () => {
const onChangeMock = vi.fn();
Expand All @@ -25,11 +27,14 @@ describe('<DateTimePicker />', () => {
it('test date change event', async () => {
render(wrapper);
const input = screen.getByRole('textbox');
fireEvent.change(input, { target: { value: '14/05/2021 10:50 AM' } });
expect(input).toHaveValue('14/05/2021 10:50 AM');
userEvent.type(input, '14/05/2021 09:50 am');

await waitFor(() => {
expect(input).toHaveValue('14/05/2021 09:50 am');
});

expect(setFieldMock).toBeCalled();
expect(onChangeMock).toBeCalled();
expect(setFieldMock).toHaveBeenCalled();
expect(onChangeMock).toHaveBeenCalled();
});

it('test date with errors', async () => {
Expand All @@ -43,7 +48,7 @@ describe('<DateTimePicker />', () => {

it('test date default value', async () => {
const props = getProps();
props.field.value = new Date();
props.field.value = dayjs();
render(<DateTimePicker {...props} />);
const input = screen.getByRole('textbox');
expect(input).toHaveValue();
Expand All @@ -55,6 +60,6 @@ describe('<DateTimePicker />', () => {
render(<DateTimePicker {...props} />);
const input = screen.getByRole('textbox');
fireEvent.change(input, { target: { value: '14/05/2021 10:50 AM' } });
expect(onChangeMock).toBeCalledTimes(1);
expect(onChangeMock).toHaveBeenCalled();
});
});
14 changes: 9 additions & 5 deletions src/components/UI/Form/DateTimePicker/DateTimePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { LocalizationProvider, DateTimePicker as Picker } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import 'date-fns';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import { getIn } from 'formik';

import styles from './DateTimePicker.module.css';
import { DATE_TIME_FORMAT_WITH_AMPM_SHORT } from 'common/constants';
dayjs.extend(utc);

export interface DateTimePickerProps {
variant?: any;
Expand All @@ -17,7 +20,7 @@ export interface DateTimePickerProps {
}

export const DateTimePicker = ({
format = 'dd/MM/yyyy hh:mm a',
format = DATE_TIME_FORMAT_WITH_AMPM_SHORT,
field,
form: { setFieldValue, errors, touched },
placeholder,
Expand All @@ -30,17 +33,18 @@ export const DateTimePicker = ({
const dateValue = field.value ? field.value : null;

const handleDateChange = (date: Date | null | string) => {
const value = date && date.toString() !== 'Invalid Date' ? date : null;
const value = date && date.toString() !== 'Invalid Date' ? dayjs(date) : null;
setFieldValue(field.name, value);
if (onChange) onChange(value);
};

return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<div className={styles.DateTimePicker} data-testid="date-picker-inline">
<Picker
className={styles.Text}
label={placeholder}
timezone="system"
format={format}
value={dateValue}
slotProps={{
Expand Down
2 changes: 1 addition & 1 deletion src/components/UI/Form/TimePicker/TimePicker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('<TimePicker />', () => {
it('test time change event', async () => {
render(wrapper);
const input = screen.getByRole('textbox');
fireEvent.change(input, { target: { value: '09:00 am' } });
fireEvent.change(input, { target: { value: '09:00 AM' } });
expect(cleanText(input.getAttribute('value'))).toBe('09:00 AM');
});

Expand Down
16 changes: 8 additions & 8 deletions src/components/UI/Form/TimePicker/TimePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useState } from 'react';
import 'date-fns';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider, TimePicker as Picker } from '@mui/x-date-pickers';
import moment from 'moment';
import dayjs from 'dayjs';
import { getIn } from 'formik';
import utc from 'dayjs/plugin/utc';

import styles from './TimePicker.module.css';
dayjs.extend(utc);

export interface TimePickerProps {
variant?: any;
Expand All @@ -24,29 +25,28 @@ export const TimePicker = ({
disabled = false,
helperText,
}: TimePickerProps) => {
moment.defaultFormat = 'Thh:mm:ss';
const timeValue = field.value ? moment(field.value, moment.defaultFormat).toDate() : null;
const timeValue = field.value ? field.value : null;
const [open, setOpen] = useState(false);

const errorText = getIn(errors, field.name);
const touchedVal = getIn(touched, field.name);
const hasError = touchedVal && errorText !== undefined;

const handleDateChange = (time: Date | null) => {
const value = time ? moment(time).format('THH:mm:ss') : null;
const value = time ? time : null;
setFieldValue(field.name, value);
};

return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<div className={styles.TimePicker} data-testid="time-picker">
<Picker
className={styles.Picker}
label={placeholder}
open={open}
value={timeValue}
onClose={() => setOpen(false)}
disabled={disabled}
value={timeValue}
onChange={handleDateChange}
slotProps={{
textField: {
Expand Down
12 changes: 6 additions & 6 deletions src/components/UI/Timer/Timer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react';
import moment from 'moment';
import { useTranslation } from 'react-i18next';
import dayjs from 'dayjs';

import ContactOptOutIcon from 'assets/images/icons/ContactOptOut.svg?react';
import Tooltip from 'components/UI/Tooltip/Tooltip';
Expand All @@ -13,7 +13,7 @@ export interface TimerProps {
}

export const Timer = (props: TimerProps) => {
const [currentTime, setCurrentTime] = useState(moment(new Date()));
const [currentTime, setCurrentTime] = useState(dayjs());
const { t } = useTranslation();

const link = (
Expand Down Expand Up @@ -41,7 +41,7 @@ export const Timer = (props: TimerProps) => {
let intervalID: any;
useEffect(() => {
intervalID = setInterval(() => {
setCurrentTime(moment(new Date()));
setCurrentTime(dayjs());
}, 60000);

return () => clearInterval(intervalID);
Expand All @@ -68,9 +68,9 @@ export const Timer = (props: TimerProps) => {

let hours: string | number = 0;
if (time) {
const lastMessageTime = moment(time);
const duration = moment.duration(currentTime.diff(lastMessageTime));
hours = Math.floor(duration.asHours());
const lastMessageTime = dayjs(time);
const duration = currentTime.diff(lastMessageTime, "hour")
hours = Math.floor(duration);
if (hours < 0) hours = 0;
hours = hours > 24 ? 0 : 24 - hours;
}
Expand Down
6 changes: 3 additions & 3 deletions src/components/simulator/Simulator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import VideocamIcon from '@mui/icons-material/Videocam';
import CameraAltIcon from '@mui/icons-material/CameraAlt';
import ClearIcon from '@mui/icons-material/Clear';
import axios from 'axios';
import moment from 'moment';
import dayjs from 'dayjs';
import { v4 as uuidv4 } from 'uuid';
import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';

Expand All @@ -22,7 +22,7 @@ import DefaultWhatsappImage from 'assets/images/whatsappDefault.jpg';
import SimulatorIcon from 'assets/images/icons/Simulator.svg?react';
import ResetIcon from 'assets/images/icons/Reset/Dark.svg?react';
import {
TIME_FORMAT,
SHORT_TIME_FORMAT,
SAMPLE_MEDIA_FOR_SIMULATOR,
LIST,
QUICK_REPLY,
Expand Down Expand Up @@ -104,7 +104,7 @@ const getStyleForDirection = (
const TimeComponent = ({ direction, insertedAt }: any) => (
<>
<span className={direction === 'received' ? styles.TimeSent : styles.TimeReceived}>
{moment(insertedAt).format(TIME_FORMAT)}
{dayjs(insertedAt).format(SHORT_TIME_FORMAT)}
{direction === 'send' && <DoneAllIcon sx={{ fontSize: 10, ml: '2px' }} />}
</span>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { fireEvent, render } from '@testing-library/react';
import moment from 'moment';
import dayjs from 'dayjs';
import { MockedProvider } from '@apollo/client/testing';
import { MemoryRouter } from 'react-router-dom';

import { MARK_AS_READ } from 'graphql/mutations/Chat';
import { DATE_FORMAT } from 'common/constants';
import { SHORT_DATE_FORMAT } from 'common/constants';
import ChatConversation from './ChatConversation';

const mockCallback = vi.fn();
Expand Down Expand Up @@ -64,7 +64,7 @@ test('it should render the message content correctly', () => {

test('it should render the message date correctly', () => {
const { getByTestId } = render(wrapperContainer(defaultProps));
expect(getByTestId('date')).toHaveTextContent(moment(insertedAt).format(DATE_FORMAT));
expect(getByTestId('date')).toHaveTextContent(dayjs(insertedAt).format(SHORT_DATE_FORMAT));
});

test('it should call the callback function on click action', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ListItemButton } from '@mui/material';
import { Link } from 'react-router-dom';
import moment from 'moment';
import dayjs from 'dayjs';
import { useApolloClient, useMutation } from '@apollo/client';

import { COMPACT_MESSAGE_LENGTH, DATE_FORMAT } from 'common/constants';
import { COMPACT_MESSAGE_LENGTH, SHORT_DATE_FORMAT } from 'common/constants';
import { Timer } from 'components/UI/Timer/Timer';
import { MARK_AS_READ, CONTACT_FRAGMENT } from 'graphql/mutations/Chat';
import { SEARCH_OFFSET } from 'graphql/queries/Search';
Expand Down Expand Up @@ -233,7 +233,7 @@ const ChatConversation = ({
{isTextType && highlightSearch ? BoldedText(body, highlightSearch) : displayMSG}
</div>
<div className={styles.MessageDate} data-testid="date">
{moment(lastMessage.insertedAt).format(DATE_FORMAT)}
{dayjs(lastMessage.insertedAt).format(SHORT_DATE_FORMAT)}
</div>
</div>
</ListItemButton>
Expand Down
Loading

0 comments on commit b403eeb

Please sign in to comment.