Refactor actions (#8761)

Closes #8737 
- Refactored actions by creating hooks to add the possibility to
register actions programatically.
- Small fixes from #8610 review
- Fixed shortcuts display inside the command menu
- Removed `actionMenuEntriesComponentState` and introduced
`actionMenuEntriesComponentSelector`
This commit is contained in:
Raphaël Bosi
2024-11-27 15:08:27 +01:00
committed by GitHub
parent 0d6a6ec678
commit a9cb1e9b0d
40 changed files with 682 additions and 479 deletions

View File

@ -1,8 +0,0 @@
import { WorkflowRunActionEffect } from '@/action-menu/actions/global-actions/workflow-run-actions/components/WorkflowRunActionEffect';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
export const GlobalActionMenuEntriesSetter = () => {
const isWorkflowEnabled = useIsFeatureEnabled('IS_WORKFLOW_ENABLED');
return <>{isWorkflowEnabled && <WorkflowRunActionEffect />}</>;
};

View File

@ -1,26 +1,12 @@
import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect';
import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect';
import { ManageFavoritesActionEffect } from '@/action-menu/actions/record-actions/components/ManageFavoritesActionEffect';
import { WorkflowRunRecordActionEffect } from '@/action-menu/actions/record-actions/workflow-run-record-actions/components/WorkflowRunRecordActionEffect';
import { MultipleRecordsActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/multiple-records/components/MultipleRecordsActionMenuEntrySetterEffect';
import { NoSelectionActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/no-selection/components/NoSelectionActionMenuEntrySetterEffect';
import { SingleRecordActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/single-record/components/SingleRecordActionMenuEntrySetterEffect';
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { isDefined } from 'twenty-ui';
const noSelectionRecordActionEffects = [ExportRecordsActionEffect];
const singleRecordActionEffects = [
ManageFavoritesActionEffect,
DeleteRecordsActionEffect,
];
const multipleRecordActionEffects = [
ExportRecordsActionEffect,
DeleteRecordsActionEffect,
];
export const RecordActionMenuEntriesSetter = () => {
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataIdComponentState,
@ -48,26 +34,20 @@ const ActionEffects = ({
contextStoreNumberOfSelectedRecordsComponentState,
);
const isWorkflowEnabled = useIsFeatureEnabled('IS_WORKFLOW_ENABLED');
const actions =
contextStoreNumberOfSelectedRecords === 0
? noSelectionRecordActionEffects
: contextStoreNumberOfSelectedRecords === 1
? singleRecordActionEffects
: multipleRecordActionEffects;
return (
<>
{actions.map((ActionEffect, index) => (
<ActionEffect
key={index}
position={index}
{contextStoreNumberOfSelectedRecords === 0 && (
<NoSelectionActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
/>
))}
{contextStoreNumberOfSelectedRecords === 1 && isWorkflowEnabled && (
<WorkflowRunRecordActionEffect
)}
{contextStoreNumberOfSelectedRecords === 1 && (
<SingleRecordActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
/>
)}
{contextStoreNumberOfSelectedRecords > 1 && (
<MultipleRecordsActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
/>
)}

View File

@ -0,0 +1,24 @@
import { useMultipleRecordsActions } from '@/action-menu/actions/record-actions/multiple-records/hooks/useMultipleRecordsActions';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useEffect } from 'react';
export const MultipleRecordsActionMenuEntrySetterEffect = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
}) => {
const { registerMultipleRecordsActions, unregisterMultipleRecordsActions } =
useMultipleRecordsActions({
objectMetadataItem,
});
useEffect(() => {
registerMultipleRecordsActions();
return () => {
unregisterMultipleRecordsActions();
};
}, [registerMultipleRecordsActions, unregisterMultipleRecordsActions]);
return null;
};

View File

@ -18,10 +18,10 @@ import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTabl
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useCallback, useContext, useEffect, useState } from 'react';
import { useCallback, useContext, useState } from 'react';
import { IconTrash, isDefined } from 'twenty-ui';
export const DeleteRecordsActionEffect = ({
export const useDeleteMultipleRecordsAction = ({
position,
objectMetadataItem,
}: {
@ -106,12 +106,12 @@ export const DeleteRecordsActionEffect = ({
const { isInRightDrawer, onActionExecutedCallback } =
useContext(ActionMenuContext);
useEffect(() => {
const registerDeleteMultipleRecordsAction = () => {
if (canDelete) {
addActionMenuEntry({
type: ActionMenuEntryType.Standard,
scope: ActionMenuEntryScope.RecordSelection,
key: 'delete',
key: 'delete-multiple-records',
label: 'Delete',
position,
Icon: IconTrash,
@ -124,16 +124,8 @@ export const DeleteRecordsActionEffect = ({
<ConfirmationModal
isOpen={isDeleteRecordsModalOpen}
setIsOpen={setIsDeleteRecordsModalOpen}
title={`Delete ${contextStoreNumberOfSelectedRecords} ${
contextStoreNumberOfSelectedRecords === 1 ? `record` : 'records'
}`}
subtitle={`Are you sure you want to delete ${
contextStoreNumberOfSelectedRecords === 1
? 'this record'
: 'these records'
}? ${
contextStoreNumberOfSelectedRecords === 1 ? 'It' : 'They'
} can be recovered from the Options menu.`}
title={'Delete Records'}
subtitle={`Are you sure you want to delete these records? They can be recovered from the Options menu.`}
onConfirmClick={() => {
handleDeleteClick();
onActionExecutedCallback?.();
@ -141,31 +133,19 @@ export const DeleteRecordsActionEffect = ({
closeRightDrawer();
}
}}
deleteButtonText={`Delete ${
contextStoreNumberOfSelectedRecords > 1 ? 'Records' : 'Record'
}`}
deleteButtonText={'Delete Records'}
/>
),
});
} else {
removeActionMenuEntry('delete');
}
};
return () => {
removeActionMenuEntry('delete');
};
}, [
addActionMenuEntry,
canDelete,
closeRightDrawer,
contextStoreNumberOfSelectedRecords,
handleDeleteClick,
isDeleteRecordsModalOpen,
isInRightDrawer,
onActionExecutedCallback,
position,
removeActionMenuEntry,
]);
const unregisterDeleteMultipleRecordsAction = () => {
removeActionMenuEntry('delete-multiple-records');
};
return null;
return {
registerDeleteMultipleRecordsAction,
unregisterDeleteMultipleRecordsAction,
};
};

View File

@ -1,7 +1,5 @@
import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries';
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { IconDatabaseExport } from 'twenty-ui';
import {
@ -12,9 +10,8 @@ import {
displayedExportProgress,
useExportRecords,
} from '@/object-record/record-index/export/hooks/useExportRecords';
import { useEffect } from 'react';
export const ExportRecordsActionEffect = ({
export const useExportMultipleRecordsAction = ({
position,
objectMetadataItem,
}: {
@ -22,9 +19,6 @@ export const ExportRecordsActionEffect = ({
objectMetadataItem: ObjectMetadataItem;
}) => {
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
contextStoreNumberOfSelectedRecordsComponentState,
);
const { progress, download } = useExportRecords({
delayMs: 100,
@ -33,32 +27,25 @@ export const ExportRecordsActionEffect = ({
filename: `${objectMetadataItem.nameSingular}.csv`,
});
useEffect(() => {
const registerExportMultipleRecordsAction = () => {
addActionMenuEntry({
type: ActionMenuEntryType.Standard,
scope:
contextStoreNumberOfSelectedRecords > 0
? ActionMenuEntryScope.RecordSelection
: ActionMenuEntryScope.Global,
key: 'export',
scope: ActionMenuEntryScope.RecordSelection,
key: 'export-multiple-records',
position,
label: displayedExportProgress(progress),
Icon: IconDatabaseExport,
accent: 'default',
onClick: () => download(),
});
};
return () => {
removeActionMenuEntry('export');
};
}, [
contextStoreNumberOfSelectedRecords,
download,
progress,
addActionMenuEntry,
removeActionMenuEntry,
position,
]);
const unregisterExportMultipleRecordsAction = () => {
removeActionMenuEntry('export-multiple-records');
};
return null;
return {
registerExportMultipleRecordsAction,
unregisterExportMultipleRecordsAction,
};
};

View File

@ -0,0 +1,40 @@
import { useDeleteMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction';
import { useExportViewNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useExportMultipleRecordsAction';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
export const useMultipleRecordsActions = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
}) => {
const {
registerDeleteMultipleRecordsAction,
unregisterDeleteMultipleRecordsAction,
} = useDeleteMultipleRecordsAction({
position: 0,
objectMetadataItem,
});
const {
registerExportViewNoSelectionRecordsAction,
unregisterExportViewNoSelectionRecordsAction,
} = useExportViewNoSelectionRecordAction({
position: 1,
objectMetadataItem,
});
const registerMultipleRecordsActions = () => {
registerDeleteMultipleRecordsAction();
registerExportViewNoSelectionRecordsAction();
};
const unregisterMultipleRecordsActions = () => {
unregisterDeleteMultipleRecordsAction();
unregisterExportViewNoSelectionRecordsAction();
};
return {
registerMultipleRecordsActions,
unregisterMultipleRecordsActions,
};
};

View File

@ -0,0 +1,26 @@
import { useNoSelectionRecordActions } from '@/action-menu/actions/record-actions/no-selection/hooks/useNoSelectionRecordActions';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useEffect } from 'react';
export const NoSelectionActionMenuEntrySetterEffect = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
}) => {
const {
registerNoSelectionRecordActions,
unregisterNoSelectionRecordActions,
} = useNoSelectionRecordActions({
objectMetadataItem,
});
useEffect(() => {
registerNoSelectionRecordActions();
return () => {
unregisterNoSelectionRecordActions();
};
}, [registerNoSelectionRecordActions, unregisterNoSelectionRecordActions]);
return null;
};

View File

@ -0,0 +1,51 @@
import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { IconDatabaseExport } from 'twenty-ui';
import {
ActionMenuEntryScope,
ActionMenuEntryType,
} from '@/action-menu/types/ActionMenuEntry';
import {
displayedExportProgress,
useExportRecords,
} from '@/object-record/record-index/export/hooks/useExportRecords';
export const useExportViewNoSelectionRecordAction = ({
position,
objectMetadataItem,
}: {
position: number;
objectMetadataItem: ObjectMetadataItem;
}) => {
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
const { progress, download } = useExportRecords({
delayMs: 100,
objectMetadataItem,
recordIndexId: objectMetadataItem.namePlural,
filename: `${objectMetadataItem.nameSingular}.csv`,
});
const registerExportViewNoSelectionRecordsAction = () => {
addActionMenuEntry({
type: ActionMenuEntryType.Standard,
scope: ActionMenuEntryScope.Global,
key: 'export-view-no-selection',
position,
label: displayedExportProgress(progress),
Icon: IconDatabaseExport,
accent: 'default',
onClick: () => download(),
});
};
const unregisterExportViewNoSelectionRecordsAction = () => {
removeActionMenuEntry('export-view-no-selection');
};
return {
registerExportViewNoSelectionRecordsAction,
unregisterExportViewNoSelectionRecordsAction,
};
};

View File

@ -0,0 +1,29 @@
import { useExportViewNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useExportMultipleRecordsAction';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
export const useNoSelectionRecordActions = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
}) => {
const {
registerExportViewNoSelectionRecordsAction,
unregisterExportViewNoSelectionRecordsAction,
} = useExportViewNoSelectionRecordAction({
position: 0,
objectMetadataItem,
});
const registerNoSelectionRecordActions = () => {
registerExportViewNoSelectionRecordsAction();
};
const unregisterNoSelectionRecordActions = () => {
unregisterExportViewNoSelectionRecordsAction();
};
return {
registerNoSelectionRecordActions,
unregisterNoSelectionRecordActions,
};
};

View File

@ -0,0 +1,24 @@
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useEffect } from 'react';
import { useSingleRecordActions } from '../hooks/useSingleRecordActions';
export const SingleRecordActionMenuEntrySetterEffect = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
}) => {
const { registerSingleRecordActions, unregisterSingleRecordActions } =
useSingleRecordActions({
objectMetadataItem,
});
useEffect(() => {
registerSingleRecordActions();
return () => {
unregisterSingleRecordActions();
};
}, [registerSingleRecordActions, unregisterSingleRecordActions]);
return null;
};

View File

@ -0,0 +1,128 @@
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries';
import {
ActionMenuEntryScope,
ActionMenuEntryType,
} from '@/action-menu/types/ActionMenuEntry';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useCallback, useContext, useState } from 'react';
import { IconTrash, isDefined } from 'twenty-ui';
export const useDeleteSingleRecordAction = ({
position,
objectMetadataItem,
}: {
position: number;
objectMetadataItem: ObjectMetadataItem;
}) => {
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
const [isDeleteRecordsModalOpen, setIsDeleteRecordsModalOpen] =
useState(false);
const { resetTableRowSelection } = useRecordTable({
recordTableId: objectMetadataItem.namePlural,
});
const { deleteOneRecord } = useDeleteOneRecord({
objectNameSingular: objectMetadataItem.nameSingular,
});
const { sortedFavorites: favorites } = useFavorites();
const { deleteFavorite } = useDeleteFavorite();
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
contextStoreTargetedRecordsRuleComponentState,
);
const { closeRightDrawer } = useRightDrawer();
const recordIdToDelete =
contextStoreTargetedRecordsRule.mode === 'selection'
? contextStoreTargetedRecordsRule.selectedRecordIds?.[0]
: undefined;
const handleDeleteClick = useCallback(async () => {
if (!isDefined(recordIdToDelete)) {
return;
}
resetTableRowSelection();
const foundFavorite = favorites?.find(
(favorite) => favorite.recordId === recordIdToDelete,
);
if (isDefined(foundFavorite)) {
deleteFavorite(foundFavorite.id);
}
await deleteOneRecord(recordIdToDelete);
}, [
deleteFavorite,
deleteOneRecord,
favorites,
recordIdToDelete,
resetTableRowSelection,
]);
const isRemoteObject = objectMetadataItem.isRemote;
const { isInRightDrawer, onActionExecutedCallback } =
useContext(ActionMenuContext);
const registerDeleteSingleRecordAction = () => {
if (isRemoteObject || !isDefined(recordIdToDelete)) {
return;
}
addActionMenuEntry({
type: ActionMenuEntryType.Standard,
scope: ActionMenuEntryScope.RecordSelection,
key: 'delete-single-record',
label: 'Delete',
position,
Icon: IconTrash,
accent: 'danger',
isPinned: true,
onClick: () => {
setIsDeleteRecordsModalOpen(true);
},
ConfirmationModal: (
<ConfirmationModal
isOpen={isDeleteRecordsModalOpen}
setIsOpen={setIsDeleteRecordsModalOpen}
title={'Delete Record'}
subtitle={
'Are you sure you want to delete this record? It can be recovered from the Options menu.'
}
onConfirmClick={() => {
handleDeleteClick();
onActionExecutedCallback?.();
if (isInRightDrawer) {
closeRightDrawer();
}
}}
deleteButtonText={'Delete Record'}
/>
),
});
};
const unregisterDeleteSingleRecordAction = () => {
removeActionMenuEntry('delete-single-record');
};
return {
registerDeleteSingleRecordAction,
unregisterDeleteSingleRecordAction,
};
};

View File

@ -10,11 +10,10 @@ import { useFavorites } from '@/favorites/hooks/useFavorites';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useEffect } from 'react';
import { useRecoilValue } from 'recoil';
import { IconHeart, IconHeartOff, isDefined } from 'twenty-ui';
export const ManageFavoritesActionEffect = ({
export const useManageFavoritesSingleRecordAction = ({
position,
objectMetadataItem,
}: {
@ -48,7 +47,7 @@ export const ManageFavoritesActionEffect = ({
const isFavorite = !!selectedRecordId && !!foundFavorite;
useEffect(() => {
const registerManageFavoritesSingleRecordAction = () => {
if (!isDefined(objectMetadataItem) || objectMetadataItem.isRemote) {
return;
}
@ -56,7 +55,7 @@ export const ManageFavoritesActionEffect = ({
addActionMenuEntry({
type: ActionMenuEntryType.Standard,
scope: ActionMenuEntryScope.RecordSelection,
key: 'manage-favorites',
key: 'manage-favorites-single-record',
label: isFavorite ? 'Remove from favorites' : 'Add to favorites',
position,
Icon: isFavorite ? IconHeartOff : IconHeart,
@ -68,21 +67,14 @@ export const ManageFavoritesActionEffect = ({
}
},
});
};
return () => {
removeActionMenuEntry('manage-favorites');
};
}, [
addActionMenuEntry,
createFavorite,
deleteFavorite,
foundFavorite?.id,
isFavorite,
objectMetadataItem,
position,
removeActionMenuEntry,
selectedRecord,
]);
const unregisterManageFavoritesSingleRecordAction = () => {
removeActionMenuEntry('manage-favorites-single-record');
};
return null;
return {
registerManageFavoritesSingleRecordAction,
unregisterManageFavoritesSingleRecordAction,
};
};

View File

@ -0,0 +1,50 @@
import { useDeleteSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useDeleteSingleRecordAction';
import { useManageFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useManageFavoritesSingleRecordAction';
import { useWorkflowRunRecordActions } from '@/action-menu/actions/record-actions/workflow-run-record-actions/hooks/useWorkflowRunRecordActions';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
export const useSingleRecordActions = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
}) => {
const {
registerManageFavoritesSingleRecordAction,
unregisterManageFavoritesSingleRecordAction,
} = useManageFavoritesSingleRecordAction({
position: 0,
objectMetadataItem,
});
const {
registerDeleteSingleRecordAction,
unregisterDeleteSingleRecordAction,
} = useDeleteSingleRecordAction({
position: 1,
objectMetadataItem,
});
const {
registerWorkflowRunRecordActions,
unregisterWorkflowRunRecordActions,
} = useWorkflowRunRecordActions({
objectMetadataItem,
});
const registerSingleRecordActions = () => {
registerManageFavoritesSingleRecordAction();
registerDeleteSingleRecordAction();
registerWorkflowRunRecordActions();
};
const unregisterSingleRecordActions = () => {
unregisterManageFavoritesSingleRecordAction();
unregisterDeleteSingleRecordAction();
unregisterWorkflowRunRecordActions();
};
return {
registerSingleRecordActions,
unregisterSingleRecordActions,
};
};

View File

@ -13,12 +13,11 @@ import { useAllActiveWorkflowVersions } from '@/workflow/hooks/useAllActiveWorkf
import { useRunWorkflowVersion } from '@/workflow/hooks/useRunWorkflowVersion';
import { useTheme } from '@emotion/react';
import { useEffect } from 'react';
import { useRecoilValue } from 'recoil';
import { IconSettingsAutomation, isDefined } from 'twenty-ui';
import { capitalize } from '~/utils/string/capitalize';
export const WorkflowRunRecordActionEffect = ({
export const useWorkflowRunRecordActions = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
@ -49,7 +48,7 @@ export const WorkflowRunRecordActionEffect = ({
const theme = useTheme();
useEffect(() => {
const registerWorkflowRunRecordActions = () => {
if (!isDefined(objectMetadataItem) || objectMetadataItem.isRemote) {
return;
}
@ -88,22 +87,16 @@ export const WorkflowRunRecordActionEffect = ({
},
});
}
};
return () => {
for (const activeWorkflowVersion of activeWorkflowVersions) {
removeActionMenuEntry(`workflow-run-${activeWorkflowVersion.id}`);
}
};
}, [
activeWorkflowVersions,
addActionMenuEntry,
enqueueSnackBar,
objectMetadataItem,
removeActionMenuEntry,
runWorkflowVersion,
selectedRecord,
theme.snackBar.success.color,
]);
const unregisterWorkflowRunRecordActions = () => {
for (const activeWorkflowVersion of activeWorkflowVersions) {
removeActionMenuEntry(`workflow-run-${activeWorkflowVersion.id}`);
}
};
return null;
return {
registerWorkflowRunRecordActions,
unregisterWorkflowRunRecordActions,
};
};

View File

@ -0,0 +1,17 @@
import { useRecordAgnosticActions } from '@/action-menu/actions/record-agnostic-actions/hooks/useGlobalActions';
import { useEffect } from 'react';
export const RecordAgnosticActionsSetterEffect = () => {
const { registerRecordAgnosticActions, unregisterRecordAgnosticActions } =
useRecordAgnosticActions();
useEffect(() => {
registerRecordAgnosticActions();
return () => {
unregisterRecordAgnosticActions();
};
}, [registerRecordAgnosticActions, unregisterRecordAgnosticActions]);
return null;
};

View File

@ -0,0 +1,23 @@
import { useWorkflowRunActions } from '@/action-menu/actions/record-agnostic-actions/workflow-run-actions/hooks/useWorkflowRunActions';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
export const useRecordAgnosticActions = () => {
const isWorkflowEnabled = useIsFeatureEnabled('IS_WORKFLOW_ENABLED');
const { addWorkflowRunActions, removeWorkflowRunActions } =
useWorkflowRunActions();
const registerRecordAgnosticActions = () => {
if (isWorkflowEnabled) {
addWorkflowRunActions();
}
};
const unregisterRecordAgnosticActions = () => {
if (isWorkflowEnabled) {
removeWorkflowRunActions();
}
};
return { registerRecordAgnosticActions, unregisterRecordAgnosticActions };
};

View File

@ -9,11 +9,10 @@ import { useAllActiveWorkflowVersions } from '@/workflow/hooks/useAllActiveWorkf
import { useRunWorkflowVersion } from '@/workflow/hooks/useRunWorkflowVersion';
import { useTheme } from '@emotion/react';
import { useEffect } from 'react';
import { IconSettingsAutomation } from 'twenty-ui';
import { capitalize } from '~/utils/string/capitalize';
export const WorkflowRunActionEffect = () => {
export const useWorkflowRunActions = () => {
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
const { records: activeWorkflowVersions } = useAllActiveWorkflowVersions({
@ -26,7 +25,7 @@ export const WorkflowRunActionEffect = () => {
const theme = useTheme();
useEffect(() => {
const addWorkflowRunActions = () => {
for (const [
index,
activeWorkflowVersion,
@ -56,20 +55,13 @@ export const WorkflowRunActionEffect = () => {
},
});
}
};
return () => {
for (const activeWorkflowVersion of activeWorkflowVersions) {
removeActionMenuEntry(`workflow-run-${activeWorkflowVersion.id}`);
}
};
}, [
activeWorkflowVersions,
addActionMenuEntry,
enqueueSnackBar,
removeActionMenuEntry,
runWorkflowVersion,
theme.snackBar.success.color,
]);
const removeWorkflowRunActions = () => {
for (const activeWorkflowVersion of activeWorkflowVersions) {
removeActionMenuEntry(`workflow-run-${activeWorkflowVersion.id}`);
}
};
return null;
return { addWorkflowRunActions, removeWorkflowRunActions };
};

View File

@ -1,5 +1,5 @@
import { GlobalActionMenuEntriesSetter } from '@/action-menu/actions/global-actions/components/GlobalActionMenuEntriesSetter';
import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter';
import { RecordAgnosticActionsSetterEffect } from '@/action-menu/actions/record-agnostic-actions/components/RecordAgnosticActionsSetterEffect';
import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
import { RecordIndexActionMenuBar } from '@/action-menu/components/RecordIndexActionMenuBar';
import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown';
@ -28,7 +28,7 @@ export const RecordIndexActionMenu = () => {
<ActionMenuConfirmationModals />
<RecordIndexActionMenuEffect />
<RecordActionMenuEntriesSetter />
<GlobalActionMenuEntriesSetter />
<RecordAgnosticActionsSetterEffect />
</ActionMenuContext.Provider>
)}
</>

View File

@ -1,5 +1,5 @@
import { GlobalActionMenuEntriesSetter } from '@/action-menu/actions/global-actions/components/GlobalActionMenuEntriesSetter';
import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter';
import { RecordAgnosticActionsSetterEffect } from '@/action-menu/actions/record-agnostic-actions/components/RecordAgnosticActionsSetterEffect';
import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
@ -48,7 +48,7 @@ export const RecordShowActionMenu = ({
/>
<ActionMenuConfirmationModals />
<RecordActionMenuEntriesSetter />
<GlobalActionMenuEntriesSetter />
<RecordAgnosticActionsSetterEffect />
</ActionMenuContext.Provider>
)}
</>

View File

@ -1,5 +1,5 @@
import { GlobalActionMenuEntriesSetter } from '@/action-menu/actions/global-actions/components/GlobalActionMenuEntriesSetter';
import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter';
import { RecordAgnosticActionsSetterEffect } from '@/action-menu/actions/record-agnostic-actions/components/RecordAgnosticActionsSetterEffect';
import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
import { RightDrawerActionMenuDropdown } from '@/action-menu/components/RightDrawerActionMenuDropdown';
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
@ -24,7 +24,7 @@ export const RecordShowRightDrawerActionMenu = () => {
<RightDrawerActionMenuDropdown />
<ActionMenuConfirmationModals />
<RecordActionMenuEntriesSetter />
<GlobalActionMenuEntriesSetter />
<RecordAgnosticActionsSetterEffect />
</ActionMenuContext.Provider>
)}
</>