## Recoil to Jotai Migration — PR 13: Workflow, Page Layout, AI,
Activities, Settings, SSE & Remaining Modules

### Summary

This is the 13th PR in the [14-PR migration
series](packages/twenty-front/src/modules/ui/utilities/state/jotai/MIGRATION_PLAN.md)
to replace Recoil with Jotai as the state management library in
`twenty-front`. This PR migrates the remaining consumer code across all
modules — updating ~1,076 files with ~10k insertions/deletions.

### What changed

**New Jotai infrastructure (13 new files):**
- `createComponentSelectorV2` and `createComponentFamilySelectorV2` —
instance-scoped derived atoms, replacing Recoil's component selectors
- 6 new hooks: `useRecoilComponentSelectorValueV2`,
`useRecoilComponentFamilySelectorValueV2`,
`useRecoilComponentSelectorCallbackStateV2`,
`useRecoilComponentFamilySelectorCallbackStateV2`,
`useRecoilComponentStateCallbackStateV2`,
`useRecoilComponentFamilyStateCallbackStateV2`
- New types: `ComponentSelectorV2`, `ComponentFamilySelectorV2`,
`SelectorCallbacksV2`
- Extended `buildGetHelper` to support the new selector patterns

**State definition migrations:**
- `createState()` → `createStateV2()` (Jotai `atom()`)
- `createFamilyState()` → `createFamilyStateV2()` (Jotai `atom()` with
family cache)
- Recoil `selector`/`selectorFamily` → Jotai derived `atom()` via V2
utilities

**Hook migrations (~2,400 removed, ~1,545 added V2 equivalents):**
- `useRecoilValue` → `useRecoilValueV2`
- `useRecoilState` → `useRecoilStateV2`
- `useSetRecoilState` → `useSetRecoilStateV2`
- `useRecoilCallback` → `useCallback` + `jotaiStore.get/set`
- `useRecoilComponentValue` → `useRecoilComponentValueV2`
- `useSetRecoilComponentState` → `useSetRecoilComponentStateV2`
- `useRecoilComponentFamilyValue` → `useRecoilComponentFamilyValueV2` /
`useFamilySelectorValueV2`
- ~397 direct `import from 'recoil'` removed

**Deleted files (9 files):**
- `dateLocaleState.ts` — consolidated
- `currentAIChatThreadTitleStateV2.ts` — renamed to replace the original
- `isCommandMenuOpenedState.ts` — removed
- `filesFieldUploadState.ts` — replaced by V2
- `recordStoreFamilySelector.ts`, `recordStoreFieldValueSelector.ts`,
`recordStoreRecordsSelector.ts` — replaced by V2 equivalents
- `settingsAllRolesSelector.ts` — replaced by `useSettingsAllRoles` hook
- `settingsRoleIdsStateV2.ts` — consolidated

