Basic data enrichment (#3023)
* Add Enrich to frontend * Naive backend implementation * Add work email check * Rename Enrich to Quick Action * Refactor logic to a separate service * Refacto to separate IntelligenceService * Small fixes * Missing Break statement * Address PR comments * Create company interface * Improve edge case handling * Use httpService instead of Axios * Fix server tests
This commit is contained in:
@ -15,6 +15,7 @@ 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),
|
||||
|
||||
@ -21,6 +21,8 @@ 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':
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module';
|
||||
import { FieldsStringFactory } from 'src/workspace/workspace-query-builder/factories/fields-string.factory';
|
||||
|
||||
import { WorkspaceQueryBuilderFactory } from './workspace-query-builder.factory';
|
||||
|
||||
@ -9,6 +10,6 @@ import { workspaceQueryBuilderFactories } from './factories/factories';
|
||||
@Module({
|
||||
imports: [ObjectMetadataModule],
|
||||
providers: [...workspaceQueryBuilderFactories, WorkspaceQueryBuilderFactory],
|
||||
exports: [WorkspaceQueryBuilderFactory],
|
||||
exports: [WorkspaceQueryBuilderFactory, FieldsStringFactory],
|
||||
})
|
||||
export class WorkspaceQueryBuilderModule {}
|
||||
|
||||
@ -181,7 +181,7 @@ export class WorkspaceQueryRunnerService {
|
||||
)?.records;
|
||||
}
|
||||
|
||||
private async execute(
|
||||
async execute(
|
||||
query: string,
|
||||
workspaceId: string,
|
||||
): Promise<PGGraphQLResult | undefined> {
|
||||
@ -215,7 +215,7 @@ export class WorkspaceQueryRunnerService {
|
||||
const errors = graphqlResult?.[0]?.resolve?.errors;
|
||||
|
||||
if (Array.isArray(errors) && errors.length > 0) {
|
||||
console.error('GraphQL errors', errors);
|
||||
console.error(`GraphQL errors on ${command}${targetTableName}`, errors);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
@ -224,4 +224,15 @@ export class WorkspaceQueryRunnerService {
|
||||
|
||||
return parseResult(result);
|
||||
}
|
||||
|
||||
async executeAndParse<Result>(
|
||||
query: string,
|
||||
targetTableName: string,
|
||||
command: string,
|
||||
workspaceId: string,
|
||||
): Promise<Result> {
|
||||
const result = await this.execute(query, workspaceId);
|
||||
|
||||
return this.parseResult(result, targetTableName, command);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
Resolver,
|
||||
FindOneResolverArgs,
|
||||
ExecuteQuickActionOnOneResolverArgs,
|
||||
DeleteOneResolverArgs,
|
||||
} from 'src/workspace/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||
import { Record as IRecord } from 'src/workspace/workspace-query-builder/interfaces/record.interface';
|
||||
import { WorkspaceSchemaBuilderContext } from 'src/workspace/workspace-schema-builder/interfaces/workspace-schema-builder-context.interface';
|
||||
import { WorkspaceResolverBuilderFactoryInterface } from 'src/workspace/workspace-resolver-builder/interfaces/workspace-resolver-builder-factory.interface';
|
||||
import { WorkspaceQueryRunnerOptions } from 'src/workspace/workspace-query-runner/interfaces/query-runner-optionts.interface';
|
||||
|
||||
import { WorkspaceQueryRunnerService } from 'src/workspace/workspace-query-runner/workspace-query-runner.service';
|
||||
import { QuickActionsService } from 'src/core/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<ExecuteQuickActionOnOneResolverArgs> {
|
||||
const internalContext = context;
|
||||
|
||||
return (_source, args, context, info) => {
|
||||
return this.executeQuickActionOnOne(args, {
|
||||
targetTableName: internalContext.targetTableName,
|
||||
workspaceId: internalContext.workspaceId,
|
||||
info,
|
||||
fieldMetadataCollection: internalContext.fieldMetadataCollection,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private async executeQuickActionOnOne<Record extends IRecord = IRecord>(
|
||||
args: DeleteOneResolverArgs,
|
||||
options: WorkspaceQueryRunnerOptions,
|
||||
): Promise<Record | undefined> {
|
||||
switch (options.targetTableName) {
|
||||
case 'company': {
|
||||
await this.quickActionsService.executeQuickActionOnCompany(
|
||||
args.id,
|
||||
options.workspaceId,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'person': {
|
||||
await this.quickActionsService.createCompanyFromPerson(
|
||||
args.id,
|
||||
options.workspaceId,
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// TODO: different quick actions per object on frontend
|
||||
break;
|
||||
}
|
||||
|
||||
return this.workspaceQueryRunnerService.findOne(
|
||||
{ filter: { id: { eq: args.id } } } as FindOneResolverArgs,
|
||||
options,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ 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,
|
||||
@ -15,6 +16,7 @@ export const workspaceResolverBuilderFactories = [
|
||||
CreateOneResolverFactory,
|
||||
UpdateOneResolverFactory,
|
||||
DeleteOneResolverFactory,
|
||||
ExecuteQuickActionOnOneResolverFactory,
|
||||
UpdateManyResolverFactory,
|
||||
DeleteManyResolverFactory,
|
||||
];
|
||||
@ -29,6 +31,7 @@ export const workspaceResolverBuilderMethodNames = {
|
||||
CreateOneResolverFactory.methodName,
|
||||
UpdateOneResolverFactory.methodName,
|
||||
DeleteOneResolverFactory.methodName,
|
||||
ExecuteQuickActionOnOneResolverFactory.methodName,
|
||||
UpdateManyResolverFactory.methodName,
|
||||
DeleteManyResolverFactory.methodName,
|
||||
],
|
||||
|
||||
@ -51,6 +51,10 @@ export interface DeleteOneResolverArgs {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface ExecuteQuickActionOnOneResolverArgs {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface DeleteManyResolverArgs<Filter = any> {
|
||||
filter: Filter;
|
||||
}
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceQueryRunnerModule } from 'src/workspace/workspace-query-runner/workspace-query-runner.module';
|
||||
import { QuickActionsModule } from 'src/core/quick-actions/quick-actions.module';
|
||||
|
||||
import { WorkspaceResolverFactory } from './workspace-resolver.factory';
|
||||
|
||||
import { workspaceResolverBuilderFactories } from './factories/factories';
|
||||
|
||||
@Module({
|
||||
imports: [WorkspaceQueryRunnerModule],
|
||||
imports: [WorkspaceQueryRunnerModule, QuickActionsModule],
|
||||
providers: [...workspaceResolverBuilderFactories, WorkspaceResolverFactory],
|
||||
exports: [WorkspaceResolverFactory],
|
||||
})
|
||||
|
||||
@ -7,6 +7,7 @@ import { ObjectMetadataInterface } from 'src/metadata/field-metadata/interfaces/
|
||||
import { getResolverName } from 'src/workspace/utils/get-resolver-name.util';
|
||||
import { UpdateManyResolverFactory } from 'src/workspace/workspace-resolver-builder/factories/update-many-resolver.factory';
|
||||
import { DeleteManyResolverFactory } from 'src/workspace/workspace-resolver-builder/factories/delete-many-resolver.factory';
|
||||
import { ExecuteQuickActionOnOneResolverFactory } from 'src/workspace/workspace-resolver-builder/factories/execute-quick-action-on-one-resolver.factory';
|
||||
|
||||
import { FindManyResolverFactory } from './factories/find-many-resolver.factory';
|
||||
import { FindOneResolverFactory } from './factories/find-one-resolver.factory';
|
||||
@ -31,6 +32,7 @@ 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,
|
||||
) {}
|
||||
@ -50,6 +52,7 @@ export class WorkspaceResolverFactory {
|
||||
['createOne', this.createOneResolverFactory],
|
||||
['updateOne', this.updateOneResolverFactory],
|
||||
['deleteOne', this.deleteOneResolverFactory],
|
||||
['executeQuickActionOnOne', this.executeQuickActionOnOneResolverFactory],
|
||||
['updateMany', this.updateManyResolverFactory],
|
||||
['deleteMany', this.deleteManyResolverFactory],
|
||||
]);
|
||||
|
||||
@ -34,6 +34,9 @@ describe('getResolverArgs', () => {
|
||||
deleteOne: {
|
||||
id: { type: FieldMetadataType.UUID, isNullable: false },
|
||||
},
|
||||
executeQuickActionOnOne: {
|
||||
id: { type: FieldMetadataType.UUID, isNullable: false },
|
||||
},
|
||||
};
|
||||
|
||||
// Test each resolver type
|
||||
|
||||
@ -76,6 +76,13 @@ export const getResolverArgs = (
|
||||
isNullable: false,
|
||||
},
|
||||
};
|
||||
case 'executeQuickActionOnOne':
|
||||
return {
|
||||
id: {
|
||||
type: FieldMetadataType.UUID,
|
||||
isNullable: false,
|
||||
},
|
||||
};
|
||||
case 'updateMany':
|
||||
return {
|
||||
data: {
|
||||
|
||||
Reference in New Issue
Block a user