diff --git a/packages/api/src/generated/graphql.ts b/packages/api/src/generated/graphql.ts index 7f25a12d1..7826942eb 100644 --- a/packages/api/src/generated/graphql.ts +++ b/packages/api/src/generated/graphql.ts @@ -2161,7 +2161,7 @@ export type QueryGetDiscoverFeedArticlesArgs = { export type QueryIntegrationArgs = { - id: Scalars['ID']; + name: Scalars['String']; }; @@ -6175,7 +6175,7 @@ export type QueryResolvers; groups?: Resolver; hello?: Resolver, ParentType, ContextType>; - integration?: Resolver>; + integration?: Resolver>; integrations?: Resolver; labels?: Resolver; me?: Resolver, ParentType, ContextType>; diff --git a/packages/api/src/generated/schema.graphql b/packages/api/src/generated/schema.graphql index 865e0cb6e..3316218ba 100644 --- a/packages/api/src/generated/schema.graphql +++ b/packages/api/src/generated/schema.graphql @@ -1605,7 +1605,7 @@ type Query { getUserPersonalization: GetUserPersonalizationResult! groups: GroupsResult! hello: String - integration(id: ID!): IntegrationResult! + integration(name: String!): IntegrationResult! integrations: IntegrationsResult! labels: LabelsResult! me: User diff --git a/packages/api/src/resolvers/integrations/index.ts b/packages/api/src/resolvers/integrations/index.ts index ffc11e4f8..0f186bc36 100644 --- a/packages/api/src/resolvers/integrations/index.ts +++ b/packages/api/src/resolvers/integrations/index.ts @@ -28,6 +28,7 @@ import { import { createIntegrationToken } from '../../routers/auth/jwt_helpers' import { findIntegration, + findIntegrationByName, findIntegrations, getIntegrationClient, removeIntegration, @@ -115,11 +116,11 @@ export const integrationResolver = authorized< IntegrationSuccess, IntegrationError, QueryIntegrationArgs ->(async (_, { id }, { uid, log }) => { - const integration = await findIntegration({ id }, uid) +>(async (_, { name }, { uid, log }) => { + const integration = await findIntegrationByName(name, uid) if (!integration) { - log.error('integration not found', id) + log.error('integration not found', name) return { errorCodes: [IntegrationErrorCode.NotFound], diff --git a/packages/api/src/schema.ts b/packages/api/src/schema.ts index 1effa7a57..7819035ac 100755 --- a/packages/api/src/schema.ts +++ b/packages/api/src/schema.ts @@ -3205,7 +3205,7 @@ const schema = gql` sort: SortParams folder: String ): UpdatesSinceResult! - integration(id: ID!): IntegrationResult! + integration(name: String!): IntegrationResult! integrations: IntegrationsResult! recentSearches: RecentSearchesResult! rules(enabled: Boolean): RulesResult! diff --git a/packages/api/src/services/integrations/index.ts b/packages/api/src/services/integrations/index.ts index 2f2b99f0d..40e83fd0b 100644 --- a/packages/api/src/services/integrations/index.ts +++ b/packages/api/src/services/integrations/index.ts @@ -60,6 +60,22 @@ export const findIntegration = async ( ) } +export const findIntegrationByName = async (name: string, userId: string) => { + return authTrx( + async (t) => + t + .getRepository(Integration) + .createQueryBuilder() + .where({ + user: { id: userId }, + }) + .andWhere('LOWER(name) = LOWER(:name)', { name }) // case insensitive + .getOne(), + undefined, + userId + ) +} + export const findIntegrations = async ( userId: string, where?: FindOptionsWhere | FindOptionsWhere[] diff --git a/packages/api/test/resolvers/integrations.test.ts b/packages/api/test/resolvers/integrations.test.ts index ac85cf48b..bc716e915 100644 --- a/packages/api/test/resolvers/integrations.test.ts +++ b/packages/api/test/resolvers/integrations.test.ts @@ -406,8 +406,8 @@ describe('Integrations resolvers', () => { describe('integration API', () => { const query = ` - query Integration ($id: ID!) { - integration(id: $id) { + query Integration ($name: String!) { + integration(name: $name) { ... on IntegrationSuccess { integration { id @@ -441,7 +441,7 @@ describe('Integrations resolvers', () => { it('returns the integration', async () => { const res = await graphqlRequest(query, authToken, { - id: existingIntegration.id, + name: existingIntegration.name, }) expect(res.body.data.integration.integration.id).to.equal( existingIntegration.id diff --git a/packages/web/lib/networking/queries/useGetIntegrationQuery.tsx b/packages/web/lib/networking/queries/useGetIntegrationQuery.tsx new file mode 100644 index 000000000..ee16f5097 --- /dev/null +++ b/packages/web/lib/networking/queries/useGetIntegrationQuery.tsx @@ -0,0 +1,68 @@ +import { gql } from 'graphql-request' +import useSWR from 'swr' +import { makeGqlFetcher } from '../networkHelpers' +import { Integration } from './useGetIntegrationsQuery' + +interface IntegrationQueryResponse { + isValidating: boolean + integration: Integration | null + revalidate: () => void +} + +interface IntegrationQueryResponseData { + integration: IntegrationData +} + +interface IntegrationData { + integration: unknown +} + +export function useGetIntegrationQuery(name: string): IntegrationQueryResponse { + const query = gql` + query GetIntegration($name: String!) { + integration(name: $name) { + ... on IntegrationSuccess { + integration { + id + name + type + token + enabled + createdAt + updatedAt + taskName + settings + } + } + ... on IntegrationError { + errorCodes + } + } + } + ` + + const { data, mutate, isValidating } = useSWR(query, makeGqlFetcher({ name })) + try { + if (data) { + const result = data as IntegrationQueryResponseData + const integration = result.integration.integration as Integration + return { + isValidating, + integration, + revalidate: () => { + mutate() + }, + } + } + } catch (error) { + console.log('error', error) + } + + return { + isValidating: false, + integration: null, + revalidate: () => { + mutate() + }, + } +} diff --git a/packages/web/pages/settings/integrations/notion.tsx b/packages/web/pages/settings/integrations/notion.tsx index e4f68a5ca..733c97a66 100644 --- a/packages/web/pages/settings/integrations/notion.tsx +++ b/packages/web/pages/settings/integrations/notion.tsx @@ -12,7 +12,7 @@ import 'antd/dist/antd.compact.css' import { CheckboxValueType } from 'antd/lib/checkbox/Group' import Image from 'next/image' import { useRouter } from 'next/router' -import { useEffect, useMemo } from 'react' +import { useEffect } from 'react' import { HStack, VStack } from '../../../components/elements/LayoutPrimitives' import { PageMetaData } from '../../../components/patterns/PageMetaData' import { Beta } from '../../../components/templates/Beta' @@ -20,7 +20,7 @@ import { Header } from '../../../components/templates/settings/SettingsTable' import { SettingsLayout } from '../../../components/templates/SettingsLayout' import { deleteIntegrationMutation } from '../../../lib/networking/mutations/deleteIntegrationMutation' import { setIntegrationMutation } from '../../../lib/networking/mutations/setIntegrationMutation' -import { useGetIntegrationsQuery } from '../../../lib/networking/queries/useGetIntegrationsQuery' +import { useGetIntegrationQuery } from '../../../lib/networking/queries/useGetIntegrationQuery' import { applyStoredTheme } from '../../../lib/themeUpdater' import { showSuccessToast } from '../../../lib/toastHelpers' @@ -35,10 +35,7 @@ export default function Notion(): JSX.Element { applyStoredTheme() const router = useRouter() - const { integrations, revalidate } = useGetIntegrationsQuery() - const notion = useMemo(() => { - return integrations.find((i) => i.name == 'NOTION' && i.type == 'EXPORT') - }, [integrations]) + const { integration: notion, revalidate } = useGetIntegrationQuery('notion') const [form] = Form.useForm() const [messageApi, contextHolder] = message.useMessage()