From 7e01843aafc812d82a5c249d0e497a9ee1c0766e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Fri, 9 Aug 2024 11:09:26 +0200 Subject: [PATCH] Remove dead code linked to quick actions (#6587) Removing dead code, we'll take another approach to build this --- .../useExecuteQuickActionOnOneRecord.ts | 16 -- .../useExecuteQuickActionOnOneRecord.test.tsx | 62 ------ ...uteQuickActionOnOneRecordMutation.test.tsx | 40 ---- .../hooks/useExecuteQuickActionOnOneRecord.ts | 57 ------ ...seExecuteQuickActionOnOneRecordMutation.ts | 53 ----- .../hooks/useRecordActionBar.tsx | 47 +---- .../modules/workspace/types/FeatureFlagKey.ts | 1 - ...te-quick-action-on-one-resolver.factory.ts | 80 -------- .../factories/factories.ts | 11 +- .../workspace-resolvers-builder.interface.ts | 5 - .../workspace-resolver-builder.module.ts | 3 +- .../workspace-resolver.factory.ts | 15 +- .../utils/__tests__/get-resolver-args.spec.ts | 3 - .../utils/get-resolver-args.util.ts | 9 +- .../quick-actions/intelligence.service.ts | 55 ------ .../interfaces/company.interface.ts | 3 - .../quick-actions/quick-actions.module.ts | 14 -- .../quick-actions/quick-actions.service.ts | 181 ------------------ .../environment/environment-variables.ts | 30 ++- .../utils/__tests__/get-resolver-name.spec.ts | 1 - .../engine/utils/get-resolver-name.util.ts | 2 - 21 files changed, 33 insertions(+), 655 deletions(-) delete mode 100644 packages/twenty-front/src/modules/object-record/hooks/__mocks__/useExecuteQuickActionOnOneRecord.ts delete mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecord.test.tsx delete mode 100644 packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecordMutation.test.tsx delete mode 100644 packages/twenty-front/src/modules/object-record/hooks/useExecuteQuickActionOnOneRecord.ts delete mode 100644 packages/twenty-front/src/modules/object-record/hooks/useExecuteQuickActionOnOneRecordMutation.ts delete mode 100644 packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/execute-quick-action-on-one-resolver.factory.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/quick-actions/intelligence.service.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/quick-actions/interfaces/company.interface.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/quick-actions/quick-actions.module.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/quick-actions/quick-actions.service.ts diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useExecuteQuickActionOnOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useExecuteQuickActionOnOneRecord.ts deleted file mode 100644 index 65a05a028..000000000 --- a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/useExecuteQuickActionOnOneRecord.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { PERSON_FRAGMENT } from '@/object-record/hooks/__mocks__/personFragment'; -import { gql } from '@apollo/client'; - -export { responseData } from './useUpdateOneRecord'; - -export const query = gql` - mutation ExecuteQuickActionOnOnePerson($idToExecuteQuickActionOn: ID!) { - executeQuickActionOnPerson(id: $idToExecuteQuickActionOn) { - ${PERSON_FRAGMENT} - } - } -`; - -export const variables = { - idToExecuteQuickActionOn: 'a7286b9a-c039-4a89-9567-2dfa7953cda9', -}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecord.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecord.test.tsx deleted file mode 100644 index 100825c3e..000000000 --- a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecord.test.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { ReactNode } from 'react'; -import { MockedProvider } from '@apollo/client/testing'; -import { act, renderHook } from '@testing-library/react'; -import { RecoilRoot } from 'recoil'; - -import { - query, - responseData, - variables, -} from '@/object-record/hooks/__mocks__/useExecuteQuickActionOnOneRecord'; -import { useExecuteQuickActionOnOneRecord } from '@/object-record/hooks/useExecuteQuickActionOnOneRecord'; - -const idToExecuteQuickActionOn = 'a7286b9a-c039-4a89-9567-2dfa7953cda9'; - -const mocks = [ - { - request: { - query, - variables, - }, - result: jest.fn(() => ({ - data: { - executeQuickActionOnPerson: { - ...responseData, - id: idToExecuteQuickActionOn, - }, - }, - })), - }, -]; - -const Wrapper = ({ children }: { children: ReactNode }) => ( - - - {children} - - -); - -describe('useExecuteQuickActionOnOneRecord', () => { - it('should work as expected', async () => { - const { result } = renderHook( - () => - useExecuteQuickActionOnOneRecord({ - objectNameSingular: 'person', - }), - { - wrapper: Wrapper, - }, - ); - - await act(async () => { - const res = await result.current.executeQuickActionOnOneRecord( - idToExecuteQuickActionOn, - ); - - expect(res).toHaveProperty('id', idToExecuteQuickActionOn); - }); - - expect(mocks[0].result).toHaveBeenCalled(); - }); -}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecordMutation.test.tsx b/packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecordMutation.test.tsx deleted file mode 100644 index b48a31a8d..000000000 --- a/packages/twenty-front/src/modules/object-record/hooks/__tests__/useExecuteQuickActionOnOneRecordMutation.test.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { renderHook } from '@testing-library/react'; -import { print } from 'graphql'; -import { RecoilRoot } from 'recoil'; - -import { PERSON_FRAGMENT } from '@/object-record/hooks/__mocks__/personFragment'; -import { useExecuteQuickActionOnOneRecordMutation } from '@/object-record/hooks/useExecuteQuickActionOnOneRecordMutation'; - -const expectedQueryTemplate = ` - mutation ExecuteQuickActionOnOnePerson($idToExecuteQuickActionOn: ID!) { - executeQuickActionOnPerson(id: $idToExecuteQuickActionOn) { - ${PERSON_FRAGMENT} - } - } -`.replace(/\s/g, ''); - -describe('useExecuteQuickActionOnOneRecordMutation', () => { - it('should return a valid executeQuickActionOnOneRecordMutation', () => { - const objectNameSingular = 'person'; - - const { result } = renderHook( - () => - useExecuteQuickActionOnOneRecordMutation({ - objectNameSingular, - }), - { - wrapper: RecoilRoot, - }, - ); - - const { executeQuickActionOnOneRecordMutation } = result.current; - - expect(executeQuickActionOnOneRecordMutation).toBeDefined(); - - const printedReceivedQuery = print( - executeQuickActionOnOneRecordMutation, - ).replace(/\s/g, ''); - - expect(printedReceivedQuery).toEqual(expectedQueryTemplate); - }); -}); diff --git a/packages/twenty-front/src/modules/object-record/hooks/useExecuteQuickActionOnOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/useExecuteQuickActionOnOneRecord.ts deleted file mode 100644 index 10b67d641..000000000 --- a/packages/twenty-front/src/modules/object-record/hooks/useExecuteQuickActionOnOneRecord.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { useCallback } from 'react'; -import { useApolloClient } from '@apollo/client'; -import { getOperationName } from '@apollo/client/utilities'; - -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { useExecuteQuickActionOnOneRecordMutation } from '@/object-record/hooks/useExecuteQuickActionOnOneRecordMutation'; -import { useFindManyRecordsQuery } from '@/object-record/hooks/useFindManyRecordsQuery'; -import { capitalize } from '~/utils/string/capitalize'; - -type useExecuteQuickActionOnOneRecordProps = { - objectNameSingular: string; -}; - -export const useExecuteQuickActionOnOneRecord = ({ - objectNameSingular, -}: useExecuteQuickActionOnOneRecordProps) => { - const { objectMetadataItem } = useObjectMetadataItem({ - objectNameSingular, - }); - - const { executeQuickActionOnOneRecordMutation } = - useExecuteQuickActionOnOneRecordMutation({ - objectNameSingular, - }); - - const { findManyRecordsQuery } = useFindManyRecordsQuery({ - objectNameSingular, - }); - - const apolloClient = useApolloClient(); - - const executeQuickActionOnOneRecord = useCallback( - async (idToExecuteQuickActionOn: string) => { - const executeQuickActionOnRecord = await apolloClient.mutate({ - mutation: executeQuickActionOnOneRecordMutation, - variables: { - idToExecuteQuickActionOn, - }, - refetchQueries: [getOperationName(findManyRecordsQuery) ?? ''], - }); - - return executeQuickActionOnRecord.data[ - `executeQuickActionOn${capitalize(objectMetadataItem.nameSingular)}` - ] as T; - }, - [ - objectMetadataItem.nameSingular, - apolloClient, - executeQuickActionOnOneRecordMutation, - findManyRecordsQuery, - ], - ); - - return { - executeQuickActionOnOneRecord, - }; -}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/useExecuteQuickActionOnOneRecordMutation.ts b/packages/twenty-front/src/modules/object-record/hooks/useExecuteQuickActionOnOneRecordMutation.ts deleted file mode 100644 index 4785029e8..000000000 --- a/packages/twenty-front/src/modules/object-record/hooks/useExecuteQuickActionOnOneRecordMutation.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { gql } from '@apollo/client'; -import { useRecoilValue } from 'recoil'; - -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; -import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery'; -import { EMPTY_MUTATION } from '@/object-record/constants/EmptyMutation'; -import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; -import { capitalize } from '~/utils/string/capitalize'; - -export const getExecuteQuickActionOnOneRecordMutationGraphQLField = ({ - objectNameSingular, -}: { - objectNameSingular: string; -}) => { - return `executeQuickActionOn${capitalize(objectNameSingular)}`; -}; - -export const useExecuteQuickActionOnOneRecordMutation = ({ - objectNameSingular, -}: { - objectNameSingular: string; -}) => { - const { objectMetadataItem } = useObjectMetadataItem({ - objectNameSingular, - }); - - const objectMetadataItems = useRecoilValue(objectMetadataItemsState); - - if (isUndefinedOrNull(objectMetadataItem)) { - return { executeQuickActionOnOneRecordMutation: EMPTY_MUTATION }; - } - - const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular); - - const graphQLFieldForExecuteQuickActionOnOneRecordMutation = - getExecuteQuickActionOnOneRecordMutationGraphQLField({ - objectNameSingular: objectMetadataItem.nameSingular, - }); - - const executeQuickActionOnOneRecordMutation = gql` - mutation ExecuteQuickActionOnOne${capitalizedObjectName}($idToExecuteQuickActionOn: ID!) { - ${graphQLFieldForExecuteQuickActionOnOneRecordMutation}(id: $idToExecuteQuickActionOn) ${mapObjectMetadataToGraphQLQuery( - { - objectMetadataItems, - objectMetadataItem, - }, - )} - } - `; - - return { executeQuickActionOnOneRecordMutation }; -}; diff --git a/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx b/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx index 77bf9bf09..24230af6b 100644 --- a/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx +++ b/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx @@ -1,20 +1,11 @@ import { isNonEmptyString } from '@sniptt/guards'; import { useCallback, useMemo, useState } from 'react'; import { useRecoilCallback, useSetRecoilState } from 'recoil'; -import { - IconClick, - IconFileExport, - IconHeart, - IconHeartOff, - IconMail, - IconPuzzle, - IconTrash, -} from 'twenty-ui'; +import { IconFileExport, IconHeart, IconHeartOff, IconTrash } from 'twenty-ui'; import { useFavorites } from '@/favorites/hooks/useFavorites'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { DELETE_MAX_COUNT } from '@/object-record/constants/DeleteMaxCount'; -import { useExecuteQuickActionOnOneRecord } from '@/object-record/hooks/useExecuteQuickActionOnOneRecord'; import { useDeleteTableData } from '@/object-record/record-index/options/hooks/useDeleteTableData'; import { displayedExportProgress, @@ -25,7 +16,6 @@ import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModa import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState'; import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState'; import { ContextMenuEntry } from '@/ui/navigation/context-menu/types/ContextMenuEntry'; -import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { isDefined } from '~/utils/isDefined'; type useRecordActionBarProps = { @@ -48,10 +38,6 @@ export const useRecordActionBar = ({ const { createFavorite, favorites, deleteFavorite } = useFavorites(); - const { executeQuickActionOnOneRecord } = useExecuteQuickActionOnOneRecord({ - objectNameSingular: objectMetadataItem.nameSingular, - }); - const handleFavoriteButtonClick = useRecoilCallback( ({ snapshot }) => () => { @@ -99,15 +85,6 @@ export const useRecordActionBar = ({ deleteTableData(selectedRecordIds); }, [deleteTableData, selectedRecordIds]); - const handleExecuteQuickActionOnClick = useCallback(async () => { - callback?.(); - await Promise.all( - selectedRecordIds.map(async (recordId) => { - await executeQuickActionOnOneRecord(recordId); - }), - ); - }, [callback, executeQuickActionOnOneRecord, selectedRecordIds]); - const { progress, download } = useExportTableData({ ...baseTableDataParams, filename: `${objectMetadataItem.nameSingular}.csv`, @@ -168,10 +145,6 @@ export const useRecordActionBar = ({ ], ); - const dataExecuteQuickActionOnmentEnabled = useIsFeatureEnabled( - 'IS_QUICK_ACTIONS_ENABLED', - ); - const hasOnlyOneRecordSelected = selectedRecordIds.length === 1; const isFavorite = @@ -212,12 +185,13 @@ export const useRecordActionBar = ({ setActionBarEntries: useCallback(() => { setActionBarEntriesState([ - ...(dataExecuteQuickActionOnmentEnabled - ? [ + /* { label: 'Actions', Icon: IconClick, - subActions: [ + subActions: + + /* [ { label: 'Enrich', Icon: IconPuzzle, @@ -228,16 +202,9 @@ export const useRecordActionBar = ({ Icon: IconMail, }, ], - }, - ] - : []), + */ ...menuActions, ]); - }, [ - menuActions, - dataExecuteQuickActionOnmentEnabled, - handleExecuteQuickActionOnClick, - setActionBarEntriesState, - ]), + }, [menuActions, setActionBarEntriesState]), }; }; diff --git a/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts b/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts index 53f29d4b2..1185aa04f 100644 --- a/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts +++ b/packages/twenty-front/src/modules/workspace/types/FeatureFlagKey.ts @@ -1,6 +1,5 @@ export type FeatureFlagKey = | 'IS_BLOCKLIST_ENABLED' - | 'IS_QUICK_ACTIONS_ENABLED' | 'IS_EVENT_OBJECT_ENABLED' | 'IS_AIRTABLE_INTEGRATION_ENABLED' | 'IS_POSTGRESQL_INTEGRATION_ENABLED' diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/execute-quick-action-on-one-resolver.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/execute-quick-action-on-one-resolver.factory.ts deleted file mode 100644 index 278dea7f5..000000000 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/execute-quick-action-on-one-resolver.factory.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; -import { WorkspaceQueryRunnerOptions } from 'src/engine/api/graphql/workspace-query-runner/interfaces/query-runner-option.interface'; -import { WorkspaceResolverBuilderFactoryInterface } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolver-builder-factory.interface'; -import { - DeleteOneResolverArgs, - ExecuteQuickActionOnOneResolverArgs, - FindOneResolverArgs, - Resolver, -} from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; -import { WorkspaceSchemaBuilderContext } from 'src/engine/api/graphql/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface'; - -import { workspaceQueryRunnerGraphqlApiExceptionHandler } from 'src/engine/api/graphql/workspace-query-runner/utils/workspace-query-runner-graphql-api-exception-handler.util'; -import { WorkspaceQueryRunnerService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service'; -import { QuickActionsService } from 'src/engine/core-modules/quick-actions/quick-actions.service'; - -@Injectable() -export class ExecuteQuickActionOnOneResolverFactory - implements WorkspaceResolverBuilderFactoryInterface -{ - public static methodName = 'executeQuickActionOnOne' as const; - - constructor( - private readonly workspaceQueryRunnerService: WorkspaceQueryRunnerService, - private readonly quickActionsService: QuickActionsService, - ) {} - - create( - context: WorkspaceSchemaBuilderContext, - ): Resolver { - const internalContext = context; - - return (_source, args, context, info) => { - try { - return this.executeQuickActionOnOne(args, { - authContext: internalContext.authContext, - objectMetadataItem: internalContext.objectMetadataItem, - info, - fieldMetadataCollection: internalContext.fieldMetadataCollection, - objectMetadataCollection: internalContext.objectMetadataCollection, - }); - } catch (error) { - workspaceQueryRunnerGraphqlApiExceptionHandler(error); - } - }; - } - - private async executeQuickActionOnOne( - args: DeleteOneResolverArgs, - options: WorkspaceQueryRunnerOptions, - ): Promise { - switch (options.objectMetadataItem.nameSingular) { - case 'company': { - await this.quickActionsService.executeQuickActionOnCompany( - args.id, - options.authContext.workspace.id, - options.objectMetadataItem, - ); - break; - } - case 'person': { - await this.quickActionsService.createCompanyFromPerson( - args.id, - options.authContext.workspace.id, - options.objectMetadataCollection, - ); - break; - } - default: - // TODO: different quick actions per object on frontend - break; - } - - return this.workspaceQueryRunnerService.findOne( - { filter: { id: { eq: args.id } } } as FindOneResolverArgs, - options, - ); - } -} diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/factories.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/factories.ts index 9bd0f4432..2f4a88b34 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/factories.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/factories/factories.ts @@ -1,14 +1,13 @@ import { UpdateManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/update-many-resolver.factory'; +import { CreateManyResolverFactory } from './create-many-resolver.factory'; +import { CreateOneResolverFactory } from './create-one-resolver.factory'; +import { DeleteManyResolverFactory } from './delete-many-resolver.factory'; +import { DeleteOneResolverFactory } from './delete-one-resolver.factory'; import { FindDuplicatesResolverFactory } from './find-duplicates-resolver.factory'; import { FindManyResolverFactory } from './find-many-resolver.factory'; import { FindOneResolverFactory } from './find-one-resolver.factory'; -import { CreateManyResolverFactory } from './create-many-resolver.factory'; -import { CreateOneResolverFactory } from './create-one-resolver.factory'; import { UpdateOneResolverFactory } from './update-one-resolver.factory'; -import { DeleteOneResolverFactory } from './delete-one-resolver.factory'; -import { DeleteManyResolverFactory } from './delete-many-resolver.factory'; -import { ExecuteQuickActionOnOneResolverFactory } from './execute-quick-action-on-one-resolver.factory'; export const workspaceResolverBuilderFactories = [ FindManyResolverFactory, @@ -18,7 +17,6 @@ export const workspaceResolverBuilderFactories = [ CreateOneResolverFactory, UpdateOneResolverFactory, DeleteOneResolverFactory, - ExecuteQuickActionOnOneResolverFactory, UpdateManyResolverFactory, DeleteManyResolverFactory, ]; @@ -34,7 +32,6 @@ export const workspaceResolverBuilderMethodNames = { CreateOneResolverFactory.methodName, UpdateOneResolverFactory.methodName, DeleteOneResolverFactory.methodName, - ExecuteQuickActionOnOneResolverFactory.methodName, UpdateManyResolverFactory.methodName, DeleteManyResolverFactory.methodName, ], diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts index a2db90947..2727a3fdc 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface.ts @@ -20,7 +20,6 @@ export enum ResolverArgsType { UpdateMany = 'UpdateMany', DeleteOne = 'DeleteOne', DeleteMany = 'DeleteMany', - ExecuteQuickActionOnOne = 'ExecuteQuickActionOnOne', } export interface FindManyResolverArgs< @@ -79,10 +78,6 @@ export interface DeleteOneResolverArgs { id: string; } -export interface ExecuteQuickActionOnOneResolverArgs { - id: string; -} - export interface DeleteManyResolverArgs { filter: Filter; } diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module.ts index 85a84f17a..7b87e49a8 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module.ts @@ -1,14 +1,13 @@ import { Module } from '@nestjs/common'; import { WorkspaceQueryRunnerModule } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module'; -import { QuickActionsModule } from 'src/engine/core-modules/quick-actions/quick-actions.module'; import { WorkspaceResolverFactory } from './workspace-resolver.factory'; import { workspaceResolverBuilderFactories } from './factories/factories'; @Module({ - imports: [WorkspaceQueryRunnerModule, QuickActionsModule], + imports: [WorkspaceQueryRunnerModule], providers: [...workspaceResolverBuilderFactories, WorkspaceResolverFactory], exports: [WorkspaceResolverFactory], }) diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory.ts b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory.ts index 87e94673e..7fed8b96c 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory.ts @@ -4,24 +4,23 @@ import { IResolvers } from '@graphql-tools/utils'; import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; -import { getResolverName } from 'src/engine/utils/get-resolver-name.util'; -import { UpdateManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/update-many-resolver.factory'; import { DeleteManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/delete-many-resolver.factory'; -import { ExecuteQuickActionOnOneResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/execute-quick-action-on-one-resolver.factory'; +import { UpdateManyResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/factories/update-many-resolver.factory'; import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type'; +import { getResolverName } from 'src/engine/utils/get-resolver-name.util'; +import { CreateManyResolverFactory } from './factories/create-many-resolver.factory'; +import { CreateOneResolverFactory } from './factories/create-one-resolver.factory'; +import { DeleteOneResolverFactory } from './factories/delete-one-resolver.factory'; import { FindDuplicatesResolverFactory } from './factories/find-duplicates-resolver.factory'; import { FindManyResolverFactory } from './factories/find-many-resolver.factory'; import { FindOneResolverFactory } from './factories/find-one-resolver.factory'; -import { CreateManyResolverFactory } from './factories/create-many-resolver.factory'; -import { CreateOneResolverFactory } from './factories/create-one-resolver.factory'; import { UpdateOneResolverFactory } from './factories/update-one-resolver.factory'; -import { DeleteOneResolverFactory } from './factories/delete-one-resolver.factory'; +import { WorkspaceResolverBuilderFactoryInterface } from './interfaces/workspace-resolver-builder-factory.interface'; import { WorkspaceResolverBuilderMethodNames, WorkspaceResolverBuilderMethods, } from './interfaces/workspace-resolvers-builder.interface'; -import { WorkspaceResolverBuilderFactoryInterface } from './interfaces/workspace-resolver-builder-factory.interface'; @Injectable() export class WorkspaceResolverFactory { @@ -35,7 +34,6 @@ export class WorkspaceResolverFactory { private readonly createOneResolverFactory: CreateOneResolverFactory, private readonly updateOneResolverFactory: UpdateOneResolverFactory, private readonly deleteOneResolverFactory: DeleteOneResolverFactory, - private readonly executeQuickActionOnOneResolverFactory: ExecuteQuickActionOnOneResolverFactory, private readonly updateManyResolverFactory: UpdateManyResolverFactory, private readonly deleteManyResolverFactory: DeleteManyResolverFactory, ) {} @@ -56,7 +54,6 @@ export class WorkspaceResolverFactory { ['createOne', this.createOneResolverFactory], ['updateOne', this.updateOneResolverFactory], ['deleteOne', this.deleteOneResolverFactory], - ['executeQuickActionOnOne', this.executeQuickActionOnOneResolverFactory], ['updateMany', this.updateManyResolverFactory], ['deleteMany', this.deleteManyResolverFactory], ]); diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/__tests__/get-resolver-args.spec.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/__tests__/get-resolver-args.spec.ts index 26652d04a..72a9de127 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/__tests__/get-resolver-args.spec.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/__tests__/get-resolver-args.spec.ts @@ -50,9 +50,6 @@ describe('getResolverArgs', () => { deleteOne: { id: { type: GraphQLID, isNullable: false }, }, - executeQuickActionOnOne: { - id: { type: GraphQLID, isNullable: false }, - }, }; // Test each resolver type diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/get-resolver-args.util.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/get-resolver-args.util.ts index 609f268fd..a279282b5 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/get-resolver-args.util.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/utils/get-resolver-args.util.ts @@ -1,4 +1,4 @@ -import { GraphQLString, GraphQLInt, GraphQLID, GraphQLBoolean } from 'graphql'; +import { GraphQLBoolean, GraphQLID, GraphQLInt, GraphQLString } from 'graphql'; import { WorkspaceResolverBuilderMethodNames } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { ArgMetadata } from 'src/engine/api/graphql/workspace-schema-builder/interfaces/param-metadata.interface'; @@ -105,13 +105,6 @@ export const getResolverArgs = ( isNullable: false, }, }; - case 'executeQuickActionOnOne': - return { - id: { - type: GraphQLID, - isNullable: false, - }, - }; case 'updateMany': return { data: { diff --git a/packages/twenty-server/src/engine/core-modules/quick-actions/intelligence.service.ts b/packages/twenty-server/src/engine/core-modules/quick-actions/intelligence.service.ts deleted file mode 100644 index 74c4d252f..000000000 --- a/packages/twenty-server/src/engine/core-modules/quick-actions/intelligence.service.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { HttpService } from '@nestjs/axios'; -import { Injectable } from '@nestjs/common'; - -import { CompanyInteface } from 'src/engine/core-modules/quick-actions/interfaces/company.interface'; - -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; - -@Injectable() -export class IntelligenceService { - constructor( - private readonly environmentService: EnvironmentService, - private readonly httpService: HttpService, - ) {} - - async enrichCompany(domainName: string): Promise { - const enrichedCompany = await this.httpService.axiosRef.get( - `https://companies.twenty.com/${domainName}`, - { - validateStatus: function () { - // This ensures the promise is always resolved, preventing axios from throwing an error - return true; - }, - }, - ); - - if (enrichedCompany.status !== 200) { - return {}; - } - - return { - linkedinLinkPrimaryLinkUrl: - `https://linkedin.com/` + enrichedCompany.data.handle, - }; - } - - async completeWithAi(content: string) { - return this.httpService.axiosRef.post( - 'https://openrouter.ai/api/v1/chat/completions', - { - headers: { - Authorization: `Bearer ${this.environmentService.get( - 'OPENROUTER_API_KEY', - )}`, - 'HTTP-Referer': `https://twenty.com`, - 'X-Title': `Twenty CRM`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - model: 'mistralai/mixtral-8x7b-instruct', - messages: [{ role: 'user', content: content }], - }), - }, - ); - } -} diff --git a/packages/twenty-server/src/engine/core-modules/quick-actions/interfaces/company.interface.ts b/packages/twenty-server/src/engine/core-modules/quick-actions/interfaces/company.interface.ts deleted file mode 100644 index 0b765beb0..000000000 --- a/packages/twenty-server/src/engine/core-modules/quick-actions/interfaces/company.interface.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface CompanyInteface { - linkedinLinkPrimaryLinkUrl?: string; -} diff --git a/packages/twenty-server/src/engine/core-modules/quick-actions/quick-actions.module.ts b/packages/twenty-server/src/engine/core-modules/quick-actions/quick-actions.module.ts deleted file mode 100644 index 95fa48dbc..000000000 --- a/packages/twenty-server/src/engine/core-modules/quick-actions/quick-actions.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Module } from '@nestjs/common'; -import { HttpModule } from '@nestjs/axios'; - -import { IntelligenceService } from 'src/engine/core-modules/quick-actions/intelligence.service'; -import { QuickActionsService } from 'src/engine/core-modules/quick-actions/quick-actions.service'; -import { WorkspaceQueryRunnerModule } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.module'; - -@Module({ - imports: [WorkspaceQueryRunnerModule, HttpModule], - controllers: [], - providers: [QuickActionsService, IntelligenceService], - exports: [QuickActionsService, IntelligenceService], -}) -export class QuickActionsModule {} diff --git a/packages/twenty-server/src/engine/core-modules/quick-actions/quick-actions.service.ts b/packages/twenty-server/src/engine/core-modules/quick-actions/quick-actions.service.ts deleted file mode 100644 index 63789e57b..000000000 --- a/packages/twenty-server/src/engine/core-modules/quick-actions/quick-actions.service.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { v4 as uuidv4 } from 'uuid'; - -import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface'; -import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; - -import { stringifyWithoutKeyQuote } from 'src/engine/api/graphql/workspace-query-builder/utils/stringify-without-key-quote.util'; -import { WorkspaceQueryRunnerService } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.service'; -import { IntelligenceService } from 'src/engine/core-modules/quick-actions/intelligence.service'; -import { getCompanyNameFromDomainName } from 'src/modules/contact-creation-manager/utils/get-company-name-from-domain-name.util'; -import { capitalize } from 'src/utils/capitalize'; -import { getCompanyDomainName } from 'src/utils/getCompanyDomainName'; -import { isWorkEmail } from 'src/utils/is-work-email'; - -@Injectable() -export class QuickActionsService { - constructor( - private readonly workspaceQueryRunnunerService: WorkspaceQueryRunnerService, - private readonly intelligenceService: IntelligenceService, - ) {} - - async createCompanyFromPerson( - id: string, - workspaceId: string, - objectMetadataItemCollection: ObjectMetadataInterface[], - ) { - const personObjectMetadata = objectMetadataItemCollection.find( - (item) => item.nameSingular === 'person', - ); - - if (!personObjectMetadata) { - return; - } - - const personRequest = - await this.workspaceQueryRunnunerService.executeAndParse( - `query { - personCollection(filter: {id: {eq: "${id}"}}) { - edges { - node { - id - email - companyId - } - } - } - } - `, - personObjectMetadata, - '', - workspaceId, - ); - const person = personRequest.edges?.[0]?.node; - - if (!person) { - return; - } - - if (!person.companyId && person.email && isWorkEmail(person.email)) { - const companyDomainName = person.email.split('@')?.[1].toLowerCase(); - const companyName = capitalize(companyDomainName.split('.')[0]); - let relatedCompanyId = uuidv4(); - - const companyObjectMetadata = objectMetadataItemCollection.find( - (item) => item.nameSingular === 'company', - ); - - if (!companyObjectMetadata) { - return; - } - - const existingCompany = - await this.workspaceQueryRunnunerService.executeAndParse( - `query {companyCollection(filter: {domainName: {eq: "${companyDomainName}"}}) { - edges { - node { - id - } - } - } - } - `, - companyObjectMetadata, - '', - workspaceId, - ); - - if (existingCompany.edges?.length) { - relatedCompanyId = existingCompany.edges[0].node.id; - } - - await this.workspaceQueryRunnunerService.execute( - `mutation { - insertIntocompanyCollection(objects: ${stringifyWithoutKeyQuote([ - { - id: relatedCompanyId, - name: companyName, - domainName: companyDomainName, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }, - ])}) { - affectedCount - records { - id - } - } - } - `, - workspaceId, - ); - - await this.workspaceQueryRunnunerService.execute( - `mutation { - updatepersonCollection(set: ${stringifyWithoutKeyQuote({ - companyId: relatedCompanyId, - })}, filter: { id: { eq: "${person.id}" } }) { - affectedCount - records { - id - } - } - } - `, - workspaceId, - ); - } - } - - async executeQuickActionOnCompany( - id: string, - workspaceId: string, - objectMetadataItem: ObjectMetadataInterface, - ) { - const companyQuery = `query { - companyCollection(filter: {id: {eq: "${id}"}}) { - edges { - node { - id - domainName - createdAt - linkedinLinkPrimaryLinkUrl - } - } - } - } - `; - - const companyRequest = - await this.workspaceQueryRunnunerService.executeAndParse( - companyQuery, - objectMetadataItem, - '', - workspaceId, - ); - const company = companyRequest.edges?.[0]?.node; - - if (!company) { - return; - } - - const enrichedData = await this.intelligenceService.enrichCompany( - getCompanyNameFromDomainName(getCompanyDomainName(company)), - ); - - await this.workspaceQueryRunnunerService.execute( - `mutation { - updatecompanyCollection(set: ${stringifyWithoutKeyQuote( - enrichedData, - )}, filter: { id: { eq: "${id}" } }) { - affectedCount - records { - id - } - } - }`, - workspaceId, - ); - } -} diff --git a/packages/twenty-server/src/engine/integrations/environment/environment-variables.ts b/packages/twenty-server/src/engine/integrations/environment/environment-variables.ts index c2e67a200..85c21c1a3 100644 --- a/packages/twenty-server/src/engine/integrations/environment/environment-variables.ts +++ b/packages/twenty-server/src/engine/integrations/environment/environment-variables.ts @@ -2,17 +2,17 @@ import { LogLevel } from '@nestjs/common'; import { plainToClass } from 'class-transformer'; import { + IsBoolean, + IsDefined, IsEnum, + IsNumber, IsOptional, IsString, IsUrl, + Max, + Min, ValidateIf, validateSync, - IsBoolean, - IsNumber, - IsDefined, - Min, - Max, } from 'class-validator'; import { EmailDriver } from 'src/engine/integrations/email/interfaces/email.interface'; @@ -20,24 +20,24 @@ import { NodeEnvironment } from 'src/engine/integrations/environment/interfaces/ import { LLMChatModelDriver } from 'src/engine/integrations/llm-chat-model/interfaces/llm-chat-model.interface'; import { LLMTracingDriver } from 'src/engine/integrations/llm-tracing/interfaces/llm-tracing.interface'; -import { ServerlessDriverType } from 'src/engine/integrations/serverless/serverless.interface'; -import { assert } from 'src/utils/assert'; +import { CacheStorageType } from 'src/engine/integrations/cache-storage/types/cache-storage-type.enum'; +import { CaptchaDriverType } from 'src/engine/integrations/captcha/interfaces'; import { CastToStringArray } from 'src/engine/integrations/environment/decorators/cast-to-string-array.decorator'; +import { IsStrictlyLowerThan } from 'src/engine/integrations/environment/decorators/is-strictly-lower-than.decorator'; import { ExceptionHandlerDriver } from 'src/engine/integrations/exception-handler/interfaces'; import { StorageDriverType } from 'src/engine/integrations/file-storage/interfaces'; import { LoggerDriverType } from 'src/engine/integrations/logger/interfaces'; -import { IsStrictlyLowerThan } from 'src/engine/integrations/environment/decorators/is-strictly-lower-than.decorator'; -import { CaptchaDriverType } from 'src/engine/integrations/captcha/interfaces'; import { MessageQueueDriverType } from 'src/engine/integrations/message-queue/interfaces'; -import { CacheStorageType } from 'src/engine/integrations/cache-storage/types/cache-storage-type.enum'; +import { ServerlessDriverType } from 'src/engine/integrations/serverless/serverless.interface'; +import { assert } from 'src/utils/assert'; +import { CastToBoolean } from './decorators/cast-to-boolean.decorator'; +import { CastToLogLevelArray } from './decorators/cast-to-log-level-array.decorator'; +import { CastToPositiveNumber } from './decorators/cast-to-positive-number.decorator'; +import { IsAWSRegion } from './decorators/is-aws-region.decorator'; import { IsDuration } from './decorators/is-duration.decorator'; import { AwsRegion } from './interfaces/aws-region.interface'; -import { IsAWSRegion } from './decorators/is-aws-region.decorator'; -import { CastToBoolean } from './decorators/cast-to-boolean.decorator'; import { SupportDriver } from './interfaces/support.interface'; -import { CastToPositiveNumber } from './decorators/cast-to-positive-number.decorator'; -import { CastToLogLevelArray } from './decorators/cast-to-log-level-array.decorator'; export class EnvironmentVariables { // Misc @@ -394,8 +394,6 @@ export class EnvironmentVariables { EMAIL_SMTP_PASSWORD: string; - OPENROUTER_API_KEY: string; - LLM_CHAT_MODEL_DRIVER: LLMChatModelDriver; OPENAI_API_KEY: string; diff --git a/packages/twenty-server/src/engine/utils/__tests__/get-resolver-name.spec.ts b/packages/twenty-server/src/engine/utils/__tests__/get-resolver-name.spec.ts index 16560a4e6..55f327d19 100644 --- a/packages/twenty-server/src/engine/utils/__tests__/get-resolver-name.spec.ts +++ b/packages/twenty-server/src/engine/utils/__tests__/get-resolver-name.spec.ts @@ -15,7 +15,6 @@ describe('getResolverName', () => { ['createOne', 'createEntity'], ['updateOne', 'updateEntity'], ['deleteOne', 'deleteEntity'], - ['executeQuickActionOnOne', 'executeQuickActionOnEntity'], ])('should return correct name for %s resolver', (type, expectedResult) => { expect( getResolverName(metadata, type as WorkspaceResolverBuilderMethodNames), diff --git a/packages/twenty-server/src/engine/utils/get-resolver-name.util.ts b/packages/twenty-server/src/engine/utils/get-resolver-name.util.ts index 1f4d0ebc7..4c35f0eda 100644 --- a/packages/twenty-server/src/engine/utils/get-resolver-name.util.ts +++ b/packages/twenty-server/src/engine/utils/get-resolver-name.util.ts @@ -23,8 +23,6 @@ export const getResolverName = ( return `update${pascalCase(objectMetadata.nameSingular)}`; case 'deleteOne': return `delete${pascalCase(objectMetadata.nameSingular)}`; - case 'executeQuickActionOnOne': - return `executeQuickActionOn${pascalCase(objectMetadata.nameSingular)}`; case 'updateMany': return `update${pascalCase(objectMetadata.namePlural)}`; case 'deleteMany':