Skip to content

Commit 62fe1d0

Browse files
authored
1 parent 3cd24d5 commit 62fe1d0

39 files changed

+813
-511
lines changed

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

+10-10
Large diffs are not rendered by default.

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

+60-45
Large diffs are not rendered by default.

packages/twenty-front/src/modules/settings/serverless-functions/components/tabs/SettingsServerlessFunctionCodeEditorTab.tsx

+27-20
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { ServerlessFunctionFormValues } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
21
import { SettingsServerlessFunctionHotkeyScope } from '@/settings/serverless-functions/types/SettingsServerlessFunctionHotKeyScope';
32
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
43
import { SettingsPath } from '@/types/SettingsPath';
54
import { Button } from '@/ui/input/button/components/Button';
6-
import { CodeEditor } from '@/ui/input/code-editor/components/CodeEditor';
5+
import { CodeEditor, File } from '@/ui/input/code-editor/components/CodeEditor';
76
import { CoreEditorHeader } from '@/ui/input/code-editor/components/CodeEditorHeader';
87
import { Section } from '@/ui/layout/section/components/Section';
98
import { TabList } from '@/ui/layout/tab/components/TabList';
@@ -13,13 +12,16 @@ import { useNavigate } from 'react-router-dom';
1312
import { Key } from 'ts-key-enum';
1413
import { H2Title, IconGitCommit, IconPlayerPlay, IconRestore } from 'twenty-ui';
1514
import { useHotkeyScopeOnMount } from '~/hooks/useHotkeyScopeOnMount';
15+
import { SETTINGS_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/settings/serverless-functions/constants/SettingsServerlessFunctionTabListComponentId';
16+
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
17+
import { useRecoilValue } from 'recoil';
1618

1719
const StyledTabList = styled(TabList)`
1820
border-bottom: none;
1921
`;
2022

2123
export const SettingsServerlessFunctionCodeEditorTab = ({
22-
formValues,
24+
files,
2325
handleExecute,
2426
handlePublish,
2527
handleReset,
@@ -28,15 +30,19 @@ export const SettingsServerlessFunctionCodeEditorTab = ({
2830
onChange,
2931
setIsCodeValid,
3032
}: {
31-
formValues: ServerlessFunctionFormValues;
33+
files: File[];
3234
handleExecute: () => void;
3335
handlePublish: () => void;
3436
handleReset: () => void;
3537
resetDisabled: boolean;
3638
publishDisabled: boolean;
37-
onChange: (key: string) => (value: string) => void;
39+
onChange: (filePath: string, value: string) => void;
3840
setIsCodeValid: (isCodeValid: boolean) => void;
3941
}) => {
42+
const { activeTabIdState } = useTabList(
43+
SETTINGS_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID,
44+
);
45+
const activeTabId = useRecoilValue(activeTabIdState);
4046
const TestButton = (
4147
<Button
4248
title="Test"
@@ -68,21 +74,15 @@ export const SettingsServerlessFunctionCodeEditorTab = ({
6874
/>
6975
);
7076

71-
const TAB_LIST_COMPONENT_ID = 'serverless-function-editor';
72-
7377
const HeaderTabList = (
7478
<StyledTabList
75-
tabListId={TAB_LIST_COMPONENT_ID}
76-
tabs={[{ id: 'index.ts', title: 'index.ts' }]}
79+
tabListId={SETTINGS_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID}
80+
tabs={files.map((file) => {
81+
return { id: file.path, title: file.path.split('/').at(-1) || '' };
82+
})}
7783
/>
7884
);
7985

80-
const Header = (
81-
<CoreEditorHeader
82-
leftNodes={[HeaderTabList]}
83-
rightNodes={[ResetButton, PublishButton, TestButton]}
84-
/>
85-
);
8686
const navigate = useNavigate();
8787
useHotkeyScopeOnMount(
8888
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionEditorTab,
@@ -95,18 +95,25 @@ export const SettingsServerlessFunctionCodeEditorTab = ({
9595
},
9696
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionEditorTab,
9797
);
98+
9899
return (
99100
<Section>
100101
<H2Title
101102
title="Code your function"
102103
description="Write your function (in typescript) below"
103104
/>
104-
<CodeEditor
105-
value={formValues.code}
106-
onChange={onChange('code')}
107-
setIsCodeValid={setIsCodeValid}
108-
header={Header}
105+
<CoreEditorHeader
106+
leftNodes={[HeaderTabList]}
107+
rightNodes={[ResetButton, PublishButton, TestButton]}
109108
/>
109+
{activeTabId && (
110+
<CodeEditor
111+
files={files}
112+
currentFilePath={activeTabId}
113+
onChange={(newCodeValue) => onChange(activeTabId, newCodeValue)}
114+
setIsCodeValid={setIsCodeValid}
115+
/>
116+
)}
110117
</Section>
111118
);
112119
};

packages/twenty-front/src/modules/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTestTab.tsx

+46-36
Original file line numberDiff line numberDiff line change
@@ -44,28 +44,6 @@ export const SettingsServerlessFunctionTestTab = ({
4444
settingsServerlessFunctionOutput.error ||
4545
'';
4646

47-
const InputHeader = (
48-
<CoreEditorHeader
49-
title={'Input'}
50-
rightNodes={[
51-
<Button
52-
title="Run Function"
53-
variant="primary"
54-
accent="blue"
55-
size="small"
56-
Icon={IconPlayerPlay}
57-
onClick={handleExecute}
58-
/>,
59-
]}
60-
/>
61-
);
62-
63-
const OutputHeader = (
64-
<CoreEditorHeader
65-
leftNodes={[<SettingsServerlessFunctionsOutputMetadataInfo />]}
66-
rightNodes={[<LightCopyIconButton copyText={result} />]}
67-
/>
68-
);
6947
const navigate = useNavigate();
7048
useHotkeyScopeOnMount(
7149
SettingsServerlessFunctionHotkeyScope.ServerlessFunctionTestTab,
@@ -86,20 +64,52 @@ export const SettingsServerlessFunctionTestTab = ({
8664
description='Insert a JSON input, then press "Run" to test your function.'
8765
/>
8866
<StyledInputsContainer>
89-
<CodeEditor
90-
value={settingsServerlessFunctionInput}
91-
height={200}
92-
onChange={setSettingsServerlessFunctionInput}
93-
language={'json'}
94-
header={InputHeader}
95-
/>
96-
<CodeEditor
97-
value={result}
98-
height={settingsServerlessFunctionCodeEditorOutputParams.height}
99-
language={settingsServerlessFunctionCodeEditorOutputParams.language}
100-
options={{ readOnly: true, domReadOnly: true }}
101-
header={OutputHeader}
102-
/>
67+
<div>
68+
<CoreEditorHeader
69+
title={'Input'}
70+
rightNodes={[
71+
<Button
72+
title="Run Function"
73+
variant="primary"
74+
accent="blue"
75+
size="small"
76+
Icon={IconPlayerPlay}
77+
onClick={handleExecute}
78+
/>,
79+
]}
80+
/>
81+
<CodeEditor
82+
files={[
83+
{
84+
content: settingsServerlessFunctionInput,
85+
language: 'json',
86+
path: 'input.json',
87+
},
88+
]}
89+
currentFilePath={'input.json'}
90+
height={200}
91+
onChange={setSettingsServerlessFunctionInput}
92+
/>
93+
</div>
94+
<div>
95+
<CoreEditorHeader
96+
leftNodes={[<SettingsServerlessFunctionsOutputMetadataInfo />]}
97+
rightNodes={[<LightCopyIconButton copyText={result} />]}
98+
/>
99+
<CodeEditor
100+
files={[
101+
{
102+
content: result,
103+
language:
104+
settingsServerlessFunctionCodeEditorOutputParams.language,
105+
path: 'result.any',
106+
},
107+
]}
108+
currentFilePath={'result.any'}
109+
height={settingsServerlessFunctionCodeEditorOutputParams.height}
110+
options={{ readOnly: true, domReadOnly: true }}
111+
/>
112+
</div>
103113
</StyledInputsContainer>
104114
</Section>
105115
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const SETTINGS_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID =
2+
'settings-serverless-function-editor-tab-list';

packages/twenty-front/src/modules/settings/serverless-functions/graphql/fragments/serverlessFunctionFragment.ts

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export const SERVERLESS_FUNCTION_FRAGMENT = gql`
55
id
66
name
77
description
8-
sourceCodeHash
98
runtime
109
syncStatus
1110
latestVersion

packages/twenty-front/src/modules/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export type ServerlessFunctionNewFormValues = {
99
};
1010

1111
export type ServerlessFunctionFormValues = ServerlessFunctionNewFormValues & {
12-
code: string;
12+
code: { [filePath: string]: string } | undefined;
1313
};
1414

1515
type SetServerlessFunctionFormValues = Dispatch<
@@ -26,7 +26,7 @@ export const useServerlessFunctionUpdateFormState = (
2626
const [formValues, setFormValues] = useState<ServerlessFunctionFormValues>({
2727
name: '',
2828
description: '',
29-
code: '',
29+
code: undefined,
3030
});
3131

3232
const { serverlessFunction } =
@@ -37,7 +37,7 @@ export const useServerlessFunctionUpdateFormState = (
3737
version: 'draft',
3838
onCompleted: (data: FindOneServerlessFunctionSourceCodeQuery) => {
3939
const newState = {
40-
code: data?.getServerlessFunctionSourceCode || '',
40+
code: data?.getServerlessFunctionSourceCode || undefined,
4141
name: serverlessFunction?.name || '',
4242
description: serverlessFunction?.description || '',
4343
};

0 commit comments

Comments
 (0)