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 index 5a99fd7d3..dd0d999da 100644 --- 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 @@ -1,11 +1,16 @@ import { FormBooleanFieldInput } from '@/object-record/record-field/form-types/components/FormBooleanFieldInput'; +import { FormFullNameFieldInput } from '@/object-record/record-field/form-types/components/FormFullNameFieldInput'; import { FormNumberFieldInput } from '@/object-record/record-field/form-types/components/FormNumberFieldInput'; import { FormSelectFieldInput } from '@/object-record/record-field/form-types/components/FormSelectFieldInput'; import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput'; import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent'; import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition'; -import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; +import { + FieldFullNameValue, + FieldMetadata, +} from '@/object-record/record-field/types/FieldMetadata'; import { isFieldBoolean } from '@/object-record/record-field/types/guards/isFieldBoolean'; +import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName'; import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber'; import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect'; import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText'; @@ -55,5 +60,12 @@ export const FormFieldInput = ({ field={field} VariablePicker={VariablePicker} /> + ) : isFieldFullName(field) ? ( + ) : null; }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormFullNameFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormFullNameFieldInput.tsx new file mode 100644 index 000000000..e4cf57b42 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormFullNameFieldInput.tsx @@ -0,0 +1,66 @@ +import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput'; +import { StyledFormCompositeFieldInputContainer } from '@/object-record/record-field/form-types/components/StyledFormCompositeFieldInputContainer'; +import { StyledFormFieldInputContainer } from '@/object-record/record-field/form-types/components/StyledFormFieldInputContainer'; +import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent'; +import { FIRST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS } from '@/object-record/record-field/meta-types/input/constants/FirstNamePlaceholder'; +import { LAST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS } from '@/object-record/record-field/meta-types/input/constants/LastNamePlaceholder'; +import { FieldFullNameValue } from '@/object-record/record-field/types/FieldMetadata'; +import { InputLabel } from '@/ui/input/components/InputLabel'; + +type FormFullNameFieldInputProps = { + label?: string; + defaultValue: FieldFullNameValue | undefined; + onPersist: (value: FieldFullNameValue) => void; + VariablePicker?: VariablePickerComponent; + readonly?: boolean; +}; + +export const FormFullNameFieldInput = ({ + label, + defaultValue, + onPersist, + readonly, + VariablePicker, +}: FormFullNameFieldInputProps) => { + const handleFirstNameChange = (newText: string) => { + onPersist({ + lastName: defaultValue?.lastName ?? '', + firstName: newText, + }); + }; + + const handleLastNameChange = (newText: string) => { + onPersist({ + firstName: defaultValue?.firstName ?? '', + lastName: newText, + }); + }; + + return ( + + {label ? {label} : null} + + + + + + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormCompositeFieldInputContainer.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormCompositeFieldInputContainer.tsx new file mode 100644 index 000000000..47a8bfe77 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormCompositeFieldInputContainer.tsx @@ -0,0 +1,11 @@ +import styled from '@emotion/styled'; + +export const StyledFormCompositeFieldInputContainer = styled.div` + display: flex; + flex-direction: column; + background: ${({ theme }) => theme.background.secondary}; + border: 1px solid ${({ theme }) => theme.border.color.medium}; + border-radius: ${({ theme }) => theme.border.radius.sm}; + gap: ${({ theme }) => theme.spacing(2)}; + padding: ${({ theme }) => theme.spacing(2)}; +`; diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormFieldInputContainer.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormFieldInputContainer.tsx index 5615ab80b..cc04e0f7a 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormFieldInputContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormFieldInputContainer.tsx @@ -3,4 +3,5 @@ import styled from '@emotion/styled'; export const StyledFormFieldInputContainer = styled.div` display: flex; flex-direction: column; + width: 100%; `; diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormFullNameFieldInput.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormFullNameFieldInput.stories.tsx new file mode 100644 index 000000000..62def51e5 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormFullNameFieldInput.stories.tsx @@ -0,0 +1,31 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { within } from '@storybook/test'; +import { FormFullNameFieldInput } from '../FormFullNameFieldInput'; + +const meta: Meta = { + title: 'UI/Data/Field/Form/Input/FormFullNameFieldInput', + component: FormFullNameFieldInput, + args: {}, + argTypes: {}, +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + label: 'Name', + defaultValue: { + firstName: 'John', + lastName: 'Doe', + }, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await canvas.findByText('Name'); + await canvas.findByText('First Name'); + await canvas.findByText('Last Name'); + }, +}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx index bdba34f0c..49335d42b 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx @@ -3,18 +3,14 @@ import { FieldDoubleText } from '@/object-record/record-field/types/FieldDoubleT import { DoubleTextInput } from '@/ui/field/input/components/DoubleTextInput'; import { FieldInputOverlay } from '@/ui/field/input/components/FieldInputOverlay'; +import { FIRST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS } from '@/object-record/record-field/meta-types/input/constants/FirstNamePlaceholder'; +import { LAST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS } from '@/object-record/record-field/meta-types/input/constants/LastNamePlaceholder'; import { isDoubleTextFieldEmpty } from '@/object-record/record-field/meta-types/input/utils/isDoubleTextFieldEmpty'; import { FieldInputClickOutsideEvent, FieldInputEvent, } from './DateTimeFieldInput'; -const FIRST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS = - 'F‌‌irst name'; - -const LAST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS = - 'L‌‌ast name'; - type FullNameFieldInputProps = { onClickOutside?: FieldInputClickOutsideEvent; onEnter?: FieldInputEvent; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/FirstNamePlaceholder.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/FirstNamePlaceholder.ts new file mode 100644 index 000000000..7eac65e02 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/FirstNamePlaceholder.ts @@ -0,0 +1,2 @@ +export const FIRST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS = + 'F‌‌irst name'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/LastNamePlaceholder.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/LastNamePlaceholder.ts new file mode 100644 index 000000000..04f082144 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/LastNamePlaceholder.ts @@ -0,0 +1,2 @@ +export const LAST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS = + 'L‌‌ast name'; diff --git a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdown.tsx b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdown.tsx index 965a41f40..64eebb382 100644 --- a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdown.tsx +++ b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdown.tsx @@ -1,4 +1,5 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; +import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { StyledDropdownButtonContainer } from '@/ui/layout/dropdown/components/StyledDropdownButtonContainer'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { SearchVariablesDropdownFieldItems } from '@/workflow/search-variables/components/SearchVariablesDropdownFieldItems'; @@ -26,7 +27,7 @@ const StyledDropdownVariableButtonContainer = styled( } `; -const StyledDropdownComponetsContainer = styled.div` +const StyledDropdownComponentsContainer = styled(DropdownMenuItemsContainer)` background-color: ${({ theme }) => theme.background.transparent.light}; `; @@ -136,9 +137,9 @@ const SearchVariablesDropdown = ({ } dropdownComponents={ - + {renderSearchVariablesDropdownComponents()} - + } dropdownPlacement="bottom-end" dropdownOffset={{ x: 0, y: 4 }} diff --git a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownFieldItems.tsx b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownFieldItems.tsx index 8dcd83572..ac274e131 100644 --- a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownFieldItems.tsx +++ b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownFieldItems.tsx @@ -1,5 +1,4 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader'; -import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { BaseOutputSchema, @@ -100,8 +99,14 @@ export const SearchVariablesDropdownFieldItems = ({ : options; return ( - - + <> + ))} - + ); }; diff --git a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownObjectItems.tsx b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownObjectItems.tsx index 92aace99a..b48cf0bff 100644 --- a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownObjectItems.tsx +++ b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownObjectItems.tsx @@ -1,5 +1,4 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader'; -import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { OutputSchema, @@ -112,7 +111,7 @@ export const SearchVariablesDropdownObjectItems = ({ : options; return ( - + <> @@ -154,6 +153,6 @@ export const SearchVariablesDropdownObjectItems = ({ LeftIcon={value.icon ? getIcon(value.icon) : undefined} /> ))} - + ); }; diff --git a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownWorkflowStepItems.tsx b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownWorkflowStepItems.tsx index 4c0520752..b4a390c73 100644 --- a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownWorkflowStepItems.tsx +++ b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownWorkflowStepItems.tsx @@ -1,5 +1,4 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader'; -import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { StepOutputSchema } from '@/workflow/search-variables/types/StepOutputSchema'; @@ -36,7 +35,7 @@ export const SearchVariablesDropdownWorkflowStepItems = ({ ); return ( - + <> @@ -74,6 +73,6 @@ export const SearchVariablesDropdownWorkflowStepItems = ({ hasSubMenu={false} /> )} - + ); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx b/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx index a5685313e..93527dd2a 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx @@ -1,4 +1,5 @@ import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput'; +import { StyledFormCompositeFieldInputContainer } from '@/object-record/record-field/form-types/components/StyledFormCompositeFieldInputContainer'; import { useGetAvailablePackages } from '@/settings/serverless-functions/hooks/useGetAvailablePackages'; import { useServerlessFunctionUpdateFormState } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState'; import { useUpdateOneServerlessFunction } from '@/settings/serverless-functions/hooks/useUpdateOneServerlessFunction'; @@ -44,17 +45,6 @@ const StyledLabel = styled.div` margin-bottom: ${({ theme }) => theme.spacing(2)}; `; -const StyledInputContainer = styled.div` - background: ${({ theme }) => theme.background.secondary}; - border: 1px solid ${({ theme }) => theme.border.color.medium}; - border-radius: ${({ theme }) => theme.border.radius.md}; - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.spacing(2)}; - padding: ${({ theme }) => theme.spacing(2)}; - position: relative; -`; - type WorkflowEditActionFormServerlessFunctionProps = { action: WorkflowCodeAction; actionOptions: @@ -223,9 +213,9 @@ export const WorkflowEditActionFormServerlessFunction = ({ return ( {inputKey} - + {renderFields(inputValue, currentPath, false)} - + ); } else {