Clean record filter and record sort (#10466)

This PR removes what's left from record filter and record sort previous
logic to handle CRUD and state management with view.

So everything that is named combinedFilter and combinedSort is removed
here.

We implement currentRecordFilters and currentRecordSorts everywhere.

We also remove the event in a state onSortSelectComponentState. (a
pattern we want to avoid)
This commit is contained in:
Lucas Bordeau
2025-02-25 15:03:30 +01:00
committed by GitHub
parent 61904050ac
commit 2247d3fa91
53 changed files with 236 additions and 1233 deletions

View File

@ -2,13 +2,13 @@ import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMeta
import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector'; import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector';
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { useUpsertCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useUpsertCombinedViewFilterGroup'; import { useUpsertCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useUpsertCombinedViewFilterGroup';
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands'; import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId'; import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
import { ViewFilterGroup } from '@/views/types/ViewFilterGroup'; import { ViewFilterGroup } from '@/views/types/ViewFilterGroup';
import { ViewFilterGroupLogicalOperator } from '@/views/types/ViewFilterGroupLogicalOperator'; import { ViewFilterGroupLogicalOperator } from '@/views/types/ViewFilterGroupLogicalOperator';
import { useCallback } from 'react'; import { useCallback } from 'react';
@ -31,7 +31,7 @@ export const AdvancedFilterAddFilterRuleSelect = ({
const { currentViewId } = useGetCurrentView(); const { currentViewId } = useGetCurrentView();
const { upsertCombinedViewFilterGroup } = useUpsertCombinedViewFilterGroup(); const { upsertCombinedViewFilterGroup } = useUpsertCombinedViewFilterGroup();
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(); const { upsertRecordFilter } = useUpsertRecordFilter();
const newPositionInViewFilterGroup = lastChildPosition + 1; const newPositionInViewFilterGroup = lastChildPosition + 1;
@ -86,7 +86,7 @@ export const AdvancedFilterAddFilterRuleSelect = ({
defaultFieldMetadataItem.type, defaultFieldMetadataItem.type,
); );
upsertCombinedViewFilter({ upsertRecordFilter({
id: v4(), id: v4(),
fieldMetadataId: defaultFieldMetadataItem.id, fieldMetadataId: defaultFieldMetadataItem.id,
type: filterType, type: filterType,
@ -124,7 +124,7 @@ export const AdvancedFilterAddFilterRuleSelect = ({
defaultFieldMetadataItem.type, defaultFieldMetadataItem.type,
); );
upsertCombinedViewFilter({ upsertRecordFilter({
id: v4(), id: v4(),
fieldMetadataId: defaultFieldMetadataItem.id, fieldMetadataId: defaultFieldMetadataItem.id,
type: filterType, type: filterType,

View File

@ -49,7 +49,7 @@ export const AdvancedFilterRootLevelViewFilterGroup = ({
return ( return (
<StyledContainer> <StyledContainer>
{childViewFiltersAndViewFilterGroups.map((child, i) => {childViewFiltersAndViewFilterGroups.map((child, i) =>
child.__typename === 'ViewFilterGroup' ? ( (child as any).__typename === 'ViewFilterGroup' ? (
<StyledRow key={child.id}> <StyledRow key={child.id}>
<AdvancedFilterLogicalOperatorCell <AdvancedFilterLogicalOperatorCell
index={i} index={i}

View File

@ -1,11 +1,14 @@
import { AdvancedFilterRuleOptionsDropdownButton } from '@/object-record/advanced-filter/components/AdvancedFilterRuleOptionsDropdownButton'; import { AdvancedFilterRuleOptionsDropdownButton } from '@/object-record/advanced-filter/components/AdvancedFilterRuleOptionsDropdownButton';
import { useCurrentViewFilter } from '@/object-record/advanced-filter/hooks/useCurrentViewFilter';
import { useCurrentViewViewFilterGroup } from '@/object-record/advanced-filter/hooks/useCurrentViewViewFilterGroup'; import { useCurrentViewViewFilterGroup } from '@/object-record/advanced-filter/hooks/useCurrentViewViewFilterGroup';
import { useDeleteCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup'; import { useDeleteCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup';
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId'; import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
import { MenuItem } from 'twenty-ui'; import { MenuItem } from 'twenty-ui';
@ -25,7 +28,7 @@ export const AdvancedFilterRuleOptionsDropdown = ({
}: AdvancedFilterRuleOptionsDropdownProps) => { }: AdvancedFilterRuleOptionsDropdownProps) => {
const dropdownId = `advanced-filter-rule-options-${viewFilterId ?? viewFilterGroupId}`; const dropdownId = `advanced-filter-rule-options-${viewFilterId ?? viewFilterGroupId}`;
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters(); const { removeRecordFilter } = useRemoveRecordFilter();
const { deleteCombinedViewFilterGroup } = useDeleteCombinedViewFilterGroup(); const { deleteCombinedViewFilterGroup } = useDeleteCombinedViewFilterGroup();
const { currentViewFilterGroup, childViewFiltersAndViewFilterGroups } = const { currentViewFilterGroup, childViewFiltersAndViewFilterGroups } =
@ -33,32 +36,37 @@ export const AdvancedFilterRuleOptionsDropdown = ({
viewFilterGroupId, viewFilterGroupId,
}); });
const currentViewFilter = useCurrentViewFilter({ const currentRecordFilters = useRecoilComponentValueV2(
viewFilterId, currentRecordFiltersComponentState,
}); );
const currentRecordFilter = currentRecordFilters.find(
(recordFilter) => recordFilter.id === viewFilterId,
);
const handleRemove = async () => { const handleRemove = async () => {
if (isDefined(viewFilterId)) { if (isDefined(viewFilterId)) {
deleteCombinedViewFilter(viewFilterId); removeRecordFilter(viewFilterId);
const isOnlyViewFilterInGroup = const isOnlyViewFilterInGroup =
childViewFiltersAndViewFilterGroups.length === 1; childViewFiltersAndViewFilterGroups.length === 1;
if ( if (
isOnlyViewFilterInGroup && isOnlyViewFilterInGroup &&
isDefined(currentViewFilter?.viewFilterGroupId) isDefined(currentRecordFilter?.viewFilterGroupId)
) { ) {
deleteCombinedViewFilterGroup(currentViewFilter.viewFilterGroupId); deleteCombinedViewFilterGroup(currentRecordFilter.viewFilterGroupId);
} }
} else if (isDefined(currentViewFilterGroup)) { } else if (isDefined(currentViewFilterGroup)) {
deleteCombinedViewFilterGroup(currentViewFilterGroup.id); deleteCombinedViewFilterGroup(currentViewFilterGroup.id);
// TODO: This is a temporary fix view filter group will be removed soon.
const childViewFilters = childViewFiltersAndViewFilterGroups.filter( const childViewFilters = childViewFiltersAndViewFilterGroups.filter(
(child) => child.__typename === 'ViewFilter', (child) => (child as any).__typename === 'ViewFilter',
); );
for (const childViewFilter of childViewFilters) { for (const childViewFilter of childViewFilters) {
await deleteCombinedViewFilter(childViewFilter.id); removeRecordFilter(childViewFilter.id);
} }
} else { } else {
throw new Error('No view filter or view filter group to remove'); throw new Error('No view filter or view filter group to remove');

View File

@ -1,10 +1,13 @@
import { AdvancedFilterViewFilterFieldSelect } from '@/object-record/advanced-filter/components/AdvancedFilterViewFilterFieldSelect'; import { AdvancedFilterViewFilterFieldSelect } from '@/object-record/advanced-filter/components/AdvancedFilterViewFilterFieldSelect';
import { AdvancedFilterViewFilterOperandSelect } from '@/object-record/advanced-filter/components/AdvancedFilterViewFilterOperandSelect'; import { AdvancedFilterViewFilterOperandSelect } from '@/object-record/advanced-filter/components/AdvancedFilterViewFilterOperandSelect';
import { AdvancedFilterViewFilterValueInput } from '@/object-record/advanced-filter/components/AdvancedFilterViewFilterValueInput'; import { AdvancedFilterViewFilterValueInput } from '@/object-record/advanced-filter/components/AdvancedFilterViewFilterValueInput';
import { useCurrentViewFilter } from '@/object-record/advanced-filter/hooks/useCurrentViewFilter';
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext'; import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { configurableViewFilterOperands } from '@/object-record/object-filter-dropdown/utils/configurableViewFilterOperands'; import { configurableViewFilterOperands } from '@/object-record/object-filter-dropdown/utils/configurableViewFilterOperands';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared';
const StyledValueDropdownContainer = styled.div` const StyledValueDropdownContainer = styled.div`
flex: 3; flex: 3;
@ -25,22 +28,30 @@ type AdvancedFilterViewFilterProps = {
export const AdvancedFilterViewFilter = ({ export const AdvancedFilterViewFilter = ({
viewFilterId, viewFilterId,
}: AdvancedFilterViewFilterProps) => { }: AdvancedFilterViewFilterProps) => {
const filter = useCurrentViewFilter({ viewFilterId }); const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
if (!filter) { const recordFilter = currentRecordFilters.find(
(recordFilter) => recordFilter.id === viewFilterId,
);
if (!isDefined(recordFilter)) {
return null; return null;
} }
return ( return (
<ObjectFilterDropdownComponentInstanceContext.Provider <ObjectFilterDropdownComponentInstanceContext.Provider
value={{ instanceId: filter.id }} value={{ instanceId: recordFilter.id }}
> >
<StyledRow> <StyledRow>
<AdvancedFilterViewFilterFieldSelect viewFilterId={filter.id} /> <AdvancedFilterViewFilterFieldSelect viewFilterId={recordFilter.id} />
<AdvancedFilterViewFilterOperandSelect viewFilterId={filter.id} /> <AdvancedFilterViewFilterOperandSelect viewFilterId={recordFilter.id} />
<StyledValueDropdownContainer> <StyledValueDropdownContainer>
{configurableViewFilterOperands.has(filter.operand) && ( {configurableViewFilterOperands.has(recordFilter.operand) && (
<AdvancedFilterViewFilterValueInput viewFilterId={filter.id} /> <AdvancedFilterViewFilterValueInput
viewFilterId={recordFilter.id}
/>
)} )}
</StyledValueDropdownContainer> </StyledValueDropdownContainer>
</StyledRow> </StyledRow>

View File

@ -1,13 +1,15 @@
import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown'; import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown';
import { useCurrentViewFilter } from '@/object-record/advanced-filter/hooks/useCurrentViewFilter';
import { ObjectFilterDropdownFilterSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect'; import { ObjectFilterDropdownFilterSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect';
import { ObjectFilterDropdownFilterSelectCompositeFieldSubMenu } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectCompositeFieldSubMenu'; import { ObjectFilterDropdownFilterSelectCompositeFieldSubMenu } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectCompositeFieldSubMenu';
import { advancedFilterViewFilterGroupIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterGroupIdComponentState'; import { advancedFilterViewFilterGroupIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterGroupIdComponentState';
import { advancedFilterViewFilterIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterIdComponentState'; import { advancedFilterViewFilterIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterIdComponentState';
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState'; import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { SelectControl } from '@/ui/input/components/SelectControl'; import { SelectControl } from '@/ui/input/components/SelectControl';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId'; import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
@ -25,7 +27,13 @@ export const AdvancedFilterViewFilterFieldSelect = ({
}: AdvancedFilterViewFilterFieldSelectProps) => { }: AdvancedFilterViewFilterFieldSelectProps) => {
const { advancedFilterDropdownId } = useAdvancedFilterDropdown(viewFilterId); const { advancedFilterDropdownId } = useAdvancedFilterDropdown(viewFilterId);
const recordFilter = useCurrentViewFilter({ viewFilterId }); const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const recordFilter = currentRecordFilters.find(
(recordFilter) => recordFilter.id === viewFilterId,
);
const selectedFieldLabel = recordFilter?.label ?? ''; const selectedFieldLabel = recordFilter?.label ?? '';

View File

@ -1,15 +1,17 @@
import { useGetFieldMetadataItemById } from '@/object-metadata/hooks/useGetFieldMetadataItemById'; import { useGetFieldMetadataItemById } from '@/object-metadata/hooks/useGetFieldMetadataItemById';
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { useCurrentViewFilter } from '@/object-record/advanced-filter/hooks/useCurrentViewFilter';
import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue'; import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue';
import { getOperandLabel } from '@/object-record/object-filter-dropdown/utils/getOperandLabel'; import { getOperandLabel } from '@/object-record/object-filter-dropdown/utils/getOperandLabel';
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands'; import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { SelectControl } from '@/ui/input/components/SelectControl'; import { SelectControl } from '@/ui/input/components/SelectControl';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId'; import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
@ -28,7 +30,13 @@ export const AdvancedFilterViewFilterOperandSelect = ({
}: AdvancedFilterViewFilterOperandSelectProps) => { }: AdvancedFilterViewFilterOperandSelectProps) => {
const dropdownId = `advanced-filter-view-filter-operand-${viewFilterId}`; const dropdownId = `advanced-filter-view-filter-operand-${viewFilterId}`;
const filter = useCurrentViewFilter({ viewFilterId }); const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const filter = currentRecordFilters.find(
(recordFilter) => recordFilter.id === viewFilterId,
);
const { getFieldMetadataItemById } = useGetFieldMetadataItemById(); const { getFieldMetadataItemById } = useGetFieldMetadataItemById();
@ -36,7 +44,7 @@ export const AdvancedFilterViewFilterOperandSelect = ({
const { closeDropdown } = useDropdown(dropdownId); const { closeDropdown } = useDropdown(dropdownId);
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(); const { upsertRecordFilter } = useUpsertRecordFilter();
const handleOperandChange = (operand: ViewFilterOperand) => { const handleOperandChange = (operand: ViewFilterOperand) => {
closeDropdown(); closeDropdown();
@ -60,7 +68,7 @@ export const AdvancedFilterViewFilterOperandSelect = ({
filter.displayValue, filter.displayValue,
); );
upsertCombinedViewFilter({ upsertRecordFilter({
...filter, ...filter,
operand, operand,
value, value,

View File

@ -1,11 +1,12 @@
import { useCurrentViewFilter } from '@/object-record/advanced-filter/hooks/useCurrentViewFilter';
import { ObjectFilterDropdownFilterInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput'; import { ObjectFilterDropdownFilterInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput';
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState'; import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { SelectControl } from '@/ui/input/components/SelectControl'; import { SelectControl } from '@/ui/input/components/SelectControl';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId'; import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
@ -18,7 +19,13 @@ export const AdvancedFilterViewFilterValueInput = ({
}: AdvancedFilterViewFilterValueInputProps) => { }: AdvancedFilterViewFilterValueInputProps) => {
const dropdownId = `advanced-filter-view-filter-value-input-${viewFilterId}`; const dropdownId = `advanced-filter-view-filter-value-input-${viewFilterId}`;
const filter = useCurrentViewFilter({ viewFilterId }); const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const filter = currentRecordFilters.find(
(recordFilter) => recordFilter.id === viewFilterId,
);
const isDisabled = !filter?.fieldMetadataId || !filter.operand; const isDisabled = !filter?.fieldMetadataId || !filter.operand;

View File

@ -1,29 +0,0 @@
import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
export const useCurrentViewFilter = ({
viewFilterId,
}: {
viewFilterId?: string;
}) => {
const { filterableFieldMetadataItems } =
useFilterableFieldMetadataItemsInRecordIndexContext();
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
const viewFilter = currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
(viewFilter) => viewFilter.id === viewFilterId,
);
if (!viewFilter) {
return undefined;
}
const [filter] = mapViewFiltersToFilters(
[viewFilter],
filterableFieldMetadataItems,
);
return filter;
};

View File

@ -1,3 +1,5 @@
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { ViewFilter } from '@/views/types/ViewFilter'; import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewFilterGroup } from '@/views/types/ViewFilterGroup'; import { ViewFilterGroup } from '@/views/types/ViewFilterGroup';
@ -10,6 +12,10 @@ export const useCurrentViewViewFilterGroup = ({
}) => { }) => {
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(); const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const viewFilterGroup = const viewFilterGroup =
currentViewWithCombinedFiltersAndSorts?.viewFilterGroups.find( currentViewWithCombinedFiltersAndSorts?.viewFilterGroups.find(
(viewFilterGroup) => viewFilterGroup.id === viewFilterGroupId, (viewFilterGroup) => viewFilterGroup.id === viewFilterGroupId,
@ -25,11 +31,10 @@ export const useCurrentViewViewFilterGroup = ({
}; };
} }
const childViewFilters = const childRecordFilters = currentRecordFilters.filter(
currentViewWithCombinedFiltersAndSorts?.viewFilters.filter( (recordFilterToFilter) =>
(viewFilterToFilter) => recordFilterToFilter.viewFilterGroupId === viewFilterGroup.id,
viewFilterToFilter.viewFilterGroupId === viewFilterGroup.id, );
);
const childViewFilterGroups = const childViewFilterGroups =
currentViewWithCombinedFiltersAndSorts?.viewFilterGroups.filter( currentViewWithCombinedFiltersAndSorts?.viewFilterGroups.filter(
@ -39,7 +44,7 @@ export const useCurrentViewViewFilterGroup = ({
const childViewFiltersAndViewFilterGroups = [ const childViewFiltersAndViewFilterGroups = [
...(childViewFilterGroups ?? []), ...(childViewFilterGroups ?? []),
...(childViewFilters ?? []), ...(childRecordFilters ?? []),
].sort((a, b) => { ].sort((a, b) => {
const positionA = a.positionInViewFilterGroup ?? 0; const positionA = a.positionInViewFilterGroup ?? 0;
const positionB = b.positionInViewFilterGroup ?? 0; const positionB = b.positionInViewFilterGroup ?? 0;

View File

@ -3,12 +3,12 @@ import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-met
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { useUpsertCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useUpsertCombinedViewFilterGroup'; import { useUpsertCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useUpsertCombinedViewFilterGroup';
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId'; import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands'; import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId'; import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
import { ViewFilterGroupLogicalOperator } from '@/views/types/ViewFilterGroupLogicalOperator'; import { ViewFilterGroupLogicalOperator } from '@/views/types/ViewFilterGroupLogicalOperator';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro'; import { useLingui } from '@lingui/react/macro';
@ -59,7 +59,7 @@ export const AdvancedFilterButton = () => {
const { upsertCombinedViewFilterGroup } = useUpsertCombinedViewFilterGroup(); const { upsertCombinedViewFilterGroup } = useUpsertCombinedViewFilterGroup();
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(); const { upsertRecordFilter } = useUpsertRecordFilter();
const objectMetadataId = const objectMetadataId =
currentViewWithCombinedFiltersAndSorts?.objectMetadataId; currentViewWithCombinedFiltersAndSorts?.objectMetadataId;
@ -115,7 +115,7 @@ export const AdvancedFilterButton = () => {
filterType, filterType,
})[0]; })[0];
upsertCombinedViewFilter({ upsertRecordFilter({
id: v4(), id: v4(),
fieldMetadataId: defaultFieldMetadataItem.id, fieldMetadataId: defaultFieldMetadataItem.id,
operand: firstOperand, operand: firstOperand,

View File

@ -11,13 +11,14 @@ import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-re
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown'; import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown';
import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect'; import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect';
import { SelectableItem } from '@/object-record/select/types/SelectableItem'; import { SelectableItem } from '@/object-record/select/types/SelectableItem';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { RelationFilterValue } from '@/views/view-filter-value/types/RelationFilterValue'; import { RelationFilterValue } from '@/views/view-filter-value/types/RelationFilterValue';
import { jsonRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/jsonRelationFilterValueSchema'; import { jsonRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/jsonRelationFilterValueSchema';
import { simpleRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/simpleRelationFilterValueSchema'; import { simpleRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/simpleRelationFilterValueSchema';
@ -59,10 +60,11 @@ export const ObjectFilterDropdownRecordSelect = ({
objectFilterDropdownSelectedRecordIdsComponentState, objectFilterDropdownSelectedRecordIdsComponentState,
); );
const { applyRecordFilter } = useApplyRecordFilter(viewComponentId); const setObjectFilterDropdownSelectedRecordIds = useSetRecoilComponentStateV2(
objectFilterDropdownSelectedRecordIdsComponentState,
);
const { currentViewWithCombinedFiltersAndSorts } = const { applyRecordFilter } = useApplyRecordFilter(viewComponentId);
useGetCurrentView(viewComponentId);
const { isCurrentWorkspaceMemberSelected } = jsonRelationFilterValueSchema const { isCurrentWorkspaceMemberSelected } = jsonRelationFilterValueSchema
.catch({ .catch({
@ -121,6 +123,10 @@ export const ObjectFilterDropdownRecordSelect = ({
.includes(objectFilterDropdownSearchInput.toLowerCase()), .includes(objectFilterDropdownSearchInput.toLowerCase()),
); );
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const handleMultipleRecordSelectChange = ( const handleMultipleRecordSelectChange = (
itemToSelect: SelectableItem, itemToSelect: SelectableItem,
isNewSelectedValue: boolean, isNewSelectedValue: boolean,
@ -136,6 +142,7 @@ export const ObjectFilterDropdownRecordSelect = ({
...objectFilterDropdownSelectedRecordIds, ...objectFilterDropdownSelectedRecordIds,
itemToSelect.id, itemToSelect.id,
]; ];
const selectedRecordIdsWithRemovedRecord = const selectedRecordIdsWithRemovedRecord =
objectFilterDropdownSelectedRecordIds.filter( objectFilterDropdownSelectedRecordIds.filter(
(id) => id !== itemToSelect.id, (id) => id !== itemToSelect.id,
@ -187,14 +194,15 @@ export const ObjectFilterDropdownRecordSelect = ({
} satisfies RelationFilterValue) } satisfies RelationFilterValue)
: ''; : '';
const viewFilter = const recordFilterInDropdown = currentRecordFilters.find(
currentViewWithCombinedFiltersAndSorts?.viewFilters.find( (recordFilter) =>
(viewFilter) => recordFilter.fieldMetadataId ===
viewFilter.fieldMetadataId === fieldMetadataItemUsedInFilterDropdown.id,
fieldMetadataItemUsedInFilterDropdown.id, );
);
const filterId = viewFilter?.id ?? v4(); setObjectFilterDropdownSelectedRecordIds(newSelectedRecordIds);
const filterId = recordFilterInDropdown?.id ?? v4();
applyRecordFilter({ applyRecordFilter({
id: selectedFilter?.id ? selectedFilter.id : filterId, id: selectedFilter?.id ? selectedFilter.id : filterId,

View File

@ -11,13 +11,12 @@ import { selectedOperandInDropdownComponentState } from '@/object-record/object-
import { getActorSourceMultiSelectOptions } from '@/object-record/object-filter-dropdown/utils/getActorSourceMultiSelectOptions'; import { getActorSourceMultiSelectOptions } from '@/object-record/object-filter-dropdown/utils/getActorSourceMultiSelectOptions';
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter'; import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown'; import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown';
import { SelectableItem } from '@/object-record/select/types/SelectableItem'; import { SelectableItem } from '@/object-record/select/types/SelectableItem';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
@ -57,12 +56,6 @@ export const ObjectFilterDropdownSourceSelect = ({
const { applyRecordFilter } = useApplyRecordFilter(viewComponentId); const { applyRecordFilter } = useApplyRecordFilter(viewComponentId);
const { deleteCombinedViewFilter } =
useDeleteCombinedViewFilters(viewComponentId);
const { currentViewWithCombinedFiltersAndSorts } =
useGetCurrentView(viewComponentId);
// TODO: this should be removed as it is not consistent across re-renders // TODO: this should be removed as it is not consistent across re-renders
const [fieldId] = useState(v4()); const [fieldId] = useState(v4());
@ -78,6 +71,10 @@ export const ObjectFilterDropdownSourceSelect = ({
const { removeRecordFilter } = useRemoveRecordFilter(); const { removeRecordFilter } = useRemoveRecordFilter();
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const handleMultipleItemSelectChange = ( const handleMultipleItemSelectChange = (
itemToSelect: SelectableItem, itemToSelect: SelectableItem,
newSelectedValue: boolean, newSelectedValue: boolean,
@ -97,7 +94,7 @@ export const ObjectFilterDropdownSourceSelect = ({
if (newSelectedItemIds.length === 0) { if (newSelectedItemIds.length === 0) {
emptyRecordFilter(); emptyRecordFilter();
removeRecordFilter(fieldMetadataItemUsedInFilterDropdown.id); removeRecordFilter(fieldMetadataItemUsedInFilterDropdown.id);
deleteCombinedViewFilter(fieldId);
return; return;
} }
@ -121,14 +118,13 @@ export const ObjectFilterDropdownSourceSelect = ({
? JSON.stringify(newSelectedItemIds) ? JSON.stringify(newSelectedItemIds)
: EMPTY_FILTER_VALUE; : EMPTY_FILTER_VALUE;
const viewFilter = const recordFilter = currentRecordFilters.find(
currentViewWithCombinedFiltersAndSorts?.viewFilters.find( (recordFilter) =>
(viewFilter) => recordFilter.fieldMetadataId ===
viewFilter.fieldMetadataId === fieldMetadataItemUsedInFilterDropdown.id,
fieldMetadataItemUsedInFilterDropdown.id, );
);
const filterId = viewFilter?.id ?? fieldId; const filterId = recordFilter?.id ?? fieldId;
applyRecordFilter({ applyRecordFilter({
id: selectedFilter?.id ? selectedFilter.id : filterId, id: selectedFilter?.id ? selectedFilter.id : filterId,

View File

@ -10,9 +10,9 @@ import { useResetSortDropdown } from '@/object-record/object-sort-dropdown/hooks
import { useToggleSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useToggleSortDropdown'; import { useToggleSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useToggleSortDropdown';
import { isRecordSortDirectionDropdownMenuUnfoldedComponentState } from '@/object-record/object-sort-dropdown/states/isRecordSortDirectionDropdownMenuUnfoldedComponentState'; import { isRecordSortDirectionDropdownMenuUnfoldedComponentState } from '@/object-record/object-sort-dropdown/states/isRecordSortDirectionDropdownMenuUnfoldedComponentState';
import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState'; import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState';
import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState';
import { selectedRecordSortDirectionComponentState } from '@/object-record/object-sort-dropdown/states/selectedRecordSortDirectionComponentState'; import { selectedRecordSortDirectionComponentState } from '@/object-record/object-sort-dropdown/states/selectedRecordSortDirectionComponentState';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { useUpsertRecordSort } from '@/object-record/record-sort/hooks/useUpsertRecordSort';
import { import {
RECORD_SORT_DIRECTIONS, RECORD_SORT_DIRECTIONS,
RecordSortDirection, RecordSortDirection,
@ -159,12 +159,12 @@ export const ObjectSortDropdownButton = ({
const { closeSortDropdown } = useCloseSortDropdown(); const { closeSortDropdown } = useCloseSortDropdown();
const onSortSelect = useRecoilComponentValueV2(onSortSelectComponentState); const { upsertRecordSort } = useUpsertRecordSort();
const handleAddSort = (fieldMetadataItem: FieldMetadataItem) => { const handleAddSort = (fieldMetadataItem: FieldMetadataItem) => {
setObjectSortDropdownSearchInput(''); setObjectSortDropdownSearchInput('');
closeSortDropdown(); closeSortDropdown();
onSortSelect?.({ upsertRecordSort({
id: v4(), id: v4(),
fieldMetadataId: fieldMetadataItem.id, fieldMetadataId: fieldMetadataItem.id,
direction: selectedRecordSortDirection, direction: selectedRecordSortDirection,

View File

@ -1,9 +0,0 @@
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
export const isRecordSortSelectedComponentState =
createComponentStateV2<boolean>({
key: 'isRecordSortSelectedComponentState',
defaultValue: false,
componentInstanceContext: ObjectSortDropdownComponentInstanceContext,
});

View File

@ -1,11 +0,0 @@
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
import { RecordSort } from '@/object-record/record-sort/types/RecordSort';
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
export const onSortSelectComponentState = createComponentStateV2<
((sort: RecordSort) => void) | undefined
>({
key: 'onSortSelectComponentState',
defaultValue: undefined,
componentInstanceContext: ObjectSortDropdownComponentInstanceContext,
});

View File

@ -2,12 +2,11 @@ import { selectedFilterComponentState } from '@/object-record/object-filter-drop
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter'; import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
export const useApplyRecordFilter = (componentInstanceId?: string) => { export const useApplyRecordFilter = (componentInstanceId?: string) => {
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters();
const selectedFilterCallbackState = useRecoilComponentCallbackStateV2( const selectedFilterCallbackState = useRecoilComponentCallbackStateV2(
selectedFilterComponentState, selectedFilterComponentState,
componentInstanceId, componentInstanceId,
@ -21,11 +20,10 @@ export const useApplyRecordFilter = (componentInstanceId?: string) => {
set(selectedFilterCallbackState, filter); set(selectedFilterCallbackState, filter);
if (isDefined(filter)) { if (isDefined(filter)) {
upsertCombinedViewFilter(filter);
upsertRecordFilter(filter); upsertRecordFilter(filter);
} }
}, },
[selectedFilterCallbackState, upsertCombinedViewFilter, upsertRecordFilter], [selectedFilterCallbackState, upsertRecordFilter],
); );
return { return {

View File

@ -51,7 +51,7 @@ export const RecordIndexBoardContainer = ({
}} }}
> >
<RecordBoard /> <RecordBoard />
<RecordIndexRemoveSortingModal recordIndexId={recordBoardId} /> <RecordIndexRemoveSortingModal />
</RecordBoardContext.Provider> </RecordBoardContext.Provider>
); );
}; };

View File

@ -1,33 +1,26 @@
import { useRecoilState } from 'recoil'; import { useRecoilState } from 'recoil';
import { useRemoveRecordSort } from '@/object-record/record-sort/hooks/useRemoveRecordSort'; import { useRemoveRecordSort } from '@/object-record/record-sort/hooks/useRemoveRecordSort';
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState'; import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useDeleteCombinedViewSorts } from '@/views/hooks/useDeleteCombinedViewSorts'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
export const RecordIndexRemoveSortingModal = ({ export const RecordIndexRemoveSortingModal = () => {
recordIndexId, const currentRecordSorts = useRecoilComponentValueV2(
}: { currentRecordSortsComponentState,
recordIndexId: string; );
}) => {
const { currentViewWithCombinedFiltersAndSorts } =
useGetCurrentView(recordIndexId);
const viewSorts = currentViewWithCombinedFiltersAndSorts?.viewSorts || []; const fieldMetadataIds = currentRecordSorts.map(
const fieldMetadataIds = viewSorts.map(
(viewSort) => viewSort.fieldMetadataId, (viewSort) => viewSort.fieldMetadataId,
); );
const [isRemoveSortingModalOpen, setIsRemoveSortingModalOpen] = const [isRemoveSortingModalOpen, setIsRemoveSortingModalOpen] =
useRecoilState(isRemoveSortingModalOpenState); useRecoilState(isRemoveSortingModalOpenState);
const { deleteCombinedViewSort } = useDeleteCombinedViewSorts(recordIndexId);
const { removeRecordSort } = useRemoveRecordSort(); const { removeRecordSort } = useRemoveRecordSort();
const handleRemoveClick = () => { const handleRemoveClick = () => {
fieldMetadataIds.forEach((id) => { fieldMetadataIds.forEach((id) => {
deleteCombinedViewSort(id);
removeRecordSort(id); removeRecordSort(id);
}); });
}; };

View File

@ -34,7 +34,7 @@ export const RecordIndexTableContainer = ({
viewBarId={viewBarId} viewBarId={viewBarId}
updateRecordMutation={updateEntity} updateRecordMutation={updateEntity}
/> />
<RecordIndexRemoveSortingModal recordIndexId={recordTableId} /> <RecordIndexRemoveSortingModal />
</> </>
); );
}; };

View File

@ -9,7 +9,7 @@ import { useSetRecordIndexEntityCount } from '@/object-record/record-index/hooks
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState'; import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState';
import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation'; import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { ViewField } from '@/views/types/ViewField'; import { ViewField } from '@/views/types/ViewField';
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
@ -48,10 +48,9 @@ export const RecordIndexTableContainerEffect = () => {
const handleToggleColumnSort = useHandleToggleColumnSort({ const handleToggleColumnSort = useHandleToggleColumnSort({
objectNameSingular, objectNameSingular,
viewBarId,
}); });
const { currentViewWithSavedFiltersAndSorts } = useGetCurrentView(); const { currentView } = useGetCurrentViewOnly();
useEffect(() => { useEffect(() => {
setOnToggleColumnFilter( setOnToggleColumnFilter(
@ -115,13 +114,10 @@ export const RecordIndexTableContainerEffect = () => {
); );
useEffect(() => { useEffect(() => {
currentViewWithSavedFiltersAndSorts?.viewFields.forEach((viewField) => { currentView?.viewFields.forEach((viewField) => {
setViewFieldAggregateOperation(viewField); setViewFieldAggregateOperation(viewField);
}); });
}, [ }, [currentView, setViewFieldAggregateOperation]);
currentViewWithSavedFiltersAndSorts?.viewFields,
setViewFieldAggregateOperation,
]);
return <></>; return <></>;
}; };

View File

@ -5,10 +5,9 @@ import { currentRecordFiltersComponentState } from '@/object-record/record-filte
import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter'; import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
import { useCurrentRecordGroupDefinition } from '@/object-record/record-group/hooks/useCurrentRecordGroupDefinition'; import { useCurrentRecordGroupDefinition } from '@/object-record/record-group/hooks/useCurrentRecordGroupDefinition';
import { useRecordGroupFilter } from '@/object-record/record-group/hooks/useRecordGroupFilter'; import { useRecordGroupFilter } from '@/object-record/record-group/hooks/useRecordGroupFilter';
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
import { tableViewFilterGroupsComponentState } from '@/object-record/record-table/states/tableViewFilterGroupsComponentState'; import { tableViewFilterGroupsComponentState } from '@/object-record/record-table/states/tableViewFilterGroupsComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
export const useFindManyRecordIndexTableParams = ( export const useFindManyRecordIndexTableParams = (
objectNameSingular: string, objectNameSingular: string,
@ -29,12 +28,9 @@ export const useFindManyRecordIndexTableParams = (
recordTableId, recordTableId,
); );
const { currentViewWithCombinedFiltersAndSorts } = const currentRecordSorts = useRecoilComponentValueV2(
useGetCurrentView(recordTableId); currentRecordSortsComponentState,
);
const viewSorts = currentViewWithCombinedFiltersAndSorts?.viewSorts ?? [];
const sorts = mapViewSortsToSorts(viewSorts);
const currentRecordFilters = useRecoilComponentValueV2( const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState, currentRecordFiltersComponentState,
@ -49,7 +45,7 @@ export const useFindManyRecordIndexTableParams = (
tableViewFilterGroups, tableViewFilterGroups,
); );
const orderBy = turnSortsIntoOrderBy(objectMetadataItem, sorts); const orderBy = turnSortsIntoOrderBy(objectMetadataItem, currentRecordSorts);
return { return {
objectNameSingular, objectNameSingular,

View File

@ -9,14 +9,14 @@ import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldM
import { useSelectFilterUsedInDropdown } from '@/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown'; import { useSelectFilterUsedInDropdown } from '@/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown';
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter'; import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands'; import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious'; import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState'; import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
import { useRecoilCallback, useRecoilValue } from 'recoil'; import { useRecoilCallback, useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
@ -36,7 +36,6 @@ export const useHandleToggleColumnFilter = ({
const { columnDefinitions } = const { columnDefinitions } =
useColumnDefinitionsFromFieldMetadata(objectMetadataItem); useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(viewBarId);
const { upsertRecordFilter } = useUpsertRecordFilter(); const { upsertRecordFilter } = useUpsertRecordFilter();
const { setActiveDropdownFocusIdAndMemorizePrevious } = const { setActiveDropdownFocusIdAndMemorizePrevious } =
@ -70,11 +69,13 @@ export const useHandleToggleColumnFilter = ({
}), }),
); );
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
const { selectFilterUsedInDropdown } = const { selectFilterUsedInDropdown } =
useSelectFilterUsedInDropdown(viewBarId); useSelectFilterUsedInDropdown(viewBarId);
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const handleToggleColumnFilter = useCallback( const handleToggleColumnFilter = useCallback(
async (fieldMetadataId: string) => { async (fieldMetadataId: string) => {
const correspondingColumnDefinition = columnDefinitions.find( const correspondingColumnDefinition = columnDefinitions.find(
@ -86,12 +87,11 @@ export const useHandleToggleColumnFilter = ({
const newFilterId = v4(); const newFilterId = v4();
const existingViewFilter = const existingRecordFilter = currentRecordFilters.find(
currentViewWithCombinedFiltersAndSorts?.viewFilters.find( (recordFilter) => recordFilter.fieldMetadataId === fieldMetadataId,
(viewFilter) => viewFilter.fieldMetadataId === fieldMetadataId, );
);
if (!existingViewFilter) { if (!isDefined(existingRecordFilter)) {
const fieldMetadataItem = availableFieldMetadataItemsForFilter.find( const fieldMetadataItem = availableFieldMetadataItemsForFilter.find(
(fieldMetadataItemToFind) => (fieldMetadataItemToFind) =>
fieldMetadataItemToFind.id === fieldMetadataId, fieldMetadataItemToFind.id === fieldMetadataId,
@ -121,19 +121,16 @@ export const useHandleToggleColumnFilter = ({
upsertRecordFilter(newFilter); upsertRecordFilter(newFilter);
await upsertCombinedViewFilter(newFilter);
selectFilterUsedInDropdown({ fieldMetadataItemId: fieldMetadataId }); selectFilterUsedInDropdown({ fieldMetadataItemId: fieldMetadataId });
} }
openDropdown(existingViewFilter?.id ?? newFilterId); openDropdown(existingRecordFilter?.id ?? newFilterId);
}, },
[ [
openDropdown, openDropdown,
columnDefinitions, columnDefinitions,
upsertCombinedViewFilter,
selectFilterUsedInDropdown, selectFilterUsedInDropdown,
currentViewWithCombinedFiltersAndSorts, currentRecordFilters,
availableFieldMetadataItemsForFilter, availableFieldMetadataItemsForFilter,
upsertRecordFilter, upsertRecordFilter,
], ],

View File

@ -4,17 +4,14 @@ import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/u
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useUpsertRecordSort } from '@/object-record/record-sort/hooks/useUpsertRecordSort'; import { useUpsertRecordSort } from '@/object-record/record-sort/hooks/useUpsertRecordSort';
import { RecordSort } from '@/object-record/record-sort/types/RecordSort'; import { RecordSort } from '@/object-record/record-sort/types/RecordSort';
import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
type UseHandleToggleColumnSortProps = { type UseHandleToggleColumnSortProps = {
objectNameSingular: string; objectNameSingular: string;
viewBarId: string;
}; };
export const useHandleToggleColumnSort = ({ export const useHandleToggleColumnSort = ({
viewBarId,
objectNameSingular, objectNameSingular,
}: UseHandleToggleColumnSortProps) => { }: UseHandleToggleColumnSortProps) => {
const { objectMetadataItem } = useObjectMetadataItem({ const { objectMetadataItem } = useObjectMetadataItem({
@ -24,8 +21,6 @@ export const useHandleToggleColumnSort = ({
const { columnDefinitions } = const { columnDefinitions } =
useColumnDefinitionsFromFieldMetadata(objectMetadataItem); useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts(viewBarId);
const { upsertRecordSort } = useUpsertRecordSort(); const { upsertRecordSort } = useUpsertRecordSort();
const handleToggleColumnSort = useCallback( const handleToggleColumnSort = useCallback(
@ -44,10 +39,8 @@ export const useHandleToggleColumnSort = ({
}; };
upsertRecordSort(newSort); upsertRecordSort(newSort);
await upsertCombinedViewSort(newSort);
}, },
[columnDefinitions, upsertCombinedViewSort, upsertRecordSort], [columnDefinitions, upsertRecordSort],
); );
return handleToggleColumnSort; return handleToggleColumnSort;

View File

@ -8,7 +8,7 @@ import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUp
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState'; import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
@ -29,8 +29,6 @@ export const useHandleToggleTrashColumnFilter = ({
const { columnDefinitions } = const { columnDefinitions } =
useColumnDefinitionsFromFieldMetadata(objectMetadataItem); useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(viewBarId);
const isSoftDeleteFilterActiveComponentRecoilState = const isSoftDeleteFilterActiveComponentRecoilState =
useRecoilComponentCallbackStateV2( useRecoilComponentCallbackStateV2(
isSoftDeleteFilterActiveComponentState, isSoftDeleteFilterActiveComponentState,
@ -68,13 +66,7 @@ export const useHandleToggleTrashColumnFilter = ({
}; };
upsertRecordFilter(newFilter); upsertRecordFilter(newFilter);
upsertCombinedViewFilter(newFilter); }, [columnDefinitions, objectMetadataItem, upsertRecordFilter]);
}, [
columnDefinitions,
objectMetadataItem,
upsertCombinedViewFilter,
upsertRecordFilter,
]);
const toggleSoftDeleteFilterState = useRecoilCallback( const toggleSoftDeleteFilterState = useRecoilCallback(
({ set }) => ({ set }) =>

View File

@ -8,16 +8,13 @@ import { useRecordTableContextOrThrow } from '@/object-record/record-table/conte
import { RecordTableEmptyStateDisplay } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay'; import { RecordTableEmptyStateDisplay } from '@/object-record/record-table/empty-state/components/RecordTableEmptyStateDisplay';
import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState'; import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
export const RecordTableEmptyStateSoftDelete = () => { export const RecordTableEmptyStateSoftDelete = () => {
const { objectMetadataItem, objectNameSingular, recordTableId } = const { objectMetadataItem, objectNameSingular, recordTableId } =
useRecordTableContextOrThrow(); useRecordTableContextOrThrow();
const { deleteCombinedViewFilter } =
useDeleteCombinedViewFilters(recordTableId);
const tableFilters = useRecoilComponentValueV2( const tableFilters = useRecoilComponentValueV2(
tableFiltersComponentState, tableFiltersComponentState,
recordTableId, recordTableId,
@ -40,7 +37,6 @@ export const RecordTableEmptyStateSoftDelete = () => {
} }
removeRecordFilter(deletedFilter.fieldMetadataId); removeRecordFilter(deletedFilter.fieldMetadataId);
deleteCombinedViewFilter(deletedFilter.id);
toggleSoftDeleteFilterState(false); toggleSoftDeleteFilterState(false);
}; };

View File

@ -1,9 +1,9 @@
import { useAggregateRecords } from '@/object-record/hooks/useAggregateRecords'; import { useAggregateRecords } from '@/object-record/hooks/useAggregateRecords';
import { computeAggregateValueAndLabel } from '@/object-record/record-board/record-board-column/utils/computeAggregateValueAndLabel'; import { computeAggregateValueAndLabel } from '@/object-record/record-board/record-board-column/utils/computeAggregateValueAndLabel';
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies'; import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter'; import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
import { useRecordGroupFilter } from '@/object-record/record-group/hooks/useRecordGroupFilter'; import { useRecordGroupFilter } from '@/object-record/record-group/hooks/useRecordGroupFilter';
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState'; import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations'; import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext'; import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
@ -11,6 +11,7 @@ import { RecordTableColumnAggregateFooterCellContext } from '@/object-record/rec
import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState'; import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState';
import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations'; import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation'; import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { UserContext } from '@/users/contexts/UserContext'; import { UserContext } from '@/users/contexts/UserContext';
import { useContext } from 'react'; import { useContext } from 'react';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
@ -26,13 +27,15 @@ export const useAggregateRecordsForRecordTableColumnFooter = (
recordIndexViewFilterGroupsState, recordIndexViewFilterGroupsState,
); );
const recordIndexFilters = useRecoilValue(recordIndexFiltersState); const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const { filterValueDependencies } = useFilterValueDependencies(); const { filterValueDependencies } = useFilterValueDependencies();
const requestFilters = computeViewRecordGqlOperationFilter( const requestFilters = computeViewRecordGqlOperationFilter(
filterValueDependencies, filterValueDependencies,
recordIndexFilters, currentRecordFilters,
objectMetadataItem.fields, objectMetadataItem.fields,
recordIndexViewFilterGroups, recordIndexViewFilterGroups,
); );

View File

@ -3,7 +3,7 @@ import { viewFieldAggregateOperationState } from '@/object-record/record-table/r
import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations'; import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import { convertExtendedAggregateOperationToAggregateOperation } from '@/object-record/utils/convertExtendedAggregateOperationToAggregateOperation'; import { convertExtendedAggregateOperationToAggregateOperation } from '@/object-record/utils/convertExtendedAggregateOperationToAggregateOperation';
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords'; import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { useContext } from 'react'; import { useContext } from 'react';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
@ -11,12 +11,11 @@ export const useViewFieldAggregateOperation = () => {
const { fieldMetadataId } = useContext( const { fieldMetadataId } = useContext(
RecordTableColumnAggregateFooterDropdownContext, RecordTableColumnAggregateFooterDropdownContext,
); );
const { currentViewWithSavedFiltersAndSorts } = useGetCurrentView(); const { currentView } = useGetCurrentViewOnly();
const currentViewField = const currentViewField = currentView?.viewFields?.find(
currentViewWithSavedFiltersAndSorts?.viewFields?.find( (viewField) => viewField.fieldMetadataId === fieldMetadataId,
(viewField) => viewField.fieldMetadataId === fieldMetadataId, );
);
const { updateViewFieldRecords } = usePersistViewFieldRecords(); const { updateViewFieldRecords } = usePersistViewFieldRecords();
const updateViewFieldAggregateOperation = ( const updateViewFieldAggregateOperation = (
aggregateOperation: ExtendedAggregateOperations | null, aggregateOperation: ExtendedAggregateOperations | null,

View File

@ -4,29 +4,35 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { AdvancedFilterRootLevelViewFilterGroup } from '@/object-record/advanced-filter/components/AdvancedFilterRootLevelViewFilterGroup'; import { AdvancedFilterRootLevelViewFilterGroup } from '@/object-record/advanced-filter/components/AdvancedFilterRootLevelViewFilterGroup';
import { useDeleteCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup'; import { useDeleteCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup';
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { AdvancedFilterChip } from '@/views/components/AdvancedFilterChip'; import { AdvancedFilterChip } from '@/views/components/AdvancedFilterChip';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId'; import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
export const AdvancedFilterDropdownButton = () => { export const AdvancedFilterDropdownButton = () => {
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
const { deleteCombinedViewFilterGroup } = useDeleteCombinedViewFilterGroup(); const { deleteCombinedViewFilterGroup } = useDeleteCombinedViewFilterGroup();
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(); const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
const advancedViewFilterIds = const currentRecordFilters = useRecoilComponentValueV2(
currentViewWithCombinedFiltersAndSorts?.viewFilters currentRecordFiltersComponentState,
.filter((viewFilter) => isDefined(viewFilter.viewFilterGroupId)) );
.map((viewFilter) => viewFilter.id);
const advancedRecordFilterIds = currentRecordFilters
.filter((recordFilter) => isDefined(recordFilter.viewFilterGroupId))
.map((recordFilter) => recordFilter.id);
const { removeRecordFilter } = useRemoveRecordFilter();
const handleDropdownClickOutside = useCallback(() => {}, []); const handleDropdownClickOutside = useCallback(() => {}, []);
const handleDropdownClose = () => {}; const handleDropdownClose = () => {};
const removeAdvancedFilter = useCallback(async () => { const removeAdvancedFilter = useCallback(async () => {
if (!advancedViewFilterIds) { if (!advancedRecordFilterIds) {
throw new Error('No advanced view filters to remove'); throw new Error('No advanced view filters to remove');
} }
@ -39,12 +45,12 @@ export const AdvancedFilterDropdownButton = () => {
await deleteCombinedViewFilterGroup(viewFilterGroupId); await deleteCombinedViewFilterGroup(viewFilterGroupId);
} }
for (const viewFilterId of advancedViewFilterIds) { for (const recordFilterId of advancedRecordFilterIds) {
await deleteCombinedViewFilter(viewFilterId); removeRecordFilter(recordFilterId);
} }
}, [ }, [
advancedViewFilterIds, advancedRecordFilterIds,
deleteCombinedViewFilter, removeRecordFilter,
deleteCombinedViewFilterGroup, deleteCombinedViewFilterGroup,
currentViewWithCombinedFiltersAndSorts?.viewFilterGroups, currentViewWithCombinedFiltersAndSorts?.viewFilterGroups,
]); ]);
@ -64,7 +70,7 @@ export const AdvancedFilterDropdownButton = () => {
clickableComponent={ clickableComponent={
<AdvancedFilterChip <AdvancedFilterChip
onRemove={removeAdvancedFilter} onRemove={removeAdvancedFilter}
advancedFilterCount={advancedViewFilterIds?.length} advancedFilterCount={advancedRecordFilterIds?.length}
/> />
} }
dropdownComponents={ dropdownComponents={

View File

@ -10,7 +10,6 @@ import { ObjectFilterOperandSelectAndInput } from '@/object-record/object-filter
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter'; import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand'; import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
import { EditableFilterDropdownButtonEffect } from '@/views/components/EditableFilterDropdownButtonEffect'; import { EditableFilterDropdownButtonEffect } from '@/views/components/EditableFilterDropdownButtonEffect';
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
type EditableFilterDropdownButtonProps = { type EditableFilterDropdownButtonProps = {
viewFilterDropdownId: string; viewFilterDropdownId: string;
@ -25,19 +24,16 @@ export const EditableFilterDropdownButton = ({
}: EditableFilterDropdownButtonProps) => { }: EditableFilterDropdownButtonProps) => {
const { closeDropdown } = useDropdown(viewFilterDropdownId); const { closeDropdown } = useDropdown(viewFilterDropdownId);
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
const { removeRecordFilter } = useRemoveRecordFilter(); const { removeRecordFilter } = useRemoveRecordFilter();
const handleRemove = () => { const handleRemove = () => {
closeDropdown(); closeDropdown();
deleteCombinedViewFilter(viewFilter.id);
removeRecordFilter(viewFilter.fieldMetadataId); removeRecordFilter(viewFilter.fieldMetadataId);
}; };
const handleDropdownClickOutside = useCallback(() => { const handleDropdownClickOutside = useCallback(() => {
const { id: fieldId, value, operand, fieldMetadataId } = viewFilter; const { value, operand, fieldMetadataId } = viewFilter;
if ( if (
!value && !value &&
![ ![
@ -49,9 +45,8 @@ export const EditableFilterDropdownButton = ({
].includes(operand) ].includes(operand)
) { ) {
removeRecordFilter(fieldMetadataId); removeRecordFilter(fieldMetadataId);
deleteCombinedViewFilter(fieldId);
} }
}, [viewFilter, deleteCombinedViewFilter, removeRecordFilter]); }, [viewFilter, removeRecordFilter]);
return ( return (
<> <>

View File

@ -5,24 +5,17 @@ import { useRemoveRecordSort } from '@/object-record/record-sort/hooks/useRemove
import { useUpsertRecordSort } from '@/object-record/record-sort/hooks/useUpsertRecordSort'; import { useUpsertRecordSort } from '@/object-record/record-sort/hooks/useUpsertRecordSort';
import { RecordSort } from '@/object-record/record-sort/types/RecordSort'; import { RecordSort } from '@/object-record/record-sort/types/RecordSort';
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip'; import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
import { useDeleteCombinedViewSorts } from '@/views/hooks/useDeleteCombinedViewSorts';
import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts';
type EditableSortChipProps = { type EditableSortChipProps = {
recordSort: RecordSort; recordSort: RecordSort;
}; };
export const EditableSortChip = ({ recordSort }: EditableSortChipProps) => { export const EditableSortChip = ({ recordSort }: EditableSortChipProps) => {
const { deleteCombinedViewSort } = useDeleteCombinedViewSorts();
const { removeRecordSort } = useRemoveRecordSort(); const { removeRecordSort } = useRemoveRecordSort();
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts();
const { upsertRecordSort } = useUpsertRecordSort(); const { upsertRecordSort } = useUpsertRecordSort();
const handleRemoveClick = () => { const handleRemoveClick = () => {
deleteCombinedViewSort(recordSort.fieldMetadataId);
removeRecordSort(recordSort.fieldMetadataId); removeRecordSort(recordSort.fieldMetadataId);
}; };
@ -36,7 +29,6 @@ export const EditableSortChip = ({ recordSort }: EditableSortChipProps) => {
direction: recordSort.direction === 'asc' ? 'desc' : 'asc', direction: recordSort.direction === 'asc' ? 'desc' : 'asc',
}; };
upsertCombinedViewSort(newSort);
upsertRecordSort(newSort); upsertRecordSort(newSort);
}; };

View File

@ -1,26 +1,13 @@
import { useEffect } from 'react'; import { useEffect } from 'react';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
import { useApplyViewFiltersToCurrentRecordFilters } from '@/views/hooks/useApplyViewFiltersToCurrentRecordFilters'; import { useApplyViewFiltersToCurrentRecordFilters } from '@/views/hooks/useApplyViewFiltersToCurrentRecordFilters';
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates'; import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
export const QueryParamsFiltersEffect = () => { export const QueryParamsFiltersEffect = () => {
const { hasFiltersQueryParams, getFiltersFromQueryParams, viewIdQueryParam } = const { hasFiltersQueryParams, getFiltersFromQueryParams } =
useViewFromQueryParams(); useViewFromQueryParams();
const currentViewId = useRecoilComponentValueV2(
contextStoreCurrentViewIdComponentState,
);
const setUnsavedViewFilter = useSetRecoilComponentFamilyStateV2(
unsavedToUpsertViewFiltersComponentFamilyState,
{ viewId: viewIdQueryParam ?? currentViewId },
);
const { resetUnsavedViewStates } = useResetUnsavedViewStates(); const { resetUnsavedViewStates } = useResetUnsavedViewStates();
const { applyViewFiltersToCurrentRecordFilters } = const { applyViewFiltersToCurrentRecordFilters } =
@ -34,7 +21,6 @@ export const QueryParamsFiltersEffect = () => {
getFiltersFromQueryParams().then((filtersFromParams) => { getFiltersFromQueryParams().then((filtersFromParams) => {
if (Array.isArray(filtersFromParams)) { if (Array.isArray(filtersFromParams)) {
applyViewFiltersToCurrentRecordFilters(filtersFromParams); applyViewFiltersToCurrentRecordFilters(filtersFromParams);
setUnsavedViewFilter(filtersFromParams);
} }
}); });
}, [ }, [
@ -42,7 +28,6 @@ export const QueryParamsFiltersEffect = () => {
getFiltersFromQueryParams, getFiltersFromQueryParams,
hasFiltersQueryParams, hasFiltersQueryParams,
resetUnsavedViewStates, resetUnsavedViewStates,
setUnsavedViewFilter,
]); ]);
return <></>; return <></>;

View File

@ -4,15 +4,12 @@ import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetada
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter'; import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip'; import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
type RecordFilterChipProps = { type RecordFilterChipProps = {
recordFilter: RecordFilter; recordFilter: RecordFilter;
}; };
export const RecordFilterChip = ({ recordFilter }: RecordFilterChipProps) => { export const RecordFilterChip = ({ recordFilter }: RecordFilterChipProps) => {
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
const { fieldMetadataItem } = useFieldMetadataItemById( const { fieldMetadataItem } = useFieldMetadataItemById(
recordFilter.fieldMetadataId, recordFilter.fieldMetadataId,
); );
@ -24,7 +21,6 @@ export const RecordFilterChip = ({ recordFilter }: RecordFilterChipProps) => {
const FieldMetadataItemIcon = getIcon(fieldMetadataItem.icon); const FieldMetadataItemIcon = getIcon(fieldMetadataItem.icon);
const handleRemoveClick = () => { const handleRemoveClick = () => {
deleteCombinedViewFilter(recordFilter.id);
removeRecordFilter(recordFilter.fieldMetadataId); removeRecordFilter(recordFilter.fieldMetadataId);
}; };

View File

@ -5,7 +5,6 @@ import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState'; import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip'; import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
type SoftDeleteFilterChipProps = { type SoftDeleteFilterChipProps = {
recordFilter: RecordFilter; recordFilter: RecordFilter;
@ -16,8 +15,6 @@ export const SoftDeleteFilterChip = ({
recordFilter, recordFilter,
viewBarId, viewBarId,
}: SoftDeleteFilterChipProps) => { }: SoftDeleteFilterChipProps) => {
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
const setIsSoftDeleteFilterActive = useSetRecoilComponentStateV2( const setIsSoftDeleteFilterActive = useSetRecoilComponentStateV2(
isSoftDeleteFilterActiveComponentState, isSoftDeleteFilterActiveComponentState,
viewBarId, viewBarId,
@ -28,7 +25,6 @@ export const SoftDeleteFilterChip = ({
const { getIcon } = useIcons(); const { getIcon } = useIcons();
const handleRemoveClick = () => { const handleRemoveClick = () => {
deleteCombinedViewFilter(recordFilter.id);
removeRecordFilter(recordFilter.fieldMetadataId); removeRecordFilter(recordFilter.fieldMetadataId);
setIsSoftDeleteFilterActive(false); setIsSoftDeleteFilterActive(false);

View File

@ -10,7 +10,6 @@ import { QueryParamsFiltersEffect } from '@/views/components/QueryParamsFiltersE
import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect'; import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
import { ViewBarPageTitle } from '@/views/components/ViewBarPageTitle'; import { ViewBarPageTitle } from '@/views/components/ViewBarPageTitle';
import { ViewBarSkeletonLoader } from '@/views/components/ViewBarSkeletonLoader'; import { ViewBarSkeletonLoader } from '@/views/components/ViewBarSkeletonLoader';
import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect';
import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDropdown'; import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDropdown';
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope'; import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
@ -51,9 +50,7 @@ export const ViewBar = ({
<ViewBarRecordFilterEffect /> <ViewBarRecordFilterEffect />
<ViewBarRecordSortEffect /> <ViewBarRecordSortEffect />
<ViewBarFilterEffect filterDropdownId={filterDropdownId} /> <ViewBarFilterEffect filterDropdownId={filterDropdownId} />
<ViewBarSortEffect />
<QueryParamsFiltersEffect /> <QueryParamsFiltersEffect />
<ViewBarPageTitle viewBarId={viewBarId} /> <ViewBarPageTitle viewBarId={viewBarId} />
<TopBar <TopBar
className={className} className={className}

View File

@ -7,7 +7,7 @@ import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-sta
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { objectFilterDropdownSelectedOptionValuesComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState'; import { objectFilterDropdownSelectedOptionValuesComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState';
import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState'; import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { jsonRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/jsonRelationFilterValueSchema'; import { jsonRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/jsonRelationFilterValueSchema';
import { simpleRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/simpleRelationFilterValueSchema'; import { simpleRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/simpleRelationFilterValueSchema';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
@ -19,8 +19,6 @@ type ViewBarFilterEffectProps = {
export const ViewBarFilterEffect = ({ export const ViewBarFilterEffect = ({
filterDropdownId, filterDropdownId,
}: ViewBarFilterEffectProps) => { }: ViewBarFilterEffectProps) => {
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
fieldMetadataItemUsedInDropdownComponentSelector, fieldMetadataItemUsedInDropdownComponentSelector,
filterDropdownId, filterDropdownId,
@ -37,46 +35,48 @@ export const ViewBarFilterEffect = ({
filterDropdownId, filterDropdownId,
); );
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
useEffect(() => { useEffect(() => {
if (fieldMetadataItemUsedInDropdown?.type === 'RELATION') { if (fieldMetadataItemUsedInDropdown?.type === 'RELATION') {
const viewFilterUsedInDropdown = const recordFilterUsedInDropdown = currentRecordFilters.find(
currentViewWithCombinedFiltersAndSorts?.viewFilters.find( (filter) =>
(filter) => filter.fieldMetadataId === fieldMetadataItemUsedInDropdown?.id,
filter.fieldMetadataId === fieldMetadataItemUsedInDropdown?.id, );
);
const { selectedRecordIds } = jsonRelationFilterValueSchema const { selectedRecordIds } = jsonRelationFilterValueSchema
.catch({ .catch({
isCurrentWorkspaceMemberSelected: false, isCurrentWorkspaceMemberSelected: false,
selectedRecordIds: simpleRelationFilterValueSchema.parse( selectedRecordIds: simpleRelationFilterValueSchema.parse(
viewFilterUsedInDropdown?.value, recordFilterUsedInDropdown?.value,
), ),
}) })
.parse(viewFilterUsedInDropdown?.value); .parse(recordFilterUsedInDropdown?.value);
setObjectFilterDropdownSelectedRecordIds(selectedRecordIds); setObjectFilterDropdownSelectedRecordIds(selectedRecordIds);
} else if ( } else if (
isDefined(fieldMetadataItemUsedInDropdown) && isDefined(fieldMetadataItemUsedInDropdown) &&
['SELECT', 'MULTI_SELECT'].includes(fieldMetadataItemUsedInDropdown.type) ['SELECT', 'MULTI_SELECT'].includes(fieldMetadataItemUsedInDropdown.type)
) { ) {
const viewFilterUsedInDropdown = const recordFilterUsedInDropdown = currentRecordFilters.find(
currentViewWithCombinedFiltersAndSorts?.viewFilters.find( (filter) =>
(filter) => filter.fieldMetadataId === fieldMetadataItemUsedInDropdown?.id,
filter.fieldMetadataId === fieldMetadataItemUsedInDropdown?.id, );
);
const viewFilterSelectedRecords = isNonEmptyString( const recordFilterSelectedRecords = isNonEmptyString(
viewFilterUsedInDropdown?.value, recordFilterUsedInDropdown?.value,
) )
? JSON.parse(viewFilterUsedInDropdown.value) ? JSON.parse(recordFilterUsedInDropdown.value)
: []; : [];
setObjectFilterDropdownSelectedOptionValues(viewFilterSelectedRecords); setObjectFilterDropdownSelectedOptionValues(recordFilterSelectedRecords);
} }
}, [ }, [
fieldMetadataItemUsedInDropdown, fieldMetadataItemUsedInDropdown,
setObjectFilterDropdownSelectedRecordIds, setObjectFilterDropdownSelectedRecordIds,
setObjectFilterDropdownSelectedOptionValues, setObjectFilterDropdownSelectedOptionValues,
currentViewWithCombinedFiltersAndSorts, currentRecordFilters,
]); ]);
return <></>; return <></>;

View File

@ -1,29 +0,0 @@
import { useEffect } from 'react';
import { onSortSelectComponentState } from '@/object-record/object-sort-dropdown/states/onSortSelectScopedState';
import { useUpsertRecordSort } from '@/object-record/record-sort/hooks/useUpsertRecordSort';
import { RecordSort } from '@/object-record/record-sort/types/RecordSort';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts';
import { isDefined } from 'twenty-shared';
export const ViewBarSortEffect = () => {
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts();
const { upsertRecordSort } = useUpsertRecordSort();
const setOnSortSelect = useSetRecoilComponentStateV2(
onSortSelectComponentState,
);
useEffect(() => {
setOnSortSelect(() => (sort: RecordSort | null) => {
if (isDefined(sort)) {
upsertCombinedViewSort(sort);
upsertRecordSort(sort);
}
});
}, [setOnSortSelect, upsertCombinedViewSort, upsertRecordSort]);
return <></>;
};

View File

@ -2,23 +2,26 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords'; import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector'; import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords'; import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
import { usePersistViewFilterGroupRecords } from '@/views/hooks/internal/usePersistViewFilterGroupRecords'; import { usePersistViewFilterGroupRecords } from '@/views/hooks/internal/usePersistViewFilterGroupRecords';
import { usePersistViewFilterRecords } from '@/views/hooks/internal/usePersistViewFilterRecords'; import { usePersistViewFilterRecords } from '@/views/hooks/internal/usePersistViewFilterRecords';
import { usePersistViewGroupRecords } from '@/views/hooks/internal/usePersistViewGroupRecords'; import { usePersistViewGroupRecords } from '@/views/hooks/internal/usePersistViewGroupRecords';
import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords'; import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords';
import { useGetViewFilterGroupsCombined } from '@/views/hooks/useGetCombinedViewFilterGroups'; import { useGetViewFilterGroupsCombined } from '@/views/hooks/useGetCombinedViewFilterGroups';
import { useGetViewFiltersCombined } from '@/views/hooks/useGetCombinedViewFilters';
import { useGetViewSortsCombined } from '@/views/hooks/useGetCombinedViewSorts';
import { isPersistingViewFieldsState } from '@/views/states/isPersistingViewFieldsState'; import { isPersistingViewFieldsState } from '@/views/states/isPersistingViewFieldsState';
import { GraphQLView } from '@/views/types/GraphQLView'; import { GraphQLView } from '@/views/types/GraphQLView';
import { View } from '@/views/types/View'; import { View } from '@/views/types/View';
import { ViewGroup } from '@/views/types/ViewGroup'; import { ViewGroup } from '@/views/types/ViewGroup';
import { ViewType } from '@/views/types/ViewType'; import { ViewType } from '@/views/types/ViewType';
import { mapRecordFilterToViewFilter } from '@/views/utils/mapRecordFilterToViewFilter';
import { mapRecordSortToViewSort } from '@/views/utils/mapRecordSortToViewSort';
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
@ -36,9 +39,6 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
const { createViewFieldRecords } = usePersistViewFieldRecords(); const { createViewFieldRecords } = usePersistViewFieldRecords();
const { getViewSortsCombined } = useGetViewSortsCombined(viewBarComponentId);
const { getViewFiltersCombined } =
useGetViewFiltersCombined(viewBarComponentId);
const { getViewFilterGroupsCombined } = const { getViewFilterGroupsCombined } =
useGetViewFilterGroupsCombined(viewBarComponentId); useGetViewFilterGroupsCombined(viewBarComponentId);
@ -57,6 +57,14 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
fetchPolicy: 'network-only', fetchPolicy: 'network-only',
}); });
const currentRecordSorts = useRecoilComponentValueV2(
currentRecordSortsComponentState,
);
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const createViewFromCurrentView = useRecoilCallback( const createViewFromCurrentView = useRecoilCallback(
({ snapshot, set }) => ({ snapshot, set }) =>
async ( async (
@ -160,13 +168,16 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
const sourceViewCombinedFilterGroups = getViewFilterGroupsCombined( const sourceViewCombinedFilterGroups = getViewFilterGroupsCombined(
sourceView.id, sourceView.id,
); );
const sourceViewCombinedFilters = getViewFiltersCombined(
sourceView.id,
);
const sourceViewCombinedSorts = getViewSortsCombined(sourceView.id);
await createViewSortRecords(sourceViewCombinedSorts, newView); const viewSortsToCreate = currentRecordSorts.map(
await createViewFilterRecords(sourceViewCombinedFilters, newView); mapRecordSortToViewSort,
);
const viewFiltersToCreate = currentRecordFilters.map(
mapRecordFilterToViewFilter,
);
await createViewSortRecords(viewSortsToCreate, newView);
await createViewFilterRecords(viewFiltersToCreate, newView);
await createViewFilterGroupRecords( await createViewFilterGroupRecords(
sourceViewCombinedFilterGroups, sourceViewCombinedFilterGroups,
newView, newView,
@ -182,13 +193,13 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
createViewFieldRecords, createViewFieldRecords,
findManyRecords, findManyRecords,
objectMetadataItem.fields, objectMetadataItem.fields,
createViewGroupRecords,
getViewFilterGroupsCombined, getViewFilterGroupsCombined,
getViewFiltersCombined, createViewGroupRecords,
getViewSortsCombined,
createViewSortRecords, createViewSortRecords,
createViewFilterRecords, createViewFilterRecords,
createViewFilterGroupRecords, createViewFilterGroupRecords,
currentRecordFilters,
currentRecordSorts,
], ],
); );

View File

@ -1,101 +0,0 @@
import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { isDefined } from 'twenty-shared';
export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => {
const unsavedToUpsertViewFiltersCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewFiltersComponentFamilyState,
viewBarComponentId,
);
const unsavedToDeleteViewFilterIdsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToDeleteViewFilterIdsComponentFamilyState,
viewBarComponentId,
);
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const deleteCombinedViewFilter = useRecoilCallback(
({ snapshot, set }) =>
async (fieldId: string) => {
const currentViewId = getSnapshotValue(
snapshot,
currentViewIdCallbackState,
);
const unsavedToUpsertViewFilters = getSnapshotValue(
snapshot,
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
);
const unsavedToDeleteViewFilterIds = getSnapshotValue(
snapshot,
unsavedToDeleteViewFilterIdsCallbackState({ viewId: currentViewId }),
);
if (!currentViewId) {
return;
}
const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
}
const matchingFilterInCurrentView = currentView.viewFilters.find(
(viewFilter) => viewFilter.id === fieldId,
);
const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find(
(viewFilter) => viewFilter.id === fieldId,
);
if (isDefined(matchingFilterInUnsavedFilters)) {
set(
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
unsavedToUpsertViewFilters.filter(
(viewFilter) => viewFilter.id !== fieldId,
),
);
}
if (isDefined(matchingFilterInCurrentView)) {
set(
unsavedToDeleteViewFilterIdsCallbackState({
viewId: currentViewId,
}),
[
...new Set([
...unsavedToDeleteViewFilterIds,
matchingFilterInCurrentView.id,
]),
],
);
}
},
[
currentViewIdCallbackState,
getViewFromPrefetchState,
unsavedToDeleteViewFilterIdsCallbackState,
unsavedToUpsertViewFiltersCallbackState,
],
);
return {
deleteCombinedViewFilter,
};
};

View File

@ -1,99 +0,0 @@
import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
import { isDefined } from 'twenty-shared';
export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => {
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
contextStoreCurrentViewIdComponentState,
);
const unsavedToUpsertViewSortsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewSortsComponentFamilyState,
viewBarComponentId,
);
const unsavedToDeleteViewSortIdsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToDeleteViewSortIdsComponentFamilyState,
viewBarComponentId,
);
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const deleteCombinedViewSort = useRecoilCallback(
({ snapshot, set }) =>
async (fieldMetadataId: string) => {
const currentViewId = getSnapshotValue(
snapshot,
currentViewIdCallbackState,
);
if (!currentViewId) {
return;
}
const unsavedToUpsertViewSorts = getSnapshotValue(
snapshot,
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
);
const unsavedToDeleteViewSortIds = getSnapshotValue(
snapshot,
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
);
const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
}
const matchingSortInCurrentView = currentView.viewSorts.find(
(viewSort) => viewSort.fieldMetadataId === fieldMetadataId,
);
const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find(
(viewSort) => viewSort.fieldMetadataId === fieldMetadataId,
);
if (isDefined(matchingSortInUnsavedSorts)) {
set(
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
unsavedToUpsertViewSorts.filter(
(viewSort) => viewSort.fieldMetadataId !== fieldMetadataId,
),
);
return;
}
if (isDefined(matchingSortInCurrentView)) {
set(
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
[
...new Set([
...unsavedToDeleteViewSortIds,
matchingSortInCurrentView.id,
]),
],
);
}
},
[
currentViewIdCallbackState,
getViewFromPrefetchState,
unsavedToDeleteViewSortIdsCallbackState,
unsavedToUpsertViewSortsCallbackState,
],
);
return {
deleteCombinedViewSort,
};
};

View File

@ -1,68 +0,0 @@
import { useRecoilCallback } from 'recoil';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters';
import { isDefined } from 'twenty-shared';
export const useGetViewFiltersCombined = (viewBarComponentId?: string) => {
const unsavedToUpsertViewFiltersCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewFiltersComponentFamilyState,
viewBarComponentId,
);
const unsavedToDeleteViewFilterIdsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToDeleteViewFilterIdsComponentFamilyState,
viewBarComponentId,
);
const getViewFiltersCombined = useRecoilCallback(
({ snapshot }) =>
(viewId: string) => {
const view = snapshot
.getLoadable(
prefetchViewFromViewIdFamilySelector({
viewId,
}),
)
.getValue();
if (!isDefined(view)) {
throw new Error(
`Cannot get view with id ${viewId}, because it cannot be found in client cache data.`,
);
}
const unsavedToUpsertViewFilters = getSnapshotValue(
snapshot,
unsavedToUpsertViewFiltersCallbackState({ viewId: view.id }),
);
const unsavedToDeleteViewFilterIds = getSnapshotValue(
snapshot,
unsavedToDeleteViewFilterIdsCallbackState({ viewId: view.id }),
);
const combinedViewFilters = getCombinedViewFilters(
view.viewFilters,
unsavedToUpsertViewFilters,
unsavedToDeleteViewFilterIds,
);
return combinedViewFilters;
},
[
unsavedToDeleteViewFilterIdsCallbackState,
unsavedToUpsertViewFiltersCallbackState,
],
);
return {
getViewFiltersCombined,
};
};

View File

@ -1,69 +0,0 @@
import { useRecoilCallback } from 'recoil';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts';
import { isDefined } from 'twenty-shared';
// TODO: fix naming
export const useGetViewSortsCombined = (viewBarComponentId?: string) => {
const unsavedToUpsertViewSortsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewSortsComponentFamilyState,
viewBarComponentId,
);
const unsavedToDeleteViewSortIdsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToDeleteViewSortIdsComponentFamilyState,
viewBarComponentId,
);
const getViewSortsCombined = useRecoilCallback(
({ snapshot }) =>
(viewId: string) => {
const view = snapshot
.getLoadable(
prefetchViewFromViewIdFamilySelector({
viewId,
}),
)
.getValue();
if (!isDefined(view)) {
throw new Error(
`Cannot get view with id ${viewId}, because it cannot be found in client cache data.`,
);
}
const unsavedToUpsertViewSorts = getSnapshotValue(
snapshot,
unsavedToUpsertViewSortsCallbackState({ viewId: view.id }),
);
const unsavedToDeleteViewSortIds = getSnapshotValue(
snapshot,
unsavedToDeleteViewSortIdsCallbackState({ viewId: view.id }),
);
const combinedViewSorts = getCombinedViewSorts(
view.viewSorts,
unsavedToUpsertViewSorts,
unsavedToDeleteViewSortIds,
);
return combinedViewSorts;
},
[
unsavedToDeleteViewSortIdsCallbackState,
unsavedToUpsertViewSortsCallbackState,
],
);
return {
getViewSortsCombined,
};
};

View File

@ -12,14 +12,8 @@ import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-sta
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
import { isCurrentViewKeyIndexComponentState } from '@/views/states/isCurrentViewIndexComponentState'; import { isCurrentViewKeyIndexComponentState } from '@/views/states/isCurrentViewIndexComponentState';
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState'; import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState'; import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
import { getCombinedViewFilterGroups } from '@/views/utils/getCombinedViewFilterGroups'; import { getCombinedViewFilterGroups } from '@/views/utils/getCombinedViewFilterGroups';
import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters';
import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared'; import { isDefined } from 'twenty-shared';
@ -71,42 +65,18 @@ export const useGetCurrentView = (viewBarInstanceId?: string) => {
}), }),
); );
const unsavedToUpsertViewFilters = useRecoilComponentFamilyValueV2(
unsavedToUpsertViewFiltersComponentFamilyState,
{ viewId },
instanceId,
);
const unsavedToUpsertViewFilterGroups = useRecoilComponentFamilyValueV2( const unsavedToUpsertViewFilterGroups = useRecoilComponentFamilyValueV2(
unsavedToUpsertViewFilterGroupsComponentFamilyState, unsavedToUpsertViewFilterGroupsComponentFamilyState,
{ viewId }, { viewId },
instanceId, instanceId,
); );
const unsavedToUpsertViewSorts = useRecoilComponentFamilyValueV2(
unsavedToUpsertViewSortsComponentFamilyState,
{ viewId },
instanceId,
);
const unsavedToDeleteViewFilterIds = useRecoilComponentFamilyValueV2(
unsavedToDeleteViewFilterIdsComponentFamilyState,
{ viewId },
instanceId,
);
const unsavedToDeleteViewFilterGroupIds = useRecoilComponentFamilyValueV2( const unsavedToDeleteViewFilterGroupIds = useRecoilComponentFamilyValueV2(
unsavedToDeleteViewFilterGroupIdsComponentFamilyState, unsavedToDeleteViewFilterGroupIdsComponentFamilyState,
{ viewId }, { viewId },
instanceId, instanceId,
); );
const unsavedToDeleteViewSortIds = useRecoilComponentFamilyValueV2(
unsavedToDeleteViewSortIdsComponentFamilyState,
{ viewId },
instanceId,
);
if (!isDefined(currentView)) { if (!isDefined(currentView)) {
return { return {
instanceId, instanceId,
@ -118,26 +88,15 @@ export const useGetCurrentView = (viewBarInstanceId?: string) => {
const currentViewWithCombinedFiltersAndSorts = { const currentViewWithCombinedFiltersAndSorts = {
...currentView, ...currentView,
viewFilters: getCombinedViewFilters(
currentView.viewFilters,
unsavedToUpsertViewFilters,
unsavedToDeleteViewFilterIds,
),
viewFilterGroups: getCombinedViewFilterGroups( viewFilterGroups: getCombinedViewFilterGroups(
currentView.viewFilterGroups ?? [], currentView.viewFilterGroups ?? [],
unsavedToUpsertViewFilterGroups, unsavedToUpsertViewFilterGroups,
unsavedToDeleteViewFilterGroupIds, unsavedToDeleteViewFilterGroupIds,
), ),
viewSorts: getCombinedViewSorts(
currentView.viewSorts,
unsavedToUpsertViewSorts,
unsavedToDeleteViewSortIds,
),
}; };
return { return {
instanceId, instanceId,
currentViewWithSavedFiltersAndSorts: currentView,
currentViewWithCombinedFiltersAndSorts, currentViewWithCombinedFiltersAndSorts,
viewsOnCurrentObject: viewsOnCurrentObject ?? [], viewsOnCurrentObject: viewsOnCurrentObject ?? [],
currentViewId, currentViewId,

View File

@ -1,43 +1,15 @@
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState'; import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState'; import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
export const useResetUnsavedViewStates = (viewBarInstanceId?: string) => { export const useResetUnsavedViewStates = (viewBarInstanceId?: string) => {
const setUnsavedToDeleteViewFilterIdsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToDeleteViewFilterIdsComponentFamilyState,
viewBarInstanceId,
);
const setUnsavedToDeleteViewSortIdsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToDeleteViewSortIdsComponentFamilyState,
viewBarInstanceId,
);
const unsavedToDeleteViewFilterGroupIdsCallbackState = const unsavedToDeleteViewFilterGroupIdsCallbackState =
useRecoilComponentCallbackStateV2( useRecoilComponentCallbackStateV2(
unsavedToDeleteViewFilterGroupIdsComponentFamilyState, unsavedToDeleteViewFilterGroupIdsComponentFamilyState,
viewBarInstanceId, viewBarInstanceId,
); );
const setUnsavedToUpsertViewFiltersCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewFiltersComponentFamilyState,
viewBarInstanceId,
);
const unsavedToUpsertViewSortsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewSortsComponentFamilyState,
viewBarInstanceId,
);
const unsavedToUpsertViewFilterGroupsCallbackState = const unsavedToUpsertViewFilterGroupsCallbackState =
useRecoilComponentCallbackStateV2( useRecoilComponentCallbackStateV2(
unsavedToUpsertViewFilterGroupsComponentFamilyState, unsavedToUpsertViewFilterGroupsComponentFamilyState,
@ -48,18 +20,10 @@ export const useResetUnsavedViewStates = (viewBarInstanceId?: string) => {
({ set }) => ({ set }) =>
(viewId: string) => { (viewId: string) => {
set(unsavedToDeleteViewFilterGroupIdsCallbackState({ viewId }), []); set(unsavedToDeleteViewFilterGroupIdsCallbackState({ viewId }), []);
set(setUnsavedToDeleteViewFilterIdsCallbackState({ viewId }), []);
set(setUnsavedToDeleteViewSortIdsCallbackState({ viewId }), []);
set(unsavedToUpsertViewFilterGroupsCallbackState({ viewId }), []); set(unsavedToUpsertViewFilterGroupsCallbackState({ viewId }), []);
set(setUnsavedToUpsertViewFiltersCallbackState({ viewId }), []);
set(unsavedToUpsertViewSortsCallbackState({ viewId }), []);
}, },
[ [
unsavedToUpsertViewSortsCallbackState,
setUnsavedToUpsertViewFiltersCallbackState,
unsavedToUpsertViewFilterGroupsCallbackState, unsavedToUpsertViewFilterGroupsCallbackState,
setUnsavedToDeleteViewSortIdsCallbackState,
setUnsavedToDeleteViewFilterIdsCallbackState,
unsavedToDeleteViewFilterGroupIdsCallbackState, unsavedToDeleteViewFilterGroupIdsCallbackState,
], ],
); );

View File

@ -1,132 +0,0 @@
import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { ViewFilter } from '@/views/types/ViewFilter';
import { shouldReplaceFilter } from '@/views/utils/shouldReplaceFilter';
import { isDefined } from 'twenty-shared';
export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => {
const unsavedToUpsertViewFiltersCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewFiltersComponentFamilyState,
viewBarComponentId,
);
const unsavedToDeleteViewFilterIdsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToDeleteViewFilterIdsComponentFamilyState,
viewBarComponentId,
);
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const upsertCombinedViewFilter = useRecoilCallback(
({ snapshot, set }) =>
async (upsertedFilter: RecordFilter) => {
const currentViewId = getSnapshotValue(
snapshot,
currentViewIdCallbackState,
);
const unsavedToUpsertViewFilters = getSnapshotValue(
snapshot,
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
);
const unsavedToDeleteViewFilterIds = getSnapshotValue(
snapshot,
unsavedToDeleteViewFilterIdsCallbackState({ viewId: currentViewId }),
);
if (!currentViewId) {
return;
}
const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
}
const matchingFilterInCurrentView = currentView.viewFilters.find(
(viewFilter) => shouldReplaceFilter(viewFilter, upsertedFilter),
);
const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find(
(viewFilter) => shouldReplaceFilter(viewFilter, upsertedFilter),
);
if (isDefined(matchingFilterInUnsavedFilters)) {
const updatedFilters = unsavedToUpsertViewFilters.map((viewFilter) =>
shouldReplaceFilter(viewFilter, matchingFilterInUnsavedFilters)
? { ...viewFilter, ...upsertedFilter, id: viewFilter.id }
: viewFilter,
);
set(
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
updatedFilters,
);
return;
}
if (isDefined(matchingFilterInCurrentView)) {
set(
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
[
...unsavedToUpsertViewFilters,
{
...matchingFilterInCurrentView,
...upsertedFilter,
id: matchingFilterInCurrentView.id,
},
],
);
set(
unsavedToDeleteViewFilterIdsCallbackState({
viewId: currentViewId,
}),
unsavedToDeleteViewFilterIds.filter(
(id) => id !== matchingFilterInCurrentView.id,
),
);
return;
}
const newValue = [
...unsavedToUpsertViewFilters,
{
...upsertedFilter,
id: upsertedFilter.id,
__typename: 'ViewFilter',
} satisfies ViewFilter,
] satisfies ViewFilter[];
set(
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
newValue,
);
},
[
currentViewIdCallbackState,
getViewFromPrefetchState,
unsavedToDeleteViewFilterIdsCallbackState,
unsavedToUpsertViewFiltersCallbackState,
],
);
return {
upsertCombinedViewFilter,
};
};

View File

@ -1,120 +0,0 @@
import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { RecordSort } from '@/object-record/record-sort/types/RecordSort';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
import { ViewSort } from '@/views/types/ViewSort';
import { isDefined } from 'twenty-shared';
export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => {
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
contextStoreCurrentViewIdComponentState,
);
const unsavedToUpsertViewSortsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewSortsComponentFamilyState,
viewBarComponentId,
);
const unsavedToDeleteViewSortIdsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToDeleteViewSortIdsComponentFamilyState,
viewBarComponentId,
);
const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const upsertCombinedViewSort = useRecoilCallback(
({ snapshot, set }) =>
async (upsertedSort: RecordSort) => {
const currentViewId = getSnapshotValue(
snapshot,
currentViewIdCallbackState,
);
const unsavedToUpsertViewSorts = getSnapshotValue(
snapshot,
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
);
const unsavedToDeleteViewSortIds = getSnapshotValue(
snapshot,
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
);
if (!currentViewId) {
return;
}
const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
}
const matchingSortInCurrentView = currentView.viewSorts.find(
(viewSort) =>
viewSort.fieldMetadataId === upsertedSort.fieldMetadataId,
);
const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find(
(viewSort) =>
viewSort.fieldMetadataId === upsertedSort.fieldMetadataId,
);
if (isDefined(matchingSortInUnsavedSorts)) {
const updatedSorts = unsavedToUpsertViewSorts.map((viewSort) =>
viewSort.id === matchingSortInUnsavedSorts.id
? { ...viewSort, ...upsertedSort }
: viewSort,
);
set(
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
updatedSorts,
);
return;
}
if (isDefined(matchingSortInCurrentView)) {
set(
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
[
...unsavedToUpsertViewSorts,
{ ...matchingSortInCurrentView, ...upsertedSort },
],
);
set(
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
unsavedToDeleteViewSortIds.filter(
(id) => id !== matchingSortInCurrentView.id,
),
);
return;
}
set(unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }), [
...unsavedToUpsertViewSorts,
{
...upsertedSort,
__typename: 'ViewSort',
} satisfies ViewSort,
]);
},
[
currentViewIdCallbackState,
getViewFromPrefetchState,
unsavedToDeleteViewSortIdsCallbackState,
unsavedToUpsertViewSortsCallbackState,
],
);
return {
upsertCombinedViewSort,
};
};

View File

@ -1,28 +0,0 @@
import { createComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
export const areViewSortsDifferentFromRecordSortsSelector =
createComponentFamilySelectorV2<boolean, { viewId?: string }>({
key: 'areViewSortsDifferentFromRecordSortsSelector',
get:
({ familyKey, instanceId }) =>
({ get }) => {
return (
get(
unsavedToUpsertViewSortsComponentFamilyState.atomFamily({
familyKey,
instanceId,
}),
).length > 0 ||
get(
unsavedToDeleteViewSortIdsComponentFamilyState.atomFamily({
familyKey,
instanceId,
}),
).length > 0
);
},
componentInstanceContext: ViewComponentInstanceContext,
});

View File

@ -1,9 +0,0 @@
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
export const unsavedToDeleteViewFilterIdsComponentFamilyState =
createComponentFamilyStateV2<string[], { viewId?: string }>({
key: 'unsavedToDeleteViewFilterIdsComponentFamilyState',
defaultValue: [],
componentInstanceContext: ViewComponentInstanceContext,
});

View File

@ -1,9 +0,0 @@
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
export const unsavedToDeleteViewSortIdsComponentFamilyState =
createComponentFamilyStateV2<string[], { viewId?: string }>({
key: 'unsavedToDeleteViewSortIdsComponentFamilyState',
defaultValue: [],
componentInstanceContext: ViewComponentInstanceContext,
});

View File

@ -1,10 +0,0 @@
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
import { ViewFilter } from '@/views/types/ViewFilter';
export const unsavedToUpsertViewFiltersComponentFamilyState =
createComponentFamilyStateV2<ViewFilter[], { viewId?: string }>({
key: 'unsavedToUpsertViewFiltersComponentFamilyState',
defaultValue: [],
componentInstanceContext: ViewComponentInstanceContext,
});

View File

@ -1,10 +0,0 @@
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
import { ViewSort } from '../types/ViewSort';
export const unsavedToUpsertViewSortsComponentFamilyState =
createComponentFamilyStateV2<ViewSort[], { viewId?: string }>({
key: 'unsavedToUpsertViewSortsComponentFamilyState',
defaultValue: [],
componentInstanceContext: ViewComponentInstanceContext,
});

View File

@ -1,112 +0,0 @@
// Generate test for getCombinedViewFilters
import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { getCombinedViewFilters } from '../getCombinedViewFilters';
describe('getCombinedViewFilters', () => {
it('should return expected combined view filters when additional filters are present', () => {
const viewFilters: ViewFilter[] = [
{
__typename: 'ViewFilter',
id: 'id',
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
value: 'testValue',
displayValue: 'Test Display Value',
operand: ViewFilterOperand.Is,
},
];
const toUpsertViewFilters: ViewFilter[] = [
{
__typename: 'ViewFilter',
id: 'id',
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
value: 'testValue',
displayValue: 'Test Display Value',
operand: ViewFilterOperand.Is,
},
];
const toDeleteViewFilterIds: string[] = [];
expect(
getCombinedViewFilters(
viewFilters,
toUpsertViewFilters,
toDeleteViewFilterIds,
),
).toEqual([
{
__typename: 'ViewFilter',
id: 'id',
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
value: 'testValue',
displayValue: 'Test Display Value',
operand: ViewFilterOperand.Is,
},
]);
});
it('should return expected combined view filters when additional filters are not present', () => {
const viewFilters: ViewFilter[] = [
{
__typename: 'ViewFilter',
id: 'id',
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
value: 'testValue',
displayValue: 'Test Display Value',
operand: ViewFilterOperand.Is,
},
];
const toUpsertViewFilters: ViewFilter[] = [];
const toDeleteViewFilterIds: string[] = [];
expect(
getCombinedViewFilters(
viewFilters,
toUpsertViewFilters,
toDeleteViewFilterIds,
),
).toEqual([
{
__typename: 'ViewFilter',
id: 'id',
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
value: 'testValue',
displayValue: 'Test Display Value',
operand: ViewFilterOperand.Is,
},
]);
});
it('should return expected combined view filters when additional filters are present and some filters are to be deleted', () => {
const viewFilters: ViewFilter[] = [
{
__typename: 'ViewFilter',
id: 'id',
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
value: 'testValue',
displayValue: 'Test Display Value',
operand: ViewFilterOperand.Is,
},
];
const toUpsertViewFilters: ViewFilter[] = [
{
__typename: 'ViewFilter',
id: 'id',
fieldMetadataId: '05731f68-6e7a-4903-8374-c0b6a9063482',
value: 'testValue',
displayValue: 'Test Display Value',
operand: ViewFilterOperand.Is,
},
];
const toDeleteViewFilterIds: string[] = ['id'];
expect(
getCombinedViewFilters(
viewFilters,
toUpsertViewFilters,
toDeleteViewFilterIds,
),
).toEqual([]);
});
});

View File

@ -1,33 +0,0 @@
import { ViewFilter } from '@/views/types/ViewFilter';
export const getCombinedViewFilters = (
viewFilters: ViewFilter[],
toUpsertViewFilters: ViewFilter[],
toDeleteViewFilterIds: string[],
): ViewFilter[] => {
const toCreateViewFilters = toUpsertViewFilters.filter(
(toUpsertViewFilter) =>
!viewFilters.some(
(viewFilter) => viewFilter.id === toUpsertViewFilter.id,
),
);
const toUpdateViewFilters = toUpsertViewFilters.filter((toUpsertViewFilter) =>
viewFilters.some((viewFilter) => viewFilter.id === toUpsertViewFilter.id),
);
const combinedViewFilters = viewFilters
.filter((viewFilter) => !toDeleteViewFilterIds.includes(viewFilter.id))
.map((viewFilter) => {
const toUpdateViewFilter = toUpdateViewFilters.find(
(toUpdateViewFilter) => toUpdateViewFilter.id === viewFilter.id,
);
return toUpdateViewFilter ?? viewFilter;
})
.concat(toCreateViewFilters);
return Object.values(
combinedViewFilters.reduce((acc, obj) => ({ ...acc, [obj.id]: obj }), {}),
);
};

View File

@ -1,34 +0,0 @@
import { ViewSort } from '@/views/types/ViewSort';
export const getCombinedViewSorts = (
viewSort: ViewSort[],
toUpsertViewSorts: ViewSort[],
toDeleteViewSortIds: string[],
): ViewSort[] => {
const toCreateViewSorts = toUpsertViewSorts.filter(
(toUpsertViewSort) =>
!viewSort.some((viewSort) => viewSort.id === toUpsertViewSort.id),
);
const toUpdateViewSorts = toUpsertViewSorts.filter((toUpsertViewSort) =>
viewSort.some((viewSort) => viewSort.id === toUpsertViewSort.id),
);
const combinedViewSorts = viewSort
.filter((viewSort) => !toDeleteViewSortIds.includes(viewSort.id))
.map((viewSort) => {
const toUpdateViewSort = toUpdateViewSorts.find(
(toUpdateViewSort) => toUpdateViewSort.id === viewSort.id,
);
return toUpdateViewSort ?? viewSort;
})
.concat(toCreateViewSorts);
return Object.values(
combinedViewSorts.reduce(
(acc, obj) => ({ ...acc, [obj.fieldMetadataId]: obj }),
{},
),
);
};