feat: record batch deleteMany (#3096)
feat: support record batch deleteMany Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -10,6 +10,7 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat
|
||||
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
|
||||
import { useGenerateCreateManyRecordMutation } from '@/object-record/hooks/useGenerateCreateManyRecordMutation';
|
||||
import { useGenerateCreateOneRecordMutation } from '@/object-record/hooks/useGenerateCreateOneRecordMutation';
|
||||
import { useGenerateDeleteManyRecordMutation } from '@/object-record/hooks/useGenerateDeleteManyRecordMutation';
|
||||
import { useGenerateExecuteQuickActionOnOneRecordMutation } from '@/object-record/hooks/useGenerateExecuteQuickActionOnOneRecordMutation';
|
||||
import { useGenerateFindManyRecordsQuery } from '@/object-record/hooks/useGenerateFindManyRecordsQuery';
|
||||
import { useGenerateFindOneRecordQuery } from '@/object-record/hooks/useGenerateFindOneRecordQuery';
|
||||
@ -107,6 +108,10 @@ export const useObjectMetadataItem = (
|
||||
objectMetadataItem,
|
||||
});
|
||||
|
||||
const deleteManyRecordsMutation = useGenerateDeleteManyRecordMutation({
|
||||
objectMetadataItem,
|
||||
});
|
||||
|
||||
const executeQuickActionOnOneRecordMutation =
|
||||
useGenerateExecuteQuickActionOnOneRecordMutation({
|
||||
objectMetadataItem,
|
||||
@ -131,6 +136,7 @@ export const useObjectMetadataItem = (
|
||||
deleteOneRecordMutation,
|
||||
executeQuickActionOnOneRecordMutation,
|
||||
createManyRecordsMutation,
|
||||
deleteManyRecordsMutation,
|
||||
mapToObjectRecordIdentifier,
|
||||
getObjectOrderByField,
|
||||
};
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
|
||||
import { useOptimisticEvict } from '@/apollo/optimistic-effect/hooks/useOptimisticEvict';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
type useDeleteOneRecordProps = {
|
||||
objectNameSingular: string;
|
||||
refetchFindManyQuery?: boolean;
|
||||
};
|
||||
|
||||
export const useDeleteManyRecords = <T>({
|
||||
objectNameSingular,
|
||||
refetchFindManyQuery = false,
|
||||
}: useDeleteOneRecordProps) => {
|
||||
const { performOptimisticEvict } = useOptimisticEvict();
|
||||
const { triggerOptimisticEffects } = useOptimisticEffect({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const {
|
||||
objectMetadataItem,
|
||||
deleteManyRecordsMutation,
|
||||
findManyRecordsQuery,
|
||||
} = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const deleteManyRecords = async (idsToDelete: string[]) => {
|
||||
triggerOptimisticEffects({
|
||||
typename: `${capitalize(objectMetadataItem.nameSingular)}Edge`,
|
||||
deletedRecordIds: idsToDelete,
|
||||
});
|
||||
|
||||
idsToDelete.forEach((idToDelete) => {
|
||||
performOptimisticEvict(
|
||||
capitalize(objectMetadataItem.nameSingular),
|
||||
'id',
|
||||
idToDelete,
|
||||
);
|
||||
});
|
||||
|
||||
const deleteRecordFilter: ObjectRecordQueryFilter = {
|
||||
id: {
|
||||
in: idsToDelete,
|
||||
},
|
||||
};
|
||||
const deletedRecords = await apolloClient.mutate({
|
||||
mutation: deleteManyRecordsMutation,
|
||||
variables: {
|
||||
filter: deleteRecordFilter,
|
||||
// atMost: idsToDelete.length,
|
||||
},
|
||||
refetchQueries: refetchFindManyQuery
|
||||
? [getOperationName(findManyRecordsQuery) ?? '']
|
||||
: [],
|
||||
});
|
||||
|
||||
return deletedRecords.data[
|
||||
`delete${capitalize(objectMetadataItem.namePlural)}`
|
||||
] as T;
|
||||
};
|
||||
|
||||
return { deleteManyRecords };
|
||||
};
|
||||
@ -0,0 +1,27 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
import { EMPTY_MUTATION } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const useGenerateDeleteManyRecordMutation = ({
|
||||
objectMetadataItem,
|
||||
}: {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
}) => {
|
||||
if (!objectMetadataItem) {
|
||||
return EMPTY_MUTATION;
|
||||
}
|
||||
|
||||
const capitalizedObjectName = capitalize(objectMetadataItem.namePlural);
|
||||
|
||||
return gql`
|
||||
mutation DeleteMany${capitalizedObjectName}($filter: ${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}FilterInput!) {
|
||||
delete${capitalizedObjectName}(filter: $filter) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
};
|
||||
@ -4,7 +4,7 @@ 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 { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords';
|
||||
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';
|
||||
@ -71,7 +71,7 @@ export const useRecordTableContextMenuEntries = (
|
||||
}
|
||||
});
|
||||
|
||||
const { deleteOneRecord } = useDeleteOneRecord({
|
||||
const { deleteManyRecords } = useDeleteManyRecords({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
@ -87,13 +87,9 @@ export const useRecordTableContextMenuEntries = (
|
||||
.getValue();
|
||||
|
||||
resetTableRowSelection();
|
||||
await Promise.all(
|
||||
rowIdsToDelete.map(async (rowId) => {
|
||||
await deleteOneRecord(rowId);
|
||||
}),
|
||||
);
|
||||
await deleteManyRecords(rowIdsToDelete);
|
||||
},
|
||||
[deleteOneRecord, resetTableRowSelection],
|
||||
[deleteManyRecords, resetTableRowSelection],
|
||||
);
|
||||
|
||||
const handleExecuteQuickActionOnClick = useRecoilCallback(
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||
import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords';
|
||||
import { useRecordBoardScopedStates } from '@/object-record/record-board/hooks/internal/useRecordBoardScopedStates';
|
||||
import { Opportunity } from '@/pipeline/types/Opportunity';
|
||||
|
||||
@ -11,8 +11,8 @@ export const useDeleteSelectedRecordBoardCardsInternal = () => {
|
||||
const removeCardIds = useRemoveRecordBoardCardIdsInternal();
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const { deleteOneRecord: deleteOneOpportunity } =
|
||||
useDeleteOneRecord<Opportunity>({
|
||||
const { deleteManyRecords: deleteManyOpportunities } =
|
||||
useDeleteManyRecords<Opportunity>({
|
||||
objectNameSingular: 'opportunity',
|
||||
});
|
||||
|
||||
@ -25,11 +25,7 @@ export const useDeleteSelectedRecordBoardCardsInternal = () => {
|
||||
.getLoadable(selectedCardIdsSelector)
|
||||
.getValue();
|
||||
|
||||
await Promise.all(
|
||||
selectedCardIds.map(async (id) => {
|
||||
await deleteOneOpportunity?.(id);
|
||||
}),
|
||||
);
|
||||
await deleteManyOpportunities?.(selectedCardIds);
|
||||
removeCardIds(selectedCardIds);
|
||||
selectedCardIds.forEach((id) => {
|
||||
apolloClient.cache.evict({ id: `Opportunity:${id}` });
|
||||
@ -38,7 +34,7 @@ export const useDeleteSelectedRecordBoardCardsInternal = () => {
|
||||
[
|
||||
selectedCardIdsSelector,
|
||||
removeCardIds,
|
||||
deleteOneOpportunity,
|
||||
deleteManyOpportunities,
|
||||
apolloClient.cache,
|
||||
],
|
||||
);
|
||||
|
||||
@ -24,7 +24,7 @@ export class DeleteManyQueryFactory {
|
||||
mutation {
|
||||
deleteFrom${
|
||||
options.targetTableName
|
||||
}Collection(filter: ${stringifyWithoutKeyQuote(args.filter)}) {
|
||||
}Collection(filter: ${stringifyWithoutKeyQuote(args.filter)}, atMost: 30) {
|
||||
affectedCount
|
||||
records {
|
||||
${fieldsString}
|
||||
|
||||
Reference in New Issue
Block a user