Skip to content

Commit 4ad4091

Browse files
committed
Merge branch 'main' into add-update-chevron
2 parents ddf6870 + 901ef65 commit 4ad4091

File tree

151 files changed

+2059
-1593
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

151 files changed

+2059
-1593
lines changed

packages/twenty-chrome-extension/src/generated/graphql.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1640,7 +1640,7 @@ export type Captcha = {
16401640
};
16411641

16421642
export enum CaptchaDriverType {
1643-
GoogleRecatpcha = 'GoogleRecatpcha',
1643+
GoogleRecaptcha = 'GoogleRecaptcha',
16441644
Turnstile = 'Turnstile'
16451645
}
16461646

packages/twenty-front/jest.config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const jestConfig: JestConfigWithTsJest = {
2525
coverageThreshold: {
2626
global: {
2727
statements: 65,
28-
lines: 65,
28+
lines: 64,
2929
functions: 55,
3030
},
3131
},

packages/twenty-front/src/generated-metadata/graphql.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export type Captcha = {
136136
};
137137

138138
export enum CaptchaDriverType {
139-
GoogleRecatpcha = 'GoogleRecatpcha',
139+
GoogleRecaptcha = 'GoogleRecaptcha',
140140
Turnstile = 'Turnstile'
141141
}
142142

packages/twenty-front/src/generated/graphql.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export type Captcha = {
130130
};
131131

132132
export enum CaptchaDriverType {
133-
GoogleRecatpcha = 'GoogleRecatpcha',
133+
GoogleRecaptcha = 'GoogleRecaptcha',
134134
Turnstile = 'Turnstile'
135135
}
136136

packages/twenty-front/src/modules/captcha/components/CaptchaProviderScriptLoaderEffect.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export const CaptchaProviderScriptLoaderEffect = () => {
3232
scriptElement = document.createElement('script');
3333
scriptElement.src = scriptUrl;
3434
scriptElement.onload = () => {
35-
if (captchaProvider.provider === CaptchaDriverType.GoogleRecatpcha) {
35+
if (captchaProvider.provider === CaptchaDriverType.GoogleRecaptcha) {
3636
window.grecaptcha?.ready(() => {
3737
setIsCaptchaScriptLoaded(true);
3838
});

packages/twenty-front/src/modules/captcha/hooks/useRequestFreshCaptchaToken.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export const useRequestFreshCaptchaToken = () => {
3535
let captchaWidget: any;
3636

3737
switch (captchaProvider.provider) {
38-
case CaptchaDriverType.GoogleRecatpcha:
38+
case CaptchaDriverType.GoogleRecaptcha:
3939
window.grecaptcha
4040
.execute(captchaProvider.siteKey, {
4141
action: 'submit',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { expect } from '@storybook/test';
2+
3+
import { CaptchaDriverType } from '~/generated/graphql';
4+
5+
import { getCaptchaUrlByProvider } from '../getCaptchaUrlByProvider';
6+
7+
describe('getCaptchaUrlByProvider', () => {
8+
it('handles GoogleRecaptcha', async () => {
9+
const captchaUrl = getCaptchaUrlByProvider(
10+
CaptchaDriverType.GoogleRecaptcha,
11+
'siteKey',
12+
);
13+
14+
expect(captchaUrl).toEqual(
15+
'https://www.google.com/recaptcha/api.js?render=siteKey',
16+
);
17+
18+
expect(() =>
19+
getCaptchaUrlByProvider(CaptchaDriverType.GoogleRecaptcha, ''),
20+
).toThrow(
21+
'SiteKey must be provided while generating url for GoogleRecaptcha provider',
22+
);
23+
});
24+
25+
it('handles Turnstile', async () => {
26+
const captchaUrl = getCaptchaUrlByProvider(CaptchaDriverType.Turnstile, '');
27+
28+
expect(captchaUrl).toEqual(
29+
'https://challenges.cloudflare.com/turnstile/v0/api.js',
30+
);
31+
});
32+
33+
it('handles unknown provider', async () => {
34+
expect(() =>
35+
getCaptchaUrlByProvider('Unknown' as CaptchaDriverType, ''),
36+
).toThrow('Unknown captcha provider');
37+
});
38+
});
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
1-
import { CaptchaDriverType } from '~/generated-metadata/graphql';
1+
import { isNonEmptyString } from '@sniptt/guards';
22

3-
export const getCaptchaUrlByProvider = (name: string, siteKey: string) => {
4-
if (!name) {
5-
return '';
6-
}
3+
import { CaptchaDriverType } from '~/generated-metadata/graphql';
74

5+
export const getCaptchaUrlByProvider = (
6+
name: CaptchaDriverType,
7+
siteKey: string,
8+
) => {
89
switch (name) {
9-
case CaptchaDriverType.GoogleRecatpcha:
10+
case CaptchaDriverType.GoogleRecaptcha:
11+
if (!isNonEmptyString(siteKey)) {
12+
throw new Error(
13+
'SiteKey must be provided while generating url for GoogleRecaptcha provider',
14+
);
15+
}
1016
return `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
1117
case CaptchaDriverType.Turnstile:
1218
return 'https://challenges.cloudflare.com/turnstile/v0/api.js';
1319
default:
14-
return '';
20+
throw new Error('Unknown captcha provider');
1521
}
1622
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { getForeignDataWrapperType } from '../getForeignDataWrapperType';
2+
3+
describe('getForeignDataWrapperType', () => {
4+
it('should handle postgres', () => {
5+
expect(getForeignDataWrapperType('postgresql')).toBe('postgres_fdw');
6+
});
7+
8+
it('should handle stripe', () => {
9+
expect(getForeignDataWrapperType('stripe')).toBe('stripe_fdw');
10+
});
11+
12+
it('should return null for unknown', () => {
13+
expect(getForeignDataWrapperType('unknown')).toBeNull();
14+
});
15+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { AppPath } from '@/types/AppPath';
2+
3+
import indexAppPath from '../indexAppPath';
4+
5+
describe('getIndexAppPath', () => {
6+
it('returns the index app path', () => {
7+
const { getIndexAppPath } = indexAppPath;
8+
expect(getIndexAppPath()).toEqual(AppPath.Index);
9+
});
10+
});

packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ export const RecordBoardCard = () => {
262262
recoilScopeId: recordId + fieldDefinition.fieldMetadataId,
263263
isLabelIdentifier: false,
264264
fieldDefinition: {
265-
disableTooltip: true,
265+
disableTooltip: false,
266266
fieldMetadataId: fieldDefinition.fieldMetadataId,
267267
label: fieldDefinition.label,
268268
iconName: fieldDefinition.iconName,

packages/twenty-front/src/modules/object-record/record-field/types/CurrencyCode.ts

+2
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ export enum CurrencyCode {
1515
QAR = 'QAR',
1616
AED = 'AED',
1717
KRW = 'KRW',
18+
BRL = 'BRL',
19+
AUD = 'AUD',
1820
}

packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useRecoilValue, useSetRecoilState } from 'recoil';
1+
import { useRecoilValue } from 'recoil';
22

33
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
44
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
@@ -41,8 +41,6 @@ export const useLoadRecordIndexTable = (objectNameSingular: string) => {
4141

4242
const { setRecordTableData, setIsRecordTableInitialLoading } =
4343
useRecordTable();
44-
const { tableLastRowVisibleState } = useRecordTableStates();
45-
const setLastRowVisible = useSetRecoilState(tableLastRowVisibleState);
4644
const currentWorkspace = useRecoilValue(currentWorkspaceState);
4745
const params = useFindManyParams(objectNameSingular);
4846

@@ -58,7 +56,6 @@ export const useLoadRecordIndexTable = (objectNameSingular: string) => {
5856
...params,
5957
recordGqlFields,
6058
onCompleted: () => {
61-
setLastRowVisible(false);
6259
setIsRecordTableInitialLoading(false);
6360
},
6461
onError: () => {

packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellContainer.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { ReactElement, useContext } from 'react';
22
import { useTheme } from '@emotion/react';
33
import styled from '@emotion/styled';
4-
import { AppTooltip, IconComponent } from 'twenty-ui';
4+
import { AppTooltip, IconComponent, TooltipDelay } from 'twenty-ui';
55

66
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
77
import { useFieldFocus } from '@/object-record/record-field/hooks/useFieldFocus';
@@ -136,6 +136,7 @@ export const RecordInlineCellContainer = ({
136136
noArrow
137137
place="bottom"
138138
positionStrategy="fixed"
139+
delay={TooltipDelay.shortDelay}
139140
/>
140141
)}
141142
</StyledLabelAndIconContainer>

packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ const StyledTable = styled.table<{
5353
color: ${({ theme }) => theme.font.color.primary};
5454
border-right: 1px solid ${({ theme }) => theme.border.color.light};
5555
56+
padding: 0;
57+
5658
text-align: left;
5759
5860
:last-child {

packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBodyEffect.tsx

+15-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useEffect } from 'react';
2-
import { useRecoilState, useRecoilValue } from 'recoil';
2+
import { useRecoilValue } from 'recoil';
3+
import { useDebouncedCallback } from 'use-debounce';
34

45
import { useLoadRecordIndexTable } from '@/object-record/record-index/hooks/useLoadRecordIndexTable';
56
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
@@ -18,20 +19,18 @@ export const RecordTableBodyEffect = ({
1819
records,
1920
totalCount,
2021
setRecordTableData,
21-
queryStateIdentifier,
2222
loading,
23+
queryStateIdentifier,
2324
} = useLoadRecordIndexTable(objectNameSingular);
2425

25-
const { tableLastRowVisibleState } = useRecordTableStates();
26-
27-
const [tableLastRowVisible, setTableLastRowVisible] = useRecoilState(
28-
tableLastRowVisibleState,
29-
);
30-
3126
const isFetchingMoreObjects = useRecoilValue(
3227
isFetchingMoreRecordsFamilyState(queryStateIdentifier),
3328
);
3429

30+
const { tableLastRowVisibleState } = useRecordTableStates();
31+
32+
const tableLastRowVisible = useRecoilValue(tableLastRowVisibleState);
33+
3534
const rowHeight = 32;
3635
const viewportHeight = records.length * rowHeight;
3736

@@ -43,14 +42,18 @@ export const RecordTableBodyEffect = ({
4342
}
4443
}, [records, totalCount, setRecordTableData, loading]);
4544

45+
const fetchMoreDebouncedIfRequested = useDebouncedCallback(async () => {
46+
// We are debouncing here to give the user some room to scroll if they want to within this throttle window
47+
await fetchMoreObjects();
48+
}, 100);
49+
4650
useEffect(() => {
47-
if (tableLastRowVisible && !isFetchingMoreObjects) {
48-
fetchMoreObjects();
51+
if (!isFetchingMoreObjects && tableLastRowVisible) {
52+
fetchMoreDebouncedIfRequested();
4953
}
5054
}, [
51-
fetchMoreObjects,
55+
fetchMoreDebouncedIfRequested,
5256
isFetchingMoreObjects,
53-
setTableLastRowVisible,
5457
tableLastRowVisible,
5558
]);
5659

packages/twenty-front/src/modules/object-record/record-table/components/RecordTableBodyLoading.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const RecordTableBodyLoading = () => {
2020
isDragging={false}
2121
data-testid={`row-id-${rowIndex}`}
2222
data-selectable-id={`row-id-${rowIndex}`}
23+
key={rowIndex}
2324
>
2425
<StyledTd data-select-disable>
2526
<GripCell isDragging={false} />

packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.module.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@
2727
.cell-base-container-soft-focus {
2828
background: var(--twentycrm-background-transparent-secondary);
2929
border-radius: var(--twentycrm-border-radius-sm);
30-
outline: 1px solid var(--twentycrm-font-color-extra-light);
30+
border: 1px solid var(--twentycrm-font-color-extra-light);
3131
}
3232

packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.module.css

+3-6
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,12 @@
33
display: flex;
44
height: 100%;
55
overflow: hidden;
6-
padding-left: 8px;
7-
padding-right: 4px;
6+
padding-left: 6px;
87
width: 100%;
98
}
109

11-
.cell-display-outer-container-soft-focus {
12-
background: var(--twentycrm-background-transparent-secondary);
13-
border-radius: var(--twentycrm-border-radius-sm);
14-
outline: 1px solid var(--twentycrm-font-color-extra-light);
10+
.cell-display-with-soft-focus {
11+
margin: -1px;
1512
}
1613

1714
.cell-display-inner-container {

packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayContainer.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const RecordTableCellDisplayContainer = ({
2323
onClick={onClick}
2424
className={clsx({
2525
[styles.cellDisplayOuterContainer]: true,
26-
[styles.cellDisplayOuterContainerSoftFocus]: softFocus,
26+
[styles.cellDisplayWithSoftFocus]: softFocus,
2727
})}
2828
ref={scrollRef}
2929
>

packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayMode.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ import { RecordTableCellDisplayContainer } from './RecordTableCellDisplayContain
44

55
export const RecordTableCellDisplayMode = ({
66
children,
7-
}: React.PropsWithChildren<unknown>) => {
7+
softFocus,
8+
}: React.PropsWithChildren<{ softFocus?: boolean }>) => {
89
const isEmpty = useIsFieldEmpty();
910

1011
if (isEmpty) {
1112
return <></>;
1213
}
1314

1415
return (
15-
<RecordTableCellDisplayContainer>
16+
<RecordTableCellDisplayContainer softFocus={softFocus}>
1617
{children}
1718
</RecordTableCellDisplayContainer>
1819
);

packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ export const RecordTableCellSoftFocusMode = ({
159159
<RecordTableCellDisplayContainer
160160
onClick={handleClick}
161161
scrollRef={scrollRef}
162+
softFocus
162163
>
163164
{editModeContentOnly ? editModeContent : nonEditModeContent}
164165
</RecordTableCellDisplayContainer>

packages/twenty-front/src/modules/settings/data-model/constants/SettingsFieldCurrencyCodes.ts

+9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
IconCurrencyKroneCzech,
99
IconCurrencyKroneSwedish,
1010
IconCurrencyPound,
11+
IconCurrencyReal,
1112
IconCurrencyRiyal,
1213
IconCurrencyWon,
1314
IconCurrencyYen,
@@ -84,4 +85,12 @@ export const SETTINGS_FIELD_CURRENCY_CODES: Record<
8485
label: 'South Korean won',
8586
Icon: IconCurrencyWon,
8687
},
88+
BRL: {
89+
label: 'Brazilian real',
90+
Icon: IconCurrencyReal,
91+
},
92+
AUD: {
93+
label: 'Australian dollar',
94+
Icon: IconCurrencyDollar,
95+
},
8796
};

0 commit comments

Comments
 (0)