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:
@ -0,0 +1,50 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
type useExecuteQuickActionOnOneRecordProps = {
|
||||
objectNameSingular: string;
|
||||
};
|
||||
|
||||
export const useExecuteQuickActionOnOneRecord = <T>({
|
||||
objectNameSingular,
|
||||
}: useExecuteQuickActionOnOneRecordProps) => {
|
||||
const {
|
||||
objectMetadataItem,
|
||||
executeQuickActionOnOneRecordMutation,
|
||||
findManyRecordsQuery,
|
||||
} = useObjectMetadataItem({
|
||||
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,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,44 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
import { useMapFieldMetadataToGraphQLQuery } from '@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery';
|
||||
import { EMPTY_MUTATION } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const getExecuteQuickActionOnOneRecordMutationGraphQLField = ({
|
||||
objectNameSingular,
|
||||
}: {
|
||||
objectNameSingular: string;
|
||||
}) => {
|
||||
return `executeQuickActionOn${capitalize(objectNameSingular)}`;
|
||||
};
|
||||
|
||||
export const useGenerateExecuteQuickActionOnOneRecordMutation = ({
|
||||
objectMetadataItem,
|
||||
}: {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
}) => {
|
||||
const mapFieldMetadataToGraphQLQuery = useMapFieldMetadataToGraphQLQuery();
|
||||
|
||||
if (!objectMetadataItem) {
|
||||
return EMPTY_MUTATION;
|
||||
}
|
||||
|
||||
const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular);
|
||||
|
||||
const graphQLFieldForExecuteQuickActionOnOneRecordMutation =
|
||||
getExecuteQuickActionOnOneRecordMutationGraphQLField({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
|
||||
return gql`
|
||||
mutation ExecuteQuickActionOnOne${capitalizedObjectName}($idToExecuteQuickActionOn: ID!) {
|
||||
${graphQLFieldForExecuteQuickActionOnOneRecordMutation}(id: $idToExecuteQuickActionOn) {
|
||||
id
|
||||
${objectMetadataItem.fields
|
||||
.map((field) => mapFieldMetadataToGraphQLQuery(field))
|
||||
.join('\n')}
|
||||
}
|
||||
}
|
||||
`;
|
||||
};
|
||||
@ -5,14 +5,21 @@ import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { useFavorites } from '@/favorites/hooks/useFavorites';
|
||||
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
|
||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||
import { useExecuteQuickActionOnOneRecord } from '@/object-record/hooks/useExecuteQuickActionOnOneRecord';
|
||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||
import { RecordTableScopeInternalContext } from '@/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
|
||||
import { selectedRowIdsSelector } from '@/object-record/record-table/states/selectors/selectedRowIdsSelector';
|
||||
import { IconHeart, IconHeartOff, IconTrash } from '@/ui/display/icon';
|
||||
import {
|
||||
IconHeart,
|
||||
IconHeartOff,
|
||||
IconTrash,
|
||||
IconWand,
|
||||
} from '@/ui/display/icon';
|
||||
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 { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
|
||||
type useRecordTableContextMenuEntriesProps = {
|
||||
recordTableScopeId?: string;
|
||||
@ -68,6 +75,10 @@ export const useRecordTableContextMenuEntries = (
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { executeQuickActionOnOneRecord } = useExecuteQuickActionOnOneRecord({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const handleDeleteClick = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async () => {
|
||||
@ -85,6 +96,27 @@ export const useRecordTableContextMenuEntries = (
|
||||
[deleteOneRecord, resetTableRowSelection],
|
||||
);
|
||||
|
||||
const handleExecuteQuickActionOnClick = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async () => {
|
||||
const rowIdsToExecuteQuickActionOn = snapshot
|
||||
.getLoadable(selectedRowIdsSelector)
|
||||
.getValue();
|
||||
|
||||
resetTableRowSelection();
|
||||
await Promise.all(
|
||||
rowIdsToExecuteQuickActionOn.map(async (rowId) => {
|
||||
await executeQuickActionOnOneRecord(rowId);
|
||||
}),
|
||||
);
|
||||
},
|
||||
[executeQuickActionOnOneRecord, resetTableRowSelection],
|
||||
);
|
||||
|
||||
const dataExecuteQuickActionOnmentEnabled = useIsFeatureEnabled(
|
||||
'IS_QUICK_ACTIONS_ENABLED',
|
||||
);
|
||||
|
||||
return {
|
||||
setContextMenuEntries: useCallback(() => {
|
||||
const selectedRowId =
|
||||
@ -143,6 +175,15 @@ export const useRecordTableContextMenuEntries = (
|
||||
// Icon: IconNotes,
|
||||
// onClick: () => {},
|
||||
// },
|
||||
...(dataExecuteQuickActionOnmentEnabled
|
||||
? [
|
||||
{
|
||||
label: 'Quick Action',
|
||||
Icon: IconWand,
|
||||
onClick: () => handleExecuteQuickActionOnClick(),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
label: 'Delete',
|
||||
Icon: IconTrash,
|
||||
|
||||
Reference in New Issue
Block a user