Skip to content

Commit

Permalink
add analytics user context and format day simplified
Browse files Browse the repository at this point in the history
  • Loading branch information
anamarn committed Oct 18, 2024
1 parent a5d3d69 commit e3ef11e
Show file tree
Hide file tree
Showing 17 changed files with 256 additions and 42 deletions.
6 changes: 4 additions & 2 deletions packages/twenty-front/src/modules/auth/hooks/useAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import {
import { isDefined } from '~/utils/isDefined';

import { currentWorkspaceMembersState } from '@/auth/states/currentWorkspaceMembersStates';
import { DateFormat } from '@/localization/constants/DateFormat';
import { TimeFormat } from '@/localization/constants/TimeFormat';
import { dateTimeFormatState } from '@/localization/states/dateTimeFormatState';
import { detectDateFormat } from '@/localization/utils/detectDateFormat';
import { detectTimeFormat } from '@/localization/utils/detectTimeFormat';
Expand Down Expand Up @@ -143,12 +145,12 @@ export const useAuth = () => {
? getDateFormatFromWorkspaceDateFormat(
user.workspaceMember.dateFormat,
)
: detectDateFormat(),
: DateFormat[detectDateFormat()],
timeFormat: isDefined(user.workspaceMember.timeFormat)
? getTimeFormatFromWorkspaceTimeFormat(
user.workspaceMember.timeFormat,
)
: detectTimeFormat(),
: TimeFormat[detectTimeFormat()],
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DateFormat } from '@/localization/constants/DateFormat';

type DateFormatWithoutYear = {
[K in keyof typeof DateFormat]: string;
};
export const DATE_FORMAT_WITHOUT_YEAR: DateFormatWithoutYear = {
SYSTEM: 'SYSTEM',
MONTH_FIRST: 'MMM d',
DAY_FIRST: 'd MMM',
YEAR_FIRST: 'MMM d',
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { DateFormat } from '@/localization/constants/DateFormat';
import { detectDateFormat } from '@/localization/utils/detectDateFormat';

describe('detectDateFormat', () => {
it('should return DateFormat.MONTH_FIRST if the detected format starts with month', () => {
it('should return MONTH_FIRST if the detected format starts with month', () => {
// Mock the Intl.DateTimeFormat to return a specific format
const mockDateTimeFormat = jest.fn().mockReturnValue({
formatToParts: () => [
Expand All @@ -16,10 +15,10 @@ describe('detectDateFormat', () => {

const result = detectDateFormat();

expect(result).toBe(DateFormat.MONTH_FIRST);
expect(result).toBe('MONTH_FIRST');
});

it('should return DateFormat.DAY_FIRST if the detected format starts with day', () => {
it('should return DAY_FIRST if the detected format starts with day', () => {
// Mock the Intl.DateTimeFormat to return a specific format
const mockDateTimeFormat = jest.fn().mockReturnValue({
formatToParts: () => [
Expand All @@ -32,10 +31,10 @@ describe('detectDateFormat', () => {

const result = detectDateFormat();

expect(result).toBe(DateFormat.DAY_FIRST);
expect(result).toBe('DAY_FIRST');
});

it('should return DateFormat.YEAR_FIRST if the detected format starts with year', () => {
it('should return YEAR_FIRST if the detected format starts with year', () => {
// Mock the Intl.DateTimeFormat to return a specific format
const mockDateTimeFormat = jest.fn().mockReturnValue({
formatToParts: () => [
Expand All @@ -48,10 +47,10 @@ describe('detectDateFormat', () => {

const result = detectDateFormat();

expect(result).toBe(DateFormat.YEAR_FIRST);
expect(result).toBe('YEAR_FIRST');
});

it('should return DateFormat.MONTH_FIRST by default if the detected format does not match any specific order', () => {
it('should return MONTH_FIRST by default if the detected format does not match any specific order', () => {
// Mock the Intl.DateTimeFormat to return a specific format
const mockDateTimeFormat = jest.fn().mockReturnValue({
formatToParts: () => [
Expand All @@ -64,6 +63,6 @@ describe('detectDateFormat', () => {

const result = detectDateFormat();

expect(result).toBe(DateFormat.MONTH_FIRST);
expect(result).toBe('MONTH_FIRST');
});
});
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { TimeFormat } from '@/localization/constants/TimeFormat';
import { detectTimeFormat } from '@/localization/utils/detectTimeFormat';

describe('detectTimeFormat', () => {
it('should return TimeFormat.HOUR_12 if the hour format is 12-hour', () => {
it('should return HOUR_12 if the hour format is 12-hour', () => {
// Mock the resolvedOptions method to return hour12 as true
const mockResolvedOptions = jest.fn(() => ({ hour12: true }));
Intl.DateTimeFormat = jest.fn().mockImplementation(() => ({
Expand All @@ -11,11 +10,11 @@ describe('detectTimeFormat', () => {

const result = detectTimeFormat();

expect(result).toBe(TimeFormat.HOUR_12);
expect(result).toBe('HOUR_12');
expect(mockResolvedOptions).toHaveBeenCalled();
});

it('should return TimeFormat.HOUR_24 if the hour format is 24-hour', () => {
it('should return HOUR_24 if the hour format is 24-hour', () => {
// Mock the resolvedOptions method to return hour12 as false
const mockResolvedOptions = jest.fn(() => ({ hour12: false }));
Intl.DateTimeFormat = jest.fn().mockImplementation(() => ({
Expand All @@ -24,7 +23,7 @@ describe('detectTimeFormat', () => {

const result = detectTimeFormat();

expect(result).toBe(TimeFormat.HOUR_24);
expect(result).toBe('HOUR_24');
expect(mockResolvedOptions).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { detectDateFormat } from '@/localization/utils/detectDateFormat';
import { formatDateISOStringToDateTimeSimplified } from '@/localization/utils/formatDateISOStringToDateTimeSimplified';
import { formatInTimeZone } from 'date-fns-tz';
// Mock the imported modules
jest.mock('@/localization/utils/detectDateFormat');
jest.mock('date-fns-tz');

describe('formatDateISOStringToDateTimeSimplified', () => {
const mockDate = new Date('2023-08-15T10:30:00Z');
const mockTimeZone = 'America/New_York';
const mockTimeFormat = 'HH:mm';

beforeEach(() => {
jest.resetAllMocks();
});

it('should format the date correctly when DATE_FORMAT is MONTH_FIRST', () => {
detectDateFormat.mockReturnValue('MONTH_FIRST');
formatInTimeZone.mockReturnValue('Oct 15 · 06:30');

const result = formatDateISOStringToDateTimeSimplified(
mockDate,
mockTimeZone,
mockTimeFormat,
);

expect(detectDateFormat).toHaveBeenCalled();
expect(formatInTimeZone).toHaveBeenCalledWith(
mockDate,
mockTimeZone,
'MMM d · HH:mm',
);
expect(result).toBe('Oct 15 · 06:30');
});

it('should format the date correctly when DATE_FORMAT is DAY_FIRST', () => {
detectDateFormat.mockReturnValue('DAY_FIRST');
formatInTimeZone.mockReturnValue('15 Oct · 06:30');

const result = formatDateISOStringToDateTimeSimplified(
mockDate,
mockTimeZone,
mockTimeFormat,
);

expect(detectDateFormat).toHaveBeenCalled();
expect(formatInTimeZone).toHaveBeenCalledWith(
mockDate,
mockTimeZone,
'd MMM · HH:mm',
);
expect(result).toBe('15 Oct · 06:30');
});

it('should use the provided time format', () => {
detectDateFormat.mockReturnValue('MONTH_FIRST');
formatInTimeZone.mockReturnValue('Oct 15 · 6:30 AM');

const result = formatDateISOStringToDateTimeSimplified(
mockDate,
mockTimeZone,
'h:mm aa',
);

expect(formatInTimeZone).toHaveBeenCalledWith(
mockDate,
mockTimeZone,
'MMM d · h:mm aa',
);
expect(result).toBe('Oct 15 · 6:30 AM');
});

it('should handle different time zones', () => {
detectDateFormat.mockReturnValue('MONTH_FIRST');
formatInTimeZone.mockReturnValue('Oct 16 · 02:30');

const result = formatDateISOStringToDateTimeSimplified(
mockDate,
'Asia/Tokyo',
mockTimeFormat,
);

expect(formatInTimeZone).toHaveBeenCalledWith(
mockDate,
'Asia/Tokyo',
'MMM d · HH:mm',
);
expect(result).toBe('Oct 16 · 02:30');
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DateFormat } from '@/localization/constants/DateFormat';

export const detectDateFormat = (): DateFormat => {
export const detectDateFormat = (): keyof typeof DateFormat => {
const date = new Date();
const formatter = new Intl.DateTimeFormat(navigator.language);
const parts = formatter.formatToParts(date);
Expand All @@ -9,9 +9,9 @@ export const detectDateFormat = (): DateFormat => {
.filter((part) => ['year', 'month', 'day'].includes(part.type))
.map((part) => part.type);

if (partOrder[0] === 'month') return DateFormat.MONTH_FIRST;
if (partOrder[0] === 'day') return DateFormat.DAY_FIRST;
if (partOrder[0] === 'year') return DateFormat.YEAR_FIRST;
if (partOrder[0] === 'month') return 'MONTH_FIRST';
if (partOrder[0] === 'day') return 'DAY_FIRST';
if (partOrder[0] === 'year') return 'YEAR_FIRST';

return DateFormat.MONTH_FIRST;
return 'MONTH_FIRST';
};
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { TimeFormat } from '@/localization/constants/TimeFormat';
import { isDefined } from '~/utils/isDefined';

export const detectTimeFormat = () => {
export const detectTimeFormat = (): keyof typeof TimeFormat => {
const isHour12 = Intl.DateTimeFormat(navigator.language, {
hour: 'numeric',
}).resolvedOptions().hour12;

if (isDefined(isHour12) && isHour12) {
return TimeFormat.HOUR_12;
return 'HOUR_12';
}

return TimeFormat.HOUR_24;
return 'HOUR_24';
};
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { DateFormat } from '@/localization/constants/DateFormat';
import { DATE_FORMAT_WITHOUT_YEAR } from '@/localization/constants/DateFormatWithoutYear';
import { TimeFormat } from '@/localization/constants/TimeFormat';
import { detectDateFormat } from '@/localization/utils/detectDateFormat';
import { formatInTimeZone } from 'date-fns-tz';

export const formatDateISOStringToDateTimeSimplified = (
date: Date,
timeZone: string,
dateFormat: DateFormat,
timeFormat: TimeFormat,
) => {
const simplifiedDateFormat = dateFormat
.replace(/,/g, '')
.split(' ')
.filter((part) => part !== 'yyyy')
.join(' ');
const simplifiedDateFormat = DATE_FORMAT_WITHOUT_YEAR[detectDateFormat()];

return formatInTimeZone(
date,
timeZone,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const getDateFormatFromWorkspaceDateFormat = (
) => {
switch (workspaceDateFormat) {
case WorkspaceMemberDateFormatEnum.System:
return detectDateFormat();
return DateFormat[detectDateFormat()];
case WorkspaceMemberDateFormatEnum.MonthFirst:
return DateFormat.MONTH_FIRST;
case WorkspaceMemberDateFormatEnum.DayFirst:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const getTimeFormatFromWorkspaceTimeFormat = (
) => {
switch (workspaceTimeFormat) {
case WorkspaceMemberTimeFormatEnum.System:
return detectTimeFormat();
return TimeFormat[detectTimeFormat()];
case WorkspaceMemberTimeFormatEnum.Hour_24:
return TimeFormat.HOUR_24;
case WorkspaceMemberTimeFormatEnum.Hour_12:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,11 @@ type SettingsDevelopersWebhookTooltipProps = {
export const SettingsDevelopersWebhookTooltip = ({
point,
}: SettingsDevelopersWebhookTooltipProps): ReactElement => {
const { dateFormat, timeFormat, timeZone } = useContext(UserContext);
const { timeFormat, timeZone } = useContext(UserContext);
const windowInterval = new Date(point.data.x);
const windowIntervalDate = formatDateISOStringToDateTimeSimplified(
windowInterval,
timeZone,
dateFormat,
timeFormat,
);
return (
Expand Down
Loading

0 comments on commit e3ef11e

Please sign in to comment.