diff --git a/packages/twenty-front/src/modules/logic-functions/components/LogicFunctionTestInputInitEffect.tsx b/packages/twenty-front/src/modules/logic-functions/components/LogicFunctionTestInputInitEffect.tsx
new file mode 100644
index 0000000000..8f36c4eade
--- /dev/null
+++ b/packages/twenty-front/src/modules/logic-functions/components/LogicFunctionTestInputInitEffect.tsx
@@ -0,0 +1,60 @@
+import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
+import { useSetAtomFamilyState } from '@/ui/utilities/state/jotai/hooks/useSetAtomFamilyState';
+import { logicFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/logicFunctionTestDataFamilyState';
+import { useEffect } from 'react';
+import { type InputJsonSchema } from 'twenty-shared/logic-function';
+import { isDefined } from 'twenty-shared/utils';
+import { getFunctionInputFromInputSchema } from 'twenty-shared/workflow';
+import { useLogicFunctionForm } from '@/logic-functions/hooks/useLogicFunctionForm';
+
+export const LogicFunctionTestInputInitEffect = ({
+ logicFunctionId,
+}: {
+ logicFunctionId: string;
+}) => {
+ const { logicFunction } = useLogicFunctionForm({ logicFunctionId });
+
+ const toolInputSchema = logicFunction?.toolInputSchema;
+
+ const logicFunctionTestData = useAtomFamilyStateValue(
+ logicFunctionTestDataFamilyState,
+ logicFunctionId,
+ );
+
+ const setLogicFunctionTestData = useSetAtomFamilyState(
+ logicFunctionTestDataFamilyState,
+ logicFunctionId,
+ );
+
+ useEffect(() => {
+ if (!logicFunctionTestData.shouldInitInput) {
+ return;
+ }
+
+ if (!isDefined(toolInputSchema)) {
+ return;
+ }
+
+ const schemaArray: InputJsonSchema[] = Array.isArray(toolInputSchema)
+ ? toolInputSchema
+ : [toolInputSchema];
+
+ const defaultInput = getFunctionInputFromInputSchema(schemaArray)[0];
+
+ if (!isDefined(defaultInput)) {
+ return;
+ }
+
+ setLogicFunctionTestData((prev) => ({
+ ...prev,
+ input: defaultInput as { [field: string]: any },
+ shouldInitInput: false,
+ }));
+ }, [
+ toolInputSchema,
+ logicFunctionTestData.shouldInitInput,
+ setLogicFunctionTestData,
+ ]);
+
+ return null;
+};
diff --git a/packages/twenty-front/src/modules/logic-functions/hooks/useExecuteLogicFunction.ts b/packages/twenty-front/src/modules/logic-functions/hooks/useExecuteLogicFunction.ts
index 2771998589..e842dbc762 100644
--- a/packages/twenty-front/src/modules/logic-functions/hooks/useExecuteLogicFunction.ts
+++ b/packages/twenty-front/src/modules/logic-functions/hooks/useExecuteLogicFunction.ts
@@ -42,11 +42,19 @@ export const useExecuteLogicFunction = ({
logicFunctionTestDataFamilyState,
logicFunctionId,
);
+
const setLogicFunctionTestData = useSetAtomFamilyState(
logicFunctionTestDataFamilyState,
logicFunctionId,
);
+ const updateLogicFunctionInput = (input: object) => {
+ setLogicFunctionTestData((prev) => ({
+ ...prev,
+ input,
+ }));
+ };
+
const executeLogicFunction = async () => {
if (isExecuting) {
return;
@@ -94,5 +102,10 @@ export const useExecuteLogicFunction = ({
}
};
- return { executeLogicFunction, isExecuting };
+ return {
+ executeLogicFunction,
+ updateLogicFunctionInput,
+ logicFunctionTestData,
+ isExecuting,
+ };
};
diff --git a/packages/twenty-front/src/modules/logic-functions/hooks/useLogicFunctionEditor.ts b/packages/twenty-front/src/modules/logic-functions/hooks/useLogicFunctionForm.ts
similarity index 82%
rename from packages/twenty-front/src/modules/logic-functions/hooks/useLogicFunctionEditor.ts
rename to packages/twenty-front/src/modules/logic-functions/hooks/useLogicFunctionForm.ts
index dcd2b55dbd..ffdebda8be 100644
--- a/packages/twenty-front/src/modules/logic-functions/hooks/useLogicFunctionEditor.ts
+++ b/packages/twenty-front/src/modules/logic-functions/hooks/useLogicFunctionForm.ts
@@ -1,4 +1,3 @@
-import { useExecuteLogicFunction } from '@/logic-functions/hooks/useExecuteLogicFunction';
import {
type LogicFunctionFormValues,
useLogicFunctionUpdateFormState,
@@ -10,23 +9,16 @@ import {
} from 'twenty-shared/logic-function';
import { useDebouncedCallback } from 'use-debounce';
-export const useLogicFunctionEditor = ({
+export const useLogicFunctionForm = ({
logicFunctionId,
- executeCallback,
}: {
logicFunctionId: string;
- executeCallback?: (result: object) => void;
}) => {
const { updateLogicFunction } = usePersistLogicFunction();
const { formValues, setFormValues, logicFunction, loading } =
useLogicFunctionUpdateFormState({ logicFunctionId });
- const { executeLogicFunction, isExecuting } = useExecuteLogicFunction({
- logicFunctionId,
- callback: executeCallback,
- });
-
const handleSave = useDebouncedCallback(async () => {
await updateLogicFunction({
input: {
@@ -74,7 +66,5 @@ export const useLogicFunctionEditor = ({
loading,
handleSave,
onChange,
- executeLogicFunction,
- isExecuting,
};
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellNoGroup.test.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellNoGroup.test.tsx
index cdfe689095..386e882953 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellNoGroup.test.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/internal/__tests__/useCloseRecordTableCellNoGroup.test.tsx
@@ -33,15 +33,15 @@ const Wrapper = ({ children }: { children: React.ReactNode }) => {
return (
-
- {}}
- >
-
+
+ {}}
>
{
-
-
-
+
+
+
);
};
diff --git a/packages/twenty-front/src/modules/settings/logic-functions/components/tabs/SettingsLogicFunctionTestTab.tsx b/packages/twenty-front/src/modules/settings/logic-functions/components/tabs/SettingsLogicFunctionTestTab.tsx
index adbbfd1a7f..b15c15118b 100644
--- a/packages/twenty-front/src/modules/settings/logic-functions/components/tabs/SettingsLogicFunctionTestTab.tsx
+++ b/packages/twenty-front/src/modules/settings/logic-functions/components/tabs/SettingsLogicFunctionTestTab.tsx
@@ -1,14 +1,12 @@
import { LogicFunctionExecutionResult } from '@/logic-functions/components/LogicFunctionExecutionResult';
import { LogicFunctionLogs } from '@/logic-functions/components/LogicFunctionLogs';
-import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
-import { useSetAtomFamilyState } from '@/ui/utilities/state/jotai/hooks/useSetAtomFamilyState';
-import { logicFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/logicFunctionTestDataFamilyState';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { H2Title, IconPlayerPlay } from 'twenty-ui/display';
import { Button, CodeEditor, CoreEditorHeader } from 'twenty-ui/input';
import { Section } from 'twenty-ui/layout';
import { themeCssVariables } from 'twenty-ui/theme-constants';
+import { useExecuteLogicFunction } from '@/logic-functions/hooks/useExecuteLogicFunction';
const StyledInputsContainer = styled.div`
display: flex;
@@ -31,20 +29,18 @@ export const SettingsLogicFunctionTestTab = ({
isTesting?: boolean;
}) => {
const { t } = useLingui();
- const logicFunctionTestData = useAtomFamilyStateValue(
- logicFunctionTestDataFamilyState,
- logicFunctionId,
- );
- const setLogicFunctionTestData = useSetAtomFamilyState(
- logicFunctionTestDataFamilyState,
- logicFunctionId,
- );
- const onChange = (newInput: string) => {
- setLogicFunctionTestData((prev) => ({
- ...prev,
- input: JSON.parse(newInput),
- }));
+ const { updateLogicFunctionInput, logicFunctionTestData } =
+ useExecuteLogicFunction({
+ logicFunctionId,
+ });
+
+ const onChange = (value: string) => {
+ try {
+ updateLogicFunctionInput(JSON.parse(value));
+ } catch {
+ // ignore invalid JSON while user is still typing
+ }
};
return (
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCode.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCode.tsx
index a5983ff26d..7cdc5f4f29 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCode.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCode.tsx
@@ -1,5 +1,5 @@
import { useGetAvailablePackages } from '@/logic-functions/hooks/useGetAvailablePackages';
-import { useLogicFunctionEditor } from '@/logic-functions/hooks/useLogicFunctionEditor';
+import { useLogicFunctionForm } from '@/logic-functions/hooks/useLogicFunctionForm';
import { useFullScreenModal } from '@/ui/layout/fullscreen/hooks/useFullScreenModal';
import { type BreadcrumbProps } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
@@ -22,9 +22,6 @@ import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowS
import { WorkflowCodeEditor } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowCodeEditor';
import { WorkflowEditActionCodeFields } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCodeFields';
import { WORKFLOW_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/workflow-actions/code-action/constants/WorkflowLogicFunctionTabListComponentId';
-import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
-import { useSetAtomFamilyState } from '@/ui/utilities/state/jotai/hooks/useSetAtomFamilyState';
-import { logicFunctionTestDataFamilyState } from '@/workflow/workflow-steps/workflow-actions/code-action/states/logicFunctionTestDataFamilyState';
import { WorkflowLogicFunctionTabId } from '@/workflow/workflow-steps/workflow-actions/code-action/types/WorkflowLogicFunctionTabId';
import { getWrongExportedFunctionMarkers } from '@/workflow/workflow-steps/workflow-actions/code-action/utils/getWrongExportedFunctionMarkers';
import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components/WorkflowVariablePicker';
@@ -49,6 +46,8 @@ import { useIsMobile } from 'twenty-ui/utilities';
import { useDebouncedCallback } from 'use-debounce';
import { getFunctionInputFromInputSchema } from 'twenty-shared/workflow';
import { themeCssVariables } from 'twenty-ui/theme-constants';
+import { LogicFunctionTestInputInitEffect } from '@/logic-functions/components/LogicFunctionTestInputInitEffect';
+import { useExecuteLogicFunction } from '@/logic-functions/hooks/useExecuteLogicFunction';
const StyledCodeEditorContainer = styled.div`
display: flex;
@@ -114,25 +113,24 @@ export const WorkflowEditActionCode = ({
});
};
- const { formValues, loading, executeLogicFunction, onChange, isExecuting } =
- useLogicFunctionEditor({
- logicFunctionId,
- executeCallback: updateOutputSchemaFromTestResult,
- });
+ const { formValues, loading, onChange } = useLogicFunctionForm({
+ logicFunctionId,
+ });
+
+ const {
+ executeLogicFunction,
+ isExecuting,
+ logicFunctionTestData,
+ updateLogicFunctionInput,
+ } = useExecuteLogicFunction({
+ logicFunctionId,
+ callback: updateOutputSchemaFromTestResult,
+ });
const { availablePackages } = useGetAvailablePackages({
id: logicFunctionId,
});
- const logicFunctionTestData = useAtomFamilyStateValue(
- logicFunctionTestDataFamilyState,
- logicFunctionId,
- );
- const setLogicFunctionTestData = useSetAtomFamilyState(
- logicFunctionTestDataFamilyState,
- logicFunctionId,
- );
-
const [functionInput, setFunctionInput] =
useState(
action.settings.input.logicFunctionInput,
@@ -158,6 +156,7 @@ export const WorkflowEditActionCode = ({
newInput: newFunctionInput,
oldInput: action.settings.input.logicFunctionInput,
});
+
const newMergedTestInput = mergeDefaultFunctionInputAndFunctionInput({
newInput: newFunctionInput,
oldInput: logicFunctionTestData.input,
@@ -165,10 +164,7 @@ export const WorkflowEditActionCode = ({
setFunctionInput(newMergedInput);
- setLogicFunctionTestData((prev) => ({
- ...prev,
- input: newMergedTestInput,
- }));
+ updateLogicFunctionInput(newMergedTestInput);
updateAction({
...action,
@@ -220,10 +216,8 @@ export const WorkflowEditActionCode = ({
path,
value,
);
- setLogicFunctionTestData((prev) => ({
- ...prev,
- input: updatedTestFunctionInput,
- }));
+
+ updateLogicFunctionInput(updatedTestFunctionInput);
};
const handleTestFunction = async () => {
@@ -375,6 +369,7 @@ export const WorkflowEditActionCode = ({
return (
!loading && (
<>
+
{
instanceId,
);
- const {
- formValues,
- logicFunction,
- loading,
- onChange,
- executeLogicFunction,
- isExecuting,
- } = useLogicFunctionEditor({ logicFunctionId });
+ const { formValues, logicFunction, loading, onChange } = useLogicFunctionForm(
+ { logicFunctionId },
+ );
+
+ const { executeLogicFunction, isExecuting } = useExecuteLogicFunction({
+ logicFunctionId,
+ });
const handleTestFunction = async () => {
navigate('#test');