From 7b0bf7c4b0446ccc21fb6e8fbaea55250b5ed651 Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Wed, 19 Mar 2025 18:44:02 +0100 Subject: [PATCH] Form action field base settings (#11035) - Add settings for text and number fields - Settings are for now the same but I still separated with two components because they will evolve https://github.com/user-attachments/assets/96b7fffd-c3a1-45b9-aeaa-45d63505de3c --- .../components/FormTextFieldInput.tsx | 4 +- .../components/TextVariableEditor.tsx | 5 +- .../validation-schemas/workflowSchema.ts | 7 +- .../components/WorkflowStepDetail.tsx | 2 +- .../components/WorkflowEditActionForm.tsx | 100 +++++++++++-- .../WorkflowEditActionFormFieldSettings.tsx | 140 ++++++++++++++++++ .../WorkflowFormFieldSettingsByType.tsx | 37 +++++ .../WorkflowFormFieldSettingsNumber.tsx | 48 ++++++ .../WorkflowFormFieldSettingsText.tsx | 47 ++++++ .../WorkflowEditActionForm.stories.tsx | 4 +- ...lowEditActionFormFieldSettings.stories.tsx | 90 +++++++++++ .../utils/getDefaultFormFieldSettings.ts | 21 +++ 12 files changed, 481 insertions(+), 24 deletions(-) rename packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/{ => form-action}/components/WorkflowEditActionForm.tsx (71%) create mode 100644 packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionFormFieldSettings.tsx create mode 100644 packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsByType.tsx create mode 100644 packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsNumber.tsx create mode 100644 packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsText.tsx rename packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/{ => form-action}/components/__stories__/WorkflowEditActionForm.stories.tsx (95%) create mode 100644 packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/__stories__/WorkflowEditActionFormFieldSettings.stories.tsx create mode 100644 packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/utils/getDefaultFormFieldSettings.ts diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormTextFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormTextFieldInput.tsx index 7190a6ff8..55d5597b3 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormTextFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormTextFieldInput.tsx @@ -4,12 +4,12 @@ import { FormFieldInputRowContainer } from '@/object-record/record-field/form-ty import { TextVariableEditor } from '@/object-record/record-field/form-types/components/TextVariableEditor'; import { useTextVariableEditor } from '@/object-record/record-field/form-types/hooks/useTextVariableEditor'; import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent'; +import { InputErrorHelper } from '@/ui/input/components/InputErrorHelper'; +import { InputHint } from '@/ui/input/components/InputHint'; import { InputLabel } from '@/ui/input/components/InputLabel'; import { parseEditorContent } from '@/workflow/workflow-variables/utils/parseEditorContent'; import { useId } from 'react'; import { isDefined } from 'twenty-shared'; -import { InputErrorHelper } from '@/ui/input/components/InputErrorHelper'; -import { InputHint } from '@/ui/input/components/InputHint'; type FormTextFieldInputProps = { label?: string; diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/TextVariableEditor.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/TextVariableEditor.tsx index 29df0894f..191650c10 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/TextVariableEditor.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/TextVariableEditor.tsx @@ -1,7 +1,10 @@ import styled from '@emotion/styled'; import { Editor, EditorContent } from '@tiptap/react'; -const StyledEditor = styled.div<{ multiline?: boolean; readonly?: boolean }>` +const StyledEditor = styled.div<{ + multiline?: boolean; + readonly?: boolean; +}>` width: 100%; display: flex; box-sizing: border-box; diff --git a/packages/twenty-front/src/modules/workflow/validation-schemas/workflowSchema.ts b/packages/twenty-front/src/modules/workflow/validation-schemas/workflowSchema.ts index b6554370f..6824d9718 100644 --- a/packages/twenty-front/src/modules/workflow/validation-schemas/workflowSchema.ts +++ b/packages/twenty-front/src/modules/workflow/validation-schemas/workflowSchema.ts @@ -88,9 +88,12 @@ export const workflowFormActionSettingsSchema = z.object({ id: z.string().uuid(), label: z.string(), - type: z.nativeEnum(FieldMetadataType), + type: z.union([ + z.literal(FieldMetadataType.TEXT), + z.literal(FieldMetadataType.NUMBER), + ]), placeholder: z.string().optional(), - settings: z.record(z.any()), + settings: z.record(z.any()).optional(), }), ), }); diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepDetail.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepDetail.tsx index 21df64c9b..dc230f719 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepDetail.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepDetail.tsx @@ -4,9 +4,9 @@ import { getStepDefinitionOrThrow } from '@/workflow/utils/getStepDefinitionOrTh import { WorkflowEditActionCreateRecord } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionCreateRecord'; import { WorkflowEditActionDeleteRecord } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionDeleteRecord'; import { WorkflowEditActionFindRecords } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFindRecords'; -import { WorkflowEditActionForm } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionForm'; import { WorkflowEditActionSendEmail } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionSendEmail'; import { WorkflowEditActionUpdateRecord } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionUpdateRecord'; +import { WorkflowEditActionForm } from '@/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionForm'; import { WorkflowEditTriggerCronForm } from '@/workflow/workflow-trigger/components/WorkflowEditTriggerCronForm'; import { WorkflowEditTriggerDatabaseEventForm } from '@/workflow/workflow-trigger/components/WorkflowEditTriggerDatabaseEventForm'; import { WorkflowEditTriggerManualForm } from '@/workflow/workflow-trigger/components/WorkflowEditTriggerManualForm'; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionForm.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionForm.tsx similarity index 71% rename from packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionForm.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionForm.tsx index 64a85fc46..17fd6a606 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionForm.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionForm.tsx @@ -5,11 +5,13 @@ import { InputLabel } from '@/ui/input/components/InputLabel'; import { WorkflowFormAction } from '@/workflow/types/Workflow'; import { WorkflowStepBody } from '@/workflow/workflow-steps/components/WorkflowStepBody'; import { WorkflowStepHeader } from '@/workflow/workflow-steps/components/WorkflowStepHeader'; +import { WorkflowEditActionFormFieldSettings } from '@/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionFormFieldSettings'; +import { getDefaultFormFieldSettings } from '@/workflow/workflow-steps/workflow-actions/form-action/utils/getDefaultFormFieldSettings'; import { getActionIcon } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIcon'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { useLingui } from '@lingui/react/macro'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { FieldMetadataType, isDefined } from 'twenty-shared'; import { IconChevronDown, @@ -18,9 +20,11 @@ import { IconTrash, useIcons, } from 'twenty-ui'; +import { useDebouncedCallback } from 'use-debounce'; + import { v4 } from 'uuid'; -type WorkflowEditActionFormProps = { +export type WorkflowEditActionFormProps = { action: WorkflowFormAction; actionOptions: | { @@ -32,6 +36,16 @@ type WorkflowEditActionFormProps = { }; }; +export type WorkflowFormActionField = { + id: string; + label: string; + type: FieldMetadataType.TEXT | FieldMetadataType.NUMBER; + placeholder?: string; + settings?: Record; +}; + +type FormData = WorkflowFormActionField[]; + const StyledRowContainer = styled.div` column-gap: ${({ theme }) => theme.spacing(1)}; display: grid; @@ -92,6 +106,9 @@ export const WorkflowEditActionForm = ({ const theme = useTheme(); const { getIcon } = useIcons(); const { t } = useLingui(); + + const [formData, setFormData] = useState(action.settings.input); + const headerTitle = isDefined(action.name) ? action.name : `Form`; const headerIcon = getActionIcon(action.type); const [selectedField, setSelectedField] = useState(null); @@ -108,6 +125,40 @@ export const WorkflowEditActionForm = ({ } }; + const onFieldUpdate = (updatedField: WorkflowFormActionField) => { + if (actionOptions.readonly === true) { + return; + } + + const updatedFormData = formData.map((currentField) => + currentField.id === updatedField.id ? updatedField : currentField, + ); + + setFormData(updatedFormData); + + saveAction(updatedFormData); + }; + + const saveAction = useDebouncedCallback(async (formData: FormData) => { + if (actionOptions.readonly === true) { + return; + } + + actionOptions.onActionUpdate({ + ...action, + settings: { + ...action.settings, + input: formData, + }, + }); + }, 1_000); + + useEffect(() => { + return () => { + saveAction.flush(); + }; + }, [saveAction]); + return ( <> - {action.settings.input.map((field) => ( + {formData.map((field) => ( {field.label ? {field.label} : null} @@ -166,19 +217,32 @@ export const WorkflowEditActionForm = ({ return; } + const updatedFormData = formData.filter( + (currentField) => currentField.id !== field.id, + ); + + setFormData(updatedFormData); + actionOptions.onActionUpdate({ ...action, settings: { ...action.settings, - input: action.settings.input.filter( - (f) => f.id !== field.id, - ), + input: updatedFormData, }, }); }} /> )} + {isFieldSelected(field.id) && ( + { + setSelectedField(null); + }} + /> + )} ))} @@ -189,20 +253,24 @@ export const WorkflowEditActionForm = ({ { + const { label, placeholder } = getDefaultFormFieldSettings( + FieldMetadataType.TEXT, + ); + + const newField: WorkflowFormActionField = { + id: v4(), + type: FieldMetadataType.TEXT, + label, + placeholder, + }; + + setFormData([...formData, newField]); + actionOptions.onActionUpdate({ ...action, settings: { ...action.settings, - input: [ - ...action.settings.input, - { - id: v4(), - type: FieldMetadataType.TEXT, - label: 'New Field', - placeholder: 'New Field', - settings: {}, - }, - ], + input: [...action.settings.input, newField], }, }); }} diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionFormFieldSettings.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionFormFieldSettings.tsx new file mode 100644 index 000000000..b0345c958 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionFormFieldSettings.tsx @@ -0,0 +1,140 @@ +import { FormFieldInputContainer } from '@/object-record/record-field/form-types/components/FormFieldInputContainer'; +import { FormSelectFieldInput } from '@/object-record/record-field/form-types/components/FormSelectFieldInput'; +import { InputLabel } from '@/ui/input/components/InputLabel'; +import { WorkflowFormActionField } from '@/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionForm'; +import { WorkflowFormFieldSettingsByType } from '@/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsByType'; +import { getDefaultFormFieldSettings } from '@/workflow/workflow-steps/workflow-actions/form-action/utils/getDefaultFormFieldSettings'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { t } from '@lingui/core/macro'; +import { FieldMetadataType } from 'twenty-shared'; +import { + IconSettingsAutomation, + IconX, + IllustrationIconNumbers, + IllustrationIconText, + LightIconButton, +} from 'twenty-ui'; + +type WorkflowEditActionFormFieldSettingsProps = { + field: WorkflowFormActionField; + onChange: (field: WorkflowFormActionField) => void; + onClose: () => void; +}; + +const StyledFormFieldSettingsContainer = styled.div` + background-color: ${({ theme }) => theme.background.transparent.lighter}; + border: 1px solid ${({ theme }) => theme.border.color.light}; + border-radius: ${({ theme }) => theme.border.radius.md}; + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spacing(1)}; + margin-top: ${({ theme }) => theme.spacing(3)}; +`; + +const StyledSettingsContent = styled.div` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spacing(2)}; + padding: ${({ theme }) => theme.spacing(3)}; +`; + +const StyledSettingsHeader = styled.div` + border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; + display: grid; + gap: ${({ theme }) => theme.spacing(1)}; + padding-inline: ${({ theme }) => theme.spacing(3)}; + grid-template-columns: 1fr 24px; + padding-bottom: ${({ theme }) => theme.spacing(3)}; +`; + +const StyledTitleContainer = styled.div` + display: flex; + flex-direction: row; + gap: ${({ theme }) => theme.spacing(1)}; + padding-top: ${({ theme }) => theme.spacing(3)}; +`; + +const StyledCloseButtonContainer = styled.div` + padding-top: ${({ theme }) => theme.spacing(2)}; +`; + +export const WorkflowEditActionFormFieldSettings = ({ + field, + onChange, + onClose, +}: WorkflowEditActionFormFieldSettingsProps) => { + const theme = useTheme(); + const onSubFieldUpdate = (fieldName: string, value: any) => { + onChange({ + ...field, + [fieldName]: value, + }); + }; + + return ( + + + + + {t`Input settings`} + + + + + + + + Type + { + if (newType === null) { + return; + } + + const type = newType as + | FieldMetadataType.TEXT + | FieldMetadataType.NUMBER; + const { label, placeholder } = getDefaultFormFieldSettings(type); + + onChange({ + ...field, + type, + label, + placeholder, + }); + }} + defaultValue={field.type} + preventDisplayPadding + /> + + + + + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsByType.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsByType.tsx new file mode 100644 index 000000000..795116a96 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsByType.tsx @@ -0,0 +1,37 @@ +import { WorkflowFormActionField } from '@/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionForm'; +import { assertUnreachable, FieldMetadataType } from 'twenty-shared'; +import { WorkflowFormFieldSettingsNumber } from './WorkflowFormFieldSettingsNumber'; +import { WorkflowFormFieldSettingsText } from './WorkflowFormFieldSettingsText'; + +export const WorkflowFormFieldSettingsByType = ({ + field, + onChange, +}: { + field: WorkflowFormActionField; + onChange: (fieldName: string, value: string | null) => void; +}) => { + switch (field.type) { + case FieldMetadataType.TEXT: + return ( + { + onChange(fieldName, value); + }} + /> + ); + case FieldMetadataType.NUMBER: + return ( + { + onChange(fieldName, value); + }} + /> + ); + default: + return assertUnreachable(field.type, 'Unknown form field type'); + } +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsNumber.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsNumber.tsx new file mode 100644 index 000000000..834eba71c --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsNumber.tsx @@ -0,0 +1,48 @@ +import { FormFieldInputContainer } from '@/object-record/record-field/form-types/components/FormFieldInputContainer'; +import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput'; +import { InputLabel } from '@/ui/input/components/InputLabel'; +import styled from '@emotion/styled'; +import { t } from '@lingui/core/macro'; + +type WorkflowFormFieldSettingsNumberProps = { + label?: string; + placeholder?: string; + onChange: (fieldName: string, value: string | null) => void; +}; + +const StyledContainer = styled.div` + display: flex; + flex-direction: row; + gap: ${({ theme }) => theme.spacing(2)}; +`; + +export const WorkflowFormFieldSettingsNumber = ({ + label, + placeholder, + onChange, +}: WorkflowFormFieldSettingsNumberProps) => { + return ( + + + Label + { + onChange('label', newLabel); + }} + defaultValue={label ?? t`Number`} + placeholder={t`Text`} + /> + + + Placeholder + { + onChange('placeholder', newPlaceholder); + }} + defaultValue={placeholder ?? '1000'} + placeholder={'1000'} + /> + + + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsText.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsText.tsx new file mode 100644 index 000000000..109106fdf --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowFormFieldSettingsText.tsx @@ -0,0 +1,47 @@ +import { FormFieldInputContainer } from '@/object-record/record-field/form-types/components/FormFieldInputContainer'; +import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput'; +import { InputLabel } from '@/ui/input/components/InputLabel'; +import styled from '@emotion/styled'; + +type WorkflowFormFieldSettingsTextProps = { + label?: string; + placeholder?: string; + onChange: (fieldName: string, value: string | null) => void; +}; + +const StyledContainer = styled.div` + display: flex; + flex-direction: row; + gap: ${({ theme }) => theme.spacing(2)}; +`; + +export const WorkflowFormFieldSettingsText = ({ + label, + placeholder, + onChange, +}: WorkflowFormFieldSettingsTextProps) => { + return ( + + + Label + { + onChange('label', newLabel); + }} + defaultValue={label} + placeholder={'Text'} + /> + + + Placeholder + { + onChange('placeholder', newPlaceholder); + }} + defaultValue={placeholder} + placeholder={'Enter your text'} + /> + + + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/__stories__/WorkflowEditActionForm.stories.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/__stories__/WorkflowEditActionForm.stories.tsx similarity index 95% rename from packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/__stories__/WorkflowEditActionForm.stories.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/__stories__/WorkflowEditActionForm.stories.tsx index 3fce15fa3..df1786786 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/__stories__/WorkflowEditActionForm.stories.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/__stories__/WorkflowEditActionForm.stories.tsx @@ -1,5 +1,5 @@ import { WorkflowFormAction } from '@/workflow/types/Workflow'; -import { WorkflowEditActionForm } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionForm'; +import { WorkflowEditActionForm } from '@/workflow/workflow-steps/workflow-actions/form-action/components/WorkflowEditActionForm'; import { Meta, StoryObj } from '@storybook/react'; import { expect, fn, within } from '@storybook/test'; import { FieldMetadataType } from 'twenty-shared'; @@ -44,7 +44,7 @@ const DEFAULT_ACTION = { } satisfies WorkflowFormAction; const meta: Meta = { - title: 'Modules/Workflow/WorkflowEditActionForm', + title: 'Modules/Workflow/Actions/Form/WorkflowEditActionForm', component: WorkflowEditActionForm, parameters: { msw: graphqlMocks, diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/__stories__/WorkflowEditActionFormFieldSettings.stories.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/__stories__/WorkflowEditActionFormFieldSettings.stories.tsx new file mode 100644 index 000000000..bcf32189e --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/components/__stories__/WorkflowEditActionFormFieldSettings.stories.tsx @@ -0,0 +1,90 @@ +import { WorkflowFormAction } from '@/workflow/types/Workflow'; +import { Meta, StoryObj } from '@storybook/react'; +import { expect, fn, userEvent, within } from '@storybook/test'; +import { FieldMetadataType } from 'twenty-shared'; +import { ComponentDecorator } from 'twenty-ui'; +import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator'; +import { WorkflowStepActionDrawerDecorator } from '~/testing/decorators/WorkflowStepActionDrawerDecorator'; +import { WorkflowEditActionFormFieldSettings } from '../WorkflowEditActionFormFieldSettings'; + +const meta: Meta = { + title: 'Modules/Workflow/Actions/Form/WorkflowEditActionFormFieldSettings', + component: WorkflowEditActionFormFieldSettings, + decorators: [ + WorkflowStepActionDrawerDecorator, + ComponentDecorator, + I18nFrontDecorator, + ], +}; + +export default meta; +type Story = StoryObj; + +const mockAction: WorkflowFormAction = { + id: 'form-action-1', + type: 'FORM', + name: 'Test Form', + valid: true, + settings: { + input: [ + { + id: 'field-1', + label: 'Text Field', + type: FieldMetadataType.TEXT, + placeholder: 'Enter text', + settings: {}, + }, + ], + outputSchema: {}, + errorHandlingOptions: { + retryOnFailure: { value: false }, + continueOnFailure: { value: false }, + }, + }, +}; + +export const TextFieldSettings: Story = { + args: { + field: mockAction.settings.input[0], + onClose: fn(), + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + const typeSelect = await canvas.findByText('Text'); + expect(typeSelect).toBeVisible(); + + const placeholderInput = await canvas.findByText('Enter text'); + expect(placeholderInput).toBeVisible(); + + const closeButton = await canvas.findByRole('button'); + await userEvent.click(closeButton); + expect(args.onClose).toHaveBeenCalled(); + }, +}; + +export const NumberFieldSettings: Story = { + args: { + field: { + id: 'field-2', + label: 'Number Field', + type: FieldMetadataType.NUMBER, + placeholder: 'Enter number', + settings: {}, + }, + onClose: fn(), + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + const typeSelect = await canvas.findByText('Number'); + expect(typeSelect).toBeVisible(); + + const placeholderInput = await canvas.findByText('Enter number'); + expect(placeholderInput).toBeInTheDocument(); + + const closeButton = await canvas.findByRole('button'); + await userEvent.click(closeButton); + expect(args.onClose).toHaveBeenCalled(); + }, +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/utils/getDefaultFormFieldSettings.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/utils/getDefaultFormFieldSettings.ts new file mode 100644 index 000000000..ab83e66fe --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/form-action/utils/getDefaultFormFieldSettings.ts @@ -0,0 +1,21 @@ +import { FieldMetadataType } from 'twenty-shared'; + +export const getDefaultFormFieldSettings = (type: FieldMetadataType) => { + switch (type) { + case FieldMetadataType.TEXT: + return { + label: 'Text', + placeholder: 'Enter your text', + }; + case FieldMetadataType.NUMBER: + return { + label: 'Number', + placeholder: '1000', + }; + default: + return { + label: type.charAt(0).toUpperCase() + type.slice(1), + placeholder: 'Enter your value', + }; + } +};