From 5b1cfa4cc0d7f35407df5e5a6f146f40fcdeb084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?= <71827178+bosiraphael@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:30:23 +0200 Subject: [PATCH] Show app name on workflow logic function nodes (#21675) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Workflow logic-function nodes from installed integration apps now show the owning app's name as the node label (e.g. "People Data Labs") instead of the generic "Action". The descriptive title below it (e.g. "Enrich Person") is unchanged. This only applies to installed integration apps — plain custom-code functions and standard functions keep showing "Action". A new `useWorkflowNodeLabel` hook resolves the logic function's `applicationId` and returns the app name for integration apps, falling back to the node type otherwise. It's used by the editable, read-only, and run node renderers. ## Before CleanShot 2026-06-16 at 16 26 42@2x ## After CleanShot 2026-06-16 at 16 25 46@2x Review in cubic --- ...WorkflowDiagramStepNodeEditableContent.tsx | 7 +++-- .../WorkflowDiagramStepNodeReadonly.tsx | 7 +++-- .../components/WorkflowRunDiagramStepNode.tsx | 7 +++-- .../hooks/useWorkflowNodeLabel.ts | 31 +++++++++++++++++++ 4 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/hooks/useWorkflowNodeLabel.ts diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx index 8c1a063fcf..2c651cae1c 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx @@ -17,13 +17,14 @@ import { WorkflowNodeRightPart } from '@/workflow/workflow-diagram/workflow-node import { WorkflowNodeTitle } from '@/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeTitle'; import { WORKFLOW_DIAGRAM_NODE_DEFAULT_SOURCE_HANDLE_ID } from '@/workflow/workflow-diagram/workflow-nodes/constants/WorkflowDiagramNodeDefaultSourceHandleId'; import { useConnectionState } from '@/workflow/workflow-diagram/workflow-nodes/hooks/useConnectionState'; +import { useWorkflowNodeLabel } from '@/workflow/workflow-diagram/workflow-nodes/hooks/useWorkflowNodeLabel'; import { isNodeTitleHighlighted } from '@/workflow/workflow-diagram/workflow-nodes/utils/isNodeTitleHighlighted'; import { workflowInsertStepIdsComponentState } from '@/workflow/workflow-steps/states/workflowInsertStepIdsComponentState'; import { styled } from '@linaria/react'; import { useLingui } from '@lingui/react/macro'; import { Position } from '@xyflow/react'; import { useState } from 'react'; -import { capitalize, isDefined } from 'twenty-shared/utils'; +import { isDefined } from 'twenty-shared/utils'; const StyledAddStepButtonContainer = styled.div<{ shouldDisplay: boolean; @@ -75,6 +76,8 @@ export const WorkflowDiagramStepNodeEditableContent = ({ const isNodeConnectable = isConnectable({ nodeId: id }); + const nodeLabel = useWorkflowNodeLabel(data); + const handleAddStepButtonContainerClick = ( event: React.MouseEvent, ) => { @@ -110,7 +113,7 @@ export const WorkflowDiagramStepNodeEditableContent = ({ - {capitalize(data.nodeType)} + {nodeLabel} diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx index fe50895f7f..8e4b6ff67e 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx @@ -20,10 +20,11 @@ import { WorkflowNodeLabelWithCounterPart } from '@/workflow/workflow-diagram/wo import { WorkflowNodeRightPart } from '@/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeRightPart'; import { WorkflowNodeTitle } from '@/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeTitle'; import { WORKFLOW_DIAGRAM_NODE_DEFAULT_SOURCE_HANDLE_ID } from '@/workflow/workflow-diagram/workflow-nodes/constants/WorkflowDiagramNodeDefaultSourceHandleId'; +import { useWorkflowNodeLabel } from '@/workflow/workflow-diagram/workflow-nodes/hooks/useWorkflowNodeLabel'; import { isNodeTitleHighlighted } from '@/workflow/workflow-diagram/workflow-nodes/utils/isNodeTitleHighlighted'; import { Position } from '@xyflow/react'; import { useContext } from 'react'; -import { capitalize, isDefined } from 'twenty-shared/utils'; +import { isDefined } from 'twenty-shared/utils'; import { useIcons } from 'twenty-ui-deprecated/display'; export const WorkflowDiagramStepNodeReadonly = ({ @@ -85,6 +86,8 @@ export const WorkflowDiagramStepNodeReadonly = ({ actionType: data.nodeType === 'action' ? data.actionType : undefined, }); + const nodeLabel = useWorkflowNodeLabel(data); + return ( <> - {capitalize(data.nodeType)} + {nodeLabel} diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx index 318683a3ec..5e3d31594c 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx @@ -22,11 +22,12 @@ import { WorkflowNodeLabel } from '@/workflow/workflow-diagram/workflow-nodes/co import { WorkflowNodeRightPart } from '@/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeRightPart'; import { WorkflowNodeTitle } from '@/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeTitle'; import { WORKFLOW_DIAGRAM_NODE_DEFAULT_SOURCE_HANDLE_ID } from '@/workflow/workflow-diagram/workflow-nodes/constants/WorkflowDiagramNodeDefaultSourceHandleId'; +import { useWorkflowNodeLabel } from '@/workflow/workflow-diagram/workflow-nodes/hooks/useWorkflowNodeLabel'; import { getNodeIterationCount } from '@/workflow/workflow-diagram/workflow-nodes/utils/getNodeIterationCount'; import { styled } from '@linaria/react'; import { Position } from '@xyflow/react'; import { useContext } from 'react'; -import { capitalize, isDefined } from 'twenty-shared/utils'; +import { isDefined } from 'twenty-shared/utils'; import { StepStatus } from 'twenty-shared/workflow'; import { IconCheck, IconX, useIcons } from 'twenty-ui-deprecated/display'; import { Loader } from 'twenty-ui-deprecated/feedback'; @@ -116,6 +117,8 @@ export const WorkflowRunDiagramStepNode = ({ ? getNodeIterationCount({ stepInfo }) : 0; + const nodeLabel = useWorkflowNodeLabel(data); + const handleClick = () => { if (!isDefined(workflowVisualizerWorkflowId)) { throw new Error('Workflow ID must be defined'); @@ -153,7 +156,7 @@ export const WorkflowRunDiagramStepNode = ({ - {capitalize(data.nodeType)} + {nodeLabel} diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/hooks/useWorkflowNodeLabel.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/hooks/useWorkflowNodeLabel.ts new file mode 100644 index 0000000000..1070ee1880 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/hooks/useWorkflowNodeLabel.ts @@ -0,0 +1,31 @@ +import { useApplicationChipData } from '@/applications/hooks/useApplicationChipData'; +import { useIsThirdPartyApplication } from '@/applications/hooks/useIsThirdPartyApplication'; +import { logicFunctionsSelector } from '@/logic-functions/states/logicFunctionsSelector'; +import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; +import { type WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; +import { capitalize, isDefined } from 'twenty-shared/utils'; + +export const useWorkflowNodeLabel = ( + data: WorkflowDiagramStepNodeData, +): string => { + const logicFunctions = useAtomStateValue(logicFunctionsSelector); + + const logicFunctionId = + data.nodeType === 'action' ? data.logicFunctionId : undefined; + + const applicationId = isDefined(logicFunctionId) + ? logicFunctions.find( + (logicFunction) => logicFunction.id === logicFunctionId, + )?.applicationId + : undefined; + + const isThirdPartyApplication = useIsThirdPartyApplication(applicationId); + + const { applicationChipData } = useApplicationChipData({ applicationId }); + + if (isThirdPartyApplication) { + return applicationChipData.name; + } + + return capitalize(data.nodeType); +};