Skip to content

Commit a7d94de

Browse files
author
Roman Snapko
committed
Add visual indicator for sensitive actions
1 parent e9b82a8 commit a7d94de

2 files changed

Lines changed: 73 additions & 26 deletions

File tree

  • packages/react-ui/src/app/features

packages/react-ui/src/app/features/builder/flow-canvas/nodes/step-node.tsx

Lines changed: 72 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,12 @@ import {
3232
FlowRunStatus,
3333
FlowVersion,
3434
isNil,
35+
RiskLevel,
3536
TriggerType,
3637
} from '@openops/shared';
3738

39+
import { getActionMetadata } from '@/app/features/flows/components/execute-risky-flow-dialog/utils';
40+
import { ShieldHalf } from 'lucide-react';
3841
import { CanvasContextMenu } from '../context-menu/canvas-context-menu';
3942
import { CollapsibleButton } from './collapsible-button';
4043
import { StackedNodeLayers } from './stacked-node-layer';
@@ -86,6 +89,11 @@ const WorkflowStepNode = React.memo(
8689
step: data.step!,
8790
});
8891

92+
const { metadata: actionsMetadata } = blocksHooks.useAllStepsMetadata({
93+
searchQuery: '',
94+
type: 'action',
95+
});
96+
8997
const stepIndex = useMemo(() => {
9098
const steps = flowHelper.getAllSteps(flowVersion.trigger);
9199
return steps.findIndex((step) => step.name === data.step!.name) + 1;
@@ -122,6 +130,27 @@ const WorkflowStepNode = React.memo(
122130
return getStepStatus(data.step?.name, run, loopIndexes, flowVersion);
123131
}, [data.step?.name, run, loopIndexes, flowVersion]);
124132

133+
const isRiskyStep = useMemo(() => {
134+
const actionName = data.step?.settings.actionName;
135+
const blockName = data.step?.settings.blockName;
136+
137+
if (!actionsMetadata || !actionName || !blockName) {
138+
return false;
139+
}
140+
141+
const actionMetadata = getActionMetadata(
142+
actionsMetadata,
143+
data.step?.settings.blockName,
144+
data.step?.settings.actionName,
145+
);
146+
147+
return actionMetadata?.riskLevel === RiskLevel.HIGH;
148+
}, [
149+
actionsMetadata,
150+
data.step?.settings.actionName,
151+
data.step?.settings.blockName,
152+
]);
153+
125154
const showRunningIcon =
126155
isNil(stepOutputStatus) && run?.status === FlowRunStatus.RUNNING;
127156
const statusInfo = isNil(stepOutputStatus)
@@ -247,15 +276,49 @@ const WorkflowStepNode = React.memo(
247276
</div>
248277
</div>
249278

250-
{!readonly && (
251-
<CanvasContextMenu
252-
data={data}
253-
isAction={isAction}
254-
openStepActionsMenu={openStepActionsMenu}
255-
setOpenStepActionsMenu={setOpenStepActionsMenu}
256-
setOpenBlockSelector={setOpenBlockSelector}
257-
/>
258-
)}
279+
<div className="flex items-center gap-0.5">
280+
<div className="flex items-center gap-[7px]">
281+
{!data.step?.valid && (
282+
<Tooltip>
283+
<TooltipTrigger asChild>
284+
<InvalidStepIcon
285+
size={16}
286+
viewBox="0 0 16 16"
287+
className="stroke-0 animate-fade"
288+
></InvalidStepIcon>
289+
</TooltipTrigger>
290+
<TooltipContent side="bottom">
291+
{t('Incomplete settings')}
292+
</TooltipContent>
293+
</Tooltip>
294+
)}
295+
296+
{isRiskyStep && (
297+
<Tooltip>
298+
<TooltipTrigger asChild>
299+
<div className="size-4 flex items-center justify-center rounded-full bg-destructive-100">
300+
<ShieldHalf className="size-[10px] text-destructive-300"></ShieldHalf>
301+
</div>
302+
</TooltipTrigger>
303+
<TooltipContent side="bottom">
304+
{t(
305+
'This step may make changes to your environment',
306+
)}
307+
</TooltipContent>
308+
</Tooltip>
309+
)}
310+
</div>
311+
312+
{!readonly && (
313+
<CanvasContextMenu
314+
data={data}
315+
isAction={isAction}
316+
openStepActionsMenu={openStepActionsMenu}
317+
setOpenStepActionsMenu={setOpenStepActionsMenu}
318+
setOpenBlockSelector={setOpenBlockSelector}
319+
/>
320+
)}
321+
</div>
259322
</div>
260323

261324
<div className="flex justify-between gap-[6px] w-full items-center">
@@ -276,22 +339,6 @@ const WorkflowStepNode = React.memo(
276339
{showRunningIcon && (
277340
<LoadingSpinner className="w-4 h-4 text-primary"></LoadingSpinner>
278341
)}
279-
{!data.step?.valid && (
280-
<Tooltip>
281-
<TooltipTrigger asChild>
282-
<div className="mr-2">
283-
<InvalidStepIcon
284-
size={16}
285-
viewBox="0 0 16 16"
286-
className="stroke-0 animate-fade"
287-
></InvalidStepIcon>
288-
</div>
289-
</TooltipTrigger>
290-
<TooltipContent side="bottom">
291-
{t('Incomplete settings')}
292-
</TooltipContent>
293-
</Tooltip>
294-
)}
295342
</div>
296343
</div>
297344
</div>

packages/react-ui/src/app/features/flows/components/execute-risky-flow-dialog/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { Action, ActionType, RiskLevel, Trigger } from '@openops/shared';
77

88
type ActionOrTriggerWithIndex = (Action | Trigger) & { index: number };
99

10-
const getActionMetadata = (
10+
export const getActionMetadata = (
1111
metadata: StepMetadataWithSuggestions[] | undefined,
1212
blockName: string,
1313
actionName: string | undefined,

0 commit comments

Comments
 (0)