diff --git a/packages/twenty-front/public/images/integrations/stripe-logo.png b/packages/twenty-front/public/images/integrations/stripe-logo.png new file mode 100644 index 000000000000..5cc85410b1ab Binary files /dev/null and b/packages/twenty-front/public/images/integrations/stripe-logo.png differ diff --git a/packages/twenty-front/src/modules/databases/hooks/useSyncRemoteTable.ts b/packages/twenty-front/src/modules/databases/hooks/useSyncRemoteTable.ts index 7a3a39ecb7a2..72b9e5c2a454 100644 --- a/packages/twenty-front/src/modules/databases/hooks/useSyncRemoteTable.ts +++ b/packages/twenty-front/src/modules/databases/hooks/useSyncRemoteTable.ts @@ -1,6 +1,5 @@ import { useCallback } from 'react'; import { ApolloClient, useApolloClient, useMutation } from '@apollo/client'; -import { getOperationName } from '@apollo/client/utilities'; import { SYNC_REMOTE_TABLE } from '@/databases/graphql/mutations/syncRemoteTable'; import { GET_MANY_REMOTE_TABLES } from '@/databases/graphql/queries/findManyRemoteTables'; @@ -39,7 +38,16 @@ export const useSyncRemoteTable = () => { input, }, awaitRefetchQueries: true, - refetchQueries: [getOperationName(GET_MANY_REMOTE_TABLES) ?? ''], + refetchQueries: [ + { + query: GET_MANY_REMOTE_TABLES, + variables: { + input: { + id: input.remoteServerId, + }, + }, + }, + ], }); // TODO: we should return the tables with the columns and store in cache instead of refetching diff --git a/packages/twenty-front/src/modules/databases/hooks/useUnsyncRemoteTable.ts b/packages/twenty-front/src/modules/databases/hooks/useUnsyncRemoteTable.ts index 6bc85507fe21..89d2bc04e115 100644 --- a/packages/twenty-front/src/modules/databases/hooks/useUnsyncRemoteTable.ts +++ b/packages/twenty-front/src/modules/databases/hooks/useUnsyncRemoteTable.ts @@ -1,6 +1,5 @@ import { useCallback } from 'react'; import { ApolloClient, useMutation } from '@apollo/client'; -import { getOperationName } from '@apollo/client/utilities'; import { UNSYNC_REMOTE_TABLE } from '@/databases/graphql/mutations/unsyncRemoteTable'; import { GET_MANY_REMOTE_TABLES } from '@/databases/graphql/queries/findManyRemoteTables'; @@ -31,7 +30,16 @@ export const useUnsyncRemoteTable = () => { input, }, awaitRefetchQueries: true, - refetchQueries: [getOperationName(GET_MANY_REMOTE_TABLES) ?? ''], + refetchQueries: [ + { + query: GET_MANY_REMOTE_TABLES, + variables: { + input: { + id: input.remoteServerId, + }, + }, + }, + ], }); await refetchObjectMetadataItems(); diff --git a/packages/twenty-front/src/modules/databases/utils/getForeignDataWrapperType.ts b/packages/twenty-front/src/modules/databases/utils/getForeignDataWrapperType.ts index af50a62419d6..cd3c16f17a3f 100644 --- a/packages/twenty-front/src/modules/databases/utils/getForeignDataWrapperType.ts +++ b/packages/twenty-front/src/modules/databases/utils/getForeignDataWrapperType.ts @@ -2,6 +2,8 @@ export const getForeignDataWrapperType = (databaseKey: string) => { switch (databaseKey) { case 'postgresql': return 'postgres_fdw'; + case 'stripe': + return 'stripe_fdw'; default: return null; } diff --git a/packages/twenty-front/src/modules/settings/integrations/constants/MockRemoteDatabases.ts b/packages/twenty-front/src/modules/settings/integrations/constants/MockRemoteDatabases.ts index d15c6cbd95bb..afcd03dd5b78 100644 --- a/packages/twenty-front/src/modules/settings/integrations/constants/MockRemoteDatabases.ts +++ b/packages/twenty-front/src/modules/settings/integrations/constants/MockRemoteDatabases.ts @@ -7,4 +7,8 @@ export const MOCK_REMOTE_DATABASES = [ name: 'postgresql', isActive: true, }, + { + name: 'stripe', + isActive: true, + }, ]; diff --git a/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm.tsx b/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm.tsx index 91848ee6e6b6..51532255d134 100644 --- a/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm.tsx +++ b/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm.tsx @@ -17,6 +17,14 @@ type SettingsIntegrationPostgreSQLConnectionFormValues = z.infer< typeof settingsIntegrationPostgreSQLConnectionFormSchema >; +export const settingsIntegrationStripeConnectionFormSchema = z.object({ + api_key: z.string().min(1), +}); + +type SettingsIntegrationStripeConnectionFormValues = z.infer< + typeof settingsIntegrationStripeConnectionFormSchema +>; + const StyledInputsContainer = styled.div` display: grid; gap: ${({ theme }) => theme.spacing(2, 4)}; @@ -31,19 +39,35 @@ const StyledInputsContainer = styled.div` } `; -type SettingsIntegrationPostgreSQLConnectionFormProps = { +type SettingsIntegrationDatabaseConnectionFormProps = { + databaseKey: string; disabled?: boolean; }; -export const SettingsIntegrationPostgreSQLConnectionForm = ({ - disabled, -}: SettingsIntegrationPostgreSQLConnectionFormProps) => { - const { control } = - useFormContext(); +type SettingsIntegrationConnectionFormValues = + | SettingsIntegrationPostgreSQLConnectionFormValues + | SettingsIntegrationStripeConnectionFormValues; - return ( - - {[ +const getFormFields = ( + databaseKey: string, +): + | { + name: + | 'dbname' + | 'host' + | 'port' + | 'user' + | 'password' + | 'schema' + | 'api_key'; + label: string; + type?: string; + placeholder: string; + }[] + | null => { + switch (databaseKey) { + case 'postgresql': + return [ { name: 'dbname' as const, label: 'Database Name', @@ -63,7 +87,28 @@ export const SettingsIntegrationPostgreSQLConnectionForm = ({ placeholder: '••••••', }, { name: 'schema' as const, label: 'Schema', placeholder: 'public' }, - ].map(({ name, label, type, placeholder }) => ( + ]; + case 'stripe': + return [ + { name: 'api_key' as const, label: 'API Key', placeholder: 'API key' }, + ]; + default: + return null; + } +}; + +export const SettingsIntegrationDatabaseConnectionForm = ({ + databaseKey, + disabled, +}: SettingsIntegrationDatabaseConnectionFormProps) => { + const { control } = useFormContext(); + const formFields = getFormFields(databaseKey); + + if (!formFields) return null; + + return ( + + {formFields.map(({ name, label, type, placeholder }) => ( { return ( )} - {databaseKey === 'postgresql' ? ( -
- +
+ - -
- ) : null} + +
); diff --git a/packages/twenty-front/src/modules/settings/integrations/database-connection/hooks/useDatabaseConnection.ts b/packages/twenty-front/src/modules/settings/integrations/database-connection/hooks/useDatabaseConnection.ts index aa94c3ffe22b..1a44195771e3 100644 --- a/packages/twenty-front/src/modules/settings/integrations/database-connection/hooks/useDatabaseConnection.ts +++ b/packages/twenty-front/src/modules/settings/integrations/database-connection/hooks/useDatabaseConnection.ts @@ -3,9 +3,9 @@ import { useNavigate, useParams } from 'react-router-dom'; import { useGetDatabaseConnection } from '@/databases/hooks/useGetDatabaseConnection'; import { useGetDatabaseConnectionTables } from '@/databases/hooks/useGetDatabaseConnectionTables'; +import { useIsSettingsIntegrationEnabled } from '@/settings/integrations/hooks/useIsSettingsIntegrationEnabled'; import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/useSettingsIntegrationCategories'; import { AppPath } from '@/types/AppPath'; -import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; export const useDatabaseConnection = () => { const { databaseKey = '', connectionId = '' } = useParams(); @@ -16,16 +16,9 @@ export const useDatabaseConnection = () => { ({ from: { key } }) => key === databaseKey, ); - const isAirtableIntegrationEnabled = useIsFeatureEnabled( - 'IS_AIRTABLE_INTEGRATION_ENABLED', - ); - const isPostgresqlIntegrationEnabled = useIsFeatureEnabled( - 'IS_POSTGRESQL_INTEGRATION_ENABLED', - ); - const isIntegrationAvailable = - !!integration && - ((databaseKey === 'airtable' && isAirtableIntegrationEnabled) || - (databaseKey === 'postgresql' && isPostgresqlIntegrationEnabled)); + const isIntegrationEnabled = useIsSettingsIntegrationEnabled(databaseKey); + + const isIntegrationAvailable = !!integration && isIntegrationEnabled; const { connection, loading } = useGetDatabaseConnection({ databaseKey, diff --git a/packages/twenty-front/src/modules/settings/integrations/database-connection/utils/editDatabaseConnection.ts b/packages/twenty-front/src/modules/settings/integrations/database-connection/utils/editDatabaseConnection.ts index 1c1988ad822c..21c0d3ed12e0 100644 --- a/packages/twenty-front/src/modules/settings/integrations/database-connection/utils/editDatabaseConnection.ts +++ b/packages/twenty-front/src/modules/settings/integrations/database-connection/utils/editDatabaseConnection.ts @@ -3,7 +3,10 @@ import isEmpty from 'lodash.isempty'; import pickBy from 'lodash.pickby'; import { z } from 'zod'; -import { settingsIntegrationPostgreSQLConnectionFormSchema } from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm'; +import { + settingsIntegrationPostgreSQLConnectionFormSchema, + settingsIntegrationStripeConnectionFormSchema, +} from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm'; import { RemoteServer } from '~/generated-metadata/graphql'; export const getEditionSchemaForForm = (databaseKey: string) => { @@ -12,6 +15,8 @@ export const getEditionSchemaForForm = (databaseKey: string) => { return settingsIntegrationPostgreSQLConnectionFormSchema.extend({ password: z.string().optional(), }); + case 'stripe': + return settingsIntegrationStripeConnectionFormSchema; default: throw new Error(`No schema found for database key: ${databaseKey}`); } @@ -34,6 +39,10 @@ export const getFormDefaultValuesFromConnection = ({ schema: connection.schema || undefined, password: '', }; + case 'stripe': + return { + api_key: connection.foreignDataWrapperOptions.api_key, + }; default: throw new Error( `No default form values for database key: ${databaseKey}`, @@ -71,6 +80,12 @@ export const formatValuesForUpdate = ({ return pickBy(formattedValues, (obj) => !isEmpty(obj)); } + case 'stripe': + return { + foreignDataWrapperOptions: { + api_key: formValues.api_key, + }, + }; default: throw new Error(`Cannot format values for database key: ${databaseKey}`); } diff --git a/packages/twenty-front/src/modules/settings/integrations/hooks/useIsSettingsIntegrationEnabled.ts b/packages/twenty-front/src/modules/settings/integrations/hooks/useIsSettingsIntegrationEnabled.ts new file mode 100644 index 000000000000..4b814402dec6 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/integrations/hooks/useIsSettingsIntegrationEnabled.ts @@ -0,0 +1,21 @@ +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; + +const getFeatureKey = (databaseKey: string) => { + switch (databaseKey) { + case 'airtable': + return 'IS_AIRTABLE_INTEGRATION_ENABLED'; + case 'postgresql': + return 'IS_POSTGRESQL_INTEGRATION_ENABLED'; + case 'stripe': + return 'IS_STRIPE_INTEGRATION_ENABLED'; + default: + return null; + } +}; + +export const useIsSettingsIntegrationEnabled = ( + databaseKey: string, +): boolean => { + const featureKey = getFeatureKey(databaseKey); + return useIsFeatureEnabled(featureKey); +}; diff --git a/packages/twenty-front/src/modules/settings/integrations/hooks/useSettingsIntegrationCategories.ts b/packages/twenty-front/src/modules/settings/integrations/hooks/useSettingsIntegrationCategories.ts index 6f90b54a556b..38a639127fb5 100644 --- a/packages/twenty-front/src/modules/settings/integrations/hooks/useSettingsIntegrationCategories.ts +++ b/packages/twenty-front/src/modules/settings/integrations/hooks/useSettingsIntegrationCategories.ts @@ -14,6 +14,7 @@ export const useSettingsIntegrationCategories = const isAirtableIntegrationActive = !!MOCK_REMOTE_DATABASES.find( ({ name }) => name === 'airtable', )?.isActive; + const isPostgresqlIntegrationEnabled = useIsFeatureEnabled( 'IS_POSTGRESQL_INTEGRATION_ENABLED', ); @@ -21,12 +22,21 @@ export const useSettingsIntegrationCategories = ({ name }) => name === 'postgresql', )?.isActive; + const isStripeIntegrationEnabled = useIsFeatureEnabled( + 'IS_STRIPE_INTEGRATION_ENABLED', + ); + const isStripeIntegrationActive = !!MOCK_REMOTE_DATABASES.find( + ({ name }) => name === 'stripe', + )?.isActive; + return [ getSettingsIntegrationAll({ isAirtableIntegrationEnabled, isAirtableIntegrationActive, isPostgresqlIntegrationEnabled, isPostgresqlIntegrationActive, + isStripeIntegrationEnabled, + isStripeIntegrationActive, }), SETTINGS_INTEGRATION_ZAPIER_CATEGORY, SETTINGS_INTEGRATION_WINDMILL_CATEGORY, diff --git a/packages/twenty-front/src/modules/settings/integrations/utils/getConnectionDbName.ts b/packages/twenty-front/src/modules/settings/integrations/utils/getConnectionDbName.ts index 084632b32db2..1d4401daf708 100644 --- a/packages/twenty-front/src/modules/settings/integrations/utils/getConnectionDbName.ts +++ b/packages/twenty-front/src/modules/settings/integrations/utils/getConnectionDbName.ts @@ -9,7 +9,13 @@ type GetConnectionDbNameParams = { export const getConnectionDbName = ({ integration, connection, -}: GetConnectionDbNameParams) => - integration.from.key === 'postgresql' - ? connection.foreignDataWrapperOptions?.dbname - : ''; +}: GetConnectionDbNameParams) => { + switch (integration.from.key) { + case 'postgresql': + return connection.foreignDataWrapperOptions?.dbname; + case 'stripe': + return connection.id; + default: + return ''; + } +}; diff --git a/packages/twenty-front/src/modules/settings/integrations/utils/getSettingsIntegrationAll.ts b/packages/twenty-front/src/modules/settings/integrations/utils/getSettingsIntegrationAll.ts index c3e51f7c6f58..a61532673dc9 100644 --- a/packages/twenty-front/src/modules/settings/integrations/utils/getSettingsIntegrationAll.ts +++ b/packages/twenty-front/src/modules/settings/integrations/utils/getSettingsIntegrationAll.ts @@ -5,11 +5,15 @@ export const getSettingsIntegrationAll = ({ isAirtableIntegrationActive, isPostgresqlIntegrationEnabled, isPostgresqlIntegrationActive, + isStripeIntegrationEnabled, + isStripeIntegrationActive, }: { isAirtableIntegrationEnabled: boolean; isAirtableIntegrationActive: boolean; isPostgresqlIntegrationEnabled: boolean; isPostgresqlIntegrationActive: boolean; + isStripeIntegrationEnabled: boolean; + isStripeIntegrationActive: boolean; }): SettingsIntegrationCategory => ({ key: 'all', title: 'All', @@ -40,5 +44,18 @@ export const getSettingsIntegrationAll = ({ text: 'PostgreSQL', link: '/settings/integrations/postgresql', }, + { + from: { + key: 'stripe', + image: '/images/integrations/stripe-logo.png', + }, + type: !isStripeIntegrationEnabled + ? 'Soon' + : isStripeIntegrationActive + ? 'Active' + : 'Add', + text: 'Stripe', + link: '/settings/integrations/stripe', + }, ], }); diff --git a/packages/twenty-front/src/modules/workspace/hooks/useIsFeatureEnabled.ts b/packages/twenty-front/src/modules/workspace/hooks/useIsFeatureEnabled.ts index 31906107de82..67419f213741 100644 --- a/packages/twenty-front/src/modules/workspace/hooks/useIsFeatureEnabled.ts +++ b/packages/twenty-front/src/modules/workspace/hooks/useIsFeatureEnabled.ts @@ -3,9 +3,13 @@ import { useRecoilValue } from 'recoil'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { FeatureFlagKey } from '@/workspace/types/FeatureFlagKey'; -export const useIsFeatureEnabled = (featureKey: FeatureFlagKey) => { +export const useIsFeatureEnabled = (featureKey: FeatureFlagKey | null) => { const currentWorkspace = useRecoilValue(currentWorkspaceState); + if (!featureKey) { + return false; + } + const featureFlag = currentWorkspace?.featureFlags?.find( (flag) => flag.key === featureKey, ); diff --git a/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts b/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts index 15671bfa8052..cb6262c2d008 100644 --- a/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts +++ b/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts @@ -3,4 +3,5 @@ export type FeatureFlagKey = | 'IS_QUICK_ACTIONS_ENABLED' | 'IS_EVENT_OBJECT_ENABLED' | 'IS_AIRTABLE_INTEGRATION_ENABLED' - | 'IS_POSTGRESQL_INTEGRATION_ENABLED'; + | 'IS_POSTGRESQL_INTEGRATION_ENABLED' + | 'IS_STRIPE_INTEGRATION_ENABLED'; diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabase.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabase.tsx index 65c241036098..bdddc56931af 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabase.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabase.tsx @@ -6,6 +6,7 @@ import { useGetDatabaseConnections } from '@/databases/hooks/useGetDatabaseConne import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SettingsIntegrationPreview } from '@/settings/integrations/components/SettingsIntegrationPreview'; import { SettingsIntegrationDatabaseConnectionsListCard } from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionsListCard'; +import { useIsSettingsIntegrationEnabled } from '@/settings/integrations/hooks/useIsSettingsIntegrationEnabled'; import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/useSettingsIntegrationCategories'; import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { AppPath } from '@/types/AppPath'; @@ -14,7 +15,6 @@ 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'; export const SettingsIntegrationDatabase = () => { const { databaseKey = '' } = useParams(); @@ -25,16 +25,9 @@ export const SettingsIntegrationDatabase = () => { ({ from: { key } }) => key === databaseKey, ); - const isAirtableIntegrationEnabled = useIsFeatureEnabled( - 'IS_AIRTABLE_INTEGRATION_ENABLED', - ); - const isPostgresqlIntegrationEnabled = useIsFeatureEnabled( - 'IS_POSTGRESQL_INTEGRATION_ENABLED', - ); - const isIntegrationAvailable = - !!integration && - ((databaseKey === 'airtable' && isAirtableIntegrationEnabled) || - (databaseKey === 'postgresql' && isPostgresqlIntegrationEnabled)); + const isIntegrationEnabled = useIsSettingsIntegrationEnabled(databaseKey); + + const isIntegrationAvailable = !!integration && isIntegrationEnabled; useEffect(() => { if (!isIntegrationAvailable) { diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx index f061f52a29e5..883b8801e7c7 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection.tsx @@ -11,9 +11,11 @@ import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { - SettingsIntegrationPostgreSQLConnectionForm, + SettingsIntegrationDatabaseConnectionForm, settingsIntegrationPostgreSQLConnectionFormSchema, + settingsIntegrationStripeConnectionFormSchema, } from '@/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionForm'; +import { useIsSettingsIntegrationEnabled } from '@/settings/integrations/hooks/useIsSettingsIntegrationEnabled'; import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/useSettingsIntegrationCategories'; import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { AppPath } from '@/types/AppPath'; @@ -23,33 +25,47 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; 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'; import { CreateRemoteServerInput } from '~/generated-metadata/graphql'; -const newConnectionSchema = settingsIntegrationPostgreSQLConnectionFormSchema; - -const createRemoteServerInputSchema = newConnectionSchema - .extend({ - foreignDataWrapperType: z.string().min(1), - }) - .transform((values) => ({ - foreignDataWrapperType: values.foreignDataWrapperType, - foreignDataWrapperOptions: { - dbname: values.dbname, - host: values.host, - port: values.port, - }, - userMappingOptions: { - password: values.password, - user: values.user, - }, - schema: values.schema, - })); - -type SettingsIntegrationNewConnectionFormValues = z.infer< - typeof newConnectionSchema +const createRemoteServerInputPostgresSchema = + settingsIntegrationPostgreSQLConnectionFormSchema.transform( + (values) => ({ + foreignDataWrapperType: 'postgres_fdw', + foreignDataWrapperOptions: { + dbname: values.dbname, + host: values.host, + port: values.port, + }, + userMappingOptions: { + password: values.password, + user: values.user, + }, + schema: values.schema, + }), + ); + +type SettingsIntegrationNewConnectionPostgresFormValues = z.infer< + typeof createRemoteServerInputPostgresSchema >; +const createRemoteServerInputStripeSchema = + settingsIntegrationStripeConnectionFormSchema.transform( + (values) => ({ + foreignDataWrapperType: 'stripe_fdw', + foreignDataWrapperOptions: { + api_key: values.api_key, + }, + }), + ); + +type SettingsIntegrationNewConnectionStripeFormValues = z.infer< + typeof createRemoteServerInputStripeSchema +>; + +type SettingsIntegrationNewConnectionFormValues = + | SettingsIntegrationNewConnectionPostgresFormValues + | SettingsIntegrationNewConnectionStripeFormValues; + export const SettingsIntegrationNewDatabaseConnection = () => { const { databaseKey = '' } = useParams(); const navigate = useNavigate(); @@ -62,16 +78,9 @@ export const SettingsIntegrationNewDatabaseConnection = () => { const { createOneDatabaseConnection } = useCreateOneDatabaseConnection(); const { enqueueSnackBar } = useSnackBar(); - const isAirtableIntegrationEnabled = useIsFeatureEnabled( - 'IS_AIRTABLE_INTEGRATION_ENABLED', - ); - const isPostgresqlIntegrationEnabled = useIsFeatureEnabled( - 'IS_POSTGRESQL_INTEGRATION_ENABLED', - ); - const isIntegrationAvailable = - !!integration && - ((databaseKey === 'airtable' && isAirtableIntegrationEnabled) || - (databaseKey === 'postgresql' && isPostgresqlIntegrationEnabled)); + const isIntegrationEnabled = useIsSettingsIntegrationEnabled(databaseKey); + + const isIntegrationAvailable = !!integration && isIntegrationEnabled; useEffect(() => { if (!isIntegrationAvailable) { @@ -79,6 +88,11 @@ export const SettingsIntegrationNewDatabaseConnection = () => { } }, [integration, databaseKey, navigate, isIntegrationAvailable]); + const newConnectionSchema = + databaseKey === 'postgresql' + ? createRemoteServerInputPostgresSchema + : createRemoteServerInputStripeSchema; + const formConfig = useForm({ mode: 'onTouched', resolver: zodResolver(newConnectionSchema), @@ -97,7 +111,7 @@ export const SettingsIntegrationNewDatabaseConnection = () => { try { const createdConnection = await createOneDatabaseConnection( - createRemoteServerInputSchema.parse({ + newConnectionSchema.parse({ ...formValues, foreignDataWrapperType: getForeignDataWrapperType(databaseKey), }), @@ -144,15 +158,15 @@ export const SettingsIntegrationNewDatabaseConnection = () => { onSave={handleSave} /> - {databaseKey === 'postgresql' ? ( -
- - -
- ) : null} +
+ + +
diff --git a/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationEditDatabaseConnection.stories.tsx b/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationEditDatabaseConnection.stories.tsx index 010d4c35711e..00e09088c0fb 100644 --- a/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationEditDatabaseConnection.stories.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/__stories__/SettingsIntegrationEditDatabaseConnection.stories.tsx @@ -35,6 +35,6 @@ export const Default: Story = { const canvas = within(canvasElement); sleep(100); - await canvas.findByText('Edit PostgreSQL Connection'); + await canvas.findByText('Edit Connection'); }, }; diff --git a/packages/twenty-front/src/testing/mock-data/remote-servers.ts b/packages/twenty-front/src/testing/mock-data/remote-servers.ts index f048392a0784..fee3c13cae5b 100644 --- a/packages/twenty-front/src/testing/mock-data/remote-servers.ts +++ b/packages/twenty-front/src/testing/mock-data/remote-servers.ts @@ -17,4 +17,15 @@ export const mockedRemoteServers = [ updatedAt: '2024-04-30T13:41:25.858Z', schema: 'public', }, + { + __typename: 'RemoteServer', + id: 'ddc3b641-2142-4b4e-8fba-976afbc3b2bc', + createdAt: '2024-04-30T13:41:25.584Z', + foreignDataWrapperId: 'dqfdsqf-2142-4b4e-8fba-976afbc3b2bc', + foreignDataWrapperOptions: { + api_key: 'sk_test_51', + }, + foreignDataWrapperType: 'stripe_fdw', + updatedAt: '2024-04-30T13:41:25.858Z', + }, ];