From ca906bbf6b83af751406a3d960efcd4e5a83fb27 Mon Sep 17 00:00:00 2001
From: nitin <142569587+ehconitin@users.noreply.github.com>
Date: Fri, 27 Sep 2024 17:50:21 +0530
Subject: [PATCH] 5922 - UI Overlap and State Persistence in Filter Menus
(#7270)
fixes #5922
https://github.com/user-attachments/assets/07d088da-cefb-4d87-9016-e14cef18567d
---
.../MultipleFiltersDropdownButton.tsx | 11 +-
.../MultipleFiltersDropdownContent.tsx | 128 ++++++++++--------
.../ObjectFilterDropdownOperandButton.tsx | 8 --
.../components/ObjectSortDropdownButton.tsx | 118 +++++++++-------
.../EditableFilterDropdownButton.tsx | 6 +
5 files changed, 154 insertions(+), 117 deletions(-)
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx
index 885a6c8eb..b88f421c9 100644
--- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton.tsx
@@ -2,6 +2,7 @@ import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdow
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
+import { useCallback } from 'react';
import { MultipleFiltersButton } from './MultipleFiltersButton';
import { MultipleFiltersDropdownContent } from './MultipleFiltersDropdownContent';
@@ -13,12 +14,18 @@ type MultipleFiltersDropdownButtonProps = {
export const MultipleFiltersDropdownButton = ({
hotkeyScope,
}: MultipleFiltersDropdownButtonProps) => {
- const { resetFilter } = useFilterDropdown();
+ const { resetFilter, setIsObjectFilterDropdownOperandSelectUnfolded } =
+ useFilterDropdown();
+
+ const handleDropdownClose = useCallback(() => {
+ resetFilter();
+ setIsObjectFilterDropdownOperandSelectUnfolded(false);
+ }, [resetFilter, setIsObjectFilterDropdownOperandSelectUnfolded]);
return (
}
dropdownComponents={}
dropdownHotkeyScope={hotkeyScope}
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx
index ec3df12f0..7638532ee 100644
--- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent.tsx
@@ -1,11 +1,9 @@
-import { useRecoilValue } from 'recoil';
-
+import { ObjectFilterDropdownRatingInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput';
import { ObjectFilterDropdownSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownSearchInput';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
-import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
-
-import { ObjectFilterDropdownRatingInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput';
+import styled from '@emotion/styled';
+import { useRecoilValue } from 'recoil';
import { MultipleFiltersDropdownFilterOnFilterChangedEffect } from './MultipleFiltersDropdownFilterOnFilterChangedEffect';
import { ObjectFilterDropdownDateInput } from './ObjectFilterDropdownDateInput';
import { ObjectFilterDropdownFilterSelect } from './ObjectFilterDropdownFilterSelect';
@@ -16,6 +14,21 @@ import { ObjectFilterDropdownOptionSelect } from './ObjectFilterDropdownOptionSe
import { ObjectFilterDropdownRecordSelect } from './ObjectFilterDropdownRecordSelect';
import { ObjectFilterDropdownTextSearchInput } from './ObjectFilterDropdownTextSearchInput';
+const StyledContainer = styled.div`
+ position: relative;
+`;
+
+const StyledOperandSelectContainer = styled.div`
+ background: ${({ theme }) => theme.background.secondary};
+ box-shadow: ${({ theme }) => theme.boxShadow.light};
+ border-radius: ${({ theme }) => theme.border.radius.md};
+ left: 10px;
+ position: absolute;
+ top: 10px;
+ width: 100%;
+ z-index: 1000;
+`;
+
type MultipleFiltersDropdownContentProps = {
filterDropdownId?: string;
};
@@ -24,20 +37,23 @@ export const MultipleFiltersDropdownContent = ({
filterDropdownId,
}: MultipleFiltersDropdownContentProps) => {
const {
- isObjectFilterDropdownOperandSelectUnfoldedState,
filterDefinitionUsedInDropdownState,
selectedOperandInDropdownState,
+ isObjectFilterDropdownOperandSelectUnfoldedState,
} = useFilterDropdown({ filterDropdownId });
const isObjectFilterDropdownOperandSelectUnfolded = useRecoilValue(
isObjectFilterDropdownOperandSelectUnfoldedState,
);
+
const filterDefinitionUsedInDropdown = useRecoilValue(
filterDefinitionUsedInDropdownState,
);
+
const selectedOperandInDropdown = useRecoilValue(
selectedOperandInDropdownState,
);
+
const isEmptyOperand =
selectedOperandInDropdown &&
[ViewFilterOperand.IsEmpty, ViewFilterOperand.IsNotEmpty].includes(
@@ -45,64 +61,64 @@ export const MultipleFiltersDropdownContent = ({
);
return (
- <>
+
{!filterDefinitionUsedInDropdown ? (
- ) : isObjectFilterDropdownOperandSelectUnfolded ? (
-
- ) : isEmptyOperand ? (
-
) : (
- selectedOperandInDropdown && (
- <>
-
-
- {[
- 'TEXT',
- 'EMAIL',
- 'EMAILS',
- 'PHONE',
- 'FULL_NAME',
- 'LINK',
- 'LINKS',
- 'ADDRESS',
- 'ACTOR',
- 'ARRAY',
- 'PHONES',
- ].includes(filterDefinitionUsedInDropdown.type) && (
-
- )}
- {['NUMBER', 'CURRENCY'].includes(
- filterDefinitionUsedInDropdown.type,
- ) && }
- {filterDefinitionUsedInDropdown.type === 'RATING' && (
-
- )}
- {['DATE_TIME', 'DATE'].includes(
- filterDefinitionUsedInDropdown.type,
- ) && }
- {filterDefinitionUsedInDropdown.type === 'RELATION' && (
- <>
-
-
-
- >
- )}
- {filterDefinitionUsedInDropdown.type === 'SELECT' && (
- <>
-
-
-
- >
- )}
- >
- )
+ <>
+
+ {isObjectFilterDropdownOperandSelectUnfolded && (
+
+
+
+ )}
+ {!isEmptyOperand && selectedOperandInDropdown && (
+ <>
+ {[
+ 'TEXT',
+ 'EMAIL',
+ 'EMAILS',
+ 'PHONE',
+ 'FULL_NAME',
+ 'LINK',
+ 'LINKS',
+ 'ADDRESS',
+ 'ACTOR',
+ 'ARRAY',
+ 'PHONES',
+ ].includes(filterDefinitionUsedInDropdown.type) && (
+
+ )}
+ {['NUMBER', 'CURRENCY'].includes(
+ filterDefinitionUsedInDropdown.type,
+ ) && }
+ {filterDefinitionUsedInDropdown.type === 'RATING' && (
+
+ )}
+ {['DATE_TIME', 'DATE'].includes(
+ filterDefinitionUsedInDropdown.type,
+ ) && }
+ {filterDefinitionUsedInDropdown.type === 'RELATION' && (
+ <>
+
+
+ >
+ )}
+ {filterDefinitionUsedInDropdown.type === 'SELECT' && (
+ <>
+
+
+ >
+ )}
+ >
+ )}
+ >
)}
- >
+
);
};
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx
index 4aa675ec3..3931c7654 100644
--- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandButton.tsx
@@ -10,19 +10,11 @@ export const ObjectFilterDropdownOperandButton = () => {
const {
selectedOperandInDropdownState,
setIsObjectFilterDropdownOperandSelectUnfolded,
- isObjectFilterDropdownOperandSelectUnfoldedState,
} = useFilterDropdown();
const selectedOperandInDropdown = useRecoilValue(
selectedOperandInDropdownState,
);
- const isObjectFilterDropdownOperandSelectUnfolded = useRecoilValue(
- isObjectFilterDropdownOperandSelectUnfoldedState,
- );
-
- if (isObjectFilterDropdownOperandSelectUnfolded) {
- return null;
- }
return (
theme.background.secondary};
+ box-shadow: ${({ theme }) => theme.boxShadow.light};
+ border-radius: ${({ theme }) => theme.border.radius.md};
+ left: 10px;
+ position: absolute;
+ top: 10px;
+ width: 100%;
+ z-index: 1000;
+`;
+
export type ObjectSortDropdownButtonProps = {
sortDropdownId: string;
hotkeyScope: HotkeyScope;
@@ -95,60 +110,61 @@ export const ObjectSortDropdownButton = ({
}
dropdownComponents={
<>
- {isSortDirectionMenuUnfolded ? (
-
- {SORT_DIRECTIONS.map((sortOrder, index) => (
-
- ) : (
- <>
- setIsSortDirectionMenuUnfolded(true)}
- >
- {selectedSortDirection === 'asc' ? 'Ascending' : 'Descending'}
-
-
- setObjectSortDropdownSearchInput(event.target.value)
- }
- />
+ {isSortDirectionMenuUnfolded && (
+
- {[...availableSortDefinitions]
- .sort((a, b) => a.label.localeCompare(b.label))
- .filter((item) =>
- item.label
- .toLocaleLowerCase()
- .includes(
- objectSortDropdownSearchInput.toLocaleLowerCase(),
- ),
- )
- .map((availableSortDefinition, index) => (
-
- >
+
)}
+
+ setIsSortDirectionMenuUnfolded(true)}
+ >
+ {selectedSortDirection === 'asc' ? 'Ascending' : 'Descending'}
+
+
+ setObjectSortDropdownSearchInput(event.target.value)
+ }
+ />
+
+ {[...availableSortDefinitions]
+ .sort((a, b) => a.label.localeCompare(b.label))
+ .filter((item) =>
+ item.label
+ .toLocaleLowerCase()
+ .includes(
+ objectSortDropdownSearchInput.toLocaleLowerCase(),
+ ),
+ )
+ .map((availableSortDefinition, index) => (
+ {
+ setObjectSortDropdownSearchInput('');
+ handleAddSort(availableSortDefinition);
+ }}
+ LeftIcon={getIcon(availableSortDefinition.iconName)}
+ text={availableSortDefinition.label}
+ />
+ ))}
+
+
>
}
onClose={handleDropdownButtonClose}
diff --git a/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx b/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx
index bbaa9af31..45c974eca 100644
--- a/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx
+++ b/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx
@@ -29,6 +29,7 @@ export const EditableFilterDropdownButton = ({
setFilterDefinitionUsedInDropdown,
setSelectedOperandInDropdown,
setSelectedFilter,
+ setIsObjectFilterDropdownOperandSelectUnfolded,
} = useFilterDropdown({
filterDropdownId: viewFilterDropdownId,
});
@@ -79,6 +80,10 @@ export const EditableFilterDropdownButton = ({
}
}, [viewFilter, deleteCombinedViewFilter]);
+ const handleDropdownClose = useCallback(() => {
+ setIsObjectFilterDropdownOperandSelectUnfolded(false);
+ }, [setIsObjectFilterDropdownOperandSelectUnfolded]);
+
return (
);
};