Fix workflow with manual triggers and no selection not appearing in the command menu (#11544)
Fix workflow with manual triggers and no selection not appearing in the command menu --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -23,5 +23,5 @@ export const Action = ({
|
||||
onClick();
|
||||
};
|
||||
|
||||
return <ActionDisplay action={actionConfig} onClick={handleClick} />;
|
||||
return <ActionDisplay onClick={handleClick} />;
|
||||
};
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDisplay';
|
||||
import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
|
||||
import { useCloseActionMenu } from '@/action-menu/hooks/useCloseActionMenu';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { useContext } from 'react';
|
||||
import { PathParam } from 'react-router-dom';
|
||||
import { getAppPath } from '~/utils/navigation/getAppPath';
|
||||
|
||||
@ -15,21 +13,9 @@ export const ActionLink = <T extends AppPath>({
|
||||
params?: { [key in PathParam<T>]: string | null };
|
||||
queryParams?: Record<string, any>;
|
||||
}) => {
|
||||
const actionConfig = useContext(ActionConfigContext);
|
||||
|
||||
const { closeActionMenu } = useCloseActionMenu();
|
||||
|
||||
if (!actionConfig) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const path = getAppPath(to, params, queryParams);
|
||||
|
||||
return (
|
||||
<ActionDisplay
|
||||
action={{ ...actionConfig }}
|
||||
onClick={closeActionMenu}
|
||||
to={path}
|
||||
/>
|
||||
);
|
||||
return <ActionDisplay onClick={closeActionMenu} to={path} />;
|
||||
};
|
||||
|
||||
@ -46,7 +46,7 @@ export const ActionModal = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<ActionDisplay action={actionConfig} onClick={handleOpen} />
|
||||
<ActionDisplay onClick={handleOpen} />
|
||||
{isOpen &&
|
||||
createPortal(
|
||||
<ConfirmationModal
|
||||
|
||||
@ -44,5 +44,5 @@ export const ActionOpenSidePanelPage = ({
|
||||
}
|
||||
};
|
||||
|
||||
return <ActionDisplay action={actionConfig} onClick={handleClick} />;
|
||||
return <ActionDisplay onClick={handleClick} />;
|
||||
};
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { ActionButton } from '@/action-menu/actions/display/components/ActionButton';
|
||||
import { ActionDropdownItem } from '@/action-menu/actions/display/components/ActionDropdownItem';
|
||||
import { ActionListItem } from '@/action-menu/actions/display/components/ActionListItem';
|
||||
import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
|
||||
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { MessageDescriptor } from '@lingui/core';
|
||||
import { useContext } from 'react';
|
||||
@ -19,14 +20,13 @@ export type ActionDisplayProps = {
|
||||
};
|
||||
|
||||
export const ActionDisplay = ({
|
||||
action,
|
||||
onClick,
|
||||
to,
|
||||
}: {
|
||||
action: ActionDisplayProps;
|
||||
onClick?: (event?: React.MouseEvent<HTMLElement>) => void;
|
||||
to?: string;
|
||||
}) => {
|
||||
const action = useContext(ActionConfigContext);
|
||||
const { displayType } = useContext(ActionMenuContext);
|
||||
|
||||
if (!action) {
|
||||
|
||||
@ -13,10 +13,12 @@ import { useRecoilValue } from 'recoil';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
import { IconSettingsAutomation } from 'twenty-ui/display';
|
||||
|
||||
export const useWorkflowRunRecordActions = ({
|
||||
export const useRunWorkflowRecordActions = ({
|
||||
objectMetadataItem,
|
||||
skip,
|
||||
}: {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
skip?: boolean;
|
||||
}) => {
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
@ -27,17 +29,14 @@ export const useWorkflowRunRecordActions = ({
|
||||
? contextStoreTargetedRecordsRule.selectedRecordIds[0]
|
||||
: undefined;
|
||||
|
||||
if (!isDefined(selectedRecordId)) {
|
||||
throw new Error('Selected record ID is required');
|
||||
}
|
||||
|
||||
const selectedRecord = useRecoilValue(
|
||||
recordStoreFamilyState(selectedRecordId),
|
||||
recordStoreFamilyState(selectedRecordId ?? ''),
|
||||
);
|
||||
|
||||
const { records: activeWorkflowVersions } =
|
||||
useActiveWorkflowVersionsWithManualTrigger({
|
||||
objectMetadataItem,
|
||||
skip,
|
||||
});
|
||||
|
||||
const { runWorkflowVersion } = useRunWorkflowVersion();
|
||||
@ -1,4 +1,5 @@
|
||||
import { ActionLink } from '@/action-menu/actions/components/ActionLink';
|
||||
import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDisplay';
|
||||
import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
@ -7,14 +8,18 @@ import { useActiveWorkflowVersion } from '@/workflow/hooks/useActiveWorkflowVers
|
||||
export const SeeActiveVersionWorkflowSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
|
||||
const workflowActiveVersion = useActiveWorkflowVersion(recordId);
|
||||
const { workflowVersion, loading } = useActiveWorkflowVersion(recordId);
|
||||
|
||||
if (loading) {
|
||||
return <ActionDisplay />;
|
||||
}
|
||||
|
||||
return (
|
||||
<ActionLink
|
||||
to={AppPath.RecordShowPage}
|
||||
params={{
|
||||
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
|
||||
objectRecordId: workflowActiveVersion.id,
|
||||
objectRecordId: workflowVersion.id,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -1,28 +1,37 @@
|
||||
import { Action } from '@/action-menu/actions/components/Action';
|
||||
import { ActionScope } from '@/action-menu/actions/types/ActionScope';
|
||||
import { ActionType } from '@/action-menu/actions/types/ActionType';
|
||||
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { useActiveWorkflowVersionsWithManualTrigger } from '@/workflow/hooks/useActiveWorkflowVersionsWithManualTrigger';
|
||||
import { useRunWorkflowVersion } from '@/workflow/hooks/useRunWorkflowVersion';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useContext } from 'react';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
import { IconSettingsAutomation } from 'twenty-ui/display';
|
||||
import { FeatureFlagKey } from '~/generated/graphql';
|
||||
|
||||
export const useRunWorkflowActions = () => {
|
||||
export const useRunWorkflowRecordAgnosticActions = () => {
|
||||
const isWorkflowEnabled = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IsWorkflowEnabled,
|
||||
);
|
||||
|
||||
const { actionMenuType } = useContext(ActionMenuContext);
|
||||
|
||||
const { records: activeWorkflowVersions } =
|
||||
useActiveWorkflowVersionsWithManualTrigger({});
|
||||
useActiveWorkflowVersionsWithManualTrigger({
|
||||
skip:
|
||||
actionMenuType !== 'command-menu' &&
|
||||
actionMenuType !== 'command-menu-show-page-action-menu-dropdown',
|
||||
});
|
||||
|
||||
const { runWorkflowVersion } = useRunWorkflowVersion();
|
||||
|
||||
if (!isWorkflowEnabled) {
|
||||
return { runWorkflowActions: [] };
|
||||
return [];
|
||||
}
|
||||
|
||||
const runWorkflowActions = activeWorkflowVersions
|
||||
return activeWorkflowVersions
|
||||
.map((activeWorkflowVersion, index) => {
|
||||
if (!isDefined(activeWorkflowVersion.workflow)) {
|
||||
return undefined;
|
||||
@ -38,18 +47,16 @@ export const useRunWorkflowActions = () => {
|
||||
position: index,
|
||||
Icon: IconSettingsAutomation,
|
||||
shouldBeRegistered: () => true,
|
||||
useAction: () => {
|
||||
return {
|
||||
onClick: async () => {
|
||||
await runWorkflowVersion({
|
||||
component: (
|
||||
<Action
|
||||
onClick={() => {
|
||||
runWorkflowVersion({
|
||||
workflowVersionId: activeWorkflowVersion.id,
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
}}
|
||||
/>
|
||||
),
|
||||
};
|
||||
})
|
||||
.filter(isDefined);
|
||||
|
||||
return { runWorkflowActions };
|
||||
};
|
||||
@ -1,10 +1,9 @@
|
||||
import { ActionMenuContextType } from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { ActionMenuContextProviderWorkflowObjects } from '@/action-menu/contexts/ActionMenuContextProviderWorkflowObjects';
|
||||
import { ActionMenuContextProviderWorkflowsEnabled } from '@/action-menu/contexts/ActionMenuContextProviderWorkflowsEnabled';
|
||||
import { ActionMenuContextProviderWorkflowsEnabledSingleRecordSelection } from '@/action-menu/contexts/ActionMenuContextProviderWorkflowsEnabledSingleRecordSelection';
|
||||
import { ActionMenuContextProviderWorkflowsNotEnabled } from '@/action-menu/contexts/ActionMenuContextProviderWorkflowsNotEnabled';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
@ -50,39 +49,30 @@ export const ActionMenuContextProvider = ({
|
||||
const objectMetadataItem =
|
||||
localContextStoreObjectMetadataItem ?? mainContextStoreObjectMetadataItem;
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
const isSingleRecordSelection =
|
||||
contextStoreTargetedRecordsRule.mode === 'selection' &&
|
||||
contextStoreTargetedRecordsRule.selectedRecordIds.length === 1;
|
||||
|
||||
const isWorkflowObject =
|
||||
objectMetadataItem?.nameSingular === CoreObjectNameSingular.Workflow ||
|
||||
objectMetadataItem?.nameSingular === CoreObjectNameSingular.WorkflowRun ||
|
||||
objectMetadataItem?.nameSingular === CoreObjectNameSingular.WorkflowVersion;
|
||||
|
||||
if (
|
||||
isWorkflowEnabled &&
|
||||
isSingleRecordSelection &&
|
||||
isDefined(objectMetadataItem) &&
|
||||
(actionMenuType === 'command-menu' ||
|
||||
actionMenuType === 'command-menu-show-page-action-menu-dropdown')
|
||||
) {
|
||||
if (isWorkflowEnabled && isDefined(objectMetadataItem) && isWorkflowObject) {
|
||||
return (
|
||||
<ActionMenuContextProviderWorkflowsEnabledSingleRecordSelection
|
||||
<ActionMenuContextProviderWorkflowObjects
|
||||
isInRightDrawer={isInRightDrawer}
|
||||
displayType={displayType}
|
||||
actionMenuType={actionMenuType}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
>
|
||||
{children}
|
||||
</ActionMenuContextProviderWorkflowsEnabledSingleRecordSelection>
|
||||
</ActionMenuContextProviderWorkflowObjects>
|
||||
);
|
||||
}
|
||||
|
||||
if (isWorkflowEnabled && isDefined(objectMetadataItem) && isWorkflowObject) {
|
||||
if (
|
||||
isWorkflowEnabled &&
|
||||
isDefined(objectMetadataItem) &&
|
||||
(actionMenuType === 'command-menu' ||
|
||||
actionMenuType === 'command-menu-show-page-action-menu-dropdown')
|
||||
) {
|
||||
return (
|
||||
<ActionMenuContextProviderWorkflowsEnabled
|
||||
isInRightDrawer={isInRightDrawer}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useWorkflowRunRecordActions } from '@/action-menu/actions/record-actions/workflow-run-record-actions/hooks/useWorkflowRunRecordActions';
|
||||
import { useRunWorkflowRecordAgnosticActions } from '@/action-menu/actions/record-agnostic-actions/run-workflow-actions/hooks/useRunWorkflowRecordAgnosticActions';
|
||||
import {
|
||||
ActionMenuContext,
|
||||
ActionMenuContextType,
|
||||
@ -8,7 +8,7 @@ import { useShouldActionBeRegisteredParams } from '@/action-menu/hooks/useShould
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
|
||||
export const ActionMenuContextProviderWorkflowsEnabledSingleRecordSelection = ({
|
||||
export const ActionMenuContextProviderWorkflowObjects = ({
|
||||
objectMetadataItem,
|
||||
isInRightDrawer,
|
||||
displayType,
|
||||
@ -36,9 +36,8 @@ export const ActionMenuContextProviderWorkflowsEnabledSingleRecordSelection = ({
|
||||
|
||||
const actions = useRegisteredActions(shouldBeRegisteredParams);
|
||||
|
||||
const workflowRunRecordActions = useWorkflowRunRecordActions({
|
||||
objectMetadataItem,
|
||||
});
|
||||
const runWorkflowRecordAgnosticActions =
|
||||
useRunWorkflowRecordAgnosticActions();
|
||||
|
||||
return (
|
||||
<ActionMenuContext.Provider
|
||||
@ -46,7 +45,7 @@ export const ActionMenuContextProviderWorkflowsEnabledSingleRecordSelection = ({
|
||||
isInRightDrawer,
|
||||
displayType,
|
||||
actionMenuType,
|
||||
actions: [...actions, ...workflowRunRecordActions],
|
||||
actions: [...actions, ...runWorkflowRecordAgnosticActions],
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
@ -1,10 +1,14 @@
|
||||
import { useRunWorkflowRecordActions } from '@/action-menu/actions/record-actions/run-workflow-actions/hooks/useRunWorkflowRecordActions';
|
||||
import { useRunWorkflowRecordAgnosticActions } from '@/action-menu/actions/record-agnostic-actions/run-workflow-actions/hooks/useRunWorkflowRecordAgnosticActions';
|
||||
import {
|
||||
ActionMenuContext,
|
||||
ActionMenuContextType,
|
||||
} from '@/action-menu/contexts/ActionMenuContext';
|
||||
import { useRegisteredActions } from '@/action-menu/hooks/useRegisteredActions';
|
||||
import { useShouldActionBeRegisteredParams } from '@/action-menu/hooks/useShouldActionBeRegisteredParams';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
|
||||
export const ActionMenuContextProviderWorkflowsEnabled = ({
|
||||
@ -35,13 +39,33 @@ export const ActionMenuContextProviderWorkflowsEnabled = ({
|
||||
|
||||
const actions = useRegisteredActions(shouldBeRegisteredParams);
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
const isSingleRecordSelection =
|
||||
contextStoreTargetedRecordsRule.mode === 'selection' &&
|
||||
contextStoreTargetedRecordsRule.selectedRecordIds.length === 1;
|
||||
|
||||
const runWorkflowRecordActions = useRunWorkflowRecordActions({
|
||||
objectMetadataItem,
|
||||
skip: !isSingleRecordSelection,
|
||||
});
|
||||
|
||||
const runWorkflowRecordAgnosticActions =
|
||||
useRunWorkflowRecordAgnosticActions();
|
||||
|
||||
return (
|
||||
<ActionMenuContext.Provider
|
||||
value={{
|
||||
isInRightDrawer,
|
||||
displayType,
|
||||
actionMenuType,
|
||||
actions,
|
||||
actions: [
|
||||
...actions,
|
||||
...runWorkflowRecordActions,
|
||||
...runWorkflowRecordAgnosticActions,
|
||||
],
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@ -3,7 +3,7 @@ import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { Workflow, WorkflowVersion } from '@/workflow/types/Workflow';
|
||||
|
||||
export const useActiveWorkflowVersion = (workflowId: string) => {
|
||||
const { records: workflowVersions } = useFindManyRecords<
|
||||
const { records: workflowVersions, loading } = useFindManyRecords<
|
||||
WorkflowVersion & {
|
||||
workflow: Omit<Workflow, 'versions'> & {
|
||||
versions: Array<{ __typename: string }>;
|
||||
@ -39,5 +39,8 @@ export const useActiveWorkflowVersion = (workflowId: string) => {
|
||||
},
|
||||
});
|
||||
|
||||
return workflowVersions?.[0];
|
||||
return {
|
||||
workflowVersion: workflowVersions?.[0],
|
||||
loading,
|
||||
};
|
||||
};
|
||||
|
||||
@ -8,8 +8,10 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useActiveWorkflowVersionsWithManualTrigger = ({
|
||||
objectMetadataItem,
|
||||
skip,
|
||||
}: {
|
||||
objectMetadataItem?: ObjectMetadataItem;
|
||||
skip?: boolean;
|
||||
}) => {
|
||||
const filters = [
|
||||
{
|
||||
@ -50,6 +52,7 @@ export const useActiveWorkflowVersionsWithManualTrigger = ({
|
||||
}),
|
||||
workflow: true,
|
||||
},
|
||||
skip,
|
||||
});
|
||||
|
||||
// TODO: refactor when we can use 'not like' in the RawJson filter
|
||||
|
||||
Reference in New Issue
Block a user