Refactored all FieldDisplay types for performance optimization (#5768)
This PR is the second part of https://github.com/twentyhq/twenty/pull/5693. It optimizes all remaining field types. The observed improvements are : - x2 loading time improvement on table rows - more consistent render time Here's a summary of measured improvements, what's given here is the average of hundreds of renders with a React Profiler component. (in our Storybook performance stories) | Component | Before (µs) | After (µs) | | ----- | ------------- | --- | | TextFieldDisplay | 127 | 83 | | EmailFieldDisplay | 117 | 83 | | NumberFieldDisplay | 97 | 56 | | DateFieldDisplay | 240 | 52 | | CurrencyFieldDisplay | 236 | 110 | | FullNameFieldDisplay | 131 | 85 | | AddressFieldDisplay | 118 | 81 | | BooleanFieldDisplay | 130 | 100 | | JSONFieldDisplay | 248 | 49 | | LinksFieldDisplay | 1180 | 140 | | LinkFieldDisplay | 140 | 78 | | MultiSelectFieldDisplay | 770 | 130 | | SelectFieldDisplay | 230 | 87 |
This commit is contained in:
@ -2,6 +2,9 @@
|
||||
import { isDate, isNumber, isString } from '@sniptt/guards';
|
||||
import { differenceInCalendarDays, formatDistanceToNow } from 'date-fns';
|
||||
import { DateTime } from 'luxon';
|
||||
import moize from 'moize';
|
||||
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
import { logError } from './logError';
|
||||
|
||||
@ -133,3 +136,75 @@ export const beautifyDateDiff = (
|
||||
if (![0, 1].includes(dateDiff.days)) result = result + 's';
|
||||
return result;
|
||||
};
|
||||
|
||||
const getMonthLabels = () => {
|
||||
const formatter = new Intl.DateTimeFormat(undefined, {
|
||||
month: 'short',
|
||||
timeZone: 'UTC',
|
||||
});
|
||||
|
||||
return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
|
||||
.map((month) => {
|
||||
const monthZeroFilled = month < 10 ? `0${month}` : month;
|
||||
return new Date(`2017-${monthZeroFilled}-01T00:00:00+00:00`);
|
||||
})
|
||||
.map((date) => formatter.format(date));
|
||||
};
|
||||
|
||||
const getMonthLabelsMemoized = moize(getMonthLabels);
|
||||
|
||||
export const formatISOStringToHumanReadableDateTime = (date: string) => {
|
||||
const monthLabels = getMonthLabelsMemoized();
|
||||
|
||||
if (!isDefined(monthLabels)) {
|
||||
return formatToHumanReadableDateTime(date);
|
||||
}
|
||||
|
||||
const year = date.slice(0, 4);
|
||||
const month = date.slice(5, 7);
|
||||
const day = date.slice(8, 10);
|
||||
|
||||
const monthLabel = monthLabels[parseInt(month, 10) - 1];
|
||||
|
||||
const jsDate = new Date(date);
|
||||
|
||||
return `${day} ${monthLabel} ${year} - ${jsDate.getHours()}:${jsDate.getMinutes()}`;
|
||||
};
|
||||
|
||||
export const formatISOStringToHumanReadableDate = (date: string) => {
|
||||
const monthLabels = getMonthLabelsMemoized();
|
||||
|
||||
if (!isDefined(monthLabels)) {
|
||||
return formatToHumanReadableDate(date);
|
||||
}
|
||||
|
||||
const year = date.slice(0, 4);
|
||||
const month = date.slice(5, 7);
|
||||
const day = date.slice(8, 10);
|
||||
|
||||
const monthLabel = monthLabels[parseInt(month, 10) - 1];
|
||||
|
||||
return `${day} ${monthLabel} ${year}`;
|
||||
};
|
||||
|
||||
export const formatToHumanReadableDate = (date: Date | string) => {
|
||||
const parsedJSDate = parseDate(date).toJSDate();
|
||||
|
||||
return new Intl.DateTimeFormat(undefined, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
}).format(parsedJSDate);
|
||||
};
|
||||
|
||||
export const formatToHumanReadableDateTime = (date: Date | string) => {
|
||||
const parsedJSDate = parseDate(date).toJSDate();
|
||||
|
||||
return new Intl.DateTimeFormat(undefined, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
}).format(parsedJSDate);
|
||||
};
|
||||
|
||||
@ -1,27 +1,3 @@
|
||||
import { parseDate } from './date-utils';
|
||||
|
||||
export const formatToHumanReadableDate = (date: Date | string) => {
|
||||
const parsedJSDate = parseDate(date).toJSDate();
|
||||
|
||||
return new Intl.DateTimeFormat(undefined, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
}).format(parsedJSDate);
|
||||
};
|
||||
|
||||
export const formatToHumanReadableDateTime = (date: Date | string) => {
|
||||
const parsedJSDate = parseDate(date).toJSDate();
|
||||
|
||||
return new Intl.DateTimeFormat(undefined, {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
}).format(parsedJSDate);
|
||||
};
|
||||
|
||||
export const sanitizeURL = (link: string | null | undefined) => {
|
||||
return link
|
||||
? link.replace(/(https?:\/\/)|(www\.)/g, '').replace(/\/$/, '')
|
||||
|
||||
Reference in New Issue
Block a user