From 5a53ef1ade824b8147b120b204c425c0565a9ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?= <71827178+bosiraphael@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:38:45 +0100 Subject: [PATCH] Make filters work on export csv action (#8389) - Create a new component state `contextStoreFiltersComponentState` and refactor `contextStoreTargetedRecordsRuleComponentState` - Refactor `computeContextStoreFilters` to use filters when no records are selected --- .../components/DeleteRecordsActionEffect.tsx | 6 +++ .../contextStoreFiltersComponentState.ts | 11 +++++ ...tStoreTargetedRecordsRuleComponentState.ts | 2 - .../computeContextStoreFilters.test.ts | 48 +++++++++++-------- .../utils/computeContextStoreFilters.ts | 10 +++- ...textStoreNumberOfSelectedRecordsEffect.tsx | 6 +++ .../RecordIndexTableContainerEffect.tsx | 15 +++++- .../hooks/__tests__/useRecordData.test.tsx | 2 +- .../options/hooks/useRecordData.ts | 6 +++ 9 files changed, 78 insertions(+), 28 deletions(-) create mode 100644 packages/twenty-front/src/modules/context-store/states/contextStoreFiltersComponentState.ts diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx index b4c7e585c1..515852428a 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx @@ -1,5 +1,6 @@ import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries'; +import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; @@ -45,8 +46,13 @@ export const DeleteRecordsActionEffect = ({ contextStoreTargetedRecordsRuleComponentState, ); + const contextStoreFilters = useRecoilComponentValueV2( + contextStoreFiltersComponentState, + ); + const graphqlFilter = computeContextStoreFilters( contextStoreTargetedRecordsRule, + contextStoreFilters, objectMetadataItem, ); diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreFiltersComponentState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreFiltersComponentState.ts new file mode 100644 index 0000000000..97e628deb4 --- /dev/null +++ b/packages/twenty-front/src/modules/context-store/states/contextStoreFiltersComponentState.ts @@ -0,0 +1,11 @@ +import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; +import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; + +export const contextStoreFiltersComponentState = createComponentStateV2< + Filter[] +>({ + key: 'contextStoreFiltersComponentState', + defaultValue: [], + componentInstanceContext: ContextStoreComponentInstanceContext, +}); diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordsRuleComponentState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordsRuleComponentState.ts index 1540c05f3f..296884fd04 100644 --- a/packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordsRuleComponentState.ts +++ b/packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordsRuleComponentState.ts @@ -1,5 +1,4 @@ import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; -import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; type ContextStoreTargetedRecordsRuleSelectionMode = { @@ -10,7 +9,6 @@ type ContextStoreTargetedRecordsRuleSelectionMode = { type ContextStoreTargetedRecordsRuleExclusionMode = { mode: 'exclusion'; excludedRecordIds: string[]; - filters: Filter[]; }; export type ContextStoreTargetedRecordsRule = 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 1c65848ede..4ea9f4a7a3 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 @@ -1,6 +1,8 @@ import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; +import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { expect } from '@storybook/test'; import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems'; describe('computeContextStoreFilters', () => { const personObjectMetadataItem = generatedMockObjectMetadataItems.find( @@ -15,6 +17,7 @@ describe('computeContextStoreFilters', () => { const filters = computeContextStoreFilters( contextStoreTargetedRecordsRule, + [], personObjectMetadataItem, ); @@ -28,32 +31,35 @@ describe('computeContextStoreFilters', () => { it('should work for exclusion mode', () => { const contextStoreTargetedRecordsRule: ContextStoreTargetedRecordsRule = { mode: 'exclusion', - filters: [ - { - id: 'name-filter', - variant: 'default', - fieldMetadataId: personObjectMetadataItem.fields.find( - (field) => field.name === 'name', - )!.id, - value: 'John', - displayValue: 'John', - displayAvatarUrl: undefined, - operand: ViewFilterOperand.Contains, - definition: { - fieldMetadataId: personObjectMetadataItem.fields.find( - (field) => field.name === 'name', - )!.id, - label: 'Name', - iconName: 'person', - type: 'TEXT', - }, - }, - ], + excludedRecordIds: ['1', '2', '3'], }; + const contextStoreFilters: Filter[] = [ + { + id: 'name-filter', + variant: 'default', + fieldMetadataId: personObjectMetadataItem.fields.find( + (field) => field.name === 'name', + )!.id, + value: 'John', + displayValue: 'John', + displayAvatarUrl: undefined, + operand: ViewFilterOperand.Contains, + definition: { + fieldMetadataId: personObjectMetadataItem.fields.find( + (field) => field.name === 'name', + )!.id, + label: 'Name', + iconName: 'person', + type: 'TEXT', + }, + }, + ]; + const filters = computeContextStoreFilters( contextStoreTargetedRecordsRule, + contextStoreFilters, personObjectMetadataItem, ); 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 5126ae272c..e685c35f59 100644 --- a/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts +++ b/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts @@ -1,11 +1,13 @@ import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter'; +import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter'; import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables'; export const computeContextStoreFilters = ( contextStoreTargetedRecordsRule: ContextStoreTargetedRecordsRule, + contextStoreFilters: Filter[], objectMetadataItem: ObjectMetadataItem, ) => { let queryFilter: RecordGqlOperationFilter | undefined; @@ -13,7 +15,7 @@ export const computeContextStoreFilters = ( if (contextStoreTargetedRecordsRule.mode === 'exclusion') { queryFilter = makeAndFilterVariables([ computeViewRecordGqlOperationFilter( - contextStoreTargetedRecordsRule.filters, + contextStoreFilters, objectMetadataItem?.fields ?? [], [], ), @@ -36,7 +38,11 @@ export const computeContextStoreFilters = ( in: contextStoreTargetedRecordsRule.selectedRecordIds, }, } - : undefined; + : computeViewRecordGqlOperationFilter( + contextStoreFilters, + objectMetadataItem?.fields ?? [], + [], + ); } return queryFilter; 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 602ed22723..d6c6f94dcf 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,3 +1,4 @@ +import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; @@ -35,6 +36,10 @@ export const RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect = objectMetadataItem?.namePlural ?? '', ); + const contextStoreFilters = useRecoilComponentValueV2( + contextStoreFiltersComponentState, + ); + const { totalCount } = useFindManyRecords({ ...findManyRecordsParams, recordGqlFields: { @@ -42,6 +47,7 @@ export const RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect = }, filter: computeContextStoreFilters( contextStoreTargetedRecordsRule, + contextStoreFilters, objectMetadataItem, ), limit: 1, diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx index 0c73aff12f..314b66cef2 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx @@ -1,5 +1,6 @@ import { useContext, useEffect } from 'react'; +import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; @@ -99,7 +100,6 @@ export const RecordIndexTableContainerEffect = () => { setContextStoreTargetedRecords({ mode: 'exclusion', excludedRecordIds: unselectedRowIds, - filters: recordIndexFilters, }); } else { setContextStoreTargetedRecords({ @@ -116,11 +116,22 @@ export const RecordIndexTableContainerEffect = () => { }; }, [ hasUserSelectedAllRows, - recordIndexFilters, selectedRowIds, setContextStoreTargetedRecords, unselectedRowIds, ]); + const setContextStoreFilters = useSetRecoilComponentStateV2( + contextStoreFiltersComponentState, + ); + + useEffect(() => { + setContextStoreFilters(recordIndexFilters); + + return () => { + setContextStoreFilters([]); + }; + }, [recordIndexFilters, setContextStoreFilters]); + return <>; }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useRecordData.test.tsx b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useRecordData.test.tsx index d7dc9df12c..4190d08b1a 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useRecordData.test.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useRecordData.test.tsx @@ -106,7 +106,7 @@ const mocks: MockedResponse[] = [ } `, variables: { - filter: undefined, + filter: {}, limit: 30, orderBy: [{ position: 'AscNullsFirst' }], }, diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordData.ts b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordData.ts index 8ef63ca85d..a541d65b23 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordData.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordData.ts @@ -6,6 +6,7 @@ import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefin import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { isDefined } from '~/utils/isDefined'; +import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; @@ -81,8 +82,13 @@ export const useRecordData = ({ contextStoreTargetedRecordsRuleComponentState, ); + const contextStoreFilters = useRecoilComponentValueV2( + contextStoreFiltersComponentState, + ); + const queryFilter = computeContextStoreFilters( contextStoreTargetedRecordsRule, + contextStoreFilters, objectMetadataItem, );