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

momentjs/date-fns to dayjs #2693

Merged
merged 19 commits into from
Jan 13, 2024
Merged
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,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 @@ -30,7 +30,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 @@ -40,7 +40,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
Loading