Add design for selected filter (#13498)
On select, filter design should be updated as it is for other nodes <img width="106" height="70" alt="Capture d’écran 2025-07-30 à 12 12 09" src="https://github.com/user-attachments/assets/66aa7838-2fb3-4593-af32-a9b361eb3225" /> <img width="106" height="70" alt="Capture d’écran 2025-07-30 à 12 12 25" src="https://github.com/user-attachments/assets/5627427b-4c36-4592-b5bb-e5d87d59232d" />
This commit is contained in:
+5
@@ -10,6 +10,7 @@ import { useRightDrawerState } from '@/workflow/workflow-diagram/hooks/useRightD
|
||||
import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState';
|
||||
import { workflowDiagramPanOnDragComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramPanOnDragComponentState';
|
||||
import { workflowDiagramWaitingNodesDimensionsComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramWaitingNodesDimensionsComponentState';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import {
|
||||
WorkflowDiagram,
|
||||
WorkflowDiagramEdge,
|
||||
@@ -145,6 +146,9 @@ export const WorkflowDiagramCanvasBase = ({
|
||||
const setWorkflowInsertStepIds = useSetRecoilComponentStateV2(
|
||||
workflowInsertStepIdsComponentState,
|
||||
);
|
||||
const setWorkflowSelectedNode = useSetRecoilComponentStateV2(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
const workflowDiagramWaitingNodesDimensionsState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
workflowDiagramWaitingNodesDimensionsComponentState,
|
||||
@@ -192,6 +196,7 @@ export const WorkflowDiagramCanvasBase = ({
|
||||
parentStepId: undefined,
|
||||
nextStepId: undefined,
|
||||
});
|
||||
setWorkflowSelectedNode(undefined);
|
||||
});
|
||||
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
+28
-8
@@ -16,13 +16,15 @@ import { WORKFLOW_DIAGRAM_EDGE_OPTIONS_CLICK_OUTSIDE_ID } from '@/workflow/workf
|
||||
import { useOpenWorkflowEditFilterInCommandMenu } from '@/workflow/workflow-diagram/hooks/useOpenWorkflowEditFilterInCommandMenu';
|
||||
import { useStartNodeCreation } from '@/workflow/workflow-diagram/hooks/useStartNodeCreation';
|
||||
import { workflowDiagramPanOnDragComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramPanOnDragComponentState';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import {
|
||||
WorkflowDiagramEdge,
|
||||
WorkflowDiagramEdgeData,
|
||||
} from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { getWorkflowDiagramNodeSelectedColors } from '@/workflow/workflow-diagram/utils/getWorkflowDiagramNodeSelectedColors';
|
||||
import { useDeleteStep } from '@/workflow/workflow-steps/hooks/useDeleteStep';
|
||||
import { workflowInsertStepIdsComponentState } from '@/workflow/workflow-steps/states/workflowInsertStepIdsComponentState';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import {
|
||||
@@ -54,8 +56,17 @@ const assertFilterEdgeDataOrThrow: (
|
||||
}
|
||||
};
|
||||
|
||||
const StyledIconButtonGroup = styled(IconButtonGroup)`
|
||||
const StyledIconButtonGroup = styled(IconButtonGroup)<{ selected?: boolean }>`
|
||||
pointer-events: all;
|
||||
|
||||
${({ selected, theme }) => {
|
||||
if (!selected) return '';
|
||||
const colors = getWorkflowDiagramNodeSelectedColors('default', theme);
|
||||
return css`
|
||||
background-color: ${colors.background};
|
||||
border: 1px solid ${colors.borderColor};
|
||||
`;
|
||||
}}
|
||||
`;
|
||||
|
||||
const StyledConfiguredFilterContainer = styled.div`
|
||||
@@ -104,11 +115,18 @@ export const WorkflowDiagramFilterEdgeEditable = ({
|
||||
workflowInsertStepIdsComponentState,
|
||||
);
|
||||
|
||||
const isSelected =
|
||||
workflowInsertStepIds.nextStepId === source &&
|
||||
(workflowInsertStepIds.parentStepId === target ||
|
||||
(isNonEmptyString(data.stepId) &&
|
||||
workflowInsertStepIds.parentStepId === data.stepId));
|
||||
const isEdgeSelected =
|
||||
(workflowInsertStepIds.nextStepId === source &&
|
||||
workflowInsertStepIds.parentStepId === target) ||
|
||||
(isNonEmptyString(data.stepId) &&
|
||||
workflowInsertStepIds.parentStepId === data.stepId);
|
||||
|
||||
const workflowSelectedNode = useRecoilComponentValueV2(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
|
||||
const isFilterNodeSelected =
|
||||
isNonEmptyString(data.stepId) && workflowSelectedNode === data.stepId;
|
||||
|
||||
const dropdownId = `${WORKFLOW_DIAGRAM_EDGE_OPTIONS_CLICK_OUTSIDE_ID}-${source}-${target}`;
|
||||
|
||||
@@ -154,7 +172,7 @@ export const WorkflowDiagramFilterEdgeEditable = ({
|
||||
>
|
||||
<WorkflowDiagramEdgeV2VisibilityContainer shouldDisplay>
|
||||
<StyledConfiguredFilterContainer>
|
||||
{hovered || isDropdownOpen || isSelected ? (
|
||||
{hovered || isDropdownOpen || isEdgeSelected ? (
|
||||
<StyledIconButtonGroup
|
||||
className="nodrag nopan"
|
||||
iconButtons={[
|
||||
@@ -171,6 +189,7 @@ export const WorkflowDiagramFilterEdgeEditable = ({
|
||||
},
|
||||
},
|
||||
]}
|
||||
selected={isFilterNodeSelected}
|
||||
/>
|
||||
) : (
|
||||
<StyledIconButtonGroup
|
||||
@@ -181,6 +200,7 @@ export const WorkflowDiagramFilterEdgeEditable = ({
|
||||
onClick: handleFilterButtonClick,
|
||||
},
|
||||
]}
|
||||
selected={isFilterNodeSelected}
|
||||
/>
|
||||
)}
|
||||
</StyledConfiguredFilterContainer>
|
||||
|
||||
+23
-2
@@ -1,14 +1,18 @@
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { WorkflowDiagramEdgeV2Container } from '@/workflow/workflow-diagram/components/WorkflowDiagramEdgeV2Container';
|
||||
import { WorkflowDiagramEdgeV2VisibilityContainer } from '@/workflow/workflow-diagram/components/WorkflowDiagramEdgeV2VisibilityContainer';
|
||||
import { CREATE_STEP_NODE_WIDTH } from '@/workflow/workflow-diagram/constants/CreateStepNodeWidth';
|
||||
import { WORKFLOW_DIAGRAM_EDGE_OPTIONS_CLICK_OUTSIDE_ID } from '@/workflow/workflow-diagram/constants/WorkflowDiagramEdgeOptionsClickOutsideId';
|
||||
import { useOpenWorkflowViewFilterInCommandMenu } from '@/workflow/workflow-diagram/hooks/useOpenWorkflowViewFilterInCommandMenu';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import {
|
||||
WorkflowDiagramEdge,
|
||||
WorkflowDiagramEdgeData,
|
||||
} from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { getWorkflowDiagramNodeSelectedColors } from '@/workflow/workflow-diagram/utils/getWorkflowDiagramNodeSelectedColors';
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import {
|
||||
BaseEdge,
|
||||
EdgeLabelRenderer,
|
||||
@@ -30,8 +34,17 @@ const assertFilterEdgeDataOrThrow: (
|
||||
}
|
||||
};
|
||||
|
||||
const StyledIconButtonGroup = styled(IconButtonGroup)`
|
||||
const StyledIconButtonGroup = styled(IconButtonGroup)<{ selected?: boolean }>`
|
||||
pointer-events: all;
|
||||
|
||||
${({ selected, theme }) => {
|
||||
if (!selected) return '';
|
||||
const colors = getWorkflowDiagramNodeSelectedColors('default', theme);
|
||||
return css`
|
||||
background-color: ${colors.background};
|
||||
border: 1px solid ${colors.borderColor};
|
||||
`;
|
||||
}}
|
||||
`;
|
||||
|
||||
const StyledConfiguredFilterContainer = styled.div`
|
||||
@@ -57,6 +70,13 @@ export const WorkflowDiagramFilterEdgeReadonly = ({
|
||||
targetY,
|
||||
});
|
||||
|
||||
const workflowSelectedNode = useRecoilComponentValueV2(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
|
||||
const isFilterNodeSelected =
|
||||
isNonEmptyString(data.stepId) && workflowSelectedNode === data.stepId;
|
||||
|
||||
const { openWorkflowViewFilterInCommandMenu } =
|
||||
useOpenWorkflowViewFilterInCommandMenu();
|
||||
|
||||
@@ -92,6 +112,7 @@ export const WorkflowDiagramFilterEdgeReadonly = ({
|
||||
onClick: handleFilterButtonClick,
|
||||
},
|
||||
]}
|
||||
selected={isFilterNodeSelected}
|
||||
/>
|
||||
</StyledConfiguredFilterContainer>
|
||||
</WorkflowDiagramEdgeV2VisibilityContainer>
|
||||
|
||||
+29
-1
@@ -1,14 +1,21 @@
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { WorkflowDiagramEdgeV2Container } from '@/workflow/workflow-diagram/components/WorkflowDiagramEdgeV2Container';
|
||||
import { WorkflowDiagramEdgeV2VisibilityContainer } from '@/workflow/workflow-diagram/components/WorkflowDiagramEdgeV2VisibilityContainer';
|
||||
import { WorkflowRunDiagramBaseEdge } from '@/workflow/workflow-diagram/components/WorkflowRunDiagramBaseEdge';
|
||||
import { CREATE_STEP_NODE_WIDTH } from '@/workflow/workflow-diagram/constants/CreateStepNodeWidth';
|
||||
import { WORKFLOW_DIAGRAM_EDGE_OPTIONS_CLICK_OUTSIDE_ID } from '@/workflow/workflow-diagram/constants/WorkflowDiagramEdgeOptionsClickOutsideId';
|
||||
import { useOpenWorkflowRunFilterInCommandMenu } from '@/workflow/workflow-diagram/hooks/useOpenWorkflowRunFilterInCommandMenu';
|
||||
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
|
||||
import {
|
||||
WorkflowDiagramEdge,
|
||||
WorkflowDiagramEdgeData,
|
||||
} from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
|
||||
import { getNodeVariantFromStepRunStatus } from '@/workflow/workflow-diagram/utils/getNodeVariantFromStepRunStatus';
|
||||
import { getWorkflowDiagramNodeSelectedColors } from '@/workflow/workflow-diagram/utils/getWorkflowDiagramNodeSelectedColors';
|
||||
import { css } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { EdgeLabelRenderer, EdgeProps, getStraightPath } from '@xyflow/react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconFilter } from 'twenty-ui/display';
|
||||
@@ -26,8 +33,20 @@ const assertFilterEdgeDataOrThrow: (
|
||||
}
|
||||
};
|
||||
|
||||
const StyledIconButtonGroup = styled(IconButtonGroup)`
|
||||
const StyledIconButtonGroup = styled(IconButtonGroup)<{
|
||||
selected?: boolean;
|
||||
variant: WorkflowDiagramNodeVariant;
|
||||
}>`
|
||||
pointer-events: all;
|
||||
|
||||
${({ selected, variant, theme }) => {
|
||||
if (!selected) return '';
|
||||
const colors = getWorkflowDiagramNodeSelectedColors(variant, theme);
|
||||
return css`
|
||||
background-color: ${colors.background};
|
||||
border: 1px solid ${colors.borderColor};
|
||||
`;
|
||||
}}
|
||||
`;
|
||||
|
||||
const StyledConfiguredFilterContainer = styled.div`
|
||||
@@ -49,6 +68,13 @@ export const WorkflowDiagramFilterEdgeRun = ({
|
||||
targetY,
|
||||
});
|
||||
|
||||
const workflowSelectedNode = useRecoilComponentValueV2(
|
||||
workflowSelectedNodeComponentState,
|
||||
);
|
||||
|
||||
const isFilterNodeSelected =
|
||||
isNonEmptyString(data.stepId) && workflowSelectedNode === data.stepId;
|
||||
|
||||
const { openWorkflowRunFilterInCommandMenu } =
|
||||
useOpenWorkflowRunFilterInCommandMenu();
|
||||
|
||||
@@ -87,6 +113,8 @@ export const WorkflowDiagramFilterEdgeRun = ({
|
||||
onClick: handleFilterButtonClick,
|
||||
},
|
||||
]}
|
||||
selected={isFilterNodeSelected}
|
||||
variant={getNodeVariantFromStepRunStatus(data.runStatus)}
|
||||
/>
|
||||
</StyledConfiguredFilterContainer>
|
||||
</WorkflowDiagramEdgeV2VisibilityContainer>
|
||||
|
||||
+6
-26
@@ -3,6 +3,7 @@ import { NODE_BORDER_WIDTH } from '@/workflow/workflow-diagram/constants/NodeBor
|
||||
import { WORKFLOW_DIAGRAM_STEP_NODE_BASE_CLICK_OUTSIDE_ID } from '@/workflow/workflow-diagram/constants/WorkflowDiagramStepNodeClickOutsideId';
|
||||
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
|
||||
import { getWorkflowDiagramNodeSelectedColors } from '@/workflow/workflow-diagram/utils/getWorkflowDiagramNodeSelectedColors';
|
||||
import { css } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Position } from '@xyflow/react';
|
||||
@@ -106,32 +107,11 @@ const StyledStepNodeInnerContainer = styled.div<{
|
||||
:is(.workflow-node-container, .workflow-node-container:hover)
|
||||
& {
|
||||
${({ theme, variant }) => {
|
||||
switch (variant) {
|
||||
case 'running': {
|
||||
return css`
|
||||
background: ${theme.adaptiveColors.yellow1};
|
||||
border-color: ${theme.adaptiveColors.yellow4};
|
||||
`;
|
||||
}
|
||||
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 colors = getWorkflowDiagramNodeSelectedColors(variant, theme);
|
||||
return css`
|
||||
background: ${colors.background};
|
||||
border-color: ${colors.borderColor};
|
||||
`;
|
||||
}}
|
||||
}
|
||||
`;
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ export const useOpenWorkflowEditFilterInCommandMenu = () => {
|
||||
...diagram,
|
||||
nodes: diagram.nodes.map((node) => ({
|
||||
...node,
|
||||
selected: false,
|
||||
selected: node.id === stepId,
|
||||
})),
|
||||
};
|
||||
});
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
|
||||
import { Theme } from '@emotion/react';
|
||||
|
||||
export type WorkflowDiagramNodeSelectedColors = {
|
||||
background: string;
|
||||
borderColor: string;
|
||||
};
|
||||
|
||||
export const getWorkflowDiagramNodeSelectedColors = (
|
||||
variant: WorkflowDiagramNodeVariant,
|
||||
theme: Theme,
|
||||
): WorkflowDiagramNodeSelectedColors => {
|
||||
switch (variant) {
|
||||
case 'running': {
|
||||
return {
|
||||
background: theme.adaptiveColors.yellow1,
|
||||
borderColor: theme.adaptiveColors.yellow4,
|
||||
};
|
||||
}
|
||||
case 'success': {
|
||||
return {
|
||||
background: theme.adaptiveColors.turquoise1,
|
||||
borderColor: theme.adaptiveColors.turquoise4,
|
||||
};
|
||||
}
|
||||
case 'failure': {
|
||||
return {
|
||||
background: theme.background.danger,
|
||||
borderColor: theme.color.red,
|
||||
};
|
||||
}
|
||||
default: {
|
||||
return {
|
||||
background: theme.adaptiveColors.blue1,
|
||||
borderColor: theme.color.blue,
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user