[FEAT] RecordAction destroy many record (#9991)

# Introduction
Added the `RecordAction` destroy multiple record

## Repro
Select multiples `deletedRecords`, you should be able to see the
`Destroy` pinned CTA ( iso short label with the destroy one ), open
control panel and fin new CTA `Permanently delete records`


https://github.com/user-attachments/assets/31ee8738-9d61-4dec-9a1f-41bb6785e018

## TODO
- [ ] Gain granularity within tests to assert the action should be
registered only when filtering by deleted

## Conclusion
Closes https://github.com/twentyhq/core-team-issues/issues/110
This commit is contained in:
Paul Rastoin
2025-02-05 11:33:01 +01:00
committed by GitHub
parent aa003f25d9
commit 28a3f75946
12 changed files with 338 additions and 33 deletions

View File

@ -1,14 +1,25 @@
import { ReactNode, useEffect, useState } from 'react';
import { PropsWithChildren, useEffect, useState } from 'react';
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import {
ContextStoreTargetedRecordsRule,
contextStoreTargetedRecordsRuleComponentState,
} from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
export type JestContextStoreSetterMocks = {
contextStoreTargetedRecordsRule?: ContextStoreTargetedRecordsRule;
contextStoreNumberOfSelectedRecords?: number;
contextStoreFilters?: RecordFilter[];
contextStoreCurrentObjectMetadataNameSingular?: string;
};
type JestContextStoreSetterProps =
PropsWithChildren<JestContextStoreSetterMocks>;
export const JestContextStoreSetter = ({
contextStoreTargetedRecordsRule = {
mode: 'selection',
@ -16,13 +27,9 @@ export const JestContextStoreSetter = ({
},
contextStoreNumberOfSelectedRecords = 0,
contextStoreCurrentObjectMetadataNameSingular = '',
contextStoreFilters = [],
children,
}: {
contextStoreTargetedRecordsRule?: ContextStoreTargetedRecordsRule;
contextStoreNumberOfSelectedRecords?: number;
contextStoreCurrentObjectMetadataNameSingular?: string;
children: ReactNode;
}) => {
}: JestContextStoreSetterProps) => {
const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2(
contextStoreTargetedRecordsRuleComponentState,
);
@ -35,6 +42,10 @@ export const JestContextStoreSetter = ({
contextStoreNumberOfSelectedRecordsComponentState,
);
const setcontextStoreFiltersComponentState = useSetRecoilComponentStateV2(
contextStoreFiltersComponentState,
);
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular: contextStoreCurrentObjectMetadataNameSingular,
});
@ -46,6 +57,8 @@ export const JestContextStoreSetter = ({
setContextStoreTargetedRecordsRule(contextStoreTargetedRecordsRule);
setContextStoreCurrentObjectMetadataId(contextStoreCurrentObjectMetadataId);
setContextStoreNumberOfSelectedRecords(contextStoreNumberOfSelectedRecords);
setcontextStoreFiltersComponentState(contextStoreFilters);
setIsLoaded(true);
}, [
setContextStoreTargetedRecordsRule,
@ -54,6 +67,8 @@ export const JestContextStoreSetter = ({
contextStoreCurrentObjectMetadataId,
setContextStoreNumberOfSelectedRecords,
contextStoreNumberOfSelectedRecords,
setcontextStoreFiltersComponentState,
contextStoreFilters,
]);
return isLoaded ? <>{children}</> : null;

View File

@ -1,23 +1,22 @@
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext';
import { MockedResponse } from '@apollo/client/testing';
import { ReactNode } from 'react';
import { MutableSnapshot } from 'recoil';
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
import { JestContextStoreSetter } from '~/testing/jest/JestContextStoreSetter';
import {
JestContextStoreSetter,
JestContextStoreSetterMocks,
} from '~/testing/jest/JestContextStoreSetter';
export type GetJestMetadataAndApolloMocksAndActionMenuWrapperProps = {
apolloMocks:
| readonly MockedResponse<Record<string, any>, Record<string, any>>[]
| undefined;
onInitializeRecoilSnapshot?: (snapshot: MutableSnapshot) => void;
contextStoreTargetedRecordsRule?: ContextStoreTargetedRecordsRule;
contextStoreNumberOfSelectedRecords?: number;
contextStoreCurrentObjectMetadataNameSingular?: string;
componentInstanceId: string;
};
} & JestContextStoreSetterMocks;
export const getJestMetadataAndApolloMocksAndActionMenuWrapper = ({
apolloMocks,
@ -25,6 +24,7 @@ export const getJestMetadataAndApolloMocksAndActionMenuWrapper = ({
contextStoreTargetedRecordsRule,
contextStoreNumberOfSelectedRecords,
contextStoreCurrentObjectMetadataNameSingular,
contextStoreFilters,
componentInstanceId,
}: GetJestMetadataAndApolloMocksAndActionMenuWrapperProps) => {
const Wrapper = getJestMetadataAndApolloMocksWrapper({
@ -48,6 +48,7 @@ export const getJestMetadataAndApolloMocksAndActionMenuWrapper = ({
}}
>
<JestContextStoreSetter
contextStoreFilters={contextStoreFilters}
contextStoreTargetedRecordsRule={contextStoreTargetedRecordsRule}
contextStoreNumberOfSelectedRecords={
contextStoreNumberOfSelectedRecords