feat: record batch deleteMany (#3096)

feat: support record batch deleteMany

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Cao Z.H
2023-12-22 02:55:40 +08:00
committed by GitHub
parent 801177531b
commit 794cf87b43
6 changed files with 113 additions and 18 deletions

View File

@ -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,
};

View File

@ -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 };
};

View File

@ -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
}
}
`;
};

View File

@ -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(

View File

@ -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,
],
);

View File

@ -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}