diff --git a/packages/twenty-front/src/modules/object-record/record-field/components/FormFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/components/FormFieldInput.tsx
new file mode 100644
index 0000000000..993dd28634
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-field/components/FormFieldInput.tsx
@@ -0,0 +1,26 @@
+import VariableTagInput from '@/workflow/search-variables/components/VariableTagInput';
+
+type FormFieldInputProps = {
+ recordFieldInputdId: string;
+ label: string;
+ value: string;
+ onChange: (value: string) => void;
+ isReadOnly?: boolean;
+};
+
+export const FormFieldInput = ({
+ recordFieldInputdId,
+ label,
+ onChange,
+ value,
+}: FormFieldInputProps) => {
+ return (
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx
index 04c6a62be9..cccb23a12a 100644
--- a/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx
+++ b/packages/twenty-front/src/modules/workflow/components/WorkflowDiagramStepNodeBase.tsx
@@ -3,7 +3,13 @@ import { WorkflowDiagramStepNodeData } from '@/workflow/types/WorkflowDiagram';
import { assertUnreachable } from '@/workflow/utils/assertUnreachable';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
-import { IconCode, IconHandMove, IconMail, IconPlaylistAdd } from 'twenty-ui';
+import {
+ IconAddressBook,
+ IconCode,
+ IconHandMove,
+ IconMail,
+ IconPlaylistAdd,
+} from 'twenty-ui';
const StyledStepNodeLabelIconContainer = styled.div`
align-items: center;
@@ -70,6 +76,21 @@ export const WorkflowDiagramStepNodeBase = ({
);
}
+ case 'RECORD_CRUD.CREATE': {
+ return (
+
+
+
+ );
+ }
+ case 'RECORD_CRUD.DELETE':
+ case 'RECORD_CRUD.UPDATE': {
+ return null;
+ }
}
}
}
diff --git a/packages/twenty-front/src/modules/workflow/components/WorkflowEditActionFormRecordCreate.tsx b/packages/twenty-front/src/modules/workflow/components/WorkflowEditActionFormRecordCreate.tsx
new file mode 100644
index 0000000000..647dfe240a
--- /dev/null
+++ b/packages/twenty-front/src/modules/workflow/components/WorkflowEditActionFormRecordCreate.tsx
@@ -0,0 +1,167 @@
+import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
+import { FormFieldInput } from '@/object-record/record-field/components/FormFieldInput';
+import { Select, SelectOption } from '@/ui/input/components/Select';
+import { WorkflowEditGenericFormBase } from '@/workflow/components/WorkflowEditGenericFormBase';
+import { WorkflowRecordCreateAction } from '@/workflow/types/Workflow';
+import { useTheme } from '@emotion/react';
+import { useEffect, useState } from 'react';
+import {
+ HorizontalSeparator,
+ IconAddressBook,
+ isDefined,
+ useIcons,
+} from 'twenty-ui';
+import { useDebouncedCallback } from 'use-debounce';
+import { FieldMetadataType } from '~/generated/graphql';
+
+type WorkflowEditActionFormRecordCreateProps = {
+ action: WorkflowRecordCreateAction;
+ actionOptions:
+ | {
+ readonly: true;
+ }
+ | {
+ readonly?: false;
+ onActionUpdate: (action: WorkflowRecordCreateAction) => void;
+ };
+};
+
+type SendEmailFormData = {
+ objectName: string;
+ [field: string]: unknown;
+};
+
+export const WorkflowEditActionFormRecordCreate = ({
+ action,
+ actionOptions,
+}: WorkflowEditActionFormRecordCreateProps) => {
+ const theme = useTheme();
+ const { getIcon } = useIcons();
+
+ const { activeObjectMetadataItems } = useFilteredObjectMetadataItems();
+
+ const availableMetadata: Array> =
+ activeObjectMetadataItems.map((item) => ({
+ Icon: getIcon(item.icon),
+ label: item.labelPlural,
+ value: item.nameSingular,
+ }));
+
+ const [formData, setFormData] = useState({
+ objectName: action.settings.input.objectName,
+ ...action.settings.input.objectRecord,
+ });
+ const isFormDisabled = actionOptions.readonly;
+
+ const handleFieldChange = (
+ fieldName: keyof SendEmailFormData,
+ updatedValue: string,
+ ) => {
+ const newFormData: SendEmailFormData = {
+ ...formData,
+ [fieldName]: updatedValue,
+ };
+
+ setFormData(newFormData);
+
+ saveAction(newFormData);
+ };
+
+ useEffect(() => {
+ setFormData({
+ objectName: action.settings.input.objectName,
+ ...action.settings.input.objectRecord,
+ });
+ }, [action.settings.input]);
+
+ const selectedObjectMetadataItemNameSingular = formData.objectName;
+
+ const selectedObjectMetadataItem = activeObjectMetadataItems.find(
+ (item) => item.nameSingular === selectedObjectMetadataItemNameSingular,
+ );
+ if (!isDefined(selectedObjectMetadataItem)) {
+ throw new Error('Should have found the metadata item');
+ }
+
+ const editableFields = selectedObjectMetadataItem.fields.filter(
+ (field) =>
+ field.type !== FieldMetadataType.Relation &&
+ !field.isSystem &&
+ field.isActive,
+ );
+
+ const saveAction = useDebouncedCallback(
+ async (formData: SendEmailFormData) => {
+ if (actionOptions.readonly === true) {
+ return;
+ }
+
+ const { objectName: updatedObjectName, ...updatedOtherFields } = formData;
+
+ actionOptions.onActionUpdate({
+ ...action,
+ settings: {
+ ...action.settings,
+ input: {
+ type: 'CREATE',
+ objectName: updatedObjectName,
+ objectRecord: updatedOtherFields,
+ },
+ },
+ });
+ },
+ 1_000,
+ );
+
+ useEffect(() => {
+ return () => {
+ saveAction.flush();
+ };
+ }, [saveAction]);
+
+ return (
+
+ }
+ headerTitle="Record Create"
+ headerType="Action"
+ >
+