Skip to content

Commit

Permalink
feat: show warning in frontend for particular action node if a previo…
Browse files Browse the repository at this point in the history
…usly selected secret is not available anymore
  • Loading branch information
leon-schmid committed Oct 28, 2024
1 parent 39f66a1 commit 39c13cd
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ function buildInitialArgs(

export default function ActionEditPanel() {
const router = useRouter();
const { nodes, selectedNodeIdx, updateNodeData } = useWorkflowStore();
const {
nodes,
selectedNodeIdx,
updateNodeData,
getMissingSecretByIdx,
deleteMissingSecretByIdx,
} = useWorkflowStore();
const { actionsIndex } = useEditorActionStore();
const { secrets } = useSecretsStore();
const { saveWorkflow } = useSaveWorkflow();
Expand Down Expand Up @@ -83,6 +89,10 @@ export default function ActionEditPanel() {
draft.secretsMapping[secretPlaceholder] = value;
}),
);

if (getMissingSecretByIdx(selectedNodeIdx) !== "") {
deleteMissingSecretByIdx(selectedNodeIdx);
}
};

const onChangeActionArgument = (
Expand Down Expand Up @@ -193,6 +203,22 @@ export default function ActionEditPanel() {
</Select.Group>
</Select.Content>
</Select.Root>
{getMissingSecretByIdx(selectedNodeIdx) !==
"" && (
<Flex
direction="row"
align="center"
className="text-red-500 font-medium mt-2"
>
<Text>
The previously selected secret "
{getMissingSecretByIdx(
selectedNodeIdx,
)}
" is not available anymore.
</Text>
</Flex>
)}
</Flex>
),
)}
Expand Down
23 changes: 22 additions & 1 deletion web/src/components/workflow-editor/workflow-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ export default function WorkflowEditor({

const [view, setView] = useState<View>("workflowBuilder");

const { isNew, setWorkflow, clearWorkflowStore } = useWorkflowStore();
const { isNew, setWorkflow, clearWorkflowStore, addMissingSecretByIdx } =
useWorkflowStore();
const { setEditorActions } = useEditorActionStore();
const { errorToast } = useToast();
const { setSecrets, clear } = useSecretsStore();
Expand Down Expand Up @@ -109,6 +110,26 @@ export default function WorkflowEditor({
router,
]);

useEffect(() => {
if (!workflow || !encryptedSecrets) {
return;
}
workflow.nodes.forEach((node, nodeIdx) => {
console.log("node", node);
if (node.type === "action") {
const secretName = Object.values(node.secretsMapping)[0];
if (
secretName &&
!encryptedSecrets.find((s) => s.secretId === secretName)
) {
addMissingSecretByIdx(secretName, nodeIdx);
return;
}
}
addMissingSecretByIdx("", nodeIdx);
});
}, [encryptedSecrets, workflow]);

// TODO(frontend): nicer loading screen
if (isLoadingEditorActions || (!isNew && isLoadingWorkflow)) {
return <Box>Loading...</Box>;
Expand Down
28 changes: 26 additions & 2 deletions web/src/components/workflow-graph/node-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { NodeToolbar, Position } from "reactflow";
import * as Toolbar from "@radix-ui/react-toolbar";
import DuplicateIcon from "../icons/duplicate-icon";
import { useWorkflowStore } from "@/stores/workflow-store";
import { TrashIcon } from "@radix-ui/react-icons";
import { TrashIcon, ExclamationTriangleIcon } from "@radix-ui/react-icons";

export interface NodeBaseProps {
nodeId: string;
Expand All @@ -20,13 +20,20 @@ export default function NodeBase({
name,
selected,
}: NodeBaseProps) {
const { nodes, duplicateNodeByIdx, deleteNodeByIdx } = useWorkflowStore();
const {
nodes,
duplicateNodeByIdx,
deleteNodeByIdx,
getMissingSecretByIdx,
} = useWorkflowStore();

const nodeIdx = nodes.findIndex((node) => node.id === nodeId);
if (nodeIdx === -1) {
return null;
}

const hasMissingSecret = getMissingSecretByIdx(nodeIdx) !== "";

const cardStyle = selected
? {
boxShadow: "0px 4px 12px 0px rgba(62, 99, 221, 0.20)",
Expand Down Expand Up @@ -59,6 +66,23 @@ export default function NodeBase({
{type}
</Text>
</Flex>
{hasMissingSecret && (
<Flex
className="absolute top-2 right-2"
justify="end"
align="start"
>
<Tooltip content="Missing secret">
<Flex
className="bg-red-500 rounded-full w-6 h-6"
justify="center"
align="center"
>
<ExclamationTriangleIcon className="text-white w-4 h-4" />
</Flex>
</Tooltip>
</Flex>
)}
</Flex>
</Card>

Expand Down
20 changes: 20 additions & 0 deletions web/src/stores/workflow-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ type WorkflowStoreState = TReactFlowGraph & {
webhookSecret: string | null;
lastDeletedEdges: TReactFlowEdge[];
payloadCache: string;
missingSecretForNodes: string[];
// Operations
clearWorkflowStore: () => void;
initWorkflow: (workflowId: string, windowInnerWidth: number) => void;
Expand Down Expand Up @@ -87,6 +88,9 @@ type WorkflowStoreState = TReactFlowGraph & {
deleteNodeByIdx: (nodeIdx: number) => void;
deleteControlByIdx: (controlIdx: number) => void;
duplicateNodeByIdx: (nodeIdx: number) => void;
addMissingSecretByIdx: (secret: string, nodeIdx: number) => void;
deleteMissingSecretByIdx: (idx: number) => void;
getMissingSecretByIdx: (idx: number) => string;
// Settings Side Panel
detailPageType: "workflow" | "action" | null;
selectedNodeIdx: number | null;
Expand All @@ -106,6 +110,7 @@ export const useWorkflowStore = create<WorkflowStoreState>((set, get) => ({
isActive: false,
nodes: [],
edges: [],
missingSecretForNodes: [],
// Other
isNew: false,
nextId: 0,
Expand All @@ -123,6 +128,7 @@ export const useWorkflowStore = create<WorkflowStoreState>((set, get) => ({
isActive: false,
nodes: [],
edges: [],
missingSecretForNodes: [],
isNew: false,
nextId: 0,
webhookId: null,
Expand All @@ -140,6 +146,7 @@ export const useWorkflowStore = create<WorkflowStoreState>((set, get) => ({
controls: [],
isActive: false,
nodes: [buildStartNode(windowInnerWidth)],
missingSecretForNodes: [],
edges: [],
isNew: true,
webhookId: null,
Expand Down Expand Up @@ -372,6 +379,19 @@ export const useWorkflowStore = create<WorkflowStoreState>((set, get) => ({
}),
);
},
addMissingSecretByIdx: (secret: string, nodeIdx: number) =>
set(
produce((draft) => {
draft.missingSecretForNodes[nodeIdx] = secret;
}),
),
deleteMissingSecretByIdx: (idx: number) =>
set(
produce((draft) => {
draft.missingSecretForNodes[idx] = "";
}),
),
getMissingSecretByIdx: (idx: number) => get().missingSecretForNodes[idx],
deleteNodeByIdx: (nodeIdx: number) =>
set(
produce((draft) => {
Expand Down

0 comments on commit 39c13cd

Please sign in to comment.