From 5e905180c831e345faaa43d5aa563f567e3c488e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?= <71827178+bosiraphael@users.noreply.github.com> Date: Wed, 2 Apr 2025 17:58:14 +0200 Subject: [PATCH] 690 extract shouldberegistered from the useaction hooks (#11355) Closes https://github.com/twentyhq/core-team-issues/issues/690 This PR is the first part of a refactoring on the actions system https://github.com/twentyhq/core-team-issues/issues/683. It: - Removes `shouldBeRegistered` from the useAction hook - Instead `shouldBeRegistered` becomes a function to which we can pass parameters which describe the context of the app (the object, the selected record, information about favorites ...). It returns a boolean. - `useShouldActionBeRegisteredParams` returns the parameters to pass to the `shouldBeRegistered` - Introduces a way to inherit actions from the default config and to overwrite its properties, closing https://github.com/twentyhq/core-team-issues/issues/72 Some tests testing if an action was registered correctly have been removed, we should add them back at the end of the global refactoring. --- .../RecordActionMenuEntriesSetter.tsx | 2 +- .../components/RegisterRecordActionEffect.tsx | 16 +- ...onfig.ts => DefaultRecordActionsConfig.ts} | 153 +++- .../constants/WorkflowActionsConfig.ts | 701 +++++++----------- .../constants/WorkflowRunsActionsConfig.ts | 409 +++------- .../WorkflowVersionsActionsConfig.ts | 496 +++++-------- .../useDestroyMultipleRecordsAction.test.tsx | 22 - .../hooks/useDeleteMultipleRecordsAction.tsx | 32 - .../hooks/useDestroyMultipleRecordsAction.tsx | 36 - .../hooks/useExportMultipleRecordsAction.tsx | 1 - .../hooks/useRestoreMultipleRecordsAction.tsx | 32 - ...teNewTableRecordNoSelectionRecordAction.ts | 14 - ...useGoToCompaniesNoSelectionRecordAction.ts | 3 - ...oToOpportunitiesNoSelectionRecordAction.ts | 3 - .../useGoToPeopleNoSelectionRecordAction.ts | 3 - .../useGoToSettingsNoSelectionRecordAction.ts | 3 - .../useGoToTasksNoSelectionRecordAction.ts | 3 - ...deDeletedRecordsNoSelectionRecordAction.ts | 1 - ...useImportRecordsNoSelectionRecordAction.ts | 5 +- ...eeDeletedRecordsNoSelectionRecordAction.ts | 14 - .../useSeeRunsNoSelectionRecordAction.ts | 3 - .../useSeeWorkflowsNoSelectionRecordAction.ts | 9 - ...Key.ts => NoSelectionRecordActionsKeys.ts} | 1 - .../NoSelectionWorkflowRecordActionsKeys.ts | 3 + ...eAddToFavoritesSingleRecordAction.test.tsx | 33 - ...veFromFavoritesSingleRecordAction.test.tsx | 47 +- .../useAddToFavoritesSingleRecordAction.ts | 20 +- .../hooks/useDeleteSingleRecordAction.tsx | 20 - .../hooks/useDestroySingleRecordAction.tsx | 20 - .../hooks/useExportNoteAction.ts | 21 +- ...eNavigateToNextRecordSingleRecordAction.ts | 5 - ...igateToPreviousRecordSingleRecordAction.ts | 5 - ...seRemoveFromFavoritesSingleRecordAction.ts | 16 +- .../hooks/useRestoreSingleRecordAction.tsx | 33 - ...ActivateWorkflowSingleRecordAction.test.ts | 124 ---- ...activateWorkflowSingleRecordAction.test.ts | 68 -- ...ardDraftWorkflowSingleRecordAction.test.ts | 136 ---- .../useActivateWorkflowSingleRecordAction.ts | 12 +- ...useDeactivateWorkflowSingleRecordAction.ts | 7 +- ...eDiscardDraftWorkflowSingleRecordAction.ts | 8 +- ...ActiveVersionWorkflowSingleRecordAction.ts | 12 +- .../useSeeRunsWorkflowSingleRecordAction.ts | 7 +- ...seSeeVersionsWorkflowSingleRecordAction.ts | 9 +- .../useTestWorkflowSingleRecordAction.ts | 11 +- ...SeeVersionWorkflowRunSingleRecordAction.ts | 10 +- ...eeWorkflowWorkflowRunSingleRecordAction.ts | 7 +- ...eeRunsWorkflowVersionSingleRecordAction.ts | 9 +- ...rsionsWorkflowVersionSingleRecordAction.ts | 9 +- ...rkflowWorkflowVersionSingleRecordAction.ts | 10 +- ...DraftWorkflowVersionSingleRecordAction.tsx | 14 +- .../utils/inheritActionsFromDefaultConfig.ts | 31 + .../RegisterAgnosticRecordActionEffect.tsx | 11 +- .../constants/RecordAgnosticActionsConfig.ts | 19 +- .../useSearchRecordsRecordAgnosticAction.ts | 1 - .../hooks/useRunWorkflowActions.tsx | 4 +- ...onsKey.ts => RecordAgnosticActionsKeys.ts} | 2 +- .../actions/types/ActionHookResult.ts | 1 - .../types/DefaultRecordActionConfigKeys.ts | 8 + .../types/RecordAgnosticConfigAction.ts | 9 + .../actions/types/RecordConfigAction.ts | 25 + .../types/ShouldBeRegisteredFunctionParams.ts | 20 + .../actions/utils/getActionConfig.ts | 4 +- .../useShouldActionBeRegisteredParams.ts | 88 +++ .../components/CommandMenuContainer.tsx | 10 +- .../hooks/useWorkflowWithCurrentVersion.ts | 3 +- 65 files changed, 931 insertions(+), 1943 deletions(-) rename packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/{DefaultActionsConfig.ts => DefaultRecordActionsConfig.ts} (75%) rename packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/types/{NoSelectionRecordActionsKey.ts => NoSelectionRecordActionsKeys.ts} (94%) create mode 100644 packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/workflow-actions/types/NoSelectionWorkflowRecordActionsKeys.ts create mode 100644 packages/twenty-front/src/modules/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig.ts rename packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/types/{RecordAgnosticActionsKey.ts => RecordAgnosticActionsKeys.ts} (70%) create mode 100644 packages/twenty-front/src/modules/action-menu/actions/types/DefaultRecordActionConfigKeys.ts create mode 100644 packages/twenty-front/src/modules/action-menu/actions/types/RecordAgnosticConfigAction.ts create mode 100644 packages/twenty-front/src/modules/action-menu/actions/types/RecordConfigAction.ts create mode 100644 packages/twenty-front/src/modules/action-menu/actions/types/ShouldBeRegisteredFunctionParams.ts create mode 100644 packages/twenty-front/src/modules/action-menu/hooks/useShouldActionBeRegisteredParams.ts diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx index fcee781ce..16c292fa4 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx @@ -10,8 +10,8 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { useRecoilValue } from 'recoil'; -import { FeatureFlagKey } from '~/generated/graphql'; import { isDefined } from 'twenty-shared/utils'; +import { FeatureFlagKey } from '~/generated/graphql'; export const RecordActionMenuEntriesSetter = () => { const localContextStoreCurrentObjectMetadataItemId = diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RegisterRecordActionEffect.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RegisterRecordActionEffect.tsx index e14eff503..2a4498285 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RegisterRecordActionEffect.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RegisterRecordActionEffect.tsx @@ -1,15 +1,13 @@ -import { ActionHook } from '@/action-menu/actions/types/ActionHook'; +import { RecordConfigAction } from '@/action-menu/actions/types/RecordConfigAction'; import { wrapActionInCallbacks } from '@/action-menu/actions/utils/wrapActionInCallbacks'; import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries'; -import { ActionMenuEntry } from '@/action-menu/types/ActionMenuEntry'; +import { useShouldActionBeRegisteredParams } from '@/action-menu/hooks/useShouldActionBeRegisteredParams'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { useContext, useEffect } from 'react'; type RegisterRecordActionEffectProps = { - action: ActionMenuEntry & { - useAction: ActionHook; - }; + action: RecordConfigAction; objectMetadataItem: ObjectMetadataItem; }; @@ -17,7 +15,7 @@ export const RegisterRecordActionEffect = ({ action, objectMetadataItem, }: RegisterRecordActionEffectProps) => { - const { shouldBeRegistered, onClick, ConfirmationModal } = action.useAction({ + const { onClick, ConfirmationModal } = action.useAction({ objectMetadataItem, }); @@ -36,6 +34,12 @@ export const RegisterRecordActionEffect = ({ onActionExecutedCallback, }); + const params = useShouldActionBeRegisteredParams({ + objectMetadataItem, + }); + + const shouldBeRegistered = action.shouldBeRegistered(params); + useEffect(() => { if (shouldBeRegistered) { addActionMenuEntry(wrappedAction); diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultActionsConfig.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig.ts similarity index 75% rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultActionsConfig.ts rename to packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig.ts index 5774a6b0b..85d1c54dc 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultActionsConfig.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig.ts @@ -13,7 +13,7 @@ import { useHideDeletedRecordsNoSelectionRecordAction } from '@/action-menu/acti import { useImportRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useImportRecordsNoSelectionRecordAction'; import { useSeeDeletedRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useSeeDeletedRecordsNoSelectionRecordAction'; import { useSeeWorkflowsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useSeeWorkflowsNoSelectionRecordAction'; -import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKey'; +import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys'; import { useAddToFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useAddToFavoritesSingleRecordAction'; import { useDeleteSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useDeleteSingleRecordAction'; import { useDestroySingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useDestroySingleRecordAction'; @@ -23,14 +23,16 @@ import { useNavigateToPreviousRecordSingleRecordAction } from '@/action-menu/act import { useRemoveFromFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useRemoveFromFavoritesSingleRecordAction'; import { useRestoreSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useRestoreSingleRecordAction'; import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey'; -import { ActionHook } from '@/action-menu/actions/types/ActionHook'; import { ActionViewType } from '@/action-menu/actions/types/ActionViewType'; +import { RecordConfigAction } from '@/action-menu/actions/types/RecordConfigAction'; import { - ActionMenuEntry, ActionMenuEntryScope, ActionMenuEntryType, } from '@/action-menu/types/ActionMenuEntry'; +import { BACKEND_BATCH_REQUEST_MAX_COUNT } from '@/object-record/constants/BackendBatchRequestMaxCount'; import { msg } from '@lingui/core/macro'; +import { isNonEmptyString } from '@sniptt/guards'; +import { isDefined } from 'twenty-shared/utils'; import { IconBuildingSkyscraper, IconCheckbox, @@ -52,13 +54,13 @@ import { IconUser, } from 'twenty-ui'; -export const DEFAULT_ACTIONS_CONFIG: Record< - string, - ActionMenuEntry & { - useAction: ActionHook; - } +export const DEFAULT_RECORD_ACTIONS_CONFIG: Record< + | NoSelectionRecordActionKeys + | SingleRecordActionKeys + | MultipleRecordsActionKeys, + RecordConfigAction > = { - createNewRecord: { + [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.Object, key: NoSelectionRecordActionKeys.CREATE_NEW_RECORD, @@ -67,10 +69,12 @@ export const DEFAULT_ACTIONS_CONFIG: Record< position: 0, isPinned: true, Icon: IconPlus, + shouldBeRegistered: ({ hasObjectReadOnlyPermission }) => + !hasObjectReadOnlyPermission, availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], useAction: useCreateNewTableRecordNoSelectionRecordAction, }, - exportNoteToPdf: { + [SingleRecordActionKeys.EXPORT_NOTE_TO_PDF]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: SingleRecordActionKeys.EXPORT_NOTE_TO_PDF, @@ -79,10 +83,14 @@ export const DEFAULT_ACTIONS_CONFIG: Record< position: 1, isPinned: false, Icon: IconFileExport, + shouldBeRegistered: ({ selectedRecord, isNoteOrTask }) => + isDefined(isNoteOrTask) && + isNoteOrTask && + isNonEmptyString(selectedRecord?.bodyV2?.blocknote), availableOn: [ActionViewType.SHOW_PAGE], useAction: useExportNoteAction, }, - addToFavoritesSingleRecord: { + [SingleRecordActionKeys.ADD_TO_FAVORITES]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: SingleRecordActionKeys.ADD_TO_FAVORITES, @@ -91,13 +99,15 @@ export const DEFAULT_ACTIONS_CONFIG: Record< position: 2, isPinned: true, Icon: IconHeart, + shouldBeRegistered: ({ selectedRecord, isFavorite }) => + !selectedRecord?.isRemote && !isFavorite, availableOn: [ ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, ActionViewType.SHOW_PAGE, ], useAction: useAddToFavoritesSingleRecordAction, }, - removeFromFavoritesSingleRecord: { + [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: SingleRecordActionKeys.REMOVE_FROM_FAVORITES, @@ -106,13 +116,18 @@ export const DEFAULT_ACTIONS_CONFIG: Record< isPinned: true, position: 3, Icon: IconHeartOff, + shouldBeRegistered: ({ selectedRecord, isFavorite }) => + isDefined(selectedRecord) && + !selectedRecord?.isRemote && + isDefined(isFavorite) && + isFavorite, availableOn: [ ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, ActionViewType.SHOW_PAGE, ], useAction: useRemoveFromFavoritesSingleRecordAction, }, - exportSingleRecord: { + [SingleRecordActionKeys.EXPORT]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: SingleRecordActionKeys.EXPORT, @@ -122,13 +137,15 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconFileExport, accent: 'default', isPinned: false, + shouldBeRegistered: ({ selectedRecord }) => + isDefined(selectedRecord) && !selectedRecord.isRemote, availableOn: [ ActionViewType.SHOW_PAGE, ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, ], useAction: useExportMultipleRecordsAction, }, - exportMultipleRecords: { + [MultipleRecordsActionKeys.EXPORT]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: MultipleRecordsActionKeys.EXPORT, @@ -138,10 +155,11 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconFileExport, accent: 'default', isPinned: false, + shouldBeRegistered: () => true, availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION], useAction: useExportMultipleRecordsAction, }, - exportView: { + [NoSelectionRecordActionKeys.EXPORT_VIEW]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.Object, key: NoSelectionRecordActionKeys.EXPORT_VIEW, @@ -151,10 +169,11 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconFileExport, accent: 'default', isPinned: false, + shouldBeRegistered: () => true, availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], useAction: useExportMultipleRecordsAction, }, - deleteSingleRecord: { + [SingleRecordActionKeys.DELETE]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: SingleRecordActionKeys.DELETE, @@ -164,13 +183,15 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconTrash, accent: 'default', isPinned: true, + shouldBeRegistered: ({ selectedRecord }) => + isDefined(selectedRecord) && !selectedRecord.isRemote, availableOn: [ ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, ActionViewType.SHOW_PAGE, ], useAction: useDeleteSingleRecordAction, }, - deleteMultipleRecords: { + [MultipleRecordsActionKeys.DELETE]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: MultipleRecordsActionKeys.DELETE, @@ -180,10 +201,21 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconTrash, accent: 'default', isPinned: true, + shouldBeRegistered: ({ + hasObjectReadOnlyPermission, + isRemote, + isSoftDeleteFilterActive, + numberOfSelectedRecords, + }) => + !hasObjectReadOnlyPermission && + !isRemote && + !isSoftDeleteFilterActive && + isDefined(numberOfSelectedRecords) && + numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT, availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION], useAction: useDeleteMultipleRecordsAction, }, - seeDeletedRecords: { + [NoSelectionRecordActionKeys.SEE_DELETED_RECORDS]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.Object, key: NoSelectionRecordActionKeys.SEE_DELETED_RECORDS, @@ -193,10 +225,12 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconRotate2, accent: 'default', isPinned: false, + shouldBeRegistered: ({ isSoftDeleteFilterActive }) => + !isSoftDeleteFilterActive, availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], useAction: useSeeDeletedRecordsNoSelectionRecordAction, }, - hideDeletedRecords: { + [NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.Object, key: NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS, @@ -206,10 +240,12 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconEyeOff, accent: 'default', isPinned: false, + shouldBeRegistered: ({ isSoftDeleteFilterActive }) => + isDefined(isSoftDeleteFilterActive) && isSoftDeleteFilterActive, availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], useAction: useHideDeletedRecordsNoSelectionRecordAction, }, - importRecords: { + [NoSelectionRecordActionKeys.IMPORT_RECORDS]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.Object, key: NoSelectionRecordActionKeys.IMPORT_RECORDS, @@ -219,10 +255,11 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconFileImport, accent: 'default', isPinned: false, + shouldBeRegistered: () => true, availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], useAction: useImportRecordsNoSelectionRecordAction, }, - destroySingleRecord: { + [SingleRecordActionKeys.DESTROY]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: SingleRecordActionKeys.DESTROY, @@ -232,13 +269,21 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconTrashX, accent: 'danger', isPinned: true, + shouldBeRegistered: ({ + selectedRecord, + hasObjectReadOnlyPermission, + isRemote, + }) => + !hasObjectReadOnlyPermission && + !isRemote && + isDefined(selectedRecord?.deletedAt), availableOn: [ ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, ActionViewType.SHOW_PAGE, ], useAction: useDestroySingleRecordAction, }, - navigateToPreviousRecord: { + [SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD, @@ -246,10 +291,11 @@ export const DEFAULT_ACTIONS_CONFIG: Record< position: 13, isPinned: true, Icon: IconChevronUp, + shouldBeRegistered: ({ isInRightDrawer }) => !isInRightDrawer, availableOn: [ActionViewType.SHOW_PAGE], useAction: useNavigateToPreviousRecordSingleRecordAction, }, - navigateToNextRecord: { + [SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD, @@ -257,10 +303,11 @@ export const DEFAULT_ACTIONS_CONFIG: Record< position: 14, isPinned: true, Icon: IconChevronDown, + shouldBeRegistered: ({ isInRightDrawer }) => !isInRightDrawer, availableOn: [ActionViewType.SHOW_PAGE], useAction: useNavigateToNextRecordSingleRecordAction, }, - destroyMultipleRecords: { + [MultipleRecordsActionKeys.DESTROY]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: MultipleRecordsActionKeys.DESTROY, @@ -270,10 +317,22 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconTrashX, accent: 'danger', isPinned: true, + shouldBeRegistered: ({ + hasObjectReadOnlyPermission, + isRemote, + isSoftDeleteFilterActive, + numberOfSelectedRecords, + }) => + !hasObjectReadOnlyPermission && + !isRemote && + isDefined(isSoftDeleteFilterActive) && + isSoftDeleteFilterActive && + isDefined(numberOfSelectedRecords) && + numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT, availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION], useAction: useDestroyMultipleRecordsAction, }, - restoreSingleRecord: { + [SingleRecordActionKeys.RESTORE]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: SingleRecordActionKeys.RESTORE, @@ -283,13 +342,25 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconRefresh, accent: 'default', isPinned: true, + shouldBeRegistered: ({ + selectedRecord, + hasObjectReadOnlyPermission, + isRemote, + isShowPage, + isSoftDeleteFilterActive, + }) => + !isRemote && + isDefined(selectedRecord?.deletedAt) && + !hasObjectReadOnlyPermission && + ((isDefined(isShowPage) && isShowPage) || + (isDefined(isSoftDeleteFilterActive) && isSoftDeleteFilterActive)), availableOn: [ ActionViewType.SHOW_PAGE, ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, ], useAction: useRestoreSingleRecordAction, }, - restoreMultipleRecords: { + [MultipleRecordsActionKeys.RESTORE]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.RecordSelection, key: MultipleRecordsActionKeys.RESTORE, @@ -299,10 +370,22 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconRefresh, accent: 'default', isPinned: true, + shouldBeRegistered: ({ + hasObjectReadOnlyPermission, + isRemote, + isSoftDeleteFilterActive, + numberOfSelectedRecords, + }) => + !hasObjectReadOnlyPermission && + !isRemote && + isDefined(isSoftDeleteFilterActive) && + isSoftDeleteFilterActive && + isDefined(numberOfSelectedRecords) && + numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT, availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION], useAction: useRestoreMultipleRecordsAction, }, - seeAllWorkflows: { + [NoSelectionRecordActionKeys.GO_TO_WORKFLOWS]: { type: ActionMenuEntryType.Navigation, scope: ActionMenuEntryScope.Global, key: NoSelectionRecordActionKeys.GO_TO_WORKFLOWS, @@ -312,11 +395,12 @@ export const DEFAULT_ACTIONS_CONFIG: Record< Icon: IconSettingsAutomation, accent: 'default', isPinned: false, + shouldBeRegistered: () => true, availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], useAction: useSeeWorkflowsNoSelectionRecordAction, hotKeys: ['G', 'W'], }, - goToPeople: { + [NoSelectionRecordActionKeys.GO_TO_PEOPLE]: { type: ActionMenuEntryType.Navigation, scope: ActionMenuEntryScope.Global, key: NoSelectionRecordActionKeys.GO_TO_PEOPLE, @@ -331,10 +415,11 @@ export const DEFAULT_ACTIONS_CONFIG: Record< ActionViewType.INDEX_PAGE_BULK_SELECTION, ActionViewType.SHOW_PAGE, ], + shouldBeRegistered: () => true, useAction: useGoToPeopleNoSelectionRecordAction, hotKeys: ['G', 'P'], }, - goToCompanies: { + [NoSelectionRecordActionKeys.GO_TO_COMPANIES]: { type: ActionMenuEntryType.Navigation, scope: ActionMenuEntryScope.Global, key: NoSelectionRecordActionKeys.GO_TO_COMPANIES, @@ -349,10 +434,11 @@ export const DEFAULT_ACTIONS_CONFIG: Record< ActionViewType.INDEX_PAGE_BULK_SELECTION, ActionViewType.SHOW_PAGE, ], + shouldBeRegistered: () => true, useAction: useGoToCompaniesNoSelectionRecordAction, hotKeys: ['G', 'C'], }, - goToOpportunities: { + [NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES]: { type: ActionMenuEntryType.Navigation, scope: ActionMenuEntryScope.Global, key: NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES, @@ -367,10 +453,11 @@ export const DEFAULT_ACTIONS_CONFIG: Record< ActionViewType.INDEX_PAGE_BULK_SELECTION, ActionViewType.SHOW_PAGE, ], + shouldBeRegistered: () => true, useAction: useGoToOpportunitiesNoSelectionRecordAction, hotKeys: ['G', 'O'], }, - goToSettings: { + [NoSelectionRecordActionKeys.GO_TO_SETTINGS]: { type: ActionMenuEntryType.Navigation, scope: ActionMenuEntryScope.Global, key: NoSelectionRecordActionKeys.GO_TO_SETTINGS, @@ -385,10 +472,11 @@ export const DEFAULT_ACTIONS_CONFIG: Record< ActionViewType.INDEX_PAGE_BULK_SELECTION, ActionViewType.SHOW_PAGE, ], + shouldBeRegistered: () => true, useAction: useGoToSettingsNoSelectionRecordAction, hotKeys: ['G', 'S'], }, - goToTasks: { + [NoSelectionRecordActionKeys.GO_TO_TASKS]: { type: ActionMenuEntryType.Navigation, scope: ActionMenuEntryScope.Global, key: NoSelectionRecordActionKeys.GO_TO_TASKS, @@ -403,6 +491,7 @@ export const DEFAULT_ACTIONS_CONFIG: Record< ActionViewType.INDEX_PAGE_BULK_SELECTION, ActionViewType.SHOW_PAGE, ], + shouldBeRegistered: () => true, useAction: useGoToTasksNoSelectionRecordAction, hotKeys: ['G', 'T'], }, diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowActionsConfig.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowActionsConfig.ts index 441e4c8fc..d496cdb27 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowActionsConfig.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowActionsConfig.ts @@ -1,24 +1,7 @@ -import { useDeleteMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction'; -import { useDestroyMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useDestroyMultipleRecordsAction'; -import { useExportMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useExportMultipleRecordsAction'; import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys'; -import { useCreateNewTableRecordNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useCreateNewTableRecordNoSelectionRecordAction'; -import { useGoToCompaniesNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToCompaniesNoSelectionRecordAction'; -import { useGoToOpportunitiesNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToOpportunitiesNoSelectionRecordAction'; -import { useGoToPeopleNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToPeopleNoSelectionRecordAction'; -import { useGoToSettingsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToSettingsNoSelectionRecordAction'; -import { useGoToTasksNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToTasksNoSelectionRecordAction'; -import { useHideDeletedRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useHideDeletedRecordsNoSelectionRecordAction'; -import { useImportRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useImportRecordsNoSelectionRecordAction'; -import { useSeeDeletedRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useSeeDeletedRecordsNoSelectionRecordAction'; import { useSeeRunsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useSeeRunsNoSelectionRecordAction'; -import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKey'; -import { useAddToFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useAddToFavoritesSingleRecordAction'; -import { useDeleteSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useDeleteSingleRecordAction'; -import { useDestroySingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useDestroySingleRecordAction'; -import { useNavigateToNextRecordSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useNavigateToNextRecordSingleRecordAction'; -import { useNavigateToPreviousRecordSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useNavigateToPreviousRecordSingleRecordAction'; -import { useRemoveFromFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useRemoveFromFavoritesSingleRecordAction'; +import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys'; +import { NoSelectionWorkflowRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/workflow-actions/types/NoSelectionWorkflowRecordActionsKeys'; import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey'; import { useActivateWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useActivateWorkflowSingleRecordAction'; import { useDeactivateWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useDeactivateWorkflowSingleRecordAction'; @@ -28,452 +11,268 @@ import { useSeeRunsWorkflowSingleRecordAction } from '@/action-menu/actions/reco import { useSeeVersionsWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeVersionsWorkflowSingleRecordAction'; import { useTestWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useTestWorkflowSingleRecordAction'; import { WorkflowSingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/workflow-actions/types/WorkflowSingleRecordActionsKeys'; -import { ActionHook } from '@/action-menu/actions/types/ActionHook'; +import { inheritActionsFromDefaultConfig } from '@/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig'; import { ActionViewType } from '@/action-menu/actions/types/ActionViewType'; import { - ActionMenuEntry, ActionMenuEntryScope, ActionMenuEntryType, } from '@/action-menu/types/ActionMenuEntry'; import { msg } from '@lingui/core/macro'; +import { isDefined } from 'twenty-shared/utils'; import { - IconBuildingSkyscraper, - IconCheckbox, - IconChevronDown, - IconChevronUp, - IconDatabaseExport, - IconEyeOff, - IconFileImport, - IconHeart, - IconHeartOff, IconHistoryToggle, IconNoteOff, IconPlayerPause, IconPlayerPlay, - IconPlus, IconPower, - IconRotate2, - IconSettings, - IconTargetArrow, - IconTrash, - IconTrashX, - IconUser, IconVersions, } from 'twenty-ui'; -export const WORKFLOW_ACTIONS_CONFIG: Record< - string, - ActionMenuEntry & { - useAction: ActionHook; - } -> = { - createNewRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.Object, - key: NoSelectionRecordActionKeys.CREATE_NEW_RECORD, - label: msg`Create new record`, - shortLabel: msg`New record`, - position: 0, - isPinned: true, - Icon: IconPlus, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useCreateNewTableRecordNoSelectionRecordAction, +export const WORKFLOW_ACTIONS_CONFIG = inheritActionsFromDefaultConfig({ + config: { + [WorkflowSingleRecordActionKeys.ACTIVATE]: { + key: WorkflowSingleRecordActionKeys.ACTIVATE, + label: msg`Activate Workflow`, + shortLabel: msg`Activate`, + isPinned: true, + position: 1, + Icon: IconPower, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + shouldBeRegistered: ({ workflowWithCurrentVersion }) => + isDefined(workflowWithCurrentVersion?.currentVersion?.trigger) && + isDefined(workflowWithCurrentVersion.currentVersion?.steps) && + workflowWithCurrentVersion.currentVersion.steps.length > 0 && + (workflowWithCurrentVersion.currentVersion.status === 'DRAFT' || + !workflowWithCurrentVersion.versions?.some( + (version) => version.status === 'ACTIVE', + )), + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useActivateWorkflowSingleRecordAction, + }, + [WorkflowSingleRecordActionKeys.DEACTIVATE]: { + key: WorkflowSingleRecordActionKeys.DEACTIVATE, + label: msg`Deactivate Workflow`, + shortLabel: msg`Deactivate`, + isPinned: true, + position: 2, + Icon: IconPlayerPause, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + shouldBeRegistered: ({ workflowWithCurrentVersion }) => + isDefined(workflowWithCurrentVersion) && + workflowWithCurrentVersion.currentVersion.status === 'ACTIVE', + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useDeactivateWorkflowSingleRecordAction, + }, + [WorkflowSingleRecordActionKeys.DISCARD_DRAFT]: { + key: WorkflowSingleRecordActionKeys.DISCARD_DRAFT, + label: msg`Discard Draft`, + shortLabel: msg`Discard Draft`, + isPinned: true, + position: 3, + Icon: IconNoteOff, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + shouldBeRegistered: ({ workflowWithCurrentVersion }) => + isDefined(workflowWithCurrentVersion) && + workflowWithCurrentVersion.versions.length > 1 && + workflowWithCurrentVersion.currentVersion.status === 'DRAFT', + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useDiscardDraftWorkflowSingleRecordAction, + }, + [WorkflowSingleRecordActionKeys.SEE_ACTIVE_VERSION]: { + key: WorkflowSingleRecordActionKeys.SEE_ACTIVE_VERSION, + label: msg`See active version`, + shortLabel: msg`See active version`, + isPinned: false, + position: 4, + Icon: IconVersions, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + shouldBeRegistered: ({ workflowWithCurrentVersion }) => + (workflowWithCurrentVersion?.statuses?.includes('ACTIVE') || false) && + (workflowWithCurrentVersion?.statuses?.includes('DRAFT') || false), + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useSeeActiveVersionWorkflowSingleRecordAction, + }, + [WorkflowSingleRecordActionKeys.SEE_RUNS]: { + key: WorkflowSingleRecordActionKeys.SEE_RUNS, + label: msg`See runs`, + shortLabel: msg`See runs`, + isPinned: true, + position: 5, + Icon: IconHistoryToggle, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + shouldBeRegistered: ({ workflowWithCurrentVersion }) => + isDefined(workflowWithCurrentVersion), + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useSeeRunsWorkflowSingleRecordAction, + }, + [WorkflowSingleRecordActionKeys.SEE_VERSIONS]: { + key: WorkflowSingleRecordActionKeys.SEE_VERSIONS, + label: msg`See versions history`, + shortLabel: msg`See versions`, + isPinned: false, + position: 6, + Icon: IconVersions, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + shouldBeRegistered: ({ workflowWithCurrentVersion }) => + isDefined(workflowWithCurrentVersion), + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useSeeVersionsWorkflowSingleRecordAction, + }, + [WorkflowSingleRecordActionKeys.TEST]: { + key: WorkflowSingleRecordActionKeys.TEST, + label: msg`Test Workflow`, + shortLabel: msg`Test`, + isPinned: true, + position: 7, + Icon: IconPlayerPlay, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + shouldBeRegistered: ({ workflowWithCurrentVersion }) => + isDefined(workflowWithCurrentVersion?.currentVersion?.trigger) && + ((workflowWithCurrentVersion.currentVersion.trigger.type === 'MANUAL' && + !isDefined( + workflowWithCurrentVersion.currentVersion.trigger.settings + .objectType, + )) || + workflowWithCurrentVersion.currentVersion.trigger.type === 'WEBHOOK'), + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useTestWorkflowSingleRecordAction, + }, + [NoSelectionWorkflowRecordActionKeys.GO_TO_RUNS]: { + type: ActionMenuEntryType.Navigation, + scope: ActionMenuEntryScope.Global, + key: NoSelectionWorkflowRecordActionKeys.GO_TO_RUNS, + label: msg`Go to runs`, + shortLabel: msg`See runs`, + position: 22, + Icon: IconHistoryToggle, + accent: 'default', + isPinned: true, + shouldBeRegistered: () => true, + availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], + useAction: useSeeRunsNoSelectionRecordAction, + }, }, - activateWorkflowSingleRecord: { - key: WorkflowSingleRecordActionKeys.ACTIVATE, - label: msg`Activate Workflow`, - shortLabel: msg`Activate`, - isPinned: true, - position: 1, - Icon: IconPower, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useActivateWorkflowSingleRecordAction, + actionKeys: [ + NoSelectionRecordActionKeys.CREATE_NEW_RECORD, + SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD, + SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD, + SingleRecordActionKeys.ADD_TO_FAVORITES, + SingleRecordActionKeys.REMOVE_FROM_FAVORITES, + SingleRecordActionKeys.DELETE, + SingleRecordActionKeys.DESTROY, + SingleRecordActionKeys.EXPORT, + MultipleRecordsActionKeys.DELETE, + MultipleRecordsActionKeys.DESTROY, + MultipleRecordsActionKeys.EXPORT, + NoSelectionRecordActionKeys.SEE_DELETED_RECORDS, + NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS, + NoSelectionRecordActionKeys.GO_TO_PEOPLE, + NoSelectionRecordActionKeys.GO_TO_COMPANIES, + NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES, + NoSelectionRecordActionKeys.GO_TO_SETTINGS, + NoSelectionRecordActionKeys.GO_TO_TASKS, + ], + propertiesToOverwrite: { + [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: { + position: 0, + label: msg`Create new workflow`, + }, + [SingleRecordActionKeys.ADD_TO_FAVORITES]: { + position: 8, + }, + [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: { + position: 9, + }, + [SingleRecordActionKeys.DELETE]: { + position: 10, + label: msg`Delete workflow`, + }, + [MultipleRecordsActionKeys.DELETE]: { + position: 11, + label: msg`Delete workflows`, + }, + [SingleRecordActionKeys.DESTROY]: { + position: 12, + label: msg`Permanently destroy workflow`, + }, + [SingleRecordActionKeys.EXPORT]: { + position: 13, + label: msg`Export workflow`, + }, + [MultipleRecordsActionKeys.EXPORT]: { + position: 14, + label: msg`Export workflows`, + }, + [NoSelectionRecordActionKeys.EXPORT_VIEW]: { + position: 15, + label: msg`Export view`, + }, + [MultipleRecordsActionKeys.DESTROY]: { + position: 16, + label: msg`Permanently destroy workflows`, + }, + [SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD]: { + position: 17, + label: msg`Navigate to previous workflow`, + }, + [SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD]: { + position: 18, + label: msg`Navigate to next workflow`, + }, + [NoSelectionRecordActionKeys.SEE_DELETED_RECORDS]: { + position: 19, + label: msg`See deleted workflows`, + }, + [NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS]: { + position: 20, + label: msg`Hide deleted workflows`, + }, + [NoSelectionRecordActionKeys.IMPORT_RECORDS]: { + position: 21, + label: msg`Import workflows`, + }, + [NoSelectionRecordActionKeys.GO_TO_PEOPLE]: { + position: 23, + }, + [NoSelectionRecordActionKeys.GO_TO_COMPANIES]: { + position: 24, + }, + [NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES]: { + position: 25, + }, + [NoSelectionRecordActionKeys.GO_TO_SETTINGS]: { + position: 26, + }, + [NoSelectionRecordActionKeys.GO_TO_TASKS]: { + position: 27, + }, }, - deactivateWorkflowSingleRecord: { - key: WorkflowSingleRecordActionKeys.DEACTIVATE, - label: msg`Deactivate Workflow`, - shortLabel: msg`Deactivate`, - isPinned: true, - position: 2, - Icon: IconPlayerPause, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useDeactivateWorkflowSingleRecordAction, - }, - discardWorkflowDraftSingleRecord: { - key: WorkflowSingleRecordActionKeys.DISCARD_DRAFT, - label: msg`Discard Draft`, - shortLabel: msg`Discard Draft`, - isPinned: true, - position: 3, - Icon: IconNoteOff, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useDiscardDraftWorkflowSingleRecordAction, - }, - seeWorkflowActiveVersionSingleRecord: { - key: WorkflowSingleRecordActionKeys.SEE_ACTIVE_VERSION, - label: msg`See active version`, - shortLabel: msg`See active version`, - isPinned: false, - position: 4, - Icon: IconVersions, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useSeeActiveVersionWorkflowSingleRecordAction, - }, - seeWorkflowRunsSingleRecord: { - key: WorkflowSingleRecordActionKeys.SEE_RUNS, - label: msg`See runs`, - shortLabel: msg`See runs`, - isPinned: true, - position: 5, - Icon: IconHistoryToggle, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useSeeRunsWorkflowSingleRecordAction, - }, - seeWorkflowVersionsHistorySingleRecord: { - key: WorkflowSingleRecordActionKeys.SEE_VERSIONS, - label: msg`See versions history`, - shortLabel: msg`See versions`, - isPinned: false, - position: 6, - Icon: IconVersions, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useSeeVersionsWorkflowSingleRecordAction, - }, - testWorkflowSingleRecord: { - key: WorkflowSingleRecordActionKeys.TEST, - label: msg`Test Workflow`, - shortLabel: msg`Test`, - isPinned: true, - position: 7, - Icon: IconPlayerPlay, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useTestWorkflowSingleRecordAction, - }, - navigateToPreviousRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD, - label: msg`Navigate to previous workflow`, - position: 8, - Icon: IconChevronUp, - availableOn: [ActionViewType.SHOW_PAGE], - useAction: useNavigateToPreviousRecordSingleRecordAction, - }, - navigateToNextRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD, - label: msg`Navigate to next workflow`, - position: 9, - Icon: IconChevronDown, - availableOn: [ActionViewType.SHOW_PAGE], - useAction: useNavigateToNextRecordSingleRecordAction, - }, - addToFavoritesSingleRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.ADD_TO_FAVORITES, - label: msg`Add to favorites`, - shortLabel: msg`Add to favorites`, - position: 10, - isPinned: false, - Icon: IconHeart, - availableOn: [ - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useAddToFavoritesSingleRecordAction, - }, - removeFromFavoritesSingleRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.REMOVE_FROM_FAVORITES, - label: msg`Remove from favorites`, - shortLabel: msg`Remove from favorites`, - isPinned: false, - position: 11, - Icon: IconHeartOff, - availableOn: [ - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useRemoveFromFavoritesSingleRecordAction, - }, - deleteSingleRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.DELETE, - label: msg`Delete workflow`, - shortLabel: msg`Delete`, - position: 12, - Icon: IconTrash, - accent: 'danger', - isPinned: true, - availableOn: [ - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useDeleteSingleRecordAction, - }, - deleteMultipleRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: MultipleRecordsActionKeys.DELETE, - label: msg`Delete workflows`, - shortLabel: msg`Delete`, - position: 13, - Icon: IconTrash, - accent: 'danger', - isPinned: true, - availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION], - useAction: useDeleteMultipleRecordsAction, - }, - destroySingleRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.DESTROY, - label: msg`Permanently destroy record`, - shortLabel: msg`Destroy`, - position: 14, - Icon: IconTrashX, - accent: 'danger', - isPinned: true, - availableOn: [ - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useDestroySingleRecordAction, - }, - exportSingleRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.EXPORT, - label: msg`Export workflow`, - shortLabel: msg`Export`, - position: 15, - Icon: IconDatabaseExport, - accent: 'default', - isPinned: false, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useExportMultipleRecordsAction, - }, - exportMultipleRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: MultipleRecordsActionKeys.EXPORT, - label: msg`Export workflows`, - shortLabel: msg`Export`, - position: 16, - Icon: IconDatabaseExport, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION], - useAction: useExportMultipleRecordsAction, - }, - exportView: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.Object, - key: NoSelectionRecordActionKeys.EXPORT_VIEW, - label: msg`Export view`, - shortLabel: msg`Export`, - position: 17, - Icon: IconDatabaseExport, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useExportMultipleRecordsAction, - }, - destroyMultipleRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: MultipleRecordsActionKeys.DESTROY, - label: msg`Permanently destroy workflows`, - shortLabel: msg`Destroy`, - position: 18, - Icon: IconTrashX, - accent: 'danger', - isPinned: true, - availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION], - useAction: useDestroyMultipleRecordsAction, - }, - seeDeletedRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.Object, - key: NoSelectionRecordActionKeys.SEE_DELETED_RECORDS, - label: msg`See deleted workflows`, - shortLabel: msg`Deleted workflows`, - position: 19, - Icon: IconRotate2, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useSeeDeletedRecordsNoSelectionRecordAction, - }, - hideDeletedRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.Object, - key: NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS, - label: msg`Hide deleted workflows`, - shortLabel: msg`Hide deleted`, - position: 20, - Icon: IconEyeOff, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useHideDeletedRecordsNoSelectionRecordAction, - }, - importRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.Object, - key: NoSelectionRecordActionKeys.IMPORT_RECORDS, - label: msg`Import workflows`, - shortLabel: msg`Import`, - position: 21, - Icon: IconFileImport, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useImportRecordsNoSelectionRecordAction, - }, - seeAllRuns: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_RUNS, - label: msg`Go to runs`, - shortLabel: msg`See runs`, - position: 22, - Icon: IconHistoryToggle, - accent: 'default', - isPinned: true, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useSeeRunsNoSelectionRecordAction, - }, - goToPeople: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_PEOPLE, - label: msg`Go to People`, - shortLabel: msg`People`, - position: 23, - Icon: IconUser, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToPeopleNoSelectionRecordAction, - hotKeys: ['G', 'P'], - }, - goToCompanies: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_COMPANIES, - label: msg`Go to Companies`, - shortLabel: msg`Companies`, - position: 24, - Icon: IconBuildingSkyscraper, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToCompaniesNoSelectionRecordAction, - hotKeys: ['G', 'C'], - }, - goToOpportunities: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES, - label: msg`Go to Opportunities`, - shortLabel: msg`Opportunities`, - position: 25, - Icon: IconTargetArrow, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToOpportunitiesNoSelectionRecordAction, - hotKeys: ['G', 'O'], - }, - goToSettings: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_SETTINGS, - label: msg`Go to Settings`, - shortLabel: msg`Settings`, - position: 26, - Icon: IconSettings, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToSettingsNoSelectionRecordAction, - hotKeys: ['G', 'S'], - }, - goToTasks: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_TASKS, - label: msg`Go to Tasks`, - shortLabel: msg`Tasks`, - position: 27, - Icon: IconCheckbox, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToTasksNoSelectionRecordAction, - hotKeys: ['G', 'T'], - }, -}; +}); diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowRunsActionsConfig.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowRunsActionsConfig.ts index 54f72a3bf..7010474cc 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowRunsActionsConfig.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowRunsActionsConfig.ts @@ -1,305 +1,134 @@ -import { useExportMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useExportMultipleRecordsAction'; import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys'; -import { useGoToCompaniesNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToCompaniesNoSelectionRecordAction'; -import { useGoToOpportunitiesNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToOpportunitiesNoSelectionRecordAction'; -import { useGoToPeopleNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToPeopleNoSelectionRecordAction'; -import { useGoToSettingsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToSettingsNoSelectionRecordAction'; -import { useGoToTasksNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToTasksNoSelectionRecordAction'; -import { useHideDeletedRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useHideDeletedRecordsNoSelectionRecordAction'; -import { useSeeDeletedRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useSeeDeletedRecordsNoSelectionRecordAction'; import { useSeeWorkflowsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useSeeWorkflowsNoSelectionRecordAction'; -import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKey'; -import { useAddToFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useAddToFavoritesSingleRecordAction'; -import { useNavigateToNextRecordSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useNavigateToNextRecordSingleRecordAction'; -import { useNavigateToPreviousRecordSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useNavigateToPreviousRecordSingleRecordAction'; -import { useRemoveFromFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useRemoveFromFavoritesSingleRecordAction'; +import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys'; import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey'; import { useSeeVersionWorkflowRunSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-run-actions/hooks/useSeeVersionWorkflowRunSingleRecordAction'; import { useSeeWorkflowWorkflowRunSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-run-actions/hooks/useSeeWorkflowWorkflowRunSingleRecordAction'; import { WorkflowRunSingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/workflow-run-actions/types/WorkflowRunSingleRecordActionsKeys'; -import { ActionHook } from '@/action-menu/actions/types/ActionHook'; +import { inheritActionsFromDefaultConfig } from '@/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig'; import { ActionViewType } from '@/action-menu/actions/types/ActionViewType'; import { - ActionMenuEntry, ActionMenuEntryScope, ActionMenuEntryType, } from '@/action-menu/types/ActionMenuEntry'; import { msg } from '@lingui/core/macro'; -import { - IconBuildingSkyscraper, - IconCheckbox, - IconChevronDown, - IconChevronUp, - IconDatabaseExport, - IconEyeOff, - IconHeart, - IconHeartOff, - IconRotate2, - IconSettings, - IconSettingsAutomation, - IconTargetArrow, - IconUser, - IconVersions, -} from 'twenty-ui'; +import { IconSettingsAutomation, IconVersions } from 'twenty-ui'; -export const WORKFLOW_RUNS_ACTIONS_CONFIG: Record< - string, - ActionMenuEntry & { - useAction: ActionHook; - } -> = { - seeWorkflowSingleRecord: { - key: WorkflowRunSingleRecordActionKeys.SEE_WORKFLOW, - label: msg`See workflow`, - shortLabel: msg`See workflow`, - position: 0, - isPinned: true, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - Icon: IconSettingsAutomation, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useSeeWorkflowWorkflowRunSingleRecordAction, +export const WORKFLOW_RUNS_ACTIONS_CONFIG = inheritActionsFromDefaultConfig({ + config: { + [WorkflowRunSingleRecordActionKeys.SEE_WORKFLOW]: { + key: WorkflowRunSingleRecordActionKeys.SEE_WORKFLOW, + label: msg`See workflow`, + shortLabel: msg`See workflow`, + position: 0, + isPinned: true, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + Icon: IconSettingsAutomation, + shouldBeRegistered: () => true, + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useSeeWorkflowWorkflowRunSingleRecordAction, + }, + [WorkflowRunSingleRecordActionKeys.SEE_VERSION]: { + key: WorkflowRunSingleRecordActionKeys.SEE_VERSION, + label: msg`See version`, + shortLabel: msg`See version`, + position: 1, + isPinned: true, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + Icon: IconVersions, + shouldBeRegistered: () => true, + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useSeeVersionWorkflowRunSingleRecordAction, + }, + [NoSelectionRecordActionKeys.GO_TO_WORKFLOWS]: { + type: ActionMenuEntryType.Navigation, + scope: ActionMenuEntryScope.Global, + key: NoSelectionRecordActionKeys.GO_TO_WORKFLOWS, + label: msg`Go to workflows`, + shortLabel: msg`See workflows`, + position: 11, + Icon: IconSettingsAutomation, + accent: 'default', + isPinned: true, + shouldBeRegistered: () => true, + availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], + useAction: useSeeWorkflowsNoSelectionRecordAction, + hotKeys: ['G', 'W'], + }, }, - seeVersionSingleRecord: { - key: WorkflowRunSingleRecordActionKeys.SEE_VERSION, - label: msg`See version`, - shortLabel: msg`See version`, - position: 1, - isPinned: true, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - Icon: IconVersions, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useSeeVersionWorkflowRunSingleRecordAction, + actionKeys: [ + SingleRecordActionKeys.ADD_TO_FAVORITES, + SingleRecordActionKeys.REMOVE_FROM_FAVORITES, + SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD, + SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD, + SingleRecordActionKeys.EXPORT, + MultipleRecordsActionKeys.EXPORT, + NoSelectionRecordActionKeys.EXPORT_VIEW, + NoSelectionRecordActionKeys.SEE_DELETED_RECORDS, + NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS, + NoSelectionRecordActionKeys.GO_TO_PEOPLE, + NoSelectionRecordActionKeys.GO_TO_COMPANIES, + NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES, + NoSelectionRecordActionKeys.GO_TO_SETTINGS, + NoSelectionRecordActionKeys.GO_TO_TASKS, + ], + propertiesToOverwrite: { + [SingleRecordActionKeys.ADD_TO_FAVORITES]: { + isPinned: false, + position: 2, + }, + [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: { + isPinned: false, + position: 3, + }, + [SingleRecordActionKeys.EXPORT]: { + position: 4, + label: msg`Export run`, + }, + [MultipleRecordsActionKeys.EXPORT]: { + position: 5, + label: msg`Export runs`, + }, + [NoSelectionRecordActionKeys.EXPORT_VIEW]: { + position: 6, + label: msg`Export view`, + }, + [NoSelectionRecordActionKeys.SEE_DELETED_RECORDS]: { + position: 7, + label: msg`See deleted runs`, + }, + [NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS]: { + position: 8, + label: msg`Hide deleted runs`, + }, + [SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD]: { + position: 9, + }, + [SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD]: { + position: 10, + }, + [NoSelectionRecordActionKeys.GO_TO_PEOPLE]: { + position: 12, + }, + [NoSelectionRecordActionKeys.GO_TO_COMPANIES]: { + position: 13, + }, + [NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES]: { + position: 14, + }, + [NoSelectionRecordActionKeys.GO_TO_SETTINGS]: { + position: 15, + }, + [NoSelectionRecordActionKeys.GO_TO_TASKS]: { + position: 16, + }, }, - addToFavoritesSingleRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.ADD_TO_FAVORITES, - label: msg`Add to favorites`, - shortLabel: msg`Add to favorites`, - position: 2, - isPinned: false, - Icon: IconHeart, - availableOn: [ - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useAddToFavoritesSingleRecordAction, - }, - removeFromFavoritesSingleRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.REMOVE_FROM_FAVORITES, - label: msg`Remove from favorites`, - shortLabel: msg`Remove from favorites`, - isPinned: false, - position: 3, - Icon: IconHeartOff, - availableOn: [ - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useRemoveFromFavoritesSingleRecordAction, - }, - navigateToPreviousRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD, - label: msg`Navigate to previous run`, - position: 4, - isPinned: true, - Icon: IconChevronUp, - availableOn: [ActionViewType.SHOW_PAGE], - useAction: useNavigateToPreviousRecordSingleRecordAction, - }, - navigateToNextRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD, - label: msg`Navigate to next run`, - position: 5, - isPinned: true, - Icon: IconChevronDown, - availableOn: [ActionViewType.SHOW_PAGE], - useAction: useNavigateToNextRecordSingleRecordAction, - }, - exportSingleRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.EXPORT, - label: msg`Export run`, - shortLabel: msg`Export`, - position: 6, - Icon: IconDatabaseExport, - accent: 'default', - isPinned: false, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useExportMultipleRecordsAction, - }, - exportMultipleRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: MultipleRecordsActionKeys.EXPORT, - label: msg`Export runs`, - shortLabel: msg`Export`, - position: 7, - Icon: IconDatabaseExport, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION], - useAction: useExportMultipleRecordsAction, - }, - exportView: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.Object, - key: NoSelectionRecordActionKeys.EXPORT_VIEW, - label: msg`Export view`, - shortLabel: msg`Export`, - position: 8, - Icon: IconDatabaseExport, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useExportMultipleRecordsAction, - }, - seeDeletedRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.Object, - key: NoSelectionRecordActionKeys.SEE_DELETED_RECORDS, - label: msg`See deleted runs`, - shortLabel: msg`Deleted runs`, - position: 9, - Icon: IconRotate2, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useSeeDeletedRecordsNoSelectionRecordAction, - }, - hideDeletedRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.Object, - key: NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS, - label: msg`Hide deleted runs`, - shortLabel: msg`Hide deleted`, - position: 10, - Icon: IconEyeOff, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useHideDeletedRecordsNoSelectionRecordAction, - }, - seeAllWorkflows: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_WORKFLOWS, - label: msg`Go to workflows`, - shortLabel: msg`See workflows`, - position: 11, - Icon: IconSettingsAutomation, - accent: 'default', - isPinned: true, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useSeeWorkflowsNoSelectionRecordAction, - hotKeys: ['G', 'W'], - }, - goToPeople: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_PEOPLE, - label: msg`Go to People`, - shortLabel: msg`People`, - position: 12, - Icon: IconUser, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToPeopleNoSelectionRecordAction, - hotKeys: ['G', 'P'], - }, - goToCompanies: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_COMPANIES, - label: msg`Go to Companies`, - shortLabel: msg`Companies`, - position: 13, - Icon: IconBuildingSkyscraper, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToCompaniesNoSelectionRecordAction, - hotKeys: ['G', 'C'], - }, - goToOpportunities: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES, - label: msg`Go to Opportunities`, - shortLabel: msg`Opportunities`, - position: 14, - Icon: IconTargetArrow, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToOpportunitiesNoSelectionRecordAction, - hotKeys: ['G', 'O'], - }, - goToSettings: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_SETTINGS, - label: msg`Go to Settings`, - shortLabel: msg`Settings`, - position: 15, - Icon: IconSettings, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToSettingsNoSelectionRecordAction, - hotKeys: ['G', 'S'], - }, - goToTasks: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_TASKS, - label: msg`Go to Tasks`, - shortLabel: msg`Tasks`, - position: 16, - Icon: IconCheckbox, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToTasksNoSelectionRecordAction, - hotKeys: ['G', 'T'], - }, -}; +}); diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowVersionsActionsConfig.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowVersionsActionsConfig.ts index 9a8461335..6805b28fb 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowVersionsActionsConfig.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowVersionsActionsConfig.ts @@ -1,350 +1,194 @@ -import { useExportMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useExportMultipleRecordsAction'; import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys'; -import { useGoToCompaniesNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToCompaniesNoSelectionRecordAction'; -import { useGoToOpportunitiesNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToOpportunitiesNoSelectionRecordAction'; -import { useGoToPeopleNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToPeopleNoSelectionRecordAction'; -import { useGoToSettingsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToSettingsNoSelectionRecordAction'; -import { useGoToTasksNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useGoToTasksNoSelectionRecordAction'; -import { useHideDeletedRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useHideDeletedRecordsNoSelectionRecordAction'; -import { useSeeDeletedRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useSeeDeletedRecordsNoSelectionRecordAction'; import { useSeeRunsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useSeeRunsNoSelectionRecordAction'; import { useSeeWorkflowsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useSeeWorkflowsNoSelectionRecordAction'; -import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKey'; -import { useAddToFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useAddToFavoritesSingleRecordAction'; -import { useNavigateToNextRecordSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useNavigateToNextRecordSingleRecordAction'; -import { useNavigateToPreviousRecordSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useNavigateToPreviousRecordSingleRecordAction'; -import { useRemoveFromFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/hooks/useRemoveFromFavoritesSingleRecordAction'; +import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys'; +import { NoSelectionWorkflowRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/workflow-actions/types/NoSelectionWorkflowRecordActionsKeys'; import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey'; import { useSeeRunsWorkflowVersionSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeRunsWorkflowVersionSingleRecordAction'; import { useSeeVersionsWorkflowVersionSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeVersionsWorkflowVersionSingleRecordAction'; import { useSeeWorkflowWorkflowVersionSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeWorkflowWorkflowVersionSingleRecordAction'; import { useUseAsDraftWorkflowVersionSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useUseAsDraftWorkflowVersionSingleRecordAction'; import { WorkflowVersionSingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/workflow-version-actions/types/WorkflowVersionSingleRecordActionsKeys'; -import { ActionHook } from '@/action-menu/actions/types/ActionHook'; +import { inheritActionsFromDefaultConfig } from '@/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig'; import { ActionViewType } from '@/action-menu/actions/types/ActionViewType'; import { - ActionMenuEntry, ActionMenuEntryScope, ActionMenuEntryType, } from '@/action-menu/types/ActionMenuEntry'; import { msg } from '@lingui/core/macro'; +import { isDefined } from 'twenty-shared/utils'; import { - IconBuildingSkyscraper, - IconCheckbox, - IconChevronDown, - IconChevronUp, - IconDatabaseExport, - IconEyeOff, - IconHeart, - IconHeartOff, IconHistoryToggle, IconPencil, - IconRotate2, - IconSettings, IconSettingsAutomation, - IconTargetArrow, - IconUser, IconVersions, } from 'twenty-ui'; -export const WORKFLOW_VERSIONS_ACTIONS_CONFIG: Record< - string, - ActionMenuEntry & { - useAction: ActionHook; - } -> = { - useAsDraftWorkflowVersionSingleRecord: { - key: WorkflowVersionSingleRecordActionKeys.USE_AS_DRAFT, - label: msg`Use as draft`, - shortLabel: msg`Use as draft`, - position: 1, - isPinned: true, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - Icon: IconPencil, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, +export const WORKFLOW_VERSIONS_ACTIONS_CONFIG = inheritActionsFromDefaultConfig( + { + config: { + [WorkflowVersionSingleRecordActionKeys.USE_AS_DRAFT]: { + key: WorkflowVersionSingleRecordActionKeys.USE_AS_DRAFT, + label: msg`Use as draft`, + shortLabel: msg`Use as draft`, + position: 1, + isPinned: true, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + Icon: IconPencil, + shouldBeRegistered: ({ selectedRecord }) => + isDefined(selectedRecord) && selectedRecord.status !== 'DRAFT', + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useUseAsDraftWorkflowVersionSingleRecordAction, + }, + [WorkflowVersionSingleRecordActionKeys.SEE_WORKFLOW]: { + key: WorkflowVersionSingleRecordActionKeys.SEE_WORKFLOW, + label: msg`See workflow`, + shortLabel: msg`See workflow`, + position: 2, + isPinned: true, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + Icon: IconSettingsAutomation, + shouldBeRegistered: ({ selectedRecord }) => + isDefined(selectedRecord?.workflow?.id), + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useSeeWorkflowWorkflowVersionSingleRecordAction, + }, + [WorkflowVersionSingleRecordActionKeys.SEE_RUNS]: { + key: WorkflowVersionSingleRecordActionKeys.SEE_RUNS, + label: msg`See runs`, + shortLabel: msg`See runs`, + position: 3, + isPinned: true, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + Icon: IconHistoryToggle, + shouldBeRegistered: ({ workflowWithCurrentVersion }) => + isDefined(workflowWithCurrentVersion), + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useSeeRunsWorkflowVersionSingleRecordAction, + }, + [WorkflowVersionSingleRecordActionKeys.SEE_VERSIONS]: { + key: WorkflowVersionSingleRecordActionKeys.SEE_VERSIONS, + label: msg`See versions history`, + shortLabel: msg`See versions`, + position: 4, + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + Icon: IconVersions, + shouldBeRegistered: ({ workflowWithCurrentVersion }) => + isDefined(workflowWithCurrentVersion), + availableOn: [ + ActionViewType.SHOW_PAGE, + ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, + ], + useAction: useSeeVersionsWorkflowVersionSingleRecordAction, + }, + [NoSelectionRecordActionKeys.GO_TO_WORKFLOWS]: { + type: ActionMenuEntryType.Navigation, + scope: ActionMenuEntryScope.Global, + key: NoSelectionRecordActionKeys.GO_TO_WORKFLOWS, + label: msg`Go to workflows`, + shortLabel: msg`See workflows`, + position: 14, + Icon: IconSettingsAutomation, + accent: 'default', + isPinned: true, + shouldBeRegistered: () => true, + availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], + useAction: useSeeWorkflowsNoSelectionRecordAction, + hotKeys: ['G', 'W'], + }, + [NoSelectionWorkflowRecordActionKeys.GO_TO_RUNS]: { + type: ActionMenuEntryType.Navigation, + scope: ActionMenuEntryScope.Global, + key: NoSelectionWorkflowRecordActionKeys.GO_TO_RUNS, + label: msg`Go to runs`, + shortLabel: msg`See runs`, + position: 15, + Icon: IconHistoryToggle, + accent: 'default', + isPinned: true, + shouldBeRegistered: () => true, + availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], + useAction: useSeeRunsNoSelectionRecordAction, + }, + }, + actionKeys: [ + SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD, + SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD, + SingleRecordActionKeys.ADD_TO_FAVORITES, + SingleRecordActionKeys.REMOVE_FROM_FAVORITES, + SingleRecordActionKeys.EXPORT, + MultipleRecordsActionKeys.EXPORT, + NoSelectionRecordActionKeys.EXPORT_VIEW, + NoSelectionRecordActionKeys.SEE_DELETED_RECORDS, + NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS, + NoSelectionRecordActionKeys.GO_TO_PEOPLE, + NoSelectionRecordActionKeys.GO_TO_COMPANIES, + NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES, + NoSelectionRecordActionKeys.GO_TO_SETTINGS, + NoSelectionRecordActionKeys.GO_TO_TASKS, ], - useAction: useUseAsDraftWorkflowVersionSingleRecordAction, + propertiesToOverwrite: { + [SingleRecordActionKeys.ADD_TO_FAVORITES]: { + position: 5, + isPinned: false, + }, + [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: { + position: 6, + isPinned: false, + }, + [SingleRecordActionKeys.EXPORT]: { + position: 7, + label: msg`Export version`, + }, + [MultipleRecordsActionKeys.EXPORT]: { + position: 8, + label: msg`Export versions`, + }, + [NoSelectionRecordActionKeys.EXPORT_VIEW]: { + position: 9, + }, + [NoSelectionRecordActionKeys.SEE_DELETED_RECORDS]: { + position: 10, + }, + [NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS]: { + position: 11, + }, + [SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD]: { + position: 12, + label: msg`Navigate to previous version`, + }, + [SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD]: { + position: 13, + label: msg`Navigate to next version`, + }, + [NoSelectionRecordActionKeys.GO_TO_PEOPLE]: { + position: 16, + }, + [NoSelectionRecordActionKeys.GO_TO_COMPANIES]: { + position: 17, + }, + [NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES]: { + position: 18, + }, + [NoSelectionRecordActionKeys.GO_TO_SETTINGS]: { + position: 19, + }, + [NoSelectionRecordActionKeys.GO_TO_TASKS]: { + position: 20, + }, + }, }, - seeWorkflowSingleRecord: { - key: WorkflowVersionSingleRecordActionKeys.SEE_WORKFLOW, - label: msg`See workflow`, - shortLabel: msg`See workflow`, - position: 2, - isPinned: true, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - Icon: IconSettingsAutomation, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useSeeWorkflowWorkflowVersionSingleRecordAction, - }, - seeWorkflowRunsSingleRecord: { - key: WorkflowVersionSingleRecordActionKeys.SEE_RUNS, - label: msg`See runs`, - shortLabel: msg`See runs`, - position: 3, - isPinned: true, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - Icon: IconHistoryToggle, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useSeeRunsWorkflowVersionSingleRecordAction, - }, - seeWorkflowVersionsHistorySingleRecord: { - key: WorkflowVersionSingleRecordActionKeys.SEE_VERSIONS, - label: msg`See versions history`, - shortLabel: msg`See versions`, - position: 4, - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - Icon: IconVersions, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useSeeVersionsWorkflowVersionSingleRecordAction, - }, - navigateToPreviousRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD, - label: msg`Navigate to previous version`, - position: 5, - Icon: IconChevronUp, - availableOn: [ActionViewType.SHOW_PAGE], - useAction: useNavigateToPreviousRecordSingleRecordAction, - }, - navigateToNextRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD, - label: msg`Navigate to next version`, - position: 6, - Icon: IconChevronDown, - availableOn: [ActionViewType.SHOW_PAGE], - useAction: useNavigateToNextRecordSingleRecordAction, - }, - addToFavoritesSingleRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.ADD_TO_FAVORITES, - label: msg`Add to favorites`, - shortLabel: msg`Add to favorites`, - position: 7, - isPinned: false, - Icon: IconHeart, - availableOn: [ - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useAddToFavoritesSingleRecordAction, - }, - removeFromFavoritesSingleRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.REMOVE_FROM_FAVORITES, - label: msg`Remove from favorites`, - shortLabel: msg`Remove from favorites`, - isPinned: false, - position: 8, - Icon: IconHeartOff, - availableOn: [ - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useRemoveFromFavoritesSingleRecordAction, - }, - exportSingleRecord: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: SingleRecordActionKeys.EXPORT, - label: msg`Export version`, - shortLabel: msg`Export`, - position: 9, - Icon: IconDatabaseExport, - accent: 'default', - isPinned: false, - availableOn: [ - ActionViewType.SHOW_PAGE, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ], - useAction: useExportMultipleRecordsAction, - }, - exportMultipleRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.RecordSelection, - key: MultipleRecordsActionKeys.EXPORT, - label: msg`Export versions`, - shortLabel: msg`Export`, - position: 10, - Icon: IconDatabaseExport, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION], - useAction: useExportMultipleRecordsAction, - }, - exportView: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.Object, - key: NoSelectionRecordActionKeys.EXPORT_VIEW, - label: msg`Export view`, - shortLabel: msg`Export`, - position: 11, - Icon: IconDatabaseExport, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useExportMultipleRecordsAction, - }, - seeDeletedRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.Object, - key: NoSelectionRecordActionKeys.SEE_DELETED_RECORDS, - label: msg`See deleted versions`, - shortLabel: msg`Deleted versions`, - position: 12, - Icon: IconRotate2, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useSeeDeletedRecordsNoSelectionRecordAction, - }, - hideDeletedRecords: { - type: ActionMenuEntryType.Standard, - scope: ActionMenuEntryScope.Object, - key: NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS, - label: msg`Hide deleted versions`, - shortLabel: msg`Hide deleted`, - position: 13, - Icon: IconEyeOff, - accent: 'default', - isPinned: false, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useHideDeletedRecordsNoSelectionRecordAction, - }, - seeAllWorkflows: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_WORKFLOWS, - label: msg`Go to workflows`, - shortLabel: msg`See workflows`, - position: 14, - Icon: IconSettingsAutomation, - accent: 'default', - isPinned: true, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useSeeWorkflowsNoSelectionRecordAction, - hotKeys: ['G', 'W'], - }, - seeAllRuns: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_RUNS, - label: msg`Go to runs`, - shortLabel: msg`See runs`, - position: 15, - Icon: IconHistoryToggle, - accent: 'default', - isPinned: true, - availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION], - useAction: useSeeRunsNoSelectionRecordAction, - }, - goToPeople: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_PEOPLE, - label: msg`Go to People`, - shortLabel: msg`People`, - position: 16, - Icon: IconUser, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToPeopleNoSelectionRecordAction, - hotKeys: ['G', 'P'], - }, - goToCompanies: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_COMPANIES, - label: msg`Go to Companies`, - shortLabel: msg`Companies`, - position: 17, - Icon: IconBuildingSkyscraper, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToCompaniesNoSelectionRecordAction, - hotKeys: ['G', 'C'], - }, - goToOpportunities: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES, - label: msg`Go to Opportunities`, - shortLabel: msg`Opportunities`, - position: 18, - Icon: IconTargetArrow, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToOpportunitiesNoSelectionRecordAction, - hotKeys: ['G', 'O'], - }, - goToSettings: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_SETTINGS, - label: msg`Go to Settings`, - shortLabel: msg`Settings`, - position: 19, - Icon: IconSettings, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToSettingsNoSelectionRecordAction, - hotKeys: ['G', 'S'], - }, - goToTasks: { - type: ActionMenuEntryType.Navigation, - scope: ActionMenuEntryScope.Global, - key: NoSelectionRecordActionKeys.GO_TO_TASKS, - label: msg`Go to Tasks`, - shortLabel: msg`Tasks`, - position: 20, - Icon: IconCheckbox, - isPinned: false, - availableOn: [ - ActionViewType.INDEX_PAGE_NO_SELECTION, - ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION, - ActionViewType.INDEX_PAGE_BULK_SELECTION, - ActionViewType.SHOW_PAGE, - ], - useAction: useGoToTasksNoSelectionRecordAction, - hotKeys: ['G', 'T'], - }, -}; +); diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/__tests__/useDestroyMultipleRecordsAction.test.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/__tests__/useDestroyMultipleRecordsAction.test.tsx index a2b8010f6..a389e68ce 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/__tests__/useDestroyMultipleRecordsAction.test.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/__tests__/useDestroyMultipleRecordsAction.test.tsx @@ -75,8 +75,6 @@ const getWrapper = ( ...overrides, }); -const defaultWrapper = getWrapper(); - describe('useDestroyMultipleRecordsAction', () => { it('should call destroyManyRecords on click if records are filtered by deletedAt', async () => { const { result } = renderHook( @@ -121,24 +119,4 @@ describe('useDestroyMultipleRecordsAction', () => { expect(destroyManyRecordsMock).toHaveBeenCalledWith(expectedParams); }); }); - - it('should not call destroyManyRecords on click if records are not filtered by deletedAt', async () => { - const { result } = renderHook( - () => - useDestroyMultipleRecordsAction({ - objectMetadataItem: personMockObjectMetadataItem, - }), - { - wrapper: defaultWrapper, - }, - ); - - expect(result.current.ConfirmationModal?.props?.isOpen).toBeFalsy(); - - act(() => { - result.current.onClick(); - }); - - expect(result.current.ConfirmationModal?.props?.isOpen).toBeFalsy(); - }); }); diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction.tsx index f16d3c98c..10660a5e4 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction.tsx @@ -2,23 +2,18 @@ import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/Ac import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; -import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; -import { BACKEND_BATCH_REQUEST_MAX_COUNT } from '@/object-record/constants/BackendBatchRequestMaxCount'; import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize'; import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords'; import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords'; -import { useCheckIsSoftDeleteFilter } from '@/object-record/record-filter/hooks/useCheckIsSoftDeleteFilter'; import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId'; -import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { t } from '@lingui/core/macro'; import { useCallback, useState } from 'react'; -import { isDefined } from 'twenty-shared/utils'; export const useDeleteMultipleRecordsAction: ActionHookWithObjectMetadataItem = ({ objectMetadataItem }) => { @@ -33,8 +28,6 @@ export const useDeleteMultipleRecordsAction: ActionHookWithObjectMetadataItem = throw new Error('Current view ID is not defined'); } - const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission(); - const { resetTableRowSelection } = useRecordTable({ recordTableId: getRecordIndexIdFromObjectNamePluralAndViewId( objectMetadataItem.namePlural, @@ -46,10 +39,6 @@ export const useDeleteMultipleRecordsAction: ActionHookWithObjectMetadataItem = objectNameSingular: objectMetadataItem.nameSingular, }); - const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2( - contextStoreNumberOfSelectedRecordsComponentState, - ); - const contextStoreTargetedRecordsRule = useRecoilComponentValueV2( contextStoreTargetedRecordsRuleComponentState, ); @@ -67,12 +56,6 @@ export const useDeleteMultipleRecordsAction: ActionHookWithObjectMetadataItem = filterValueDependencies, ); - const { checkIsSoftDeleteFilter } = useCheckIsSoftDeleteFilter(); - - const isDeletedFilterActive = contextStoreFilters.some( - checkIsSoftDeleteFilter, - ); - const { fetchAllRecords: fetchAllRecordIds } = useLazyFetchAllRecords({ objectNameSingular: objectMetadataItem.nameSingular, filter: graphqlFilter, @@ -91,21 +74,7 @@ export const useDeleteMultipleRecordsAction: ActionHookWithObjectMetadataItem = }); }, [deleteManyRecords, fetchAllRecordIds, resetTableRowSelection]); - const isRemoteObject = objectMetadataItem.isRemote; - - const shouldBeRegistered = - !hasObjectReadOnlyPermission && - !isRemoteObject && - !isDeletedFilterActive && - isDefined(contextStoreNumberOfSelectedRecords) && - contextStoreNumberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT && - contextStoreNumberOfSelectedRecords > 0; - const onClick = () => { - if (!shouldBeRegistered) { - return; - } - setIsDeleteRecordsModalOpen(true); }; @@ -121,7 +90,6 @@ export const useDeleteMultipleRecordsAction: ActionHookWithObjectMetadataItem = ); return { - shouldBeRegistered, onClick, ConfirmationModal: confirmationModal, }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDestroyMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDestroyMultipleRecordsAction.tsx index e2d10e539..dddc57c5c 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDestroyMultipleRecordsAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDestroyMultipleRecordsAction.tsx @@ -2,23 +2,18 @@ import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/Ac import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; -import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; -import { BACKEND_BATCH_REQUEST_MAX_COUNT } from '@/object-record/constants/BackendBatchRequestMaxCount'; import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize'; import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter'; import { useDestroyManyRecords } from '@/object-record/hooks/useDestroyManyRecords'; import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords'; import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies'; -import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId'; -import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useCallback, useState } from 'react'; -import { isDefined } from 'twenty-shared/utils'; export const useDestroyMultipleRecordsAction: ActionHookWithObjectMetadataItem = ({ objectMetadataItem }) => { @@ -40,16 +35,10 @@ export const useDestroyMultipleRecordsAction: ActionHookWithObjectMetadataItem = ), }); - const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission(); - const { destroyManyRecords } = useDestroyManyRecords({ objectNameSingular: objectMetadataItem.nameSingular, }); - const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2( - contextStoreNumberOfSelectedRecordsComponentState, - ); - const contextStoreTargetedRecordsRule = useRecoilComponentValueV2( contextStoreTargetedRecordsRuleComponentState, ); @@ -73,16 +62,6 @@ export const useDestroyMultipleRecordsAction: ActionHookWithObjectMetadataItem = ...deletedAtFilter, }; - const deletedAtFieldMetadata = objectMetadataItem.fields.find( - (field) => field.name === 'deletedAt', - ); - - const isDeletedFilterActive = contextStoreFilters.some( - (filter) => - filter.fieldMetadataId === deletedAtFieldMetadata?.id && - filter.operand === RecordFilterOperand.IsNotEmpty, - ); - const { fetchAllRecords: fetchAllRecordIds } = useLazyFetchAllRecords({ objectNameSingular: objectMetadataItem.nameSingular, filter: graphqlFilter, @@ -99,21 +78,7 @@ export const useDestroyMultipleRecordsAction: ActionHookWithObjectMetadataItem = await destroyManyRecords({ recordIdsToDestroy }); }, [destroyManyRecords, fetchAllRecordIds, resetTableRowSelection]); - const isRemoteObject = objectMetadataItem.isRemote; - - const shouldBeRegistered = - !hasObjectReadOnlyPermission && - !isRemoteObject && - isDeletedFilterActive && - isDefined(contextStoreNumberOfSelectedRecords) && - contextStoreNumberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT && - contextStoreNumberOfSelectedRecords > 0; - const onClick = () => { - if (!shouldBeRegistered) { - return; - } - setIsDestroyRecordsModalOpen(true); }; @@ -131,7 +96,6 @@ export const useDestroyMultipleRecordsAction: ActionHookWithObjectMetadataItem = ); return { - shouldBeRegistered, onClick, ConfirmationModal: confirmationModal, }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useExportMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useExportMultipleRecordsAction.tsx index dd371053d..a29fa4752 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useExportMultipleRecordsAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useExportMultipleRecordsAction.tsx @@ -33,7 +33,6 @@ export const useExportMultipleRecordsAction = ({ }; return { - shouldBeRegistered: true, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useRestoreMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useRestoreMultipleRecordsAction.tsx index 0e65c1246..680b55c84 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useRestoreMultipleRecordsAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useRestoreMultipleRecordsAction.tsx @@ -3,22 +3,17 @@ import { useCallback, useState } from 'react'; import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; -import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; -import { BACKEND_BATCH_REQUEST_MAX_COUNT } from '@/object-record/constants/BackendBatchRequestMaxCount'; import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize'; import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter'; import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords'; import { useRestoreManyRecords } from '@/object-record/hooks/useRestoreManyRecords'; -import { useCheckIsSoftDeleteFilter } from '@/object-record/record-filter/hooks/useCheckIsSoftDeleteFilter'; import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId'; -import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { isDefined } from 'twenty-shared/utils'; export const useRestoreMultipleRecordsAction: ActionHookWithObjectMetadataItem = ({ objectMetadataItem }) => { @@ -33,8 +28,6 @@ export const useRestoreMultipleRecordsAction: ActionHookWithObjectMetadataItem = throw new Error('Current view ID is not defined'); } - const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission(); - const { resetTableRowSelection } = useRecordTable({ recordTableId: getRecordIndexIdFromObjectNamePluralAndViewId( objectMetadataItem.namePlural, @@ -46,10 +39,6 @@ export const useRestoreMultipleRecordsAction: ActionHookWithObjectMetadataItem = objectNameSingular: objectMetadataItem.nameSingular, }); - const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2( - contextStoreNumberOfSelectedRecordsComponentState, - ); - const contextStoreTargetedRecordsRule = useRecoilComponentValueV2( contextStoreTargetedRecordsRuleComponentState, ); @@ -74,12 +63,6 @@ export const useRestoreMultipleRecordsAction: ActionHookWithObjectMetadataItem = ...deletedAtFilter, }; - const { checkIsSoftDeleteFilter } = useCheckIsSoftDeleteFilter(); - - const isDeletedFilterActive = contextStoreFilters.some( - checkIsSoftDeleteFilter, - ); - const { fetchAllRecords: fetchAllRecordIds } = useLazyFetchAllRecords({ objectNameSingular: objectMetadataItem.nameSingular, filter: graphqlFilter, @@ -98,21 +81,7 @@ export const useRestoreMultipleRecordsAction: ActionHookWithObjectMetadataItem = }); }, [restoreManyRecords, fetchAllRecordIds, resetTableRowSelection]); - const isRemoteObject = objectMetadataItem.isRemote; - - const shouldBeRegistered = - !hasObjectReadOnlyPermission && - !isRemoteObject && - isDeletedFilterActive && - isDefined(contextStoreNumberOfSelectedRecords) && - contextStoreNumberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT && - contextStoreNumberOfSelectedRecords > 0; - const onClick = () => { - if (!shouldBeRegistered) { - return; - } - setIsRestoreRecordsModalOpen(true); }; @@ -128,7 +97,6 @@ export const useRestoreMultipleRecordsAction: ActionHookWithObjectMetadataItem = ); return { - shouldBeRegistered, onClick, ConfirmationModal: confirmationModal, }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useCreateNewTableRecordNoSelectionRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useCreateNewTableRecordNoSelectionRecordAction.ts index 56709b1ac..983480212 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useCreateNewTableRecordNoSelectionRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useCreateNewTableRecordNoSelectionRecordAction.ts @@ -1,27 +1,13 @@ import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; -import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; import { useCreateNewIndexRecord } from '@/object-record/record-table/hooks/useCreateNewIndexRecord'; -import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission'; -import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; export const useCreateNewTableRecordNoSelectionRecordAction: ActionHookWithObjectMetadataItem = ({ objectMetadataItem }) => { - const currentViewId = useRecoilComponentValueV2( - contextStoreCurrentViewIdComponentState, - ); - - if (!currentViewId) { - throw new Error('Current view ID is not defined'); - } - - const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission(); - const { createNewIndexRecord } = useCreateNewIndexRecord({ objectMetadataItem, }); return { - shouldBeRegistered: !hasObjectReadOnlyPermission, onClick: createNewIndexRecord, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToCompaniesNoSelectionRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToCompaniesNoSelectionRecordAction.ts index 20fac3b5b..60cae8ff2 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToCompaniesNoSelectionRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToCompaniesNoSelectionRecordAction.ts @@ -7,8 +7,6 @@ export const useGoToCompaniesNoSelectionRecordAction: ActionHookWithoutObjectMet () => { const navigateApp = useNavigateApp(); - const shouldBeRegistered = true; - const onClick = () => { navigateApp(AppPath.RecordIndexPage, { objectNamePlural: CoreObjectNamePlural.Company, @@ -16,7 +14,6 @@ export const useGoToCompaniesNoSelectionRecordAction: ActionHookWithoutObjectMet }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToOpportunitiesNoSelectionRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToOpportunitiesNoSelectionRecordAction.ts index 4f2b2f679..63559779a 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToOpportunitiesNoSelectionRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToOpportunitiesNoSelectionRecordAction.ts @@ -7,8 +7,6 @@ export const useGoToOpportunitiesNoSelectionRecordAction: ActionHookWithoutObjec () => { const navigateApp = useNavigateApp(); - const shouldBeRegistered = true; - const onClick = () => { navigateApp(AppPath.RecordIndexPage, { objectNamePlural: CoreObjectNamePlural.Opportunity, @@ -16,7 +14,6 @@ export const useGoToOpportunitiesNoSelectionRecordAction: ActionHookWithoutObjec }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToPeopleNoSelectionRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToPeopleNoSelectionRecordAction.ts index 39877aba0..ec3de4124 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToPeopleNoSelectionRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToPeopleNoSelectionRecordAction.ts @@ -7,8 +7,6 @@ export const useGoToPeopleNoSelectionRecordAction: ActionHookWithoutObjectMetada () => { const navigateApp = useNavigateApp(); - const shouldBeRegistered = true; - const onClick = () => { navigateApp(AppPath.RecordIndexPage, { objectNamePlural: CoreObjectNamePlural.Person, @@ -16,7 +14,6 @@ export const useGoToPeopleNoSelectionRecordAction: ActionHookWithoutObjectMetada }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToSettingsNoSelectionRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToSettingsNoSelectionRecordAction.ts index d4a2fc199..4bfc548f4 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToSettingsNoSelectionRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToSettingsNoSelectionRecordAction.ts @@ -6,14 +6,11 @@ export const useGoToSettingsNoSelectionRecordAction: ActionHookWithoutObjectMeta () => { const navigateSettings = useNavigateSettings(); - const shouldBeRegistered = true; - const onClick = () => { navigateSettings(SettingsPath.ProfilePage); }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToTasksNoSelectionRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToTasksNoSelectionRecordAction.ts index 635935c86..db440a3d7 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToTasksNoSelectionRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useGoToTasksNoSelectionRecordAction.ts @@ -7,8 +7,6 @@ export const useGoToTasksNoSelectionRecordAction: ActionHookWithoutObjectMetadat () => { const navigateApp = useNavigateApp(); - const shouldBeRegistered = true; - const onClick = () => { navigateApp(AppPath.RecordIndexPage, { objectNamePlural: CoreObjectNamePlural.Task, @@ -16,7 +14,6 @@ export const useGoToTasksNoSelectionRecordAction: ActionHookWithoutObjectMetadat }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useHideDeletedRecordsNoSelectionRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useHideDeletedRecordsNoSelectionRecordAction.ts index 55aedb2c7..b5ba37b80 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useHideDeletedRecordsNoSelectionRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useHideDeletedRecordsNoSelectionRecordAction.ts @@ -52,7 +52,6 @@ export const useHideDeletedRecordsNoSelectionRecordAction: ActionHookWithObjectM }, [deletedFilter, removeRecordFilter, toggleSoftDeleteFilterState]); return { - shouldBeRegistered: isDefined(deletedFilter), onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useImportRecordsNoSelectionRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useImportRecordsNoSelectionRecordAction.ts index 2e071827b..d26697133 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useImportRecordsNoSelectionRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useImportRecordsNoSelectionRecordAction.ts @@ -9,9 +9,6 @@ export const useImportRecordsNoSelectionRecordAction: ActionHookWithObjectMetada ); return { - shouldBeRegistered: true, - onClick: () => { - openObjectRecordsSpreadsheetImportDialog(); - }, + onClick: openObjectRecordsSpreadsheetImportDialog, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeDeletedRecordsNoSelectionRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeDeletedRecordsNoSelectionRecordAction.ts index 0cd961f89..7bf15cfaf 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeDeletedRecordsNoSelectionRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeDeletedRecordsNoSelectionRecordAction.ts @@ -2,8 +2,6 @@ import { useCallback } from 'react'; import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState'; -import { useCheckIsSoftDeleteFilter } from '@/object-record/record-filter/hooks/useCheckIsSoftDeleteFilter'; -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 { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; @@ -29,24 +27,12 @@ export const useSeeDeletedRecordsNoSelectionRecordAction: ActionHookWithObjectMe viewBarId: recordIndexId, }); - const { checkIsSoftDeleteFilter } = useCheckIsSoftDeleteFilter(); - - const currentRecordFilters = useRecoilComponentValueV2( - currentRecordFiltersComponentState, - recordIndexId, - ); - - const isDeletedFilterActive = currentRecordFilters.some( - checkIsSoftDeleteFilter, - ); - const onClick = useCallback(() => { handleToggleTrashColumnFilter(); toggleSoftDeleteFilterState(true); }, [handleToggleTrashColumnFilter, toggleSoftDeleteFilterState]); return { - shouldBeRegistered: !isDeletedFilterActive, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeRunsNoSelectionRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeRunsNoSelectionRecordAction.ts index 0d42d9f4a..d6497bc52 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeRunsNoSelectionRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeRunsNoSelectionRecordAction.ts @@ -7,8 +7,6 @@ export const useSeeRunsNoSelectionRecordAction: ActionHookWithoutObjectMetadataI () => { const navigateApp = useNavigateApp(); - const shouldBeRegistered = true; - const onClick = () => { navigateApp(AppPath.RecordIndexPage, { objectNamePlural: CoreObjectNamePlural.WorkflowRun, @@ -16,7 +14,6 @@ export const useSeeRunsNoSelectionRecordAction: ActionHookWithoutObjectMetadataI }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeWorkflowsNoSelectionRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeWorkflowsNoSelectionRecordAction.ts index 8bae60b93..1d7b89c83 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeWorkflowsNoSelectionRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/hooks/useSeeWorkflowsNoSelectionRecordAction.ts @@ -1,20 +1,12 @@ import { ActionHookWithoutObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural'; import { AppPath } from '@/types/AppPath'; -import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; -import { FeatureFlagKey } from '~/generated-metadata/graphql'; import { useNavigateApp } from '~/hooks/useNavigateApp'; export const useSeeWorkflowsNoSelectionRecordAction: ActionHookWithoutObjectMetadataItem = () => { const navigateApp = useNavigateApp(); - const isWorkflowsEnabled = useIsFeatureEnabled( - FeatureFlagKey.IsWorkflowEnabled, - ); - - const shouldBeRegistered = isWorkflowsEnabled; - const onClick = () => { navigateApp(AppPath.RecordIndexPage, { objectNamePlural: CoreObjectNamePlural.Workflow, @@ -22,7 +14,6 @@ export const useSeeWorkflowsNoSelectionRecordAction: ActionHookWithoutObjectMeta }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKey.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys.ts similarity index 94% rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKey.ts rename to packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys.ts index 4b0f76ae4..98a3e0e71 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKey.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys.ts @@ -4,7 +4,6 @@ export enum NoSelectionRecordActionKeys { SEE_DELETED_RECORDS = 'see-deleted-records', HIDE_DELETED_RECORDS = 'hide-deleted-records', IMPORT_RECORDS = 'import-records', - GO_TO_RUNS = 'go-to-runs', GO_TO_WORKFLOWS = 'go-to-workflows', GO_TO_PEOPLE = 'go-to-people', GO_TO_COMPANIES = 'go-to-companies', diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/workflow-actions/types/NoSelectionWorkflowRecordActionsKeys.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/workflow-actions/types/NoSelectionWorkflowRecordActionsKeys.ts new file mode 100644 index 000000000..aa128a112 --- /dev/null +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/workflow-actions/types/NoSelectionWorkflowRecordActionsKeys.ts @@ -0,0 +1,3 @@ +export enum NoSelectionWorkflowRecordActionKeys { + GO_TO_RUNS = 'go-to-runs', +} diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/__tests__/useAddToFavoritesSingleRecordAction.test.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/__tests__/useAddToFavoritesSingleRecordAction.test.tsx index 974dd2b63..0b9c9ba5e 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/__tests__/useAddToFavoritesSingleRecordAction.test.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/__tests__/useAddToFavoritesSingleRecordAction.test.tsx @@ -70,45 +70,12 @@ const wrapperConfigWithSelectedRecordNotAsFavorite: GetJestMetadataAndApolloMock }, }; -const wrapperWithSelectedRecordAsFavorite = - getJestMetadataAndApolloMocksAndActionMenuWrapper( - wrapperConfigWithSelectedRecordAsFavorite, - ); - const wrapperWithSelectedRecordNotAsFavorite = getJestMetadataAndApolloMocksAndActionMenuWrapper( wrapperConfigWithSelectedRecordNotAsFavorite, ); describe('useAddToFavoritesSingleRecordAction', () => { - it('should be registered when the record is not a favorite', () => { - const { result } = renderHook( - () => - useAddToFavoritesSingleRecordAction({ - objectMetadataItem: personMockObjectMetadataItem, - }), - { - wrapper: wrapperWithSelectedRecordNotAsFavorite, - }, - ); - - expect(result.current.shouldBeRegistered).toBe(true); - }); - - it('should not be registered when the record is a favorite', () => { - const { result } = renderHook( - () => - useAddToFavoritesSingleRecordAction({ - objectMetadataItem: personMockObjectMetadataItem, - }), - { - wrapper: wrapperWithSelectedRecordAsFavorite, - }, - ); - - expect(result.current.shouldBeRegistered).toBe(false); - }); - it('should call createFavorite on click', () => { const { result } = renderHook( () => diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/__tests__/useRemoveFromFavoritesSingleRecordAction.test.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/__tests__/useRemoveFromFavoritesSingleRecordAction.test.tsx index c22406e15..651beb4ce 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/__tests__/useRemoveFromFavoritesSingleRecordAction.test.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/__tests__/useRemoveFromFavoritesSingleRecordAction.test.tsx @@ -61,60 +61,15 @@ const wrapperConfigWithSelectedRecordAsFavorite: GetJestMetadataAndApolloMocksAn }, }; -const wrapperConfigWithSelectedRecordNotAsFavorite: GetJestMetadataAndApolloMocksAndActionMenuWrapperProps = - { - ...wrapperConfigWithSelectedRecordAsFavorite, - contextStoreTargetedRecordsRule: { - mode: 'selection', - selectedRecordIds: [peopleMock[1].id], - }, - }; - const wrapperWithSelectedRecordAsFavorite = getJestMetadataAndApolloMocksAndActionMenuWrapper( wrapperConfigWithSelectedRecordAsFavorite, ); -const wrapperWithSelectedRecordNotAsFavorite = - getJestMetadataAndApolloMocksAndActionMenuWrapper( - wrapperConfigWithSelectedRecordNotAsFavorite, - ); - describe('useRemoveFromFavoritesSingleRecordAction', () => { - it('should be registered when the record is a favorite', () => { - const { result } = renderHook( - () => - useRemoveFromFavoritesSingleRecordAction({ - objectMetadataItem: personMockObjectMetadataItem, - }), - { - wrapper: wrapperWithSelectedRecordAsFavorite, - }, - ); - - expect(result.current.shouldBeRegistered).toBe(true); - }); - - it('should not be registered when the record is not a favorite', () => { - const { result } = renderHook( - () => - useRemoveFromFavoritesSingleRecordAction({ - objectMetadataItem: personMockObjectMetadataItem, - }), - { - wrapper: wrapperWithSelectedRecordNotAsFavorite, - }, - ); - - expect(result.current.shouldBeRegistered).toBe(false); - }); - it('should call deleteFavorite on click', () => { const { result } = renderHook( - () => - useRemoveFromFavoritesSingleRecordAction({ - objectMetadataItem: personMockObjectMetadataItem, - }), + () => useRemoveFromFavoritesSingleRecordAction(), { wrapper: wrapperWithSelectedRecordAsFavorite, }, diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useAddToFavoritesSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useAddToFavoritesSingleRecordAction.ts index b26714089..38b76aa73 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useAddToFavoritesSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useAddToFavoritesSingleRecordAction.ts @@ -1,9 +1,7 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow'; import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; import { useCreateFavorite } from '@/favorites/hooks/useCreateFavorite'; -import { useFavorites } from '@/favorites/hooks/useFavorites'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; -import { isNull } from '@sniptt/guards'; import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared/utils'; @@ -11,27 +9,12 @@ export const useAddToFavoritesSingleRecordAction: ActionHookWithObjectMetadataIt ({ objectMetadataItem }) => { const recordId = useSelectedRecordIdOrThrow(); - const { sortedFavorites: favorites } = useFavorites(); - const { createFavorite } = useCreateFavorite(); const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId)); - const foundFavorite = favorites?.find( - (favorite) => favorite.recordId === recordId, - ); - - const isFavorite = !!foundFavorite; - - const shouldBeRegistered = - isDefined(objectMetadataItem) && - isDefined(selectedRecord) && - !objectMetadataItem.isRemote && - !isFavorite && - isNull(selectedRecord.deletedAt); - const onClick = () => { - if (!shouldBeRegistered) { + if (!isDefined(selectedRecord)) { return; } @@ -39,7 +22,6 @@ export const useAddToFavoritesSingleRecordAction: ActionHookWithObjectMetadataIt }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useDeleteSingleRecordAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useDeleteSingleRecordAction.tsx index 8caa9f4fa..297057cb4 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useDeleteSingleRecordAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useDeleteSingleRecordAction.tsx @@ -3,14 +3,10 @@ import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/Ac import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite'; import { useFavorites } from '@/favorites/hooks/useFavorites'; import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; -import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; -import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { t } from '@lingui/core/macro'; -import { isNull } from '@sniptt/guards'; import { useCallback, useState } from 'react'; -import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared/utils'; export const useDeleteSingleRecordAction: ActionHookWithObjectMetadataItem = ({ @@ -21,8 +17,6 @@ export const useDeleteSingleRecordAction: ActionHookWithObjectMetadataItem = ({ const [isDeleteRecordsModalOpen, setIsDeleteRecordsModalOpen] = useState(false); - const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission(); - const { resetTableRowSelection } = useRecordTable({ recordTableId: objectMetadataItem.namePlural, }); @@ -31,8 +25,6 @@ export const useDeleteSingleRecordAction: ActionHookWithObjectMetadataItem = ({ objectNameSingular: objectMetadataItem.nameSingular, }); - const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId)); - const { sortedFavorites: favorites } = useFavorites(); const { deleteFavorite } = useDeleteFavorite(); @@ -56,23 +48,11 @@ export const useDeleteSingleRecordAction: ActionHookWithObjectMetadataItem = ({ recordId, ]); - const isRemoteObject = objectMetadataItem.isRemote; - - const shouldBeRegistered = - !isRemoteObject && - isNull(selectedRecord?.deletedAt) && - !hasObjectReadOnlyPermission; - const onClick = () => { - if (!shouldBeRegistered) { - return; - } - setIsDeleteRecordsModalOpen(true); }; return { - shouldBeRegistered, onClick, ConfirmationModal: ( { resetTableRowSelection(); @@ -48,23 +40,11 @@ export const useDestroySingleRecordAction: ActionHookWithObjectMetadataItem = ({ objectMetadataItem.namePlural, ]); - const isRemoteObject = objectMetadataItem.isRemote; - - const shouldBeRegistered = - !hasObjectReadOnlyPermission && - !isRemoteObject && - isDefined(selectedRecord?.deletedAt); - const onClick = () => { - if (!shouldBeRegistered) { - return; - } - setIsDestroyRecordsModalOpen(true); }; return { - shouldBeRegistered, onClick, ConfirmationModal: ( { +export const useExportNoteAction: ActionHookWithoutObjectMetadataItem = () => { const recordId = useSelectedRecordIdOrThrow(); const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId)); const filename = `${(selectedRecord?.title || 'Untitled Note').replace(/[<>:"/\\|?*]/g, '-')}`; - const isNoteOrTask = - objectMetadataItem?.nameSingular === CoreObjectNameSingular.Note || - objectMetadataItem?.nameSingular === CoreObjectNameSingular.Task; - - const shouldBeRegistered = - isDefined(objectMetadataItem) && - isDefined(selectedRecord) && - isNoteOrTask && - isNonEmptyString(selectedRecord.bodyV2?.blocknote); - const onClick = async () => { - if (!shouldBeRegistered || !selectedRecord.bodyV2.blocknote) { + if (!isDefined(selectedRecord)) { return; } @@ -65,7 +51,6 @@ export const useExportNoteAction: ActionHookWithObjectMetadataItem = ({ }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useNavigateToNextRecordSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useNavigateToNextRecordSingleRecordAction.ts index 35757df3b..7eced3a36 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useNavigateToNextRecordSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useNavigateToNextRecordSingleRecordAction.ts @@ -1,22 +1,17 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow'; import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; -import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { useRecordShowPagePagination } from '@/object-record/record-show/hooks/useRecordShowPagePagination'; -import { useContext } from 'react'; export const useNavigateToNextRecordSingleRecordAction: ActionHookWithObjectMetadataItem = ({ objectMetadataItem }) => { const recordId = useSelectedRecordIdOrThrow(); - const { isInRightDrawer } = useContext(ActionMenuContext); - const { navigateToNextRecord } = useRecordShowPagePagination( objectMetadataItem.nameSingular, recordId, ); return { - shouldBeRegistered: !isInRightDrawer, onClick: navigateToNextRecord, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useNavigateToPreviousRecordSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useNavigateToPreviousRecordSingleRecordAction.ts index 36cec0c5f..e1ad5b1bf 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useNavigateToPreviousRecordSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useNavigateToPreviousRecordSingleRecordAction.ts @@ -1,22 +1,17 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow'; import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; -import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { useRecordShowPagePagination } from '@/object-record/record-show/hooks/useRecordShowPagePagination'; -import { useContext } from 'react'; export const useNavigateToPreviousRecordSingleRecordAction: ActionHookWithObjectMetadataItem = ({ objectMetadataItem }) => { const recordId = useSelectedRecordIdOrThrow(); - const { isInRightDrawer } = useContext(ActionMenuContext); - const { navigateToPreviousRecord } = useRecordShowPagePagination( objectMetadataItem.nameSingular, recordId, ); return { - shouldBeRegistered: !isInRightDrawer, onClick: navigateToPreviousRecord, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useRemoveFromFavoritesSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useRemoveFromFavoritesSingleRecordAction.ts index e2867229e..6ff1b6017 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useRemoveFromFavoritesSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useRemoveFromFavoritesSingleRecordAction.ts @@ -1,11 +1,11 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow'; -import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; +import { ActionHookWithoutObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite'; import { useFavorites } from '@/favorites/hooks/useFavorites'; import { isDefined } from 'twenty-shared/utils'; -export const useRemoveFromFavoritesSingleRecordAction: ActionHookWithObjectMetadataItem = - ({ objectMetadataItem }) => { +export const useRemoveFromFavoritesSingleRecordAction: ActionHookWithoutObjectMetadataItem = + () => { const recordId = useSelectedRecordIdOrThrow(); const { sortedFavorites: favorites } = useFavorites(); @@ -16,15 +16,8 @@ export const useRemoveFromFavoritesSingleRecordAction: ActionHookWithObjectMetad (favorite) => favorite.recordId === recordId, ); - const isFavorite = !!foundFavorite; - - const shouldBeRegistered = - isDefined(objectMetadataItem) && - !objectMetadataItem.isRemote && - isFavorite; - const onClick = () => { - if (!shouldBeRegistered) { + if (!isDefined(foundFavorite)) { return; } @@ -32,7 +25,6 @@ export const useRemoveFromFavoritesSingleRecordAction: ActionHookWithObjectMetad }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useRestoreSingleRecordAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useRestoreSingleRecordAction.tsx index b38f6e492..ca66b68c5 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useRestoreSingleRecordAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useRestoreSingleRecordAction.tsx @@ -1,17 +1,9 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow'; import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; -import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState'; -import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType'; import { useRestoreManyRecords } from '@/object-record/hooks/useRestoreManyRecords'; -import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; -import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState'; -import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; -import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useCallback, useState } from 'react'; -import { useRecoilValue } from 'recoil'; -import { isDefined } from 'twenty-shared/utils'; export const useRestoreSingleRecordAction: ActionHookWithObjectMetadataItem = ({ objectMetadataItem, @@ -21,8 +13,6 @@ export const useRestoreSingleRecordAction: ActionHookWithObjectMetadataItem = ({ const [isRestoreRecordModalOpen, setIsRestoreRecordModalOpen] = useState(false); - const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission(); - const { resetTableRowSelection } = useRecordTable({ recordTableId: objectMetadataItem.namePlural, }); @@ -31,8 +21,6 @@ export const useRestoreSingleRecordAction: ActionHookWithObjectMetadataItem = ({ objectNameSingular: objectMetadataItem.nameSingular, }); - const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId)); - const handleRestoreClick = useCallback(async () => { resetTableRowSelection(); @@ -41,27 +29,7 @@ export const useRestoreSingleRecordAction: ActionHookWithObjectMetadataItem = ({ }); }, [restoreManyRecords, resetTableRowSelection, recordId]); - const isRemoteObject = objectMetadataItem.isRemote; - - const isSoftDeleteFilterActive = useRecoilComponentValueV2( - isSoftDeleteFilterActiveComponentState, - ); - - const isShowPage = - useRecoilComponentValueV2(contextStoreCurrentViewTypeComponentState) === - ContextStoreViewType.ShowPage; - - const shouldBeRegistered = - !isRemoteObject && - isDefined(selectedRecord?.deletedAt) && - !hasObjectReadOnlyPermission && - (isShowPage || isSoftDeleteFilterActive); - const onClick = () => { - if (!shouldBeRegistered) { - return; - } - setIsRestoreRecordModalOpen(true); }; @@ -70,7 +38,6 @@ export const useRestoreSingleRecordAction: ActionHookWithObjectMetadataItem = ({ }; return { - shouldBeRegistered, onClick, ConfirmationModal: ( ({ useWorkflowWithCurrentVersion: jest.fn(), })); @@ -138,66 +93,6 @@ describe('useActivateWorkflowSingleRecordAction', () => { jest.clearAllMocks(); }); - it('should be registered when workflow has trigger and steps and is not active', () => { - (useWorkflowWithCurrentVersion as jest.Mock).mockReturnValue( - draftWorkflowMock, - ); - - const { result } = renderHook( - () => useActivateWorkflowSingleRecordAction(), - { - wrapper: createWrapper(draftWorkflowMock), - }, - ); - - expect(result.current.shouldBeRegistered).toBe(true); - }); - - it('should not be registered when workflow is already active', () => { - (useWorkflowWithCurrentVersion as jest.Mock).mockReturnValue( - activeWorkflowMock, - ); - - const { result } = renderHook( - () => useActivateWorkflowSingleRecordAction(), - { - wrapper: createWrapper(activeWorkflowMock), - }, - ); - - expect(result.current.shouldBeRegistered).toBe(false); - }); - - it('should not be registered when workflow has no steps', () => { - (useWorkflowWithCurrentVersion as jest.Mock).mockReturnValue( - noStepsWorkflowMock, - ); - - const { result } = renderHook( - () => useActivateWorkflowSingleRecordAction(), - { - wrapper: createWrapper(noStepsWorkflowMock), - }, - ); - - expect(result.current.shouldBeRegistered).toBe(false); - }); - - it('should not be registered when workflow has no trigger', () => { - (useWorkflowWithCurrentVersion as jest.Mock).mockReturnValue( - noTriggerWorkflowMock, - ); - - const { result } = renderHook( - () => useActivateWorkflowSingleRecordAction(), - { - wrapper: createWrapper(noTriggerWorkflowMock), - }, - ); - - expect(result.current.shouldBeRegistered).toBe(false); - }); - it('should call activateWorkflowVersion on click', () => { (useWorkflowWithCurrentVersion as jest.Mock).mockReturnValue( draftWorkflowMock, @@ -219,23 +114,4 @@ describe('useActivateWorkflowSingleRecordAction', () => { workflowVersionId: draftWorkflowMock.currentVersion.id, }); }); - - it('should not call activateWorkflowVersion when not registered', () => { - (useWorkflowWithCurrentVersion as jest.Mock).mockReturnValue( - activeWorkflowMock, - ); - - const { result } = renderHook( - () => useActivateWorkflowSingleRecordAction(), - { - wrapper: createWrapper(activeWorkflowMock), - }, - ); - - act(() => { - result.current.onClick(); - }); - - expect(activateWorkflowVersionMock).not.toHaveBeenCalled(); - }); }); diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/__tests__/useDeactivateWorkflowSingleRecordAction.test.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/__tests__/useDeactivateWorkflowSingleRecordAction.test.ts index 86a6a4a50..31f668f19 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/__tests__/useDeactivateWorkflowSingleRecordAction.test.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/__tests__/useDeactivateWorkflowSingleRecordAction.test.ts @@ -37,24 +37,6 @@ const activeWorkflowMock = { }, }; -const deactivatedWorkflowMock = { - __typename: 'Workflow', - id: 'workflowId', - lastPublishedVersionId: 'lastPublishedVersionId', - currentVersion: { - __typename: 'WorkflowVersion', - id: 'currentVersionId', - trigger: 'trigger', - status: 'DEACTIVATED', - steps: [ - { - __typename: 'WorkflowStep', - id: 'stepId1', - }, - ], - }, -}; - jest.mock('@/workflow/hooks/useWorkflowWithCurrentVersion', () => ({ useWorkflowWithCurrentVersion: jest.fn(), })); @@ -90,61 +72,11 @@ const activeWorkflowWrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper( }, ); -const deactivatedWorkflowWrapper = - getJestMetadataAndApolloMocksAndActionMenuWrapper({ - apolloMocks: [], - componentInstanceId: '1', - contextStoreCurrentObjectMetadataNameSingular: - workflowMockObjectMetadataItem.nameSingular, - contextStoreTargetedRecordsRule: { - mode: 'selection', - selectedRecordIds: [deactivatedWorkflowMock.id], - }, - onInitializeRecoilSnapshot: (snapshot) => { - snapshot.set( - recordStoreFamilyState(deactivatedWorkflowMock.id), - deactivatedWorkflowMock, - ); - snapshot.set(currentWorkspaceState, { - ...mockCurrentWorkspace, - featureFlags: [mockedWorkflowEnabledFeatureFlag], - }); - }, - }); - describe('useDeactivateWorkflowSingleRecordAction', () => { beforeEach(() => { jest.clearAllMocks(); }); - it('should not be registered when the workflow is deactivated', () => { - (useWorkflowWithCurrentVersion as jest.Mock).mockImplementation( - () => deactivatedWorkflowMock, - ); - const { result } = renderHook( - () => useDeactivateWorkflowSingleRecordAction(), - { - wrapper: deactivatedWorkflowWrapper, - }, - ); - - expect(result.current.shouldBeRegistered).toBe(false); - }); - - it('should be registered when the workflow is active', () => { - (useWorkflowWithCurrentVersion as jest.Mock).mockImplementation( - () => activeWorkflowMock, - ); - const { result } = renderHook( - () => useDeactivateWorkflowSingleRecordAction(), - { - wrapper: activeWorkflowWrapper, - }, - ); - - expect(result.current.shouldBeRegistered).toBe(true); - }); - it('should call deactivateWorkflowVersion on click', () => { (useWorkflowWithCurrentVersion as jest.Mock).mockImplementation( () => activeWorkflowMock, diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/__tests__/useDiscardDraftWorkflowSingleRecordAction.test.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/__tests__/useDiscardDraftWorkflowSingleRecordAction.test.ts index c60e16d4c..afc63d6b7 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/__tests__/useDiscardDraftWorkflowSingleRecordAction.test.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/__tests__/useDiscardDraftWorkflowSingleRecordAction.test.ts @@ -20,50 +20,6 @@ const mockedWorkflowEnabledFeatureFlag = { workspaceId: '1', }; -const noDraftWorkflowMock = { - __typename: 'Workflow', - id: 'workflowId', - lastPublishedVersionId: 'lastPublishedVersionId', - currentVersion: { - __typename: 'WorkflowVersion', - id: 'currentVersionId', - trigger: 'trigger', - status: 'ACTIVE', - steps: [ - { - __typename: 'WorkflowStep', - id: 'stepId1', - }, - ], - }, - versions: [ - { - __typename: 'WorkflowVersion', - id: 'currentVersionId', - trigger: 'trigger', - status: 'ACTIVE', - steps: [ - { - __typename: 'WorkflowStep', - id: 'stepId1', - }, - ], - }, - { - __typename: 'WorkflowVersion', - id: 'versionId2', - trigger: 'trigger', - status: 'ACTIVE', - steps: [ - { - __typename: 'WorkflowStep', - id: 'stepId2', - }, - ], - }, - ], -}; - const draftWorkflowMock = { __typename: 'Workflow', id: 'workflowId', @@ -108,11 +64,6 @@ const draftWorkflowMock = { ], }; -const draftWorkflowMockWithOneVersion = { - ...draftWorkflowMock, - versions: [draftWorkflowMock.currentVersion], -}; - jest.mock('@/workflow/hooks/useWorkflowWithCurrentVersion', () => ({ useWorkflowWithCurrentVersion: jest.fn(), })); @@ -125,28 +76,6 @@ jest.mock('@/workflow/hooks/useDeleteOneWorkflowVersion', () => ({ }), })); -const noDraftWorkflowWrapper = - getJestMetadataAndApolloMocksAndActionMenuWrapper({ - apolloMocks: [], - componentInstanceId: '1', - contextStoreCurrentObjectMetadataNameSingular: - workflowMockObjectMetadataItem.nameSingular, - contextStoreTargetedRecordsRule: { - mode: 'selection', - selectedRecordIds: [noDraftWorkflowMock.id], - }, - onInitializeRecoilSnapshot: (snapshot) => { - snapshot.set( - recordStoreFamilyState(noDraftWorkflowMock.id), - noDraftWorkflowMock, - ); - snapshot.set(currentWorkspaceState, { - ...mockCurrentWorkspace, - featureFlags: [mockedWorkflowEnabledFeatureFlag], - }); - }, - }); - const draftWorkflowWrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({ apolloMocks: [], componentInstanceId: '1', @@ -168,76 +97,11 @@ const draftWorkflowWrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({ }, }); -const draftWorkflowWithOneVersionWrapper = - getJestMetadataAndApolloMocksAndActionMenuWrapper({ - apolloMocks: [], - componentInstanceId: '1', - contextStoreCurrentObjectMetadataNameSingular: - workflowMockObjectMetadataItem.nameSingular, - contextStoreTargetedRecordsRule: { - mode: 'selection', - selectedRecordIds: [draftWorkflowMockWithOneVersion.id], - }, - onInitializeRecoilSnapshot: (snapshot) => { - snapshot.set( - recordStoreFamilyState(draftWorkflowMockWithOneVersion.id), - draftWorkflowMockWithOneVersion, - ); - snapshot.set(currentWorkspaceState, { - ...mockCurrentWorkspace, - featureFlags: [mockedWorkflowEnabledFeatureFlag], - }); - }, - }); - describe('useDiscardDraftWorkflowSingleRecordAction', () => { beforeEach(() => { jest.clearAllMocks(); }); - it('should not be registered when there is no draft', () => { - (useWorkflowWithCurrentVersion as jest.Mock).mockImplementation( - () => noDraftWorkflowMock, - ); - const { result } = renderHook( - () => useDiscardDraftWorkflowSingleRecordAction(), - { - wrapper: noDraftWorkflowWrapper, - }, - ); - - expect(result.current.shouldBeRegistered).toBe(false); - }); - - it('should not be registered when there is only one version', () => { - (useWorkflowWithCurrentVersion as jest.Mock).mockImplementation( - () => draftWorkflowMockWithOneVersion, - ); - - const { result } = renderHook( - () => useDiscardDraftWorkflowSingleRecordAction(), - { - wrapper: draftWorkflowWithOneVersionWrapper, - }, - ); - - expect(result.current.shouldBeRegistered).toBe(false); - }); - - it('should be registered when the workflow is draft', () => { - (useWorkflowWithCurrentVersion as jest.Mock).mockImplementation( - () => draftWorkflowMock, - ); - const { result } = renderHook( - () => useDiscardDraftWorkflowSingleRecordAction(), - { - wrapper: draftWorkflowWrapper, - }, - ); - - expect(result.current.shouldBeRegistered).toBe(true); - }); - it('should call deleteOneWorkflowVersion on click', () => { (useWorkflowWithCurrentVersion as jest.Mock).mockImplementation( () => draftWorkflowMock, diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useActivateWorkflowSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useActivateWorkflowSingleRecordAction.ts index f6d42fc27..d3ea2a653 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useActivateWorkflowSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useActivateWorkflowSingleRecordAction.ts @@ -12,17 +12,8 @@ export const useActivateWorkflowSingleRecordAction: ActionHookWithoutObjectMetad const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(recordId); - const shouldBeRegistered = - isDefined(workflowWithCurrentVersion?.currentVersion?.trigger) && - isDefined(workflowWithCurrentVersion.currentVersion?.steps) && - workflowWithCurrentVersion.currentVersion.steps.length > 0 && - (workflowWithCurrentVersion.currentVersion.status === 'DRAFT' || - !workflowWithCurrentVersion.versions?.some( - (version) => version.status === 'ACTIVE', - )); - const onClick = () => { - if (!shouldBeRegistered) { + if (!isDefined(workflowWithCurrentVersion)) { return; } @@ -33,7 +24,6 @@ export const useActivateWorkflowSingleRecordAction: ActionHookWithoutObjectMetad }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useDeactivateWorkflowSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useDeactivateWorkflowSingleRecordAction.ts index 19f3537db..feb5559c0 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useDeactivateWorkflowSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useDeactivateWorkflowSingleRecordAction.ts @@ -12,12 +12,8 @@ export const useDeactivateWorkflowSingleRecordAction: ActionHookWithoutObjectMet const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(recordId); - const shouldBeRegistered = - isDefined(workflowWithCurrentVersion) && - workflowWithCurrentVersion.currentVersion.status === 'ACTIVE'; - const onClick = () => { - if (!shouldBeRegistered) { + if (!isDefined(workflowWithCurrentVersion)) { return; } @@ -27,7 +23,6 @@ export const useDeactivateWorkflowSingleRecordAction: ActionHookWithoutObjectMet }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useDiscardDraftWorkflowSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useDiscardDraftWorkflowSingleRecordAction.ts index 75342b6e5..5c5ec1b51 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useDiscardDraftWorkflowSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useDiscardDraftWorkflowSingleRecordAction.ts @@ -12,13 +12,8 @@ export const useDiscardDraftWorkflowSingleRecordAction: ActionHookWithoutObjectM const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(recordId); - const shouldBeRegistered = - isDefined(workflowWithCurrentVersion) && - workflowWithCurrentVersion.versions.length > 1 && - workflowWithCurrentVersion.currentVersion.status === 'DRAFT'; - const onClick = () => { - if (!shouldBeRegistered) { + if (!isDefined(workflowWithCurrentVersion)) { return; } @@ -28,7 +23,6 @@ export const useDiscardDraftWorkflowSingleRecordAction: ActionHookWithoutObjectM }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeActiveVersionWorkflowSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeActiveVersionWorkflowSingleRecordAction.ts index 3b6d40b24..25b639ec5 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeActiveVersionWorkflowSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeActiveVersionWorkflowSingleRecordAction.ts @@ -3,26 +3,19 @@ import { ActionHookWithoutObjectMetadataItem } from '@/action-menu/actions/types import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { AppPath } from '@/types/AppPath'; import { useActiveWorkflowVersion } from '@/workflow/hooks/useActiveWorkflowVersion'; -import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; -import { useNavigateApp } from '~/hooks/useNavigateApp'; import { isDefined } from 'twenty-shared/utils'; +import { useNavigateApp } from '~/hooks/useNavigateApp'; export const useSeeActiveVersionWorkflowSingleRecordAction: ActionHookWithoutObjectMetadataItem = () => { const recordId = useSelectedRecordIdOrThrow(); - const workflow = useWorkflowWithCurrentVersion(recordId); - - const isDraft = workflow?.statuses?.includes('DRAFT') || false; - const workflowActiveVersion = useActiveWorkflowVersion(recordId); const navigateApp = useNavigateApp(); - const shouldBeRegistered = isDefined(workflowActiveVersion) && isDraft; - const onClick = () => { - if (!shouldBeRegistered) { + if (!isDefined(workflowActiveVersion)) { return; } @@ -33,7 +26,6 @@ export const useSeeActiveVersionWorkflowSingleRecordAction: ActionHookWithoutObj }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeRunsWorkflowSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeRunsWorkflowSingleRecordAction.ts index f51058abb..be17a73b7 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeRunsWorkflowSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeRunsWorkflowSingleRecordAction.ts @@ -4,8 +4,8 @@ import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlur import { AppPath } from '@/types/AppPath'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; -import { useNavigateApp } from '~/hooks/useNavigateApp'; import { isDefined } from 'twenty-shared/utils'; +import { useNavigateApp } from '~/hooks/useNavigateApp'; export const useSeeRunsWorkflowSingleRecordAction: ActionHookWithoutObjectMetadataItem = () => { @@ -15,10 +15,8 @@ export const useSeeRunsWorkflowSingleRecordAction: ActionHookWithoutObjectMetada const navigateApp = useNavigateApp(); - const shouldBeRegistered = isDefined(workflowWithCurrentVersion); - const onClick = () => { - if (!shouldBeRegistered) { + if (!isDefined(workflowWithCurrentVersion)) { return; } @@ -40,7 +38,6 @@ export const useSeeRunsWorkflowSingleRecordAction: ActionHookWithoutObjectMetada }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeVersionsWorkflowSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeVersionsWorkflowSingleRecordAction.ts index c6e43bfe3..a2e6ff80c 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeVersionsWorkflowSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useSeeVersionsWorkflowSingleRecordAction.ts @@ -4,8 +4,8 @@ import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlur import { AppPath } from '@/types/AppPath'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; -import { useNavigateApp } from '~/hooks/useNavigateApp'; import { isDefined } from 'twenty-shared/utils'; +import { useNavigateApp } from '~/hooks/useNavigateApp'; export const useSeeVersionsWorkflowSingleRecordAction: ActionHookWithoutObjectMetadataItem = () => { @@ -15,10 +15,10 @@ export const useSeeVersionsWorkflowSingleRecordAction: ActionHookWithoutObjectMe const navigateApp = useNavigateApp(); - const shouldBeRegistered = isDefined(workflowWithCurrentVersion); - const onClick = () => { - if (!shouldBeRegistered) return; + if (!isDefined(workflowWithCurrentVersion)) { + return; + } navigateApp( AppPath.RecordIndexPage, @@ -38,7 +38,6 @@ export const useSeeVersionsWorkflowSingleRecordAction: ActionHookWithoutObjectMe }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useTestWorkflowSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useTestWorkflowSingleRecordAction.ts index b06dbd67d..977a113eb 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useTestWorkflowSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/hooks/useTestWorkflowSingleRecordAction.ts @@ -12,16 +12,8 @@ export const useTestWorkflowSingleRecordAction: ActionHookWithoutObjectMetadataI const { runWorkflowVersion } = useRunWorkflowVersion(); - const shouldBeRegistered = - isDefined(workflowWithCurrentVersion?.currentVersion?.trigger) && - ((workflowWithCurrentVersion.currentVersion.trigger.type === 'MANUAL' && - !isDefined( - workflowWithCurrentVersion.currentVersion.trigger.settings.objectType, - )) || - workflowWithCurrentVersion.currentVersion.trigger.type === 'WEBHOOK'); - const onClick = () => { - if (!shouldBeRegistered) { + if (!isDefined(workflowWithCurrentVersion)) { return; } @@ -31,7 +23,6 @@ export const useTestWorkflowSingleRecordAction: ActionHookWithoutObjectMetadataI }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/hooks/useSeeVersionWorkflowRunSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/hooks/useSeeVersionWorkflowRunSingleRecordAction.ts index 6ea3c516a..4a1a9cb6b 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/hooks/useSeeVersionWorkflowRunSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/hooks/useSeeVersionWorkflowRunSingleRecordAction.ts @@ -15,10 +15,13 @@ export const useSeeVersionWorkflowRunSingleRecordAction: ActionHookWithoutObject const navigateApp = useNavigateApp(); - const shouldBeRegistered = isDefined(workflowRun?.workflowVersion?.id); - const onClick = () => { - if (!shouldBeRegistered || !workflowRun?.workflowVersion?.id) return; + if ( + !isDefined(workflowRun) || + !isDefined(workflowRun?.workflowVersion?.id) + ) { + return; + } navigateApp(AppPath.RecordShowPage, { objectNameSingular: CoreObjectNameSingular.WorkflowVersion, @@ -27,7 +30,6 @@ export const useSeeVersionWorkflowRunSingleRecordAction: ActionHookWithoutObject }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/hooks/useSeeWorkflowWorkflowRunSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/hooks/useSeeWorkflowWorkflowRunSingleRecordAction.ts index 0fd5b6a18..d3a82a5c7 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/hooks/useSeeWorkflowWorkflowRunSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/hooks/useSeeWorkflowWorkflowRunSingleRecordAction.ts @@ -15,10 +15,10 @@ export const useSeeWorkflowWorkflowRunSingleRecordAction: ActionHookWithoutObjec const navigateApp = useNavigateApp(); - const shouldBeRegistered = isDefined(workflowRun?.workflow?.id); - const onClick = () => { - if (!shouldBeRegistered || !workflowRun?.workflow?.id) return; + if (!isDefined(workflowRun) || !isDefined(workflowRun?.workflow?.id)) { + return; + } navigateApp(AppPath.RecordShowPage, { objectNameSingular: CoreObjectNameSingular.Workflow, @@ -27,7 +27,6 @@ export const useSeeWorkflowWorkflowRunSingleRecordAction: ActionHookWithoutObjec }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeRunsWorkflowVersionSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeRunsWorkflowVersionSingleRecordAction.ts index d72a4e9f7..de34a2765 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeRunsWorkflowVersionSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeRunsWorkflowVersionSingleRecordAction.ts @@ -6,8 +6,8 @@ import { AppPath } from '@/types/AppPath'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; import { useRecoilValue } from 'recoil'; -import { useNavigateApp } from '~/hooks/useNavigateApp'; import { isDefined } from 'twenty-shared/utils'; +import { useNavigateApp } from '~/hooks/useNavigateApp'; export const useSeeRunsWorkflowVersionSingleRecordAction: ActionHookWithoutObjectMetadataItem = () => { @@ -21,10 +21,10 @@ export const useSeeRunsWorkflowVersionSingleRecordAction: ActionHookWithoutObjec const navigateApp = useNavigateApp(); - const shouldBeRegistered = isDefined(workflowWithCurrentVersion); - const onClick = () => { - if (!shouldBeRegistered) return; + if (!isDefined(workflowWithCurrentVersion)) { + return; + } navigateApp( AppPath.RecordIndexPage, @@ -49,7 +49,6 @@ export const useSeeRunsWorkflowVersionSingleRecordAction: ActionHookWithoutObjec }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeVersionsWorkflowVersionSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeVersionsWorkflowVersionSingleRecordAction.ts index 4565a2d9e..c06d09a59 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeVersionsWorkflowVersionSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeVersionsWorkflowVersionSingleRecordAction.ts @@ -6,8 +6,8 @@ import { AppPath } from '@/types/AppPath'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; import { useRecoilValue } from 'recoil'; -import { useNavigateApp } from '~/hooks/useNavigateApp'; import { isDefined } from 'twenty-shared/utils'; +import { useNavigateApp } from '~/hooks/useNavigateApp'; export const useSeeVersionsWorkflowVersionSingleRecordAction: ActionHookWithoutObjectMetadataItem = () => { @@ -21,10 +21,10 @@ export const useSeeVersionsWorkflowVersionSingleRecordAction: ActionHookWithoutO const navigateApp = useNavigateApp(); - const shouldBeRegistered = isDefined(workflowWithCurrentVersion); - const onClick = () => { - if (!shouldBeRegistered) return; + if (!isDefined(workflowWithCurrentVersion)) { + return; + } navigateApp( AppPath.RecordIndexPage, @@ -44,7 +44,6 @@ export const useSeeVersionsWorkflowVersionSingleRecordAction: ActionHookWithoutO }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeWorkflowWorkflowVersionSingleRecordAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeWorkflowWorkflowVersionSingleRecordAction.ts index b4fdb2103..cf58cb9bd 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeWorkflowWorkflowVersionSingleRecordAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useSeeWorkflowWorkflowVersionSingleRecordAction.ts @@ -15,10 +15,13 @@ export const useSeeWorkflowWorkflowVersionSingleRecordAction: ActionHookWithoutO const navigateApp = useNavigateApp(); - const shouldBeRegistered = isDefined(workflowVersion?.workflow?.id); - const onClick = () => { - if (!shouldBeRegistered || !workflowVersion?.workflow?.id) return; + if ( + !isDefined(workflowVersion) || + !isDefined(workflowVersion?.workflow?.id) + ) { + return; + } navigateApp(AppPath.RecordShowPage, { objectNameSingular: CoreObjectNameSingular.Workflow, @@ -27,7 +30,6 @@ export const useSeeWorkflowWorkflowVersionSingleRecordAction: ActionHookWithoutO }; return { - shouldBeRegistered, onClick, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useUseAsDraftWorkflowVersionSingleRecordAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useUseAsDraftWorkflowVersionSingleRecordAction.tsx index 36234a5a8..a2702f109 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useUseAsDraftWorkflowVersionSingleRecordAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/hooks/useUseAsDraftWorkflowVersionSingleRecordAction.tsx @@ -8,8 +8,8 @@ import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion'; import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; import { openOverrideWorkflowDraftConfirmationModalState } from '@/workflow/states/openOverrideWorkflowDraftConfirmationModalState'; import { useSetRecoilState } from 'recoil'; -import { useNavigateApp } from '~/hooks/useNavigateApp'; import { isDefined } from 'twenty-shared/utils'; +import { useNavigateApp } from '~/hooks/useNavigateApp'; export const useUseAsDraftWorkflowVersionSingleRecordAction: ActionHookWithoutObjectMetadataItem = () => { @@ -33,13 +33,10 @@ export const useUseAsDraftWorkflowVersionSingleRecordAction: ActionHookWithoutOb const hasAlreadyDraftVersion = workflow?.versions.some((version) => version.status === 'DRAFT') || false; - const shouldBeRegistered = - isDefined(workflowVersion) && - isDefined(workflow) && - workflowVersion.status !== 'DRAFT'; - const onClick = async () => { - if (!shouldBeRegistered) return; + if (!isDefined(workflowVersion) || !isDefined(workflow)) { + return; + } if (hasAlreadyDraftVersion) { setOpenOverrideWorkflowDraftConfirmationModal(true); @@ -55,7 +52,7 @@ export const useUseAsDraftWorkflowVersionSingleRecordAction: ActionHookWithoutOb } }; - const ConfirmationModal = shouldBeRegistered ? ( + const ConfirmationModal = isDefined(workflowVersion) ? ( ; + actionKeys: DefaultRecordActionConfigKeys[]; + propertiesToOverwrite: Partial< + Record> + >; +}): Record => { + const actionsFromDefaultConfig = actionKeys.reduce( + (acc, key) => ({ + ...acc, + [key]: { + ...DEFAULT_RECORD_ACTIONS_CONFIG[key], + ...propertiesToOverwrite[key], + }, + }), + {} as Record, + ); + + return { + ...actionsFromDefaultConfig, + ...config, + }; +}; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/components/RegisterAgnosticRecordActionEffect.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/components/RegisterAgnosticRecordActionEffect.tsx index 493b8b5ba..e8a664db5 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/components/RegisterAgnosticRecordActionEffect.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/components/RegisterAgnosticRecordActionEffect.tsx @@ -1,20 +1,19 @@ -import { ActionHookWithoutObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; +import { RecordAgnosticConfigAction } from '@/action-menu/actions/types/RecordAgnosticConfigAction'; import { wrapActionInCallbacks } from '@/action-menu/actions/utils/wrapActionInCallbacks'; import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries'; -import { ActionMenuEntry } from '@/action-menu/types/ActionMenuEntry'; import { useContext, useEffect } from 'react'; type RegisterAgnosticRecordActionEffectProps = { - action: ActionMenuEntry & { - useAction: ActionHookWithoutObjectMetadataItem; - }; + action: RecordAgnosticConfigAction; }; export const RegisterAgnosticRecordActionEffect = ({ action, }: RegisterAgnosticRecordActionEffectProps) => { - const { shouldBeRegistered, onClick, ConfirmationModal } = action.useAction(); + const { onClick, ConfirmationModal } = action.useAction(); + + const shouldBeRegistered = action.shouldBeRegistered({}); const { onActionStartedCallback, onActionExecutedCallback } = useContext(ActionMenuContext); diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/constants/RecordAgnosticActionsConfig.ts b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/constants/RecordAgnosticActionsConfig.ts index f042e0259..3185e8474 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/constants/RecordAgnosticActionsConfig.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/constants/RecordAgnosticActionsConfig.ts @@ -1,9 +1,8 @@ import { useSearchRecordsRecordAgnosticAction } from '@/action-menu/actions/record-agnostic-actions/hooks/useSearchRecordsRecordAgnosticAction'; -import { RecordAgnosticActionsKey } from '@/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKey'; -import { ActionHookWithoutObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; +import { RecordAgnosticActionsKeys } from '@/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKeys'; import { ActionViewType } from '@/action-menu/actions/types/ActionViewType'; +import { RecordAgnosticConfigAction } from '@/action-menu/actions/types/RecordAgnosticConfigAction'; import { - ActionMenuEntry, ActionMenuEntryScope, ActionMenuEntryType, } from '@/action-menu/types/ActionMenuEntry'; @@ -12,14 +11,12 @@ import { IconSearch } from 'twenty-ui'; export const RECORD_AGNOSTIC_ACTIONS_CONFIG: Record< string, - ActionMenuEntry & { - useAction: ActionHookWithoutObjectMetadataItem; - } + RecordAgnosticConfigAction > = { - searchRecords: { + [RecordAgnosticActionsKeys.SEARCH_RECORDS]: { type: ActionMenuEntryType.Standard, scope: ActionMenuEntryScope.Global, - key: RecordAgnosticActionsKey.SEARCH_RECORDS, + key: RecordAgnosticActionsKeys.SEARCH_RECORDS, label: msg`Search records`, shortLabel: msg`Search`, position: 0, @@ -28,11 +25,12 @@ export const RECORD_AGNOSTIC_ACTIONS_CONFIG: Record< availableOn: [ActionViewType.GLOBAL], useAction: useSearchRecordsRecordAgnosticAction, hotKeys: ['/'], + shouldBeRegistered: () => true, }, - searchRecordsFallback: { + [RecordAgnosticActionsKeys.SEARCH_RECORDS_FALLBACK]: { type: ActionMenuEntryType.Fallback, scope: ActionMenuEntryScope.Global, - key: RecordAgnosticActionsKey.SEARCH_RECORDS_FALLBACK, + key: RecordAgnosticActionsKeys.SEARCH_RECORDS_FALLBACK, label: msg`Search records`, shortLabel: msg`Search`, position: 1, @@ -41,5 +39,6 @@ export const RECORD_AGNOSTIC_ACTIONS_CONFIG: Record< availableOn: [ActionViewType.GLOBAL], useAction: useSearchRecordsRecordAgnosticAction, hotKeys: ['/'], + shouldBeRegistered: () => true, }, }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/useSearchRecordsRecordAgnosticAction.ts b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/useSearchRecordsRecordAgnosticAction.ts index 51a3bdf5c..74ca4007c 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/useSearchRecordsRecordAgnosticAction.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/useSearchRecordsRecordAgnosticAction.ts @@ -15,6 +15,5 @@ export const useSearchRecordsRecordAgnosticAction = () => { return { onClick, - shouldBeRegistered: true, }; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/run-workflow-actions/hooks/useRunWorkflowActions.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/run-workflow-actions/hooks/useRunWorkflowActions.tsx index d66ca20ed..f5dd470cb 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/run-workflow-actions/hooks/useRunWorkflowActions.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/run-workflow-actions/hooks/useRunWorkflowActions.tsx @@ -6,9 +6,9 @@ import { useActiveWorkflowVersionsWithManualTrigger } from '@/workflow/hooks/use import { useRunWorkflowVersion } from '@/workflow/hooks/useRunWorkflowVersion'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { msg } from '@lingui/core/macro'; +import { capitalize, isDefined } from 'twenty-shared/utils'; import { IconSettingsAutomation } from 'twenty-ui'; import { FeatureFlagKey } from '~/generated/graphql'; -import { capitalize, isDefined } from 'twenty-shared/utils'; export const useRunWorkflowActions = () => { const isWorkflowEnabled = useIsFeatureEnabled( @@ -39,9 +39,9 @@ export const useRunWorkflowActions = () => { label: msg`${name}`, position: index, Icon: IconSettingsAutomation, + shouldBeRegistered: () => true, useAction: () => { return { - shouldBeRegistered: true, onClick: async () => { await runWorkflowVersion({ workflowVersionId: activeWorkflowVersion.id, diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKey.ts b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKeys.ts similarity index 70% rename from packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKey.ts rename to packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKeys.ts index ddbbaba10..efeae410f 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKey.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKeys.ts @@ -1,4 +1,4 @@ -export enum RecordAgnosticActionsKey { +export enum RecordAgnosticActionsKeys { SEARCH_RECORDS = 'search-records', SEARCH_RECORDS_FALLBACK = 'search-records-fallback', } diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/ActionHookResult.ts b/packages/twenty-front/src/modules/action-menu/actions/types/ActionHookResult.ts index 7fa7c3a68..7bc70def2 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/types/ActionHookResult.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/types/ActionHookResult.ts @@ -1,7 +1,6 @@ import { ConfirmationModalProps } from '@/ui/layout/modal/components/ConfirmationModal'; export type ActionHookResult = { - shouldBeRegistered: boolean; onClick: () => Promise | void; ConfirmationModal?: React.ReactElement; }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/DefaultRecordActionConfigKeys.ts b/packages/twenty-front/src/modules/action-menu/actions/types/DefaultRecordActionConfigKeys.ts new file mode 100644 index 000000000..df8652069 --- /dev/null +++ b/packages/twenty-front/src/modules/action-menu/actions/types/DefaultRecordActionConfigKeys.ts @@ -0,0 +1,8 @@ +import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys'; +import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys'; +import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey'; + +export type DefaultRecordActionConfigKeys = + | NoSelectionRecordActionKeys + | SingleRecordActionKeys + | MultipleRecordsActionKeys; diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/RecordAgnosticConfigAction.ts b/packages/twenty-front/src/modules/action-menu/actions/types/RecordAgnosticConfigAction.ts new file mode 100644 index 000000000..95dbb81e8 --- /dev/null +++ b/packages/twenty-front/src/modules/action-menu/actions/types/RecordAgnosticConfigAction.ts @@ -0,0 +1,9 @@ +import { ActionHookWithoutObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; +import { RecordConfigAction } from '@/action-menu/actions/types/RecordConfigAction'; + +export type RecordAgnosticConfigAction = Omit< + RecordConfigAction, + 'useAction' +> & { + useAction: ActionHookWithoutObjectMetadataItem; +}; diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/RecordConfigAction.ts b/packages/twenty-front/src/modules/action-menu/actions/types/RecordConfigAction.ts new file mode 100644 index 000000000..cdacbf1a1 --- /dev/null +++ b/packages/twenty-front/src/modules/action-menu/actions/types/RecordConfigAction.ts @@ -0,0 +1,25 @@ +import { ActionHook } from '@/action-menu/actions/types/ActionHook'; +import { ActionViewType } from '@/action-menu/actions/types/ActionViewType'; +import { ShouldBeRegisteredFunctionParams } from '@/action-menu/actions/types/ShouldBeRegisteredFunctionParams'; +import { + ActionMenuEntryScope, + ActionMenuEntryType, +} from '@/action-menu/types/ActionMenuEntry'; +import { MessageDescriptor } from '@lingui/core'; +import { IconComponent, MenuItemAccent } from 'twenty-ui'; + +export type RecordConfigAction = { + type: ActionMenuEntryType; + scope: ActionMenuEntryScope; + key: string; + label: MessageDescriptor; + shortLabel?: MessageDescriptor; + position: number; + Icon: IconComponent; + isPinned?: boolean; + accent?: MenuItemAccent; + availableOn?: ActionViewType[]; + shouldBeRegistered: (params: ShouldBeRegisteredFunctionParams) => boolean; + useAction: ActionHook; + hotKeys?: string[]; +}; diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/ShouldBeRegisteredFunctionParams.ts b/packages/twenty-front/src/modules/action-menu/actions/types/ShouldBeRegisteredFunctionParams.ts new file mode 100644 index 000000000..8a5821869 --- /dev/null +++ b/packages/twenty-front/src/modules/action-menu/actions/types/ShouldBeRegisteredFunctionParams.ts @@ -0,0 +1,20 @@ +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; +import { ObjectRecord } from '@/object-record/types/ObjectRecord'; +import { WorkflowWithCurrentVersion } from '@/workflow/types/Workflow'; + +export type ShouldBeRegisteredFunctionParams = { + objectMetadataItem?: ObjectMetadataItem; + hasObjectReadOnlyPermission?: boolean; + isWorkflowsEnabled?: boolean; + recordFilters?: RecordFilter[]; + isShowPage?: boolean; + isSoftDeleteFilterActive?: boolean; + isInRightDrawer?: boolean; + isFavorite?: boolean; + isRemote?: boolean; + isNoteOrTask?: boolean; + selectedRecord?: ObjectRecord; + numberOfSelectedRecords?: number; + workflowWithCurrentVersion?: WorkflowWithCurrentVersion; +}; diff --git a/packages/twenty-front/src/modules/action-menu/actions/utils/getActionConfig.ts b/packages/twenty-front/src/modules/action-menu/actions/utils/getActionConfig.ts index 3ab53f1d0..c804b300c 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/utils/getActionConfig.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/utils/getActionConfig.ts @@ -1,4 +1,4 @@ -import { DEFAULT_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/DefaultActionsConfig'; +import { DEFAULT_RECORD_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig'; import { WORKFLOW_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/WorkflowActionsConfig'; import { WORKFLOW_RUNS_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/WorkflowRunsActionsConfig'; import { WORKFLOW_VERSIONS_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/WorkflowVersionsActionsConfig'; @@ -14,6 +14,6 @@ export const getActionConfig = (objectMetadataItem: ObjectMetadataItem) => { case CoreObjectNameSingular.WorkflowRun: return WORKFLOW_RUNS_ACTIONS_CONFIG; default: - return DEFAULT_ACTIONS_CONFIG; + return DEFAULT_RECORD_ACTIONS_CONFIG; } }; diff --git a/packages/twenty-front/src/modules/action-menu/hooks/useShouldActionBeRegisteredParams.ts b/packages/twenty-front/src/modules/action-menu/hooks/useShouldActionBeRegisteredParams.ts new file mode 100644 index 000000000..33b0d1f1e --- /dev/null +++ b/packages/twenty-front/src/modules/action-menu/hooks/useShouldActionBeRegisteredParams.ts @@ -0,0 +1,88 @@ +import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; +import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState'; +import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; +import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; +import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType'; +import { useFavorites } from '@/favorites/hooks/useFavorites'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; +import { isSoftDeleteFilterActiveComponentState } from '@/object-record/record-table/states/isSoftDeleteFilterActiveComponentState'; +import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; +import { useContext } from 'react'; +import { useRecoilValue } from 'recoil'; +import { FeatureFlagKey } from '~/generated-metadata/graphql'; + +export const useShouldActionBeRegisteredParams = ({ + objectMetadataItem, +}: { + objectMetadataItem: ObjectMetadataItem; +}) => { + const { sortedFavorites: favorites } = useFavorites(); + + const contextStoreTargetedRecordsRule = useRecoilComponentValueV2( + contextStoreTargetedRecordsRuleComponentState, + ); + + const recordId = + contextStoreTargetedRecordsRule.mode === 'selection' + ? contextStoreTargetedRecordsRule.selectedRecordIds[0] + : undefined; + + const foundFavorite = favorites?.find( + (favorite) => favorite.recordId === recordId, + ); + + const isFavorite = !!foundFavorite; + + const selectedRecord = + useRecoilValue(recordStoreFamilyState(recordId ?? '')) || undefined; + + const isRemoteObject = objectMetadataItem.isRemote; + + const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission(); + + const isNoteOrTask = + objectMetadataItem?.nameSingular === CoreObjectNameSingular.Note || + objectMetadataItem?.nameSingular === CoreObjectNameSingular.Task; + + const { isInRightDrawer } = useContext(ActionMenuContext); + + const isSoftDeleteFilterActive = useRecoilComponentValueV2( + isSoftDeleteFilterActiveComponentState, + ); + + const isShowPage = + useRecoilComponentValueV2(contextStoreCurrentViewTypeComponentState) === + ContextStoreViewType.ShowPage; + + const isWorkflowsEnabled = useIsFeatureEnabled( + FeatureFlagKey.IsWorkflowEnabled, + ); + + const numberOfSelectedRecords = useRecoilComponentValueV2( + contextStoreNumberOfSelectedRecordsComponentState, + ); + + const workflowWithCurrentVersion = useWorkflowWithCurrentVersion( + recordId, + objectMetadataItem.nameSingular !== CoreObjectNameSingular.Workflow, + ); + + return { + isFavorite, + isRemoteObject, + hasObjectReadOnlyPermission, + isNoteOrTask, + isInRightDrawer, + isSoftDeleteFilterActive, + isShowPage, + selectedRecord, + isWorkflowsEnabled, + numberOfSelectedRecords, + workflowWithCurrentVersion, + }; +}; diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenuContainer.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenuContainer.tsx index b481cc722..633367bae 100644 --- a/packages/twenty-front/src/modules/command-menu/components/CommandMenuContainer.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenuContainer.tsx @@ -1,8 +1,8 @@ import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter'; -import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKey'; +import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys'; import { RecordAgnosticActionMenuEntriesSetter } from '@/action-menu/actions/record-agnostic-actions/components/RecordAgnosticActionMenuEntriesSetter'; import { RunWorkflowRecordAgnosticActionMenuEntriesSetter } from '@/action-menu/actions/record-agnostic-actions/components/RunWorkflowRecordAgnosticActionMenuEntriesSetter'; -import { RecordAgnosticActionsKey } from '@/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKey'; +import { RecordAgnosticActionsKeys } from '@/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKeys'; import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals'; import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; @@ -144,16 +144,16 @@ export const CommandMenuContainer = ({ isInRightDrawer: true, onActionExecutedCallback: ({ key }) => { if ( - key !== RecordAgnosticActionsKey.SEARCH_RECORDS && + key !== RecordAgnosticActionsKeys.SEARCH_RECORDS && key !== - RecordAgnosticActionsKey.SEARCH_RECORDS_FALLBACK && + RecordAgnosticActionsKeys.SEARCH_RECORDS_FALLBACK && key !== NoSelectionRecordActionKeys.CREATE_NEW_RECORD ) { toggleCommandMenu(); } if ( - key !== RecordAgnosticActionsKey.SEARCH_RECORDS_FALLBACK + key !== RecordAgnosticActionsKeys.SEARCH_RECORDS_FALLBACK ) { setCommandMenuSearch(''); } diff --git a/packages/twenty-front/src/modules/workflow/hooks/useWorkflowWithCurrentVersion.ts b/packages/twenty-front/src/modules/workflow/hooks/useWorkflowWithCurrentVersion.ts index d3a4920f8..bca93e017 100644 --- a/packages/twenty-front/src/modules/workflow/hooks/useWorkflowWithCurrentVersion.ts +++ b/packages/twenty-front/src/modules/workflow/hooks/useWorkflowWithCurrentVersion.ts @@ -9,6 +9,7 @@ import { isDefined } from 'twenty-shared/utils'; export const useWorkflowWithCurrentVersion = ( workflowId: string | undefined, + skip = false, ): WorkflowWithCurrentVersion | undefined => { const { record: workflow } = useFindOneRecord({ objectNameSingular: CoreObjectNameSingular.Workflow, @@ -20,7 +21,7 @@ export const useWorkflowWithCurrentVersion = ( lastPublishedVersionId: true, versions: true, }, - skip: !isDefined(workflowId), + skip: !isDefined(workflowId) || skip, }); return useMemo(() => {