diff --git a/.github/workflows/ci-front.yaml b/.github/workflows/ci-front.yaml
index 51bb90329..b95960b42 100644
--- a/.github/workflows/ci-front.yaml
+++ b/.github/workflows/ci-front.yaml
@@ -11,13 +11,8 @@ jobs:
REACT_APP_SERVER_BASE_URL: http://localhost:3000
steps:
- uses: actions/checkout@v3
- if: github.event_name == 'push'
with:
ref: ${{ github.head_ref || github.ref_name }}
- - uses: actions/checkout@v3
- if: github.event_name == 'pull_request_target'
- with:
- ref: "refs/pull/${{ github.event.number }}/merge"
- name: Setup Node.js
uses: actions/setup-node@v3
with:
diff --git a/front/src/modules/ui/dropdown/components/DropdownButton.tsx b/front/src/modules/ui/dropdown/components/DropdownButton.tsx
index eb5214784..edfe28fd5 100644
--- a/front/src/modules/ui/dropdown/components/DropdownButton.tsx
+++ b/front/src/modules/ui/dropdown/components/DropdownButton.tsx
@@ -1,16 +1,13 @@
-import { useEffect, useRef } from 'react';
+import { useRef } from 'react';
import { Keys } from 'react-hotkeys-hook';
import { flip, offset, Placement, useFloating } from '@floating-ui/react';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
-import { useRecoilScopedFamilyState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedFamilyState';
-import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { HotkeyEffect } from '../../utilities/hotkey/components/HotkeyEffect';
import { useDropdownButton } from '../hooks/useDropdownButton';
-import { dropdownButtonCustomHotkeyScopeScopedFamilyState } from '../states/dropdownButtonCustomHotkeyScopeScopedFamilyState';
-import { DropdownRecoilScopeContext } from '../states/recoil-scope-contexts/DropdownRecoilScopeContext';
+import { useInternalHotkeyScopeManagement } from '../hooks/useInternalHotkeyScopeManagement';
type OwnProps = {
buttonComponents: JSX.Element | JSX.Element[];
@@ -57,22 +54,10 @@ export function DropdownButton({
},
});
- const [dropdownButtonCustomHotkeyScope, setDropdownButtonCustomHotkeyScope] =
- useRecoilScopedFamilyState(
- dropdownButtonCustomHotkeyScopeScopedFamilyState,
- dropdownId,
- DropdownRecoilScopeContext,
- );
-
- useEffect(() => {
- if (!isDeeplyEqual(dropdownButtonCustomHotkeyScope, dropdownHotkeyScope)) {
- setDropdownButtonCustomHotkeyScope(dropdownHotkeyScope);
- }
- }, [
+ useInternalHotkeyScopeManagement({
+ dropdownId,
dropdownHotkeyScope,
- dropdownButtonCustomHotkeyScope,
- setDropdownButtonCustomHotkeyScope,
- ]);
+ });
return (
diff --git a/front/src/modules/ui/view-bar/components/DropdownMenuContainer.tsx b/front/src/modules/ui/dropdown/components/DropdownMenuContainer.tsx
similarity index 100%
rename from front/src/modules/ui/view-bar/components/DropdownMenuContainer.tsx
rename to front/src/modules/ui/dropdown/components/DropdownMenuContainer.tsx
diff --git a/front/src/modules/ui/dropdown/components/StyledDropdownButtonContainer.tsx b/front/src/modules/ui/dropdown/components/StyledDropdownButtonContainer.tsx
new file mode 100644
index 000000000..20c4f0f70
--- /dev/null
+++ b/front/src/modules/ui/dropdown/components/StyledDropdownButtonContainer.tsx
@@ -0,0 +1,27 @@
+import styled from '@emotion/styled';
+
+type StyledDropdownButtonProps = {
+ isUnfolded: boolean;
+ isActive?: boolean;
+};
+
+export const StyledDropdownButtonContainer = styled.div`
+ align-items: center;
+ background: ${({ theme }) => theme.background.primary};
+ border-radius: ${({ theme }) => theme.border.radius.sm};
+ color: ${({ isActive, theme, color }) =>
+ color ?? (isActive ? theme.color.blue : 'none')};
+ cursor: pointer;
+ display: flex;
+ filter: ${(props) => (props.isUnfolded ? 'brightness(0.95)' : 'none')};
+
+ padding: ${({ theme }) => theme.spacing(1)};
+ padding-left: ${({ theme }) => theme.spacing(2)};
+
+ padding-right: ${({ theme }) => theme.spacing(2)};
+ user-select: none;
+
+ &:hover {
+ filter: brightness(0.95);
+ }
+`;
diff --git a/front/src/modules/ui/dropdown/hooks/useDropdownButton.ts b/front/src/modules/ui/dropdown/hooks/useDropdownButton.ts
index 895626182..939959534 100644
--- a/front/src/modules/ui/dropdown/hooks/useDropdownButton.ts
+++ b/front/src/modules/ui/dropdown/hooks/useDropdownButton.ts
@@ -1,7 +1,7 @@
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { useRecoilScopedFamilyState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedFamilyState';
-import { dropdownButtonCustomHotkeyScopeScopedFamilyState } from '../states/dropdownButtonCustomHotkeyScopeScopedFamilyState';
+import { dropdownButtonHotkeyScopeScopedFamilyState } from '../states/dropdownButtonHotkeyScopeScopedFamilyState';
import { isDropdownButtonOpenScopedFamilyState } from '../states/isDropdownButtonOpenScopedFamilyState';
import { DropdownRecoilScopeContext } from '../states/recoil-scope-contexts/DropdownRecoilScopeContext';
@@ -18,8 +18,8 @@ export function useDropdownButton({ dropdownId }: { dropdownId: string }) {
DropdownRecoilScopeContext,
);
- const [dropdownButtonCustomHotkeyScope] = useRecoilScopedFamilyState(
- dropdownButtonCustomHotkeyScopeScopedFamilyState,
+ const [dropdownButtonHotkeyScope] = useRecoilScopedFamilyState(
+ dropdownButtonHotkeyScopeScopedFamilyState,
dropdownId,
DropdownRecoilScopeContext,
);
@@ -32,10 +32,10 @@ export function useDropdownButton({ dropdownId }: { dropdownId: string }) {
function openDropdownButton() {
setIsDropdownButtonOpen(true);
- if (dropdownButtonCustomHotkeyScope) {
+ if (dropdownButtonHotkeyScope) {
setHotkeyScopeAndMemorizePreviousScope(
- dropdownButtonCustomHotkeyScope.scope,
- dropdownButtonCustomHotkeyScope.customScopes,
+ dropdownButtonHotkeyScope.scope,
+ dropdownButtonHotkeyScope.customScopes,
);
}
}
diff --git a/front/src/modules/ui/dropdown/hooks/useInternalHotkeyScopeManagement.ts b/front/src/modules/ui/dropdown/hooks/useInternalHotkeyScopeManagement.ts
new file mode 100644
index 000000000..51052c5a6
--- /dev/null
+++ b/front/src/modules/ui/dropdown/hooks/useInternalHotkeyScopeManagement.ts
@@ -0,0 +1,33 @@
+import { useEffect } from 'react';
+
+import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
+import { useRecoilScopedFamilyState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedFamilyState';
+import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
+
+import { dropdownButtonHotkeyScopeScopedFamilyState } from '../states/dropdownButtonHotkeyScopeScopedFamilyState';
+import { DropdownRecoilScopeContext } from '../states/recoil-scope-contexts/DropdownRecoilScopeContext';
+
+export const useInternalHotkeyScopeManagement = ({
+ dropdownId,
+ dropdownHotkeyScope,
+}: {
+ dropdownId: string;
+ dropdownHotkeyScope?: HotkeyScope;
+}) => {
+ const [dropdownButtonHotkeyScope, setDropdownButtonHotkeyScope] =
+ useRecoilScopedFamilyState(
+ dropdownButtonHotkeyScopeScopedFamilyState,
+ dropdownId,
+ DropdownRecoilScopeContext,
+ );
+
+ useEffect(() => {
+ if (!isDeeplyEqual(dropdownButtonHotkeyScope, dropdownHotkeyScope)) {
+ setDropdownButtonHotkeyScope(dropdownHotkeyScope);
+ }
+ }, [
+ dropdownHotkeyScope,
+ dropdownButtonHotkeyScope,
+ setDropdownButtonHotkeyScope,
+ ]);
+};
diff --git a/front/src/modules/ui/dropdown/states/dropdownButtonCustomHotkeyScopeScopedFamilyState.ts b/front/src/modules/ui/dropdown/states/dropdownButtonHotkeyScopeScopedFamilyState.ts
similarity index 57%
rename from front/src/modules/ui/dropdown/states/dropdownButtonCustomHotkeyScopeScopedFamilyState.ts
rename to front/src/modules/ui/dropdown/states/dropdownButtonHotkeyScopeScopedFamilyState.ts
index 2e73d7f82..67a5952cc 100644
--- a/front/src/modules/ui/dropdown/states/dropdownButtonCustomHotkeyScopeScopedFamilyState.ts
+++ b/front/src/modules/ui/dropdown/states/dropdownButtonHotkeyScopeScopedFamilyState.ts
@@ -2,10 +2,10 @@ import { atomFamily } from 'recoil';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
-export const dropdownButtonCustomHotkeyScopeScopedFamilyState = atomFamily<
+export const dropdownButtonHotkeyScopeScopedFamilyState = atomFamily<
HotkeyScope | null | undefined,
string
>({
- key: 'dropdownButtonCustomHotkeyScopeScopedState',
+ key: 'dropdownButtonHotkeyScopeScopedFamilyState',
default: null,
});
diff --git a/front/src/modules/ui/utilities/recoil-scope/hooks/useRecoilScopedFamilyState.ts b/front/src/modules/ui/utilities/recoil-scope/hooks/useRecoilScopedFamilyState.ts
index 4245d06b2..b7881d3dc 100644
--- a/front/src/modules/ui/utilities/recoil-scope/hooks/useRecoilScopedFamilyState.ts
+++ b/front/src/modules/ui/utilities/recoil-scope/hooks/useRecoilScopedFamilyState.ts
@@ -4,8 +4,8 @@ import { RecoilState, useRecoilState } from 'recoil';
import { RecoilScopeContext } from '../states/RecoilScopeContext';
export function useRecoilScopedFamilyState(
- recoilState: (param: string) => RecoilState,
- stateKey: string,
+ recoilState: (familyUniqueId: string) => RecoilState,
+ uniqueIdInRecoilScope: string,
SpecificContext?: Context,
) {
const recoilScopeId = useContext(SpecificContext ?? RecoilScopeContext);
@@ -13,9 +13,11 @@ export function useRecoilScopedFamilyState(
if (!recoilScopeId)
throw new Error(
`Using a scoped atom without a RecoilScope : ${
- recoilState(stateKey).key
+ recoilState('').key
}, verify that you are using a RecoilScope with a specific context if you intended to do so.`,
);
- return useRecoilState(recoilState(recoilScopeId + stateKey));
+ const familyUniqueId = recoilScopeId + uniqueIdInRecoilScope;
+
+ return useRecoilState(recoilState(familyUniqueId));
}
diff --git a/front/src/modules/ui/view-bar/components/DropdownButton.tsx b/front/src/modules/ui/view-bar/components/DropdownButton.tsx
deleted file mode 100644
index 5ede64927..000000000
--- a/front/src/modules/ui/view-bar/components/DropdownButton.tsx
+++ /dev/null
@@ -1,126 +0,0 @@
-import { ReactNode } from 'react';
-import { useTheme } from '@emotion/react';
-import styled from '@emotion/styled';
-import { Key } from 'ts-key-enum';
-
-import { IconComponent } from '@/ui/icon/types/IconComponent';
-import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
-
-import { DropdownMenuContainer } from './DropdownMenuContainer';
-
-type DropdownButtonProps = {
- anchor?: 'left' | 'right';
- label: ReactNode;
- isActive: boolean;
- children?: ReactNode;
- isUnfolded?: boolean;
- Icon?: IconComponent;
- onIsUnfoldedChange?: (newIsUnfolded: boolean) => void;
- resetState?: () => void;
- hotkeyScope: string;
- color?: string;
- menuWidth?: `${string}px` | 'auto' | number;
-};
-
-const StyledDropdownButtonContainer = styled.div`
- display: flex;
- flex-direction: column;
-`;
-
-const StyledDropdownButtonIcon = styled.div`
- display: flex;
- justify-content: center;
- margin-right: ${({ theme }) => theme.spacing(1)};
-`;
-
-type StyledDropdownButtonProps = {
- isUnfolded: boolean;
- isActive: boolean;
-};
-
-const StyledDropdownButton = styled.div`
- align-items: center;
- background: ${({ theme }) => theme.background.primary};
- border-radius: ${({ theme }) => theme.border.radius.sm};
- color: ${({ isActive, theme, color }) =>
- color ?? (isActive ? theme.color.blue : 'none')};
- cursor: pointer;
- display: flex;
- filter: ${(props) => (props.isUnfolded ? 'brightness(0.95)' : 'none')};
-
- padding: ${({ theme }) => theme.spacing(1)};
- padding-left: ${({ theme }) => theme.spacing(2)};
-
- padding-right: ${({ theme }) => theme.spacing(2)};
- user-select: none;
-
- &:hover {
- filter: brightness(0.95);
- }
-`;
-
-/**
- *
- * @deprecated use ui/dropdown/components/DropdownButton.tsx instead
- */
-function DropdownButton({
- anchor,
- label,
- isActive,
- children,
- isUnfolded = false,
- onIsUnfoldedChange,
- Icon,
- hotkeyScope,
- color,
- menuWidth,
-}: DropdownButtonProps) {
- useScopedHotkeys(
- [Key.Enter, Key.Escape],
- () => {
- onIsUnfoldedChange?.(false);
- },
- hotkeyScope,
- [onIsUnfoldedChange],
- );
-
- const onButtonClick = () => {
- onIsUnfoldedChange?.(!isUnfolded);
- };
-
- const onOutsideClick = () => {
- onIsUnfoldedChange?.(false);
- };
-
- const theme = useTheme();
-
- return (
-
-
- {Icon && (
-
- {}
-
- )}
- {label}
-
- {isUnfolded && (
-
- {children}
-
- )}
-
- );
-}
-
-export default DropdownButton;
diff --git a/front/src/modules/ui/view-bar/components/MultipleFiltersButton.tsx b/front/src/modules/ui/view-bar/components/MultipleFiltersButton.tsx
index 25e8a0aaa..3195da139 100644
--- a/front/src/modules/ui/view-bar/components/MultipleFiltersButton.tsx
+++ b/front/src/modules/ui/view-bar/components/MultipleFiltersButton.tsx
@@ -1,15 +1,54 @@
+import { Context } from 'react';
+
import { StyledHeaderDropdownButton } from '@/ui/dropdown/components/StyledHeaderDropdownButton';
import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
+import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { FilterDropdownId } from '../constants/FilterDropdownId';
+import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
+import { filterDropdownSearchInputScopedState } from '../states/filterDropdownSearchInputScopedState';
+import { isFilterDropdownOperandSelectUnfoldedScopedState } from '../states/isFilterDropdownOperandSelectUnfoldedScopedState';
+import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
-export function MultipleFiltersButton() {
+type OwnProps = {
+ context: Context;
+};
+
+export function MultipleFiltersButton({ context }: OwnProps) {
const { isDropdownButtonOpen, toggleDropdownButton } = useDropdownButton({
dropdownId: FilterDropdownId,
});
+ const [, setIsFilterDropdownOperandSelectUnfolded] = useRecoilScopedState(
+ isFilterDropdownOperandSelectUnfoldedScopedState,
+ context,
+ );
+
+ const [, setFilterDefinitionUsedInDropdown] = useRecoilScopedState(
+ filterDefinitionUsedInDropdownScopedState,
+ context,
+ );
+
+ const [, setFilterDropdownSearchInput] = useRecoilScopedState(
+ filterDropdownSearchInputScopedState,
+ context,
+ );
+
+ const [, setSelectedOperandInDropdown] = useRecoilScopedState(
+ selectedOperandInDropdownScopedState,
+ context,
+ );
+
+ const resetState = () => {
+ setIsFilterDropdownOperandSelectUnfolded(false);
+ setFilterDefinitionUsedInDropdown(null);
+ setSelectedOperandInDropdown(null);
+ setFilterDropdownSearchInput('');
+ };
+
function handleClick() {
toggleDropdownButton();
+ resetState();
}
return (
diff --git a/front/src/modules/ui/view-bar/components/MultipleFiltersDropdownButton.tsx b/front/src/modules/ui/view-bar/components/MultipleFiltersDropdownButton.tsx
index 667670264..572bcc2ee 100644
--- a/front/src/modules/ui/view-bar/components/MultipleFiltersDropdownButton.tsx
+++ b/front/src/modules/ui/view-bar/components/MultipleFiltersDropdownButton.tsx
@@ -1,15 +1,9 @@
-import { Context, useCallback, useEffect } from 'react';
+import { Context } from 'react';
import { DropdownButton } from '@/ui/dropdown/components/DropdownButton';
-import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
-import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { FilterDropdownId } from '../constants/FilterDropdownId';
-import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
-import { filterDropdownSearchInputScopedState } from '../states/filterDropdownSearchInputScopedState';
-import { isFilterDropdownOperandSelectUnfoldedScopedState } from '../states/isFilterDropdownOperandSelectUnfoldedScopedState';
-import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
import { MultipleFiltersButton } from './MultipleFiltersButton';
import { MultipleFiltersDropdownContent } from './MultipleFiltersDropdownContent';
@@ -23,52 +17,10 @@ export function MultipleFiltersDropdownButton({
context,
hotkeyScope,
}: MultipleFiltersDropdownButtonProps) {
- const [, setIsFilterDropdownOperandSelectUnfolded] = useRecoilScopedState(
- isFilterDropdownOperandSelectUnfoldedScopedState,
- context,
- );
-
- const [, setFilterDefinitionUsedInDropdown] = useRecoilScopedState(
- filterDefinitionUsedInDropdownScopedState,
- context,
- );
-
- const [, setFilterDropdownSearchInput] = useRecoilScopedState(
- filterDropdownSearchInputScopedState,
- context,
- );
-
- const [, setSelectedOperandInDropdown] = useRecoilScopedState(
- selectedOperandInDropdownScopedState,
- context,
- );
-
- const { isDropdownButtonOpen } = useDropdownButton({
- dropdownId: FilterDropdownId,
- });
-
- const resetState = useCallback(() => {
- setIsFilterDropdownOperandSelectUnfolded(false);
- setFilterDefinitionUsedInDropdown(null);
- setSelectedOperandInDropdown(null);
- setFilterDropdownSearchInput('');
- }, [
- setFilterDefinitionUsedInDropdown,
- setSelectedOperandInDropdown,
- setFilterDropdownSearchInput,
- setIsFilterDropdownOperandSelectUnfolded,
- ]);
-
- useEffect(() => {
- if (!isDropdownButtonOpen) {
- resetState();
- }
- }, [isDropdownButtonOpen, resetState]);
-
return (
}
+ buttonComponents={}
dropdownComponents={}
dropdownHotkeyScope={hotkeyScope}
/>
diff --git a/front/src/modules/ui/view-bar/components/SingleEntityFilterDropdownButton.tsx b/front/src/modules/ui/view-bar/components/SingleEntityFilterDropdownButton.tsx
index 509c2832c..11adfac23 100644
--- a/front/src/modules/ui/view-bar/components/SingleEntityFilterDropdownButton.tsx
+++ b/front/src/modules/ui/view-bar/components/SingleEntityFilterDropdownButton.tsx
@@ -3,6 +3,7 @@ import React from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
+import { DropdownMenuContainer } from '@/ui/dropdown/components/DropdownMenuContainer';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { IconChevronDown } from '@/ui/icon';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
@@ -18,7 +19,6 @@ import { filtersScopedState } from '../states/filtersScopedState';
import { isFilterDropdownUnfoldedScopedState } from '../states/isFilterDropdownUnfoldedScopedState';
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
-import { DropdownMenuContainer } from './DropdownMenuContainer';
import { FilterDropdownEntitySearchInput } from './FilterDropdownEntitySearchInput';
import { FilterDropdownEntitySelect } from './FilterDropdownEntitySelect';
import { GenericEntityFilterChip } from './GenericEntityFilterChip';
diff --git a/front/src/modules/ui/view-bar/components/UpdateViewButtonGroup.tsx b/front/src/modules/ui/view-bar/components/UpdateViewButtonGroup.tsx
index ec3d242b3..4457fe5f8 100644
--- a/front/src/modules/ui/view-bar/components/UpdateViewButtonGroup.tsx
+++ b/front/src/modules/ui/view-bar/components/UpdateViewButtonGroup.tsx
@@ -5,13 +5,13 @@ import { Key } from 'ts-key-enum';
import { Button } from '@/ui/button/components/Button';
import { ButtonGroup } from '@/ui/button/components/ButtonGroup';
+import { DropdownMenuContainer } from '@/ui/dropdown/components/DropdownMenuContainer';
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
import { IconChevronDown, IconPlus } from '@/ui/icon';
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
-import { DropdownMenuContainer } from '@/ui/view-bar/components/DropdownMenuContainer';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
diff --git a/front/src/modules/ui/view-bar/components/ViewBar.tsx b/front/src/modules/ui/view-bar/components/ViewBar.tsx
index 3dc27cd33..3f5cef062 100644
--- a/front/src/modules/ui/view-bar/components/ViewBar.tsx
+++ b/front/src/modules/ui/view-bar/components/ViewBar.tsx
@@ -35,7 +35,7 @@ export const ViewBar = ({
leftComponent={
}
diff --git a/front/src/modules/ui/view-bar/components/ViewsDropdownButton.tsx b/front/src/modules/ui/view-bar/components/ViewsDropdownButton.tsx
index 280363b10..3f8136fab 100644
--- a/front/src/modules/ui/view-bar/components/ViewsDropdownButton.tsx
+++ b/front/src/modules/ui/view-bar/components/ViewsDropdownButton.tsx
@@ -1,17 +1,14 @@
-import {
- type Context,
- type MouseEvent,
- useCallback,
- useContext,
- useEffect,
- useState,
-} from 'react';
+import { type Context, type MouseEvent, useContext } from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useRecoilCallback, useSetRecoilState } from 'recoil';
+import { DropdownButton } from '@/ui/dropdown/components/DropdownButton';
+import { StyledDropdownButtonContainer } from '@/ui/dropdown/components/StyledDropdownButtonContainer';
+import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
+import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
import {
IconChevronDown,
IconList,
@@ -21,10 +18,10 @@ import {
} from '@/ui/icon';
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
import { MOBILE_VIEWPORT } from '@/ui/theme/constants/theme';
-import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
+import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
+import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
-import DropdownButton from '@/ui/view-bar/components/DropdownButton';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
@@ -33,9 +30,9 @@ import { currentViewScopedSelector } from '@/ui/view-bar/states/selectors/curren
import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState';
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
import { viewsScopedState } from '@/ui/view-bar/states/viewsScopedState';
-import { ViewsHotkeyScope } from '@/ui/view-bar/types/ViewsHotkeyScope';
import { assertNotNull } from '~/utils/assert';
+import { ViewsDropdownId } from '../constants/ViewsDropdownId';
import { ViewBarContext } from '../contexts/ViewBarContext';
import { useRemoveView } from '../hooks/useRemoveView';
@@ -73,7 +70,7 @@ const StyledViewName = styled.span`
`;
export type ViewsDropdownButtonProps = {
- hotkeyScope: ViewsHotkeyScope;
+ hotkeyScope: HotkeyScope;
onViewEditModeChange?: () => void;
scopeContext: Context;
};
@@ -88,24 +85,24 @@ export const ViewsDropdownButton = ({
const { defaultViewName, onViewSelect } = useContext(ViewBarContext);
const recoilScopeId = useContextScopeId(scopeContext);
- const [isUnfolded, setIsUnfolded] = useState(false);
-
const currentView = useRecoilScopedValue(
currentViewScopedSelector,
scopeContext,
);
- const views = useRecoilScopedValue(viewsScopedState, scopeContext);
- const setViewEditMode = useSetRecoilState(viewEditModeState);
+ const [views] = useRecoilScopedState(viewsScopedState, scopeContext);
- const {
- goBackToPreviousHotkeyScope,
- setHotkeyScopeAndMemorizePreviousScope,
- } = usePreviousHotkeyScope();
+ const { isDropdownButtonOpen, closeDropdownButton, toggleDropdownButton } =
+ useDropdownButton({
+ dropdownId: ViewsDropdownId,
+ });
+
+ const setViewEditMode = useSetRecoilState(viewEditModeState);
const handleViewSelect = useRecoilCallback(
({ set, snapshot }) =>
async (viewId: string) => {
await onViewSelect?.(viewId);
+
const savedFilters = await snapshot.getPromise(
savedFiltersFamilyState(viewId),
);
@@ -116,26 +113,26 @@ export const ViewsDropdownButton = ({
set(filtersScopedState(recoilScopeId), savedFilters);
set(sortsScopedState(recoilScopeId), savedSorts);
set(currentViewIdScopedState(recoilScopeId), viewId);
- setIsUnfolded(false);
+ closeDropdownButton();
},
- [onViewSelect, recoilScopeId],
+ [onViewSelect, recoilScopeId, closeDropdownButton],
);
- const handleAddViewButtonClick = useCallback(() => {
+ const handleAddViewButtonClick = () => {
setViewEditMode({ mode: 'create', viewId: undefined });
onViewEditModeChange?.();
- setIsUnfolded(false);
- }, [setViewEditMode, onViewEditModeChange]);
+ closeDropdownButton();
+ };
- const handleEditViewButtonClick = useCallback(
- (event: MouseEvent, viewId: string) => {
- event.stopPropagation();
- setViewEditMode({ mode: 'edit', viewId });
- onViewEditModeChange?.();
- setIsUnfolded(false);
- },
- [setViewEditMode, onViewEditModeChange],
- );
+ const handleEditViewButtonClick = (
+ event: MouseEvent,
+ viewId: string,
+ ) => {
+ event.stopPropagation();
+ setViewEditMode({ mode: 'edit', viewId });
+ onViewEditModeChange?.();
+ closeDropdownButton();
+ };
const { removeView } = useRemoveView({ scopeContext });
@@ -146,24 +143,22 @@ export const ViewsDropdownButton = ({
event.stopPropagation();
await removeView(viewId);
- setIsUnfolded(false);
+ closeDropdownButton();
};
- useEffect(() => {
- isUnfolded
- ? setHotkeyScopeAndMemorizePreviousScope(hotkeyScope)
- : goBackToPreviousHotkeyScope();
- }, [
- hotkeyScope,
- goBackToPreviousHotkeyScope,
- isUnfolded,
- setHotkeyScopeAndMemorizePreviousScope,
- ]);
+ const handleViewButtonClick = () => {
+ toggleDropdownButton();
+ };
return (
+ dropdownId={ViewsDropdownId}
+ dropdownHotkeyScope={hotkeyScope}
+ buttonComponents={
+
{currentView?.name || defaultViewName}
@@ -171,47 +166,44 @@ export const ViewsDropdownButton = ({
ยท {views.length}
- >
+
}
- isActive={false}
- isUnfolded={isUnfolded}
- onIsUnfoldedChange={setIsUnfolded}
- anchor="left"
- hotkeyScope={hotkeyScope}
- menuWidth="auto"
- >
-
- {views.map((view) => (
-
+ handleEditViewButtonClick(event, view.id),
+ },
+ views.length > 1
+ ? {
+ Icon: IconTrash,
+ onClick: (event: MouseEvent) =>
+ handleDeleteViewButtonClick(event, view.id),
+ }
+ : null,
+ ].filter(assertNotNull)}
+ onClick={() => handleViewSelect(view.id)}
+ LeftIcon={IconList}
+ text={view.name}
+ />
+ ))}
+
+
+
+
+
+
+ }
+ />
);
};
diff --git a/front/src/modules/ui/view-bar/constants/ViewsDropdownId.ts b/front/src/modules/ui/view-bar/constants/ViewsDropdownId.ts
new file mode 100644
index 000000000..390e32277
--- /dev/null
+++ b/front/src/modules/ui/view-bar/constants/ViewsDropdownId.ts
@@ -0,0 +1 @@
+export const ViewsDropdownId = 'views';