Simplify the component layers for workflow nodes (#10042)
- Remove the `WorkflowDiagramBaseStepNode` component - Create the `WorkflowDiagramStepNodeIcon` component to centralize the icon put in workflow step nodes; that was the main task of the `WorkflowDiagramBaseStepNode` component and the new `WorkflowDiagramStepNodeIcon` component made it obsolete - Update the `WorkflowDiagramStepNodeBase` component to be THE low level component
This commit is contained in:
committed by
GitHub
parent
9838bec004
commit
e21cbb2fe2
@ -1,219 +0,0 @@
|
|||||||
import { NODE_BORDER_WIDTH } from '@/workflow/workflow-diagram/constants/NodeBorderWidth';
|
|
||||||
import { NODE_HANDLE_HEIGHT_PX } from '@/workflow/workflow-diagram/constants/NodeHandleHeightPx';
|
|
||||||
import { NODE_HANDLE_WIDTH_PX } from '@/workflow/workflow-diagram/constants/NodeHandleWidthPx';
|
|
||||||
import { NODE_ICON_LEFT_MARGIN } from '@/workflow/workflow-diagram/constants/NodeIconLeftMargin';
|
|
||||||
import { NODE_ICON_WIDTH } from '@/workflow/workflow-diagram/constants/NodeIconWidth';
|
|
||||||
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
|
||||||
import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
|
|
||||||
import { css } from '@emotion/react';
|
|
||||||
import styled from '@emotion/styled';
|
|
||||||
import { Handle, Position } from '@xyflow/react';
|
|
||||||
import React from 'react';
|
|
||||||
import { capitalize, isDefined } from 'twenty-shared';
|
|
||||||
import { Label, OverflowingTextWithTooltip } from 'twenty-ui';
|
|
||||||
|
|
||||||
const StyledStepNodeContainer = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
padding-block: ${({ theme }) => theme.spacing(3)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledStepNodeType = styled.div<{
|
|
||||||
nodeVariant: WorkflowDiagramNodeVariant;
|
|
||||||
}>`
|
|
||||||
${({ nodeVariant, theme }) => {
|
|
||||||
switch (nodeVariant) {
|
|
||||||
case 'success': {
|
|
||||||
return css`
|
|
||||||
background-color: ${theme.tag.background.turquoise};
|
|
||||||
color: ${theme.tag.text.turquoise};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
case 'failure': {
|
|
||||||
return css`
|
|
||||||
background-color: ${theme.tag.background.red};
|
|
||||||
color: ${theme.color.red};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
return css`
|
|
||||||
background-color: ${theme.background.tertiary};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
|
|
||||||
align-self: flex-start;
|
|
||||||
border-radius: ${({ theme }) =>
|
|
||||||
`${theme.border.radius.sm} ${theme.border.radius.sm} 0 0`};
|
|
||||||
margin-left: ${({ theme }) => theme.spacing(2)};
|
|
||||||
padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)};
|
|
||||||
|
|
||||||
.selectable:is(.selected, :focus, :focus-visible) & {
|
|
||||||
${({ nodeVariant, theme }) => {
|
|
||||||
switch (nodeVariant) {
|
|
||||||
case 'empty':
|
|
||||||
case 'default':
|
|
||||||
case 'not-executed':
|
|
||||||
return css`
|
|
||||||
background-color: ${theme.color.blue};
|
|
||||||
color: ${theme.font.color.inverted};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
`.withComponent(Label);
|
|
||||||
|
|
||||||
const StyledStepNodeInnerContainer = styled.div<{
|
|
||||||
variant: WorkflowDiagramNodeVariant;
|
|
||||||
}>`
|
|
||||||
background: ${({ theme }) => theme.background.secondary};
|
|
||||||
border-color: ${({ theme }) => theme.border.color.medium};
|
|
||||||
|
|
||||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
|
||||||
border-style: solid;
|
|
||||||
border-width: ${NODE_BORDER_WIDTH}px;
|
|
||||||
box-shadow: ${({ variant, theme }) =>
|
|
||||||
variant === 'empty' ? 'none' : theme.boxShadow.strong};
|
|
||||||
display: flex;
|
|
||||||
gap: ${({ theme }) => theme.spacing(2)};
|
|
||||||
padding: ${({ theme }) => theme.spacing(2)};
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
transition: background ${({ theme }) => theme.animation.duration.fast} ease;
|
|
||||||
|
|
||||||
.workflow-node-container:hover & {
|
|
||||||
${({ theme }) => {
|
|
||||||
return css`
|
|
||||||
background: linear-gradient(
|
|
||||||
0deg,
|
|
||||||
${theme.background.transparent.lighter} 0%,
|
|
||||||
${theme.background.transparent.lighter} 100%
|
|
||||||
),
|
|
||||||
${theme.background.secondary};
|
|
||||||
`;
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
.selectable:is(.selected, :focus, :focus-visible)
|
|
||||||
:is(.workflow-node-container, .workflow-node-container:hover)
|
|
||||||
& {
|
|
||||||
${({ theme, variant }) => {
|
|
||||||
switch (variant) {
|
|
||||||
case 'success': {
|
|
||||||
return css`
|
|
||||||
background: ${theme.adaptiveColors.turquoise1};
|
|
||||||
border-color: ${theme.adaptiveColors.turquoise4};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
case 'failure': {
|
|
||||||
return css`
|
|
||||||
background: ${theme.background.danger};
|
|
||||||
border-color: ${theme.color.red};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
return css`
|
|
||||||
background: ${theme.adaptiveColors.blue1};
|
|
||||||
border-color: ${theme.color.blue};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledStepNodeLabel = styled.div<{
|
|
||||||
variant: WorkflowDiagramNodeVariant;
|
|
||||||
}>`
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
|
||||||
column-gap: ${({ theme }) => theme.spacing(2)};
|
|
||||||
color: ${({ variant, theme }) => {
|
|
||||||
switch (variant) {
|
|
||||||
case 'empty':
|
|
||||||
case 'not-executed':
|
|
||||||
return theme.font.color.light;
|
|
||||||
default:
|
|
||||||
return theme.font.color.primary;
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
max-width: 200px;
|
|
||||||
|
|
||||||
.selectable:is(.selected, :focus, :focus-visible) & {
|
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const StyledHandle = styled(Handle)`
|
|
||||||
background-color: ${({ theme }) => theme.grayScale.gray25};
|
|
||||||
border: none;
|
|
||||||
width: ${NODE_HANDLE_WIDTH_PX}px;
|
|
||||||
height: ${NODE_HANDLE_HEIGHT_PX}px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledSourceHandle = styled(StyledHandle)`
|
|
||||||
background-color: ${({ theme }) => theme.border.color.strong};
|
|
||||||
left: ${NODE_ICON_WIDTH + NODE_ICON_LEFT_MARGIN + NODE_BORDER_WIDTH}px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledTargetHandle = styled(StyledSourceHandle)`
|
|
||||||
left: ${NODE_ICON_WIDTH + NODE_ICON_LEFT_MARGIN + NODE_BORDER_WIDTH}px;
|
|
||||||
visibility: hidden;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledRightFloatingElementContainer = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
position: absolute;
|
|
||||||
right: ${({ theme }) => theme.spacing(-4)};
|
|
||||||
bottom: 0;
|
|
||||||
top: 0;
|
|
||||||
transform: translateX(100%);
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const WorkflowDiagramBaseStepNode = ({
|
|
||||||
nodeType,
|
|
||||||
name,
|
|
||||||
variant,
|
|
||||||
Icon,
|
|
||||||
RightFloatingElement,
|
|
||||||
}: {
|
|
||||||
nodeType: WorkflowDiagramStepNodeData['nodeType'];
|
|
||||||
name: string;
|
|
||||||
variant: WorkflowDiagramNodeVariant;
|
|
||||||
Icon?: React.ReactNode;
|
|
||||||
RightFloatingElement?: React.ReactNode;
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<StyledStepNodeContainer className="workflow-node-container">
|
|
||||||
{nodeType !== 'trigger' ? (
|
|
||||||
<StyledTargetHandle type="target" position={Position.Top} />
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<StyledStepNodeType variant="small" nodeVariant={variant}>
|
|
||||||
{capitalize(nodeType)}
|
|
||||||
</StyledStepNodeType>
|
|
||||||
|
|
||||||
<StyledStepNodeInnerContainer variant={variant}>
|
|
||||||
<StyledStepNodeLabel variant={variant}>
|
|
||||||
{Icon}
|
|
||||||
|
|
||||||
<OverflowingTextWithTooltip text={name} />
|
|
||||||
</StyledStepNodeLabel>
|
|
||||||
|
|
||||||
{isDefined(RightFloatingElement) ? (
|
|
||||||
<StyledRightFloatingElementContainer>
|
|
||||||
{RightFloatingElement}
|
|
||||||
</StyledRightFloatingElementContainer>
|
|
||||||
) : null}
|
|
||||||
</StyledStepNodeInnerContainer>
|
|
||||||
|
|
||||||
<StyledSourceHandle type="source" position={Position.Bottom} />
|
|
||||||
</StyledStepNodeContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { StyledHandle } from '@/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode';
|
import { StyledHandle } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
|
||||||
import { NODE_BORDER_WIDTH } from '@/workflow/workflow-diagram/constants/NodeBorderWidth';
|
import { NODE_BORDER_WIDTH } from '@/workflow/workflow-diagram/constants/NodeBorderWidth';
|
||||||
import { NODE_ICON_LEFT_MARGIN } from '@/workflow/workflow-diagram/constants/NodeIconLeftMargin';
|
import { NODE_ICON_LEFT_MARGIN } from '@/workflow/workflow-diagram/constants/NodeIconLeftMargin';
|
||||||
import { NODE_ICON_WIDTH } from '@/workflow/workflow-diagram/constants/NodeIconWidth';
|
import { NODE_ICON_WIDTH } from '@/workflow/workflow-diagram/constants/NodeIconWidth';
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { WorkflowDiagramBaseStepNode } from '@/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode';
|
import { WorkflowDiagramStepNodeBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
const StyledStepNodeLabelIconContainer = styled.div`
|
const StyledStepNodeLabelIconContainer = styled.div`
|
||||||
@ -12,7 +12,7 @@ const StyledStepNodeLabelIconContainer = styled.div`
|
|||||||
|
|
||||||
export const WorkflowDiagramEmptyTrigger = () => {
|
export const WorkflowDiagramEmptyTrigger = () => {
|
||||||
return (
|
return (
|
||||||
<WorkflowDiagramBaseStepNode
|
<WorkflowDiagramStepNodeBase
|
||||||
name="Add a Trigger"
|
name="Add a Trigger"
|
||||||
nodeType="trigger"
|
nodeType="trigger"
|
||||||
variant="empty"
|
variant="empty"
|
||||||
|
|||||||
@ -1,105 +1,219 @@
|
|||||||
import { assertUnreachable } from '@/workflow/utils/assertUnreachable';
|
import { NODE_BORDER_WIDTH } from '@/workflow/workflow-diagram/constants/NodeBorderWidth';
|
||||||
import { WorkflowDiagramBaseStepNode } from '@/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode';
|
import { NODE_HANDLE_HEIGHT_PX } from '@/workflow/workflow-diagram/constants/NodeHandleHeightPx';
|
||||||
|
import { NODE_HANDLE_WIDTH_PX } from '@/workflow/workflow-diagram/constants/NodeHandleWidthPx';
|
||||||
|
import { NODE_ICON_LEFT_MARGIN } from '@/workflow/workflow-diagram/constants/NodeIconLeftMargin';
|
||||||
|
import { NODE_ICON_WIDTH } from '@/workflow/workflow-diagram/constants/NodeIconWidth';
|
||||||
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||||
import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
|
import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
|
||||||
import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey';
|
import { css } from '@emotion/react';
|
||||||
import { useTheme } from '@emotion/react';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useIcons } from 'twenty-ui';
|
import { Handle, Position } from '@xyflow/react';
|
||||||
|
import React from 'react';
|
||||||
|
import { capitalize, isDefined } from 'twenty-shared';
|
||||||
|
import { Label, OverflowingTextWithTooltip } from 'twenty-ui';
|
||||||
|
|
||||||
const StyledStepNodeLabelIconContainer = styled.div`
|
const StyledStepNodeContainer = styled.div`
|
||||||
align-items: center;
|
|
||||||
background: ${({ theme }) => theme.background.transparent.light};
|
|
||||||
border-radius: ${({ theme }) => theme.spacing(1)};
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
flex-direction: column;
|
||||||
padding: ${({ theme }) => theme.spacing(1)};
|
|
||||||
|
padding-block: ${({ theme }) => theme.spacing(3)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledStepNodeType = styled.div<{
|
||||||
|
nodeVariant: WorkflowDiagramNodeVariant;
|
||||||
|
}>`
|
||||||
|
${({ nodeVariant, theme }) => {
|
||||||
|
switch (nodeVariant) {
|
||||||
|
case 'success': {
|
||||||
|
return css`
|
||||||
|
background-color: ${theme.tag.background.turquoise};
|
||||||
|
color: ${theme.tag.text.turquoise};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
case 'failure': {
|
||||||
|
return css`
|
||||||
|
background-color: ${theme.tag.background.red};
|
||||||
|
color: ${theme.color.red};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return css`
|
||||||
|
background-color: ${theme.background.tertiary};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
align-self: flex-start;
|
||||||
|
border-radius: ${({ theme }) =>
|
||||||
|
`${theme.border.radius.sm} ${theme.border.radius.sm} 0 0`};
|
||||||
|
margin-left: ${({ theme }) => theme.spacing(2)};
|
||||||
|
padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)};
|
||||||
|
|
||||||
|
.selectable:is(.selected, :focus, :focus-visible) & {
|
||||||
|
${({ nodeVariant, theme }) => {
|
||||||
|
switch (nodeVariant) {
|
||||||
|
case 'empty':
|
||||||
|
case 'default':
|
||||||
|
case 'not-executed':
|
||||||
|
return css`
|
||||||
|
background-color: ${theme.color.blue};
|
||||||
|
color: ${theme.font.color.inverted};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
`.withComponent(Label);
|
||||||
|
|
||||||
|
const StyledStepNodeInnerContainer = styled.div<{
|
||||||
|
variant: WorkflowDiagramNodeVariant;
|
||||||
|
}>`
|
||||||
|
background: ${({ theme }) => theme.background.secondary};
|
||||||
|
border-color: ${({ theme }) => theme.border.color.medium};
|
||||||
|
|
||||||
|
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||||
|
border-style: solid;
|
||||||
|
border-width: ${NODE_BORDER_WIDTH}px;
|
||||||
|
box-shadow: ${({ variant, theme }) =>
|
||||||
|
variant === 'empty' ? 'none' : theme.boxShadow.strong};
|
||||||
|
display: flex;
|
||||||
|
gap: ${({ theme }) => theme.spacing(2)};
|
||||||
|
padding: ${({ theme }) => theme.spacing(2)};
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
transition: background ${({ theme }) => theme.animation.duration.fast} ease;
|
||||||
|
|
||||||
|
.workflow-node-container:hover & {
|
||||||
|
${({ theme }) => {
|
||||||
|
return css`
|
||||||
|
background: linear-gradient(
|
||||||
|
0deg,
|
||||||
|
${theme.background.transparent.lighter} 0%,
|
||||||
|
${theme.background.transparent.lighter} 100%
|
||||||
|
),
|
||||||
|
${theme.background.secondary};
|
||||||
|
`;
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectable:is(.selected, :focus, :focus-visible)
|
||||||
|
:is(.workflow-node-container, .workflow-node-container:hover)
|
||||||
|
& {
|
||||||
|
${({ theme, variant }) => {
|
||||||
|
switch (variant) {
|
||||||
|
case 'success': {
|
||||||
|
return css`
|
||||||
|
background: ${theme.adaptiveColors.turquoise1};
|
||||||
|
border-color: ${theme.adaptiveColors.turquoise4};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
case 'failure': {
|
||||||
|
return css`
|
||||||
|
background: ${theme.background.danger};
|
||||||
|
border-color: ${theme.color.red};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return css`
|
||||||
|
background: ${theme.adaptiveColors.blue1};
|
||||||
|
border-color: ${theme.color.blue};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledStepNodeLabel = styled.div<{
|
||||||
|
variant: WorkflowDiagramNodeVariant;
|
||||||
|
}>`
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
|
column-gap: ${({ theme }) => theme.spacing(2)};
|
||||||
|
color: ${({ variant, theme }) => {
|
||||||
|
switch (variant) {
|
||||||
|
case 'empty':
|
||||||
|
case 'not-executed':
|
||||||
|
return theme.font.color.light;
|
||||||
|
default:
|
||||||
|
return theme.font.color.primary;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
max-width: 200px;
|
||||||
|
|
||||||
|
.selectable:is(.selected, :focus, :focus-visible) & {
|
||||||
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const StyledHandle = styled(Handle)`
|
||||||
|
background-color: ${({ theme }) => theme.grayScale.gray25};
|
||||||
|
border: none;
|
||||||
|
width: ${NODE_HANDLE_WIDTH_PX}px;
|
||||||
|
height: ${NODE_HANDLE_HEIGHT_PX}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledSourceHandle = styled(StyledHandle)`
|
||||||
|
background-color: ${({ theme }) => theme.border.color.strong};
|
||||||
|
left: ${NODE_ICON_WIDTH + NODE_ICON_LEFT_MARGIN + NODE_BORDER_WIDTH}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledTargetHandle = styled(StyledSourceHandle)`
|
||||||
|
left: ${NODE_ICON_WIDTH + NODE_ICON_LEFT_MARGIN + NODE_BORDER_WIDTH}px;
|
||||||
|
visibility: hidden;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledRightFloatingElementContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
right: ${({ theme }) => theme.spacing(-4)};
|
||||||
|
bottom: 0;
|
||||||
|
top: 0;
|
||||||
|
transform: translateX(100%);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const WorkflowDiagramStepNodeBase = ({
|
export const WorkflowDiagramStepNodeBase = ({
|
||||||
data,
|
nodeType,
|
||||||
|
name,
|
||||||
variant,
|
variant,
|
||||||
|
Icon,
|
||||||
RightFloatingElement,
|
RightFloatingElement,
|
||||||
}: {
|
}: {
|
||||||
data: WorkflowDiagramStepNodeData;
|
nodeType: WorkflowDiagramStepNodeData['nodeType'];
|
||||||
|
name: string;
|
||||||
variant: WorkflowDiagramNodeVariant;
|
variant: WorkflowDiagramNodeVariant;
|
||||||
|
Icon?: React.ReactNode;
|
||||||
RightFloatingElement?: React.ReactNode;
|
RightFloatingElement?: React.ReactNode;
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
|
||||||
const { getIcon } = useIcons();
|
|
||||||
const Icon = getIcon(getWorkflowNodeIconKey(data));
|
|
||||||
|
|
||||||
const renderStepIcon = () => {
|
|
||||||
switch (data.nodeType) {
|
|
||||||
case 'trigger': {
|
|
||||||
switch (data.triggerType) {
|
|
||||||
case 'DATABASE_EVENT': {
|
|
||||||
return (
|
|
||||||
<StyledStepNodeLabelIconContainer>
|
|
||||||
<Icon
|
|
||||||
size={theme.icon.size.md}
|
|
||||||
color={theme.font.color.tertiary}
|
|
||||||
/>
|
|
||||||
</StyledStepNodeLabelIconContainer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case 'MANUAL': {
|
|
||||||
return (
|
|
||||||
<StyledStepNodeLabelIconContainer>
|
|
||||||
<Icon
|
|
||||||
size={theme.icon.size.md}
|
|
||||||
color={theme.font.color.tertiary}
|
|
||||||
/>
|
|
||||||
</StyledStepNodeLabelIconContainer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return assertUnreachable(data.triggerType);
|
|
||||||
}
|
|
||||||
case 'action': {
|
|
||||||
switch (data.actionType) {
|
|
||||||
case 'CODE': {
|
|
||||||
return (
|
|
||||||
<StyledStepNodeLabelIconContainer>
|
|
||||||
<Icon
|
|
||||||
size={theme.icon.size.md}
|
|
||||||
color={theme.color.orange}
|
|
||||||
stroke={theme.icon.stroke.sm}
|
|
||||||
/>
|
|
||||||
</StyledStepNodeLabelIconContainer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case 'SEND_EMAIL': {
|
|
||||||
return (
|
|
||||||
<StyledStepNodeLabelIconContainer>
|
|
||||||
<Icon size={theme.icon.size.md} color={theme.color.blue} />
|
|
||||||
</StyledStepNodeLabelIconContainer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
return (
|
|
||||||
<StyledStepNodeLabelIconContainer>
|
|
||||||
<Icon
|
|
||||||
size={theme.icon.size.md}
|
|
||||||
color={theme.font.color.tertiary}
|
|
||||||
stroke={theme.icon.stroke.sm}
|
|
||||||
/>
|
|
||||||
</StyledStepNodeLabelIconContainer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WorkflowDiagramBaseStepNode
|
<StyledStepNodeContainer className="workflow-node-container">
|
||||||
name={data.name}
|
{nodeType !== 'trigger' ? (
|
||||||
variant={variant}
|
<StyledTargetHandle type="target" position={Position.Top} />
|
||||||
nodeType={data.nodeType}
|
) : null}
|
||||||
Icon={renderStepIcon()}
|
|
||||||
RightFloatingElement={RightFloatingElement}
|
<StyledStepNodeType variant="small" nodeVariant={variant}>
|
||||||
/>
|
{capitalize(nodeType)}
|
||||||
|
</StyledStepNodeType>
|
||||||
|
|
||||||
|
<StyledStepNodeInnerContainer variant={variant}>
|
||||||
|
<StyledStepNodeLabel variant={variant}>
|
||||||
|
{Icon}
|
||||||
|
|
||||||
|
<OverflowingTextWithTooltip text={name} />
|
||||||
|
</StyledStepNodeLabel>
|
||||||
|
|
||||||
|
{isDefined(RightFloatingElement) ? (
|
||||||
|
<StyledRightFloatingElementContainer>
|
||||||
|
{RightFloatingElement}
|
||||||
|
</StyledRightFloatingElementContainer>
|
||||||
|
) : null}
|
||||||
|
</StyledStepNodeInnerContainer>
|
||||||
|
|
||||||
|
<StyledSourceHandle type="source" position={Position.Bottom} />
|
||||||
|
</StyledStepNodeContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { WorkflowDiagramStepNodeBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
|
import { WorkflowDiagramStepNodeBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
|
||||||
|
import { WorkflowDiagramStepNodeIcon } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeIcon';
|
||||||
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||||
import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
|
import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
|
||||||
import { FloatingIconButton, IconTrash } from 'twenty-ui';
|
import { FloatingIconButton, IconTrash } from 'twenty-ui';
|
||||||
@ -16,8 +17,10 @@ export const WorkflowDiagramStepNodeEditableContent = ({
|
|||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<WorkflowDiagramStepNodeBase
|
<WorkflowDiagramStepNodeBase
|
||||||
data={data}
|
name={data.name}
|
||||||
variant={variant}
|
variant={variant}
|
||||||
|
nodeType={data.nodeType}
|
||||||
|
Icon={<WorkflowDiagramStepNodeIcon data={data} />}
|
||||||
RightFloatingElement={
|
RightFloatingElement={
|
||||||
selected ? (
|
selected ? (
|
||||||
<FloatingIconButton
|
<FloatingIconButton
|
||||||
|
|||||||
@ -0,0 +1,87 @@
|
|||||||
|
import { assertUnreachable } from '@/workflow/utils/assertUnreachable';
|
||||||
|
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||||
|
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;
|
||||||
|
background: ${({ theme }) => theme.background.transparent.light};
|
||||||
|
border-radius: ${({ theme }) => theme.spacing(1)};
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: ${({ theme }) => theme.spacing(1)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const WorkflowDiagramStepNodeIcon = ({
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
data: WorkflowDiagramStepNodeData;
|
||||||
|
}) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const { getIcon } = useIcons();
|
||||||
|
const Icon = getIcon(getWorkflowNodeIconKey(data));
|
||||||
|
|
||||||
|
switch (data.nodeType) {
|
||||||
|
case 'trigger': {
|
||||||
|
switch (data.triggerType) {
|
||||||
|
case 'DATABASE_EVENT': {
|
||||||
|
return (
|
||||||
|
<StyledStepNodeLabelIconContainer>
|
||||||
|
<Icon
|
||||||
|
size={theme.icon.size.md}
|
||||||
|
color={theme.font.color.tertiary}
|
||||||
|
/>
|
||||||
|
</StyledStepNodeLabelIconContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case 'MANUAL': {
|
||||||
|
return (
|
||||||
|
<StyledStepNodeLabelIconContainer>
|
||||||
|
<Icon
|
||||||
|
size={theme.icon.size.md}
|
||||||
|
color={theme.font.color.tertiary}
|
||||||
|
/>
|
||||||
|
</StyledStepNodeLabelIconContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return assertUnreachable(data.triggerType);
|
||||||
|
}
|
||||||
|
case 'action': {
|
||||||
|
switch (data.actionType) {
|
||||||
|
case 'CODE': {
|
||||||
|
return (
|
||||||
|
<StyledStepNodeLabelIconContainer>
|
||||||
|
<Icon
|
||||||
|
size={theme.icon.size.md}
|
||||||
|
color={theme.color.orange}
|
||||||
|
stroke={theme.icon.stroke.sm}
|
||||||
|
/>
|
||||||
|
</StyledStepNodeLabelIconContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case 'SEND_EMAIL': {
|
||||||
|
return (
|
||||||
|
<StyledStepNodeLabelIconContainer>
|
||||||
|
<Icon size={theme.icon.size.md} color={theme.color.blue} />
|
||||||
|
</StyledStepNodeLabelIconContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return (
|
||||||
|
<StyledStepNodeLabelIconContainer>
|
||||||
|
<Icon
|
||||||
|
size={theme.icon.size.md}
|
||||||
|
color={theme.font.color.tertiary}
|
||||||
|
stroke={theme.icon.stroke.sm}
|
||||||
|
/>
|
||||||
|
</StyledStepNodeLabelIconContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import { WorkflowDiagramStepNodeBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
|
import { WorkflowDiagramStepNodeBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
|
||||||
|
import { WorkflowDiagramStepNodeIcon } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeIcon';
|
||||||
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||||
|
|
||||||
export const WorkflowDiagramStepNodeReadonly = ({
|
export const WorkflowDiagramStepNodeReadonly = ({
|
||||||
@ -6,5 +7,12 @@ export const WorkflowDiagramStepNodeReadonly = ({
|
|||||||
}: {
|
}: {
|
||||||
data: WorkflowDiagramStepNodeData;
|
data: WorkflowDiagramStepNodeData;
|
||||||
}) => {
|
}) => {
|
||||||
return <WorkflowDiagramStepNodeBase variant="default" data={data} />;
|
return (
|
||||||
|
<WorkflowDiagramStepNodeBase
|
||||||
|
name={data.name}
|
||||||
|
variant="default"
|
||||||
|
nodeType={data.nodeType}
|
||||||
|
Icon={<WorkflowDiagramStepNodeIcon data={data} />}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user