diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DeleteMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DeleteMultipleRecordsAction.tsx index 5865e37013..6287988b5c 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DeleteMultipleRecordsAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DeleteMultipleRecordsAction.tsx @@ -1,6 +1,7 @@ import { ActionModal } from '@/action-menu/actions/components/ActionModal'; import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; @@ -39,19 +40,24 @@ export const DeleteMultipleRecordsAction = () => { contextStoreFiltersComponentState, ); + const contextStoreFilterGroups = useRecoilComponentValue( + contextStoreFilterGroupsComponentState, + ); + const contextStoreAnyFieldFilterValue = useRecoilComponentValue( contextStoreAnyFieldFilterValueComponentState, ); const { filterValueDependencies } = useFilterValueDependencies(); - const graphqlFilter = computeContextStoreFilters( + const graphqlFilter = computeContextStoreFilters({ contextStoreTargetedRecordsRule, contextStoreFilters, + contextStoreFilterGroups, objectMetadataItem, filterValueDependencies, contextStoreAnyFieldFilterValue, - ); + }); const { fetchAllRecords: fetchAllRecordIds } = useLazyFetchAllRecords({ objectNameSingular: objectMetadataItem.nameSingular, diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DestroyMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DestroyMultipleRecordsAction.tsx index 9af83d6d4c..a2443656cd 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DestroyMultipleRecordsAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DestroyMultipleRecordsAction.tsx @@ -1,6 +1,7 @@ import { ActionModal } from '@/action-menu/actions/components/ActionModal'; import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; @@ -39,6 +40,10 @@ export const DestroyMultipleRecordsAction = () => { contextStoreFiltersComponentState, ); + const contextStoreFilterGroups = useRecoilComponentValue( + contextStoreFilterGroupsComponentState, + ); + const contextStoreAnyFieldFilterValue = useRecoilComponentValue( contextStoreAnyFieldFilterValueComponentState, ); @@ -49,13 +54,14 @@ export const DestroyMultipleRecordsAction = () => { deletedAt: { is: 'NOT_NULL' }, }; const graphqlFilter = { - ...computeContextStoreFilters( + ...computeContextStoreFilters({ contextStoreTargetedRecordsRule, contextStoreFilters, + contextStoreFilterGroups, objectMetadataItem, filterValueDependencies, contextStoreAnyFieldFilterValue, - ), + }), ...deletedAtFilter, }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/RestoreMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/RestoreMultipleRecordsAction.tsx index 92030daeac..223da282be 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/RestoreMultipleRecordsAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/RestoreMultipleRecordsAction.tsx @@ -1,6 +1,7 @@ import { ActionModal } from '@/action-menu/actions/components/ActionModal'; import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; @@ -39,6 +40,10 @@ export const RestoreMultipleRecordsAction = () => { contextStoreFiltersComponentState, ); + const contextStoreFilterGroups = useRecoilComponentValue( + contextStoreFilterGroupsComponentState, + ); + const contextStoreAnyFieldFilterValue = useRecoilComponentValue( contextStoreAnyFieldFilterValueComponentState, ); @@ -50,13 +55,14 @@ export const RestoreMultipleRecordsAction = () => { }; const graphqlFilter = { - ...computeContextStoreFilters( + ...computeContextStoreFilters({ contextStoreTargetedRecordsRule, contextStoreFilters, + contextStoreFilterGroups, objectMetadataItem, filterValueDependencies, contextStoreAnyFieldFilterValue, - ), + }), ...deletedAtFilter, }; diff --git a/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useSetGlobalCommandMenuContext.test.tsx b/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useSetGlobalCommandMenuContext.test.tsx index 0b1da47659..1525b47a65 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useSetGlobalCommandMenuContext.test.tsx +++ b/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useSetGlobalCommandMenuContext.test.tsx @@ -17,6 +17,7 @@ import { recordStoreFamilyState } from '@/object-record/record-store/states/reco import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper'; import { getPeopleRecordConnectionMock } from '~/testing/mock-data/people'; import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; const mockCopyContextStoreStates = jest.fn(); jest.mock( @@ -81,6 +82,12 @@ describe('useSetGlobalCommandMenuContext', () => { }), ); + const filterGroups = useRecoilValue( + contextStoreFilterGroupsComponentState.atomFamily({ + instanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID, + }), + ); + const anyFieldFilterValue = useRecoilValue( contextStoreAnyFieldFilterValueComponentState.atomFamily({ instanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID, @@ -104,6 +111,7 @@ describe('useSetGlobalCommandMenuContext', () => { targetedRecordsRule, numberOfSelectedRecords, filters, + filterGroups, currentViewType, commandMenuPageInfo, hasUserSelectedCommand, diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts b/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts index b4c1a1cf9d..3f34a8a20d 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts +++ b/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts @@ -2,6 +2,7 @@ import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/s import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; @@ -77,6 +78,21 @@ export const useCopyContextStoreStates = () => { contextStoreFilters, ); + const contextStoreFilterGroups = snapshot + .getLoadable( + contextStoreFilterGroupsComponentState.atomFamily({ + instanceId: instanceIdToCopyFrom, + }), + ) + .getValue(); + + set( + contextStoreFilterGroupsComponentState.atomFamily({ + instanceId: instanceIdToCopyTo, + }), + contextStoreFilterGroups, + ); + const contextStoreAnyFieldFilterValue = snapshot .getLoadable( contextStoreAnyFieldFilterValueComponentState.atomFamily({ diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts b/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts index eee7c7fa42..d2b550a04e 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts +++ b/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts @@ -1,6 +1,7 @@ import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState'; import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; @@ -40,6 +41,13 @@ export const useResetContextStoreStates = () => { [], ); + set( + contextStoreFilterGroupsComponentState.atomFamily({ + instanceId, + }), + [], + ); + set( contextStoreAnyFieldFilterValueComponentState.atomFamily({ instanceId, diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useSetGlobalCommandMenuContext.ts b/packages/twenty-front/src/modules/command-menu/hooks/useSetGlobalCommandMenuContext.ts index 57a6e4b35a..a405969bf3 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/useSetGlobalCommandMenuContext.ts +++ b/packages/twenty-front/src/modules/command-menu/hooks/useSetGlobalCommandMenuContext.ts @@ -5,6 +5,7 @@ import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageI import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState'; import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState'; import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; @@ -46,6 +47,13 @@ export const useSetGlobalCommandMenuContext = () => { [], ); + set( + contextStoreFilterGroupsComponentState.atomFamily({ + instanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID, + }), + [], + ); + set( contextStoreAnyFieldFilterValueComponentState.atomFamily({ instanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID, diff --git a/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts b/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts index 02f1ebc48e..9cb0e5eb34 100644 --- a/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts +++ b/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts @@ -1,5 +1,6 @@ import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState'; import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; @@ -37,6 +38,11 @@ export const useFindManyRecordsSelectedInContextStore = ({ instanceId, ); + const contextStoreFilterGroups = useRecoilComponentValue( + contextStoreFilterGroupsComponentState, + instanceId, + ); + const contextStoreAnyFieldFilterValue = useRecoilComponentValue( contextStoreAnyFieldFilterValueComponentState, instanceId, @@ -61,13 +67,14 @@ export const useFindManyRecordsSelectedInContextStore = ({ ); }); - const queryFilter = computeContextStoreFilters( + const queryFilter = computeContextStoreFilters({ contextStoreTargetedRecordsRule, contextStoreFilters, + contextStoreFilterGroups, objectMetadataItem, filterValueDependencies, contextStoreAnyFieldFilterValue, - ); + }); const { records, loading, totalCount } = useFindManyRecords({ objectNameSingular: objectMetadataItem?.nameSingular ?? '', diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreFilterGroupsComponentState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreFilterGroupsComponentState.ts new file mode 100644 index 0000000000..713dbd5b56 --- /dev/null +++ b/packages/twenty-front/src/modules/context-store/states/contextStoreFilterGroupsComponentState.ts @@ -0,0 +1,11 @@ +import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; +import { type RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup'; +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; + +export const contextStoreFilterGroupsComponentState = createComponentState< + RecordFilterGroup[] +>({ + key: 'contextStoreFilterGroupsComponentState', + defaultValue: [], + componentInstanceContext: ContextStoreComponentInstanceContext, +}); diff --git a/packages/twenty-front/src/modules/context-store/utils/__tests__/computeContextStoreFilters.test.ts b/packages/twenty-front/src/modules/context-store/utils/__tests__/computeContextStoreFilters.test.ts index b59d33db4e..b62850167f 100644 --- a/packages/twenty-front/src/modules/context-store/utils/__tests__/computeContextStoreFilters.test.ts +++ b/packages/twenty-front/src/modules/context-store/utils/__tests__/computeContextStoreFilters.test.ts @@ -20,13 +20,14 @@ describe('computeContextStoreFilters', () => { selectedRecordIds: ['1', '2', '3'], }; - const filters = computeContextStoreFilters( + const filters = computeContextStoreFilters({ contextStoreTargetedRecordsRule, - [], - personObjectMetadataItem, - mockFilterValueDependencies, - '', - ); + contextStoreFilters: [], + contextStoreFilterGroups: [], + objectMetadataItem: personObjectMetadataItem, + filterValueDependencies: mockFilterValueDependencies, + contextStoreAnyFieldFilterValue: '', + }); expect(filters).toEqual({ and: [ @@ -63,13 +64,14 @@ describe('computeContextStoreFilters', () => { }, ]; - const filters = computeContextStoreFilters( + const filters = computeContextStoreFilters({ contextStoreTargetedRecordsRule, contextStoreFilters, - personObjectMetadataItem, - mockFilterValueDependencies, - '', - ); + contextStoreFilterGroups: [], + objectMetadataItem: personObjectMetadataItem, + filterValueDependencies: mockFilterValueDependencies, + contextStoreAnyFieldFilterValue: '', + }); expect(filters).toEqual({ and: [ diff --git a/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts b/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts index 9a77de791b..e0d7f32b96 100644 --- a/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts +++ b/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts @@ -1,24 +1,35 @@ import { type ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter'; +import { type RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup'; import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { type RecordFilterValueDependencies } from '@/object-record/record-filter/types/RecordFilterValueDependencies'; import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeRecordGqlOperationFilter'; import { turnAnyFieldFilterIntoRecordGqlFilter } from '@/object-record/record-filter/utils/turnAnyFieldFilterIntoRecordGqlFilter'; import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables'; -export const computeContextStoreFilters = ( - contextStoreTargetedRecordsRule: ContextStoreTargetedRecordsRule, - contextStoreFilters: RecordFilter[], - objectMetadataItem: ObjectMetadataItem, - filterValueDependencies: RecordFilterValueDependencies, - anyFieldFilterValue: string, -) => { +type ComputeContextStoreFiltersProps = { + contextStoreTargetedRecordsRule: ContextStoreTargetedRecordsRule; + contextStoreFilters: RecordFilter[]; + contextStoreFilterGroups: RecordFilterGroup[]; + objectMetadataItem: ObjectMetadataItem; + filterValueDependencies: RecordFilterValueDependencies; + contextStoreAnyFieldFilterValue: string; +}; + +export const computeContextStoreFilters = ({ + contextStoreTargetedRecordsRule, + contextStoreFilters, + contextStoreFilterGroups, + objectMetadataItem, + filterValueDependencies, + contextStoreAnyFieldFilterValue, +}: ComputeContextStoreFiltersProps) => { let queryFilter: RecordGqlOperationFilter | undefined; const { recordGqlOperationFilter: recordGqlFilterForAnyFieldFilter } = turnAnyFieldFilterIntoRecordGqlFilter({ - filterValue: anyFieldFilterValue, + filterValue: contextStoreAnyFieldFilterValue, objectMetadataItem, }); @@ -29,7 +40,7 @@ export const computeContextStoreFilters = ( filterValueDependencies, fields: objectMetadataItem?.fields ?? [], recordFilters: contextStoreFilters, - recordFilterGroups: [], + recordFilterGroups: contextStoreFilterGroups, }), contextStoreTargetedRecordsRule.excludedRecordIds.length > 0 ? { @@ -56,7 +67,7 @@ export const computeContextStoreFilters = ( filterValueDependencies, fields: objectMetadataItem?.fields ?? [], recordFilters: contextStoreFilters, - recordFilterGroups: [], + recordFilterGroups: contextStoreFilterGroups, }), ]); } diff --git a/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts index 437d9b3e7c..1868374f30 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useFindManyRecords.ts @@ -15,6 +15,8 @@ import { type ObjectRecord } from '@/object-record/types/ObjectRecord'; import { type OnFindManyRecordsCompleted } from '@/object-record/types/OnFindManyRecordsCompleted'; import { getQueryIdentifier } from '@/object-record/utils/getQueryIdentifier'; +import { type RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter'; + export type UseFindManyRecordsParams = ObjectMetadataItemIdentifier & RecordGqlOperationVariables & { onError?: (error?: Error) => void; @@ -53,9 +55,19 @@ export const useFindManyRecords = ({ handleError: onError, }); + const softDeleteFilter: RecordGqlOperationFilter = { + or: [{ deletedAt: { is: 'NULL' } }, { deletedAt: { is: 'NOT_NULL' } }], + }; + + const withSoftDeleteFilter = withSoftDeleted + ? { + and: [...(filter ? [filter] : []), softDeleteFilter], + } + : filter; + const queryIdentifier = getQueryIdentifier({ objectNameSingular, - filter, + filter: withSoftDeleteFilter, orderBy, limit, }); @@ -66,10 +78,6 @@ export const useFindManyRecords = ({ onCompleted, }); - const withSoftDeleterFilter = { - or: [{ deletedAt: { is: 'NULL' } }, { deletedAt: { is: 'NOT_NULL' } }], - }; - const objectPermissions = useObjectPermissionsForObject( objectMetadataItem.id, ); @@ -80,14 +88,7 @@ export const useFindManyRecords = ({ useQuery(findManyRecordsQuery, { skip: skip || !objectMetadataItem || !hasReadPermission, variables: { - filter: withSoftDeleted - ? { - and: [ - ...(filter ? [filter] : []), - ...(withSoftDeleted ? [withSoftDeleterFilter] : []), - ], - } - : filter, + filter: withSoftDeleteFilter, orderBy, lastCursor: cursorFilter?.cursor ?? undefined, limit, @@ -101,7 +102,7 @@ export const useFindManyRecords = ({ const { fetchMoreRecords, records, hasNextPage } = useFetchMoreRecordsWithPagination({ objectNameSingular, - filter, + filter: withSoftDeleteFilter, orderBy, limit, fetchMore, diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect.tsx index 077d6c42f4..b0871c2f8b 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect.tsx @@ -1,4 +1,5 @@ import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; @@ -41,24 +42,31 @@ export const RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect = contextStoreFiltersComponentState, ); + const contextStoreFilterGroups = useRecoilComponentValue( + contextStoreFilterGroupsComponentState, + ); + const contextStoreAnyFieldFilterValue = useRecoilComponentValue( contextStoreAnyFieldFilterValueComponentState, ); const { filterValueDependencies } = useFilterValueDependencies(); + const computedFilter = computeContextStoreFilters({ + contextStoreTargetedRecordsRule, + contextStoreFilters, + contextStoreFilterGroups, + objectMetadataItem, + filterValueDependencies, + contextStoreAnyFieldFilterValue, + }); + const { totalCount } = useFindManyRecords({ ...findManyRecordsParams, recordGqlFields: { id: true, }, - filter: computeContextStoreFilters( - contextStoreTargetedRecordsRule, - contextStoreFilters, - objectMetadataItem, - filterValueDependencies, - contextStoreAnyFieldFilterValue, - ), + filter: computedFilter, limit: 1, skip: contextStoreTargetedRecordsRule.mode === 'selection', }); diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexFiltersToContextStoreEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexFiltersToContextStoreEffect.tsx index f7caa718de..22b8ff1f7e 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexFiltersToContextStoreEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexFiltersToContextStoreEffect.tsx @@ -1,8 +1,10 @@ import { useEffect } from 'react'; import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; +import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState'; import { anyFieldFilterValueComponentState } from '@/object-record/record-filter/states/anyFieldFilterValueComponentState'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; @@ -20,6 +22,11 @@ export const RecordIndexFiltersToContextStoreEffect = () => { recordIndexId, ); + const recordIndexFilterGroups = useRecoilComponentValue( + currentRecordFilterGroupsComponentState, + recordIndexId, + ); + const setContextStoreTargetedRecords = useSetRecoilComponentState( contextStoreTargetedRecordsRuleComponentState, ); @@ -68,13 +75,23 @@ export const RecordIndexFiltersToContextStoreEffect = () => { contextStoreFiltersComponentState, ); + const setContextStoreFilterGroups = useSetRecoilComponentState( + contextStoreFilterGroupsComponentState, + ); + useEffect(() => { setContextStoreFilters(recordIndexFilters); + setContextStoreFilterGroups(recordIndexFilterGroups); return () => { setContextStoreFilters([]); }; - }, [recordIndexFilters, setContextStoreFilters]); + }, [ + recordIndexFilterGroups, + recordIndexFilters, + setContextStoreFilterGroups, + setContextStoreFilters, + ]); const setContextStoreAnyFieldFilterValue = useSetRecoilComponentState( contextStoreAnyFieldFilterValueComponentState, diff --git a/packages/twenty-front/src/modules/object-record/record-index/export/hooks/useRecordIndexLazyFetchRecords.ts b/packages/twenty-front/src/modules/object-record/record-index/export/hooks/useRecordIndexLazyFetchRecords.ts index 386fa335c5..cc2ee57034 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/export/hooks/useRecordIndexLazyFetchRecords.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/export/hooks/useRecordIndexLazyFetchRecords.ts @@ -3,6 +3,7 @@ import { type ColumnDefinition } from '@/object-record/record-table/types/Column import { type ObjectRecord } from '@/object-record/types/ObjectRecord'; import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; @@ -73,6 +74,10 @@ export const useRecordIndexLazyFetchRecords = ({ contextStoreFiltersComponentState, ); + const contextStoreFilterGroups = useRecoilComponentValue( + contextStoreFilterGroupsComponentState, + ); + const contextStoreAnyFieldFilterValue = useRecoilComponentValue( contextStoreAnyFieldFilterValueComponentState, ); @@ -83,13 +88,14 @@ export const useRecordIndexLazyFetchRecords = ({ objectMetadataItem.nameSingular, ); - const queryFilter = computeContextStoreFilters( + const queryFilter = computeContextStoreFilters({ contextStoreTargetedRecordsRule, contextStoreFilters, + contextStoreFilterGroups, objectMetadataItem, filterValueDependencies, contextStoreAnyFieldFilterValue, - ); + }); const finalColumns = [ ...columns, diff --git a/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx b/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx index 590dfc378e..a666d1930c 100644 --- a/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx +++ b/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx @@ -3,6 +3,7 @@ import { type PropsWithChildren, useEffect, useState } from 'react'; import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState'; +import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { @@ -11,6 +12,7 @@ import { } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { type ContextStoreViewType } from '@/context-store/types/ContextStoreViewType'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { type RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup'; import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState'; @@ -18,6 +20,7 @@ export type JestContextStoreSetterMocks = { contextStoreTargetedRecordsRule?: ContextStoreTargetedRecordsRule; contextStoreNumberOfSelectedRecords?: number; contextStoreFilters?: RecordFilter[]; + contextStoreFilterGroups?: RecordFilterGroup[]; contextStoreCurrentObjectMetadataNameSingular?: string; contextStoreCurrentViewId?: string; contextStoreCurrentViewType?: ContextStoreViewType; @@ -34,6 +37,7 @@ export const JestContextStoreSetter = ({ contextStoreNumberOfSelectedRecords = 0, contextStoreCurrentObjectMetadataNameSingular = 'company', contextStoreFilters = [], + contextStoreFilterGroups = [], contextStoreCurrentViewType, children, }: JestContextStoreSetterProps) => { @@ -53,6 +57,10 @@ export const JestContextStoreSetter = ({ contextStoreFiltersComponentState, ); + const setContextStoreFilterGroupsComponentState = useSetRecoilComponentState( + contextStoreFilterGroupsComponentState, + ); + const setContextStoreCurrentViewId = useSetRecoilComponentState( contextStoreCurrentViewIdComponentState, ); @@ -74,6 +82,7 @@ export const JestContextStoreSetter = ({ setContextStoreCurrentObjectMetadataItemId(objectMetadataItem.id); setContextStoreNumberOfSelectedRecords(contextStoreNumberOfSelectedRecords); setcontextStoreFiltersComponentState(contextStoreFilters); + setContextStoreFilterGroupsComponentState(contextStoreFilterGroups); setContextStoreCurrentViewType(contextStoreCurrentViewType ?? null); setIsLoaded(true); }, [ @@ -90,6 +99,8 @@ export const JestContextStoreSetter = ({ contextStoreCurrentViewId, setContextStoreCurrentViewType, contextStoreCurrentViewType, + setContextStoreFilterGroupsComponentState, + contextStoreFilterGroups, ]); return isLoaded ? <>{children} : null;