Fix icon matching + small other fixes on workflows (#9814)
- Record Fields label - body height fix - Icons on object picker - Fix icon matching between nodes and right drawer <img width="1296" alt="Capture d’écran 2025-01-23 à 18 51 12" src="https://github.com/user-attachments/assets/ecd5fb00-49cd-416e-96af-9200418294e0" />
This commit is contained in:
@ -12,13 +12,14 @@ import {
|
||||
WorkflowDiagramNode,
|
||||
WorkflowDiagramStepNodeData,
|
||||
} from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { getWorkflowNodeIcon } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIcon';
|
||||
import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey';
|
||||
import { OnSelectionChangeParams, useOnSelectionChange } from '@xyflow/react';
|
||||
import { useCallback } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { IconBolt, isDefined } from 'twenty-ui';
|
||||
import { IconBolt, isDefined, useIcons } from 'twenty-ui';
|
||||
|
||||
export const WorkflowDiagramCanvasEditableEffect = () => {
|
||||
const { getIcon } = useIcons();
|
||||
const { startNodeCreation } = useStartNodeCreation();
|
||||
|
||||
const { openRightDrawer, closeRightDrawer } = useRightDrawer();
|
||||
@ -66,7 +67,7 @@ export const WorkflowDiagramCanvasEditableEffect = () => {
|
||||
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
|
||||
openRightDrawer(RightDrawerPages.WorkflowStepEdit, {
|
||||
title: selectedNodeData.name,
|
||||
Icon: getWorkflowNodeIcon(selectedNodeData),
|
||||
Icon: getIcon(getWorkflowNodeIconKey(selectedNodeData)),
|
||||
});
|
||||
},
|
||||
[
|
||||
@ -76,6 +77,7 @@ export const WorkflowDiagramCanvasEditableEffect = () => {
|
||||
closeRightDrawer,
|
||||
closeCommandMenu,
|
||||
startNodeCreation,
|
||||
getIcon,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@ -9,13 +9,14 @@ import {
|
||||
WorkflowDiagramNode,
|
||||
WorkflowDiagramStepNodeData,
|
||||
} from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { getWorkflowNodeIcon } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIcon';
|
||||
import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey';
|
||||
import { OnSelectionChangeParams, useOnSelectionChange } from '@xyflow/react';
|
||||
import { useCallback } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
import { isDefined, useIcons } from 'twenty-ui';
|
||||
|
||||
export const WorkflowDiagramCanvasReadonlyEffect = () => {
|
||||
const { getIcon } = useIcons();
|
||||
const { openRightDrawer, closeRightDrawer } = useRightDrawer();
|
||||
const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState);
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
@ -38,7 +39,7 @@ export const WorkflowDiagramCanvasReadonlyEffect = () => {
|
||||
const selectedNodeData = selectedNode.data as WorkflowDiagramStepNodeData;
|
||||
openRightDrawer(RightDrawerPages.WorkflowStepView, {
|
||||
title: selectedNodeData.name,
|
||||
Icon: getWorkflowNodeIcon(selectedNodeData),
|
||||
Icon: getIcon(getWorkflowNodeIconKey(selectedNodeData)),
|
||||
});
|
||||
},
|
||||
[
|
||||
@ -47,6 +48,7 @@ export const WorkflowDiagramCanvasReadonlyEffect = () => {
|
||||
openRightDrawer,
|
||||
closeRightDrawer,
|
||||
closeCommandMenu,
|
||||
getIcon,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { WorkflowDiagramBaseStepNode } from '@/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconPlaylistAdd } from 'twenty-ui';
|
||||
|
||||
const StyledStepNodeLabelIconContainer = styled.div`
|
||||
align-items: center;
|
||||
@ -9,25 +7,16 @@ const StyledStepNodeLabelIconContainer = styled.div`
|
||||
border-radius: ${({ theme }) => theme.spacing(1)};
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: ${({ theme }) => theme.spacing(1)};
|
||||
padding: ${({ theme }) => theme.spacing(3)};
|
||||
`;
|
||||
|
||||
export const WorkflowDiagramEmptyTrigger = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<WorkflowDiagramBaseStepNode
|
||||
name="Add a Trigger"
|
||||
nodeType="trigger"
|
||||
variant="placeholder"
|
||||
Icon={
|
||||
<StyledStepNodeLabelIconContainer>
|
||||
<IconPlaylistAdd
|
||||
size={theme.icon.size.md}
|
||||
color={theme.font.color.tertiary}
|
||||
/>
|
||||
</StyledStepNodeLabelIconContainer>
|
||||
}
|
||||
Icon={<StyledStepNodeLabelIconContainer />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { assertUnreachable } from '@/workflow/utils/assertUnreachable';
|
||||
import { WorkflowDiagramBaseStepNode } from '@/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode';
|
||||
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { getWorkflowNodeIcon } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIcon';
|
||||
import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useIcons } from 'twenty-ui';
|
||||
|
||||
const StyledStepNodeLabelIconContainer = styled.div`
|
||||
align-items: center;
|
||||
@ -22,8 +23,8 @@ export const WorkflowDiagramStepNodeBase = ({
|
||||
RightFloatingElement?: React.ReactNode;
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const Icon = getWorkflowNodeIcon(data);
|
||||
const { getIcon } = useIcons();
|
||||
const Icon = getIcon(getWorkflowNodeIconKey(data));
|
||||
|
||||
const renderStepIcon = () => {
|
||||
switch (data.nodeType) {
|
||||
@ -73,9 +74,7 @@ export const WorkflowDiagramStepNodeBase = ({
|
||||
</StyledStepNodeLabelIconContainer>
|
||||
);
|
||||
}
|
||||
case 'CREATE_RECORD':
|
||||
case 'UPDATE_RECORD':
|
||||
case 'DELETE_RECORD': {
|
||||
default: {
|
||||
return (
|
||||
<StyledStepNodeLabelIconContainer>
|
||||
<Icon
|
||||
@ -89,8 +88,6 @@ export const WorkflowDiagramStepNodeBase = ({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return assertUnreachable(data);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@ -17,6 +17,7 @@ export type WorkflowDiagramStepNodeData =
|
||||
nodeType: 'trigger';
|
||||
triggerType: WorkflowTriggerType;
|
||||
name: string;
|
||||
icon?: string;
|
||||
}
|
||||
| {
|
||||
nodeType: 'action';
|
||||
|
||||
@ -33,7 +33,7 @@ describe('getWorkflowVersionDiagram', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('returns a diagram with an empty-trigger node if the provided workflow version has no steps', () => {
|
||||
it('returns a diagram with only a trigger node if the provided workflow version has no steps', () => {
|
||||
const result = getWorkflowVersionDiagram({
|
||||
__typename: 'WorkflowVersion',
|
||||
status: 'ACTIVE',
|
||||
@ -42,7 +42,7 @@ describe('getWorkflowVersionDiagram', () => {
|
||||
name: '',
|
||||
steps: null,
|
||||
trigger: {
|
||||
name: 'Company created',
|
||||
name: 'Record is created',
|
||||
settings: { eventName: 'company.created', outputSchema: {} },
|
||||
type: 'DATABASE_EVENT',
|
||||
},
|
||||
@ -54,9 +54,10 @@ describe('getWorkflowVersionDiagram', () => {
|
||||
nodes: [
|
||||
{
|
||||
data: {
|
||||
name: 'Company created',
|
||||
name: 'Record is created',
|
||||
nodeType: 'trigger',
|
||||
triggerType: 'DATABASE_EVENT',
|
||||
icon: 'IconPlus',
|
||||
},
|
||||
id: 'trigger',
|
||||
position: { x: 0, y: 0 },
|
||||
|
||||
@ -7,9 +7,10 @@ import {
|
||||
WorkflowDiagramEdge,
|
||||
WorkflowDiagramNode,
|
||||
} from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { DATABASE_TRIGGER_EVENTS } from '@/workflow/workflow-trigger/constants/DatabaseTriggerEvents';
|
||||
import { DATABASE_TRIGGER_TYPES } from '@/workflow/workflow-trigger/constants/DatabaseTriggerTypes';
|
||||
|
||||
import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId';
|
||||
import { getTriggerIcon } from '@/workflow/workflow-trigger/utils/getTriggerIcon';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
@ -57,11 +58,15 @@ export const generateWorkflowDiagram = ({
|
||||
const triggerNodeId = TRIGGER_STEP_ID;
|
||||
|
||||
if (isDefined(trigger)) {
|
||||
let triggerLabel: string;
|
||||
let triggerDefaultLabel: string;
|
||||
let triggerIcon: string | undefined;
|
||||
|
||||
switch (trigger.type) {
|
||||
case 'MANUAL': {
|
||||
triggerLabel = 'Manual Trigger';
|
||||
triggerDefaultLabel = 'Manual Trigger';
|
||||
triggerIcon = getTriggerIcon({
|
||||
type: 'MANUAL',
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
@ -70,10 +75,15 @@ export const generateWorkflowDiagram = ({
|
||||
trigger.settings.eventName,
|
||||
);
|
||||
|
||||
triggerLabel =
|
||||
DATABASE_TRIGGER_EVENTS.find(
|
||||
(event) => event.value === triggerEvent.event,
|
||||
)?.label ?? '';
|
||||
triggerDefaultLabel =
|
||||
DATABASE_TRIGGER_TYPES.find(
|
||||
(item) => item.event === triggerEvent.event,
|
||||
)?.defaultLabel ?? '';
|
||||
|
||||
triggerIcon = getTriggerIcon({
|
||||
type: 'DATABASE_EVENT',
|
||||
eventName: triggerEvent.event,
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
@ -90,7 +100,8 @@ export const generateWorkflowDiagram = ({
|
||||
data: {
|
||||
nodeType: 'trigger',
|
||||
triggerType: trigger.type,
|
||||
name: isDefined(trigger.name) ? trigger.name : triggerLabel,
|
||||
name: isDefined(trigger.name) ? trigger.name : triggerDefaultLabel,
|
||||
icon: triggerIcon,
|
||||
},
|
||||
position: {
|
||||
x: 0,
|
||||
|
||||
@ -1,56 +0,0 @@
|
||||
import {
|
||||
WorkflowActionType,
|
||||
WorkflowTriggerType,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { assertUnreachable } from '@/workflow/utils/assertUnreachable';
|
||||
import {
|
||||
IconAddressBook,
|
||||
IconCode,
|
||||
IconHandMove,
|
||||
IconMail,
|
||||
IconPlaylistAdd,
|
||||
} from 'twenty-ui';
|
||||
|
||||
export const getWorkflowNodeIcon = (
|
||||
data:
|
||||
| {
|
||||
nodeType: 'trigger';
|
||||
triggerType: WorkflowTriggerType;
|
||||
}
|
||||
| {
|
||||
nodeType: 'action';
|
||||
actionType: WorkflowActionType;
|
||||
},
|
||||
) => {
|
||||
switch (data.nodeType) {
|
||||
case 'trigger': {
|
||||
switch (data.triggerType) {
|
||||
case 'DATABASE_EVENT': {
|
||||
return IconPlaylistAdd;
|
||||
}
|
||||
case 'MANUAL': {
|
||||
return IconHandMove;
|
||||
}
|
||||
}
|
||||
|
||||
return assertUnreachable(data.triggerType);
|
||||
}
|
||||
case 'action': {
|
||||
switch (data.actionType) {
|
||||
case 'CODE': {
|
||||
return IconCode;
|
||||
}
|
||||
case 'SEND_EMAIL': {
|
||||
return IconMail;
|
||||
}
|
||||
case 'CREATE_RECORD':
|
||||
case 'UPDATE_RECORD':
|
||||
case 'DELETE_RECORD': {
|
||||
return IconAddressBook;
|
||||
}
|
||||
}
|
||||
|
||||
return assertUnreachable(data.actionType);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,13 @@
|
||||
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { getActionIcon } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIcon';
|
||||
|
||||
export const getWorkflowNodeIconKey = (data: WorkflowDiagramStepNodeData) => {
|
||||
switch (data.nodeType) {
|
||||
case 'trigger': {
|
||||
return data.icon;
|
||||
}
|
||||
case 'action': {
|
||||
return getActionIcon(data.actionType);
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user