**Modules migrated:**
- Workflow (diagram, steps, variables, filters)
- Page Layout (widgets, fields, graph, tabs)
- AI (chat, agents, browsing context)
- Activities (rich text editor, targets, timeline)
- Action Menu (single/multiple record actions)
- Command Menu (navigation, history, pages, workflow)
- Context Store
- Record Board, Record Table, Record Calendar, Record Index
- Record Field, Record Filter, Record Sort, Record Group
- Record Drag, Record Picker, Record Store
- Views (view bar, view picker, filters, sorts)
- Settings (roles, permissions, SSO, security, data model, developers,
domains)
- SSE (event streams, subscriptions)
- Spreadsheet Import
- Auth, Favorites, Front Components, Information Banner
This commit is contained in:
Charles Bochet
2026-02-24 17:37:01 +01:00
committed by GitHub
parent c6ec764b23
commit 0f2af6a6cb
1326 changed files with 19248 additions and 19389 deletions
@@ -7,12 +7,12 @@ import { useGenerateDepthRecordGqlFieldsFromObject } from '@/object-record/graph
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
import { LayoutRenderingProvider } from '@/ui/layout/contexts/LayoutRenderingContext';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { PageLayoutType } from '~/generated-metadata/graphql';
export const CommandMenuCalendarEventPage = () => {
const { upsertRecordsInStore } = useUpsertRecordsInStore();
const viewableRecordId = useRecoilComponentValue(
const viewableRecordId = useRecoilComponentValueV2(
viewableRecordIdComponentState,
);
@@ -1,7 +1,7 @@
import { Suspense, lazy } from 'react';
import { viewableFrontComponentIdComponentState } from '@/command-menu/pages/front-component/states/viewableFrontComponentIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { isDefined } from 'twenty-shared/utils';
const FrontComponentRenderer = lazy(() =>
@@ -11,7 +11,7 @@ const FrontComponentRenderer = lazy(() =>
);
export const CommandMenuFrontComponentPage = () => {
const viewableFrontComponentId = useRecoilComponentValue(
const viewableFrontComponentId = useRecoilComponentValueV2(
viewableFrontComponentIdComponentState,
);
@@ -1,7 +1,7 @@
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const viewableFrontComponentIdComponentState = createComponentState<
export const viewableFrontComponentIdComponentState = createComponentStateV2<
string | null
>({
key: 'command-menu/viewable-front-component-id',
@@ -8,7 +8,7 @@ import { EmailThreadMessage } from '@/activities/emails/components/EmailThreadMe
import { CommandMenuMessageThreadIntermediaryMessages } from '@/command-menu/pages/message-thread/components/CommandMenuMessageThreadIntermediaryMessages';
import { useEmailThreadInCommandMenu } from '@/command-menu/pages/message-thread/hooks/useEmailThreadInCommandMenu';
import { messageThreadComponentState } from '@/command-menu/pages/message-thread/states/messageThreadComponentState';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { t } from '@lingui/core/macro';
import { ConnectedAccountProvider } from 'twenty-shared/types';
import { assertUnreachable, isDefined } from 'twenty-shared/utils';
@@ -47,7 +47,7 @@ const ALLOWED_REPLY_PROVIDERS = [
];
export const CommandMenuMessageThreadPage = () => {
const setMessageThread = useSetRecoilComponentState(
const setMessageThread = useSetRecoilComponentStateV2(
messageThreadComponentState,
);
@@ -366,8 +366,8 @@ const mocks = [
const Wrapper = ({ children }: { children: React.ReactNode }) => {
const MetadataWrapper = getJestMetadataAndApolloMocksWrapper({
apolloMocks: mocks,
onInitializeRecoilSnapshot: ({ set }) => {
set(
onInitializeJotaiStore: (store) => {
store.set(
viewableRecordIdComponentState.atomFamily({
instanceId: 'test-instance',
}),
@@ -13,13 +13,13 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { MessageParticipantRole } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
// to improve - https://github.com/twentyhq/twenty/issues/12190
export const useEmailThreadInCommandMenu = () => {
const viewableRecordId = useRecoilComponentValue(
const viewableRecordId = useRecoilComponentValueV2(
viewableRecordIdComponentState,
);
const { upsertRecordsInStore } = useUpsertRecordsInStore();
@@ -1,9 +1,9 @@
import { type MessageThread } from '@/activities/emails/types/MessageThread';
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const messageThreadComponentState =
createComponentState<MessageThread | null>({
createComponentStateV2<MessageThread | null>({
key: 'messageThreadComponentState',
defaultValue: null,
componentInstanceContext: CommandMenuPageComponentInstanceContext,
@@ -14,11 +14,10 @@ import { currentRecordFilterGroupsComponentState } from '@/object-record/record-
import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { InputLabel } from '@/ui/input/components/InputLabel';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
import { useStore } from 'jotai';
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
import { useRecoilCallback } from 'recoil';
const StyledChartFiltersPageContainer = styled.div`
display: flex;
@@ -50,49 +49,33 @@ export const ChartFiltersSettings = ({
const { updateCurrentWidgetConfig } =
useUpdateCurrentWidgetConfig(pageLayoutId);
const currentRecordFiltersCallbackState = useRecoilComponentCallbackState(
const currentRecordFiltersAtom = useRecoilComponentStateCallbackStateV2(
currentRecordFiltersComponentState,
instanceId,
);
const currentRecordFilterGroupsCallbackState =
useRecoilComponentCallbackState(
currentRecordFilterGroupsComponentState,
instanceId,
);
const currentRecordFilterGroupsAtom = useRecoilComponentStateCallbackStateV2(
currentRecordFilterGroupsComponentState,
instanceId,
);
const store = useStore();
const chartWidgetConfiguration = widget.configuration;
const handleFiltersUpdate = useRecoilCallback(
({ snapshot }) =>
() => {
const currentRecordFilters = getSnapshotValue(
snapshot,
currentRecordFiltersCallbackState,
);
const handleFiltersUpdate = () => {
const currentRecordFilters = store.get(currentRecordFiltersAtom);
const currentRecordFilterGroups = store.get(currentRecordFilterGroupsAtom);
const currentRecordFilterGroups = getSnapshotValue(
snapshot,
currentRecordFilterGroupsCallbackState,
);
updateCurrentWidgetConfig({
objectMetadataId: objectMetadataItem.id,
configToUpdate: {
filter: {
recordFilters: currentRecordFilters,
recordFilterGroups: currentRecordFilterGroups,
},
} satisfies Partial<ChartWidgetConfiguration>,
});
},
[
currentRecordFiltersCallbackState,
currentRecordFilterGroupsCallbackState,
objectMetadataItem,
updateCurrentWidgetConfig,
],
);
updateCurrentWidgetConfig({
objectMetadataId: objectMetadataItem.id,
configToUpdate: {
filter: {
recordFilters: currentRecordFilters,
recordFilterGroups: currentRecordFilterGroups,
},
} satisfies Partial<ChartWidgetConfiguration>,
});
};
return (
<>
@@ -3,8 +3,8 @@ import { type ChartFilters } from '@/command-menu/pages/page-layout/types/ChartF
import { useSetAdvancedFilterDropdownStates } from '@/object-record/advanced-filter/hooks/useSetAdvancedFilterDropdownAllRowsStates';
import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { useEffect, useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
@@ -16,13 +16,13 @@ export const ChartFiltersSettingsInitializeStateEffect = ({
initialChartFilters,
}: ChartFiltersSettingsInitializeStateEffectProps) => {
const [hasInitializedChartFilters, setHasInitializedChartFilters] =
useRecoilComponentState(hasInitializedChartFiltersComponentState);
useRecoilComponentStateV2(hasInitializedChartFiltersComponentState);
const setCurrentRecordFilters = useSetRecoilComponentState(
const setCurrentRecordFilters = useSetRecoilComponentStateV2(
currentRecordFiltersComponentState,
);
const setCurrentRecordFilterGroups = useSetRecoilComponentState(
const setCurrentRecordFilterGroups = useSetRecoilComponentStateV2(
currentRecordFilterGroupsComponentState,
);
@@ -14,7 +14,7 @@ import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layou
import { shouldHideChartSetting } from '@/command-menu/pages/page-layout/utils/shouldHideChartSetting';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { hasWidgetTooManyGroupsComponentState } from '@/page-layout/widgets/graph/states/hasWidgetTooManyGroupsComponentState';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
import { isFieldMetadataDateKind } from 'twenty-shared/utils';
@@ -58,7 +58,7 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
CHART_CONFIGURATION_SETTING_IDS.GROUP_BY,
);
const [hasWidgetTooManyGroups, setHasWidgetTooManyGroups] =
useRecoilComponentState(hasWidgetTooManyGroupsComponentState);
useRecoilComponentStateV2(hasWidgetTooManyGroupsComponentState);
const handleGraphTypeChange = (graphType: GraphType) => {
const configToUpdate = getConfigToUpdateAfterGraphTypeChange(graphType);
@@ -5,7 +5,7 @@ import { isChartWidget } from '@/command-menu/pages/page-layout/utils/isChartWid
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
import { WidgetComponentInstanceContext } from '@/page-layout/widgets/states/contexts/WidgetComponentInstanceContext';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared/utils';
@@ -18,12 +18,12 @@ const StyledContainer = styled.div`
export const CommandMenuPageLayoutChartSettings = () => {
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
const draftPageLayout = useRecoilComponentValue(
const draftPageLayout = useRecoilComponentValueV2(
pageLayoutDraftComponentState,
pageLayoutId,
);
const pageLayoutEditingWidgetId = useRecoilComponentValue(
const pageLayoutEditingWidgetId = useRecoilComponentValueV2(
pageLayoutEditingWidgetIdComponentState,
pageLayoutId,
);
@@ -4,19 +4,19 @@ import { isChartWidget } from '@/command-menu/pages/page-layout/utils/isChartWid
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { isDefined } from 'twenty-shared/utils';
export const CommandMenuPageLayoutGraphFilter = () => {
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
const draftPageLayout = useRecoilComponentValue(
const draftPageLayout = useRecoilComponentValueV2(
pageLayoutDraftComponentState,
pageLayoutId,
);
const pageLayoutEditingWidgetId = useRecoilComponentValue(
const pageLayoutEditingWidgetId = useRecoilComponentValueV2(
pageLayoutEditingWidgetIdComponentState,
pageLayoutId,
);
@@ -11,8 +11,8 @@ import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDr
import { pageLayoutTabSettingsOpenTabIdComponentState } from '@/page-layout/states/pageLayoutTabSettingsOpenTabIdComponentState';
import { sortTabsByPosition } from '@/page-layout/utils/sortTabsByPosition';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { t } from '@lingui/core/macro';
import { isDefined } from 'twenty-shared/utils';
import {
@@ -26,12 +26,12 @@ export const CommandMenuPageLayoutTabSettings = () => {
const { closeCommandMenu } = useCommandMenu();
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
const draft = useRecoilComponentValue(
const draft = useRecoilComponentValueV2(
pageLayoutDraftComponentState,
pageLayoutId,
);
const [openTabId, setOpenTabId] = useRecoilComponentState(
const [openTabId, setOpenTabId] = useRecoilComponentStateV2(
pageLayoutTabSettingsOpenTabIdComponentState,
pageLayoutId,
);
@@ -16,8 +16,8 @@ import { useRemovePageLayoutWidgetAndPreservePosition } from '@/page-layout/hook
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useQuery } from '@apollo/client';
import { t } from '@lingui/core/macro';
@@ -79,12 +79,12 @@ export const CommandMenuPageLayoutWidgetTypeSelect = () => {
);
const [pageLayoutEditingWidgetId, setPageLayoutEditingWidgetId] =
useRecoilComponentState(
useRecoilComponentStateV2(
pageLayoutEditingWidgetIdComponentState,
pageLayoutId,
);
const draftPageLayout = useRecoilComponentValue(
const draftPageLayout = useRecoilComponentValueV2(
pageLayoutDraftComponentState,
pageLayoutId,
);
@@ -6,7 +6,6 @@ import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { RightDrawerFooter } from '@/ui/layout/right-drawer/components/RightDrawerFooter';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useLingui } from '@lingui/react/macro';
import { useId } from 'react';
@@ -24,7 +23,7 @@ export const WidgetSettingsFooter = ({
const { closeDropdown } = useCloseDropdown();
const { duplicateWidget } = useDuplicatePageLayoutWidget(pageLayoutId);
const { deletePageLayoutWidget } = useDeletePageLayoutWidget(pageLayoutId);
const editingWidgetId = useRecoilComponentValue(
const editingWidgetId = useRecoilComponentValueV2(
pageLayoutEditingWidgetIdComponentState,
pageLayoutId,
);
@@ -2,7 +2,7 @@ import { useNavigateCommandMenu } from '@/command-menu/hooks/useNavigateCommandM
import { type PageLayoutCommandMenuPage } from '@/command-menu/pages/page-layout/types/PageLayoutCommandMenuPage';
import { getPageLayoutIcon } from '@/command-menu/pages/page-layout/utils/getPageLayoutIcon';
import { getPageLayoutPageTitle } from '@/command-menu/pages/page-layout/utils/getPageLayoutPageTitle';
import { useRecoilCallback } from 'recoil';
import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { type IconComponent } from 'twenty-ui/display';
@@ -17,8 +17,8 @@ type NavigatePageLayoutCommandMenuProps = {
export const useNavigatePageLayoutCommandMenu = () => {
const { navigateCommandMenu } = useNavigateCommandMenu();
const navigatePageLayoutCommandMenu = useRecoilCallback(() => {
return ({
const navigatePageLayoutCommandMenu = useCallback(
({
commandMenuPage,
pageTitle,
pageIcon,
@@ -36,8 +36,9 @@ export const useNavigatePageLayoutCommandMenu = () => {
focusTitleInput,
resetNavigationStack,
});
};
}, [navigateCommandMenu]);
},
[navigateCommandMenu],
);
return {
navigatePageLayoutCommandMenu,
@@ -1,10 +1,10 @@
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilValue } from 'recoil';
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
export const usePageLayoutIdFromContextStoreTargetedRecord = () => {
const targetedRecordsRule = useRecoilComponentValue(
const targetedRecordsRule = useRecoilComponentValueV2(
contextStoreTargetedRecordsRuleComponentState,
);
@@ -19,7 +19,7 @@ export const usePageLayoutIdFromContextStoreTargetedRecord = () => {
const recordId: string = targetedRecordsRule.selectedRecordIds[0];
const record = useRecoilValue(recordStoreFamilyState(recordId));
const record = useFamilyRecoilValueV2(recordStoreFamilyState, recordId);
return { pageLayoutId: record?.pageLayoutId };
};
@@ -2,16 +2,16 @@ import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
import { useRecordPageLayoutIdFromRecordStoreOrThrow } from '@/page-layout/hooks/useRecordPageLayoutIdFromRecordStoreOrThrow';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { isDefined } from 'twenty-shared/utils';
export const usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord =
() => {
const targetedRecordsRule = useRecoilComponentValue(
const targetedRecordsRule = useRecoilComponentValueV2(
contextStoreTargetedRecordsRuleComponentState,
);
const objectMetadataId = useRecoilComponentValue(
const objectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataItemIdComponentState,
);
@@ -5,7 +5,8 @@ import { currentRecordFilterGroupsComponentState } from '@/object-record/record-
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { hasInitializedCurrentRecordFilterGroupsComponentFamilyState } from '@/views/states/hasInitializedCurrentRecordFilterGroupsComponentFamilyState';
import { hasInitializedCurrentRecordFiltersComponentFamilyState } from '@/views/states/hasInitializedCurrentRecordFiltersComponentFamilyState';
import { useRecoilCallback } from 'recoil';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
export const useResetChartDraftFiltersSettings = () => {
@@ -13,42 +14,42 @@ export const useResetChartDraftFiltersSettings = () => {
const { widgetInEditMode } = useWidgetInEditMode(pageLayoutId);
const resetChartDraftFiltersSettings = useRecoilCallback(
({ set }) =>
(objectMetadataItemId: string) => {
if (!isDefined(widgetInEditMode)) {
return;
}
const resetChartDraftFiltersSettings = useCallback(
(objectMetadataItemId: string) => {
if (!isDefined(widgetInEditMode)) {
return;
}
const { instanceId } = getChartFiltersSettingsInstanceId({
widgetId: widgetInEditMode.id,
objectMetadataItemId: objectMetadataItemId,
});
const { instanceId } = getChartFiltersSettingsInstanceId({
widgetId: widgetInEditMode.id,
objectMetadataItemId: objectMetadataItemId,
});
set(
hasInitializedCurrentRecordFilterGroupsComponentFamilyState.atomFamily(
{
familyKey: {},
instanceId,
},
),
false,
);
jotaiStore.set(
hasInitializedCurrentRecordFilterGroupsComponentFamilyState.atomFamily({
familyKey: {},
instanceId,
}),
false,
);
set(
hasInitializedCurrentRecordFiltersComponentFamilyState.atomFamily({
familyKey: {},
instanceId,
}),
false,
);
jotaiStore.set(
hasInitializedCurrentRecordFiltersComponentFamilyState.atomFamily({
familyKey: {},
instanceId,
}),
false,
);
set(currentRecordFiltersComponentState.atomFamily({ instanceId }), []);
set(
currentRecordFilterGroupsComponentState.atomFamily({ instanceId }),
[],
);
},
jotaiStore.set(
currentRecordFiltersComponentState.atomFamily({ instanceId }),
[],
);
jotaiStore.set(
currentRecordFilterGroupsComponentState.atomFamily({ instanceId }),
[],
);
},
[widgetInEditMode],
);
@@ -1,51 +1,53 @@
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
import type { PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilCallback } from 'recoil';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useStore } from 'jotai';
import { useCallback } from 'react';
export const useUpdateCurrentWidgetConfig = (pageLayoutIdFromProps: string) => {
const pageLayoutDraftCallbackState = useRecoilComponentCallbackState(
const pageLayoutDraftAtom = useRecoilComponentStateCallbackStateV2(
pageLayoutDraftComponentState,
pageLayoutIdFromProps,
);
const currentlyEditingWidgetId = useRecoilComponentValue(
const currentlyEditingWidgetId = useRecoilComponentValueV2(
pageLayoutEditingWidgetIdComponentState,
pageLayoutIdFromProps,
);
const updateCurrentWidgetConfig = useRecoilCallback(
({ set }) =>
({
objectMetadataId,
configToUpdate,
}: {
objectMetadataId?: string | null;
configToUpdate?: Partial<PageLayoutWidget['configuration']>;
}) => {
set(pageLayoutDraftCallbackState, (prev) => ({
...prev,
tabs: prev.tabs.map((tab) => ({
...tab,
widgets: tab.widgets.map((widget) =>
widget.id === currentlyEditingWidgetId
? {
...widget,
objectMetadataId:
objectMetadataId ?? widget.objectMetadataId,
configuration: {
...(widget.configuration ?? {}),
...configToUpdate,
} as PageLayoutWidget['configuration'],
}
: widget,
),
})),
}));
},
[pageLayoutDraftCallbackState, currentlyEditingWidgetId],
const store = useStore();
const updateCurrentWidgetConfig = useCallback(
({
objectMetadataId,
configToUpdate,
}: {
objectMetadataId?: string | null;
configToUpdate?: Partial<PageLayoutWidget['configuration']>;
}) => {
const prev = store.get(pageLayoutDraftAtom);
store.set(pageLayoutDraftAtom, {
...prev,
tabs: prev.tabs.map((tab) => ({
...tab,
widgets: tab.widgets.map((widget) =>
widget.id === currentlyEditingWidgetId
? {
...widget,
objectMetadataId: objectMetadataId ?? widget.objectMetadataId,
configuration: {
...(widget.configuration ?? {}),
...configToUpdate,
} as PageLayoutWidget['configuration'],
}
: widget,
),
})),
});
},
[pageLayoutDraftAtom, currentlyEditingWidgetId, store],
);
return { updateCurrentWidgetConfig };
@@ -15,9 +15,9 @@ import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
import { getTabListInstanceIdFromPageLayoutId } from '@/page-layout/utils/getTabListInstanceIdFromPageLayoutId';
import { updateWidgetMinimumSizeForGraphType } from '@/page-layout/utils/updateWidgetMinimumSizeForGraphType';
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
import { useStore } from 'jotai';
import { useRecoilCallback } from 'recoil';
import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { BarChartLayout } from '~/generated-metadata/graphql';
@@ -32,159 +32,148 @@ export const useGetConfigToUpdateAfterGraphTypeChange = ({
const tabListInstanceId = getTabListInstanceIdFromPageLayoutId(pageLayoutId);
const currentlyEditingWidgetIdState = useRecoilComponentCallbackState(
const currentlyEditingWidgetIdState = useRecoilComponentStateCallbackStateV2(
pageLayoutEditingWidgetIdComponentState,
pageLayoutId,
);
const pageLayoutCurrentLayoutsState = useRecoilComponentCallbackState(
const pageLayoutCurrentLayoutsState = useRecoilComponentStateCallbackStateV2(
pageLayoutCurrentLayoutsComponentState,
pageLayoutId,
);
const pageLayoutDraftState = useRecoilComponentCallbackState(
const pageLayoutDraftState = useRecoilComponentStateCallbackStateV2(
pageLayoutDraftComponentState,
pageLayoutId,
);
const store = useStore();
const getConfigToUpdateAfterGraphTypeChange = useRecoilCallback(
({ set, snapshot }) =>
(graphType: GraphType) => {
const currentlyEditingWidgetId = snapshot
.getLoadable(currentlyEditingWidgetIdState)
.getValue();
const getConfigToUpdateAfterGraphTypeChange = useCallback(
(graphType: GraphType) => {
const currentlyEditingWidgetId = store.get(currentlyEditingWidgetIdState);
if (!isDefined(currentlyEditingWidgetId)) {
throw new Error('No widget is currently being edited');
}
if (!isDefined(currentlyEditingWidgetId)) {
throw new Error('No widget is currently being edited');
}
const draftPageLayout = snapshot
.getLoadable(pageLayoutDraftState)
.getValue();
const draftPageLayout = store.get(pageLayoutDraftState);
const widgetInDraft = draftPageLayout.tabs
.flatMap((tab) => tab.widgets)
.find((w) => w.id === currentlyEditingWidgetId);
const widgetInDraft = draftPageLayout.tabs
.flatMap((tab) => tab.widgets)
.find((w) => w.id === currentlyEditingWidgetId);
if (
!isDefined(widgetInDraft) ||
!isDefined(widgetInDraft.configuration)
) {
throw new Error('Widget configuration not found in draft state');
}
if (
!isDefined(widgetInDraft) ||
!isDefined(widgetInDraft.configuration)
) {
throw new Error('Widget configuration not found in draft state');
}
const currentConfiguration = widgetInDraft.configuration;
const currentConfiguration = widgetInDraft.configuration;
if (!isWidgetConfigurationOfTypeGraph(currentConfiguration)) {
throw new Error('Widget configuration is not a chart configuration');
}
if (!isWidgetConfigurationOfTypeGraph(currentConfiguration)) {
throw new Error('Widget configuration is not a chart configuration');
}
const newConfigurationType =
getConfigurationTypeFromGraphType(graphType);
const newConfigurationType = getConfigurationTypeFromGraphType(graphType);
let configToUpdate = {
__typename:
GRAPH_CONFIGURATION_TYPE_TO_CONFIG_TYPENAME[newConfigurationType],
configurationType: newConfigurationType,
} as Partial<ChartConfiguration>;
let configToUpdate = {
__typename:
GRAPH_CONFIGURATION_TYPE_TO_CONFIG_TYPENAME[newConfigurationType],
configurationType: newConfigurationType,
} as Partial<ChartConfiguration>;
if (
graphType !== GraphType.AGGREGATE &&
graphType !== GraphType.GAUGE
) {
const objectMetadataItem = objectMetadataItems.find(
(item) => item.id === widget.objectMetadataId,
if (graphType !== GraphType.AGGREGATE && graphType !== GraphType.GAUGE) {
const objectMetadataItem = objectMetadataItems.find(
(item) => item.id === widget.objectMetadataId,
);
const convertedAggregateOperation =
convertAggregateOperationForDateField(
currentConfiguration,
objectMetadataItem,
);
const convertedAggregateOperation =
convertAggregateOperationForDateField(
currentConfiguration,
objectMetadataItem,
);
if (isDefined(convertedAggregateOperation)) {
configToUpdate = {
...configToUpdate,
aggregateOperation: convertedAggregateOperation,
};
}
if (isDefined(convertedAggregateOperation)) {
configToUpdate = {
...configToUpdate,
aggregateOperation: convertedAggregateOperation,
};
}
}
const isPieChart = graphType === GraphType.PIE;
const isVerticalBarChart = graphType === GraphType.VERTICAL_BAR;
const isHorizontalBarChart = graphType === GraphType.HORIZONTAL_BAR;
const isLineChart = graphType === GraphType.LINE;
const isBarOrLineChart =
isVerticalBarChart || isHorizontalBarChart || isLineChart;
const isPieChart = graphType === GraphType.PIE;
const isVerticalBarChart = graphType === GraphType.VERTICAL_BAR;
const isHorizontalBarChart = graphType === GraphType.HORIZONTAL_BAR;
const isLineChart = graphType === GraphType.LINE;
const isBarOrLineChart =
isVerticalBarChart || isHorizontalBarChart || isLineChart;
const wasBarOrLineChart =
isWidgetConfigurationOfType(
currentConfiguration,
'BarChartConfiguration',
) ||
isWidgetConfigurationOfType(
currentConfiguration,
'LineChartConfiguration',
);
const wasPieChart = isWidgetConfigurationOfType(
const wasBarOrLineChart =
isWidgetConfigurationOfType(
currentConfiguration,
'PieChartConfiguration',
'BarChartConfiguration',
) ||
isWidgetConfigurationOfType(
currentConfiguration,
'LineChartConfiguration',
);
if (isPieChart && wasBarOrLineChart) {
configToUpdate = {
...configToUpdate,
...convertBarOrLineChartConfigToPieChart(currentConfiguration),
};
}
const wasPieChart = isWidgetConfigurationOfType(
currentConfiguration,
'PieChartConfiguration',
);
if (isBarOrLineChart && wasPieChart) {
configToUpdate = {
...configToUpdate,
...convertPieChartConfigToBarOrLineChart(currentConfiguration),
};
}
if (isPieChart && wasBarOrLineChart) {
configToUpdate = {
...configToUpdate,
...convertBarOrLineChartConfigToPieChart(currentConfiguration),
};
}
if (isHorizontalBarChart) {
configToUpdate = {
...configToUpdate,
layout: BarChartLayout.HORIZONTAL,
};
}
if (isBarOrLineChart && wasPieChart) {
configToUpdate = {
...configToUpdate,
...convertPieChartConfigToBarOrLineChart(currentConfiguration),
};
}
if (isVerticalBarChart) {
configToUpdate = {
...configToUpdate,
layout: BarChartLayout.VERTICAL,
};
}
if (isHorizontalBarChart) {
configToUpdate = {
...configToUpdate,
layout: BarChartLayout.HORIZONTAL,
};
}
const activeTabId = store.get(
activeTabIdComponentState.atomFamily({
instanceId: tabListInstanceId,
}),
);
if (isVerticalBarChart) {
configToUpdate = {
...configToUpdate,
layout: BarChartLayout.VERTICAL,
};
}
if (isDefined(activeTabId) && isDefined(currentlyEditingWidgetId)) {
const currentLayouts = snapshot
.getLoadable(pageLayoutCurrentLayoutsState)
.getValue();
const activeTabId = store.get(
activeTabIdComponentState.atomFamily({
instanceId: tabListInstanceId,
}),
);
const updatedLayouts = updateWidgetMinimumSizeForGraphType({
configurationType: newConfigurationType,
widgetId: currentlyEditingWidgetId,
tabId: activeTabId,
currentLayouts,
});
if (isDefined(activeTabId) && isDefined(currentlyEditingWidgetId)) {
const currentLayouts = store.get(pageLayoutCurrentLayoutsState);
set(pageLayoutCurrentLayoutsState, updatedLayouts);
}
const updatedLayouts = updateWidgetMinimumSizeForGraphType({
configurationType: newConfigurationType,
widgetId: currentlyEditingWidgetId,
tabId: activeTabId,
currentLayouts,
});
return configToUpdate;
},
store.set(pageLayoutCurrentLayoutsState, updatedLayouts);
}
return configToUpdate;
},
[
currentlyEditingWidgetIdState,
objectMetadataItems,
@@ -1,14 +1,14 @@
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
export const useWidgetInEditMode = (pageLayoutId: string) => {
const draftPageLayout = useRecoilComponentValue(
const draftPageLayout = useRecoilComponentValueV2(
pageLayoutDraftComponentState,
pageLayoutId,
);
const pageLayoutEditingWidgetId = useRecoilComponentValue(
const pageLayoutEditingWidgetId = useRecoilComponentValueV2(
pageLayoutEditingWidgetIdComponentState,
pageLayoutId,
);
@@ -1,8 +1,8 @@
import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const hasInitializedChartFiltersComponentState =
createComponentState<boolean>({
createComponentStateV2<boolean>({
key: 'hasInitializedCurrentRecordFiltersComponentFamilyState',
defaultValue: false,
componentInstanceContext: RecordFiltersComponentInstanceContext,
@@ -8,11 +8,11 @@ import { INFORMATION_BANNER_HEIGHT } from '@/information-banner/constants/Inform
import { RecordComponentInstanceContextsWrapper } from '@/object-record/components/RecordComponentInstanceContextsWrapper';
import { PageLayoutRecordPageRenderer } from '@/object-record/record-show/components/PageLayoutRecordPageRenderer';
import { useRecordShowPage } from '@/object-record/record-show/hooks/useRecordShowPage';
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
import { recordStoreFamilySelectorV2 } from '@/object-record/record-store/states/selectors/recordStoreFamilySelectorV2';
import { useComponentInstanceStateContext } from '@/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { useFamilySelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilySelectorValueV2';
const StyledRightDrawerRecord = styled.div<{
hasDeletedRecordBanner: boolean;
@@ -26,11 +26,11 @@ const StyledRightDrawerRecord = styled.div<{
`;
export const CommandMenuRecordPage = () => {
const viewableRecordNameSingular = useRecoilComponentValue(
const viewableRecordNameSingular = useRecoilComponentValueV2(
viewableRecordNameSingularComponentState,
);
const viewableRecordId = useRecoilComponentValue(
const viewableRecordId = useRecoilComponentValueV2(
viewableRecordIdComponentState,
);
@@ -47,11 +47,9 @@ export const CommandMenuRecordPage = () => {
viewableRecordId,
);
const recordDeletedAt = useRecoilValue(
recordStoreFamilySelector({
recordId: objectRecordId,
fieldName: 'deletedAt',
}),
const recordDeletedAt = useFamilySelectorValueV2(
recordStoreFamilySelectorV2,
{ recordId: objectRecordId, fieldName: 'deletedAt' },
);
const commandMenuPageInstanceId = useComponentInstanceStateContext(
@@ -1,7 +1,7 @@
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const viewableRecordIdComponentState = createComponentState<
export const viewableRecordIdComponentState = createComponentStateV2<
string | null
>({
key: 'command-menu/viewable-record-id',
@@ -1,7 +1,7 @@
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const viewableRecordNameSingularComponentState = createComponentState<
export const viewableRecordNameSingularComponentState = createComponentStateV2<
string | null
>({
key: 'command-menu/viewable-record-name-singular',
@@ -11,8 +11,8 @@ import { RECORD_ACTIONS } from '@/workflow/workflow-steps/workflow-actions/const
import { getActionIconColorOrThrow } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIconColorOrThrow';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useTheme } from '@emotion/react';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { useLingui } from '@lingui/react/macro';
import { useRecoilValue } from 'recoil';
import { IconFunction } from 'twenty-ui/display';
import { MenuItem } from 'twenty-ui/navigation';
import { FeatureFlagKey } from '~/generated-metadata/graphql';
@@ -35,7 +35,7 @@ export const CommandMenuWorkflowSelectAction = ({
const { t } = useLingui();
const logicFunctions = useRecoilValue(logicFunctionsState);
const logicFunctions = useRecoilValueV2(logicFunctionsState);
const toolFunctions = logicFunctions.filter((fn) => fn.isTool === true);
@@ -1,9 +1,9 @@
import { commandMenuWorkflowIdComponentState } from '@/command-menu/pages/workflow/states/commandMenuWorkflowIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { isDefined } from 'twenty-shared/utils';
export const useCommandMenuWorkflowIdOrThrow = () => {
const workflowId = useRecoilComponentValue(
const workflowId = useRecoilComponentValueV2(
commandMenuWorkflowIdComponentState,
);
if (!isDefined(workflowId)) {
@@ -1,7 +1,7 @@
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const commandMenuWorkflowIdComponentState = createComponentState<
export const commandMenuWorkflowIdComponentState = createComponentStateV2<
string | undefined
>({
key: 'command-menu/workflow-id',
@@ -1,7 +1,7 @@
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const commandMenuWorkflowRunIdComponentState = createComponentState<
export const commandMenuWorkflowRunIdComponentState = createComponentStateV2<
string | undefined
>({
key: 'command-menu/workflow-run-id',
@@ -1,7 +1,7 @@
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const commandMenuWorkflowStepIdComponentState = createComponentState<
export const commandMenuWorkflowStepIdComponentState = createComponentStateV2<
string | undefined
>({
key: 'command-menu/workflow-step-id',
@@ -1,10 +1,9 @@
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const commandMenuWorkflowVersionIdComponentState = createComponentState<
string | undefined
>({
key: 'command-menu/workflow-version-id',
defaultValue: undefined,
componentInstanceContext: CommandMenuPageComponentInstanceContext,
});
export const commandMenuWorkflowVersionIdComponentState =
createComponentStateV2<string | undefined>({
key: 'command-menu/workflow-version-id',
defaultValue: undefined,
componentInstanceContext: CommandMenuPageComponentInstanceContext,
});
@@ -4,8 +4,8 @@ import {
type WorkflowActionSelection,
} from '@/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction';
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
import {
@@ -18,13 +18,13 @@ import { useUpdateStep } from '@/workflow/workflow-steps/hooks/useUpdateStep';
import { workflowInsertStepIdsComponentState } from '@/workflow/workflow-steps/states/workflowInsertStepIdsComponentState';
import { prepareIfElseStepWithNewBranch } from '@/workflow/workflow-steps/workflow-actions/if-else-action/utils/prepareIfElseStepWithNewBranch';
import { getActionIcon } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIcon';
import { useSetRecoilState } from 'recoil';
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
export const CommandMenuWorkflowCreateStepContent = () => {
const { getIcon } = useIcons();
const workflowVisualizerWorkflowId = useRecoilComponentValue(
const workflowVisualizerWorkflowId = useRecoilComponentValueV2(
workflowVisualizerWorkflowIdComponentState,
);
@@ -36,12 +36,12 @@ export const CommandMenuWorkflowCreateStepContent = () => {
const { openWorkflowEditStepInCommandMenu } = useWorkflowCommandMenu();
const { closeRightClickMenu } = useCloseRightClickMenu();
const setCommandMenuNavigationStack = useSetRecoilState(
const setCommandMenuNavigationStack = useSetRecoilStateV2(
commandMenuNavigationStackState,
);
const [workflowInsertStepIds, setWorkflowInsertStepIds] =
useRecoilComponentState(workflowInsertStepIdsComponentState);
useRecoilComponentStateV2(workflowInsertStepIdsComponentState);
const handleIfElseParentStep = async ({
parentStep,
@@ -1,4 +1,4 @@
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow';
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
import { WorkflowStepDetail } from '@/workflow/workflow-steps/components/WorkflowStepDetail';
@@ -15,7 +15,7 @@ const StyledContainer = styled.div`
export const CommandMenuWorkflowEditStepContent = () => {
const flow = useFlowOrThrow();
const workflowSelectedNode = useRecoilComponentValue(
const workflowSelectedNode = useRecoilComponentValueV2(
workflowSelectedNodeComponentState,
);
@@ -4,7 +4,7 @@ import {
type WorkflowActionSelection,
} from '@/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction';
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow';
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
import {
@@ -15,16 +15,16 @@ import { useCloseRightClickMenu } from '@/workflow/workflow-diagram/hooks/useClo
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
import { useUpdateStep } from '@/workflow/workflow-steps/hooks/useUpdateStep';
import { getActionIcon } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIcon';
import { useSetRecoilState } from 'recoil';
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
export const CommandMenuWorkflowEditStepTypeContent = () => {
const { getIcon } = useIcons();
const workflowSelectedNode = useRecoilComponentValue(
const workflowSelectedNode = useRecoilComponentValueV2(
workflowSelectedNodeComponentState,
);
const workflowVisualizerWorkflowId = useRecoilComponentValue(
const workflowVisualizerWorkflowId = useRecoilComponentValueV2(
workflowVisualizerWorkflowIdComponentState,
);
const flow = useFlowOrThrow();
@@ -33,7 +33,7 @@ export const CommandMenuWorkflowEditStepTypeContent = () => {
const { openWorkflowEditStepInCommandMenu } = useWorkflowCommandMenu();
const { closeRightClickMenu } = useCloseRightClickMenu();
const setCommandMenuNavigationStack = useSetRecoilState(
const setCommandMenuNavigationStack = useSetRecoilStateV2(
commandMenuNavigationStackState,
);
@@ -7,7 +7,6 @@ import { TabList } from '@/ui/layout/tab-list/components/TabList';
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
import { type SingleTabProps } from '@/ui/layout/tab-list/types/SingleTabProps';
import { useComponentInstanceStateContext } from '@/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow';
import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun';
@@ -44,7 +43,7 @@ type TabId = WorkflowRunTabIdType;
export const CommandMenuWorkflowRunViewStepContent = () => {
const flow = useFlowOrThrow();
const workflowSelectedNode = useRecoilComponentValue(
const workflowSelectedNode = useRecoilComponentValueV2(
workflowSelectedNodeComponentState,
);
const workflowRunId = useWorkflowRunIdOrThrow();
@@ -1,9 +1,9 @@
import { commandMenuWorkflowRunIdComponentState } from '@/command-menu/pages/workflow/states/commandMenuWorkflowRunIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { isDefined } from 'twenty-shared/utils';
export const useCommandMenuWorkflowRunIdOrThrow = () => {
const workflowRunId = useRecoilComponentValue(
const workflowRunId = useRecoilComponentValueV2(
commandMenuWorkflowRunIdComponentState,
);
if (!isDefined(workflowRunId)) {
@@ -1,8 +1,8 @@
import { CommandMenuWorkflowRunStepContentComponentInstanceContext } from '@/command-menu/pages/workflow/step/view-run/states/contexts/CommandMenuWorkflowRunStepContentComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const workflowRunIteratorSubStepIterationIndexComponentState =
createComponentState<number>({
createComponentStateV2<number>({
key: 'workflowRunIteratorSubStepIterationIndexComponentState',
defaultValue: 0,
componentInstanceContext:
@@ -1,4 +1,4 @@
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow';
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
import { WorkflowStepDetail } from '@/workflow/workflow-steps/components/WorkflowStepDetail';
@@ -13,7 +13,7 @@ const StyledContainer = styled.div`
export const CommandMenuWorkflowViewStepContent = () => {
const flow = useFlowOrThrow();
const workflowSelectedNode = useRecoilComponentValue(
const workflowSelectedNode = useRecoilComponentValueV2(
workflowSelectedNodeComponentState,
);
@@ -1,9 +1,9 @@
import { commandMenuWorkflowVersionIdComponentState } from '@/command-menu/pages/workflow/states/commandMenuWorkflowVersionIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { isDefined } from 'twenty-shared/utils';
export const useCommandMenuWorkflowVersionIdOrThrow = () => {
const workflowVersionId = useRecoilComponentValue(
const workflowVersionId = useRecoilComponentValueV2(
commandMenuWorkflowVersionIdComponentState,
);
if (!isDefined(workflowVersionId)) {
@@ -1,7 +1,7 @@
import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu';
import { useCommandMenuWorkflowIdOrThrow } from '@/command-menu/pages/workflow/hooks/useCommandMenuWorkflowIdOrThrow';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow';
import {
type WorkflowTrigger,
@@ -29,7 +29,7 @@ export const CommandMenuWorkflowSelectTriggerTypeContent = () => {
const { activeNonSystemObjectMetadataItems } =
useFilteredObjectMetadataItems();
const setWorkflowSelectedNode = useSetRecoilComponentState(
const setWorkflowSelectedNode = useSetRecoilComponentStateV2(
workflowSelectedNodeComponentState,
);
const { openWorkflowEditStepInCommandMenu } = useWorkflowCommandMenu();