Advanced filters bug bash (#11178)
This commit is contained in:
@ -13,8 +13,8 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import styled from '@emotion/styled';
|
||||
import { MenuItem } from 'twenty-ui';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { MenuItem } from 'twenty-ui';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
flex: 1;
|
||||
@ -80,6 +80,7 @@ export const AdvancedFilterRecordFilterOperandSelect = ({
|
||||
const operandsForFilterType = isDefined(filterType)
|
||||
? getRecordFilterOperands({
|
||||
filterType,
|
||||
subFieldName: filter?.subFieldName,
|
||||
})
|
||||
: [];
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-recor
|
||||
import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState';
|
||||
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
|
||||
import { objectFilterDropdownSubMenuFieldTypeComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSubMenuFieldTypeComponentState';
|
||||
import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState';
|
||||
import { getCompositeSubFieldLabel } from '@/object-record/object-filter-dropdown/utils/getCompositeSubFieldLabel';
|
||||
import { getFilterableFieldTypeLabel } from '@/object-record/object-filter-dropdown/utils/getFilterableFieldTypeLabel';
|
||||
import { SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsCompositeFieldTypeConfigs';
|
||||
@ -37,6 +38,10 @@ export const AdvancedFilterSubFieldSelectMenu = ({
|
||||
objectFilterDropdownFilterIsSelectedComponentState,
|
||||
);
|
||||
|
||||
const [, setSubFieldNameUsedInDropdown] = useRecoilComponentStateV2(
|
||||
subFieldNameUsedInDropdownComponentState,
|
||||
);
|
||||
|
||||
const [, setObjectFilterDropdownIsSelectingCompositeField] =
|
||||
useRecoilComponentStateV2(
|
||||
objectFilterDropdownIsSelectingCompositeFieldComponentState,
|
||||
@ -81,6 +86,7 @@ export const AdvancedFilterSubFieldSelectMenu = ({
|
||||
setObjectFilterDropdownSubMenuFieldType(null);
|
||||
setObjectFilterDropdownIsSelectingCompositeField(false);
|
||||
setObjectFilterDropdownFilterIsSelected(false);
|
||||
setSubFieldNameUsedInDropdown(null);
|
||||
};
|
||||
|
||||
if (!isDefined(objectFilterDropdownSubMenuFieldType)) {
|
||||
|
||||
@ -6,7 +6,6 @@ import { configurableViewFilterOperands } from '@/object-record/object-filter-dr
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { SelectControl } from '@/ui/input/components/SelectControl';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
|
||||
@ -79,14 +78,12 @@ export const AdvancedFilterValueInputDropdownButton = ({
|
||||
setSelectedFilter(filter);
|
||||
}}
|
||||
dropdownComponents={
|
||||
<DropdownMenuItemsContainer>
|
||||
<ObjectFilterDropdownFilterInput />
|
||||
</DropdownMenuItemsContainer>
|
||||
<ObjectFilterDropdownFilterInput recordFilterId={filter.id} />
|
||||
}
|
||||
dropdownHotkeyScope={{ scope: dropdownId }}
|
||||
dropdownOffset={{ y: 8, x: 0 }}
|
||||
dropdownPlacement="bottom-start"
|
||||
dropdownMenuWidth={280}
|
||||
dropdownMenuWidth={200}
|
||||
/>
|
||||
)}
|
||||
</StyledValueDropdownContainer>
|
||||
|
||||
@ -72,6 +72,7 @@ export const useSelectFieldUsedInAdvancedFilterDropdown = () => {
|
||||
|
||||
const firstOperand = getRecordFilterOperands({
|
||||
filterType,
|
||||
subFieldName,
|
||||
})[0];
|
||||
|
||||
setSelectedOperandInDropdown(firstOperand);
|
||||
@ -97,9 +98,7 @@ export const useSelectFieldUsedInAdvancedFilterDropdown = () => {
|
||||
subFieldName,
|
||||
});
|
||||
|
||||
if (isDefined(subFieldName)) {
|
||||
setSubFieldNameUsedInDropdown(subFieldName);
|
||||
}
|
||||
setSubFieldNameUsedInDropdown(subFieldName);
|
||||
|
||||
setObjectFilterDropdownSearchInput('');
|
||||
};
|
||||
|
||||
@ -16,8 +16,8 @@ import {
|
||||
VariableDateViewFilterValueUnit,
|
||||
} from '@/views/view-filter-value/utils/resolveDateViewFilterValue';
|
||||
import { useState } from 'react';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const ObjectFilterDropdownDateInput = () => {
|
||||
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||
@ -114,7 +114,6 @@ export const ObjectFilterDropdownDateInput = () => {
|
||||
date={internalDate}
|
||||
onChange={handleAbsoluteDateChange}
|
||||
onRelativeDateChange={handleRelativeDateChange}
|
||||
onClose={handleAbsoluteDateChange}
|
||||
isDateTimeInput={isDateTimeInput}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -23,10 +23,12 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type ObjectFilterDropdownFilterInputProps = {
|
||||
filterDropdownId?: string;
|
||||
recordFilterId?: string;
|
||||
};
|
||||
|
||||
export const ObjectFilterDropdownFilterInput = ({
|
||||
filterDropdownId,
|
||||
recordFilterId,
|
||||
}: ObjectFilterDropdownFilterInputProps) => {
|
||||
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||
@ -74,8 +76,9 @@ export const ObjectFilterDropdownFilterInput = ({
|
||||
<>
|
||||
{isConfigurable && selectedOperandInDropdown && (
|
||||
<>
|
||||
{TEXT_FILTER_TYPES.includes(filterType) &&
|
||||
!isActorSourceCompositeFilter && <ObjectFilterDropdownTextInput />}
|
||||
{TEXT_FILTER_TYPES.includes(filterType) && (
|
||||
<ObjectFilterDropdownTextInput />
|
||||
)}
|
||||
{NUMBER_FILTER_TYPES.includes(filterType) && (
|
||||
<ObjectFilterDropdownNumberInput />
|
||||
)}
|
||||
@ -87,15 +90,21 @@ export const ObjectFilterDropdownFilterInput = ({
|
||||
<>
|
||||
<ObjectFilterDropdownSearchInput />
|
||||
<DropdownMenuSeparator />
|
||||
<ObjectFilterDropdownRecordSelect />
|
||||
</>
|
||||
)}
|
||||
{filterType === 'ACTOR' && isActorSourceCompositeFilter && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<ObjectFilterDropdownSourceSelect />
|
||||
<ObjectFilterDropdownRecordSelect
|
||||
recordFilterId={recordFilterId}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{filterType === 'ACTOR' &&
|
||||
(isActorSourceCompositeFilter ? (
|
||||
<>
|
||||
<ObjectFilterDropdownSourceSelect />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<ObjectFilterDropdownTextInput />
|
||||
</>
|
||||
))}
|
||||
{['SELECT', 'MULTI_SELECT'].includes(filterType) && (
|
||||
<>
|
||||
<ObjectFilterDropdownSearchInput />
|
||||
|
||||
@ -22,8 +22,8 @@ import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useState } from 'react';
|
||||
import { IconApps, IconChevronLeft, MenuItem, useIcons } from 'twenty-ui';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconApps, IconChevronLeft, MenuItem, useIcons } from 'twenty-ui';
|
||||
|
||||
export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => {
|
||||
const [searchText] = useState('');
|
||||
@ -126,6 +126,7 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => {
|
||||
setObjectFilterDropdownSubMenuFieldType(null);
|
||||
setObjectFilterDropdownIsSelectingCompositeField(false);
|
||||
setObjectFilterDropdownFilterIsSelected(false);
|
||||
setSubFieldNameUsedInDropdown(null);
|
||||
};
|
||||
|
||||
if (!isDefined(objectFilterDropdownSubMenuFieldType)) {
|
||||
|
||||
@ -7,6 +7,7 @@ import { selectedFilterComponentState } from '@/object-record/object-filter-drop
|
||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const ObjectFilterDropdownNumberInput = () => {
|
||||
@ -44,31 +45,33 @@ export const ObjectFilterDropdownNumberInput = () => {
|
||||
return (
|
||||
fieldMetadataItemUsedInDropdown &&
|
||||
selectedOperandInDropdown && (
|
||||
<DropdownMenuInput
|
||||
ref={handleInputRef}
|
||||
value={inputValue}
|
||||
autoFocus
|
||||
type="number"
|
||||
placeholder={fieldMetadataItemUsedInDropdown.label}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
const newValue = event.target.value;
|
||||
<DropdownMenuItemsContainer>
|
||||
<DropdownMenuInput
|
||||
ref={handleInputRef}
|
||||
value={inputValue}
|
||||
autoFocus
|
||||
type="number"
|
||||
placeholder={fieldMetadataItemUsedInDropdown.label}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
setInputValue(newValue);
|
||||
setInputValue(newValue);
|
||||
|
||||
applyRecordFilter({
|
||||
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
||||
fieldMetadataId: fieldMetadataItemUsedInDropdown?.id ?? '',
|
||||
value: newValue,
|
||||
operand: selectedOperandInDropdown,
|
||||
displayValue: newValue,
|
||||
type: getFilterTypeFromFieldType(
|
||||
fieldMetadataItemUsedInDropdown.type,
|
||||
),
|
||||
label: fieldMetadataItemUsedInDropdown.label,
|
||||
recordFilterGroupId: selectedFilter?.recordFilterGroupId,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
applyRecordFilter({
|
||||
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
||||
fieldMetadataId: fieldMetadataItemUsedInDropdown?.id ?? '',
|
||||
value: newValue,
|
||||
operand: selectedOperandInDropdown,
|
||||
displayValue: newValue,
|
||||
type: getFilterTypeFromFieldType(
|
||||
fieldMetadataItemUsedInDropdown.type,
|
||||
),
|
||||
label: fieldMetadataItemUsedInDropdown.label,
|
||||
recordFilterGroupId: selectedFilter?.recordFilterGroupId,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
@ -14,9 +14,9 @@ import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import styled from '@emotion/styled';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { MenuItem } from 'twenty-ui';
|
||||
import { getOperandLabel } from '../utils/getOperandLabel';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
const StyledDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
|
||||
background-color: ${({ theme }) => theme.background.primary};
|
||||
@ -66,7 +66,7 @@ export const ObjectFilterDropdownOperandSelect = () => {
|
||||
|
||||
if (isValuelessOperand && isDefined(fieldMetadataItemUsedInDropdown)) {
|
||||
applyRecordFilter({
|
||||
id: v4(),
|
||||
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
||||
fieldMetadataId: fieldMetadataItemUsedInDropdown.id,
|
||||
displayValue: '',
|
||||
operand: newOperand,
|
||||
|
||||
@ -5,12 +5,17 @@ import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants
|
||||
import { FieldRatingValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||
import { RatingInput } from '@/ui/field/input/components/RatingInput';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
import { 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 styled from '@emotion/styled';
|
||||
|
||||
const StyledRatingInputContainer = styled.div`
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const convertFieldRatingValueToNumber = (
|
||||
rating: Exclude<FieldRatingValue, null>,
|
||||
): string => {
|
||||
@ -51,7 +56,7 @@ export const ObjectFilterDropdownRatingInput = () => {
|
||||
return (
|
||||
fieldMetadataItemUsedInDropdown &&
|
||||
selectedOperandInDropdown && (
|
||||
<DropdownMenuItemsContainer>
|
||||
<StyledRatingInputContainer>
|
||||
<RatingInput
|
||||
value={selectedFilter?.value as FieldRatingValue}
|
||||
onChange={(newValue: FieldRatingValue) => {
|
||||
@ -73,7 +78,7 @@ export const ObjectFilterDropdownRatingInput = () => {
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
</StyledRatingInputContainer>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
@ -7,24 +7,23 @@ import { ObjectFilterDropdownRecordPinnedItems } from '@/object-record/object-fi
|
||||
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 { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||
import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState';
|
||||
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
|
||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { findDuplicateRecordFilterInNonAdvancedRecordFilters } from '@/object-record/record-filter/utils/findDuplicateRecordFilterInNonAdvancedRecordFilters';
|
||||
import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope';
|
||||
import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown';
|
||||
import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect';
|
||||
import { SelectableItem } from '@/object-record/select/types/SelectableItem';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { RelationFilterValue } from '@/views/view-filter-value/types/RelationFilterValue';
|
||||
import { jsonRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/jsonRelationFilterValueSchema';
|
||||
import { simpleRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/simpleRelationFilterValueSchema';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconUserCircle } from 'twenty-ui';
|
||||
import { v4 } from 'uuid';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const EMPTY_FILTER_VALUE: string = JSON.stringify({
|
||||
isCurrentWorkspaceMemberSelected: false,
|
||||
@ -35,10 +34,12 @@ export const MAX_RECORDS_TO_DISPLAY = 3;
|
||||
|
||||
type ObjectFilterDropdownRecordSelectProps = {
|
||||
viewComponentId?: string;
|
||||
recordFilterId?: string;
|
||||
};
|
||||
|
||||
export const ObjectFilterDropdownRecordSelect = ({
|
||||
viewComponentId,
|
||||
recordFilterId,
|
||||
}: ObjectFilterDropdownRecordSelectProps) => {
|
||||
const fieldMetadataItemUsedInFilterDropdown = useRecoilComponentValueV2(
|
||||
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||
@ -56,12 +57,8 @@ export const ObjectFilterDropdownRecordSelect = ({
|
||||
objectFilterDropdownSearchInputComponentState,
|
||||
);
|
||||
|
||||
const objectFilterDropdownSelectedRecordIds = useRecoilComponentValueV2(
|
||||
objectFilterDropdownSelectedRecordIdsComponentState,
|
||||
);
|
||||
|
||||
const setObjectFilterDropdownSelectedRecordIds = useSetRecoilComponentStateV2(
|
||||
objectFilterDropdownSelectedRecordIdsComponentState,
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const { applyRecordFilter } = useApplyRecordFilter(viewComponentId);
|
||||
@ -97,10 +94,34 @@ export const ObjectFilterDropdownRecordSelect = ({
|
||||
throw new Error('objectNameSingular is not defined');
|
||||
}
|
||||
|
||||
const firstSimpleRecordFilterForFieldMetadataItemUsedInDropdown =
|
||||
currentRecordFilters.find(
|
||||
(filter) =>
|
||||
filter.fieldMetadataId === fieldMetadataItemUsedInFilterDropdown?.id &&
|
||||
!isDefined(filter.recordFilterGroupId),
|
||||
);
|
||||
|
||||
const recordFilterPassedInProps = currentRecordFilters.find(
|
||||
(filter) => filter.id === recordFilterId,
|
||||
);
|
||||
|
||||
const recordFilterUsedInDropdown = isDefined(recordFilterId)
|
||||
? recordFilterPassedInProps
|
||||
: firstSimpleRecordFilterForFieldMetadataItemUsedInDropdown;
|
||||
|
||||
const { selectedRecordIds } = jsonRelationFilterValueSchema
|
||||
.catch({
|
||||
isCurrentWorkspaceMemberSelected: false,
|
||||
selectedRecordIds: simpleRelationFilterValueSchema.parse(
|
||||
recordFilterUsedInDropdown?.value,
|
||||
),
|
||||
})
|
||||
.parse(recordFilterUsedInDropdown?.value);
|
||||
|
||||
const { loading, filteredSelectedRecords, recordsToSelect, selectedRecords } =
|
||||
useRecordsForSelect({
|
||||
searchFilterText: objectFilterDropdownSearchInput,
|
||||
selectedIds: objectFilterDropdownSelectedRecordIds,
|
||||
selectedIds: selectedRecordIds,
|
||||
objectNameSingular,
|
||||
limit: 10,
|
||||
});
|
||||
@ -123,10 +144,6 @@ export const ObjectFilterDropdownRecordSelect = ({
|
||||
.includes(objectFilterDropdownSearchInput.toLowerCase()),
|
||||
);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const handleMultipleRecordSelectChange = (
|
||||
itemToSelect: SelectableItem,
|
||||
isNewSelectedValue: boolean,
|
||||
@ -139,17 +156,16 @@ export const ObjectFilterDropdownRecordSelect = ({
|
||||
itemToSelect.id === CURRENT_WORKSPACE_MEMBER_SELECTABLE_ITEM_ID;
|
||||
|
||||
const selectedRecordIdsWithAddedRecord = [
|
||||
...objectFilterDropdownSelectedRecordIds,
|
||||
...selectedRecordIds,
|
||||
itemToSelect.id,
|
||||
];
|
||||
|
||||
const selectedRecordIdsWithRemovedRecord =
|
||||
objectFilterDropdownSelectedRecordIds.filter(
|
||||
(id) => id !== itemToSelect.id,
|
||||
);
|
||||
const selectedRecordIdsWithRemovedRecord = selectedRecordIds.filter(
|
||||
(id) => id !== itemToSelect.id,
|
||||
);
|
||||
|
||||
const newSelectedRecordIds = isItemCurrentWorkspaceMember
|
||||
? objectFilterDropdownSelectedRecordIds
|
||||
? selectedRecordIds
|
||||
: isNewSelectedValue
|
||||
? selectedRecordIdsWithAddedRecord
|
||||
: selectedRecordIdsWithRemovedRecord;
|
||||
@ -194,28 +210,44 @@ export const ObjectFilterDropdownRecordSelect = ({
|
||||
} satisfies RelationFilterValue)
|
||||
: '';
|
||||
|
||||
const recordFilterInDropdown = currentRecordFilters.find(
|
||||
(recordFilter) =>
|
||||
recordFilter.fieldMetadataId ===
|
||||
fieldMetadataItemUsedInFilterDropdown.id,
|
||||
const duplicateFilterInCurrentRecordFilters =
|
||||
findDuplicateRecordFilterInNonAdvancedRecordFilters({
|
||||
recordFilters: currentRecordFilters,
|
||||
fieldMetadataItemId: fieldMetadataItemUsedInFilterDropdown.id,
|
||||
});
|
||||
|
||||
const filterIsAlreadyInCurrentRecordFilters = isDefined(
|
||||
duplicateFilterInCurrentRecordFilters,
|
||||
);
|
||||
|
||||
setObjectFilterDropdownSelectedRecordIds(newSelectedRecordIds);
|
||||
|
||||
const filterId = recordFilterInDropdown?.id ?? v4();
|
||||
|
||||
applyRecordFilter({
|
||||
id: selectedFilter?.id ? selectedFilter.id : filterId,
|
||||
type: getFilterTypeFromFieldType(
|
||||
fieldMetadataItemUsedInFilterDropdown.type,
|
||||
),
|
||||
label: fieldMetadataItemUsedInFilterDropdown.label,
|
||||
operand: selectedOperandInDropdown,
|
||||
displayValue: filterDisplayValue,
|
||||
fieldMetadataId: fieldMetadataItemUsedInFilterDropdown.id,
|
||||
value: newFilterValue,
|
||||
recordFilterGroupId: selectedFilter?.recordFilterGroupId,
|
||||
});
|
||||
if (filterIsAlreadyInCurrentRecordFilters && !isDefined(recordFilterId)) {
|
||||
applyRecordFilter({
|
||||
id: duplicateFilterInCurrentRecordFilters.id,
|
||||
type: getFilterTypeFromFieldType(
|
||||
fieldMetadataItemUsedInFilterDropdown.type,
|
||||
),
|
||||
label: fieldMetadataItemUsedInFilterDropdown.label,
|
||||
operand: selectedOperandInDropdown,
|
||||
displayValue: filterDisplayValue,
|
||||
fieldMetadataId: fieldMetadataItemUsedInFilterDropdown.id,
|
||||
value: newFilterValue,
|
||||
recordFilterGroupId:
|
||||
duplicateFilterInCurrentRecordFilters.recordFilterGroupId,
|
||||
});
|
||||
} else {
|
||||
applyRecordFilter({
|
||||
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
||||
type: getFilterTypeFromFieldType(
|
||||
fieldMetadataItemUsedInFilterDropdown.type,
|
||||
),
|
||||
label: fieldMetadataItemUsedInFilterDropdown.label,
|
||||
operand: selectedOperandInDropdown,
|
||||
displayValue: filterDisplayValue,
|
||||
fieldMetadataId: fieldMetadataItemUsedInFilterDropdown.id,
|
||||
value: newFilterValue,
|
||||
recordFilterGroupId: selectedFilter?.recordFilterGroupId,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||
import { useEmptyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useEmptyRecordFilter';
|
||||
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||
import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState';
|
||||
@ -10,8 +6,8 @@ import { selectedFilterComponentState } from '@/object-record/object-filter-drop
|
||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||
import { getActorSourceMultiSelectOptions } from '@/object-record/object-filter-dropdown/utils/getActorSourceMultiSelectOptions';
|
||||
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { findDuplicateRecordFilterInNonAdvancedRecordFilters } from '@/object-record/record-filter/utils/findDuplicateRecordFilterInNonAdvancedRecordFilters';
|
||||
import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope';
|
||||
import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown';
|
||||
import { SelectableItem } from '@/object-record/select/types/SelectableItem';
|
||||
@ -19,6 +15,7 @@ import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const EMPTY_FILTER_VALUE = '[]';
|
||||
export const MAX_ITEMS_TO_DISPLAY = 3;
|
||||
@ -56,9 +53,6 @@ export const ObjectFilterDropdownSourceSelect = ({
|
||||
|
||||
const { applyRecordFilter } = useApplyRecordFilter(viewComponentId);
|
||||
|
||||
// TODO: this should be removed as it is not consistent across re-renders
|
||||
const [fieldId] = useState(v4());
|
||||
|
||||
const sourceTypes = getActorSourceMultiSelectOptions(
|
||||
objectFilterDropdownSelectedRecordIds,
|
||||
);
|
||||
@ -67,10 +61,6 @@ export const ObjectFilterDropdownSourceSelect = ({
|
||||
objectFilterDropdownSelectedRecordIds.includes(option.id),
|
||||
);
|
||||
|
||||
const { emptyRecordFilter } = useEmptyRecordFilter();
|
||||
|
||||
const { removeRecordFilter } = useRemoveRecordFilter();
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
@ -91,13 +81,6 @@ export const ObjectFilterDropdownSourceSelect = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (newSelectedItemIds.length === 0) {
|
||||
emptyRecordFilter();
|
||||
removeRecordFilter(fieldMetadataItemUsedInFilterDropdown.id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setObjectFilterDropdownSelectedRecordIds(newSelectedItemIds);
|
||||
|
||||
const selectedItemNames = sourceTypes
|
||||
@ -118,13 +101,20 @@ export const ObjectFilterDropdownSourceSelect = ({
|
||||
? JSON.stringify(newSelectedItemIds)
|
||||
: EMPTY_FILTER_VALUE;
|
||||
|
||||
const recordFilter = currentRecordFilters.find(
|
||||
(recordFilter) =>
|
||||
recordFilter.fieldMetadataId ===
|
||||
fieldMetadataItemUsedInFilterDropdown.id,
|
||||
const duplicateFilterInCurrentRecordFilters =
|
||||
findDuplicateRecordFilterInNonAdvancedRecordFilters({
|
||||
recordFilters: currentRecordFilters,
|
||||
fieldMetadataItemId: fieldMetadataItemUsedInFilterDropdown.id,
|
||||
subFieldName: 'source',
|
||||
});
|
||||
|
||||
const filterIsAlreadyInCurrentRecordFilters = isDefined(
|
||||
duplicateFilterInCurrentRecordFilters,
|
||||
);
|
||||
|
||||
const filterId = recordFilter?.id ?? fieldId;
|
||||
const filterId = filterIsAlreadyInCurrentRecordFilters
|
||||
? duplicateFilterInCurrentRecordFilters?.id
|
||||
: v4();
|
||||
|
||||
applyRecordFilter({
|
||||
id: selectedFilter?.id ? selectedFilter.id : filterId,
|
||||
@ -137,6 +127,7 @@ export const ObjectFilterDropdownSourceSelect = ({
|
||||
fieldMetadataId: fieldMetadataItemUsedInFilterDropdown.id,
|
||||
value: newFilterValue,
|
||||
recordFilterGroupId: selectedFilter?.recordFilterGroupId,
|
||||
subFieldName: 'source',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -7,6 +7,7 @@ import { selectedFilterComponentState } from '@/object-record/object-filter-drop
|
||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const ObjectFilterDropdownTextInput = () => {
|
||||
@ -44,31 +45,33 @@ export const ObjectFilterDropdownTextInput = () => {
|
||||
return (
|
||||
fieldMetadataItemUsedInDropdown &&
|
||||
selectedOperandInDropdown && (
|
||||
<DropdownMenuInput
|
||||
ref={handleInputRef}
|
||||
value={inputValue}
|
||||
autoFocus
|
||||
type="text"
|
||||
placeholder={fieldMetadataItemUsedInDropdown.label}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
const newValue = event.target.value;
|
||||
<DropdownMenuItemsContainer>
|
||||
<DropdownMenuInput
|
||||
ref={handleInputRef}
|
||||
value={inputValue}
|
||||
autoFocus
|
||||
type="text"
|
||||
placeholder={fieldMetadataItemUsedInDropdown.label}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
const newValue = event.target.value;
|
||||
|
||||
setInputValue(newValue);
|
||||
setInputValue(newValue);
|
||||
|
||||
applyRecordFilter({
|
||||
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
||||
fieldMetadataId: fieldMetadataItemUsedInDropdown?.id ?? '',
|
||||
value: newValue,
|
||||
operand: selectedOperandInDropdown,
|
||||
displayValue: newValue,
|
||||
type: getFilterTypeFromFieldType(
|
||||
fieldMetadataItemUsedInDropdown.type,
|
||||
),
|
||||
label: fieldMetadataItemUsedInDropdown.label,
|
||||
recordFilterGroupId: selectedFilter?.recordFilterGroupId,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
applyRecordFilter({
|
||||
id: selectedFilter?.id ? selectedFilter.id : v4(),
|
||||
fieldMetadataId: fieldMetadataItemUsedInDropdown?.id ?? '',
|
||||
value: newValue,
|
||||
operand: selectedOperandInDropdown,
|
||||
displayValue: newValue,
|
||||
type: getFilterTypeFromFieldType(
|
||||
fieldMetadataItemUsedInDropdown.type,
|
||||
),
|
||||
label: fieldMetadataItemUsedInDropdown.label,
|
||||
recordFilterGroupId: selectedFilter?.recordFilterGroupId,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
@ -6,7 +6,6 @@ export const TEXT_FILTER_TYPES = [
|
||||
'LINK',
|
||||
'LINKS',
|
||||
'ADDRESS',
|
||||
'ACTOR',
|
||||
'ARRAY',
|
||||
'RAW_JSON',
|
||||
];
|
||||
|
||||
@ -671,6 +671,10 @@ export const computeFilterRecordGqlOperationFilter = ({
|
||||
case 'ACTOR': {
|
||||
switch (filter.operand) {
|
||||
case RecordFilterOperand.Is: {
|
||||
if (filter.value === '[]') {
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedRecordIds = JSON.parse(filter.value) as string[];
|
||||
|
||||
return {
|
||||
@ -682,6 +686,10 @@ export const computeFilterRecordGqlOperationFilter = ({
|
||||
};
|
||||
}
|
||||
case RecordFilterOperand.IsNot: {
|
||||
if (filter.value === '[]') {
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedRecordIds = JSON.parse(filter.value) as string[];
|
||||
|
||||
if (parsedRecordIds.length === 0) return;
|
||||
|
||||
Reference in New Issue
Block a user