From b12b2485c5e10ec8794c369bdce2a1529fb2c9a0 Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Fri, 14 Mar 2025 14:41:30 +0100 Subject: [PATCH] Fixed kanban for advanced filters and other bugs (#10888) This PR mainly fixes advanced filters on kanban view. It also fixes various bugs and cleans some old states. ## Advanced filters on kanban views Kanban views use a different hook to retrieve data from the backend : useLoadRecordIndexBoardColumn, this hook wasn't using the new state currentRecordFilterGroupsComponentState. ## Removal of confusing duplicate states A few different states were used for filters and states, where we only need one for filters and one for sorts for all indexes. So we remove here the different states that can lead to confusion about what state should be used in what case. States removed : - recordIndexFilterState - recordIndexSortState - recordIndexViewFilterGroupsState - tableFiltersComponentState - tableSortsComponentState We also remove the logic that was used to manage those states. ## Abstracted non composite field type check into a util We abstract the check made in mapFieldMetadataToGraphQLQuery into a util isNonCompositeField, because those kinds of checks should be stored into a separate unique file that acts as a source of truth. ## Bug with advanced filter rule position not saved The position of an advanced filter rule wasn't correctly saved in the backend, here we remove the WorkspaceIsSystem decorator on the positionInViewFilterGroup fields. The function that saved view filters was also ignoring the field positionInViewFilterGroup, we add it back. ## Bug with view picker option dropdown closing weirdly The view picker option dropdown was closing as soon as we hovered outside of the option dropdown, which was annoying for the user, here we apply the same behavior as every dropdown in the app : closing on click outside. --- .../utils/mapFieldMetadataToGraphQLQuery.ts | 19 ++------ .../utils/isNonCompositeField.ts | 25 ++++++++++ .../hooks/useLoadRecordIndexBoardColumn.ts | 14 ++---- .../hooks/useLoadRecordIndexStates.ts | 46 ++----------------- .../states/recordIndexFiltersState.ts | 8 ---- .../states/recordIndexSortsState.ts | 7 --- .../recordIndexViewFilterGroupsState.ts | 7 --- .../RecordTableEmptyStateSoftDelete.tsx | 9 ++-- .../hooks/useAggregateRecordsForHeader.ts | 20 ++++---- .../record-table/hooks/useRecordTable.ts | 14 ------ ...BodyRecordGroupDragDropContextProvider.tsx | 13 ++++-- ...egateRecordsForRecordTableColumnFooter.tsx | 13 ++---- .../states/tableFiltersComponentState.ts | 11 ----- .../states/tableSortsComponentState.ts | 9 ---- .../internal/usePersistViewFilterRecords.ts | 7 ++- .../components/ViewPickerOptionDropdown.tsx | 1 - .../view-filter-group.workspace-entity.ts | 1 - .../view-filter.workspace-entity.ts | 1 - 18 files changed, 68 insertions(+), 157 deletions(-) create mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/isNonCompositeField.ts delete mode 100644 packages/twenty-front/src/modules/object-record/record-index/states/recordIndexFiltersState.ts delete mode 100644 packages/twenty-front/src/modules/object-record/record-index/states/recordIndexSortsState.ts delete mode 100644 packages/twenty-front/src/modules/object-record/record-index/states/recordIndexViewFilterGroupsState.ts delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/states/tableFiltersComponentState.ts delete mode 100644 packages/twenty-front/src/modules/object-record/record-table/states/tableSortsComponentState.ts diff --git a/packages/twenty-front/src/modules/object-metadata/utils/mapFieldMetadataToGraphQLQuery.ts b/packages/twenty-front/src/modules/object-metadata/utils/mapFieldMetadataToGraphQLQuery.ts index 3428a712c..0599d68fb 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/mapFieldMetadataToGraphQLQuery.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/mapFieldMetadataToGraphQLQuery.ts @@ -7,6 +7,7 @@ import { import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { RecordGqlFields } from '@/object-record/graphql/types/RecordGqlFields'; +import { isNonCompositeField } from '@/object-record/object-filter-dropdown/utils/isNonCompositeField'; import { FieldMetadataItem } from '../types/FieldMetadataItem'; type MapFieldMetadataToGraphQLQueryArgs = { @@ -24,23 +25,9 @@ export const mapFieldMetadataToGraphQLQuery = ({ }: MapFieldMetadataToGraphQLQueryArgs): string => { const fieldType = field.type; - const fieldIsSimpleValue = [ - FieldMetadataType.UUID, - FieldMetadataType.TEXT, - FieldMetadataType.DATE_TIME, - FieldMetadataType.DATE, - FieldMetadataType.NUMBER, - FieldMetadataType.BOOLEAN, - FieldMetadataType.RATING, - FieldMetadataType.SELECT, - FieldMetadataType.MULTI_SELECT, - FieldMetadataType.POSITION, - FieldMetadataType.RAW_JSON, - FieldMetadataType.RICH_TEXT, - FieldMetadataType.ARRAY, - ].includes(fieldType); + const fieldIsNonCompositeField = isNonCompositeField(fieldType); - if (fieldIsSimpleValue) { + if (fieldIsNonCompositeField) { return field.name; } diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/isNonCompositeField.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/isNonCompositeField.ts new file mode 100644 index 000000000..981c73e14 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/isNonCompositeField.ts @@ -0,0 +1,25 @@ +import { FieldType } from '@/settings/data-model/types/FieldType'; +import { FieldMetadataType } from 'twenty-shared'; + +// TODO: see why RELATION is considered as a non composite type in settings, because it prevents this function +// to be a typeguard +export const isNonCompositeField = (type: FieldType) => { + const fieldIsSimpleValue = [ + FieldMetadataType.UUID, + FieldMetadataType.TEXT, + FieldMetadataType.DATE_TIME, + FieldMetadataType.DATE, + FieldMetadataType.NUMBER, + FieldMetadataType.NUMERIC, + FieldMetadataType.BOOLEAN, + FieldMetadataType.RATING, + FieldMetadataType.SELECT, + FieldMetadataType.MULTI_SELECT, + FieldMetadataType.POSITION, + FieldMetadataType.RAW_JSON, + FieldMetadataType.RICH_TEXT, + FieldMetadataType.ARRAY, + ].includes(type as any); + + return fieldIsSimpleValue; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts index 304c472fd..ead6b4b3e 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts @@ -5,17 +5,17 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy'; import { useSetRecordIdsForColumn } from '@/object-record/record-board/hooks/useSetRecordIdsForColumn'; +import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState'; import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter'; import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState'; import { useRecordBoardRecordGqlFields } from '@/object-record/record-index/hooks/useRecordBoardRecordGqlFields'; import { useSetRecordIndexEntityCount } from '@/object-record/record-index/hooks/useSetRecordIndexEntityCount'; -import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState'; + import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState'; import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { mapViewFilterGroupsToRecordFilterGroups } from '@/views/utils/mapViewFilterGroupsToRecordFilterGroups'; import { isDefined } from 'twenty-shared'; type UseLoadRecordIndexBoardProps = { @@ -41,12 +41,8 @@ export const useLoadRecordIndexBoardColumn = ({ recordGroupDefinitionFamilyState(columnId), ); - const recordIndexViewFilterGroups = useRecoilValue( - recordIndexViewFilterGroupsState, - ); - - const recordFilterGroups = mapViewFilterGroupsToRecordFilterGroups( - recordIndexViewFilterGroups, + const currentRecordFilterGroups = useRecoilComponentValueV2( + currentRecordFilterGroupsComponentState, ); const currentRecordFilters = useRecoilComponentValueV2( @@ -62,7 +58,7 @@ export const useLoadRecordIndexBoardColumn = ({ const requestFilters = computeRecordGqlOperationFilter({ filterValueDependencies, recordFilters: currentRecordFilters, - recordFilterGroups, + recordFilterGroups: currentRecordFilterGroups, fields: objectMetadataItem.fields, }); diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts index 44fa81a6a..d270bb78e 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts @@ -6,18 +6,13 @@ import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/uti import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { useSetRecordGroups } from '@/object-record/record-group/hooks/useSetRecordGroups'; import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState'; -import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState'; import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState'; import { recordIndexKanbanAggregateOperationState } from '@/object-record/record-index/states/recordIndexKanbanAggregateOperationState'; import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState'; import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState'; -import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState'; -import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState'; import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState'; import { useSetTableColumns } from '@/object-record/record-table/hooks/useSetTableColumns'; import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState'; -import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState'; -import { tableSortsComponentState } from '@/object-record/record-table/states/tableSortsComponentState'; import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition'; import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation'; import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns'; @@ -27,7 +22,6 @@ import { View } from '@/views/types/View'; import { ViewField } from '@/views/types/ViewField'; import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; -import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; import { useRecoilCallback, useSetRecoilState } from 'recoil'; import { isDefined } from 'twenty-shared'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; @@ -36,12 +30,6 @@ export const useLoadRecordIndexStates = () => { const setContextStoreTargetedRecordsRuleComponentState = useSetRecoilComponentStateV2(contextStoreTargetedRecordsRuleComponentState); - const setRecordIndexViewFilterGroups = useSetRecoilState( - recordIndexViewFilterGroupsState, - ); - - const setRecordIndexFilters = useSetRecoilState(recordIndexFiltersState); - const setRecordIndexSorts = useSetRecoilState(recordIndexSortsState); const setRecordIndexIsCompactModeActive = useSetRecoilState( recordIndexIsCompactModeActiveState, ); @@ -172,7 +160,7 @@ export const useLoadRecordIndexStates = () => { ); const loadRecordIndexStates = useRecoilCallback( - ({ snapshot, set }) => + ({ snapshot }) => async (view: View, objectMetadataItem: ObjectMetadataItem) => { const recordIndexId = getRecordIndexIdFromObjectNamePluralAndViewId( objectMetadataItem.namePlural, @@ -190,22 +178,6 @@ export const useLoadRecordIndexStates = () => { onViewFieldsChange(view.viewFields, objectMetadataItem, recordIndexId); setRecordGroupsFromViewGroups(view.id, view.viewGroups); - set( - tableFiltersComponentState.atomFamily({ - instanceId: recordIndexId, - }), - mapViewFiltersToFilters( - view.viewFilters, - filterableFieldMetadataItems, - ), - ); - setRecordIndexFilters( - mapViewFiltersToFilters( - view.viewFilters, - filterableFieldMetadataItems, - ), - ); - setRecordIndexViewFilterGroups(view.viewFilterGroups ?? []); setContextStoreTargetedRecordsRuleComponentState((prev) => ({ ...prev, filters: mapViewFiltersToFilters( @@ -214,13 +186,6 @@ export const useLoadRecordIndexStates = () => { ), })); - set( - tableSortsComponentState.atomFamily({ - instanceId: recordIndexId, - }), - mapViewSortsToSorts(view.viewSorts), - ); - setRecordIndexSorts(mapViewSortsToSorts(view.viewSorts)); setRecordIndexViewType(view.type); setRecordIndexOpenRecordIn(view.openRecordIn); setRecordIndexViewKanbanFieldMetadataIdState( @@ -245,15 +210,12 @@ export const useLoadRecordIndexStates = () => { [ onViewFieldsChange, setRecordGroupsFromViewGroups, - setRecordIndexFilters, - setRecordIndexViewFilterGroups, setContextStoreTargetedRecordsRuleComponentState, - setRecordIndexSorts, + setRecordIndexIsCompactModeActive, + setRecordIndexViewKanbanAggregateOperationState, + setRecordIndexViewKanbanFieldMetadataIdState, setRecordIndexViewType, setRecordIndexOpenRecordIn, - setRecordIndexViewKanbanFieldMetadataIdState, - setRecordIndexViewKanbanAggregateOperationState, - setRecordIndexIsCompactModeActive, ], ); diff --git a/packages/twenty-front/src/modules/object-record/record-index/states/recordIndexFiltersState.ts b/packages/twenty-front/src/modules/object-record/record-index/states/recordIndexFiltersState.ts deleted file mode 100644 index b60300f83..000000000 --- a/packages/twenty-front/src/modules/object-record/record-index/states/recordIndexFiltersState.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createState } from '@ui/utilities/state/utils/createState'; - -import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; - -export const recordIndexFiltersState = createState({ - key: 'recordIndexFiltersState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/object-record/record-index/states/recordIndexSortsState.ts b/packages/twenty-front/src/modules/object-record/record-index/states/recordIndexSortsState.ts deleted file mode 100644 index 9ce465acb..000000000 --- a/packages/twenty-front/src/modules/object-record/record-index/states/recordIndexSortsState.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { RecordSort } from '@/object-record/record-sort/types/RecordSort'; -import { createState } from '@ui/utilities/state/utils/createState'; - -export const recordIndexSortsState = createState({ - key: 'recordIndexSortsState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/object-record/record-index/states/recordIndexViewFilterGroupsState.ts b/packages/twenty-front/src/modules/object-record/record-index/states/recordIndexViewFilterGroupsState.ts deleted file mode 100644 index ea07e363d..000000000 --- a/packages/twenty-front/src/modules/object-record/record-index/states/recordIndexViewFilterGroupsState.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ViewFilterGroup } from '@/views/types/ViewFilterGroup'; -import { createState } from '@ui/utilities/state/utils/createState'; - -export const recordIndexViewFilterGroupsState = createState({ - key: 'recordIndexViewFilterGroupsState', - defaultValue: [], -}); diff --git a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx index 42d761f8f..d17ca9c6d 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/empty-state/components/RecordTableEmptyStateSoftDelete.tsx @@ -6,18 +6,17 @@ import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRe import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { RecordTableEmptyStateDisplay } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay'; -import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; import { isDefined } from 'twenty-shared'; export const RecordTableEmptyStateSoftDelete = () => { const { objectMetadataItem, objectNameSingular, recordTableId } = useRecordTableContextOrThrow(); - const tableFilters = useRecoilComponentValueV2( - tableFiltersComponentState, - recordTableId, + const currentRecordFilters = useRecoilComponentValueV2( + currentRecordFiltersComponentState, ); const { toggleSoftDeleteFilterState } = useHandleToggleTrashColumnFilter({ @@ -30,7 +29,7 @@ export const RecordTableEmptyStateSoftDelete = () => { const { checkIsSoftDeleteFilter } = useCheckIsSoftDeleteFilter(); const handleButtonClick = async () => { - const deletedFilter = tableFilters.find(checkIsSoftDeleteFilter); + const deletedFilter = currentRecordFilters.find(checkIsSoftDeleteFilter); if (!isDefined(deletedFilter)) { throw new Error('Deleted filter not found'); diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useAggregateRecordsForHeader.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useAggregateRecordsForHeader.ts index 684b7bc4c..97de061d6 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useAggregateRecordsForHeader.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useAggregateRecordsForHeader.ts @@ -2,13 +2,13 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { useAggregateRecords } from '@/object-record/hooks/useAggregateRecords'; import { buildRecordGqlFieldsAggregateForView } from '@/object-record/record-board/record-board-column/utils/buildRecordGqlFieldsAggregateForView'; import { computeAggregateValueAndLabel } from '@/object-record/record-board/record-board-column/utils/computeAggregateValueAndLabel'; +import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState'; import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies'; +import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter'; -import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState'; import { recordIndexKanbanAggregateOperationState } from '@/object-record/record-index/states/recordIndexKanbanAggregateOperationState'; -import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { UserContext } from '@/users/contexts/UserContext'; -import { mapViewFilterGroupsToRecordFilterGroups } from '@/views/utils/mapViewFilterGroupsToRecordFilterGroups'; import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; @@ -23,16 +23,14 @@ export const useAggregateRecordsForHeader = ({ objectMetadataItem, additionalFilters = {}, }: UseAggregateRecordsProps) => { - const recordIndexViewFilterGroups = useRecoilValue( - recordIndexViewFilterGroupsState, + const currentRecordFilterGroups = useRecoilComponentValueV2( + currentRecordFilterGroupsComponentState, ); - const recordFilterGroups = mapViewFilterGroupsToRecordFilterGroups( - recordIndexViewFilterGroups, + const currentRecordFilters = useRecoilComponentValueV2( + currentRecordFiltersComponentState, ); - const recordIndexFilters = useRecoilValue(recordIndexFiltersState); - const recordIndexKanbanAggregateOperation = useRecoilValue( recordIndexKanbanAggregateOperationState, ); @@ -43,8 +41,8 @@ export const useAggregateRecordsForHeader = ({ const requestFilters = computeRecordGqlOperationFilter({ filterValueDependencies, - recordFilters: recordIndexFilters, - recordFilterGroups, + recordFilters: currentRecordFilters, + recordFilterGroups: currentRecordFilterGroups, fields: objectMetadataItem.fields, }); diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts index d0d6784ea..90b96d1b9 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts @@ -22,9 +22,7 @@ import { onColumnsChangeComponentState } from '@/object-record/record-table/stat import { onEntityCountChangeComponentState } from '@/object-record/record-table/states/onEntityCountChangeComponentState'; import { onToggleColumnFilterComponentState } from '@/object-record/record-table/states/onToggleColumnFilterComponentState'; import { onToggleColumnSortComponentState } from '@/object-record/record-table/states/onToggleColumnSortComponentState'; -import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState'; import { tableLastRowVisibleComponentState } from '@/object-record/record-table/states/tableLastRowVisibleComponentState'; -import { tableSortsComponentState } from '@/object-record/record-table/states/tableSortsComponentState'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; @@ -72,16 +70,6 @@ export const useRecordTable = (props?: useRecordTableProps) => { recordTableId, ); - const setTableFilters = useSetRecoilComponentStateV2( - tableFiltersComponentState, - recordTableId, - ); - - const setTableSorts = useSetRecoilComponentStateV2( - tableSortsComponentState, - recordTableId, - ); - const setOnColumnsChange = useSetRecoilComponentStateV2( onColumnsChangeComponentState, recordTableId, @@ -230,8 +218,6 @@ export const useRecordTable = (props?: useRecordTableProps) => { return { onColumnsChange, setAvailableTableColumns, - setTableFilters, - setTableSorts, setOnEntityCountChange, setRecordTableData, leaveTableFocus, diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyRecordGroupDragDropContextProvider.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyRecordGroupDragDropContextProvider.tsx index a5024e329..4552a2aca 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyRecordGroupDragDropContextProvider.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyRecordGroupDragDropContextProvider.tsx @@ -6,7 +6,7 @@ import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { getDraggedRecordPosition } from '@/object-record/record-board/utils/getDraggedRecordPosition'; import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState'; import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState'; -import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState'; +import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState'; @@ -34,6 +34,10 @@ export const RecordTableBodyRecordGroupDragDropContextProvider = ({ recordIndexRecordIdsByGroupComponentFamilyState, ); + const currentRecordSortsCallbackState = useRecoilComponentCallbackStateV2( + currentRecordSortsComponentState, + ); + const handleDragEnd = useRecoilCallback( ({ snapshot }) => (result: DropResult) => { @@ -52,8 +56,8 @@ export const RecordTableBodyRecordGroupDragDropContextProvider = ({ recordGroupDefinitionFamilyState(destinationRecordGroupId), ); - const indexSorts = snapshot - .getLoadable(recordIndexSortsState) + const currentRecordSorts = snapshot + .getLoadable(currentRecordSortsCallbackState) .getValue(); if (!isDefined(destinationRecordGroup)) { @@ -68,7 +72,7 @@ export const RecordTableBodyRecordGroupDragDropContextProvider = ({ throw new Error('Field metadata is not defined'); } - if (indexSorts.length > 0) { + if (currentRecordSorts.length > 0) { setIsRemoveSortingModalOpen(true); return; } @@ -130,6 +134,7 @@ export const RecordTableBodyRecordGroupDragDropContextProvider = ({ recordIdsByGroupFamilyState, updateOneRow, setIsRemoveSortingModalOpen, + currentRecordSortsCallbackState, ], ); diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/hooks/useAggregateRecordsForRecordTableColumnFooter.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/hooks/useAggregateRecordsForRecordTableColumnFooter.tsx index 1c481becc..81baac725 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/hooks/useAggregateRecordsForRecordTableColumnFooter.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-footer/hooks/useAggregateRecordsForRecordTableColumnFooter.tsx @@ -1,10 +1,10 @@ import { useAggregateRecords } from '@/object-record/hooks/useAggregateRecords'; import { computeAggregateValueAndLabel } from '@/object-record/record-board/record-board-column/utils/computeAggregateValueAndLabel'; +import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState'; import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter'; import { useRecordGroupFilter } from '@/object-record/record-group/hooks/useRecordGroupFilter'; -import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState'; import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { RecordTableColumnAggregateFooterCellContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterCellContext'; @@ -13,7 +13,6 @@ import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { UserContext } from '@/users/contexts/UserContext'; -import { mapViewFilterGroupsToRecordFilterGroups } from '@/views/utils/mapViewFilterGroupsToRecordFilterGroups'; import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; import { isDefined, isFieldMetadataDateKind } from 'twenty-shared'; @@ -24,8 +23,8 @@ export const useAggregateRecordsForRecordTableColumnFooter = ( const { objectMetadataItem } = useRecordTableContextOrThrow(); const { recordGroupFilter } = useRecordGroupFilter(objectMetadataItem.fields); - const recordIndexViewFilterGroups = useRecoilValue( - recordIndexViewFilterGroupsState, + const currentRecordFilterGroups = useRecoilComponentValueV2( + currentRecordFilterGroupsComponentState, ); const currentRecordFilters = useRecoilComponentValueV2( @@ -34,14 +33,10 @@ export const useAggregateRecordsForRecordTableColumnFooter = ( const { filterValueDependencies } = useFilterValueDependencies(); - const recordFilterGroups = mapViewFilterGroupsToRecordFilterGroups( - recordIndexViewFilterGroups, - ); - const requestFilters = computeRecordGqlOperationFilter({ fields: objectMetadataItem.fields, filterValueDependencies, - recordFilterGroups, + recordFilterGroups: currentRecordFilterGroups, recordFilters: currentRecordFilters, }); diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/tableFiltersComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/tableFiltersComponentState.ts deleted file mode 100644 index 2f9a557bd..000000000 --- a/packages/twenty-front/src/modules/object-record/record-table/states/tableFiltersComponentState.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; -import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext'; -import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; - -export const tableFiltersComponentState = createComponentStateV2< - RecordFilter[] ->({ - key: 'tableFiltersComponentState', - defaultValue: [], - componentInstanceContext: RecordTableComponentInstanceContext, -}); diff --git a/packages/twenty-front/src/modules/object-record/record-table/states/tableSortsComponentState.ts b/packages/twenty-front/src/modules/object-record/record-table/states/tableSortsComponentState.ts deleted file mode 100644 index ff280e8fe..000000000 --- a/packages/twenty-front/src/modules/object-record/record-table/states/tableSortsComponentState.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { RecordSort } from '@/object-record/record-sort/types/RecordSort'; -import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext'; -import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; - -export const tableSortsComponentState = createComponentStateV2({ - key: 'tableSortsComponentState', - defaultValue: [], - componentInstanceContext: RecordTableComponentInstanceContext, -}); diff --git a/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFilterRecords.ts b/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFilterRecords.ts index 38cda8932..0d8b08c61 100644 --- a/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFilterRecords.ts +++ b/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewFilterRecords.ts @@ -57,7 +57,8 @@ export const usePersistViewFilterRecords = () => { displayValue: viewFilter.displayValue, operand: viewFilter.operand, viewFilterGroupId: viewFilter.viewFilterGroupId, - }, + positionInViewFilterGroup: viewFilter.positionInViewFilterGroup, + } satisfies Partial, }, update: (cache, { data }) => { const record = data?.['createViewFilter']; @@ -95,7 +96,9 @@ export const usePersistViewFilterRecords = () => { value: viewFilter.value, displayValue: viewFilter.displayValue, operand: viewFilter.operand, - }, + positionInViewFilterGroup: viewFilter.positionInViewFilterGroup, + viewFilterGroupId: viewFilter.viewFilterGroupId, + } satisfies Partial, }, update: (cache, { data }) => { const record = data?.['updateViewFilter']; diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerOptionDropdown.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerOptionDropdown.tsx index d6616b8c5..af97a85e4 100644 --- a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerOptionDropdown.tsx +++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerOptionDropdown.tsx @@ -77,7 +77,6 @@ export const ViewPickerOptionDropdown = ({ onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => { setIsHovered(false); - closeDropdown(); }} dropdownPlacement="bottom-start" dropdownId={`view-picker-options-${view.id}`} diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-filter-group.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view-filter-group.workspace-entity.ts index f807eca53..c844a6f17 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-filter-group.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-filter-group.workspace-entity.ts @@ -90,7 +90,6 @@ export class ViewFilterGroupWorkspaceEntity extends BaseWorkspaceEntity { description: msg`Position in the parent view filter group`, icon: 'IconHierarchy2', }) - @WorkspaceIsSystem() @WorkspaceIsNullable() positionInViewFilterGroup: number | null; } diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts index 88387de62..9543b41d4 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts @@ -92,7 +92,6 @@ export class ViewFilterWorkspaceEntity extends BaseWorkspaceEntity { description: msg`Position in the view filter group`, icon: 'IconHierarchy2', }) - @WorkspaceIsSystem() @WorkspaceIsNullable() positionInViewFilterGroup: number | null; }