Fully deprecate old recoil (#18210)

## Summary

Removes the `recoil` dependency entirely from `package.json` and
`twenty-front/package.json`, completing the migration to Jotai as the
sole state management library.

Removes all Recoil infrastructure: `RecoilRoot` wrapper from `App.tsx`
and test decorators, `RecoilDebugObserver`, Recoil-specific ESLint rules
(`use-getLoadable-and-getValue-to-get-atoms`,
`useRecoilCallback-has-dependency-array`), and legacy Recoil utility
hooks/types (`useRecoilComponentState`, `useRecoilComponentValue`,
`createComponentState`, `createFamilyState`, `getSnapshotValue`,
`cookieStorageEffect`, `localStorageEffect`, etc.).

Renames all `V2`-suffixed Jotai state files and types to their canonical
names (e.g., `ComponentStateV2` -> `ComponentState`,
`agentChatInputStateV2` -> `agentChatInputState`, `SelectorCallbacksV2`
-> `SelectorCallbacks`), and removes the now-redundant V1 counterparts.

Updates ~433 files across the codebase to use the renamed Jotai imports,
remove Recoil imports, and clean up test wrappers (`RecoilRootDecorator`
-> `JotaiRootDecorator`).
This commit is contained in:
Charles Bochet
2026-02-25 12:26:42 +01:00
committed by GitHub
parent ecb7270a7b
commit 121788c42f
439 changed files with 1714 additions and 3929 deletions
@@ -2,27 +2,24 @@ import { renderHook } from '@testing-library/react';
import { Provider as JotaiProvider } from 'jotai';
import { act } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { RecoilRoot } from 'recoil';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageInfoState';
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
import { isCommandMenuOpenedStateV2 } from '@/command-menu/states/isCommandMenuOpenedStateV2';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { CommandMenuPages } from 'twenty-shared/types';
import { IconDotsVertical } from 'twenty-ui/display';
const Wrapper = ({ children }: { children: React.ReactNode }) => (
<JotaiProvider store={jotaiStore}>
<RecoilRoot>
<MemoryRouter
initialEntries={['/one', '/two', { pathname: '/three' }]}
initialIndex={1}
>
{children}
</MemoryRouter>
</RecoilRoot>
<MemoryRouter
initialEntries={['/one', '/two', { pathname: '/three' }]}
initialIndex={1}
>
{children}
</MemoryRouter>
</JotaiProvider>
);
@@ -54,31 +51,31 @@ describe('useCommandMenu', () => {
result.current.commandMenu.openCommandMenu();
});
expect(jotaiStore.get(isCommandMenuOpenedStateV2.atom)).toBe(true);
expect(jotaiStore.get(isCommandMenuOpenedState.atom)).toBe(true);
act(() => {
result.current.commandMenu.closeCommandMenu();
});
expect(jotaiStore.get(isCommandMenuOpenedStateV2.atom)).toBe(false);
expect(jotaiStore.get(isCommandMenuOpenedState.atom)).toBe(false);
});
it('should toggle the command menu', () => {
const { result } = renderHooks();
expect(jotaiStore.get(isCommandMenuOpenedStateV2.atom)).toBe(false);
expect(jotaiStore.get(isCommandMenuOpenedState.atom)).toBe(false);
act(() => {
result.current.commandMenu.toggleCommandMenu();
});
expect(jotaiStore.get(isCommandMenuOpenedStateV2.atom)).toBe(true);
expect(jotaiStore.get(isCommandMenuOpenedState.atom)).toBe(true);
act(() => {
result.current.commandMenu.toggleCommandMenu();
});
expect(jotaiStore.get(isCommandMenuOpenedStateV2.atom)).toBe(false);
expect(jotaiStore.get(isCommandMenuOpenedState.atom)).toBe(false);
});
it('should navigate command menu and reset navigation stack when resetNavigationStack is true', () => {
@@ -2,8 +2,6 @@ import { renderHook } from '@testing-library/react';
import { Provider as JotaiProvider } from 'jotai';
import { act } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { RecoilRoot } from 'recoil';
import { COMMAND_MENU_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuComponentInstanceId';
import { COMMAND_MENU_CONTEXT_CHIP_GROUPS_DROPDOWN_ID } from '@/command-menu/constants/CommandMenuContextChipGroupsDropdownId';
import { COMMAND_MENU_PREVIOUS_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuPreviousComponentInstanceId';
@@ -14,7 +12,7 @@ import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState';
import { isCommandMenuClosingState } from '@/command-menu/states/isCommandMenuClosingState';
import { isCommandMenuOpenedStateV2 } from '@/command-menu/states/isCommandMenuOpenedStateV2';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
@@ -53,9 +51,7 @@ jest.mock('@/ui/layout/right-drawer/utils/emitSidePanelCloseEvent', () => ({
const Wrapper = ({ children }: { children: React.ReactNode }) => (
<JotaiProvider store={jotaiStore}>
<RecoilRoot>
<MemoryRouter>{children}</MemoryRouter>
</RecoilRoot>
<MemoryRouter>{children}</MemoryRouter>
</JotaiProvider>
);
@@ -97,7 +93,7 @@ describe('useCommandMenuCloseAnimationCompleteCleanup', () => {
Icon: IconList,
instanceId: 'test-id',
});
jotaiStore.set(isCommandMenuOpenedStateV2.atom, true);
jotaiStore.set(isCommandMenuOpenedState.atom, true);
jotaiStore.set(commandMenuSearchState.atom, 'test search');
jotaiStore.set(commandMenuNavigationStackState.atom, [
{
@@ -120,7 +116,7 @@ describe('useCommandMenuCloseAnimationCompleteCleanup', () => {
Icon: IconList,
instanceId: 'test-id',
});
expect(jotaiStore.get(isCommandMenuOpenedStateV2.atom)).toBe(true);
expect(jotaiStore.get(isCommandMenuOpenedState.atom)).toBe(true);
expect(jotaiStore.get(commandMenuSearchState.atom)).toBe('test search');
expect(jotaiStore.get(commandMenuNavigationStackState.atom)).toEqual([
{
@@ -146,7 +142,7 @@ describe('useCommandMenuCloseAnimationCompleteCleanup', () => {
Icon: undefined,
instanceId: '',
});
expect(jotaiStore.get(isCommandMenuOpenedStateV2.atom)).toBe(false);
expect(jotaiStore.get(isCommandMenuOpenedState.atom)).toBe(false);
expect(jotaiStore.get(commandMenuSearchState.atom)).toBe('');
expect(jotaiStore.get(commandMenuNavigationStackState.atom)).toEqual([]);
expect(jotaiStore.get(hasUserSelectedCommandState.atom)).toBe(false);
@@ -2,24 +2,20 @@ import { renderHook } from '@testing-library/react';
import { Provider as JotaiProvider } from 'jotai';
import { act } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { RecoilRoot } from 'recoil';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { useCommandMenuCloseAnimationCompleteCleanup } from '@/command-menu/hooks/useCommandMenuCloseAnimationCompleteCleanup';
import { useCommandMenuHistory } from '@/command-menu/hooks/useCommandMenuHistory';
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageInfoState';
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
import { isCommandMenuOpenedStateV2 } from '@/command-menu/states/isCommandMenuOpenedStateV2';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { CommandMenuPages } from 'twenty-shared/types';
import { IconList, IconSearch } from 'twenty-ui/display';
const Wrapper = ({ children }: { children: React.ReactNode }) => (
<JotaiProvider store={jotaiStore}>
<RecoilRoot>
<MemoryRouter>{children}</MemoryRouter>
</RecoilRoot>
<MemoryRouter>{children}</MemoryRouter>
</JotaiProvider>
);
@@ -116,7 +112,7 @@ describe('useCommandMenuHistory', () => {
instanceId: '',
Icon: undefined,
});
expect(jotaiStore.get(isCommandMenuOpenedStateV2.atom)).toBe(false);
expect(jotaiStore.get(isCommandMenuOpenedState.atom)).toBe(false);
});
it('should navigate to a page in history', () => {
@@ -1,18 +1,15 @@
import { renderHook } from '@testing-library/react';
import { act } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { RecoilRoot } from 'recoil';
import { useCommandMenuOnItemClick } from '@/command-menu/hooks/useCommandMenuOnItemClick';
const Wrapper = ({ children }: { children: React.ReactNode }) => (
<RecoilRoot>
<MemoryRouter
initialEntries={['/one', '/two', { pathname: '/three' }]}
initialIndex={1}
>
{children}
</MemoryRouter>
</RecoilRoot>
<MemoryRouter
initialEntries={['/one', '/two', { pathname: '/three' }]}
initialIndex={1}
>
{children}
</MemoryRouter>
);
const renderHooks = () => {
@@ -4,15 +4,11 @@ import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { renderHook } from '@testing-library/react';
import { Provider as JotaiProvider } from 'jotai';
import { act } from 'react';
import { RecoilRoot } from 'recoil';
const pageId = 'merge-page-id';
const objectMetadataId = 'company-metadata-id';
const Wrapper = ({ children }: { children: React.ReactNode }) => (
<JotaiProvider store={jotaiStore}>
<RecoilRoot>{children}</RecoilRoot>
</JotaiProvider>
<JotaiProvider store={jotaiStore}>{children}</JotaiProvider>
);
const renderHooks = (initialRecordIds: string[]) => {
@@ -1,10 +1,9 @@
import { act, renderHook } from '@testing-library/react';
import { Provider as JotaiProvider } from 'jotai';
import { type ReactNode } from 'react';
import { RecoilRoot } from 'recoil';
import { useOpenAskAIPageInCommandMenu } from '@/command-menu/hooks/useOpenAskAIPageInCommandMenu';
import { isCommandMenuOpenedStateV2 } from '@/command-menu/states/isCommandMenuOpenedStateV2';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { CommandMenuPages } from 'twenty-shared/types';
import { IconSparkles } from 'twenty-ui/display';
@@ -21,15 +20,13 @@ jest.mock('@/command-menu/hooks/useCommandMenu', () => ({
}));
const Wrapper = ({ children }: { children: ReactNode }) => (
<JotaiProvider store={jotaiStore}>
<RecoilRoot>{children}</RecoilRoot>
</JotaiProvider>
<JotaiProvider store={jotaiStore}>{children}</JotaiProvider>
);
describe('useOpenAskAIPageInCommandMenu', () => {
beforeEach(() => {
jest.clearAllMocks();
jotaiStore.set(isCommandMenuOpenedStateV2.atom, false);
jotaiStore.set(isCommandMenuOpenedState.atom, false);
});
it('should navigate to AskAI page with correct defaults', () => {
@@ -51,7 +48,7 @@ describe('useOpenAskAIPageInCommandMenu', () => {
});
it('should use resetNavigationStack from argument when provided', () => {
jotaiStore.set(isCommandMenuOpenedStateV2.atom, true);
jotaiStore.set(isCommandMenuOpenedState.atom, true);
const { result } = renderHook(() => useOpenAskAIPageInCommandMenu(), {
wrapper: Wrapper,
@@ -69,7 +66,7 @@ describe('useOpenAskAIPageInCommandMenu', () => {
});
it('should default resetNavigationStack to isCommandMenuOpened', () => {
jotaiStore.set(isCommandMenuOpenedStateV2.atom, true);
jotaiStore.set(isCommandMenuOpenedState.atom, true);
const { result } = renderHook(() => useOpenAskAIPageInCommandMenu(), {
wrapper: Wrapper,
@@ -20,22 +20,21 @@ import { getPeopleRecordConnectionMock } from '~/testing/mock-data/people';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState';
const mockCopyContextStoreStates = jest.fn();
jest.mock(
'@/command-menu/hooks/useCopyContextStoreAndActionMenuStates',
() => ({
useCopyContextStoreStates: () => ({
copyContextStoreStates: mockCopyContextStoreStates,
}),
}),
);
const personMockObjectMetadataItem = generatedMockObjectMetadataItems.find(
(item) => item.nameSingular === 'person',
)!;
const peopleMock = getPeopleRecordConnectionMock();
jotaiStore.set(
recordStoreFamilyState.atomFamily(peopleMock[0].id),
peopleMock[0],
);
jotaiStore.set(
recordStoreFamilyState.atomFamily(peopleMock[1].id),
peopleMock[1],
);
const wrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({
apolloMocks: [],
componentInstanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID,
@@ -48,16 +47,6 @@ const wrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({
},
contextStoreNumberOfSelectedRecords: 2,
contextStoreCurrentViewType: ContextStoreViewType.Table,
onInitializeRecoilSnapshot: (_snapshot) => {
jotaiStore.set(
recordStoreFamilyState.atomFamily(peopleMock[0].id),
peopleMock[0],
);
jotaiStore.set(
recordStoreFamilyState.atomFamily(peopleMock[1].id),
peopleMock[1],
);
},
});
describe('useSetGlobalCommandMenuContext', () => {
@@ -161,18 +150,41 @@ describe('useSetGlobalCommandMenuContext', () => {
expect(hasUserSelectedCommandAfter).toBe(false);
});
it('should call copyContextStoreStates with correct parameters', () => {
const { result } = renderHook(() => useSetGlobalCommandMenuContext(), {
wrapper,
});
it('should copy context store states to previous instance before resetting', () => {
const { result } = renderHook(
() => {
const { setGlobalCommandMenuContext } =
useSetGlobalCommandMenuContext();
const previousTargetedRecordsRule = useAtomComponentStateValue(
contextStoreTargetedRecordsRuleComponentState,
COMMAND_MENU_PREVIOUS_COMPONENT_INSTANCE_ID,
);
const previousNumberOfSelectedRecords = useAtomComponentStateValue(
contextStoreNumberOfSelectedRecordsComponentState,
COMMAND_MENU_PREVIOUS_COMPONENT_INSTANCE_ID,
);
return {
setGlobalCommandMenuContext,
previousTargetedRecordsRule,
previousNumberOfSelectedRecords,
};
},
{
wrapper,
},
);
act(() => {
result.current.setGlobalCommandMenuContext();
});
expect(mockCopyContextStoreStates).toHaveBeenCalledWith({
instanceIdToCopyFrom: COMMAND_MENU_COMPONENT_INSTANCE_ID,
instanceIdToCopyTo: COMMAND_MENU_PREVIOUS_COMPONENT_INSTANCE_ID,
expect(result.current.previousTargetedRecordsRule).toEqual({
mode: 'selection',
selectedRecordIds: [peopleMock[0].id, peopleMock[1].id],
});
expect(result.current.previousNumberOfSelectedRecords).toBe(2);
});
});
@@ -5,7 +5,6 @@ import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { renderHook } from '@testing-library/react';
import { Provider as JotaiProvider } from 'jotai';
import { act } from 'react';
import { RecoilRoot } from 'recoil';
import { CommandMenuPages } from 'twenty-shared/types';
import { IconArrowDown, IconDotsVertical } from 'twenty-ui/display';
@@ -25,9 +24,7 @@ const mockedNavigationStack = [
];
const Wrapper = ({ children }: { children: React.ReactNode }) => (
<JotaiProvider store={jotaiStore}>
<RecoilRoot>{children}</RecoilRoot>
</JotaiProvider>
<JotaiProvider store={jotaiStore}>{children}</JotaiProvider>
);
describe('useUpdateCommandMenuPageInfo', () => {
@@ -2,8 +2,8 @@ import { SIDE_PANEL_FOCUS_ID } from '@/command-menu/constants/SidePanelFocusId';
import { useNavigateCommandMenu } from '@/command-menu/hooks/useNavigateCommandMenu';
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
import { isCommandMenuClosingState } from '@/command-menu/states/isCommandMenuClosingState';
import { isCommandMenuOpenedStateV2 } from '@/command-menu/states/isCommandMenuOpenedStateV2';
import { addToNavPayloadRegistryStateV2 } from '@/navigation-menu-item/states/addToNavPayloadRegistryStateV2';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { addToNavPayloadRegistryState } from '@/navigation-menu-item/states/addToNavPayloadRegistryState';
import { useCloseAnyOpenDropdown } from '@/ui/layout/dropdown/hooks/useCloseAnyOpenDropdown';
import { emitSidePanelOpenEvent } from '@/ui/layout/right-drawer/utils/emitSidePanelOpenEvent';
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
@@ -22,11 +22,11 @@ export const useCommandMenu = () => {
useRemoveFocusItemFromFocusStackById();
const closeCommandMenu = useCallback(() => {
const isCommandMenuOpened = store.get(isCommandMenuOpenedStateV2.atom);
const isCommandMenuOpened = store.get(isCommandMenuOpenedState.atom);
if (isCommandMenuOpened) {
store.set(addToNavPayloadRegistryStateV2.atom, new Map());
store.set(isCommandMenuOpenedStateV2.atom, false);
store.set(addToNavPayloadRegistryState.atom, new Map());
store.set(isCommandMenuOpenedState.atom, false);
store.set(isCommandMenuClosingState.atom, true);
closeAnyOpenDropdown();
removeFocusItemFromFocusStackById({
@@ -47,7 +47,7 @@ export const useCommandMenu = () => {
}, [closeAnyOpenDropdown, navigateCommandMenu]);
const toggleCommandMenu = useCallback(() => {
const isCommandMenuOpened = store.get(isCommandMenuOpenedStateV2.atom);
const isCommandMenuOpened = store.get(isCommandMenuOpenedState.atom);
store.set(commandMenuSearchState.atom, '');
@@ -10,7 +10,7 @@ import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState';
import { isCommandMenuClosingState } from '@/command-menu/states/isCommandMenuClosingState';
import { isCommandMenuOpenedStateV2 } from '@/command-menu/states/isCommandMenuOpenedStateV2';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
@@ -97,7 +97,7 @@ export const useCommandMenuCloseAnimationCompleteCleanup = () => {
Icon: undefined,
instanceId: '',
});
store.set(isCommandMenuOpenedStateV2.atom, false);
store.set(isCommandMenuOpenedState.atom, false);
store.set(commandMenuSearchState.atom, '');
store.set(commandMenuNavigationMorphItemsByPageState.atom, new Map());
store.set(commandMenuNavigationStackState.atom, []);
@@ -5,7 +5,7 @@ import { commandMenuNavigationStackState } from '@/command-menu/states/commandMe
import { CommandMenuPages } from 'twenty-shared/types';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { recordStoreIdentifiersFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreIdentifiersSelector';
import { recordStoreRecordsSelectorV2 } from '@/object-record/record-store/states/selectors/recordStoreRecordsSelectorV2';
import { recordStoreRecordsSelector } from '@/object-record/record-store/states/selectors/recordStoreRecordsSelector';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useMemo } from 'react';
@@ -54,7 +54,7 @@ export const useCommandMenuContextChips = () => {
allowRequestsToTwentyIcons,
},
);
const records = useAtomFamilySelectorValue(recordStoreRecordsSelectorV2, {
const records = useAtomFamilySelectorValue(recordStoreRecordsSelector, {
recordIds: allRecordIds,
});
@@ -9,7 +9,7 @@ import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState
import { commandMenuShouldFocusTitleInputComponentState } from '@/command-menu/states/commandMenuShouldFocusTitleInputComponentState';
import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState';
import { isCommandMenuClosingState } from '@/command-menu/states/isCommandMenuClosingState';
import { isCommandMenuOpenedStateV2 } from '@/command-menu/states/isCommandMenuOpenedStateV2';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
@@ -37,7 +37,7 @@ export const useNavigateCommandMenu = () => {
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
const openCommandMenu = useCallback(() => {
const isCommandMenuOpened = store.get(isCommandMenuOpenedStateV2.atom);
const isCommandMenuOpened = store.get(isCommandMenuOpenedState.atom);
const isCommandMenuClosing = store.get(isCommandMenuClosingState.atom);
@@ -65,7 +65,7 @@ export const useNavigateCommandMenu = () => {
instanceIdToCopyTo: COMMAND_MENU_COMPONENT_INSTANCE_ID,
});
store.set(isCommandMenuOpenedStateV2.atom, true);
store.set(isCommandMenuOpenedState.atom, true);
store.set(hasUserSelectedCommandState.atom, false);
}, [
copyContextStoreStates,
@@ -1,5 +1,5 @@
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { isCommandMenuOpenedStateV2 } from '@/command-menu/states/isCommandMenuOpenedStateV2';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { t } from '@lingui/core/macro';
import { useCallback } from 'react';
@@ -9,7 +9,7 @@ import { v4 } from 'uuid';
export const useOpenAskAIPageInCommandMenu = () => {
const { navigateCommandMenu } = useCommandMenu();
const isCommandMenuOpened = useAtomStateValue(isCommandMenuOpenedStateV2);
const isCommandMenuOpened = useAtomStateValue(isCommandMenuOpenedState);
const openAskAIPage = useCallback(
({
@@ -1,5 +1,5 @@
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { isCommandMenuOpenedStateV2 } from '@/command-menu/states/isCommandMenuOpenedStateV2';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { t } from '@lingui/core/macro';
import { CommandMenuPages } from 'twenty-shared/types';
@@ -8,7 +8,7 @@ import { v4 } from 'uuid';
export const useOpenRecordsSearchPageInCommandMenu = () => {
const { navigateCommandMenu } = useCommandMenu();
const isCommandMenuOpened = useAtomStateValue(isCommandMenuOpenedStateV2);
const isCommandMenuOpened = useAtomStateValue(isCommandMenuOpenedState);
const openRecordsSearchPage = () => {
navigateCommandMenu({
@@ -1,5 +1,5 @@
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { viewableRichTextComponentStateV2 } from '@/command-menu/pages/rich-text-page/states/viewableRichTextComponentStateV2';
import { viewableRichTextComponentState } from '@/command-menu/pages/rich-text-page/states/viewableRichTextComponentState';
import { t } from '@lingui/core/macro';
import { useStore } from 'jotai';
import { useCallback } from 'react';
@@ -19,7 +19,7 @@ export const useRichTextCommandMenu = () => {
activityId: string;
activityObjectNameSingular: string;
}) => {
store.set(viewableRichTextComponentStateV2.atom, {
store.set(viewableRichTextComponentState.atom, {
activityId,
activityObjectNameSingular,
});
@@ -1,81 +1,180 @@
import { COMMAND_MENU_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuComponentInstanceId';
import { COMMAND_MENU_PREVIOUS_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuPreviousComponentInstanceId';
import { useCopyContextStoreStates } from '@/command-menu/hooks/useCopyContextStoreAndActionMenuStates';
import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageInfoState';
import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState';
import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState';
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState';
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
import { atom, useStore } from 'jotai';
import { useCallback } from 'react';
import { useStore } from 'jotai';
export const useSetGlobalCommandMenuContext = () => {
const store = useStore();
const { copyContextStoreStates } = useCopyContextStoreStates();
const setGlobalCommandMenuContext = useCallback(() => {
copyContextStoreStates({
instanceIdToCopyFrom: COMMAND_MENU_COMPONENT_INSTANCE_ID,
instanceIdToCopyTo: COMMAND_MENU_PREVIOUS_COMPONENT_INSTANCE_ID,
});
store.set(
contextStoreTargetedRecordsRuleComponentState.atomFamily({
instanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID,
atom(null, (get, batchSet) => {
const fromId = COMMAND_MENU_COMPONENT_INSTANCE_ID;
const toId = COMMAND_MENU_PREVIOUS_COMPONENT_INSTANCE_ID;
batchSet(
contextStoreCurrentObjectMetadataItemIdComponentState.atomFamily({
instanceId: toId,
}),
get(
contextStoreCurrentObjectMetadataItemIdComponentState.atomFamily({
instanceId: fromId,
}),
),
);
batchSet(
contextStoreTargetedRecordsRuleComponentState.atomFamily({
instanceId: toId,
}),
get(
contextStoreTargetedRecordsRuleComponentState.atomFamily({
instanceId: fromId,
}),
),
);
batchSet(
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
instanceId: toId,
}),
get(
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
instanceId: fromId,
}),
),
);
batchSet(
contextStoreFiltersComponentState.atomFamily({
instanceId: toId,
}),
get(
contextStoreFiltersComponentState.atomFamily({
instanceId: fromId,
}),
),
);
batchSet(
contextStoreFilterGroupsComponentState.atomFamily({
instanceId: toId,
}),
get(
contextStoreFilterGroupsComponentState.atomFamily({
instanceId: fromId,
}),
),
);
batchSet(
contextStoreAnyFieldFilterValueComponentState.atomFamily({
instanceId: toId,
}),
get(
contextStoreAnyFieldFilterValueComponentState.atomFamily({
instanceId: fromId,
}),
),
);
batchSet(
contextStoreCurrentViewIdComponentState.atomFamily({
instanceId: toId,
}),
get(
contextStoreCurrentViewIdComponentState.atomFamily({
instanceId: fromId,
}),
),
);
batchSet(
contextStoreCurrentViewTypeComponentState.atomFamily({
instanceId: toId,
}),
get(
contextStoreCurrentViewTypeComponentState.atomFamily({
instanceId: fromId,
}),
),
);
batchSet(
contextStoreIsPageInEditModeComponentState.atomFamily({
instanceId: toId,
}),
get(
contextStoreIsPageInEditModeComponentState.atomFamily({
instanceId: fromId,
}),
),
);
batchSet(
contextStoreTargetedRecordsRuleComponentState.atomFamily({
instanceId: fromId,
}),
{ mode: 'selection', selectedRecordIds: [] },
);
batchSet(
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
instanceId: fromId,
}),
0,
);
batchSet(
contextStoreFiltersComponentState.atomFamily({
instanceId: fromId,
}),
[],
);
batchSet(
contextStoreFilterGroupsComponentState.atomFamily({
instanceId: fromId,
}),
[],
);
batchSet(
contextStoreAnyFieldFilterValueComponentState.atomFamily({
instanceId: fromId,
}),
'',
);
batchSet(
contextStoreCurrentViewTypeComponentState.atomFamily({
instanceId: fromId,
}),
ContextStoreViewType.Table,
);
batchSet(commandMenuPageInfoState.atom, {
title: undefined,
Icon: undefined,
instanceId: '',
});
batchSet(hasUserSelectedCommandState.atom, false);
}),
{
mode: 'selection',
selectedRecordIds: [],
},
);
store.set(
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
instanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID,
}),
0,
);
store.set(
contextStoreFiltersComponentState.atomFamily({
instanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID,
}),
[],
);
store.set(
contextStoreFilterGroupsComponentState.atomFamily({
instanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID,
}),
[],
);
store.set(
contextStoreAnyFieldFilterValueComponentState.atomFamily({
instanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID,
}),
'',
);
store.set(
contextStoreCurrentViewTypeComponentState.atomFamily({
instanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID,
}),
ContextStoreViewType.Table,
);
store.set(commandMenuPageInfoState.atom, {
title: undefined,
Icon: undefined,
instanceId: '',
});
store.set(hasUserSelectedCommandState.atom, false);
}, [copyContextStoreStates, store]);
}, [store]);
return {
setGlobalCommandMenuContext,