Fix advanced filters (#10665)
This PR partially fixes advanced filters that were not working even with feature flag activated. Bugs fixed here : - Advanced filters are not applied - Root advanced filters cannot be created - Cannot close advanced filters dropdown - Can create multiple times the same non-advanced filter (reserved for advanced filters) upsertRecordFilter and removeRecordFilter have been refactored to take record filter id instead of field metadata id, because the user should be allowed to apply multiple filters for the same field. We now base view filter CRUD directly on id, otherwise it could lead to inconsistencies between advanced filters and simple filters. This PR also refactors an important hook : computeRecordGqlOperationFilter, so that it takes an object instead of multiple params. There are still bugs left, they will be taken in other PRs.
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
|
||||
import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector';
|
||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||
import { getAdvancedFilterAddFilterRuleSelectDropdownId } from '@/object-record/advanced-filter/utils/getAdvancedFilterAddFilterRuleSelectDropdownId';
|
||||
import { useUpsertRecordFilterGroup } from '@/object-record/record-filter-group/hooks/useUpsertRecordFilterGroup';
|
||||
import { RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup';
|
||||
import { RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator';
|
||||
@ -27,7 +28,9 @@ export const AdvancedFilterAddFilterRuleSelect = ({
|
||||
recordFilterGroup,
|
||||
lastChildPosition = 0,
|
||||
}: AdvancedFilterAddFilterRuleSelectProps) => {
|
||||
const dropdownId = `advanced-filter-add-filter-rule-${recordFilterGroup.id}`;
|
||||
const dropdownId = getAdvancedFilterAddFilterRuleSelectDropdownId(
|
||||
recordFilterGroup.id,
|
||||
);
|
||||
|
||||
const { currentViewId } = useGetCurrentView();
|
||||
|
||||
|
||||
@ -8,7 +8,6 @@ import { currentRecordFiltersComponentState } from '@/object-record/record-filte
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
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 { isDefined } from 'twenty-shared';
|
||||
import { MenuItem } from 'twenty-ui';
|
||||
|
||||
@ -46,7 +45,7 @@ export const AdvancedFilterRuleOptionsDropdown = ({
|
||||
|
||||
const handleRemove = async () => {
|
||||
if (isDefined(viewFilterId)) {
|
||||
removeRecordFilter(viewFilterId);
|
||||
removeRecordFilter({ recordFilterId: viewFilterId });
|
||||
|
||||
const isOnlyViewFilterInGroup =
|
||||
childViewFiltersAndViewFilterGroups.length === 1;
|
||||
@ -66,7 +65,7 @@ export const AdvancedFilterRuleOptionsDropdown = ({
|
||||
);
|
||||
|
||||
for (const childViewFilter of childViewFilters) {
|
||||
removeRecordFilter(childViewFilter.id);
|
||||
removeRecordFilter({ recordFilterId: childViewFilter.id });
|
||||
}
|
||||
} else {
|
||||
throw new Error('No view filter or view filter group to remove');
|
||||
@ -86,7 +85,7 @@ export const AdvancedFilterRuleOptionsDropdown = ({
|
||||
<MenuItem text={removeButtonLabel} onClick={handleRemove} />
|
||||
</DropdownMenuItemsContainer>
|
||||
}
|
||||
dropdownHotkeyScope={{ scope: ADVANCED_FILTER_DROPDOWN_ID }}
|
||||
dropdownHotkeyScope={{ scope: dropdownId }}
|
||||
dropdownOffset={{ y: 8, x: 0 }}
|
||||
dropdownPlacement="bottom-start"
|
||||
/>
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
export const getAdvancedFilterAddFilterRuleSelectDropdownId = (
|
||||
recordFilterGroupId: string,
|
||||
) => {
|
||||
return `advanced-filter-add-filter-rule-${recordFilterGroupId}`;
|
||||
};
|
||||
@ -133,8 +133,8 @@ export const AdvancedFilterButton = () => {
|
||||
});
|
||||
}
|
||||
|
||||
openAdvancedFilterDropdown();
|
||||
closeObjectFilterDropdown();
|
||||
openAdvancedFilterDropdown();
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@ -9,12 +9,15 @@ import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-rec
|
||||
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
|
||||
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||
import { objectFilterDropdownSubMenuFieldTypeComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSubMenuFieldTypeComponentState';
|
||||
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||
import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState';
|
||||
import { getCompositeSubFieldLabel } from '@/object-record/object-filter-dropdown/utils/getCompositeSubFieldLabel';
|
||||
import { getFilterableFieldTypeLabel } from '@/object-record/object-filter-dropdown/utils/getFilterableFieldTypeLabel';
|
||||
import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue';
|
||||
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { findDuplicateRecordFilterInNonAdvancedRecordFilters } from '@/object-record/record-filter/utils/findDuplicateRecordFilterInNonAdvancedRecordFilters';
|
||||
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
|
||||
import { SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsCompositeFieldTypeConfigs';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
||||
@ -81,55 +84,84 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => {
|
||||
advancedFilterViewFilterId,
|
||||
);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const setSelectedFilter = useSetRecoilComponentStateV2(
|
||||
selectedFilterComponentState,
|
||||
);
|
||||
|
||||
const handleSelectFilter = (
|
||||
fieldMetadataItem: FieldMetadataItem | null | undefined,
|
||||
subFieldName?: string | null | undefined,
|
||||
) => {
|
||||
if (isDefined(fieldMetadataItem)) {
|
||||
if (
|
||||
isDefined(advancedFilterViewFilterId) &&
|
||||
isDefined(advancedFilterViewFilterGroupId)
|
||||
) {
|
||||
closeAdvancedFilterDropdown();
|
||||
if (!isDefined(fieldMetadataItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const type = getFilterTypeFromFieldType(fieldMetadataItem.type);
|
||||
const type = getFilterTypeFromFieldType(fieldMetadataItem.type);
|
||||
|
||||
const operand = getRecordFilterOperands({
|
||||
filterType: type,
|
||||
subFieldName: subFieldName,
|
||||
})[0];
|
||||
const defaultOperand = getRecordFilterOperands({
|
||||
filterType: type,
|
||||
subFieldName: subFieldName,
|
||||
})[0];
|
||||
|
||||
const { value, displayValue } = getInitialFilterValue(type, operand);
|
||||
if (
|
||||
isDefined(advancedFilterViewFilterId) &&
|
||||
isDefined(advancedFilterViewFilterGroupId)
|
||||
) {
|
||||
closeAdvancedFilterDropdown();
|
||||
|
||||
applyRecordFilter({
|
||||
id: advancedFilterViewFilterId,
|
||||
fieldMetadataId: fieldMetadataItem.id,
|
||||
value,
|
||||
operand,
|
||||
displayValue,
|
||||
type: getFilterTypeFromFieldType(fieldMetadataItem.type),
|
||||
label: fieldMetadataItem.label,
|
||||
recordFilterGroupId: advancedFilterViewFilterGroupId,
|
||||
subFieldName: subFieldName,
|
||||
});
|
||||
}
|
||||
|
||||
setFieldMetadataItemIdUsedInDropdown(fieldMetadataItem.id);
|
||||
|
||||
const type = getFilterTypeFromFieldType(fieldMetadataItem.type);
|
||||
|
||||
setSelectedOperandInDropdown(
|
||||
getRecordFilterOperands({
|
||||
filterType: type,
|
||||
subFieldName: subFieldName,
|
||||
})[0],
|
||||
const { value, displayValue } = getInitialFilterValue(
|
||||
type,
|
||||
defaultOperand,
|
||||
);
|
||||
|
||||
setSubFieldNameUsedInDropdown(subFieldName);
|
||||
applyRecordFilter({
|
||||
id: advancedFilterViewFilterId,
|
||||
fieldMetadataId: fieldMetadataItem.id,
|
||||
value,
|
||||
operand: defaultOperand,
|
||||
displayValue,
|
||||
type,
|
||||
label: fieldMetadataItem.label,
|
||||
recordFilterGroupId: advancedFilterViewFilterGroupId,
|
||||
subFieldName: subFieldName,
|
||||
});
|
||||
}
|
||||
|
||||
setObjectFilterDropdownSearchInput('');
|
||||
setFieldMetadataItemIdUsedInDropdown(fieldMetadataItem.id);
|
||||
|
||||
setObjectFilterDropdownFilterIsSelected(true);
|
||||
setSubFieldNameUsedInDropdown(subFieldName);
|
||||
|
||||
setObjectFilterDropdownSearchInput('');
|
||||
|
||||
setObjectFilterDropdownFilterIsSelected(true);
|
||||
|
||||
const duplicateFilterInCurrentRecordFilters =
|
||||
findDuplicateRecordFilterInNonAdvancedRecordFilters({
|
||||
recordFilters: currentRecordFilters,
|
||||
fieldMetadataItemId: fieldMetadataItem.id,
|
||||
subFieldName,
|
||||
});
|
||||
|
||||
const filterIsAlreadyInCurrentRecordFilters = isDefined(
|
||||
duplicateFilterInCurrentRecordFilters,
|
||||
);
|
||||
|
||||
const isSimpleFilter = !isDefined(advancedFilterViewFilterId);
|
||||
|
||||
if (isSimpleFilter && filterIsAlreadyInCurrentRecordFilters) {
|
||||
setSelectedFilter({
|
||||
...duplicateFilterInCurrentRecordFilters,
|
||||
});
|
||||
|
||||
setSelectedOperandInDropdown(
|
||||
duplicateFilterInCurrentRecordFilters.operand,
|
||||
);
|
||||
} else {
|
||||
setSelectedOperandInDropdown(defaultOperand);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -10,7 +10,10 @@ import { selectedOperandInDropdownComponentState } from '@/object-record/object-
|
||||
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
||||
import { isCompositeField } from '@/object-record/object-filter-dropdown/utils/isCompositeField';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { findDuplicateRecordFilterInNonAdvancedRecordFilters } from '@/object-record/record-filter/utils/findDuplicateRecordFilterInNonAdvancedRecordFilters';
|
||||
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
|
||||
import { RecordPickerHotkeyScope } from '@/object-record/record-picker/types/RecordPickerHotkeyScope';
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
@ -19,6 +22,7 @@ import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { MenuItemSelect, useIcons } from 'twenty-ui';
|
||||
|
||||
export type ObjectFilterDropdownFilterSelectMenuItemProps = {
|
||||
@ -67,6 +71,14 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
||||
advancedFilterViewFilterId,
|
||||
);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const setSelectedFilter = useSetRecoilComponentStateV2(
|
||||
selectedFilterComponentState,
|
||||
);
|
||||
|
||||
const handleSelectFilter = (fieldMetadataItem: FieldMetadataItem) => {
|
||||
closeAdvancedFilterDropdown();
|
||||
|
||||
@ -78,13 +90,35 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
||||
setHotkeyScope(RecordPickerHotkeyScope.RecordPicker);
|
||||
}
|
||||
|
||||
setSelectedOperandInDropdown(
|
||||
getRecordFilterOperands({
|
||||
filterType,
|
||||
})[0],
|
||||
);
|
||||
const defaultOperand = getRecordFilterOperands({
|
||||
filterType,
|
||||
})[0];
|
||||
|
||||
setObjectFilterDropdownFilterIsSelected(true);
|
||||
|
||||
const duplicateFilterInCurrentRecordFilters =
|
||||
findDuplicateRecordFilterInNonAdvancedRecordFilters({
|
||||
recordFilters: currentRecordFilters,
|
||||
fieldMetadataItemId: fieldMetadataItem.id,
|
||||
});
|
||||
|
||||
const filterIsAlreadyInCurrentRecordFilters = isDefined(
|
||||
duplicateFilterInCurrentRecordFilters,
|
||||
);
|
||||
|
||||
const isSimpleFilter = !isDefined(advancedFilterViewFilterId);
|
||||
|
||||
if (isSimpleFilter && filterIsAlreadyInCurrentRecordFilters) {
|
||||
setSelectedFilter({
|
||||
...duplicateFilterInCurrentRecordFilters,
|
||||
});
|
||||
|
||||
setSelectedOperandInDropdown(
|
||||
duplicateFilterInCurrentRecordFilters.operand,
|
||||
);
|
||||
} else {
|
||||
setSelectedOperandInDropdown(defaultOperand);
|
||||
}
|
||||
};
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
@ -54,7 +54,9 @@ describe('useRemoveRecordFilter', () => {
|
||||
expect(result.current.currentRecordFilters[0]).toEqual(mockRecordFilter);
|
||||
|
||||
act(() => {
|
||||
result.current.removeRecordFilter(mockRecordFilter.fieldMetadataId);
|
||||
result.current.removeRecordFilter({
|
||||
recordFilterId: mockRecordFilter.id,
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.currentRecordFilters).toHaveLength(0);
|
||||
@ -96,7 +98,9 @@ describe('useRemoveRecordFilter', () => {
|
||||
expect(result.current.currentRecordFilters).toHaveLength(1);
|
||||
|
||||
act(() => {
|
||||
result.current.removeRecordFilter('non-existent-field-metadata-id');
|
||||
result.current.removeRecordFilter({
|
||||
recordFilterId: 'non-existent-field-metadata-id',
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.currentRecordFilters).toHaveLength(1);
|
||||
|
||||
@ -14,7 +14,7 @@ const Wrapper = getJestMetadataAndApolloMocksWrapper({
|
||||
});
|
||||
|
||||
describe('useUpsertRecordFilter', () => {
|
||||
it('should add a new filter when fieldMetadataId does not exist', () => {
|
||||
it('should add a new filter when record filter id does not exist', () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
@ -48,7 +48,7 @@ describe('useUpsertRecordFilter', () => {
|
||||
expect(result.current.currentRecordFilters[0]).toEqual(mockNewRecordFilter);
|
||||
});
|
||||
|
||||
it('should update an existing filter when fieldMetadataId exists', () => {
|
||||
it('should update an existing filter when record filter id exists', () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
|
||||
@ -10,7 +10,7 @@ export const useRemoveRecordFilter = () => {
|
||||
|
||||
const removeRecordFilter = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(fieldMetadataId: string) => {
|
||||
({ recordFilterId }: { recordFilterId: string }) => {
|
||||
const currentRecordFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
currentRecordFiltersCallbackState,
|
||||
@ -18,8 +18,7 @@ export const useRemoveRecordFilter = () => {
|
||||
|
||||
const foundRecordFilterInCurrentRecordFilters =
|
||||
currentRecordFilters.some(
|
||||
(existingFilter) =>
|
||||
existingFilter.fieldMetadataId === fieldMetadataId,
|
||||
(existingFilter) => existingFilter.id === recordFilterId,
|
||||
);
|
||||
|
||||
if (foundRecordFilterInCurrentRecordFilters) {
|
||||
@ -27,8 +26,7 @@ export const useRemoveRecordFilter = () => {
|
||||
const newCurrentRecordFilters = [...currentRecordFilters];
|
||||
|
||||
const indexOfFilterToRemove = newCurrentRecordFilters.findIndex(
|
||||
(existingFilter) =>
|
||||
existingFilter.fieldMetadataId === fieldMetadataId,
|
||||
(existingFilter) => existingFilter.id === recordFilterId,
|
||||
);
|
||||
|
||||
newCurrentRecordFilters.splice(indexOfFilterToRemove, 1);
|
||||
|
||||
@ -19,9 +19,7 @@ export const useUpsertRecordFilter = () => {
|
||||
|
||||
const foundRecordFilterInCurrentRecordFilters =
|
||||
currentRecordFilters.some(
|
||||
(existingFilter) =>
|
||||
existingFilter.fieldMetadataId ===
|
||||
recordFilterToSet.fieldMetadataId,
|
||||
(existingFilter) => existingFilter.id === recordFilterToSet.id,
|
||||
);
|
||||
|
||||
if (!foundRecordFilterInCurrentRecordFilters) {
|
||||
@ -34,9 +32,7 @@ export const useUpsertRecordFilter = () => {
|
||||
const newCurrentRecordFilters = [...currentRecordFilters];
|
||||
|
||||
const indexOfFilterToUpdate = newCurrentRecordFilters.findIndex(
|
||||
(existingFilter) =>
|
||||
existingFilter.fieldMetadataId ===
|
||||
recordFilterToSet.fieldMetadataId,
|
||||
(existingFilter) => existingFilter.id === recordFilterToSet.id,
|
||||
);
|
||||
|
||||
newCurrentRecordFilters[indexOfFilterToUpdate] = {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
|
||||
import { RecordFilterValueDependencies } from '@/object-record/record-filter/types/RecordFilterValueDependencies';
|
||||
import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import { FieldMetadataType } from '~/generated/graphql';
|
||||
import { getCompaniesMock } from '~/testing/mock-data/companies';
|
||||
@ -40,12 +40,12 @@ describe('computeViewRecordGqlOperationFilter', () => {
|
||||
label: 'Name',
|
||||
};
|
||||
|
||||
const result = computeViewRecordGqlOperationFilter(
|
||||
mockFilterValueDependencies,
|
||||
[nameFilter],
|
||||
companyMockObjectMetadataItem.fields,
|
||||
[],
|
||||
);
|
||||
const result = computeRecordGqlOperationFilter({
|
||||
filterValueDependencies: mockFilterValueDependencies,
|
||||
recordFilters: [nameFilter],
|
||||
recordFilterGroups: [],
|
||||
fields: companyMockObjectMetadataItem.fields,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
name: {
|
||||
@ -85,12 +85,12 @@ describe('computeViewRecordGqlOperationFilter', () => {
|
||||
label: 'Employees',
|
||||
};
|
||||
|
||||
const result = computeViewRecordGqlOperationFilter(
|
||||
mockFilterValueDependencies,
|
||||
[nameFilter, employeesFilter],
|
||||
companyMockObjectMetadataItem.fields,
|
||||
[],
|
||||
);
|
||||
const result = computeRecordGqlOperationFilter({
|
||||
filterValueDependencies: mockFilterValueDependencies,
|
||||
recordFilters: [nameFilter, employeesFilter],
|
||||
recordFilterGroups: [],
|
||||
fields: companyMockObjectMetadataItem.fields,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
and: [
|
||||
@ -156,17 +156,17 @@ describe('should work as expected for the different field types', () => {
|
||||
type: FieldMetadataType.ADDRESS,
|
||||
};
|
||||
|
||||
const result = computeViewRecordGqlOperationFilter(
|
||||
mockFilterValueDependencies,
|
||||
[
|
||||
const result = computeRecordGqlOperationFilter({
|
||||
filterValueDependencies: mockFilterValueDependencies,
|
||||
recordFilters: [
|
||||
addressFilterContains,
|
||||
addressFilterDoesNotContain,
|
||||
addressFilterIsEmpty,
|
||||
addressFilterIsNotEmpty,
|
||||
],
|
||||
companyMockObjectMetadataItem.fields,
|
||||
[],
|
||||
);
|
||||
recordFilterGroups: [],
|
||||
fields: companyMockObjectMetadataItem.fields,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
and: [
|
||||
@ -523,17 +523,17 @@ describe('should work as expected for the different field types', () => {
|
||||
type: FieldMetadataType.PHONES,
|
||||
};
|
||||
|
||||
const result = computeViewRecordGqlOperationFilter(
|
||||
mockFilterValueDependencies,
|
||||
[
|
||||
const result = computeRecordGqlOperationFilter({
|
||||
filterValueDependencies: mockFilterValueDependencies,
|
||||
recordFilters: [
|
||||
phonesFilterContains,
|
||||
phonesFilterDoesNotContain,
|
||||
phonesFilterIsEmpty,
|
||||
phonesFilterIsNotEmpty,
|
||||
],
|
||||
personMockObjectMetadataItem.fields,
|
||||
[],
|
||||
);
|
||||
recordFilterGroups: [],
|
||||
fields: personMockObjectMetadataItem.fields,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
and: [
|
||||
@ -657,17 +657,17 @@ describe('should work as expected for the different field types', () => {
|
||||
type: FieldMetadataType.EMAILS,
|
||||
};
|
||||
|
||||
const result = computeViewRecordGqlOperationFilter(
|
||||
mockFilterValueDependencies,
|
||||
[
|
||||
const result = computeRecordGqlOperationFilter({
|
||||
filterValueDependencies: mockFilterValueDependencies,
|
||||
recordFilters: [
|
||||
emailsFilterContains,
|
||||
emailsFilterDoesNotContain,
|
||||
emailsFilterIsEmpty,
|
||||
emailsFilterIsNotEmpty,
|
||||
],
|
||||
personMockObjectMetadataItem.fields,
|
||||
[],
|
||||
);
|
||||
recordFilterGroups: [],
|
||||
fields: personMockObjectMetadataItem.fields,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
and: [
|
||||
@ -793,18 +793,18 @@ describe('should work as expected for the different field types', () => {
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
};
|
||||
|
||||
const result = computeViewRecordGqlOperationFilter(
|
||||
mockFilterValueDependencies,
|
||||
[
|
||||
const result = computeRecordGqlOperationFilter({
|
||||
filterValueDependencies: mockFilterValueDependencies,
|
||||
recordFilters: [
|
||||
dateFilterIsAfter,
|
||||
dateFilterIsBefore,
|
||||
dateFilterIs,
|
||||
dateFilterIsEmpty,
|
||||
dateFilterIsNotEmpty,
|
||||
],
|
||||
companyMockObjectMetadataItem.fields,
|
||||
[],
|
||||
);
|
||||
recordFilterGroups: [],
|
||||
fields: companyMockObjectMetadataItem.fields,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
and: [
|
||||
@ -894,17 +894,17 @@ describe('should work as expected for the different field types', () => {
|
||||
type: FieldMetadataType.NUMBER,
|
||||
};
|
||||
|
||||
const result = computeViewRecordGqlOperationFilter(
|
||||
mockFilterValueDependencies,
|
||||
[
|
||||
const result = computeRecordGqlOperationFilter({
|
||||
filterValueDependencies: mockFilterValueDependencies,
|
||||
recordFilters: [
|
||||
employeesFilterIsGreaterThan,
|
||||
employeesFilterIsLessThan,
|
||||
employeesFilterIsEmpty,
|
||||
employeesFilterIsNotEmpty,
|
||||
],
|
||||
companyMockObjectMetadataItem.fields,
|
||||
[],
|
||||
);
|
||||
recordFilterGroups: [],
|
||||
fields: companyMockObjectMetadataItem.fields,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
and: [
|
||||
|
||||
@ -32,8 +32,7 @@ import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
|
||||
import { RecordFilterValueDependencies } from '@/object-record/record-filter/types/RecordFilterValueDependencies';
|
||||
import { getEmptyRecordGqlOperationFilter } from '@/object-record/record-filter/utils/getEmptyRecordGqlOperationFilter';
|
||||
import { ViewFilterGroup } from '@/views/types/ViewFilterGroup';
|
||||
import { ViewFilterGroupLogicalOperator } from '@/views/types/ViewFilterGroupLogicalOperator';
|
||||
|
||||
import { resolveDateViewFilterValue } from '@/views/view-filter-value/utils/resolveDateViewFilterValue';
|
||||
import { resolveSelectViewFilterValue } from '@/views/view-filter-value/utils/resolveSelectViewFilterValue';
|
||||
import { jsonRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/jsonRelationFilterValueSchema';
|
||||
@ -41,6 +40,8 @@ import { simpleRelationFilterValueSchema } from '@/views/view-filter-value/valid
|
||||
import { endOfDay, roundToNearestMinutes, startOfDay } from 'date-fns';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup';
|
||||
import { RecordFilterGroupLogicalOperator } from '@/object-record/record-filter-group/types/RecordFilterGroupLogicalOperator';
|
||||
import { FilterableFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
|
||||
|
||||
type ComputeFilterRecordGqlOperationFilterParams = {
|
||||
@ -808,54 +809,55 @@ export const computeFilterRecordGqlOperationFilter = ({
|
||||
}
|
||||
};
|
||||
|
||||
const computeViewFilterGroupRecordGqlOperationFilter = (
|
||||
const computeRecordFilterGroupRecordGqlOperationFilter = (
|
||||
filterValueDependencies: RecordFilterValueDependencies,
|
||||
filters: RecordFilter[],
|
||||
fields: Pick<Field, 'id' | 'name' | 'type'>[],
|
||||
viewFilterGroups: ViewFilterGroup[],
|
||||
currentViewFilterGroupId?: string,
|
||||
recordFilterGroups: RecordFilterGroup[],
|
||||
currentRecordFilterGroupId?: string,
|
||||
): RecordGqlOperationFilter | undefined => {
|
||||
const currentViewFilterGroup = viewFilterGroups.find(
|
||||
(viewFilterGroup) => viewFilterGroup.id === currentViewFilterGroupId,
|
||||
const currentRecordFilterGroup = recordFilterGroups.find(
|
||||
(recordFilterGroup) => recordFilterGroup.id === currentRecordFilterGroupId,
|
||||
);
|
||||
|
||||
if (!currentViewFilterGroup) {
|
||||
if (!currentRecordFilterGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
const groupFilters = filters.filter(
|
||||
(filter) => filter.recordFilterGroupId === currentViewFilterGroupId,
|
||||
const recordFiltersInGroup = filters.filter(
|
||||
(filter) => filter.recordFilterGroupId === currentRecordFilterGroupId,
|
||||
);
|
||||
|
||||
const groupRecordGqlOperationFilters = groupFilters
|
||||
.map((filter) =>
|
||||
const groupRecordGqlOperationFilters = recordFiltersInGroup
|
||||
.map((recordFilter) =>
|
||||
computeFilterRecordGqlOperationFilter({
|
||||
filterValueDependencies,
|
||||
filter,
|
||||
filter: recordFilter,
|
||||
fieldMetadataItems: fields,
|
||||
}),
|
||||
)
|
||||
.filter(isDefined);
|
||||
|
||||
const subGroupRecordGqlOperationFilters = viewFilterGroups
|
||||
const subGroupRecordGqlOperationFilters = recordFilterGroups
|
||||
.filter(
|
||||
(viewFilterGroup) =>
|
||||
viewFilterGroup.parentViewFilterGroupId === currentViewFilterGroupId,
|
||||
(recordFilterGroup) =>
|
||||
recordFilterGroup.parentRecordFilterGroupId ===
|
||||
currentRecordFilterGroupId,
|
||||
)
|
||||
.map((subViewFilterGroup) =>
|
||||
computeViewFilterGroupRecordGqlOperationFilter(
|
||||
computeRecordFilterGroupRecordGqlOperationFilter(
|
||||
filterValueDependencies,
|
||||
filters,
|
||||
fields,
|
||||
viewFilterGroups,
|
||||
recordFilterGroups,
|
||||
subViewFilterGroup.id,
|
||||
),
|
||||
)
|
||||
.filter(isDefined);
|
||||
|
||||
if (
|
||||
currentViewFilterGroup.logicalOperator ===
|
||||
ViewFilterGroupLogicalOperator.AND
|
||||
currentRecordFilterGroup.logicalOperator ===
|
||||
RecordFilterGroupLogicalOperator.AND
|
||||
) {
|
||||
return {
|
||||
and: [
|
||||
@ -864,7 +866,8 @@ const computeViewFilterGroupRecordGqlOperationFilter = (
|
||||
],
|
||||
};
|
||||
} else if (
|
||||
currentViewFilterGroup.logicalOperator === ViewFilterGroupLogicalOperator.OR
|
||||
currentRecordFilterGroup.logicalOperator ===
|
||||
RecordFilterGroupLogicalOperator.OR
|
||||
) {
|
||||
return {
|
||||
or: [
|
||||
@ -874,38 +877,44 @@ const computeViewFilterGroupRecordGqlOperationFilter = (
|
||||
};
|
||||
} else {
|
||||
throw new Error(
|
||||
`Unknown logical operator ${currentViewFilterGroup.logicalOperator}`,
|
||||
`Unknown logical operator ${currentRecordFilterGroup.logicalOperator}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const computeViewRecordGqlOperationFilter = (
|
||||
filterValueDependencies: RecordFilterValueDependencies,
|
||||
filters: RecordFilter[],
|
||||
fields: Pick<Field, 'id' | 'name' | 'type'>[],
|
||||
viewFilterGroups: ViewFilterGroup[],
|
||||
): RecordGqlOperationFilter => {
|
||||
const regularRecordGqlOperationFilter: RecordGqlOperationFilter[] = filters
|
||||
.filter((filter) => !filter.recordFilterGroupId)
|
||||
.map((regularFilter) =>
|
||||
computeFilterRecordGqlOperationFilter({
|
||||
filterValueDependencies,
|
||||
filter: regularFilter,
|
||||
fieldMetadataItems: fields,
|
||||
}),
|
||||
)
|
||||
.filter(isDefined);
|
||||
export const computeRecordGqlOperationFilter = ({
|
||||
fields,
|
||||
filterValueDependencies,
|
||||
recordFilters,
|
||||
recordFilterGroups,
|
||||
}: {
|
||||
filterValueDependencies: RecordFilterValueDependencies;
|
||||
recordFilters: RecordFilter[];
|
||||
fields: Pick<Field, 'id' | 'name' | 'type'>[];
|
||||
recordFilterGroups: RecordFilterGroup[];
|
||||
}): RecordGqlOperationFilter => {
|
||||
const regularRecordGqlOperationFilter: RecordGqlOperationFilter[] =
|
||||
recordFilters
|
||||
.filter((filter) => !isDefined(filter.recordFilterGroupId))
|
||||
.map((regularFilter) =>
|
||||
computeFilterRecordGqlOperationFilter({
|
||||
filterValueDependencies,
|
||||
filter: regularFilter,
|
||||
fieldMetadataItems: fields,
|
||||
}),
|
||||
)
|
||||
.filter(isDefined);
|
||||
|
||||
const outermostFilterGroupId = viewFilterGroups.find(
|
||||
(viewFilterGroup) => !viewFilterGroup.parentViewFilterGroupId,
|
||||
const outermostFilterGroupId = recordFilterGroups.find(
|
||||
(recordFilterGroup) => !recordFilterGroup.parentRecordFilterGroupId,
|
||||
)?.id;
|
||||
|
||||
const advancedRecordGqlOperationFilter =
|
||||
computeViewFilterGroupRecordGqlOperationFilter(
|
||||
computeRecordFilterGroupRecordGqlOperationFilter(
|
||||
filterValueDependencies,
|
||||
filters,
|
||||
recordFilters,
|
||||
fields,
|
||||
viewFilterGroups,
|
||||
recordFilterGroups,
|
||||
outermostFilterGroupId,
|
||||
);
|
||||
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||
import { compareStrictlyExceptForNullAndUndefined } from '~/utils/compareStrictlyExceptForNullAndUndefined';
|
||||
|
||||
export const findDuplicateRecordFilterInNonAdvancedRecordFilters = ({
|
||||
recordFilters,
|
||||
fieldMetadataItemId,
|
||||
subFieldName,
|
||||
}: {
|
||||
recordFilters: RecordFilter[];
|
||||
fieldMetadataItemId: string;
|
||||
subFieldName?: string | null | undefined;
|
||||
}): RecordFilter | undefined => {
|
||||
const duplicateFilterInCurrentRecordFilters = recordFilters.find(
|
||||
(recordFilter) =>
|
||||
compareStrictlyExceptForNullAndUndefined(
|
||||
recordFilter.fieldMetadataId,
|
||||
fieldMetadataItemId,
|
||||
) &&
|
||||
compareStrictlyExceptForNullAndUndefined(
|
||||
recordFilter.subFieldName,
|
||||
subFieldName,
|
||||
),
|
||||
);
|
||||
|
||||
return duplicateFilterInCurrentRecordFilters;
|
||||
};
|
||||
@ -34,7 +34,6 @@ export const RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect =
|
||||
|
||||
const findManyRecordsParams = useFindManyRecordIndexTableParams(
|
||||
objectMetadataItem?.nameSingular ?? '',
|
||||
objectMetadataItem?.namePlural ?? '',
|
||||
);
|
||||
|
||||
const contextStoreFilters = useRecoilComponentValueV2(
|
||||
|
||||
@ -83,7 +83,6 @@ export const useExportFetchRecords = ({
|
||||
|
||||
const findManyRecordsParams = useFindManyRecordIndexTableParams(
|
||||
objectMetadataItem.nameSingular,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const finalColumns = [
|
||||
|
||||
@ -1,17 +1,16 @@
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy';
|
||||
import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState';
|
||||
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { useCurrentRecordGroupDefinition } from '@/object-record/record-group/hooks/useCurrentRecordGroupDefinition';
|
||||
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 { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const useFindManyRecordIndexTableParams = (
|
||||
objectNameSingular: string,
|
||||
recordTableId?: string,
|
||||
) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
@ -23,9 +22,8 @@ export const useFindManyRecordIndexTableParams = (
|
||||
|
||||
const currentRecordGroupDefinition = useCurrentRecordGroupDefinition();
|
||||
|
||||
const tableViewFilterGroups = useRecoilComponentValueV2(
|
||||
tableViewFilterGroupsComponentState,
|
||||
recordTableId,
|
||||
const currentRecordFilterGroups = useRecoilComponentValueV2(
|
||||
currentRecordFilterGroupsComponentState,
|
||||
);
|
||||
|
||||
const currentRecordSorts = useRecoilComponentValueV2(
|
||||
@ -38,12 +36,12 @@ export const useFindManyRecordIndexTableParams = (
|
||||
|
||||
const { filterValueDependencies } = useFilterValueDependencies();
|
||||
|
||||
const stateFilter = computeViewRecordGqlOperationFilter(
|
||||
const stateFilter = computeRecordGqlOperationFilter({
|
||||
fields: objectMetadataItem?.fields ?? [],
|
||||
filterValueDependencies,
|
||||
currentRecordFilters,
|
||||
objectMetadataItem?.fields ?? [],
|
||||
tableViewFilterGroups,
|
||||
);
|
||||
recordFilterGroups: currentRecordFilterGroups,
|
||||
recordFilters: currentRecordFilters,
|
||||
});
|
||||
|
||||
const orderBy = turnSortsIntoOrderBy(objectMetadataItem, currentRecordSorts);
|
||||
|
||||
|
||||
@ -7,13 +7,14 @@ import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils
|
||||
import { useSetRecordIdsForColumn } from '@/object-record/record-board/hooks/useSetRecordIdsForColumn';
|
||||
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 { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
|
||||
import { useRecordBoardRecordGqlFields } from '@/object-record/record-index/hooks/useRecordBoardRecordGqlFields';
|
||||
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { mapViewFilterGroupsToRecordFilterGroups } from '@/views/utils/mapViewFilterGroupsToRecordFilterGroups';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
type UseLoadRecordIndexBoardProps = {
|
||||
@ -43,6 +44,10 @@ export const useLoadRecordIndexBoardColumn = ({
|
||||
recordIndexViewFilterGroupsState,
|
||||
);
|
||||
|
||||
const recordFilterGroups = mapViewFilterGroupsToRecordFilterGroups(
|
||||
recordIndexViewFilterGroups,
|
||||
);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
@ -53,12 +58,12 @@ export const useLoadRecordIndexBoardColumn = ({
|
||||
|
||||
const { filterValueDependencies } = useFilterValueDependencies();
|
||||
|
||||
const requestFilters = computeViewRecordGqlOperationFilter(
|
||||
const requestFilters = computeRecordGqlOperationFilter({
|
||||
filterValueDependencies,
|
||||
currentRecordFilters,
|
||||
objectMetadataItem?.fields ?? [],
|
||||
recordIndexViewFilterGroups,
|
||||
);
|
||||
recordFilters: currentRecordFilters,
|
||||
recordFilterGroups,
|
||||
fields: objectMetadataItem.fields,
|
||||
});
|
||||
|
||||
const orderBy = turnSortsIntoOrderBy(objectMetadataItem, currentRecordSorts);
|
||||
|
||||
|
||||
@ -18,7 +18,6 @@ import { useSetTableColumns } from '@/object-record/record-table/hooks/useSetTab
|
||||
import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState';
|
||||
import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState';
|
||||
import { tableSortsComponentState } from '@/object-record/record-table/states/tableSortsComponentState';
|
||||
import { tableViewFilterGroupsComponentState } from '@/object-record/record-table/states/tableViewFilterGroupsComponentState';
|
||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||
import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation';
|
||||
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
|
||||
@ -205,12 +204,7 @@ export const useLoadRecordIndexStates = () => {
|
||||
|
||||
onViewFieldsChange(view.viewFields, objectMetadataItem, recordIndexId);
|
||||
onViewGroupsChange(view.viewGroups, objectMetadataItem, recordIndexId);
|
||||
set(
|
||||
tableViewFilterGroupsComponentState.atomFamily({
|
||||
instanceId: recordIndexId,
|
||||
}),
|
||||
view.viewFilterGroups ?? [],
|
||||
);
|
||||
|
||||
set(
|
||||
tableFiltersComponentState.atomFamily({
|
||||
instanceId: recordIndexId,
|
||||
|
||||
@ -36,7 +36,7 @@ export const RecordTableEmptyStateSoftDelete = () => {
|
||||
throw new Error('Deleted filter not found');
|
||||
}
|
||||
|
||||
removeRecordFilter(deletedFilter.fieldMetadataId);
|
||||
removeRecordFilter({ recordFilterId: deletedFilter.id });
|
||||
|
||||
toggleSoftDeleteFilterState(false);
|
||||
};
|
||||
|
||||
@ -3,11 +3,12 @@ import { useAggregateRecords } from '@/object-record/hooks/useAggregateRecords';
|
||||
import { buildRecordGqlFieldsAggregateForView } from '@/object-record/record-board/record-board-column/utils/buildRecordGqlFieldsAggregateForView';
|
||||
import { computeAggregateValueAndLabel } from '@/object-record/record-board/record-board-column/utils/computeAggregateValueAndLabel';
|
||||
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
|
||||
import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
|
||||
import { recordIndexKanbanAggregateOperationState } from '@/object-record/record-index/states/recordIndexKanbanAggregateOperationState';
|
||||
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
|
||||
import { UserContext } from '@/users/contexts/UserContext';
|
||||
import { mapViewFilterGroupsToRecordFilterGroups } from '@/views/utils/mapViewFilterGroupsToRecordFilterGroups';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
@ -26,6 +27,10 @@ export const useAggregateRecordsForHeader = ({
|
||||
recordIndexViewFilterGroupsState,
|
||||
);
|
||||
|
||||
const recordFilterGroups = mapViewFilterGroupsToRecordFilterGroups(
|
||||
recordIndexViewFilterGroups,
|
||||
);
|
||||
|
||||
const recordIndexFilters = useRecoilValue(recordIndexFiltersState);
|
||||
|
||||
const recordIndexKanbanAggregateOperation = useRecoilValue(
|
||||
@ -36,12 +41,12 @@ export const useAggregateRecordsForHeader = ({
|
||||
|
||||
const { dateFormat, timeFormat, timeZone } = useContext(UserContext);
|
||||
|
||||
const requestFilters = computeViewRecordGqlOperationFilter(
|
||||
const requestFilters = computeRecordGqlOperationFilter({
|
||||
filterValueDependencies,
|
||||
recordIndexFilters,
|
||||
objectMetadataItem.fields,
|
||||
recordIndexViewFilterGroups,
|
||||
);
|
||||
recordFilters: recordIndexFilters,
|
||||
recordFilterGroups,
|
||||
fields: objectMetadataItem.fields,
|
||||
});
|
||||
|
||||
const recordGqlFieldsAggregate = buildRecordGqlFieldsAggregateForView({
|
||||
objectMetadataItem,
|
||||
|
||||
@ -2,7 +2,7 @@ import { useAggregateRecords } from '@/object-record/hooks/useAggregateRecords';
|
||||
import { computeAggregateValueAndLabel } from '@/object-record/record-board/record-board-column/utils/computeAggregateValueAndLabel';
|
||||
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 { computeRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
|
||||
import { useRecordGroupFilter } from '@/object-record/record-group/hooks/useRecordGroupFilter';
|
||||
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
|
||||
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
|
||||
@ -13,6 +13,7 @@ import { ExtendedAggregateOperations } from '@/object-record/record-table/types/
|
||||
import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { UserContext } from '@/users/contexts/UserContext';
|
||||
import { mapViewFilterGroupsToRecordFilterGroups } from '@/views/utils/mapViewFilterGroupsToRecordFilterGroups';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined, isFieldMetadataDateKind } from 'twenty-shared';
|
||||
@ -33,13 +34,17 @@ export const useAggregateRecordsForRecordTableColumnFooter = (
|
||||
|
||||
const { filterValueDependencies } = useFilterValueDependencies();
|
||||
|
||||
const requestFilters = computeViewRecordGqlOperationFilter(
|
||||
filterValueDependencies,
|
||||
currentRecordFilters,
|
||||
objectMetadataItem.fields,
|
||||
const recordFilterGroups = mapViewFilterGroupsToRecordFilterGroups(
|
||||
recordIndexViewFilterGroups,
|
||||
);
|
||||
|
||||
const requestFilters = computeRecordGqlOperationFilter({
|
||||
fields: objectMetadataItem.fields,
|
||||
filterValueDependencies,
|
||||
recordFilterGroups,
|
||||
recordFilters: currentRecordFilters,
|
||||
});
|
||||
|
||||
const { viewFieldId } = useContext(
|
||||
RecordTableColumnAggregateFooterCellContext,
|
||||
);
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewFilterGroup } from '@/views/types/ViewFilterGroup';
|
||||
|
||||
export const tableViewFilterGroupsComponentState = createComponentStateV2<
|
||||
ViewFilterGroup[]
|
||||
>({
|
||||
key: 'tableViewFilterGroupsComponentState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: RecordTableComponentInstanceContext,
|
||||
});
|
||||
Reference in New Issue
Block a user