Record filters - Introduced fieldMetadataItemUsedInDropdown instead of filterDefinitionUsedInDropdown (#10044)
This PR progressively introduces fieldMetadataItemUsedInDropdown instead of filterDefinitionUsedInDropdown where most easy to replace. This allows to use `fieldMetadataItemUsedInDropdown.id` instead of `filterDefinition.fieldMetadataId`, which is one easy dependency to remove on filter definition. We still derive filterDefinition instead of fully replacing it, because it will be easier to remove RecordFilterDefinition usage in a bottom-up approach instead. In multiple components of the filter dropdown, we try to replace filterDefinition by fieldMetadataItem derivation : Icon, label, id, type, etc. We also introduce the usage of subFieldNameUsedInDropdown instead of storing it dynamically on filterDefinition, for handling filtering on composite sub fields. The method `formatFieldMetadataItemAsFilterDefinition()` that is used to derive filterDefinition from fieldMetadataItem is what was being used originally to create the availableFilterDefinition state. (That is already removed) Fixed associated unit tests accordingly.
This commit is contained in:
@ -54,10 +54,8 @@ describe('useColumnDefinitionsFromFieldMetadata', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(Array.isArray(result.current.columnDefinitions)).toBe(true);
|
expect(Array.isArray(result.current.columnDefinitions)).toBe(true);
|
||||||
expect(Array.isArray(result.current.filterDefinitions)).toBe(true);
|
|
||||||
expect(Array.isArray(result.current.sortDefinitions)).toBe(true);
|
expect(Array.isArray(result.current.sortDefinitions)).toBe(true);
|
||||||
expect(result.current.columnDefinitions.length).toBe(0);
|
expect(result.current.columnDefinitions.length).toBe(0);
|
||||||
expect(result.current.filterDefinitions.length).toBe(0);
|
|
||||||
expect(result.current.sortDefinitions.length).toBe(0);
|
expect(result.current.sortDefinitions.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -76,11 +74,9 @@ describe('useColumnDefinitionsFromFieldMetadata', () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const { columnDefinitions, filterDefinitions, sortDefinitions } =
|
const { columnDefinitions, sortDefinitions } = result.current;
|
||||||
result.current;
|
|
||||||
|
|
||||||
expect(columnDefinitions.length).toBe(21);
|
expect(columnDefinitions.length).toBe(21);
|
||||||
expect(filterDefinitions.length).toBe(17);
|
|
||||||
expect(sortDefinitions.length).toBe(14);
|
expect(sortDefinitions.length).toBe(14);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
RelationDefinitionType,
|
RelationDefinitionType,
|
||||||
} from '~/generated-metadata/graphql';
|
} from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
|
import { FilterableFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
|
||||||
import { ObjectMetadataItem } from '../types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '../types/ObjectMetadataItem';
|
||||||
|
|
||||||
export const formatFieldMetadataItemsAsFilterDefinitions = ({
|
export const formatFieldMetadataItemsAsFilterDefinitions = ({
|
||||||
@ -79,7 +80,9 @@ export const getRelationObjectMetadataNamePlural = ({
|
|||||||
return field.relationDefinition?.targetObjectMetadata.namePlural;
|
return field.relationDefinition?.targetObjectMetadata.namePlural;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getFilterTypeFromFieldType = (fieldType: FieldMetadataType) => {
|
export const getFilterTypeFromFieldType = (
|
||||||
|
fieldType: FieldMetadataType,
|
||||||
|
): FilterableFieldType => {
|
||||||
switch (fieldType) {
|
switch (fieldType) {
|
||||||
case FieldMetadataType.DATE_TIME:
|
case FieldMetadataType.DATE_TIME:
|
||||||
return 'DATE_TIME';
|
return 'DATE_TIME';
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
|
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
|
||||||
import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector';
|
import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector';
|
||||||
import { formatFieldMetadataItemAsFilterDefinition } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
import {
|
||||||
|
formatFieldMetadataItemAsFilterDefinition,
|
||||||
|
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 { getRecordFilterOperandsForRecordFilterDefinition } from '@/object-record/record-filter/utils/getRecordFilterOperandsForRecordFilterDefinition';
|
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';
|
||||||
@ -86,12 +89,17 @@ export const AdvancedFilterAddFilterRuleSelect = ({
|
|||||||
field: defaultFieldMetadataItem,
|
field: defaultFieldMetadataItem,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const filterType = getFilterTypeFromFieldType(
|
||||||
|
defaultFieldMetadataItem.type,
|
||||||
|
);
|
||||||
|
|
||||||
upsertCombinedViewFilter({
|
upsertCombinedViewFilter({
|
||||||
id: v4(),
|
id: v4(),
|
||||||
fieldMetadataId: defaultFieldMetadataItem.id,
|
fieldMetadataId: defaultFieldMetadataItem.id,
|
||||||
operand: getRecordFilterOperandsForRecordFilterDefinition(
|
type: filterType,
|
||||||
defaultFilterDefinition,
|
operand: getRecordFilterOperands({
|
||||||
)[0],
|
filterType,
|
||||||
|
})[0],
|
||||||
definition: defaultFilterDefinition,
|
definition: defaultFilterDefinition,
|
||||||
value: '',
|
value: '',
|
||||||
displayValue: '',
|
displayValue: '',
|
||||||
@ -123,12 +131,17 @@ export const AdvancedFilterAddFilterRuleSelect = ({
|
|||||||
field: defaultFieldMetadataItem,
|
field: defaultFieldMetadataItem,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const filterType = getFilterTypeFromFieldType(
|
||||||
|
defaultFieldMetadataItem.type,
|
||||||
|
);
|
||||||
|
|
||||||
upsertCombinedViewFilter({
|
upsertCombinedViewFilter({
|
||||||
id: v4(),
|
id: v4(),
|
||||||
fieldMetadataId: defaultFieldMetadataItem.id,
|
fieldMetadataId: defaultFieldMetadataItem.id,
|
||||||
operand: getRecordFilterOperandsForRecordFilterDefinition(
|
type: filterType,
|
||||||
defaultFilterDefinition,
|
operand: getRecordFilterOperands({
|
||||||
)[0],
|
filterType,
|
||||||
|
})[0],
|
||||||
definition: defaultFilterDefinition,
|
definition: defaultFilterDefinition,
|
||||||
value: '',
|
value: '',
|
||||||
displayValue: '',
|
displayValue: '',
|
||||||
|
|||||||
@ -25,9 +25,9 @@ export const AdvancedFilterViewFilterFieldSelect = ({
|
|||||||
}: AdvancedFilterViewFilterFieldSelectProps) => {
|
}: AdvancedFilterViewFilterFieldSelectProps) => {
|
||||||
const { advancedFilterDropdownId } = useAdvancedFilterDropdown(viewFilterId);
|
const { advancedFilterDropdownId } = useAdvancedFilterDropdown(viewFilterId);
|
||||||
|
|
||||||
const filter = useCurrentViewFilter({ viewFilterId });
|
const recordFilter = useCurrentViewFilter({ viewFilterId });
|
||||||
|
|
||||||
const selectedFieldLabel = filter?.definition.label ?? '';
|
const selectedFieldLabel = recordFilter?.label ?? '';
|
||||||
|
|
||||||
const setAdvancedFilterViewFilterId = useSetRecoilComponentStateV2(
|
const setAdvancedFilterViewFilterId = useSetRecoilComponentStateV2(
|
||||||
advancedFilterViewFilterIdComponentState,
|
advancedFilterViewFilterIdComponentState,
|
||||||
@ -58,8 +58,8 @@ export const AdvancedFilterViewFilterFieldSelect = ({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
onOpen={() => {
|
onOpen={() => {
|
||||||
setAdvancedFilterViewFilterId(filter?.id);
|
setAdvancedFilterViewFilterId(recordFilter?.id);
|
||||||
setAdvancedFilterViewFilterGroupId(filter?.viewFilterGroupId);
|
setAdvancedFilterViewFilterGroupId(recordFilter?.viewFilterGroupId);
|
||||||
}}
|
}}
|
||||||
dropdownComponents={
|
dropdownComponents={
|
||||||
shouldShowCompositeSelectionSubMenu ? (
|
shouldShowCompositeSelectionSubMenu ? (
|
||||||
|
|||||||
@ -3,7 +3,8 @@ import styled from '@emotion/styled';
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
import { formatFieldMetadataItemAsFilterDefinition } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
|
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||||
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';
|
||||||
@ -39,8 +40,8 @@ export const ObjectFilterDropdownBooleanSelect = () => {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const options = [true, false];
|
const options = [true, false];
|
||||||
|
|
||||||
const filterDefinitionUsedInDropdown = useRecoilComponentValueV2(
|
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||||
filterDefinitionUsedInDropdownComponentState,
|
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedOperandInDropdown = useRecoilComponentValueV2(
|
const selectedOperandInDropdown = useRecoilComponentValueV2(
|
||||||
@ -65,18 +66,22 @@ export const ObjectFilterDropdownBooleanSelect = () => {
|
|||||||
|
|
||||||
const handleOptionSelect = (value: boolean) => {
|
const handleOptionSelect = (value: boolean) => {
|
||||||
if (
|
if (
|
||||||
!isDefined(filterDefinitionUsedInDropdown) ||
|
!isDefined(fieldMetadataItemUsedInDropdown) ||
|
||||||
!isDefined(selectedOperandInDropdown)
|
!isDefined(selectedOperandInDropdown)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemUsedInDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
applyRecordFilter({
|
applyRecordFilter({
|
||||||
id: selectedFilter?.id ?? v4(),
|
id: selectedFilter?.id ?? v4(),
|
||||||
definition: filterDefinitionUsedInDropdown,
|
definition: filterDefinition,
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: value ? 'True' : 'False',
|
displayValue: value ? 'True' : 'False',
|
||||||
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
|
fieldMetadataId: fieldMetadataItemUsedInDropdown.id,
|
||||||
value: value.toString(),
|
value: value.toString(),
|
||||||
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
import { formatFieldMetadataItemAsFilterDefinition } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
|
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||||
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 { getRelativeDateDisplayValue } from '@/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue';
|
import { getRelativeDateDisplayValue } from '@/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue';
|
||||||
@ -19,8 +20,8 @@ import { isDefined } from 'twenty-shared';
|
|||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
export const ObjectFilterDropdownDateInput = () => {
|
export const ObjectFilterDropdownDateInput = () => {
|
||||||
const filterDefinitionUsedInDropdown = useRecoilComponentValueV2(
|
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||||
filterDefinitionUsedInDropdownComponentState,
|
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedOperandInDropdown = useRecoilComponentValueV2(
|
const selectedOperandInDropdown = useRecoilComponentValueV2(
|
||||||
@ -41,16 +42,21 @@ export const ObjectFilterDropdownDateInput = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const isDateTimeInput =
|
const isDateTimeInput =
|
||||||
filterDefinitionUsedInDropdown?.type === FieldMetadataType.DATE_TIME;
|
fieldMetadataItemUsedInDropdown?.type === FieldMetadataType.DATE_TIME;
|
||||||
|
|
||||||
const handleAbsoluteDateChange = (newDate: Date | null) => {
|
const handleAbsoluteDateChange = (newDate: Date | null) => {
|
||||||
setInternalDate(newDate);
|
setInternalDate(newDate);
|
||||||
|
|
||||||
if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return;
|
if (!fieldMetadataItemUsedInDropdown || !selectedOperandInDropdown) return;
|
||||||
|
|
||||||
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemUsedInDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
applyRecordFilter({
|
applyRecordFilter({
|
||||||
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
||||||
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
|
definition: filterDefinition,
|
||||||
|
fieldMetadataId: fieldMetadataItemUsedInDropdown.id,
|
||||||
value: newDate?.toISOString() ?? '',
|
value: newDate?.toISOString() ?? '',
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: isDefined(newDate)
|
displayValue: isDefined(newDate)
|
||||||
@ -58,7 +64,6 @@ export const ObjectFilterDropdownDateInput = () => {
|
|||||||
? newDate.toLocaleString()
|
? newDate.toLocaleString()
|
||||||
: newDate.toLocaleDateString()
|
: newDate.toLocaleDateString()
|
||||||
: '',
|
: '',
|
||||||
definition: filterDefinitionUsedInDropdown,
|
|
||||||
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -70,7 +75,11 @@ export const ObjectFilterDropdownDateInput = () => {
|
|||||||
unit: VariableDateViewFilterValueUnit;
|
unit: VariableDateViewFilterValueUnit;
|
||||||
} | null,
|
} | null,
|
||||||
) => {
|
) => {
|
||||||
if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return;
|
if (!fieldMetadataItemUsedInDropdown || !selectedOperandInDropdown) return;
|
||||||
|
|
||||||
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemUsedInDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
const value = relativeDate
|
const value = relativeDate
|
||||||
? computeVariableDateViewFilterValue(
|
? computeVariableDateViewFilterValue(
|
||||||
@ -82,11 +91,11 @@ export const ObjectFilterDropdownDateInput = () => {
|
|||||||
|
|
||||||
applyRecordFilter({
|
applyRecordFilter({
|
||||||
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
||||||
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
|
fieldMetadataId: fieldMetadataItemUsedInDropdown.id,
|
||||||
value,
|
value,
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: getRelativeDateDisplayValue(relativeDate),
|
displayValue: getRelativeDateDisplayValue(relativeDate),
|
||||||
definition: filterDefinitionUsedInDropdown,
|
definition: filterDefinition,
|
||||||
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -151,9 +151,7 @@ export const ObjectFilterDropdownFilterSelect = ({
|
|||||||
filterDefinition: selectedFilterDefinition,
|
filterDefinition: selectedFilterDefinition,
|
||||||
});
|
});
|
||||||
|
|
||||||
setFieldMetadataItemIdUsedInDropdown(
|
setFieldMetadataItemIdUsedInDropdown(fieldMetadataItemId);
|
||||||
selectedFilterDefinition.fieldMetadataId,
|
|
||||||
);
|
|
||||||
|
|
||||||
closeAdvancedFilterDropdown();
|
closeAdvancedFilterDropdown();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
|
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||||
|
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown';
|
import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown';
|
||||||
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 { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
|
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
|
||||||
|
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||||
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
||||||
import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState';
|
import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState';
|
||||||
import { objectFilterDropdownFirstLevelFilterDefinitionComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFirstLevelFilterDefinitionComponentState';
|
import { objectFilterDropdownFirstLevelFilterDefinitionComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFirstLevelFilterDefinitionComponentState';
|
||||||
@ -9,12 +12,13 @@ import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/o
|
|||||||
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||||
import { objectFilterDropdownSubMenuFieldTypeComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSubMenuFieldTypeComponentState';
|
import { objectFilterDropdownSubMenuFieldTypeComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSubMenuFieldTypeComponentState';
|
||||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
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 { getCompositeSubFieldLabel } from '@/object-record/object-filter-dropdown/utils/getCompositeSubFieldLabel';
|
||||||
import { getFilterableFieldTypeLabel } from '@/object-record/object-filter-dropdown/utils/getFilterableFieldTypeLabel';
|
import { getFilterableFieldTypeLabel } from '@/object-record/object-filter-dropdown/utils/getFilterableFieldTypeLabel';
|
||||||
import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue';
|
import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue';
|
||||||
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||||
import { RecordFilterDefinition } from '@/object-record/record-filter/types/RecordFilterDefinition';
|
import { RecordFilterDefinition } from '@/object-record/record-filter/types/RecordFilterDefinition';
|
||||||
import { getRecordFilterOperandsForRecordFilterDefinition } from '@/object-record/record-filter/utils/getRecordFilterOperandsForRecordFilterDefinition';
|
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
|
||||||
import { SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsCompositeFieldTypeConfigs';
|
import { SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsCompositeFieldTypeConfigs';
|
||||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
@ -37,6 +41,14 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => {
|
|||||||
objectFilterDropdownFirstLevelFilterDefinitionComponentState,
|
objectFilterDropdownFirstLevelFilterDefinitionComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||||
|
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||||
|
);
|
||||||
|
|
||||||
|
const setSubFieldNameUsedInDropdown = useSetRecoilComponentStateV2(
|
||||||
|
subFieldNameUsedInDropdownComponentState,
|
||||||
|
);
|
||||||
|
|
||||||
const [, setObjectFilterDropdownFilterIsSelected] = useRecoilComponentStateV2(
|
const [, setObjectFilterDropdownFilterIsSelected] = useRecoilComponentStateV2(
|
||||||
objectFilterDropdownFilterIsSelectedComponentState,
|
objectFilterDropdownFilterIsSelectedComponentState,
|
||||||
);
|
);
|
||||||
@ -83,39 +95,60 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => {
|
|||||||
advancedFilterViewFilterId,
|
advancedFilterViewFilterId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSelectFilter = (definition: RecordFilterDefinition | null) => {
|
const handleSelectFilter = (
|
||||||
if (definition !== null) {
|
fieldMetadataItem: FieldMetadataItem | null | undefined,
|
||||||
|
subFieldName?: string | null | undefined,
|
||||||
|
) => {
|
||||||
|
if (isDefined(fieldMetadataItem)) {
|
||||||
|
const filterDefinition: RecordFilterDefinition = {
|
||||||
|
fieldMetadataId: fieldMetadataItem.id,
|
||||||
|
type: getFilterTypeFromFieldType(fieldMetadataItem.type),
|
||||||
|
label: fieldMetadataItem.label,
|
||||||
|
iconName: fieldMetadataItem.icon ?? '',
|
||||||
|
compositeFieldName: subFieldName ?? undefined,
|
||||||
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isDefined(advancedFilterViewFilterId) &&
|
isDefined(advancedFilterViewFilterId) &&
|
||||||
isDefined(advancedFilterViewFilterGroupId)
|
isDefined(advancedFilterViewFilterGroupId)
|
||||||
) {
|
) {
|
||||||
closeAdvancedFilterDropdown();
|
closeAdvancedFilterDropdown();
|
||||||
|
|
||||||
const operand =
|
const type = getFilterTypeFromFieldType(fieldMetadataItem.type);
|
||||||
getRecordFilterOperandsForRecordFilterDefinition(definition)[0];
|
|
||||||
const { value, displayValue } = getInitialFilterValue(
|
const operand = getRecordFilterOperands({
|
||||||
definition.type,
|
filterType: type,
|
||||||
operand,
|
subFieldName: subFieldName,
|
||||||
);
|
})[0];
|
||||||
|
|
||||||
|
const { value, displayValue } = getInitialFilterValue(type, operand);
|
||||||
|
|
||||||
applyRecordFilter({
|
applyRecordFilter({
|
||||||
id: advancedFilterViewFilterId,
|
id: advancedFilterViewFilterId,
|
||||||
fieldMetadataId: definition.fieldMetadataId,
|
fieldMetadataId: fieldMetadataItem.id,
|
||||||
value,
|
value,
|
||||||
operand,
|
operand,
|
||||||
displayValue,
|
displayValue,
|
||||||
definition,
|
definition: filterDefinition,
|
||||||
viewFilterGroupId: advancedFilterViewFilterGroupId,
|
viewFilterGroupId: advancedFilterViewFilterGroupId,
|
||||||
|
subFieldName: subFieldName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setFilterDefinitionUsedInDropdown(definition);
|
setFilterDefinitionUsedInDropdown(filterDefinition);
|
||||||
setFieldMetadataItemIdUsedInDropdown(definition.fieldMetadataId);
|
setFieldMetadataItemIdUsedInDropdown(fieldMetadataItem.id);
|
||||||
|
|
||||||
|
const type = getFilterTypeFromFieldType(fieldMetadataItem.type);
|
||||||
|
|
||||||
setSelectedOperandInDropdown(
|
setSelectedOperandInDropdown(
|
||||||
getRecordFilterOperandsForRecordFilterDefinition(definition)[0],
|
getRecordFilterOperands({
|
||||||
|
filterType: type,
|
||||||
|
subFieldName: subFieldName,
|
||||||
|
})[0],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
setSubFieldNameUsedInDropdown(subFieldName);
|
||||||
|
|
||||||
setObjectFilterDropdownSearchInput('');
|
setObjectFilterDropdownSearchInput('');
|
||||||
|
|
||||||
setObjectFilterDropdownFilterIsSelected(true);
|
setObjectFilterDropdownFilterIsSelected(true);
|
||||||
@ -167,36 +200,30 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => {
|
|||||||
key={`select-filter-${-1}`}
|
key={`select-filter-${-1}`}
|
||||||
testId={`select-filter-${-1}`}
|
testId={`select-filter-${-1}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleSelectFilter(objectFilterDropdownFirstLevelFilterDefinition);
|
handleSelectFilter(fieldMetadataItemUsedInDropdown);
|
||||||
}}
|
}}
|
||||||
LeftIcon={IconApps}
|
LeftIcon={IconApps}
|
||||||
text={`Any ${getFilterableFieldTypeLabel(objectFilterDropdownSubMenuFieldType)} field`}
|
text={`Any ${getFilterableFieldTypeLabel(objectFilterDropdownSubMenuFieldType)} field`}
|
||||||
/>
|
/>
|
||||||
{/* TODO: fix this with a backend field on ViewFilter for composite field filter */}
|
{/* TODO: fix this with a backend field on ViewFilter for composite field filter */}
|
||||||
{objectFilterDropdownFirstLevelFilterDefinition.type === 'ACTOR' &&
|
{fieldMetadataItemUsedInDropdown?.type === 'ACTOR' &&
|
||||||
options.map((subFieldName, index) => (
|
options.map((subFieldName, index) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={`select-filter-${index}`}
|
key={`select-filter-${index}`}
|
||||||
testId={`select-filter-${index}`}
|
testId={`select-filter-${index}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isDefined(objectFilterDropdownFirstLevelFilterDefinition)) {
|
if (isDefined(fieldMetadataItemUsedInDropdown)) {
|
||||||
handleSelectFilter({
|
handleSelectFilter(
|
||||||
...objectFilterDropdownFirstLevelFilterDefinition,
|
fieldMetadataItemUsedInDropdown,
|
||||||
label: getCompositeSubFieldLabel(
|
subFieldName,
|
||||||
objectFilterDropdownSubMenuFieldType,
|
);
|
||||||
subFieldName,
|
|
||||||
),
|
|
||||||
compositeFieldName: subFieldName,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
text={getCompositeSubFieldLabel(
|
text={getCompositeSubFieldLabel(
|
||||||
objectFilterDropdownSubMenuFieldType,
|
objectFilterDropdownSubMenuFieldType,
|
||||||
subFieldName,
|
subFieldName,
|
||||||
)}
|
)}
|
||||||
LeftIcon={getIcon(
|
LeftIcon={getIcon(fieldMetadataItemUsedInDropdown?.icon)}
|
||||||
objectFilterDropdownFirstLevelFilterDefinition?.iconName,
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</DropdownMenuItemsContainer>
|
</DropdownMenuItemsContainer>
|
||||||
|
|||||||
@ -7,14 +7,15 @@ import { objectFilterDropdownFirstLevelFilterDefinitionComponentState } from '@/
|
|||||||
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
|
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
|
||||||
import { objectFilterDropdownSubMenuFieldTypeComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSubMenuFieldTypeComponentState';
|
import { objectFilterDropdownSubMenuFieldTypeComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSubMenuFieldTypeComponentState';
|
||||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||||
import { CompositeFilterableFieldType } from '@/object-record/record-filter/types/CompositeFilterableFieldType';
|
|
||||||
|
|
||||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||||
import { formatFieldMetadataItemAsFilterDefinition } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
import {
|
||||||
|
formatFieldMetadataItemAsFilterDefinition,
|
||||||
|
getFilterTypeFromFieldType,
|
||||||
|
} from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
||||||
import { isCompositeField } from '@/object-record/object-filter-dropdown/utils/isCompositeField';
|
import { isCompositeField } from '@/object-record/object-filter-dropdown/utils/isCompositeField';
|
||||||
import { RecordFilterDefinition } from '@/object-record/record-filter/types/RecordFilterDefinition';
|
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
|
||||||
import { getRecordFilterOperandsForRecordFilterDefinition } from '@/object-record/record-filter/utils/getRecordFilterOperandsForRecordFilterDefinition';
|
|
||||||
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
|
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
|
||||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||||
@ -57,16 +58,10 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
|||||||
OBJECT_FILTER_DROPDOWN_ID,
|
OBJECT_FILTER_DROPDOWN_ID,
|
||||||
);
|
);
|
||||||
|
|
||||||
const filterDefinitionToSelect = formatFieldMetadataItemAsFilterDefinition({
|
|
||||||
field: fieldMetadataItemToSelect,
|
|
||||||
});
|
|
||||||
|
|
||||||
const isSelectedItem = useRecoilValue(
|
const isSelectedItem = useRecoilValue(
|
||||||
isSelectedItemIdSelector(fieldMetadataItemToSelect.id),
|
isSelectedItemIdSelector(fieldMetadataItemToSelect.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
const isACompositeField = isCompositeField(fieldMetadataItemToSelect.type);
|
|
||||||
|
|
||||||
const setSelectedOperandInDropdown = useSetRecoilComponentStateV2(
|
const setSelectedOperandInDropdown = useSetRecoilComponentStateV2(
|
||||||
selectedOperandInDropdownComponentState,
|
selectedOperandInDropdownComponentState,
|
||||||
);
|
);
|
||||||
@ -85,27 +80,28 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
|||||||
advancedFilterViewFilterId,
|
advancedFilterViewFilterId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSelectFilterDefinition = (
|
const handleSelectFilter = (fieldMetadataItem: FieldMetadataItem) => {
|
||||||
availableFilterDefinition: RecordFilterDefinition,
|
|
||||||
) => {
|
|
||||||
closeAdvancedFilterDropdown();
|
closeAdvancedFilterDropdown();
|
||||||
|
|
||||||
setFieldMetadataItemIdUsedInDropdown(
|
setFieldMetadataItemIdUsedInDropdown(fieldMetadataItem.id);
|
||||||
availableFilterDefinition.fieldMetadataId,
|
|
||||||
);
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
setFilterDefinitionUsedInDropdown(availableFilterDefinition);
|
field: fieldMetadataItem,
|
||||||
|
});
|
||||||
|
|
||||||
|
setFilterDefinitionUsedInDropdown(filterDefinition);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
availableFilterDefinition.type === 'RELATION' ||
|
filterDefinition.type === 'RELATION' ||
|
||||||
availableFilterDefinition.type === 'SELECT'
|
filterDefinition.type === 'SELECT'
|
||||||
) {
|
) {
|
||||||
setHotkeyScope(RelationPickerHotkeyScope.RelationPicker);
|
setHotkeyScope(RelationPickerHotkeyScope.RelationPicker);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedOperandInDropdown(
|
setSelectedOperandInDropdown(
|
||||||
getRecordFilterOperandsForRecordFilterDefinition(
|
getRecordFilterOperands({
|
||||||
availableFilterDefinition,
|
filterType: filterDefinition.type,
|
||||||
)[0],
|
})[0],
|
||||||
);
|
);
|
||||||
|
|
||||||
setObjectFilterDropdownFilterIsSelected(true);
|
setObjectFilterDropdownFilterIsSelected(true);
|
||||||
@ -113,20 +109,29 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
|||||||
|
|
||||||
const { getIcon } = useIcons();
|
const { getIcon } = useIcons();
|
||||||
|
|
||||||
|
const Icon = getIcon(fieldMetadataItemToSelect.icon);
|
||||||
|
|
||||||
|
const shouldShowSubMenu = isCompositeField(fieldMetadataItemToSelect.type);
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
resetSelectedItem();
|
resetSelectedItem();
|
||||||
|
|
||||||
if (isACompositeField) {
|
const filterType = getFilterTypeFromFieldType(
|
||||||
// TODO: create isCompositeFilterableFieldType type guard
|
fieldMetadataItemToSelect.type,
|
||||||
setObjectFilterDropdownSubMenuFieldType(
|
);
|
||||||
filterDefinitionToSelect.type as CompositeFilterableFieldType,
|
|
||||||
);
|
if (isCompositeField(filterType)) {
|
||||||
setObjectFilterDropdownFirstLevelFilterDefinition(
|
setObjectFilterDropdownSubMenuFieldType(filterType);
|
||||||
filterDefinitionToSelect,
|
|
||||||
);
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemToSelect,
|
||||||
|
});
|
||||||
|
|
||||||
|
setObjectFilterDropdownFirstLevelFilterDefinition(filterDefinition);
|
||||||
|
setFieldMetadataItemIdUsedInDropdown(fieldMetadataItemToSelect.id);
|
||||||
setObjectFilterDropdownIsSelectingCompositeField(true);
|
setObjectFilterDropdownIsSelectingCompositeField(true);
|
||||||
} else {
|
} else {
|
||||||
handleSelectFilterDefinition(filterDefinitionToSelect);
|
handleSelectFilter(fieldMetadataItemToSelect);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -135,9 +140,9 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
|||||||
selected={false}
|
selected={false}
|
||||||
hovered={isSelectedItem}
|
hovered={isSelectedItem}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
LeftIcon={getIcon(filterDefinitionToSelect.iconName)}
|
LeftIcon={Icon}
|
||||||
text={filterDefinitionToSelect.label}
|
text={fieldMetadataItemToSelect.label}
|
||||||
hasSubMenu={isACompositeField}
|
hasSubMenu={shouldShowSubMenu}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { ChangeEvent, useCallback, useState } from 'react';
|
import { ChangeEvent, useCallback, useState } from 'react';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
import { formatFieldMetadataItemAsFilterDefinition } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
|
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||||
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';
|
||||||
@ -13,8 +14,8 @@ export const ObjectFilterDropdownNumberInput = () => {
|
|||||||
selectedOperandInDropdownComponentState,
|
selectedOperandInDropdownComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const filterDefinitionUsedInDropdown = useRecoilComponentValueV2(
|
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||||
filterDefinitionUsedInDropdownComponentState,
|
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedFilter = useRecoilComponentValueV2(
|
const selectedFilter = useRecoilComponentValueV2(
|
||||||
@ -39,27 +40,32 @@ export const ObjectFilterDropdownNumberInput = () => {
|
|||||||
},
|
},
|
||||||
[hasFocused],
|
[hasFocused],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
fieldMetadataItemUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<DropdownMenuInput
|
<DropdownMenuInput
|
||||||
ref={handleInputRef}
|
ref={handleInputRef}
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
autoFocus
|
autoFocus
|
||||||
type="number"
|
type="number"
|
||||||
placeholder={filterDefinitionUsedInDropdown.label}
|
placeholder={fieldMetadataItemUsedInDropdown.label}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
const newValue = event.target.value;
|
const newValue = event.target.value;
|
||||||
|
|
||||||
setInputValue(newValue);
|
setInputValue(newValue);
|
||||||
|
|
||||||
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemUsedInDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
applyRecordFilter({
|
applyRecordFilter({
|
||||||
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
||||||
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
|
fieldMetadataId: fieldMetadataItemUsedInDropdown?.id ?? '',
|
||||||
value: newValue,
|
value: newValue,
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: newValue,
|
displayValue: newValue,
|
||||||
definition: filterDefinitionUsedInDropdown,
|
definition: filterDefinition,
|
||||||
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
import {
|
||||||
|
formatFieldMetadataItemAsFilterDefinition,
|
||||||
|
getFilterTypeFromFieldType,
|
||||||
|
} from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
|
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||||
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 { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState';
|
||||||
import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue';
|
import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue';
|
||||||
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||||
|
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
|
||||||
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 { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
@ -13,7 +19,6 @@ 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';
|
||||||
import { MenuItem } from 'twenty-ui';
|
import { MenuItem } from 'twenty-ui';
|
||||||
import { getRecordFilterOperandsForRecordFilterDefinition } from '../../record-filter/utils/getRecordFilterOperandsForRecordFilterDefinition';
|
|
||||||
import { getOperandLabel } from '../utils/getOperandLabel';
|
import { getOperandLabel } from '../utils/getOperandLabel';
|
||||||
|
|
||||||
const StyledDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
|
const StyledDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
|
||||||
@ -22,8 +27,8 @@ const StyledDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const ObjectFilterDropdownOperandSelect = () => {
|
export const ObjectFilterDropdownOperandSelect = () => {
|
||||||
const filterDefinitionUsedInDropdown = useRecoilComponentValueV2(
|
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||||
filterDefinitionUsedInDropdownComponentState,
|
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||||
);
|
);
|
||||||
|
|
||||||
const setSelectedOperandInDropdown = useSetRecoilComponentStateV2(
|
const setSelectedOperandInDropdown = useSetRecoilComponentStateV2(
|
||||||
@ -34,14 +39,21 @@ export const ObjectFilterDropdownOperandSelect = () => {
|
|||||||
selectedFilterComponentState,
|
selectedFilterComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const subFieldNameUsedInDropdown = useRecoilComponentValueV2(
|
||||||
|
subFieldNameUsedInDropdownComponentState,
|
||||||
|
);
|
||||||
|
|
||||||
const { applyRecordFilter } = useApplyRecordFilter();
|
const { applyRecordFilter } = useApplyRecordFilter();
|
||||||
|
|
||||||
const { closeDropdown } = useDropdown();
|
const { closeDropdown } = useDropdown();
|
||||||
|
|
||||||
const operandsForFilterType = isDefined(filterDefinitionUsedInDropdown)
|
const operandsForFilterType = isDefined(fieldMetadataItemUsedInDropdown)
|
||||||
? getRecordFilterOperandsForRecordFilterDefinition(
|
? getRecordFilterOperands({
|
||||||
filterDefinitionUsedInDropdown,
|
filterType: getFilterTypeFromFieldType(
|
||||||
)
|
fieldMetadataItemUsedInDropdown.type,
|
||||||
|
),
|
||||||
|
subFieldName: subFieldNameUsedInDropdown,
|
||||||
|
})
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const handleOperandChange = (newOperand: ViewFilterOperand) => {
|
const handleOperandChange = (newOperand: ViewFilterOperand) => {
|
||||||
@ -55,36 +67,48 @@ export const ObjectFilterDropdownOperandSelect = () => {
|
|||||||
|
|
||||||
setSelectedOperandInDropdown(newOperand);
|
setSelectedOperandInDropdown(newOperand);
|
||||||
|
|
||||||
if (isValuelessOperand && isDefined(filterDefinitionUsedInDropdown)) {
|
if (isValuelessOperand && isDefined(fieldMetadataItemUsedInDropdown)) {
|
||||||
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemUsedInDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
applyRecordFilter({
|
applyRecordFilter({
|
||||||
id: v4(),
|
id: v4(),
|
||||||
fieldMetadataId: filterDefinitionUsedInDropdown?.fieldMetadataId ?? '',
|
fieldMetadataId: fieldMetadataItemUsedInDropdown.id,
|
||||||
displayValue: '',
|
displayValue: '',
|
||||||
operand: newOperand,
|
operand: newOperand,
|
||||||
value: '',
|
value: '',
|
||||||
definition: filterDefinitionUsedInDropdown,
|
definition: filterDefinition,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isDefined(filterDefinitionUsedInDropdown) &&
|
isDefined(fieldMetadataItemUsedInDropdown) &&
|
||||||
isDefined(selectedFilter)
|
isDefined(selectedFilter)
|
||||||
) {
|
) {
|
||||||
|
const filterType = getFilterTypeFromFieldType(
|
||||||
|
fieldMetadataItemUsedInDropdown.type,
|
||||||
|
);
|
||||||
|
|
||||||
const { value, displayValue } = getInitialFilterValue(
|
const { value, displayValue } = getInitialFilterValue(
|
||||||
filterDefinitionUsedInDropdown.type,
|
filterType,
|
||||||
newOperand,
|
newOperand,
|
||||||
selectedFilter.value,
|
selectedFilter.value,
|
||||||
selectedFilter.displayValue,
|
selectedFilter.displayValue,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemUsedInDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
applyRecordFilter({
|
applyRecordFilter({
|
||||||
id: selectedFilter.id ? selectedFilter.id : v4(),
|
id: selectedFilter.id ? selectedFilter.id : v4(),
|
||||||
fieldMetadataId: selectedFilter.fieldMetadataId,
|
fieldMetadataId: selectedFilter.fieldMetadataId,
|
||||||
displayValue,
|
displayValue,
|
||||||
operand: newOperand,
|
operand: newOperand,
|
||||||
value,
|
value,
|
||||||
definition: filterDefinitionUsedInDropdown,
|
definition: filterDefinition,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,7 +13,8 @@ import { SelectableList } from '@/ui/layout/selectable-list/components/Selectabl
|
|||||||
import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates';
|
import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates';
|
||||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||||
|
|
||||||
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
import { formatFieldMetadataItemAsFilterDefinition } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
|
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||||
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||||
import { objectFilterDropdownSelectedOptionValuesComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState';
|
import { objectFilterDropdownSelectedOptionValuesComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState';
|
||||||
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
||||||
@ -32,8 +33,8 @@ type SelectOptionForFilter = FieldMetadataItemOption & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const ObjectFilterDropdownOptionSelect = () => {
|
export const ObjectFilterDropdownOptionSelect = () => {
|
||||||
const filterDefinitionUsedInDropdown = useRecoilComponentValueV2(
|
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||||
filterDefinitionUsedInDropdownComponentState,
|
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||||
);
|
);
|
||||||
|
|
||||||
const objectFilterDropdownSelectedOptionValues = useRecoilComponentValueV2(
|
const objectFilterDropdownSelectedOptionValues = useRecoilComponentValueV2(
|
||||||
@ -66,7 +67,7 @@ export const ObjectFilterDropdownOptionSelect = () => {
|
|||||||
|
|
||||||
const selectedItemId = useRecoilValue(selectedItemIdState);
|
const selectedItemId = useRecoilValue(selectedItemIdState);
|
||||||
|
|
||||||
const fieldMetaDataId = filterDefinitionUsedInDropdown?.fieldMetadataId ?? '';
|
const fieldMetaDataId = fieldMetadataItemUsedInDropdown?.id ?? '';
|
||||||
|
|
||||||
const { selectOptions } = useOptionsForSelect(fieldMetaDataId);
|
const { selectOptions } = useOptionsForSelect(fieldMetaDataId);
|
||||||
|
|
||||||
@ -125,7 +126,7 @@ export const ObjectFilterDropdownOptionSelect = () => {
|
|||||||
: selectedOptions.map((option) => option.label).join(', ');
|
: selectedOptions.map((option) => option.label).join(', ');
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isDefined(filterDefinitionUsedInDropdown) &&
|
isDefined(fieldMetadataItemUsedInDropdown) &&
|
||||||
isDefined(selectedOperandInDropdown)
|
isDefined(selectedOperandInDropdown)
|
||||||
) {
|
) {
|
||||||
const newFilterValue =
|
const newFilterValue =
|
||||||
@ -133,12 +134,16 @@ export const ObjectFilterDropdownOptionSelect = () => {
|
|||||||
? JSON.stringify(selectedOptions.map((option) => option.value))
|
? JSON.stringify(selectedOptions.map((option) => option.value))
|
||||||
: EMPTY_FILTER_VALUE;
|
: EMPTY_FILTER_VALUE;
|
||||||
|
|
||||||
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemUsedInDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
applyRecordFilter({
|
applyRecordFilter({
|
||||||
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
||||||
definition: filterDefinitionUsedInDropdown,
|
definition: filterDefinition,
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: filterDisplayValue,
|
displayValue: filterDisplayValue,
|
||||||
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
|
fieldMetadataId: fieldMetadataItemUsedInDropdown.id,
|
||||||
value: newFilterValue,
|
value: newFilterValue,
|
||||||
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
|
||||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||||
import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants/RatingValues';
|
import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants/RatingValues';
|
||||||
import { FieldRatingValue } from '@/object-record/record-field/types/FieldMetadata';
|
import { FieldRatingValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||||
@ -9,6 +8,8 @@ import { RatingInput } from '@/ui/field/input/components/RatingInput';
|
|||||||
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 { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
|
|
||||||
|
import { formatFieldMetadataItemAsFilterDefinition } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
|
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||||
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
||||||
const convertFieldRatingValueToNumber = (
|
const convertFieldRatingValueToNumber = (
|
||||||
rating: Exclude<FieldRatingValue, null>,
|
rating: Exclude<FieldRatingValue, null>,
|
||||||
@ -37,8 +38,8 @@ export const ObjectFilterDropdownRatingInput = () => {
|
|||||||
selectedOperandInDropdownComponentState,
|
selectedOperandInDropdownComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const filterDefinitionUsedInDropdown = useRecoilComponentValueV2(
|
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||||
filterDefinitionUsedInDropdownComponentState,
|
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedFilter = useRecoilComponentValueV2(
|
const selectedFilter = useRecoilComponentValueV2(
|
||||||
@ -48,7 +49,7 @@ export const ObjectFilterDropdownRatingInput = () => {
|
|||||||
const { applyRecordFilter } = useApplyRecordFilter();
|
const { applyRecordFilter } = useApplyRecordFilter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
fieldMetadataItemUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
<RatingInput
|
<RatingInput
|
||||||
@ -58,13 +59,17 @@ export const ObjectFilterDropdownRatingInput = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemUsedInDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
applyRecordFilter?.({
|
applyRecordFilter?.({
|
||||||
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
||||||
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
|
fieldMetadataId: fieldMetadataItemUsedInDropdown.id,
|
||||||
value: convertFieldRatingValueToNumber(newValue),
|
value: convertFieldRatingValueToNumber(newValue),
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: convertFieldRatingValueToNumber(newValue),
|
displayValue: convertFieldRatingValueToNumber(newValue),
|
||||||
definition: filterDefinitionUsedInDropdown,
|
definition: filterDefinition,
|
||||||
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import { v4 } from 'uuid';
|
|
||||||
|
|
||||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
import { getRelationObjectMetadataNameSingular } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
import {
|
||||||
|
formatFieldMetadataItemAsFilterDefinition,
|
||||||
|
getRelationObjectMetadataNameSingular,
|
||||||
|
} from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
import { ObjectFilterDropdownRecordPinnedItems } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordPinnedItems';
|
import { ObjectFilterDropdownRecordPinnedItems } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordPinnedItems';
|
||||||
import { CURRENT_WORKSPACE_MEMBER_SELECTABLE_ITEM_ID } from '@/object-record/object-filter-dropdown/constants/CurrentWorkspaceMemberSelectableItemId';
|
import { CURRENT_WORKSPACE_MEMBER_SELECTABLE_ITEM_ID } from '@/object-record/object-filter-dropdown/constants/CurrentWorkspaceMemberSelectableItemId';
|
||||||
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||||
@ -24,6 +24,7 @@ import { jsonRelationFilterValueSchema } from '@/views/view-filter-value/validat
|
|||||||
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';
|
||||||
import { IconUserCircle } from 'twenty-ui';
|
import { IconUserCircle } from 'twenty-ui';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
export const EMPTY_FILTER_VALUE: string = JSON.stringify({
|
export const EMPTY_FILTER_VALUE: string = JSON.stringify({
|
||||||
isCurrentWorkspaceMemberSelected: false,
|
isCurrentWorkspaceMemberSelected: false,
|
||||||
@ -68,8 +69,6 @@ export const ObjectFilterDropdownRecordSelect = ({
|
|||||||
const { currentViewWithCombinedFiltersAndSorts } =
|
const { currentViewWithCombinedFiltersAndSorts } =
|
||||||
useGetCurrentView(viewComponentId);
|
useGetCurrentView(viewComponentId);
|
||||||
|
|
||||||
const [fieldId] = useState(v4());
|
|
||||||
|
|
||||||
const { isCurrentWorkspaceMemberSelected } = jsonRelationFilterValueSchema
|
const { isCurrentWorkspaceMemberSelected } = jsonRelationFilterValueSchema
|
||||||
.catch({
|
.catch({
|
||||||
isCurrentWorkspaceMemberSelected: false,
|
isCurrentWorkspaceMemberSelected: false,
|
||||||
@ -200,17 +199,21 @@ export const ObjectFilterDropdownRecordSelect = ({
|
|||||||
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
||||||
(viewFilter) =>
|
(viewFilter) =>
|
||||||
viewFilter.fieldMetadataId ===
|
viewFilter.fieldMetadataId ===
|
||||||
filterDefinitionUsedInDropdown.fieldMetadataId,
|
fieldMetadataItemUsedInFilterDropdown.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
const filterId = viewFilter?.id ?? fieldId;
|
const filterId = viewFilter?.id ?? v4();
|
||||||
|
|
||||||
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemUsedInFilterDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
applyRecordFilter({
|
applyRecordFilter({
|
||||||
id: selectedFilter?.id ? selectedFilter.id : filterId,
|
id: selectedFilter?.id ? selectedFilter.id : filterId,
|
||||||
definition: filterDefinitionUsedInDropdown,
|
definition: filterDefinition,
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: filterDisplayValue,
|
displayValue: filterDisplayValue,
|
||||||
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
|
fieldMetadataId: fieldMetadataItemUsedInFilterDropdown.id,
|
||||||
value: newFilterValue,
|
value: newFilterValue,
|
||||||
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ChangeEvent, useCallback, useState } from 'react';
|
import { ChangeEvent, useCallback, useState } from 'react';
|
||||||
|
|
||||||
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||||
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||||
@ -8,8 +8,8 @@ import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/
|
|||||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||||
|
|
||||||
export const ObjectFilterDropdownSearchInput = () => {
|
export const ObjectFilterDropdownSearchInput = () => {
|
||||||
const filterDefinitionUsedInDropdown = useRecoilComponentValueV2(
|
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||||
filterDefinitionUsedInDropdownComponentState,
|
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedOperandInDropdown = useRecoilComponentValueV2(
|
const selectedOperandInDropdown = useRecoilComponentValueV2(
|
||||||
@ -37,14 +37,14 @@ export const ObjectFilterDropdownSearchInput = () => {
|
|||||||
[hasFocused],
|
[hasFocused],
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
fieldMetadataItemUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<DropdownMenuSearchInput
|
<DropdownMenuSearchInput
|
||||||
ref={handleInputRef}
|
ref={handleInputRef}
|
||||||
autoFocus
|
autoFocus
|
||||||
type="text"
|
type="text"
|
||||||
value={objectFilterDropdownSearchInput}
|
value={objectFilterDropdownSearchInput}
|
||||||
placeholder={filterDefinitionUsedInDropdown.label}
|
placeholder={fieldMetadataItemUsedInDropdown.label}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
setObjectFilterDropdownSearchInput(event.target.value);
|
setObjectFilterDropdownSearchInput(event.target.value);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
|
import { formatFieldMetadataItemAsFilterDefinition } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
import { useEmptyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useEmptyRecordFilter';
|
import { useEmptyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useEmptyRecordFilter';
|
||||||
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||||
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||||
import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState';
|
import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState';
|
||||||
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
||||||
@ -50,8 +51,8 @@ export const ObjectFilterDropdownSourceSelect = ({
|
|||||||
selectedOperandInDropdownComponentState,
|
selectedOperandInDropdownComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const filterDefinitionUsedInDropdown = useRecoilComponentValueV2(
|
const fieldMetadataItemUsedInFilterDropdown = useRecoilComponentValueV2(
|
||||||
filterDefinitionUsedInDropdownComponentState,
|
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { applyRecordFilter } = useApplyRecordFilter(viewComponentId);
|
const { applyRecordFilter } = useApplyRecordFilter(viewComponentId);
|
||||||
@ -87,13 +88,15 @@ export const ObjectFilterDropdownSourceSelect = ({
|
|||||||
(id) => id !== itemToSelect.id,
|
(id) => id !== itemToSelect.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!filterDefinitionUsedInDropdown) {
|
if (!isDefined(fieldMetadataItemUsedInFilterDropdown)) {
|
||||||
throw new Error('Filter definition used in dropdown should be defined');
|
throw new Error(
|
||||||
|
'Field metadata item used in filter dropdown should be defined',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newSelectedItemIds.length === 0) {
|
if (newSelectedItemIds.length === 0) {
|
||||||
emptyRecordFilter();
|
emptyRecordFilter();
|
||||||
removeRecordFilter(filterDefinitionUsedInDropdown.fieldMetadataId);
|
removeRecordFilter(fieldMetadataItemUsedInFilterDropdown.id);
|
||||||
deleteCombinedViewFilter(fieldId);
|
deleteCombinedViewFilter(fieldId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -110,7 +113,7 @@ export const ObjectFilterDropdownSourceSelect = ({
|
|||||||
: selectedItemNames.join(', ');
|
: selectedItemNames.join(', ');
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isDefined(filterDefinitionUsedInDropdown) &&
|
isDefined(fieldMetadataItemUsedInFilterDropdown) &&
|
||||||
isDefined(selectedOperandInDropdown)
|
isDefined(selectedOperandInDropdown)
|
||||||
) {
|
) {
|
||||||
const newFilterValue =
|
const newFilterValue =
|
||||||
@ -122,17 +125,21 @@ export const ObjectFilterDropdownSourceSelect = ({
|
|||||||
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
||||||
(viewFilter) =>
|
(viewFilter) =>
|
||||||
viewFilter.fieldMetadataId ===
|
viewFilter.fieldMetadataId ===
|
||||||
filterDefinitionUsedInDropdown.fieldMetadataId,
|
fieldMetadataItemUsedInFilterDropdown.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
const filterId = viewFilter?.id ?? fieldId;
|
const filterId = viewFilter?.id ?? fieldId;
|
||||||
|
|
||||||
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemUsedInFilterDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
applyRecordFilter({
|
applyRecordFilter({
|
||||||
id: selectedFilter?.id ? selectedFilter.id : filterId,
|
id: selectedFilter?.id ? selectedFilter.id : filterId,
|
||||||
definition: filterDefinitionUsedInDropdown,
|
definition: filterDefinition,
|
||||||
operand: selectedOperandInDropdown || ViewFilterOperand.Is,
|
operand: selectedOperandInDropdown || ViewFilterOperand.Is,
|
||||||
displayValue: filterDisplayValue,
|
displayValue: filterDisplayValue,
|
||||||
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
|
fieldMetadataId: fieldMetadataItemUsedInFilterDropdown.id,
|
||||||
value: newFilterValue,
|
value: newFilterValue,
|
||||||
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { ChangeEvent, useCallback, useState } from 'react';
|
import { ChangeEvent, useCallback, useState } from 'react';
|
||||||
import { v4 } from 'uuid';
|
|
||||||
|
|
||||||
import { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
import { formatFieldMetadataItemAsFilterDefinition } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
|
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||||
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||||
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';
|
||||||
@ -9,13 +9,13 @@ import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApp
|
|||||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||||
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 { v4 } from 'uuid';
|
||||||
|
|
||||||
export const ObjectFilterDropdownTextSearchInput = () => {
|
export const ObjectFilterDropdownTextSearchInput = () => {
|
||||||
const [filterId] = useState(v4());
|
|
||||||
const [hasFocused, setHasFocused] = useState(false);
|
const [hasFocused, setHasFocused] = useState(false);
|
||||||
|
|
||||||
const filterDefinitionUsedInDropdown = useRecoilComponentValueV2(
|
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||||
filterDefinitionUsedInDropdownComponentState,
|
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedOperandInDropdown = useRecoilComponentValueV2(
|
const selectedOperandInDropdown = useRecoilComponentValueV2(
|
||||||
@ -47,24 +47,28 @@ export const ObjectFilterDropdownTextSearchInput = () => {
|
|||||||
[hasFocused],
|
[hasFocused],
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
fieldMetadataItemUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<DropdownMenuSearchInput
|
<DropdownMenuSearchInput
|
||||||
ref={handleInputRef}
|
ref={handleInputRef}
|
||||||
autoFocus
|
autoFocus
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={filterDefinitionUsedInDropdown.label}
|
placeholder={fieldMetadataItemUsedInDropdown.label}
|
||||||
value={selectedFilter?.value ?? objectFilterDropdownSearchInput}
|
value={selectedFilter?.value ?? objectFilterDropdownSearchInput}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
setObjectFilterDropdownSearchInput(event.target.value);
|
setObjectFilterDropdownSearchInput(event.target.value);
|
||||||
|
|
||||||
|
const filterDefinition = formatFieldMetadataItemAsFilterDefinition({
|
||||||
|
field: fieldMetadataItemUsedInDropdown,
|
||||||
|
});
|
||||||
|
|
||||||
applyRecordFilter({
|
applyRecordFilter({
|
||||||
id: selectedFilter?.id ?? filterId,
|
id: selectedFilter?.id ?? v4(),
|
||||||
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
|
fieldMetadataId: fieldMetadataItemUsedInDropdown.id,
|
||||||
value: event.target.value,
|
value: event.target.value,
|
||||||
operand: selectedOperandInDropdown,
|
operand: selectedOperandInDropdown,
|
||||||
displayValue: event.target.value,
|
displayValue: event.target.value,
|
||||||
definition: filterDefinitionUsedInDropdown,
|
definition: filterDefinition,
|
||||||
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
viewFilterGroupId: selectedFilter?.viewFilterGroupId,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/ob
|
|||||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||||
|
|
||||||
export const subFieldNameUsedInDropdownComponentState = createComponentStateV2<
|
export const subFieldNameUsedInDropdownComponentState = createComponentStateV2<
|
||||||
string | null
|
string | null | undefined
|
||||||
>({
|
>({
|
||||||
key: 'subFieldNameUsedInDropdownComponentState',
|
key: 'subFieldNameUsedInDropdownComponentState',
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
import { FieldActorValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||||
|
|
||||||
|
export const isFilterOnActorSourceSubField = (
|
||||||
|
subFieldName?: string | null | undefined,
|
||||||
|
) => {
|
||||||
|
return subFieldName === ('source' satisfies keyof FieldActorValue);
|
||||||
|
};
|
||||||
@ -47,6 +47,8 @@ describe('useRemoveRecordFilter', () => {
|
|||||||
label: 'Test Field',
|
label: 'Test Field',
|
||||||
iconName: 'IconText',
|
iconName: 'IconText',
|
||||||
},
|
},
|
||||||
|
label: 'Test Field',
|
||||||
|
type: 'TEXT',
|
||||||
};
|
};
|
||||||
|
|
||||||
// First add a filter
|
// First add a filter
|
||||||
@ -96,6 +98,8 @@ describe('useRemoveRecordFilter', () => {
|
|||||||
label: 'Test Field',
|
label: 'Test Field',
|
||||||
iconName: 'IconText',
|
iconName: 'IconText',
|
||||||
},
|
},
|
||||||
|
label: 'Test Field',
|
||||||
|
type: 'TEXT',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add a filter
|
// Add a filter
|
||||||
|
|||||||
@ -41,6 +41,8 @@ describe('useUpsertRecordFilter', () => {
|
|||||||
label: 'Test Field',
|
label: 'Test Field',
|
||||||
iconName: 'IconText',
|
iconName: 'IconText',
|
||||||
},
|
},
|
||||||
|
label: 'Test Field',
|
||||||
|
type: 'TEXT',
|
||||||
};
|
};
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
@ -79,6 +81,8 @@ describe('useUpsertRecordFilter', () => {
|
|||||||
label: 'Test Field',
|
label: 'Test Field',
|
||||||
iconName: 'IconText',
|
iconName: 'IconText',
|
||||||
},
|
},
|
||||||
|
label: 'Test Field',
|
||||||
|
type: 'TEXT',
|
||||||
};
|
};
|
||||||
|
|
||||||
const updatedFilter: RecordFilter = {
|
const updatedFilter: RecordFilter = {
|
||||||
@ -93,6 +97,8 @@ describe('useUpsertRecordFilter', () => {
|
|||||||
label: 'Test Field',
|
label: 'Test Field',
|
||||||
iconName: 'IconText',
|
iconName: 'IconText',
|
||||||
},
|
},
|
||||||
|
label: 'Test Field',
|
||||||
|
type: 'TEXT',
|
||||||
};
|
};
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
|
|||||||
@ -17,16 +17,25 @@ export const useUpsertRecordFilter = () => {
|
|||||||
currentRecordFiltersCallbackState,
|
currentRecordFiltersCallbackState,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: This is a temporary solution to ensure that the record filter is compatible with filter definitions
|
||||||
|
// Label and type will be set without definition
|
||||||
|
const recordFilterToSet: RecordFilter = {
|
||||||
|
...filter,
|
||||||
|
label: filter.definition.label,
|
||||||
|
type: filter.definition.type,
|
||||||
|
};
|
||||||
|
|
||||||
const foundRecordFilterInCurrentRecordFilters =
|
const foundRecordFilterInCurrentRecordFilters =
|
||||||
currentRecordFilters.some(
|
currentRecordFilters.some(
|
||||||
(existingFilter) =>
|
(existingFilter) =>
|
||||||
existingFilter.fieldMetadataId === filter.fieldMetadataId,
|
existingFilter.fieldMetadataId ===
|
||||||
|
recordFilterToSet.fieldMetadataId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!foundRecordFilterInCurrentRecordFilters) {
|
if (!foundRecordFilterInCurrentRecordFilters) {
|
||||||
set(currentRecordFiltersCallbackState, [
|
set(currentRecordFiltersCallbackState, [
|
||||||
...currentRecordFilters,
|
...currentRecordFilters,
|
||||||
filter,
|
recordFilterToSet,
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
set(currentRecordFiltersCallbackState, (currentRecordFilters) => {
|
set(currentRecordFiltersCallbackState, (currentRecordFilters) => {
|
||||||
@ -34,11 +43,12 @@ export const useUpsertRecordFilter = () => {
|
|||||||
|
|
||||||
const indexOfFilterToUpdate = newCurrentRecordFilters.findIndex(
|
const indexOfFilterToUpdate = newCurrentRecordFilters.findIndex(
|
||||||
(existingFilter) =>
|
(existingFilter) =>
|
||||||
existingFilter.fieldMetadataId === filter.fieldMetadataId,
|
existingFilter.fieldMetadataId ===
|
||||||
|
recordFilterToSet.fieldMetadataId,
|
||||||
);
|
);
|
||||||
|
|
||||||
newCurrentRecordFilters[indexOfFilterToUpdate] = {
|
newCurrentRecordFilters[indexOfFilterToUpdate] = {
|
||||||
...filter,
|
...recordFilterToSet,
|
||||||
};
|
};
|
||||||
|
|
||||||
return newCurrentRecordFilters;
|
return newCurrentRecordFilters;
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { FilterableFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
|
||||||
import { RecordFilterDefinition } from '@/object-record/record-filter/types/RecordFilterDefinition';
|
import { RecordFilterDefinition } from '@/object-record/record-filter/types/RecordFilterDefinition';
|
||||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||||
|
|
||||||
@ -7,11 +8,12 @@ export type RecordFilter = {
|
|||||||
fieldMetadataId: string;
|
fieldMetadataId: string;
|
||||||
value: string;
|
value: string;
|
||||||
displayValue: string;
|
displayValue: string;
|
||||||
|
type?: FilterableFieldType;
|
||||||
viewFilterGroupId?: string;
|
viewFilterGroupId?: string;
|
||||||
displayAvatarUrl?: string;
|
displayAvatarUrl?: string;
|
||||||
operand: ViewFilterOperand;
|
operand: ViewFilterOperand;
|
||||||
positionInViewFilterGroup?: number | null;
|
positionInViewFilterGroup?: number | null;
|
||||||
definition: RecordFilterDefinition;
|
definition: RecordFilterDefinition;
|
||||||
label?: string;
|
label?: string;
|
||||||
subFieldName?: string;
|
subFieldName?: string | null | undefined;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -795,7 +795,7 @@ const computeFilterRecordGqlOperationFilter = (
|
|||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unknown operand ${filter.operand} for ${filter.definition.label} filter`,
|
`Unknown operand ${filter.operand} for ${filter.label} filter`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,105 @@
|
|||||||
|
import { isFilterOnActorSourceSubField } from '@/object-record/object-filter-dropdown/utils/isFilterOnActorSourceSubField';
|
||||||
|
import { FilterableFieldType } from '@/object-record/record-filter/types/FilterableFieldType';
|
||||||
|
import { ViewFilterOperand as RecordFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||||
|
|
||||||
|
export type GetRecordFilterOperandsParams = {
|
||||||
|
filterType: FilterableFieldType;
|
||||||
|
subFieldName?: string | null | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getRecordFilterOperands = ({
|
||||||
|
filterType,
|
||||||
|
subFieldName,
|
||||||
|
}: GetRecordFilterOperandsParams): RecordFilterOperand[] => {
|
||||||
|
const emptyOperands = [
|
||||||
|
RecordFilterOperand.IsEmpty,
|
||||||
|
RecordFilterOperand.IsNotEmpty,
|
||||||
|
];
|
||||||
|
|
||||||
|
const relationOperands = [RecordFilterOperand.Is, RecordFilterOperand.IsNot];
|
||||||
|
|
||||||
|
switch (filterType) {
|
||||||
|
case 'TEXT':
|
||||||
|
case 'EMAILS':
|
||||||
|
case 'FULL_NAME':
|
||||||
|
case 'ADDRESS':
|
||||||
|
case 'LINKS':
|
||||||
|
case 'PHONES':
|
||||||
|
return [
|
||||||
|
RecordFilterOperand.Contains,
|
||||||
|
RecordFilterOperand.DoesNotContain,
|
||||||
|
...emptyOperands,
|
||||||
|
];
|
||||||
|
case 'CURRENCY':
|
||||||
|
case 'NUMBER':
|
||||||
|
return [
|
||||||
|
RecordFilterOperand.GreaterThan,
|
||||||
|
RecordFilterOperand.LessThan,
|
||||||
|
...emptyOperands,
|
||||||
|
];
|
||||||
|
case 'RAW_JSON':
|
||||||
|
return [
|
||||||
|
RecordFilterOperand.Contains,
|
||||||
|
RecordFilterOperand.DoesNotContain,
|
||||||
|
...emptyOperands,
|
||||||
|
];
|
||||||
|
case 'DATE_TIME':
|
||||||
|
case 'DATE':
|
||||||
|
return [
|
||||||
|
RecordFilterOperand.Is,
|
||||||
|
RecordFilterOperand.IsRelative,
|
||||||
|
RecordFilterOperand.IsInPast,
|
||||||
|
RecordFilterOperand.IsInFuture,
|
||||||
|
RecordFilterOperand.IsToday,
|
||||||
|
RecordFilterOperand.IsBefore,
|
||||||
|
RecordFilterOperand.IsAfter,
|
||||||
|
...emptyOperands,
|
||||||
|
];
|
||||||
|
case 'RATING':
|
||||||
|
return [
|
||||||
|
RecordFilterOperand.Is,
|
||||||
|
RecordFilterOperand.GreaterThan,
|
||||||
|
RecordFilterOperand.LessThan,
|
||||||
|
...emptyOperands,
|
||||||
|
];
|
||||||
|
case 'RELATION':
|
||||||
|
return [...relationOperands, ...emptyOperands];
|
||||||
|
case 'MULTI_SELECT':
|
||||||
|
return [
|
||||||
|
RecordFilterOperand.Contains,
|
||||||
|
RecordFilterOperand.DoesNotContain,
|
||||||
|
...emptyOperands,
|
||||||
|
];
|
||||||
|
case 'SELECT':
|
||||||
|
return [
|
||||||
|
RecordFilterOperand.Is,
|
||||||
|
RecordFilterOperand.IsNot,
|
||||||
|
...emptyOperands,
|
||||||
|
];
|
||||||
|
case 'ACTOR': {
|
||||||
|
if (isFilterOnActorSourceSubField(subFieldName)) {
|
||||||
|
return [
|
||||||
|
RecordFilterOperand.Is,
|
||||||
|
RecordFilterOperand.IsNot,
|
||||||
|
...emptyOperands,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
RecordFilterOperand.Contains,
|
||||||
|
RecordFilterOperand.DoesNotContain,
|
||||||
|
...emptyOperands,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'ARRAY':
|
||||||
|
return [
|
||||||
|
RecordFilterOperand.Contains,
|
||||||
|
RecordFilterOperand.DoesNotContain,
|
||||||
|
...emptyOperands,
|
||||||
|
];
|
||||||
|
case 'BOOLEAN':
|
||||||
|
return [RecordFilterOperand.Is];
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -30,9 +30,7 @@ export const RecordTableEmptyStateSoftDelete = () => {
|
|||||||
|
|
||||||
const handleButtonClick = async () => {
|
const handleButtonClick = async () => {
|
||||||
const deletedFilter = tableFilters.find(
|
const deletedFilter = tableFilters.find(
|
||||||
(filter) =>
|
(filter) => filter.label === 'Deleted' && filter.operand === 'isNotEmpty',
|
||||||
filter.definition.label === 'Deleted' &&
|
|
||||||
filter.operand === 'isNotEmpty',
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!deletedFilter) {
|
if (!deletedFilter) {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { useIcons } from 'twenty-ui';
|
import { useIcons } from 'twenty-ui';
|
||||||
|
|
||||||
|
import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetadataItemById';
|
||||||
import { getOperandLabelShort } from '@/object-record/object-filter-dropdown/utils/getOperandLabel';
|
import { getOperandLabelShort } from '@/object-record/object-filter-dropdown/utils/getOperandLabel';
|
||||||
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';
|
||||||
@ -14,13 +15,20 @@ export const EditableFilterChip = ({
|
|||||||
onRemove,
|
onRemove,
|
||||||
}: EditableFilterChipProps) => {
|
}: EditableFilterChipProps) => {
|
||||||
const { getIcon } = useIcons();
|
const { getIcon } = useIcons();
|
||||||
|
|
||||||
|
const { fieldMetadataItem } = useFieldMetadataItemById(
|
||||||
|
viewFilter.fieldMetadataId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const FieldMetadataItemIcon = getIcon(fieldMetadataItem.icon);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SortOrFilterChip
|
<SortOrFilterChip
|
||||||
key={viewFilter.id}
|
key={viewFilter.id}
|
||||||
testId={viewFilter.id}
|
testId={viewFilter.id}
|
||||||
labelKey={`${viewFilter.definition.label}${getOperandLabelShort(viewFilter.operand)}`}
|
labelKey={`${viewFilter.label}${getOperandLabelShort(viewFilter.operand)}`}
|
||||||
labelValue={viewFilter.displayValue}
|
labelValue={viewFilter.displayValue}
|
||||||
Icon={getIcon(viewFilter.definition.iconName)}
|
Icon={FieldMetadataItemIcon}
|
||||||
onRemove={onRemove}
|
onRemove={onRemove}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { useIcons } from 'twenty-ui';
|
import { useIcons } from 'twenty-ui';
|
||||||
|
|
||||||
|
import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetadataItemById';
|
||||||
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
|
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
|
||||||
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';
|
||||||
@ -9,12 +10,12 @@ import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedVie
|
|||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
type VariantFilterChipProps = {
|
type VariantFilterChipProps = {
|
||||||
viewFilter: RecordFilter;
|
recordFilter: RecordFilter;
|
||||||
viewBarId: string;
|
viewBarId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VariantFilterChip = ({
|
export const VariantFilterChip = ({
|
||||||
viewFilter,
|
recordFilter,
|
||||||
viewBarId,
|
viewBarId,
|
||||||
}: VariantFilterChipProps) => {
|
}: VariantFilterChipProps) => {
|
||||||
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
|
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
|
||||||
@ -30,17 +31,23 @@ export const VariantFilterChip = ({
|
|||||||
viewBarId,
|
viewBarId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { fieldMetadataItem } = useFieldMetadataItemById(
|
||||||
|
recordFilter.fieldMetadataId,
|
||||||
|
);
|
||||||
|
|
||||||
const { removeRecordFilter } = useRemoveRecordFilter();
|
const { removeRecordFilter } = useRemoveRecordFilter();
|
||||||
|
|
||||||
const { getIcon } = useIcons();
|
const { getIcon } = useIcons();
|
||||||
|
|
||||||
|
const FieldMetadataItemIcon = getIcon(fieldMetadataItem.icon);
|
||||||
|
|
||||||
const handleRemoveClick = () => {
|
const handleRemoveClick = () => {
|
||||||
deleteCombinedViewFilter(viewFilter.id);
|
deleteCombinedViewFilter(recordFilter.id);
|
||||||
removeRecordFilter(viewFilter.fieldMetadataId);
|
removeRecordFilter(recordFilter.fieldMetadataId);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
viewFilter.definition.label === 'Deleted' &&
|
recordFilter.label === 'Deleted' &&
|
||||||
viewFilter.operand === 'isNotEmpty'
|
recordFilter.operand === 'isNotEmpty'
|
||||||
) {
|
) {
|
||||||
toggleSoftDeleteFilterState(false);
|
toggleSoftDeleteFilterState(false);
|
||||||
}
|
}
|
||||||
@ -48,11 +55,11 @@ export const VariantFilterChip = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<SortOrFilterChip
|
<SortOrFilterChip
|
||||||
key={viewFilter.fieldMetadataId}
|
key={recordFilter.fieldMetadataId}
|
||||||
testId={viewFilter.fieldMetadataId}
|
testId={recordFilter.fieldMetadataId}
|
||||||
variant={viewFilter.variant}
|
variant={recordFilter.variant}
|
||||||
labelValue={viewFilter.definition.label}
|
labelValue={recordFilter.label ?? ''}
|
||||||
Icon={getIcon(viewFilter.definition.iconName)}
|
Icon={FieldMetadataItemIcon}
|
||||||
onRemove={handleRemoveClick}
|
onRemove={handleRemoveClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -193,7 +193,7 @@ export const ViewBarDetails = ({
|
|||||||
{otherViewFilters.map((viewFilter) => (
|
{otherViewFilters.map((viewFilter) => (
|
||||||
<VariantFilterChip
|
<VariantFilterChip
|
||||||
key={viewFilter.fieldMetadataId}
|
key={viewFilter.fieldMetadataId}
|
||||||
viewFilter={viewFilter}
|
recordFilter={viewFilter}
|
||||||
viewBarId={viewBarId}
|
viewBarId={viewBarId}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useEffect } from 'react';
|
|||||||
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 { filterDefinitionUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/filterDefinitionUsedInDropdownComponentState';
|
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 { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||||
@ -21,8 +21,8 @@ export const ViewBarFilterEffect = ({
|
|||||||
}: ViewBarFilterEffectProps) => {
|
}: ViewBarFilterEffectProps) => {
|
||||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||||
|
|
||||||
const filterDefinitionUsedInDropdown = useRecoilComponentValueV2(
|
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||||
filterDefinitionUsedInDropdownComponentState,
|
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||||
filterDropdownId,
|
filterDropdownId,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -38,12 +38,11 @@ export const ViewBarFilterEffect = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (filterDefinitionUsedInDropdown?.type === 'RELATION') {
|
if (fieldMetadataItemUsedInDropdown?.type === 'RELATION') {
|
||||||
const viewFilterUsedInDropdown =
|
const viewFilterUsedInDropdown =
|
||||||
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
||||||
(filter) =>
|
(filter) =>
|
||||||
filter.fieldMetadataId ===
|
filter.fieldMetadataId === fieldMetadataItemUsedInDropdown?.id,
|
||||||
filterDefinitionUsedInDropdown?.fieldMetadataId,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const { selectedRecordIds } = jsonRelationFilterValueSchema
|
const { selectedRecordIds } = jsonRelationFilterValueSchema
|
||||||
@ -57,14 +56,13 @@ export const ViewBarFilterEffect = ({
|
|||||||
|
|
||||||
setObjectFilterDropdownSelectedRecordIds(selectedRecordIds);
|
setObjectFilterDropdownSelectedRecordIds(selectedRecordIds);
|
||||||
} else if (
|
} else if (
|
||||||
isDefined(filterDefinitionUsedInDropdown) &&
|
isDefined(fieldMetadataItemUsedInDropdown) &&
|
||||||
['SELECT', 'MULTI_SELECT'].includes(filterDefinitionUsedInDropdown.type)
|
['SELECT', 'MULTI_SELECT'].includes(fieldMetadataItemUsedInDropdown.type)
|
||||||
) {
|
) {
|
||||||
const viewFilterUsedInDropdown =
|
const viewFilterUsedInDropdown =
|
||||||
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
currentViewWithCombinedFiltersAndSorts?.viewFilters.find(
|
||||||
(filter) =>
|
(filter) =>
|
||||||
filter.fieldMetadataId ===
|
filter.fieldMetadataId === fieldMetadataItemUsedInDropdown?.id,
|
||||||
filterDefinitionUsedInDropdown?.fieldMetadataId,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const viewFilterSelectedRecords = isNonEmptyString(
|
const viewFilterSelectedRecords = isNonEmptyString(
|
||||||
@ -75,7 +73,7 @@ export const ViewBarFilterEffect = ({
|
|||||||
setObjectFilterDropdownSelectedOptionValues(viewFilterSelectedRecords);
|
setObjectFilterDropdownSelectedOptionValues(viewFilterSelectedRecords);
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
filterDefinitionUsedInDropdown,
|
fieldMetadataItemUsedInDropdown,
|
||||||
setObjectFilterDropdownSelectedRecordIds,
|
setObjectFilterDropdownSelectedRecordIds,
|
||||||
setObjectFilterDropdownSelectedOptionValues,
|
setObjectFilterDropdownSelectedOptionValues,
|
||||||
currentViewWithCombinedFiltersAndSorts,
|
currentViewWithCombinedFiltersAndSorts,
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
import { act, renderHook } from '@testing-library/react';
|
import { act, renderHook } from '@testing-library/react';
|
||||||
|
|
||||||
import { formatFieldMetadataItemAsFilterDefinition } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
import {
|
||||||
|
formatFieldMetadataItemAsFilterDefinition,
|
||||||
|
getFilterTypeFromFieldType,
|
||||||
|
} from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||||
|
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||||
import { RecordFilterDefinition } from '@/object-record/record-filter/types/RecordFilterDefinition';
|
import { RecordFilterDefinition } from '@/object-record/record-filter/types/RecordFilterDefinition';
|
||||||
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
@ -39,7 +43,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
|
|||||||
fieldMetadataId: mockFieldMetadataItem.id,
|
fieldMetadataId: mockFieldMetadataItem.id,
|
||||||
operand: ViewFilterOperand.Contains,
|
operand: ViewFilterOperand.Contains,
|
||||||
value: 'test',
|
value: 'test',
|
||||||
displayValue: 'test',
|
displayValue: mockFieldMetadataItem.label,
|
||||||
viewFilterGroupId: 'group-1',
|
viewFilterGroupId: 'group-1',
|
||||||
positionInViewFilterGroup: 0,
|
positionInViewFilterGroup: 0,
|
||||||
definition: mockFilterDefinition,
|
definition: mockFilterDefinition,
|
||||||
@ -99,7 +103,9 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
|
|||||||
viewFilterGroupId: mockViewFilter.viewFilterGroupId,
|
viewFilterGroupId: mockViewFilter.viewFilterGroupId,
|
||||||
positionInViewFilterGroup: mockViewFilter.positionInViewFilterGroup,
|
positionInViewFilterGroup: mockViewFilter.positionInViewFilterGroup,
|
||||||
definition: mockFilterDefinition,
|
definition: mockFilterDefinition,
|
||||||
},
|
label: mockViewFilter.displayValue,
|
||||||
|
type: getFilterTypeFromFieldType(mockFieldMetadataItem.type),
|
||||||
|
} satisfies RecordFilter,
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
import { act, renderHook } from '@testing-library/react';
|
import { act, renderHook } from '@testing-library/react';
|
||||||
|
|
||||||
import { formatFieldMetadataItemAsFilterDefinition } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
import {
|
||||||
|
formatFieldMetadataItemAsFilterDefinition,
|
||||||
|
getFilterTypeFromFieldType,
|
||||||
|
} from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||||
|
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||||
import { RecordFilterDefinition } from '@/object-record/record-filter/types/RecordFilterDefinition';
|
import { RecordFilterDefinition } from '@/object-record/record-filter/types/RecordFilterDefinition';
|
||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||||
@ -35,7 +39,7 @@ describe('useApplyViewFiltersToCurrentRecordFilters', () => {
|
|||||||
fieldMetadataId: mockFieldMetadataItem.id,
|
fieldMetadataId: mockFieldMetadataItem.id,
|
||||||
operand: ViewFilterOperand.Contains,
|
operand: ViewFilterOperand.Contains,
|
||||||
value: 'test',
|
value: 'test',
|
||||||
displayValue: 'test',
|
displayValue: mockFieldMetadataItem.label,
|
||||||
viewFilterGroupId: 'group-1',
|
viewFilterGroupId: 'group-1',
|
||||||
positionInViewFilterGroup: 0,
|
positionInViewFilterGroup: 0,
|
||||||
definition: mockAvailableFilterDefinition,
|
definition: mockAvailableFilterDefinition,
|
||||||
@ -72,7 +76,9 @@ describe('useApplyViewFiltersToCurrentRecordFilters', () => {
|
|||||||
viewFilterGroupId: mockViewFilter.viewFilterGroupId,
|
viewFilterGroupId: mockViewFilter.viewFilterGroupId,
|
||||||
positionInViewFilterGroup: mockViewFilter.positionInViewFilterGroup,
|
positionInViewFilterGroup: mockViewFilter.positionInViewFilterGroup,
|
||||||
definition: mockAvailableFilterDefinition,
|
definition: mockAvailableFilterDefinition,
|
||||||
},
|
label: mockViewFilter.displayValue,
|
||||||
|
type: getFilterTypeFromFieldType(mockFieldMetadataItem.type),
|
||||||
|
} satisfies RecordFilter,
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { mapColumnDefinitionsToViewFields } from '@/views/utils/mapColumnDefinit
|
|||||||
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
|
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
|
||||||
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
||||||
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
|
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
|
||||||
|
|
||||||
import { FieldMetadataType } from '~/generated/graphql';
|
import { FieldMetadataType } from '~/generated/graphql';
|
||||||
|
|
||||||
const baseDefinition = {
|
const baseDefinition = {
|
||||||
@ -65,6 +66,10 @@ describe('mapViewFiltersToFilters', () => {
|
|||||||
...baseDefinition,
|
...baseDefinition,
|
||||||
type: 'FULL_NAME',
|
type: 'FULL_NAME',
|
||||||
},
|
},
|
||||||
|
label: baseDefinition.label,
|
||||||
|
type: 'FULL_NAME',
|
||||||
|
positionInViewFilterGroup: undefined,
|
||||||
|
viewFilterGroupId: undefined,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
expect(
|
expect(
|
||||||
|
|||||||
@ -26,6 +26,8 @@ export const mapViewFiltersToFilters = (
|
|||||||
viewFilterGroupId: viewFilter.viewFilterGroupId,
|
viewFilterGroupId: viewFilter.viewFilterGroupId,
|
||||||
positionInViewFilterGroup: viewFilter.positionInViewFilterGroup,
|
positionInViewFilterGroup: viewFilter.positionInViewFilterGroup,
|
||||||
definition: viewFilter.definition ?? availableFilterDefinition,
|
definition: viewFilter.definition ?? availableFilterDefinition,
|
||||||
|
label: viewFilter.definition?.label ?? availableFilterDefinition.label,
|
||||||
|
type: viewFilter.definition?.type ?? availableFilterDefinition.type,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(isDefined);
|
.filter(isDefined);
|
||||||
|
|||||||
Reference in New Issue
Block a user