mirror of
https://github.com/twentyhq/twenty.git
synced 2026-06-14 10:59:20 -04:00
Show app logo on workflow logic function nodes (#21482)
Workflow `LOGIC_FUNCTION` action nodes (functions provided by an installed app) previously rendered a generic ƒ icon in the diagram. They now display the owning app's logo instead. The node's logic function id is resolved to its `applicationId` and rendered via the existing `AppChip`. When no app can be resolved (e.g. the logic function isn't loaded yet, or has no application), it falls back to the original ƒ icon, so nodes never look broken. Inline `CODE` actions are unchanged. ## Before <img width="692" height="670" alt="CleanShot 2026-06-12 at 15 27 22@2x" src="https://github.com/user-attachments/assets/4d7c17ce-dbe3-45e6-9d44-41e363b2e4a5" /> ## After <img width="592" height="628" alt="CleanShot 2026-06-12 at 15 26 22@2x" src="https://github.com/user-attachments/assets/d55c308f-3cde-4153-8d5d-ec948bebc823" /> <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/21482?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
@@ -65,6 +65,7 @@ export type WorkflowDiagramStepNodeData =
|
||||
nodeType: 'action';
|
||||
actionType: WorkflowActionType;
|
||||
name: string;
|
||||
logicFunctionId?: string;
|
||||
runStatus?: WorkflowRunStepStatus;
|
||||
hasNextStepIds: boolean;
|
||||
stepId: string;
|
||||
|
||||
@@ -47,6 +47,9 @@ export const generateNodesAndEdgesForDefaultNode = ({
|
||||
nodeType: 'action',
|
||||
actionType: step.type,
|
||||
name: step.name,
|
||||
...(step.type === 'LOGIC_FUNCTION'
|
||||
? { logicFunctionId: step.settings.input.logicFunctionId }
|
||||
: {}),
|
||||
hasNextStepIds:
|
||||
isDefined(step.nextStepIds) && step.nextStepIds.length > 0,
|
||||
stepId: step.id,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { type WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey';
|
||||
import { WorkflowDiagramStepNodeLogicFunctionIcon } from '@/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeLogicFunctionIcon';
|
||||
import { assertUnreachable } from 'twenty-shared/utils';
|
||||
import { useIcons } from 'twenty-ui-deprecated/display';
|
||||
import { ThemeContext } from 'twenty-ui-deprecated/theme-constants';
|
||||
@@ -43,6 +44,13 @@ export const WorkflowDiagramStepNodeIcon = ({
|
||||
/>
|
||||
);
|
||||
}
|
||||
case 'LOGIC_FUNCTION': {
|
||||
return (
|
||||
<WorkflowDiagramStepNodeLogicFunctionIcon
|
||||
logicFunctionId={data.logicFunctionId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
case 'FORM': {
|
||||
return <Icon size={theme.icon.size.md} color={theme.color.orange} />;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { AppChip } from '@/applications/components/AppChip';
|
||||
import { logicFunctionsSelector } from '@/logic-functions/states/logicFunctionsSelector';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { getActionIcon } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIcon';
|
||||
import { useContext } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useIcons } from 'twenty-ui-deprecated/display';
|
||||
import { ThemeContext } from 'twenty-ui-deprecated/theme-constants';
|
||||
|
||||
export const WorkflowDiagramStepNodeLogicFunctionIcon = ({
|
||||
logicFunctionId,
|
||||
}: {
|
||||
logicFunctionId?: string;
|
||||
}) => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const { getIcon } = useIcons();
|
||||
const logicFunctions = useAtomStateValue(logicFunctionsSelector);
|
||||
|
||||
const applicationId = isDefined(logicFunctionId)
|
||||
? logicFunctions.find(
|
||||
(logicFunction) => logicFunction.id === logicFunctionId,
|
||||
)?.applicationId
|
||||
: undefined;
|
||||
|
||||
if (isDefined(applicationId)) {
|
||||
return <AppChip applicationId={applicationId} size="md" chipOnly />;
|
||||
}
|
||||
|
||||
const FallbackIcon = getIcon(getActionIcon('LOGIC_FUNCTION'));
|
||||
|
||||
return (
|
||||
<FallbackIcon
|
||||
size={theme.icon.size.md}
|
||||
color={theme.font.color.tertiary}
|
||||
stroke={theme.icon.stroke.sm}
|
||||
/>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user