Skip to content

Commit

Permalink
Added Linaria for performance optimization (twentyhq#5693)
Browse files Browse the repository at this point in the history
- Added Linaria to have compiled CSS on our optimized field displays
- Refactored mocks for performance stories on fields
- Refactored generateRecordChipData into a global context, computed only
when we fetch object metadata items.
- Refactored ChipFieldDisplay 
- Refactored PhoneFieldDisplay
  • Loading branch information
lucasbordeau authored Jun 12, 2024
1 parent 30d3ebc commit 732e891
Show file tree
Hide file tree
Showing 43 changed files with 2,167 additions and 520 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
"@hello-pangea/dnd": "^16.2.0",
"@hookform/resolvers": "^3.1.1",
"@jsdevtools/rehype-toc": "^3.0.2",
"@linaria/core": "^6.2.0",
"@linaria/react": "^6.2.1",
"@mdx-js/react": "^3.0.0",
"@nestjs/apollo": "^11.0.5",
"@nestjs/axios": "^3.0.1",
Expand Down Expand Up @@ -61,6 +63,7 @@
"@types/lodash.pick": "^4.3.7",
"@types/nodemailer": "^6.4.14",
"@types/passport-microsoft": "^1.0.3",
"@wyw-in-js/vite": "^0.5.3",
"add": "^2.0.6",
"addressparser": "^1.0.1",
"afterframe": "^1.0.2",
Expand Down Expand Up @@ -192,6 +195,7 @@
"devDependencies": {
"@babel/core": "^7.14.5",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.24.6",
"@crxjs/vite-plugin": "^1.0.14",
"@docusaurus/module-type-aliases": "^3.1.0",
"@docusaurus/tsconfig": "3.1.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/twenty-front/nyc.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const globalCoverage = {

const modulesCoverage = {
branches: 25,
statements: 50,
statements: 49,
lines: 50,
functions: 40,
include: ['src/modules/**/*'],
Expand Down
19 changes: 12 additions & 7 deletions packages/twenty-front/src/modules/companies/types/Company.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ export type Company = {
__typename: 'Company';
id: string;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
updatedAt?: string;
deletedAt?: string | null;
name: string;
domainName: string;
address: string;
accountOwnerId: string | null;
linkedinLink: { url: string; label: string };
xLink: { url: string; label: string };
annualRecurringRevenue: { amountMicros: number | null; currencyCode: string };
accountOwnerId?: string | null;
position?: number;
linkedinLink: { __typename?: 'Link'; url: string; label: string };
xLink?: { __typename?: 'Link'; url: string; label: string };
annualRecurringRevenue: {
__typename?: 'Currency';
amountMicros: number | null;
currencyCode: string;
};
employees: number | null;
idealCustomerProfile: boolean;
idealCustomerProfile?: boolean;
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React from 'react';
import React, { useMemo } from 'react';
import { useRecoilValue } from 'recoil';

import { ObjectMetadataItemsLoadEffect } from '@/object-metadata/components/ObjectMetadataItemsLoadEffect';
import { PreComputedChipGeneratorsContext } from '@/object-metadata/context/PreComputedChipGeneratorsContext';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope';
import { getRecordChipGeneratorPerObjectPerField } from '@/object-record/utils/getRecordChipGeneratorPerObjectPerField';
import { UserOrMetadataLoader } from '~/loading/components/UserOrMetadataLoader';

export const ObjectMetadataItemsProvider = ({
Expand All @@ -13,13 +15,23 @@ export const ObjectMetadataItemsProvider = ({

const shouldDisplayChildren = objectMetadataItems.length > 0;

const chipGeneratorPerObjectPerField = useMemo(() => {
return getRecordChipGeneratorPerObjectPerField(objectMetadataItems);
}, [objectMetadataItems]);

return (
<>
<ObjectMetadataItemsLoadEffect />
{shouldDisplayChildren ? (
<RelationPickerScope relationPickerScopeId="relation-picker">
{children}
</RelationPickerScope>
<PreComputedChipGeneratorsContext.Provider
value={{
chipGeneratorPerObjectPerField,
}}
>
<RelationPickerScope relationPickerScopeId="relation-picker">
{children}
</RelationPickerScope>
</PreComputedChipGeneratorsContext.Provider>
) : (
<UserOrMetadataLoader />
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { createContext } from 'react';

import { RecordChipData } from '@/object-record/record-field/types/RecordChipData';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';

export type ChipGeneratorPerObjectPerField = Record<
string,
Record<string, (record: ObjectRecord) => RecordChipData>
>;

export type PreComputedChipGeneratorsContextProps = {
chipGeneratorPerObjectPerField: ChipGeneratorPerObjectPerField;
};

export const PreComputedChipGeneratorsContext =
createContext<PreComputedChipGeneratorsContextProps>(
{} as PreComputedChipGeneratorsContextProps,
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { LinksFieldDisplay } from '@/object-record/record-field/meta-types/displ
import { isFieldBoolean } from '@/object-record/record-field/types/guards/isFieldBoolean';
import { isFieldDisplayedAsPhone } from '@/object-record/record-field/types/guards/isFieldDisplayedAsPhone';
import { isFieldLinks } from '@/object-record/record-field/types/guards/isFieldLinks';
import { isFieldChipDisplay } from '@/object-record/utils/getRecordChipGeneratorPerObjectPerField';

import { FieldContext } from '../contexts/FieldContext';
import { AddressFieldDisplay } from '../meta-types/display/components/AddressFieldDisplay';
Expand Down Expand Up @@ -42,11 +43,7 @@ import { isFieldUuid } from '../types/guards/isFieldUuid';
export const FieldDisplay = () => {
const { fieldDefinition, isLabelIdentifier } = useContext(FieldContext);

const isChipDisplay =
isLabelIdentifier &&
(isFieldText(fieldDefinition) ||
isFieldFullName(fieldDefinition) ||
isFieldNumber(fieldDefinition));
const isChipDisplay = isFieldChipDisplay(fieldDefinition, isLabelIdentifier);

return isChipDisplay ? (
<ChipFieldDisplay />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import { RecordChip } from '@/object-record/components/RecordChip';
import { useChipField } from '@/object-record/record-field/meta-types/hooks/useChipField';
import { EntityChip } from 'twenty-ui';

import { useChipFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useChipFieldDisplay';
import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64';

export const ChipFieldDisplay = () => {
const { objectNameSingular, record } = useChipField();
const { recordValue, generateRecordChipData } = useChipFieldDisplay();

if (!recordValue) {
return null;
}

if (!record) return null;
const recordChipData = generateRecordChipData(recordValue);

return (
<RecordChip objectNameSingular={objectNameSingular || ''} record={record} />
<EntityChip
entityId={recordValue.id}
name={recordChipData.name as any}
avatarType={recordChipData.avatarType}
avatarUrl={getImageAbsoluteURIOrBase64(recordChipData.avatarUrl) ?? ''}
linkToEntity={recordChipData.linkToShowPage}
/>
);
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { usePhoneFieldDisplay } from '@/object-record/record-field/meta-types/hooks/usePhoneFieldDisplay';
import { PhoneDisplay } from '@/ui/field/display/components/PhoneDisplay';

import { usePhoneField } from '../../hooks/usePhoneField';

export const PhoneFieldDisplay = () => {
const { fieldValue } = usePhoneField();
const { fieldValue } = usePhoneFieldDisplay();

return <PhoneDisplay value={fieldValue} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ export const RelationFromManyFieldDisplay = ({
{recordChipsData.map((record) => {
return (
<EntityChip
key={record.id}
entityId={record.id}
key={record.recordId}
entityId={record.recordId}
name={record.name as any}
avatarType={record.avatarType}
avatarUrl={getImageAbsoluteURIOrBase64(record.avatarUrl) || ''}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from 'twenty-ui';

import { ChipFieldDisplay } from '@/object-record/record-field/meta-types/display/components/ChipFieldDisplay';
import { ChipGeneratorsDecorator } from '~/testing/decorators/ChipGeneratorsDecorator';
import { getFieldDecorator } from '~/testing/decorators/getFieldDecorator';
import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
import { getProfilingStory } from '~/testing/profiling/utils/getProfilingStory';

const meta: Meta = {
title: 'UI/Data/Field/Display/ChipFieldDisplay',
decorators: [
MemoryRouterDecorator,
ChipGeneratorsDecorator,
getFieldDecorator('person', 'name'),
ComponentDecorator,
],
component: ChipFieldDisplay,
args: {},
parameters: {
chromatic: { disableSnapshot: true },
},
};

export default meta;

type Story = StoryObj<typeof ChipFieldDisplay>;

export const Default: Story = {};

export const Performance = getProfilingStory({
componentName: 'ChipFieldDisplay',
averageThresholdInMs: 0.2,
numberOfRuns: 20,
numberOfTestsPerRun: 100,
});
Loading

0 comments on commit 732e891

Please sign in to comment.