From d4a9a260692cfdcebbc42cb0c89036583db2ffc7 Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Mon, 8 Apr 2024 17:27:14 +0200 Subject: [PATCH] Delete connection from frontend (#4880) This PR: - creates the query to delete a connection - creates the hook that triggers the query - triggers the hook function when clicking on remove + get back to connection page --------- Co-authored-by: Thomas Trompette --- .../src/generated-metadata/gql.ts | 5 +++ .../src/generated-metadata/graphql.ts | 16 +++++++-- .../mutations/deleteOneDatabaseConnection.ts | 9 +++++ .../hooks/useDeleteOneDatabaseConnection.ts | 36 +++++++++++++++++++ .../SettingsIntegrationDatabaseConnection.tsx | 12 +++++++ ...tegrationDatabaseConnectionSummaryCard.tsx | 8 ++++- 6 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 packages/twenty-front/src/modules/databases/graphql/mutations/deleteOneDatabaseConnection.ts create mode 100644 packages/twenty-front/src/modules/databases/hooks/useDeleteOneDatabaseConnection.ts diff --git a/packages/twenty-front/src/generated-metadata/gql.ts b/packages/twenty-front/src/generated-metadata/gql.ts index d86971caa..dfdadbd8f 100644 --- a/packages/twenty-front/src/generated-metadata/gql.ts +++ b/packages/twenty-front/src/generated-metadata/gql.ts @@ -14,6 +14,7 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ */ const documents = { "\n mutation createServer($input: CreateRemoteServerInput!) {\n createOneRemoteServer(input: $input) {\n id\n foreignDataWrapperId\n foreignDataWrapperOptions\n foreignDataWrapperType\n }\n }\n": types.CreateServerDocument, + "\n mutation deleteServer($input: RemoteServerIdInput!) {\n deleteOneRemoteServer(input: $input) {\n id\n }\n }\n": types.DeleteServerDocument, "\n query GetManyDatabaseConnections($input: RemoteServerTypeInput!) {\n findManyRemoteServersByType(input: $input) {\n id\n createdAt\n foreignDataWrapperId\n foreignDataWrapperOptions\n foreignDataWrapperType\n updatedAt\n }\n }\n": types.GetManyDatabaseConnectionsDocument, "\n mutation CreateOneObjectMetadataItem($input: CreateOneObjectInput!) {\n createOneObject(input: $input) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n }\n }\n": types.CreateOneObjectMetadataItemDocument, "\n mutation CreateOneFieldMetadataItem($input: CreateOneFieldMetadataInput!) {\n createOneField(input: $input) {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n defaultValue\n options\n }\n }\n": types.CreateOneFieldMetadataItemDocument, @@ -43,6 +44,10 @@ export function graphql(source: string): unknown; * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql(source: "\n mutation createServer($input: CreateRemoteServerInput!) {\n createOneRemoteServer(input: $input) {\n id\n foreignDataWrapperId\n foreignDataWrapperOptions\n foreignDataWrapperType\n }\n }\n"): (typeof documents)["\n mutation createServer($input: CreateRemoteServerInput!) {\n createOneRemoteServer(input: $input) {\n id\n foreignDataWrapperId\n foreignDataWrapperOptions\n foreignDataWrapperType\n }\n }\n"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n mutation deleteServer($input: RemoteServerIdInput!) {\n deleteOneRemoteServer(input: $input) {\n id\n }\n }\n"): (typeof documents)["\n mutation deleteServer($input: RemoteServerIdInput!) {\n deleteOneRemoteServer(input: $input) {\n id\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index d9a5140dc..24c52a1a1 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -393,7 +393,8 @@ export type MutationActivateWorkspaceArgs = { export type MutationAuthorizeAppArgs = { clientId: Scalars['String']['input']; - codeChallenge: Scalars['String']['input']; + codeChallenge?: InputMaybe; + redirectUrl?: InputMaybe; }; @@ -632,7 +633,8 @@ export type QueryCheckWorkspaceInviteHashIsValidArgs = { export type QueryExchangeAuthorizationCodeArgs = { authorizationCode: Scalars['String']['input']; - codeVerifier: Scalars['String']['input']; + clientSecret?: InputMaybe; + codeVerifier?: InputMaybe; }; @@ -1037,7 +1039,7 @@ export type Workspace = { billingSubscriptions?: Maybe>; createdAt: Scalars['DateTime']['output']; currentBillingSubscription?: Maybe; - currentCacheVersion: Scalars['String']['output']; + currentCacheVersion?: Maybe; deletedAt?: Maybe; displayName?: Maybe; domainName?: Maybe; @@ -1195,6 +1197,13 @@ export type CreateServerMutationVariables = Exact<{ export type CreateServerMutation = { __typename?: 'Mutation', createOneRemoteServer: { __typename?: 'RemoteServer', id: string, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string } }; +export type DeleteServerMutationVariables = Exact<{ + input: RemoteServerIdInput; +}>; + + +export type DeleteServerMutation = { __typename?: 'Mutation', deleteOneRemoteServer: { __typename?: 'RemoteServer', id: string } }; + export type GetManyDatabaseConnectionsQueryVariables = Exact<{ input: RemoteServerTypeInput; }>; @@ -1263,6 +1272,7 @@ export type ObjectMetadataItemsQuery = { __typename?: 'Query', objects: { __type export const CreateServerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"createServer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateRemoteServerInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneRemoteServer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}}]}}]}}]} as unknown as DocumentNode; +export const DeleteServerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"deleteServer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServerIdInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneRemoteServer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode; export const GetManyDatabaseConnectionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetManyDatabaseConnections"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteServerTypeInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findManyRemoteServersByType"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperId"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperOptions"}},{"kind":"Field","name":{"kind":"Name","value":"foreignDataWrapperType"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode; export const CreateOneObjectMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneObjectMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneObjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}}]}}]}}]} as unknown as DocumentNode; export const CreateOneFieldMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneFieldMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneFieldMetadataInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneField"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"defaultValue"}},{"kind":"Field","name":{"kind":"Name","value":"options"}}]}}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/modules/databases/graphql/mutations/deleteOneDatabaseConnection.ts b/packages/twenty-front/src/modules/databases/graphql/mutations/deleteOneDatabaseConnection.ts new file mode 100644 index 000000000..c2f9974ba --- /dev/null +++ b/packages/twenty-front/src/modules/databases/graphql/mutations/deleteOneDatabaseConnection.ts @@ -0,0 +1,9 @@ +import { gql } from '@apollo/client'; + +export const DELETE_ONE_DATABASE_CONNECTION = gql` + mutation deleteServer($input: RemoteServerIdInput!) { + deleteOneRemoteServer(input: $input) { + id + } + } +`; diff --git a/packages/twenty-front/src/modules/databases/hooks/useDeleteOneDatabaseConnection.ts b/packages/twenty-front/src/modules/databases/hooks/useDeleteOneDatabaseConnection.ts new file mode 100644 index 000000000..eae2f4a42 --- /dev/null +++ b/packages/twenty-front/src/modules/databases/hooks/useDeleteOneDatabaseConnection.ts @@ -0,0 +1,36 @@ +import { ApolloClient, useMutation } from '@apollo/client'; +import { getOperationName } from '@apollo/client/utilities'; + +import { DELETE_ONE_DATABASE_CONNECTION } from '@/databases/graphql/mutations/deleteOneDatabaseConnection'; +import { GET_MANY_DATABASE_CONNECTIONS } from '@/databases/graphql/queries/findManyDatabaseConnections'; +import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient'; +import { + DeleteServerMutation, + DeleteServerMutationVariables, + RemoteServerIdInput, +} from '~/generated-metadata/graphql'; + +export const useDeleteOneDatabaseConnection = () => { + const apolloMetadataClient = useApolloMetadataClient(); + + const [mutate] = useMutation< + DeleteServerMutation, + DeleteServerMutationVariables + >(DELETE_ONE_DATABASE_CONNECTION, { + client: apolloMetadataClient ?? ({} as ApolloClient), + }); + + const deleteOneDatabaseConnection = async (input: RemoteServerIdInput) => { + return await mutate({ + variables: { + input, + }, + awaitRefetchQueries: true, + refetchQueries: [getOperationName(GET_MANY_DATABASE_CONNECTIONS) ?? ''], + }); + }; + + return { + deleteOneDatabaseConnection, + }; +}; diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnection.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnection.tsx index c84390bd8..7043594d9 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnection.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnection.tsx @@ -4,6 +4,7 @@ import { useNavigate, useParams } from 'react-router-dom'; import { zodResolver } from '@hookform/resolvers/zod'; import { IconSettings } from 'twenty-ui'; +import { useDeleteOneDatabaseConnection } from '@/databases/hooks/useDeleteOneDatabaseConnection'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SettingsIntegrationDatabaseTablesListCard, @@ -48,6 +49,16 @@ export const SettingsIntegrationDatabaseConnection = () => { )?.connections || []; const connection = connections.find(({ key }) => key === connectionKey); + const { deleteOneDatabaseConnection } = useDeleteOneDatabaseConnection(); + + const deleteConnection = async () => { + if (!connection) return; + + await deleteOneDatabaseConnection({ id: connection.id }); + + navigate(`${settingsIntegrationsPagePath}/${databaseKey}`); + }; + useEffect(() => { if (!isIntegrationAvailable || !connection) { navigate(AppPath.NotFound); @@ -91,6 +102,7 @@ export const SettingsIntegrationDatabaseConnection = () => { databaseLogoUrl={integration.from.image} connectionName={connection.name} connectedTablesNb={tables.length} + onRemove={deleteConnection} />
diff --git a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnectionSummaryCard.tsx b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnectionSummaryCard.tsx index 216d3625c..4d2dd3084 100644 --- a/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnectionSummaryCard.tsx +++ b/packages/twenty-front/src/pages/settings/integrations/SettingsIntegrationDatabaseConnectionSummaryCard.tsx @@ -13,6 +13,7 @@ type SettingsIntegrationDatabaseConnectionSummaryCardProps = { databaseLogoUrl: string; connectionName: string; connectedTablesNb: number; + onRemove: () => void; }; const StyledDatabaseLogoContainer = styled.div` @@ -31,6 +32,7 @@ export const SettingsIntegrationDatabaseConnectionSummaryCard = ({ databaseLogoUrl, connectionName, connectedTablesNb, + onRemove, }: SettingsIntegrationDatabaseConnectionSummaryCardProps) => { const dropdownId = 'settings-integration-database-connection-summary-card-dropdown'; @@ -59,7 +61,11 @@ export const SettingsIntegrationDatabaseConnectionSummaryCard = ({ dropdownComponents={ - + }