Jotai 13 (#18178)
## 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:
+2
-2
@@ -2,10 +2,10 @@ import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDi
|
||||
import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
|
||||
import { useNavigateCommandMenu } from '@/command-menu/hooks/useNavigateCommandMenu';
|
||||
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
|
||||
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
|
||||
import { type MessageDescriptor } from '@lingui/core';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useContext } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { type CommandMenuPages } from 'twenty-shared/types';
|
||||
import { type IconComponent } from 'twenty-ui/display';
|
||||
|
||||
@@ -26,7 +26,7 @@ export const ActionOpenSidePanelPage = ({
|
||||
|
||||
const { navigateCommandMenu } = useNavigateCommandMenu();
|
||||
|
||||
const setCommandMenuSearchState = useSetRecoilState(commandMenuSearchState);
|
||||
const setCommandMenuSearchState = useSetRecoilStateV2(commandMenuSearchState);
|
||||
|
||||
if (!actionConfig) {
|
||||
return null;
|
||||
|
||||
+4
-3
@@ -1,8 +1,8 @@
|
||||
import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
|
||||
import { useCloseActionMenu } from '@/action-menu/hooks/useCloseActionMenu';
|
||||
import { isHeadlessFrontComponentMountedFamilySelector } from '@/front-components/selectors/isHeadlessFrontComponentMountedFamilySelector';
|
||||
import { useFamilySelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilySelectorValueV2';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { ActionDisplay } from './ActionDisplay';
|
||||
|
||||
@@ -20,8 +20,9 @@ export const HeadlessFrontComponentAction = ({
|
||||
closeSidePanelOnCommandMenuListActionExecution: false,
|
||||
});
|
||||
|
||||
const isMounted = useRecoilValue(
|
||||
isHeadlessFrontComponentMountedFamilySelector(frontComponentId),
|
||||
const isMounted = useFamilySelectorValueV2(
|
||||
isHeadlessFrontComponentMountedFamilySelector,
|
||||
frontComponentId,
|
||||
);
|
||||
|
||||
if (!actionConfig) {
|
||||
|
||||
+11
-6
@@ -14,7 +14,7 @@ import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-
|
||||
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useContext } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@@ -22,8 +22,9 @@ export const DeleteMultipleRecordsAction = () => {
|
||||
const { recordIndexId, objectMetadataItem } =
|
||||
useRecordIndexIdFromCurrentContextStore();
|
||||
|
||||
const contextStoreCurrentViewId = useRecoilComponentValue(
|
||||
const contextStoreCurrentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
if (!contextStoreCurrentViewId) {
|
||||
@@ -32,20 +33,24 @@ export const DeleteMultipleRecordsAction = () => {
|
||||
|
||||
const { resetTableRowSelection } = useResetTableRowSelection(recordIndexId);
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreFilters = useRecoilComponentValue(
|
||||
const contextStoreFilters = useRecoilComponentValueV2(
|
||||
contextStoreFiltersComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreFilterGroups = useRecoilComponentValue(
|
||||
const contextStoreFilterGroups = useRecoilComponentValueV2(
|
||||
contextStoreFilterGroupsComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreAnyFieldFilterValue = useRecoilComponentValue(
|
||||
const contextStoreAnyFieldFilterValue = useRecoilComponentValueV2(
|
||||
contextStoreAnyFieldFilterValueComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const { removeSelectedRecordsFromRecordBoard } =
|
||||
|
||||
+11
-6
@@ -14,7 +14,7 @@ import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-
|
||||
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useContext } from 'react';
|
||||
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
|
||||
@@ -24,8 +24,9 @@ export const DestroyMultipleRecordsAction = () => {
|
||||
const { recordIndexId, objectMetadataItem } =
|
||||
useRecordIndexIdFromCurrentContextStore();
|
||||
|
||||
const contextStoreCurrentViewId = useRecoilComponentValue(
|
||||
const contextStoreCurrentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
if (!contextStoreCurrentViewId) {
|
||||
@@ -36,20 +37,24 @@ export const DestroyMultipleRecordsAction = () => {
|
||||
const { removeSelectedRecordsFromRecordBoard } =
|
||||
useRemoveSelectedRecordsFromRecordBoard(recordIndexId);
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreFilters = useRecoilComponentValue(
|
||||
const contextStoreFilters = useRecoilComponentValueV2(
|
||||
contextStoreFiltersComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreFilterGroups = useRecoilComponentValue(
|
||||
const contextStoreFilterGroups = useRecoilComponentValueV2(
|
||||
contextStoreFilterGroupsComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreAnyFieldFilterValue = useRecoilComponentValue(
|
||||
const contextStoreAnyFieldFilterValue = useRecoilComponentValueV2(
|
||||
contextStoreAnyFieldFilterValueComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const { filterValueDependencies } = useFilterValueDependencies();
|
||||
|
||||
+2
-2
@@ -7,14 +7,14 @@ import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { useRecordIndexExportRecords } from '@/object-record/record-index/export/hooks/useRecordIndexExportRecords';
|
||||
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useContext } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const ExportMultipleRecordsAction = () => {
|
||||
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
|
||||
|
||||
const contextStoreCurrentViewId = useRecoilComponentValue(
|
||||
const contextStoreCurrentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -3,12 +3,12 @@ import { useSelectedRecordIds } from '@/action-menu/actions/record-actions/singl
|
||||
import { useOpenMergeRecordsPageInCommandMenu } from '@/command-menu/hooks/useOpenMergeRecordsPageInCommandMenu';
|
||||
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const MergeMultipleRecordsAction = () => {
|
||||
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
|
||||
|
||||
const contextStoreCurrentViewId = useRecoilComponentValue(
|
||||
const contextStoreCurrentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
|
||||
+11
-6
@@ -12,7 +12,7 @@ import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-
|
||||
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
|
||||
|
||||
@@ -20,8 +20,9 @@ export const RestoreMultipleRecordsAction = () => {
|
||||
const { recordIndexId, objectMetadataItem } =
|
||||
useRecordIndexIdFromCurrentContextStore();
|
||||
|
||||
const contextStoreCurrentViewId = useRecoilComponentValue(
|
||||
const contextStoreCurrentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
if (!contextStoreCurrentViewId) {
|
||||
@@ -36,20 +37,24 @@ export const RestoreMultipleRecordsAction = () => {
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreFilters = useRecoilComponentValue(
|
||||
const contextStoreFilters = useRecoilComponentValueV2(
|
||||
contextStoreFiltersComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreFilterGroups = useRecoilComponentValue(
|
||||
const contextStoreFilterGroups = useRecoilComponentValueV2(
|
||||
contextStoreFilterGroupsComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreAnyFieldFilterValue = useRecoilComponentValue(
|
||||
const contextStoreAnyFieldFilterValue = useRecoilComponentValueV2(
|
||||
contextStoreAnyFieldFilterValueComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const { filterValueDependencies } = useFilterValueDependencies();
|
||||
|
||||
+4
-4
@@ -3,8 +3,8 @@ import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
|
||||
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
|
||||
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
|
||||
@@ -13,7 +13,7 @@ export const CreateNewViewNoSelectionRecord = () => {
|
||||
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
|
||||
const currentViewId = useRecoilComponentValue(
|
||||
const currentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
@@ -26,7 +26,7 @@ export const CreateNewViewNoSelectionRecord = () => {
|
||||
currentViewId,
|
||||
);
|
||||
|
||||
const setViewPickerReferenceViewId = useSetRecoilComponentState(
|
||||
const setViewPickerReferenceViewId = useSetRecoilComponentStateV2(
|
||||
viewPickerReferenceViewIdComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
+3
-3
@@ -6,13 +6,13 @@ import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRe
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter';
|
||||
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
|
||||
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 HideDeletedRecordsNoSelectionRecordAction = () => {
|
||||
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
|
||||
|
||||
const currentViewId = useRecoilComponentValue(
|
||||
const currentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
@@ -32,7 +32,7 @@ export const HideDeletedRecordsNoSelectionRecordAction = () => {
|
||||
|
||||
const { isRecordFilterAboutSoftDelete } = useCheckIsSoftDeleteFilter();
|
||||
|
||||
const currentRecordFilters = useRecoilComponentValue(
|
||||
const currentRecordFilters = useRecoilComponentValueV2(
|
||||
currentRecordFiltersComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
+2
-2
@@ -3,12 +3,12 @@ import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter';
|
||||
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const SeeDeletedRecordsNoSelectionRecordAction = () => {
|
||||
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
|
||||
|
||||
const currentViewId = useRecoilComponentValue(
|
||||
const currentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
|
||||
+63
-58
@@ -7,14 +7,16 @@ import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/s
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useActiveWorkflowVersionsWithManualTrigger } from '@/workflow/hooks/useActiveWorkflowVersionsWithManualTrigger';
|
||||
import { useRunWorkflowVersion } from '@/workflow/hooks/useRunWorkflowVersion';
|
||||
|
||||
import { type WorkflowVersion } from '@/workflow/types/Workflow';
|
||||
import { COMMAND_MENU_DEFAULT_ICON } from '@/workflow/workflow-trigger/constants/CommandMenuDefaultIcon';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { useCallback } from 'react';
|
||||
import { QUERY_MAX_RECORDS } from 'twenty-shared/constants';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
@@ -28,12 +30,16 @@ export const useRunWorkflowRecordActions = ({
|
||||
}) => {
|
||||
const { getIcon } = useIcons();
|
||||
const { enqueueWarningSnackBar } = useSnackBar();
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const { recordIndexId } = useRecordIndexIdFromCurrentContextStore();
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const isPageInEditMode = useRecoilComponentValue(
|
||||
const isPageInEditMode = useRecoilComponentValueV2(
|
||||
contextStoreIsPageInEditModeComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const selectedRecordIds =
|
||||
@@ -49,69 +55,68 @@ export const useRunWorkflowRecordActions = ({
|
||||
|
||||
const { runWorkflowVersion } = useRunWorkflowVersion();
|
||||
|
||||
const runWorkflowVersionOnSelectedRecords = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async (
|
||||
selectedRecordIds: string[],
|
||||
activeWorkflowVersion: Pick<
|
||||
WorkflowVersion,
|
||||
'id' | 'workflowId' | 'trigger'
|
||||
>,
|
||||
) => {
|
||||
if (selectedRecordIds.length > QUERY_MAX_RECORDS) {
|
||||
const selectedCountFormatted =
|
||||
selectedRecordIds.length.toLocaleString();
|
||||
const limitFormatted = QUERY_MAX_RECORDS.toLocaleString();
|
||||
const runWorkflowVersionOnSelectedRecords = useCallback(
|
||||
async (
|
||||
selectedRecordIds: string[],
|
||||
activeWorkflowVersion: Pick<
|
||||
WorkflowVersion,
|
||||
'id' | 'workflowId' | 'trigger'
|
||||
>,
|
||||
) => {
|
||||
if (selectedRecordIds.length > QUERY_MAX_RECORDS) {
|
||||
const selectedCountFormatted =
|
||||
selectedRecordIds.length.toLocaleString();
|
||||
const limitFormatted = QUERY_MAX_RECORDS.toLocaleString();
|
||||
|
||||
enqueueWarningSnackBar({
|
||||
message: t`You selected ${selectedCountFormatted} records but manual triggers can run on at most ${limitFormatted} records at once. Only the first ${limitFormatted} records will be processed.`,
|
||||
options: {
|
||||
dedupeKey: 'workflow-manual-trigger-selection-limit',
|
||||
},
|
||||
});
|
||||
}
|
||||
enqueueWarningSnackBar({
|
||||
message: t`You selected ${selectedCountFormatted} records but manual triggers can run on at most ${limitFormatted} records at once. Only the first ${limitFormatted} records will be processed.`,
|
||||
options: {
|
||||
dedupeKey: 'workflow-manual-trigger-selection-limit',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const limitedSelectedRecordIds = selectedRecordIds.slice(
|
||||
0,
|
||||
QUERY_MAX_RECORDS,
|
||||
);
|
||||
const limitedSelectedRecordIds = selectedRecordIds.slice(
|
||||
0,
|
||||
QUERY_MAX_RECORDS,
|
||||
);
|
||||
|
||||
if (
|
||||
isDefined(activeWorkflowVersion?.trigger) &&
|
||||
isBulkRecordsManualTrigger(activeWorkflowVersion.trigger)
|
||||
) {
|
||||
const objectNamePlural = objectMetadataItem.namePlural;
|
||||
const selectedRecords = limitedSelectedRecordIds
|
||||
.map((recordId) =>
|
||||
snapshot.getLoadable(recordStoreFamilyState(recordId)).getValue(),
|
||||
)
|
||||
.filter(isDefined);
|
||||
if (
|
||||
isDefined(activeWorkflowVersion?.trigger) &&
|
||||
isBulkRecordsManualTrigger(activeWorkflowVersion.trigger)
|
||||
) {
|
||||
const objectNamePlural = objectMetadataItem.namePlural;
|
||||
const selectedRecords = limitedSelectedRecordIds
|
||||
.map((recordId) =>
|
||||
jotaiStore.get(recordStoreFamilyState.atomFamily(recordId)),
|
||||
)
|
||||
.filter(isDefined);
|
||||
|
||||
await runWorkflowVersion({
|
||||
workflowId: activeWorkflowVersion.workflowId,
|
||||
workflowVersionId: activeWorkflowVersion.id,
|
||||
payload: {
|
||||
[objectNamePlural]: selectedRecords,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
for (const selectedRecordId of limitedSelectedRecordIds) {
|
||||
const selectedRecord = jotaiStore.get(
|
||||
recordStoreFamilyState.atomFamily(selectedRecordId),
|
||||
);
|
||||
|
||||
if (!isDefined(selectedRecord)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await runWorkflowVersion({
|
||||
workflowId: activeWorkflowVersion.workflowId,
|
||||
workflowVersionId: activeWorkflowVersion.id,
|
||||
payload: {
|
||||
[objectNamePlural]: selectedRecords,
|
||||
},
|
||||
payload: selectedRecord,
|
||||
});
|
||||
} else {
|
||||
for (const selectedRecordId of limitedSelectedRecordIds) {
|
||||
const selectedRecord = snapshot
|
||||
.getLoadable(recordStoreFamilyState(selectedRecordId))
|
||||
.getValue();
|
||||
|
||||
if (!isDefined(selectedRecord)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await runWorkflowVersion({
|
||||
workflowId: activeWorkflowVersion.workflowId,
|
||||
workflowVersionId: activeWorkflowVersion.id,
|
||||
payload: selectedRecord,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
[runWorkflowVersion, objectMetadataItem, enqueueWarningSnackBar],
|
||||
);
|
||||
|
||||
|
||||
+5
-2
@@ -3,7 +3,7 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions
|
||||
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
|
||||
import { useCreateFavorite } from '@/favorites/hooks/useCreateFavorite';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const AddToFavoritesSingleRecordAction = () => {
|
||||
@@ -13,7 +13,10 @@ export const AddToFavoritesSingleRecordAction = () => {
|
||||
|
||||
const { createFavorite } = useCreateFavorite();
|
||||
|
||||
const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
const selectedRecord = useFamilyRecoilValueV2(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
|
||||
const handleClick = () => {
|
||||
if (!isDefined(selectedRecord)) {
|
||||
|
||||
+5
-2
@@ -1,13 +1,16 @@
|
||||
import { Action } from '@/action-menu/actions/components/Action';
|
||||
import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const ExportNoteActionSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
|
||||
const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
const selectedRecord = useFamilyRecoilValueV2(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
|
||||
const filename = `${(selectedRecord?.title || 'Untitled Note').replace(/[<>:"/\\|?*]/g, '-')}`;
|
||||
|
||||
|
||||
+2
-2
@@ -2,14 +2,14 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions
|
||||
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { useExportSingleRecord } from '@/object-record/record-show/hooks/useExportSingleRecord';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
|
||||
import { Action } from '@/action-menu/actions/components/Action';
|
||||
|
||||
export const ExportSingleRecordAction = () => {
|
||||
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
|
||||
|
||||
const contextStoreCurrentViewId = useRecoilComponentValue(
|
||||
const contextStoreCurrentViewId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
|
||||
+5
-2
@@ -4,12 +4,15 @@ import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useResetDraftPageLayoutToPersistedPageLayout } from '@/page-layout/hooks/useResetDraftPageLayoutToPersistedPageLayout';
|
||||
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
|
||||
export const CancelDashboardSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
|
||||
const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
const selectedRecord = useFamilyRecoilValueV2(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
|
||||
const pageLayoutId = selectedRecord?.pageLayoutId;
|
||||
|
||||
|
||||
+5
-2
@@ -2,13 +2,16 @@ import { Action } from '@/action-menu/actions/components/Action';
|
||||
import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { useResetLocationHash } from 'twenty-ui/utilities';
|
||||
|
||||
export const EditDashboardSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
|
||||
const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
const selectedRecord = useFamilyRecoilValueV2(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
|
||||
const pageLayoutId = selectedRecord?.pageLayoutId;
|
||||
|
||||
|
||||
+5
-2
@@ -4,12 +4,15 @@ import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useSavePageLayout } from '@/page-layout/hooks/useSavePageLayout';
|
||||
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
|
||||
export const SaveDashboardSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
|
||||
const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
const selectedRecord = useFamilyRecoilValueV2(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
|
||||
const pageLayoutId = selectedRecord?.pageLayoutId;
|
||||
|
||||
|
||||
+6
-2
@@ -1,9 +1,13 @@
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const useSelectedRecordIdOrThrow = () => {
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const { recordIndexId } = useRecordIndexIdFromCurrentContextStore();
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
if (
|
||||
|
||||
+6
-2
@@ -1,9 +1,13 @@
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const useSelectedRecordIds = () => {
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const { recordIndexId } = useRecordIndexIdFromCurrentContextStore();
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
if (
|
||||
|
||||
+12
-18
@@ -4,7 +4,7 @@ import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUp
|
||||
import { getWorkflowVisualizerComponentInstanceId } from '@/workflow/utils/getWorkflowVisualizerComponentInstanceId';
|
||||
import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState';
|
||||
import { useTidyUpWorkflowVersion } from '@/workflow/workflow-version/hooks/useTidyUpWorkflowVersion';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const TidyUpWorkflowSingleRecordAction = () => {
|
||||
@@ -16,26 +16,20 @@ export const TidyUpWorkflowSingleRecordAction = () => {
|
||||
const { getUpdatableWorkflowVersion } =
|
||||
useGetUpdatableWorkflowVersionOrThrow(instanceId);
|
||||
|
||||
const onClick = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async () => {
|
||||
const workflowDiagramState = workflowDiagramComponentState.atomFamily({
|
||||
instanceId,
|
||||
});
|
||||
const workflowDiagram = snapshot
|
||||
.getLoadable(workflowDiagramState)
|
||||
.getValue();
|
||||
const onClick = async () => {
|
||||
const workflowDiagramAtom = workflowDiagramComponentState.atomFamily({
|
||||
instanceId,
|
||||
});
|
||||
const workflowDiagram = jotaiStore.get(workflowDiagramAtom);
|
||||
|
||||
if (!isDefined(workflowDiagram)) {
|
||||
return;
|
||||
}
|
||||
if (!isDefined(workflowDiagram)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion();
|
||||
const workflowVersionId = await getUpdatableWorkflowVersion();
|
||||
|
||||
await tidyUpWorkflowVersion(workflowVersionId, workflowDiagram);
|
||||
},
|
||||
[getUpdatableWorkflowVersion, tidyUpWorkflowVersion, instanceId],
|
||||
);
|
||||
await tidyUpWorkflowVersion(workflowVersionId, workflowDiagram);
|
||||
};
|
||||
|
||||
return <Action onClick={onClick} />;
|
||||
};
|
||||
|
||||
+2
-2
@@ -2,13 +2,13 @@ import { ActionLink } from '@/action-menu/actions/components/ActionLink';
|
||||
import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { AppPath } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeVersionWorkflowRunSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
const workflowRun = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
const workflowRun = useFamilyRecoilValueV2(recordStoreFamilyState, recordId);
|
||||
|
||||
if (!isDefined(workflowRun) || !isDefined(workflowRun?.workflowVersion?.id)) {
|
||||
return null;
|
||||
|
||||
+2
-2
@@ -2,13 +2,13 @@ import { ActionLink } from '@/action-menu/actions/components/ActionLink';
|
||||
import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { AppPath } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeWorkflowWorkflowRunSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
const workflowRun = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
const workflowRun = useFamilyRecoilValueV2(recordStoreFamilyState, recordId);
|
||||
|
||||
if (!isDefined(workflowRun) || !isDefined(workflowRun?.workflow?.id)) {
|
||||
return null;
|
||||
|
||||
+11
-6
@@ -9,26 +9,31 @@ import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryP
|
||||
import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords';
|
||||
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useStopWorkflowRun } from '@/workflow/hooks/useStopWorkflowRun';
|
||||
|
||||
export const StopWorkflowRunSingleRecordAction = () => {
|
||||
const { objectMetadataItem } = useRecordIndexIdFromCurrentContextStore();
|
||||
const { objectMetadataItem, recordIndexId } =
|
||||
useRecordIndexIdFromCurrentContextStore();
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreFilters = useRecoilComponentValue(
|
||||
const contextStoreFilters = useRecoilComponentValueV2(
|
||||
contextStoreFiltersComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreFilterGroups = useRecoilComponentValue(
|
||||
const contextStoreFilterGroups = useRecoilComponentValueV2(
|
||||
contextStoreFilterGroupsComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const contextStoreAnyFieldFilterValue = useRecoilComponentValue(
|
||||
const contextStoreAnyFieldFilterValue = useRecoilComponentValueV2(
|
||||
contextStoreAnyFieldFilterValueComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const { filterValueDependencies } = useFilterValueDependencies();
|
||||
|
||||
+5
-2
@@ -2,8 +2,8 @@ import { ActionLink } from '@/action-menu/actions/components/ActionLink';
|
||||
import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
|
||||
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { AppPath, ViewFilterOperand } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@@ -40,7 +40,10 @@ const SeeRunsWorkflowVersionSingleRecordActionContent = ({
|
||||
|
||||
export const SeeRunsWorkflowVersionSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
const workflowVersion = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
const workflowVersion = useFamilyRecoilValueV2(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
|
||||
const workflowId = workflowVersion?.workflow?.id;
|
||||
|
||||
|
||||
+5
-2
@@ -3,7 +3,7 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions
|
||||
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { AppPath, ViewFilterOperand } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@@ -33,7 +33,10 @@ const SeeVersionsWorkflowVersionSingleRecordActionContent = ({
|
||||
|
||||
export const SeeVersionsWorkflowVersionSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
const workflowVersion = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
const workflowVersion = useFamilyRecoilValueV2(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
|
||||
if (!isDefined(workflowVersion) || !isDefined(workflowVersion.workflowId)) {
|
||||
return null;
|
||||
|
||||
+5
-2
@@ -2,12 +2,15 @@ import { ActionLink } from '@/action-menu/actions/components/ActionLink';
|
||||
import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { AppPath } from 'twenty-shared/types';
|
||||
|
||||
export const SeeWorkflowWorkflowVersionSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
const workflowVersion = useRecoilValue(recordStoreFamilyState(recordId));
|
||||
const workflowVersion = useFamilyRecoilValueV2(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
|
||||
return (
|
||||
<ActionLink
|
||||
|
||||
+4
-2
@@ -2,8 +2,9 @@ import { Action } from '@/action-menu/actions/components/Action';
|
||||
import { ActionScope } from '@/action-menu/actions/types/ActionScope';
|
||||
import { ActionType } from '@/action-menu/actions/types/ActionType';
|
||||
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useActiveWorkflowVersionsWithManualTrigger } from '@/workflow/hooks/useActiveWorkflowVersionsWithManualTrigger';
|
||||
import { useRunWorkflowVersion } from '@/workflow/hooks/useRunWorkflowVersion';
|
||||
import { COMMAND_MENU_DEFAULT_ICON } from '@/workflow/workflow-trigger/constants/CommandMenuDefaultIcon';
|
||||
@@ -14,8 +15,9 @@ import { useIcons } from 'twenty-ui/display';
|
||||
export const useRunWorkflowRecordAgnosticActions = () => {
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const isPageInEditMode = useRecoilComponentValue(
|
||||
const isPageInEditMode = useRecoilComponentValueV2(
|
||||
contextStoreIsPageInEditModeComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const { actionMenuType } = useContext(ActionMenuContext);
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { createState } from '@/ui/utilities/state/utils/createState';
|
||||
import { createStateV2 } from '@/ui/utilities/state/jotai/utils/createStateV2';
|
||||
|
||||
export const forceRegisteredActionsByKeyState = createState<
|
||||
export const forceRegisteredActionsByKeyState = createStateV2<
|
||||
Record<string, boolean | undefined>
|
||||
>({
|
||||
key: 'forceRegisteredActionsByKeyComponentState',
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { PageHeaderActionMenuButtons } from '@/action-menu/components/PageHeaderActionMenuButtons';
|
||||
import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown';
|
||||
import { ActionMenuContextProvider } from '@/action-menu/contexts/ActionMenuContextProvider';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
export const RecordIndexActionMenu = () => {
|
||||
const contextStoreCurrentObjectMetadataItemId = useRecoilComponentValue(
|
||||
const contextStoreCurrentObjectMetadataItemId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
+1
-2
@@ -15,7 +15,6 @@ import { SelectableList } from '@/ui/layout/selectable-list/components/Selectabl
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
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 { useLingui } from '@lingui/react/macro';
|
||||
@@ -50,7 +49,7 @@ export const RecordIndexActionMenuDropdown = () => {
|
||||
const dropdownId = getActionMenuDropdownIdFromActionMenuId(actionMenuId);
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const actionMenuDropdownPosition = useRecoilComponentValue(
|
||||
const actionMenuDropdownPosition = useRecoilComponentValueV2(
|
||||
recordIndexActionMenuDropdownPositionComponentState,
|
||||
dropdownId,
|
||||
);
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import { PageHeaderActionMenuButtons } from '@/action-menu/components/PageHeaderActionMenuButtons';
|
||||
import { ActionMenuContextProvider } from '@/action-menu/contexts/ActionMenuContextProvider';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
export const RecordShowActionMenu = () => {
|
||||
const contextStoreCurrentObjectMetadataItemId = useRecoilComponentValue(
|
||||
const contextStoreCurrentObjectMetadataItemId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const hasSelectedRecord =
|
||||
|
||||
+4
-2
@@ -1,11 +1,13 @@
|
||||
import { CommandMenuActionMenuDropdown } from '@/action-menu/components/CommandMenuActionMenuDropdown';
|
||||
import { ActionMenuContextProvider } from '@/action-menu/contexts/ActionMenuContextProvider';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const RecordShowRightDrawerActionMenu = () => {
|
||||
const contextStoreCurrentObjectMetadataItemId = useRecoilComponentValue(
|
||||
const contextStoreCurrentObjectMetadataItemId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
+45
-43
@@ -14,11 +14,13 @@ import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTab
|
||||
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useComponentInstanceStateContext } from '@/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext';
|
||||
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
|
||||
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useRecoilCallback, useRecoilValue } from 'recoil';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { AppPath } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconBrowserMaximize } from 'twenty-ui/display';
|
||||
@@ -35,9 +37,10 @@ export const RecordShowRightDrawerOpenRecordButton = ({
|
||||
objectNameSingular,
|
||||
recordId,
|
||||
}: RecordShowRightDrawerOpenRecordButtonProps) => {
|
||||
const record = useRecoilValue<ObjectRecord | null | undefined>(
|
||||
recordStoreFamilyState(recordId),
|
||||
);
|
||||
const record = useFamilyRecoilValueV2(recordStoreFamilyState, recordId) as
|
||||
| ObjectRecord
|
||||
| null
|
||||
| undefined;
|
||||
const { closeCommandMenu } = useCommandMenu();
|
||||
|
||||
const commandMenuPageComponentInstance = useComponentInstanceStateContext(
|
||||
@@ -63,11 +66,13 @@ export const RecordShowRightDrawerOpenRecordButton = ({
|
||||
tabListComponentIdInRecordPage,
|
||||
);
|
||||
|
||||
const parentViewState = useRecoilComponentCallbackState(
|
||||
const parentViewState = useRecoilComponentStateCallbackStateV2(
|
||||
contextStoreRecordShowParentViewComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const navigate = useNavigateApp();
|
||||
|
||||
const actionMenuId = useAvailableComponentInstanceIdOrThrow(
|
||||
@@ -76,48 +81,45 @@ export const RecordShowRightDrawerOpenRecordButton = ({
|
||||
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const handleOpenRecord = useRecoilCallback(
|
||||
({ snapshot, reset }) =>
|
||||
() => {
|
||||
const tabIdToOpen =
|
||||
activeTabIdInRightDrawer === 'home'
|
||||
? objectNameSingular === CoreObjectNameSingular.Note ||
|
||||
objectNameSingular === CoreObjectNameSingular.Task
|
||||
? 'richText'
|
||||
: 'timeline'
|
||||
: activeTabIdInRightDrawer;
|
||||
const handleOpenRecord = useCallback(() => {
|
||||
const tabIdToOpen =
|
||||
activeTabIdInRightDrawer === 'home'
|
||||
? objectNameSingular === CoreObjectNameSingular.Note ||
|
||||
objectNameSingular === CoreObjectNameSingular.Task
|
||||
? 'richText'
|
||||
: 'timeline'
|
||||
: activeTabIdInRightDrawer;
|
||||
|
||||
setActiveTabIdInRecordPage(tabIdToOpen);
|
||||
setActiveTabIdInRecordPage(tabIdToOpen);
|
||||
|
||||
const parentView = snapshot.getLoadable(parentViewState).getValue();
|
||||
const parentView = store.get(parentViewState);
|
||||
|
||||
if (parentView?.parentViewObjectNameSingular !== objectNameSingular) {
|
||||
reset(parentViewState);
|
||||
}
|
||||
if (parentView?.parentViewObjectNameSingular !== objectNameSingular) {
|
||||
store.set(parentViewState, undefined);
|
||||
}
|
||||
|
||||
navigate(AppPath.RecordShowPage, {
|
||||
objectNameSingular,
|
||||
objectRecordId: recordId,
|
||||
});
|
||||
|
||||
closeDropdown(
|
||||
getRightDrawerActionMenuDropdownIdFromActionMenuId(actionMenuId),
|
||||
);
|
||||
|
||||
closeCommandMenu();
|
||||
},
|
||||
[
|
||||
actionMenuId,
|
||||
activeTabIdInRightDrawer,
|
||||
closeCommandMenu,
|
||||
closeDropdown,
|
||||
navigate,
|
||||
navigate(AppPath.RecordShowPage, {
|
||||
objectNameSingular,
|
||||
parentViewState,
|
||||
recordId,
|
||||
setActiveTabIdInRecordPage,
|
||||
],
|
||||
);
|
||||
objectRecordId: recordId,
|
||||
});
|
||||
|
||||
closeDropdown(
|
||||
getRightDrawerActionMenuDropdownIdFromActionMenuId(actionMenuId),
|
||||
);
|
||||
|
||||
closeCommandMenu();
|
||||
}, [
|
||||
actionMenuId,
|
||||
activeTabIdInRightDrawer,
|
||||
closeCommandMenu,
|
||||
closeDropdown,
|
||||
navigate,
|
||||
objectNameSingular,
|
||||
parentViewState,
|
||||
recordId,
|
||||
setActiveTabIdInRecordPage,
|
||||
store,
|
||||
]);
|
||||
|
||||
useHotkeysOnFocusedElement({
|
||||
keys: ['ctrl+Enter,meta+Enter'],
|
||||
|
||||
+37
-37
@@ -1,5 +1,5 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { Provider as JotaiProvider } from 'jotai';
|
||||
import * as test from 'storybook/test';
|
||||
import { expect, userEvent, waitFor, within } from 'storybook/test';
|
||||
|
||||
@@ -7,10 +7,14 @@ import { CommandMenuActionMenuDropdown } from '@/action-menu/components/CommandM
|
||||
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { createMockActionMenuActions } from '@/action-menu/mock/action-menu-actions.mock';
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { ComponentDecorator, RouterDecorator } from 'twenty-ui/testing';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { ContextStoreDecorator } from '~/testing/decorators/ContextStoreDecorator';
|
||||
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
import { JestContextStoreSetter } from '~/testing/jest/JestContextStoreSetter';
|
||||
const deleteMock = test.fn();
|
||||
const addToFavoritesMock = test.fn();
|
||||
const exportMock = test.fn();
|
||||
@@ -20,47 +24,43 @@ const meta: Meta<typeof CommandMenuActionMenuDropdown> = {
|
||||
component: CommandMenuActionMenuDropdown,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<RecoilRoot
|
||||
initializeState={({ set }) => {
|
||||
set(
|
||||
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
||||
instanceId: 'story-action-menu',
|
||||
}),
|
||||
{
|
||||
<JotaiProvider store={jotaiStore}>
|
||||
<ContextStoreComponentInstanceContext.Provider
|
||||
value={{ instanceId: MAIN_CONTEXT_STORE_INSTANCE_ID }}
|
||||
>
|
||||
<JestContextStoreSetter
|
||||
contextStoreTargetedRecordsRule={{
|
||||
mode: 'selection',
|
||||
selectedRecordIds: ['1'],
|
||||
},
|
||||
);
|
||||
set(
|
||||
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
|
||||
instanceId: 'story-action-menu',
|
||||
}),
|
||||
1,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'story-action-menu' }}
|
||||
>
|
||||
<ActionMenuContext.Provider
|
||||
value={{
|
||||
isInRightDrawer: true,
|
||||
displayType: 'dropdownItem',
|
||||
actionMenuType: 'command-menu-show-page-action-menu-dropdown',
|
||||
actions: createMockActionMenuActions({
|
||||
deleteMock,
|
||||
addToFavoritesMock,
|
||||
exportMock,
|
||||
}),
|
||||
}}
|
||||
contextStoreNumberOfSelectedRecords={1}
|
||||
>
|
||||
<Story />
|
||||
</ActionMenuContext.Provider>
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'story-action-menu' }}
|
||||
>
|
||||
<ActionMenuContext.Provider
|
||||
value={{
|
||||
isInRightDrawer: true,
|
||||
displayType: 'dropdownItem',
|
||||
actionMenuType: 'command-menu-show-page-action-menu-dropdown',
|
||||
actions: createMockActionMenuActions({
|
||||
deleteMock,
|
||||
addToFavoritesMock,
|
||||
exportMock,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
</ActionMenuContext.Provider>
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
</JestContextStoreSetter>
|
||||
</ContextStoreComponentInstanceContext.Provider>
|
||||
</JotaiProvider>
|
||||
),
|
||||
ComponentDecorator,
|
||||
ContextStoreDecorator,
|
||||
ObjectMetadataItemsDecorator,
|
||||
SnackBarDecorator,
|
||||
RouterDecorator,
|
||||
],
|
||||
args: {
|
||||
|
||||
+22
-28
@@ -1,6 +1,5 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
||||
import { Provider as JotaiProvider } from 'jotai';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import * as test from 'storybook/test';
|
||||
import { expect, userEvent, waitFor, within } from 'storybook/test';
|
||||
|
||||
@@ -30,38 +29,33 @@ const meta: Meta<typeof RecordIndexActionMenuDropdown> = {
|
||||
}),
|
||||
true,
|
||||
);
|
||||
jotaiStore.set(
|
||||
recordIndexActionMenuDropdownPositionComponentState.atomFamily({
|
||||
instanceId: 'action-menu-dropdown-story',
|
||||
}),
|
||||
{ x: 10, y: 10 },
|
||||
);
|
||||
|
||||
return (
|
||||
<JotaiProvider store={jotaiStore}>
|
||||
<RecoilRoot
|
||||
initializeState={({ set }) => {
|
||||
set(
|
||||
recordIndexActionMenuDropdownPositionComponentState.atomFamily({
|
||||
instanceId: 'action-menu-dropdown-story',
|
||||
}),
|
||||
{ x: 10, y: 10 },
|
||||
);
|
||||
}}
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'story-action-menu' }}
|
||||
>
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'story-action-menu' }}
|
||||
<ActionMenuContext.Provider
|
||||
value={{
|
||||
isInRightDrawer: true,
|
||||
displayType: 'dropdownItem',
|
||||
actionMenuType: 'index-page-action-menu-dropdown',
|
||||
actions: createMockActionMenuActions({
|
||||
deleteMock,
|
||||
addToFavoritesMock,
|
||||
exportMock,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<ActionMenuContext.Provider
|
||||
value={{
|
||||
isInRightDrawer: true,
|
||||
displayType: 'dropdownItem',
|
||||
actionMenuType: 'index-page-action-menu-dropdown',
|
||||
actions: createMockActionMenuActions({
|
||||
deleteMock,
|
||||
addToFavoritesMock,
|
||||
exportMock,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
</ActionMenuContext.Provider>
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
<Story />
|
||||
</ActionMenuContext.Provider>
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
</JotaiProvider>
|
||||
);
|
||||
},
|
||||
|
||||
+4
-2
@@ -1,11 +1,12 @@
|
||||
import { type ActionMenuContextType } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { ActionMenuContextProviderDefault } from '@/action-menu/contexts/ActionMenuContextProviderDefault';
|
||||
import { ActionMenuContextProviderWorkflowObjects } from '@/action-menu/contexts/ActionMenuContextProviderWorkflowObjects';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
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';
|
||||
|
||||
@@ -19,8 +20,9 @@ export const ActionMenuContextProvider = ({
|
||||
children: React.ReactNode;
|
||||
objectMetadataItemOverride?: ObjectMetadataItem;
|
||||
}) => {
|
||||
const contextStoreCurrentObjectMetadataItemId = useRecoilComponentValue(
|
||||
const contextStoreCurrentObjectMetadataItemId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const objectMetadataItems = useRecoilValueV2(objectMetadataItemsState);
|
||||
|
||||
+4
-2
@@ -7,9 +7,10 @@ import {
|
||||
import { useRegisteredActions } from '@/action-menu/hooks/useRegisteredActions';
|
||||
import { useShouldActionBeRegisteredParams } from '@/action-menu/hooks/useShouldActionBeRegisteredParams';
|
||||
import { useCommandMenuItemFrontComponentActions } from '@/command-menu-item/hooks/useCommandMenuItemFrontComponentActions';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const ActionMenuContextProviderDefault = ({
|
||||
objectMetadataItem,
|
||||
@@ -34,8 +35,9 @@ export const ActionMenuContextProviderDefault = ({
|
||||
|
||||
const actions = useRegisteredActions(shouldBeRegisteredParams);
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const isRecordSelection =
|
||||
|
||||
+6
-4
@@ -6,13 +6,14 @@ import {
|
||||
import { useRegisteredActions } from '@/action-menu/hooks/useRegisteredActions';
|
||||
import { useShouldActionBeRegisteredParams } from '@/action-menu/hooks/useShouldActionBeRegisteredParams';
|
||||
import { useCommandMenuItemFrontComponentActions } from '@/command-menu-item/hooks/useCommandMenuItemFrontComponentActions';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type ActionMenuContextProviderWorkflowObjectsProps = {
|
||||
@@ -122,8 +123,9 @@ export const ActionMenuContextProviderWorkflowObjects = ({
|
||||
actionMenuType,
|
||||
children,
|
||||
}: ActionMenuContextProviderWorkflowObjectsProps) => {
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const recordId =
|
||||
@@ -133,7 +135,7 @@ export const ActionMenuContextProviderWorkflowObjects = ({
|
||||
: undefined;
|
||||
|
||||
const selectedRecord =
|
||||
useRecoilValue(recordStoreFamilyState(recordId ?? '')) || undefined;
|
||||
useFamilyRecoilValueV2(recordStoreFamilyState, recordId ?? '') || undefined;
|
||||
|
||||
if (isDefined(selectedRecord?.id)) {
|
||||
return (
|
||||
|
||||
@@ -4,11 +4,13 @@ import { ActionViewType } from '@/action-menu/actions/types/ActionViewType';
|
||||
import { type ShouldBeRegisteredFunctionParams } from '@/action-menu/actions/types/ShouldBeRegisteredFunctionParams';
|
||||
import { getActionConfig } from '@/action-menu/actions/utils/getActionConfig';
|
||||
import { getActionViewType } from '@/action-menu/actions/utils/getActionViewType';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
|
||||
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
|
||||
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';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
|
||||
@@ -20,16 +22,21 @@ export const useRegisteredActions = (
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const contextStoreCurrentViewType = useRecoilComponentValue(
|
||||
const contextStoreCurrentViewType = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewTypeComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const isFullTabWidgetInEditMode = useRecoilComponentValue(
|
||||
const { recordIndexId } = useRecordIndexIdFromCurrentContextStore();
|
||||
|
||||
const isFullTabWidgetInEditMode = useRecoilComponentValueV2(
|
||||
contextStoreIsPageInEditModeComponentState,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const viewType = getActionViewType(
|
||||
|
||||
+21
-10
@@ -4,6 +4,7 @@ import { getActionViewType } from '@/action-menu/actions/utils/getActionViewType
|
||||
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { objectPermissionsFamilySelector } from '@/auth/states/objectPermissionsFamilySelector';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
@@ -12,15 +13,17 @@ import { useFavorites } from '@/favorites/hooks/useFavorites';
|
||||
import { usePrefetchedNavigationMenuItemsData } from '@/navigation-menu-item/hooks/usePrefetchedNavigationMenuItemsData';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
|
||||
import { hasAnySoftDeleteFilterOnViewComponentSelector } from '@/object-record/record-filter/states/hasAnySoftDeleteFilterOnView';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { useCallback, useContext, useMemo } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
||||
|
||||
@@ -35,8 +38,9 @@ export const useShouldActionBeRegisteredParams = ({
|
||||
FeatureFlagKey.IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED,
|
||||
);
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValue(
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const recordId =
|
||||
@@ -71,7 +75,7 @@ export const useShouldActionBeRegisteredParams = ({
|
||||
]);
|
||||
|
||||
const selectedRecord =
|
||||
useRecoilValue(recordStoreFamilyState(recordId ?? '')) || undefined;
|
||||
useFamilyRecoilValueV2(recordStoreFamilyState, recordId ?? '') || undefined;
|
||||
|
||||
const objectPermissions = useObjectPermissionsForObject(
|
||||
objectMetadataItem?.id ?? '',
|
||||
@@ -83,20 +87,27 @@ export const useShouldActionBeRegisteredParams = ({
|
||||
|
||||
const { isInRightDrawer } = useContext(ActionMenuContext);
|
||||
|
||||
const hasAnySoftDeleteFilterOnView = useRecoilComponentValue(
|
||||
const { recordIndexId } = useRecordIndexIdFromCurrentContextStore();
|
||||
|
||||
const hasAnySoftDeleteFilterOnView = useRecoilComponentSelectorValueV2(
|
||||
hasAnySoftDeleteFilterOnViewComponentSelector,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const isShowPage =
|
||||
useRecoilComponentValue(contextStoreCurrentViewTypeComponentState) ===
|
||||
ContextStoreViewType.ShowPage;
|
||||
useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewTypeComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
) === ContextStoreViewType.ShowPage;
|
||||
|
||||
const numberOfSelectedRecords = useRecoilComponentValue(
|
||||
const numberOfSelectedRecords = useRecoilComponentValueV2(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const contextStoreCurrentViewType = useRecoilComponentValue(
|
||||
const contextStoreCurrentViewType = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewTypeComponentState,
|
||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const viewType = getActionViewType(
|
||||
@@ -128,7 +139,7 @@ export const useShouldActionBeRegisteredParams = ({
|
||||
[],
|
||||
);
|
||||
|
||||
const forceRegisteredActionsByKey = useRecoilValue(
|
||||
const forceRegisteredActionsByKey = useRecoilValueV2(
|
||||
forceRegisteredActionsByKeyState,
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { type PositionType } from '@/action-menu/types/PositionType';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
|
||||
|
||||
export const recordIndexActionMenuDropdownPositionComponentState =
|
||||
createComponentState<PositionType>({
|
||||
createComponentStateV2<PositionType>({
|
||||
key: 'recordIndexActionMenuDropdownPositionComponentState',
|
||||
defaultValue: {
|
||||
x: null,
|
||||
|
||||
Reference in New Issue
Block a user