Fix bug and refactored advanced filter field selection dropdown (#11103)
This PR is a first step towards isolating each filter dropdown use case, here we isolate advanced filter field selection dropdown from view bar filter field selection dropdown. ## Isolation of advanced filter field selection logic We reimplement the previously generic logic into AdvancedFilterFieldSelectMenu and AdvancedFilterSubFieldSelectMenu components. For now it contains duplicated code but, the end goal is to factorize what's common to all object filter dropdowns in small hooks where possible, at the end of the code path isolation first step, which will be done for applyFilter and selectFilter logic that will be able to be deleted after code path isolation. A new component ObjectFilterDropdownFilterSelectMenuItemV2 has been created to expose an onClick method instead of computing logic that tries to guess where it is located, which allows to verticalize what happens when we select a field in each specific use case, one layer above. Created the hook useSelectFieldUsedInAdvancedFilterDropdown which contains the logic for field selection for advanced filter field select dropdown specific use case, the first example of a good verticalized and unique place to handle field selection in the context of advanced filter. The naming useAdvancedFilterDropdown was lying and is now useAdvancedFilterFieldSelectDropdown which is now self-explanatory. useAdvancedFilterFieldSelectDropdown has been removed from the main object filter dropdown, thus isolating advanced filters field select dropdown from the generic object filter field select dropdown. ## Miscellaneous Removed states that were used in the generic filter dropdown to guess whether it was in advanced filter context or not.
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
import { AdvancedFilterFieldSelectDrodownContent } from '@/object-record/advanced-filter/components/AdvancedFilterFieldSelectDrodownContent';
|
||||
import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown';
|
||||
import { AdvancedFilterFieldSelectDropdownContent } from '@/object-record/advanced-filter/components/AdvancedFilterFieldSelectDropdownContent';
|
||||
import { useAdvancedFilterFieldSelectDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterFieldSelectDropdown';
|
||||
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { SelectControl } from '@/ui/input/components/SelectControl';
|
||||
@ -11,15 +11,15 @@ const StyledContainer = styled.div`
|
||||
flex: 2;
|
||||
`;
|
||||
|
||||
type AdvancedFilterFieldSelectDrodownButtonProps = {
|
||||
type AdvancedFilterFieldSelectDropdownButtonProps = {
|
||||
recordFilterId: string;
|
||||
};
|
||||
|
||||
export const AdvancedFilterFieldSelectDrodownButton = ({
|
||||
export const AdvancedFilterFieldSelectDropdownButton = ({
|
||||
recordFilterId,
|
||||
}: AdvancedFilterFieldSelectDrodownButtonProps) => {
|
||||
const { advancedFilterDropdownId } =
|
||||
useAdvancedFilterDropdown(recordFilterId);
|
||||
}: AdvancedFilterFieldSelectDropdownButtonProps) => {
|
||||
const { advancedFilterFieldSelectDropdownId } =
|
||||
useAdvancedFilterFieldSelectDropdown(recordFilterId);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
@ -34,7 +34,7 @@ export const AdvancedFilterFieldSelectDrodownButton = ({
|
||||
return (
|
||||
<StyledContainer>
|
||||
<Dropdown
|
||||
dropdownId={advancedFilterDropdownId}
|
||||
dropdownId={advancedFilterFieldSelectDropdownId}
|
||||
clickableComponent={
|
||||
<SelectControl
|
||||
selectedOption={{
|
||||
@ -43,8 +43,12 @@ export const AdvancedFilterFieldSelectDrodownButton = ({
|
||||
}}
|
||||
/>
|
||||
}
|
||||
dropdownComponents={<AdvancedFilterFieldSelectDrodownContent />}
|
||||
dropdownHotkeyScope={{ scope: advancedFilterDropdownId }}
|
||||
dropdownComponents={
|
||||
<AdvancedFilterFieldSelectDropdownContent
|
||||
recordFilterId={recordFilterId}
|
||||
/>
|
||||
}
|
||||
dropdownHotkeyScope={{ scope: advancedFilterFieldSelectDropdownId }}
|
||||
dropdownOffset={{ y: 8, x: 0 }}
|
||||
dropdownPlacement="bottom-start"
|
||||
/>
|
||||
@ -1,9 +1,15 @@
|
||||
import { ObjectFilterDropdownFilterSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect';
|
||||
import { ObjectFilterDropdownFilterSelectCompositeFieldSubMenu } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectCompositeFieldSubMenu';
|
||||
import { AdvancedFilterFieldSelectMenu } from '@/object-record/advanced-filter/components/AdvancedFilterFieldSelectMenu';
|
||||
import { AdvancedFilterSubFieldSelectMenu } from '@/object-record/advanced-filter/components/AdvancedFilterSubFieldSelectMenu';
|
||||
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
|
||||
export const AdvancedFilterFieldSelectDrodownContent = () => {
|
||||
type AdvancedFilterFieldSelectDropdownContentProps = {
|
||||
recordFilterId: string;
|
||||
};
|
||||
|
||||
export const AdvancedFilterFieldSelectDropdownContent = ({
|
||||
recordFilterId,
|
||||
}: AdvancedFilterFieldSelectDropdownContentProps) => {
|
||||
const [objectFilterDropdownIsSelectingCompositeField] =
|
||||
useRecoilComponentStateV2(
|
||||
objectFilterDropdownIsSelectingCompositeFieldComponentState,
|
||||
@ -13,8 +19,8 @@ export const AdvancedFilterFieldSelectDrodownContent = () => {
|
||||
objectFilterDropdownIsSelectingCompositeField;
|
||||
|
||||
return shouldShowCompositeSelectionSubMenu ? (
|
||||
<ObjectFilterDropdownFilterSelectCompositeFieldSubMenu />
|
||||
<AdvancedFilterSubFieldSelectMenu recordFilterId={recordFilterId} />
|
||||
) : (
|
||||
<ObjectFilterDropdownFilterSelect />
|
||||
<AdvancedFilterFieldSelectMenu recordFilterId={recordFilterId} />
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,182 @@
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
|
||||
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
|
||||
|
||||
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
|
||||
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||
import { AdvancedFilterFieldSelectSearchInput } from '@/object-record/advanced-filter/components/AdvancedFilterFieldSelectSearchInput';
|
||||
import { useAdvancedFilterFieldSelectDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterFieldSelectDropdown';
|
||||
import { useSelectFieldUsedInAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useSelectFieldUsedInAdvancedFilterDropdown';
|
||||
import { ObjectFilterDropdownFilterSelectMenuItemV2 } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItemV2';
|
||||
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
|
||||
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
|
||||
import { objectFilterDropdownSubMenuFieldTypeComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSubMenuFieldTypeComponentState';
|
||||
import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope';
|
||||
import { isCompositeField } from '@/object-record/object-filter-dropdown/utils/isCompositeField';
|
||||
import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
|
||||
type AdvancedFilterFieldSelectMenuProps = {
|
||||
recordFilterId: string;
|
||||
};
|
||||
|
||||
export const AdvancedFilterFieldSelectMenu = ({
|
||||
recordFilterId,
|
||||
}: AdvancedFilterFieldSelectMenuProps) => {
|
||||
const { recordIndexId } = useRecordIndexContextOrThrow();
|
||||
|
||||
const { closeAdvancedFilterFieldSelectDropdown } =
|
||||
useAdvancedFilterFieldSelectDropdown(recordFilterId);
|
||||
|
||||
const [objectFilterDropdownSearchInput] = useRecoilComponentStateV2(
|
||||
objectFilterDropdownSearchInputComponentState,
|
||||
);
|
||||
|
||||
const { filterableFieldMetadataItems } =
|
||||
useFilterableFieldMetadataItemsInRecordIndexContext();
|
||||
|
||||
const visibleTableColumns = useRecoilComponentValueV2(
|
||||
visibleTableColumnsComponentSelector,
|
||||
recordIndexId,
|
||||
);
|
||||
const visibleColumnsIds = visibleTableColumns.map(
|
||||
(column) => column.fieldMetadataId,
|
||||
);
|
||||
|
||||
const filteredSearchInputFieldMetadataItems =
|
||||
filterableFieldMetadataItems.filter((fieldMetadataItem) =>
|
||||
fieldMetadataItem.label
|
||||
.toLocaleLowerCase()
|
||||
.includes(objectFilterDropdownSearchInput.toLocaleLowerCase()),
|
||||
);
|
||||
|
||||
const visibleColumnsFieldMetadataItems = filteredSearchInputFieldMetadataItems
|
||||
.sort((a, b) => {
|
||||
return visibleColumnsIds.indexOf(a.id) - visibleColumnsIds.indexOf(b.id);
|
||||
})
|
||||
.filter((fieldMetadataItem) =>
|
||||
visibleColumnsIds.includes(fieldMetadataItem.id),
|
||||
);
|
||||
|
||||
const hiddenColumnsFieldMetadataItems = filteredSearchInputFieldMetadataItems
|
||||
.sort((a, b) => a.label.localeCompare(b.label))
|
||||
.filter(
|
||||
(fieldMetadataItem) => !visibleColumnsIds.includes(fieldMetadataItem.id),
|
||||
);
|
||||
|
||||
const selectableFieldMetadataItemIds = filterableFieldMetadataItems.map(
|
||||
(fieldMetadataItem) => fieldMetadataItem.id,
|
||||
);
|
||||
|
||||
const { resetSelectedItem } = useSelectableList(OBJECT_FILTER_DROPDOWN_ID);
|
||||
|
||||
const { selectFieldUsedInAdvancedFilterDropdown } =
|
||||
useSelectFieldUsedInAdvancedFilterDropdown();
|
||||
|
||||
const [, setObjectFilterDropdownSubMenuFieldType] = useRecoilComponentStateV2(
|
||||
objectFilterDropdownSubMenuFieldTypeComponentState,
|
||||
);
|
||||
|
||||
const [, setObjectFilterDropdownIsSelectingCompositeField] =
|
||||
useRecoilComponentStateV2(
|
||||
objectFilterDropdownIsSelectingCompositeFieldComponentState,
|
||||
);
|
||||
|
||||
const setFieldMetadataItemIdUsedInDropdown = useSetRecoilComponentStateV2(
|
||||
fieldMetadataItemIdUsedInDropdownComponentState,
|
||||
);
|
||||
|
||||
const handleEnter = (fieldMetadataItemId: string) => {
|
||||
const selectedFieldMetadataItem = filterableFieldMetadataItems.find(
|
||||
(fieldMetadataItem) => fieldMetadataItem.id === fieldMetadataItemId,
|
||||
);
|
||||
|
||||
if (!isDefined(selectedFieldMetadataItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
handleFieldMetadataItemSelect(selectedFieldMetadataItem);
|
||||
};
|
||||
|
||||
const handleFieldMetadataItemSelect = (
|
||||
selectedFieldMetadataItem: FieldMetadataItem,
|
||||
) => {
|
||||
resetSelectedItem();
|
||||
|
||||
const filterType = getFilterTypeFromFieldType(
|
||||
selectedFieldMetadataItem.type,
|
||||
);
|
||||
|
||||
if (isCompositeField(filterType)) {
|
||||
setObjectFilterDropdownSubMenuFieldType(filterType);
|
||||
|
||||
setFieldMetadataItemIdUsedInDropdown(selectedFieldMetadataItem.id);
|
||||
setObjectFilterDropdownIsSelectingCompositeField(true);
|
||||
} else {
|
||||
selectFieldUsedInAdvancedFilterDropdown({
|
||||
fieldMetadataItemId: selectedFieldMetadataItem.id,
|
||||
recordFilterId,
|
||||
});
|
||||
|
||||
closeAdvancedFilterFieldSelectDropdown();
|
||||
}
|
||||
};
|
||||
|
||||
const shouldShowSeparator =
|
||||
visibleColumnsFieldMetadataItems.length > 0 &&
|
||||
hiddenColumnsFieldMetadataItems.length > 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<AdvancedFilterFieldSelectSearchInput />
|
||||
<SelectableList
|
||||
hotkeyScope={FiltersHotkeyScope.ObjectFilterDropdownButton}
|
||||
selectableItemIdArray={selectableFieldMetadataItemIds}
|
||||
selectableListId={OBJECT_FILTER_DROPDOWN_ID}
|
||||
onEnter={handleEnter}
|
||||
>
|
||||
<DropdownMenuItemsContainer>
|
||||
{visibleColumnsFieldMetadataItems.map(
|
||||
(visibleFieldMetadataItem, index) => (
|
||||
<SelectableItem
|
||||
itemId={visibleFieldMetadataItem.id}
|
||||
key={`visible-select-filter-${index}`}
|
||||
>
|
||||
<ObjectFilterDropdownFilterSelectMenuItemV2
|
||||
fieldMetadataItemToSelect={visibleFieldMetadataItem}
|
||||
onClick={handleFieldMetadataItemSelect}
|
||||
/>
|
||||
</SelectableItem>
|
||||
),
|
||||
)}
|
||||
{shouldShowSeparator && <DropdownMenuSeparator />}
|
||||
{hiddenColumnsFieldMetadataItems.map(
|
||||
(hiddenFieldMetadataItem, index) => (
|
||||
<SelectableItem
|
||||
itemId={hiddenFieldMetadataItem.id}
|
||||
key={`hidden-select-filter-${index}`}
|
||||
>
|
||||
<ObjectFilterDropdownFilterSelectMenuItemV2
|
||||
fieldMetadataItemToSelect={hiddenFieldMetadataItem}
|
||||
onClick={handleFieldMetadataItemSelect}
|
||||
/>
|
||||
</SelectableItem>
|
||||
),
|
||||
)}
|
||||
</DropdownMenuItemsContainer>
|
||||
</SelectableList>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -1,5 +1,5 @@
|
||||
import { AdvancedFilterDropdownRow } from '@/object-record/advanced-filter/components/AdvancedFilterDropdownRow';
|
||||
import { AdvancedFilterFieldSelectDrodownButton } from '@/object-record/advanced-filter/components/AdvancedFilterFieldSelectDrodownButton';
|
||||
import { AdvancedFilterFieldSelectDropdownButton } from '@/object-record/advanced-filter/components/AdvancedFilterFieldSelectDropdownButton';
|
||||
import { AdvancedFilterLogicalOperatorCell } from '@/object-record/advanced-filter/components/AdvancedFilterLogicalOperatorCell';
|
||||
import { AdvancedFilterRecordFilterOperandSelect } from '@/object-record/advanced-filter/components/AdvancedFilterRecordFilterOperandSelect';
|
||||
import { AdvancedFilterRecordFilterOptionsDropdown } from '@/object-record/advanced-filter/components/AdvancedFilterRecordFilterOptionsDropdown';
|
||||
@ -26,7 +26,7 @@ export const AdvancedFilterRecordFilterRow = ({
|
||||
index={recordFilterIndex}
|
||||
recordFilterGroup={recordFilterGroup}
|
||||
/>
|
||||
<AdvancedFilterFieldSelectDrodownButton
|
||||
<AdvancedFilterFieldSelectDropdownButton
|
||||
recordFilterId={recordFilter.id}
|
||||
/>
|
||||
<AdvancedFilterRecordFilterOperandSelect
|
||||
|
||||
@ -0,0 +1,140 @@
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { useAdvancedFilterFieldSelectDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterFieldSelectDropdown';
|
||||
import { useSelectFieldUsedInAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useSelectFieldUsedInAdvancedFilterDropdown';
|
||||
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
|
||||
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||
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 { 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';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
||||
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { IconApps, IconChevronLeft, MenuItem, useIcons } from 'twenty-ui';
|
||||
|
||||
type AdvancedFilterSubFieldSelectMenuProps = {
|
||||
recordFilterId: string;
|
||||
};
|
||||
|
||||
export const AdvancedFilterSubFieldSelectMenu = ({
|
||||
recordFilterId,
|
||||
}: AdvancedFilterSubFieldSelectMenuProps) => {
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2(
|
||||
fieldMetadataItemUsedInDropdownComponentSelector,
|
||||
);
|
||||
|
||||
const [, setObjectFilterDropdownFilterIsSelected] = useRecoilComponentStateV2(
|
||||
objectFilterDropdownFilterIsSelectedComponentState,
|
||||
);
|
||||
|
||||
const [, setObjectFilterDropdownIsSelectingCompositeField] =
|
||||
useRecoilComponentStateV2(
|
||||
objectFilterDropdownIsSelectingCompositeFieldComponentState,
|
||||
);
|
||||
|
||||
const [
|
||||
objectFilterDropdownSubMenuFieldType,
|
||||
setObjectFilterDropdownSubMenuFieldType,
|
||||
] = useRecoilComponentStateV2(
|
||||
objectFilterDropdownSubMenuFieldTypeComponentState,
|
||||
);
|
||||
|
||||
const setFieldMetadataItemIdUsedInDropdown = useSetRecoilComponentStateV2(
|
||||
fieldMetadataItemIdUsedInDropdownComponentState,
|
||||
);
|
||||
|
||||
const { closeAdvancedFilterFieldSelectDropdown } =
|
||||
useAdvancedFilterFieldSelectDropdown(recordFilterId);
|
||||
|
||||
const { selectFieldUsedInAdvancedFilterDropdown } =
|
||||
useSelectFieldUsedInAdvancedFilterDropdown();
|
||||
|
||||
const handleSelectFilter = (
|
||||
selectedFieldMetadataItem: FieldMetadataItem | null | undefined,
|
||||
subFieldName?: string | null | undefined,
|
||||
) => {
|
||||
if (!isDefined(selectedFieldMetadataItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectFieldUsedInAdvancedFilterDropdown({
|
||||
fieldMetadataItemId: selectedFieldMetadataItem.id,
|
||||
recordFilterId,
|
||||
subFieldName,
|
||||
});
|
||||
|
||||
closeAdvancedFilterFieldSelectDropdown();
|
||||
};
|
||||
|
||||
const handleSubMenuBack = () => {
|
||||
setFieldMetadataItemIdUsedInDropdown(null);
|
||||
setObjectFilterDropdownSubMenuFieldType(null);
|
||||
setObjectFilterDropdownIsSelectingCompositeField(false);
|
||||
setObjectFilterDropdownFilterIsSelected(false);
|
||||
};
|
||||
|
||||
if (!isDefined(objectFilterDropdownSubMenuFieldType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const options = SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[
|
||||
objectFilterDropdownSubMenuFieldType
|
||||
].filterableSubFields.sort((a, b) => a.localeCompare(b));
|
||||
|
||||
return (
|
||||
<>
|
||||
<DropdownMenuHeader
|
||||
StartComponent={
|
||||
<DropdownMenuHeaderLeftComponent
|
||||
onClick={handleSubMenuBack}
|
||||
Icon={IconChevronLeft}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{getFilterableFieldTypeLabel(objectFilterDropdownSubMenuFieldType)}
|
||||
</DropdownMenuHeader>
|
||||
<DropdownMenuItemsContainer>
|
||||
<MenuItem
|
||||
key={`select-filter-${-1}`}
|
||||
testId={`select-filter-${-1}`}
|
||||
onClick={() => {
|
||||
handleSelectFilter(fieldMetadataItemUsedInDropdown);
|
||||
}}
|
||||
LeftIcon={IconApps}
|
||||
text={`Any ${getFilterableFieldTypeLabel(objectFilterDropdownSubMenuFieldType)} field`}
|
||||
/>
|
||||
{/* TODO: fix this with a backend field on ViewFilter for composite field filter */}
|
||||
{fieldMetadataItemUsedInDropdown?.type === 'ACTOR' &&
|
||||
options.map((subFieldName, index) => (
|
||||
<MenuItem
|
||||
key={`select-filter-${index}`}
|
||||
testId={`select-filter-${index}`}
|
||||
onClick={() => {
|
||||
if (isDefined(fieldMetadataItemUsedInDropdown)) {
|
||||
handleSelectFilter(
|
||||
fieldMetadataItemUsedInDropdown,
|
||||
subFieldName,
|
||||
);
|
||||
}
|
||||
}}
|
||||
text={getCompositeSubFieldLabel(
|
||||
objectFilterDropdownSubMenuFieldType,
|
||||
subFieldName,
|
||||
)}
|
||||
LeftIcon={getIcon(fieldMetadataItemUsedInDropdown?.icon)}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -1,84 +0,0 @@
|
||||
import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown';
|
||||
|
||||
import { ObjectFilterDropdownFilterSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect';
|
||||
import { ObjectFilterDropdownFilterSelectCompositeFieldSubMenu } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectCompositeFieldSubMenu';
|
||||
import { advancedFilterViewFilterGroupIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterGroupIdComponentState';
|
||||
import { advancedFilterViewFilterIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterIdComponentState';
|
||||
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { SelectControl } from '@/ui/input/components/SelectControl';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
flex: 2;
|
||||
`;
|
||||
|
||||
type AdvancedFilterViewFilterFieldSelectProps = {
|
||||
viewFilterId: string;
|
||||
};
|
||||
|
||||
export const AdvancedFilterViewFilterFieldSelect = ({
|
||||
viewFilterId,
|
||||
}: AdvancedFilterViewFilterFieldSelectProps) => {
|
||||
const { advancedFilterDropdownId } = useAdvancedFilterDropdown(viewFilterId);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const recordFilter = currentRecordFilters.find(
|
||||
(recordFilter) => recordFilter.id === viewFilterId,
|
||||
);
|
||||
|
||||
const selectedFieldLabel = recordFilter?.label ?? '';
|
||||
|
||||
const setAdvancedFilterViewFilterId = useSetRecoilComponentStateV2(
|
||||
advancedFilterViewFilterIdComponentState,
|
||||
);
|
||||
|
||||
const setAdvancedFilterViewFilterGroupId = useSetRecoilComponentStateV2(
|
||||
advancedFilterViewFilterGroupIdComponentState,
|
||||
);
|
||||
|
||||
const [objectFilterDropdownIsSelectingCompositeField] =
|
||||
useRecoilComponentStateV2(
|
||||
objectFilterDropdownIsSelectingCompositeFieldComponentState,
|
||||
);
|
||||
|
||||
const shouldShowCompositeSelectionSubMenu =
|
||||
objectFilterDropdownIsSelectingCompositeField;
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<Dropdown
|
||||
dropdownId={advancedFilterDropdownId}
|
||||
clickableComponent={
|
||||
<SelectControl
|
||||
selectedOption={{
|
||||
label: selectedFieldLabel,
|
||||
value: null,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
onOpen={() => {
|
||||
setAdvancedFilterViewFilterId(recordFilter?.id);
|
||||
setAdvancedFilterViewFilterGroupId(recordFilter?.recordFilterGroupId);
|
||||
}}
|
||||
dropdownComponents={
|
||||
shouldShowCompositeSelectionSubMenu ? (
|
||||
<ObjectFilterDropdownFilterSelectCompositeFieldSubMenu />
|
||||
) : (
|
||||
<ObjectFilterDropdownFilterSelect />
|
||||
)
|
||||
}
|
||||
dropdownHotkeyScope={{ scope: advancedFilterDropdownId }}
|
||||
dropdownOffset={{ y: 8, x: 0 }}
|
||||
dropdownPlacement="bottom-start"
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
@ -1,14 +0,0 @@
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
export const useAdvancedFilterDropdown = (viewFilterId?: string) => {
|
||||
const advancedFilterDropdownId = `advanced-filter-view-filter-field-${viewFilterId}`;
|
||||
|
||||
const { closeDropdown: closeAdvancedFilterDropdown } = useDropdown(
|
||||
advancedFilterDropdownId,
|
||||
);
|
||||
|
||||
return {
|
||||
closeAdvancedFilterDropdown,
|
||||
advancedFilterDropdownId,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,14 @@
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
export const useAdvancedFilterFieldSelectDropdown = (viewFilterId?: string) => {
|
||||
const advancedFilterFieldSelectDropdownId = `advanced-filter-view-filter-field-${viewFilterId}`;
|
||||
|
||||
const { closeDropdown: closeAdvancedFilterFieldSelectDropdown } = useDropdown(
|
||||
advancedFilterFieldSelectDropdownId,
|
||||
);
|
||||
|
||||
return {
|
||||
closeAdvancedFilterFieldSelectDropdown,
|
||||
advancedFilterFieldSelectDropdownId,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,110 @@
|
||||
import { useGetFieldMetadataItemById } from '@/object-metadata/hooks/useGetFieldMetadataItemById';
|
||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
|
||||
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||
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 { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
|
||||
import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope';
|
||||
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type SelectFilterParams = {
|
||||
fieldMetadataItemId: string;
|
||||
recordFilterId: string;
|
||||
subFieldName?: string | null | undefined;
|
||||
};
|
||||
|
||||
export const useSelectFieldUsedInAdvancedFilterDropdown = () => {
|
||||
const setSelectedOperandInDropdown = useSetRecoilComponentStateV2(
|
||||
selectedOperandInDropdownComponentState,
|
||||
);
|
||||
|
||||
const setFieldMetadataItemIdUsedInDropdown = useSetRecoilComponentStateV2(
|
||||
fieldMetadataItemIdUsedInDropdownComponentState,
|
||||
);
|
||||
|
||||
const setObjectFilterDropdownSearchInput = useSetRecoilComponentStateV2(
|
||||
objectFilterDropdownSearchInputComponentState,
|
||||
);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
const { applyRecordFilter } = useApplyRecordFilter();
|
||||
|
||||
const { getFieldMetadataItemById } = useGetFieldMetadataItemById();
|
||||
|
||||
const setSubFieldNameUsedInDropdown = useSetRecoilComponentStateV2(
|
||||
subFieldNameUsedInDropdownComponentState,
|
||||
);
|
||||
|
||||
const selectFieldUsedInAdvancedFilterDropdown = ({
|
||||
fieldMetadataItemId,
|
||||
recordFilterId,
|
||||
subFieldName,
|
||||
}: SelectFilterParams) => {
|
||||
setFieldMetadataItemIdUsedInDropdown(fieldMetadataItemId);
|
||||
|
||||
const fieldMetadataItem = getFieldMetadataItemById(fieldMetadataItemId);
|
||||
|
||||
if (!isDefined(fieldMetadataItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
fieldMetadataItem.type === 'RELATION' ||
|
||||
fieldMetadataItem.type === 'SELECT'
|
||||
) {
|
||||
setHotkeyScope(SingleRecordPickerHotkeyScope.SingleRecordPicker);
|
||||
}
|
||||
|
||||
const filterType = getFilterTypeFromFieldType(fieldMetadataItem.type);
|
||||
|
||||
const firstOperand = getRecordFilterOperands({
|
||||
filterType,
|
||||
})[0];
|
||||
|
||||
setSelectedOperandInDropdown(firstOperand);
|
||||
|
||||
const { value, displayValue } = getInitialFilterValue(
|
||||
filterType,
|
||||
firstOperand,
|
||||
);
|
||||
|
||||
const existingRecordFilter = currentRecordFilters.find(
|
||||
(recordFilter) => recordFilter.id === recordFilterId,
|
||||
);
|
||||
|
||||
applyRecordFilter({
|
||||
id: recordFilterId,
|
||||
fieldMetadataId: fieldMetadataItem.id,
|
||||
displayValue,
|
||||
operand: firstOperand,
|
||||
value,
|
||||
recordFilterGroupId: existingRecordFilter?.recordFilterGroupId,
|
||||
type: filterType,
|
||||
label: fieldMetadataItem.label,
|
||||
subFieldName,
|
||||
});
|
||||
|
||||
if (isDefined(subFieldName)) {
|
||||
setSubFieldNameUsedInDropdown(subFieldName);
|
||||
}
|
||||
|
||||
setObjectFilterDropdownSearchInput('');
|
||||
};
|
||||
|
||||
return {
|
||||
selectFieldUsedInAdvancedFilterDropdown,
|
||||
};
|
||||
};
|
||||
@ -27,11 +27,11 @@ export const MultipleFiltersDropdownContent = ({
|
||||
const shouldShowCompositeSelectionSubMenu =
|
||||
objectFilterDropdownIsSelectingCompositeField;
|
||||
|
||||
const shoudShowFilterInput = objectFilterDropdownFilterIsSelected;
|
||||
const shouldShowFilterInput = objectFilterDropdownFilterIsSelected;
|
||||
|
||||
return (
|
||||
<>
|
||||
{shoudShowFilterInput ? (
|
||||
{shouldShowFilterInput ? (
|
||||
<ObjectFilterOperandSelectAndInput
|
||||
filterDropdownId={filterDropdownId}
|
||||
/>
|
||||
|
||||
@ -2,7 +2,6 @@ import styled from '@emotion/styled';
|
||||
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
|
||||
import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown';
|
||||
import { AdvancedFilterButton } from '@/object-record/object-filter-dropdown/components/AdvancedFilterButton';
|
||||
import { ObjectFilterDropdownFilterSelectMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem';
|
||||
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
|
||||
@ -21,7 +20,6 @@ import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { FeatureFlagKey } from '~/generated/graphql';
|
||||
|
||||
import { useSelectFilterUsedInDropdown } from '@/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown';
|
||||
import { advancedFilterViewFilterIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterIdComponentState';
|
||||
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
|
||||
import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope';
|
||||
import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext';
|
||||
@ -65,17 +63,9 @@ export const ObjectFilterDropdownFilterSelect = ({
|
||||
}: ObjectFilterDropdownFilterSelectProps) => {
|
||||
const { recordIndexId } = useRecordIndexContextOrThrow();
|
||||
|
||||
const advancedFilterViewFilterId = useRecoilComponentValueV2(
|
||||
advancedFilterViewFilterIdComponentState,
|
||||
);
|
||||
|
||||
const [objectFilterDropdownSearchInput, setObjectFilterDropdownSearchInput] =
|
||||
useRecoilComponentStateV2(objectFilterDropdownSearchInputComponentState);
|
||||
|
||||
const { closeAdvancedFilterDropdown } = useAdvancedFilterDropdown(
|
||||
advancedFilterViewFilterId,
|
||||
);
|
||||
|
||||
const { filterableFieldMetadataItems } =
|
||||
useFilterableFieldMetadataItemsInRecordIndexContext();
|
||||
|
||||
@ -136,11 +126,9 @@ export const ObjectFilterDropdownFilterSelect = ({
|
||||
});
|
||||
|
||||
setFieldMetadataItemIdUsedInDropdown(fieldMetadataItemId);
|
||||
|
||||
closeAdvancedFilterDropdown();
|
||||
};
|
||||
|
||||
const shoudShowSeparator =
|
||||
const shouldShowSeparator =
|
||||
visibleColumnsFieldMetadataItems.length > 0 &&
|
||||
hiddenColumnsFieldMetadataItems.length > 0;
|
||||
|
||||
@ -186,7 +174,7 @@ export const ObjectFilterDropdownFilterSelect = ({
|
||||
</SelectableItem>
|
||||
),
|
||||
)}
|
||||
{shoudShowSeparator && <DropdownMenuSeparator />}
|
||||
{shouldShowSeparator && <DropdownMenuSeparator />}
|
||||
{hiddenColumnsFieldMetadataItems.map(
|
||||
(hiddenFieldMetadataItem, index) => (
|
||||
<SelectableItem
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||
import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown';
|
||||
|
||||
import { advancedFilterViewFilterGroupIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterGroupIdComponentState';
|
||||
import { advancedFilterViewFilterIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterIdComponentState';
|
||||
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
|
||||
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
|
||||
import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState';
|
||||
@ -15,8 +11,6 @@ import { selectedOperandInDropdownComponentState } from '@/object-record/object-
|
||||
import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState';
|
||||
import { getCompositeSubFieldLabel } from '@/object-record/object-filter-dropdown/utils/getCompositeSubFieldLabel';
|
||||
import { getFilterableFieldTypeLabel } from '@/object-record/object-filter-dropdown/utils/getFilterableFieldTypeLabel';
|
||||
import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue';
|
||||
import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { findDuplicateRecordFilterInNonAdvancedRecordFilters } from '@/object-record/record-filter/utils/findDuplicateRecordFilterInNonAdvancedRecordFilters';
|
||||
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
|
||||
@ -72,20 +66,6 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => {
|
||||
objectFilterDropdownSearchInputComponentState,
|
||||
);
|
||||
|
||||
const advancedFilterViewFilterId = useRecoilComponentValueV2(
|
||||
advancedFilterViewFilterIdComponentState,
|
||||
);
|
||||
|
||||
const advancedFilterViewFilterGroupId = useRecoilComponentValueV2(
|
||||
advancedFilterViewFilterGroupIdComponentState,
|
||||
);
|
||||
|
||||
const { applyRecordFilter } = useApplyRecordFilter();
|
||||
|
||||
const { closeAdvancedFilterDropdown } = useAdvancedFilterDropdown(
|
||||
advancedFilterViewFilterId,
|
||||
);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
@ -109,30 +89,6 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => {
|
||||
subFieldName: subFieldName,
|
||||
})[0];
|
||||
|
||||
if (
|
||||
isDefined(advancedFilterViewFilterId) &&
|
||||
isDefined(advancedFilterViewFilterGroupId)
|
||||
) {
|
||||
closeAdvancedFilterDropdown();
|
||||
|
||||
const { value, displayValue } = getInitialFilterValue(
|
||||
type,
|
||||
defaultOperand,
|
||||
);
|
||||
|
||||
applyRecordFilter({
|
||||
id: advancedFilterViewFilterId,
|
||||
fieldMetadataId: fieldMetadataItem.id,
|
||||
value,
|
||||
operand: defaultOperand,
|
||||
displayValue,
|
||||
type,
|
||||
label: fieldMetadataItem.label,
|
||||
recordFilterGroupId: advancedFilterViewFilterGroupId,
|
||||
subFieldName: subFieldName,
|
||||
});
|
||||
}
|
||||
|
||||
setFieldMetadataItemIdUsedInDropdown(fieldMetadataItem.id);
|
||||
|
||||
setSubFieldNameUsedInDropdown(subFieldName);
|
||||
@ -152,9 +108,7 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => {
|
||||
duplicateFilterInCurrentRecordFilters,
|
||||
);
|
||||
|
||||
const isSimpleFilter = !isDefined(advancedFilterViewFilterId);
|
||||
|
||||
if (isSimpleFilter && filterIsAlreadyInCurrentRecordFilters) {
|
||||
if (filterIsAlreadyInCurrentRecordFilters) {
|
||||
setSelectedFilter({
|
||||
...duplicateFilterInCurrentRecordFilters,
|
||||
});
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown';
|
||||
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
|
||||
import { advancedFilterViewFilterIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterIdComponentState';
|
||||
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
|
||||
import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState';
|
||||
|
||||
@ -61,16 +59,8 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
||||
selectedOperandInDropdownComponentState,
|
||||
);
|
||||
|
||||
const advancedFilterViewFilterId = useRecoilComponentValueV2(
|
||||
advancedFilterViewFilterIdComponentState,
|
||||
);
|
||||
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
const { closeAdvancedFilterDropdown } = useAdvancedFilterDropdown(
|
||||
advancedFilterViewFilterId,
|
||||
);
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
);
|
||||
@ -80,8 +70,6 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
||||
);
|
||||
|
||||
const handleSelectFilter = (fieldMetadataItem: FieldMetadataItem) => {
|
||||
closeAdvancedFilterDropdown();
|
||||
|
||||
setFieldMetadataItemIdUsedInDropdown(fieldMetadataItem.id);
|
||||
|
||||
const filterType = getFilterTypeFromFieldType(fieldMetadataItem.type);
|
||||
@ -106,9 +94,7 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
||||
duplicateFilterInCurrentRecordFilters,
|
||||
);
|
||||
|
||||
const isSimpleFilter = !isDefined(advancedFilterViewFilterId);
|
||||
|
||||
if (isSimpleFilter && filterIsAlreadyInCurrentRecordFilters) {
|
||||
if (filterIsAlreadyInCurrentRecordFilters) {
|
||||
setSelectedFilter({
|
||||
...duplicateFilterInCurrentRecordFilters,
|
||||
});
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
|
||||
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { isCompositeField } from '@/object-record/object-filter-dropdown/utils/isCompositeField';
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { MenuItemSelect, useIcons } from 'twenty-ui';
|
||||
|
||||
export type ObjectFilterDropdownFilterSelectMenuItemV2Props = {
|
||||
fieldMetadataItemToSelect: FieldMetadataItem;
|
||||
onClick: (selectedFieldMetadataItem: FieldMetadataItem) => void;
|
||||
};
|
||||
|
||||
export const ObjectFilterDropdownFilterSelectMenuItemV2 = ({
|
||||
fieldMetadataItemToSelect,
|
||||
onClick,
|
||||
}: ObjectFilterDropdownFilterSelectMenuItemV2Props) => {
|
||||
const { isSelectedItemIdSelector, resetSelectedItem } = useSelectableList(
|
||||
OBJECT_FILTER_DROPDOWN_ID,
|
||||
);
|
||||
|
||||
const isSelectedItem = useRecoilValue(
|
||||
isSelectedItemIdSelector(fieldMetadataItemToSelect.id),
|
||||
);
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const Icon = getIcon(fieldMetadataItemToSelect.icon);
|
||||
|
||||
const shouldShowSubMenu = isCompositeField(fieldMetadataItemToSelect.type);
|
||||
|
||||
const handleClick = () => {
|
||||
resetSelectedItem();
|
||||
|
||||
onClick(fieldMetadataItemToSelect);
|
||||
};
|
||||
|
||||
return (
|
||||
<MenuItemSelect
|
||||
selected={false}
|
||||
hovered={isSelectedItem}
|
||||
onClick={handleClick}
|
||||
LeftIcon={Icon}
|
||||
text={fieldMetadataItemToSelect.label}
|
||||
hasSubMenu={shouldShowSubMenu}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -1,7 +1,5 @@
|
||||
import { useGetFieldMetadataItemById } from '@/object-metadata/hooks/useGetFieldMetadataItemById';
|
||||
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
|
||||
import { advancedFilterViewFilterGroupIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterGroupIdComponentState';
|
||||
import { advancedFilterViewFilterIdComponentState } from '@/object-record/object-filter-dropdown/states/advancedFilterViewFilterIdComponentState';
|
||||
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
|
||||
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
|
||||
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
|
||||
@ -11,7 +9,6 @@ import { getRecordFilterOperands } from '@/object-record/record-filter/utils/get
|
||||
import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope';
|
||||
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { v4 } from 'uuid';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@ -36,16 +33,6 @@ export const useSelectFilterUsedInDropdown = (componentInstanceId?: string) => {
|
||||
componentInstanceId,
|
||||
);
|
||||
|
||||
const advancedFilterViewFilterGroupId = useRecoilComponentValueV2(
|
||||
advancedFilterViewFilterGroupIdComponentState,
|
||||
componentInstanceId,
|
||||
);
|
||||
|
||||
const advancedFilterViewFilterId = useRecoilComponentValueV2(
|
||||
advancedFilterViewFilterIdComponentState,
|
||||
componentInstanceId,
|
||||
);
|
||||
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
const { applyRecordFilter } = useApplyRecordFilter(componentInstanceId);
|
||||
@ -83,16 +70,13 @@ export const useSelectFilterUsedInDropdown = (componentInstanceId?: string) => {
|
||||
firstOperand,
|
||||
);
|
||||
|
||||
const isAdvancedFilter = isDefined(advancedFilterViewFilterId);
|
||||
|
||||
if (isAdvancedFilter || value !== '') {
|
||||
if (value !== '') {
|
||||
applyRecordFilter({
|
||||
id: advancedFilterViewFilterId ?? v4(),
|
||||
id: v4(),
|
||||
fieldMetadataId: fieldMetadataItem.id,
|
||||
displayValue,
|
||||
operand: firstOperand,
|
||||
value,
|
||||
recordFilterGroupId: advancedFilterViewFilterGroupId,
|
||||
type: filterType,
|
||||
label: fieldMetadataItem.label,
|
||||
});
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const advancedFilterViewFilterGroupIdComponentState =
|
||||
createComponentStateV2<string | undefined>({
|
||||
key: 'advancedFilterViewFilterGroupIdComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
|
||||
});
|
||||
@ -1,10 +0,0 @@
|
||||
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const advancedFilterViewFilterIdComponentState = createComponentStateV2<
|
||||
string | undefined
|
||||
>({
|
||||
key: 'advancedFilterViewFilterIdComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
|
||||
});
|
||||
Reference in New Issue
Block a user