diff --git a/packages/twenty-front/src/modules/settings/integrations/components/SettingsIntegrationDatabaseConnectionForm.tsx b/packages/twenty-front/src/modules/settings/integrations/components/SettingsIntegrationDatabaseConnectionForm.tsx new file mode 100644 index 000000000..f0c20165f --- /dev/null +++ b/packages/twenty-front/src/modules/settings/integrations/components/SettingsIntegrationDatabaseConnectionForm.tsx @@ -0,0 +1,62 @@ +import { Controller, useFormContext } from 'react-hook-form'; +import styled from '@emotion/styled'; +import { z } from 'zod'; + +import { TextInput } from '@/ui/input/components/TextInput'; + +export const settingsIntegrationPostgreSQLConnectionFormSchema = z.object({ + dbname: z.string().min(1), + host: z.string().min(1), + port: z.number().positive(), + username: z.string().min(1), + password: z.string().min(1), +}); + +type SettingsIntegrationPostgreSQLConnectionFormValues = z.infer< + typeof settingsIntegrationPostgreSQLConnectionFormSchema +>; + +const StyledInputsContainer = styled.div` + display: grid; + gap: ${({ theme }) => theme.spacing(2, 4)}; + grid-template-columns: 1fr 1fr; + grid-template-areas: + 'input-1 input-1' + 'input-2 input-3' + 'input-4 input-5'; + + & :first-child { + grid-area: input-1; + } +`; + +export const SettingsIntegrationPostgreSQLConnectionForm = () => { + const { control } = + useFormContext(); + + return ( + + {[ + { name: 'dbname' as const, label: 'Database Name' }, + { name: 'host' as const, label: 'Host' }, + { name: 'port' as const, label: 'Port' }, + { name: 'username' as const, label: 'Username' }, + { name: 'password' as const, label: 'Password' }, + ].map(({ name, label }) => ( + ( + + )} + /> + ))} + + ); +}; diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnection.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnection.tsx index 7dae2081a..7cc53d7dc 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnection.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnection.tsx @@ -46,6 +46,10 @@ export const SettingsIntegrationDatabaseConnection = () => { if (!isIntegrationAvailable || !connection) return null; + const settingsIntegrationsPagePath = getSettingsPagePath( + SettingsPath.Integrations, + ); + return ( @@ -53,11 +57,11 @@ export const SettingsIntegrationDatabaseConnection = () => { links={[ { children: 'Integrations', - href: getSettingsPagePath(SettingsPath.Integrations), + href: settingsIntegrationsPagePath, }, { children: integration.text, - href: `/settings/integrations/${databaseKey}`, + href: `${settingsIntegrationsPagePath}/${databaseKey}`, }, { children: connection.name }, ]} diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx index cb6daa5b2..bb7dda87b 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx @@ -1,14 +1,31 @@ import { useEffect } from 'react'; +import { FormProvider, useForm } from 'react-hook-form'; import { useNavigate, useParams } from 'react-router-dom'; +import { zodResolver } from '@hookform/resolvers/zod'; import { IconSettings } from 'twenty-ui'; +import { z } from 'zod'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; +import { + SettingsIntegrationPostgreSQLConnectionForm, + settingsIntegrationPostgreSQLConnectionFormSchema, +} from '@/settings/integrations/components/SettingsIntegrationDatabaseConnectionForm'; import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/useSettingsIntegrationCategories'; +import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { AppPath } from '@/types/AppPath'; +import { SettingsPath } from '@/types/SettingsPath'; +import { H2Title } from '@/ui/display/typography/components/H2Title'; import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'; +import { Section } from '@/ui/layout/section/components/Section'; import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; +const newConnectionSchema = settingsIntegrationPostgreSQLConnectionFormSchema; + +type SettingsIntegrationNewConnectionFormValues = z.infer< + typeof newConnectionSchema +>; + export const SettingsIntegrationNewDatabaseConnection = () => { const { databaseKey = '' } = useParams(); const navigate = useNavigate(); @@ -35,22 +52,46 @@ export const SettingsIntegrationNewDatabaseConnection = () => { } }, [integration, databaseKey, navigate, isIntegrationAvailable]); + const formConfig = useForm({ + mode: 'onTouched', + resolver: zodResolver(newConnectionSchema), + }); + if (!isIntegrationAvailable) return null; + const settingsIntegrationsPagePath = getSettingsPagePath( + SettingsPath.Integrations, + ); + return ( - - - - - + // eslint-disable-next-line react/jsx-props-no-spreading + + + + + {databaseKey === 'postgresql' ? ( +
+ + +
+ ) : null} +
+
+
); };