+60
@@ -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;
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
+1
-11
@@ -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,
|
||||
};
|
||||
};
|
||||
+12
-12
@@ -33,15 +33,15 @@ const Wrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
|
||||
return (
|
||||
<JotaiProvider store={jotaiStore}>
|
||||
<RecordTableComponentInstance recordTableId={recordTableId}>
|
||||
<RecordTableContextProvider
|
||||
recordTableId={recordTableId}
|
||||
viewBarId="viewBarId"
|
||||
objectNameSingular={CoreObjectNameSingular.Person}
|
||||
onRecordIdentifierClick={() => {}}
|
||||
>
|
||||
<RecordComponentInstanceContextsWrapper
|
||||
componentInstanceId={recordTableId}
|
||||
<RecordComponentInstanceContextsWrapper
|
||||
componentInstanceId={recordTableId}
|
||||
>
|
||||
<RecordTableComponentInstance recordTableId={recordTableId}>
|
||||
<RecordTableContextProvider
|
||||
recordTableId={recordTableId}
|
||||
viewBarId="viewBarId"
|
||||
objectNameSingular={CoreObjectNameSingular.Person}
|
||||
onRecordIdentifierClick={() => {}}
|
||||
>
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
@@ -63,9 +63,9 @@ const Wrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
</RecordTableRowDraggableContextProvider>
|
||||
</RecordTableRowContextProvider>
|
||||
</FieldContext.Provider>
|
||||
</RecordComponentInstanceContextsWrapper>
|
||||
</RecordTableContextProvider>
|
||||
</RecordTableComponentInstance>
|
||||
</RecordTableContextProvider>
|
||||
</RecordTableComponentInstance>
|
||||
</RecordComponentInstanceContextsWrapper>
|
||||
</JotaiProvider>
|
||||
);
|
||||
};
|
||||
|
||||
+12
-16
@@ -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 (
|
||||
|
||||
+21
-26
@@ -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<LogicFunctionInputFormData>(
|
||||
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 && (
|
||||
<>
|
||||
<LogicFunctionTestInputInitEffect logicFunctionId={logicFunctionId} />
|
||||
<StyledTabList
|
||||
tabs={tabs}
|
||||
behaveAsLinks={false}
|
||||
|
||||
+9
-9
@@ -1,6 +1,6 @@
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
|
||||
import { useLogicFunctionEditor } from '@/logic-functions/hooks/useLogicFunctionEditor';
|
||||
import { useLogicFunctionForm } from '@/logic-functions/hooks/useLogicFunctionForm';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { SettingsLogicFunctionLabelContainer } from '@/settings/logic-functions/components/SettingsLogicFunctionLabelContainer';
|
||||
import { SettingsLogicFunctionSettingsTab } from '@/settings/logic-functions/components/tabs/SettingsLogicFunctionSettingsTab';
|
||||
@@ -23,6 +23,7 @@ import { useFindOneApplicationQuery } from '~/generated-metadata/graphql';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { SettingsLogicFunctionCodeEditorTab } from '@/settings/logic-functions/components/tabs/SettingsLogicFunctionCodeEditorTab';
|
||||
import { useExecuteLogicFunction } from '@/logic-functions/hooks/useExecuteLogicFunction';
|
||||
|
||||
const LOGIC_FUNCTION_DETAIL_ID = 'logic-function-detail';
|
||||
|
||||
@@ -51,14 +52,13 @@ export const SettingsLogicFunctionDetail = () => {
|
||||
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');
|
||||
|
||||
Reference in New Issue
Block a user