From 9c5ec164fc35277099b9cfe5379735ee416888c8 Mon Sep 17 00:00:00 2001 From: Kerem Yilmaz Date: Mon, 16 Sep 2024 11:41:52 -0700 Subject: [PATCH] Fix email node not saved correctly (#832) --- .../workflows/editor/WorkflowEditor.tsx | 21 ++++++- .../src/routes/workflows/editor/constants.ts | 14 +++++ .../editor/nodes/DownloadNode/types.ts | 3 +- .../nodes/SendEmailNode/SendEmailNode.tsx | 16 +---- .../editor/nodes/SendEmailNode/types.ts | 16 ++++- .../editor/nodes/UploadNode/types.ts | 3 +- .../workflows/editor/workflowEditorUtils.ts | 62 ++++++++++++++++++- 7 files changed, 112 insertions(+), 23 deletions(-) diff --git a/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx b/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx index 72b6f525..81b0edc5 100644 --- a/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx @@ -1,6 +1,10 @@ import { useParams } from "react-router-dom"; import { useWorkflowQuery } from "../hooks/useWorkflowQuery"; -import { convertEchoParameters, getElements } from "./workflowEditorUtils"; +import { + convertEchoParameters, + getAdditionalParametersForEmailBlock, + getElements, +} from "./workflowEditorUtils"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { BlockYAML, @@ -143,8 +147,21 @@ function WorkflowEditor() { const echoParameters = convertEchoParameters(filteredParameters); + const overallParameters = [ + ...parameters, + ...echoParameters, + ] as Array; + + // if there is an email node, we need to add the email aws secret parameters + const emailAwsSecretParameters = + getAdditionalParametersForEmailBlock(blocks, overallParameters); + saveWorkflowMutation.mutate({ - parameters: [...echoParameters, ...parameters], + parameters: [ + ...echoParameters, + ...parameters, + ...emailAwsSecretParameters, + ], blocks, title, }); diff --git a/skyvern-frontend/src/routes/workflows/editor/constants.ts b/skyvern-frontend/src/routes/workflows/editor/constants.ts index 1ac395b4..b0c6cc28 100644 --- a/skyvern-frontend/src/routes/workflows/editor/constants.ts +++ b/skyvern-frontend/src/routes/workflows/editor/constants.ts @@ -1,2 +1,16 @@ // nodes have 1000 Z index and we want edges above export const REACT_FLOW_EDGE_Z_INDEX = 1001; + +export const SKYVERN_DOWNLOAD_DIRECTORY = "SKYVERN_DOWNLOAD_DIRECTORY"; + +export const SMTP_HOST_PARAMETER_KEY = "smtp_host"; +export const SMTP_PORT_PARAMETER_KEY = "smtp_port"; +export const SMTP_USERNAME_PARAMETER_KEY = "smtp_username"; +export const SMTP_PASSWORD_PARAMETER_KEY = "smtp_password"; + +export const SMTP_HOST_AWS_KEY = "SKYVERN_SMTP_HOST_AWS_SES"; +export const SMTP_PORT_AWS_KEY = "SKYVERN_SMTP_PORT_AWS_SES"; +export const SMTP_USERNAME_AWS_KEY = "SKYVERN_SMTP_USERNAME_AWS_SES"; +export const SMTP_PASSWORD_AWS_KEY = "SKYVERN_SMTP_PASSWORD_AWS_SES"; + +export const EMAIL_BLOCK_SENDER = "hello@skyvern.com"; diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/DownloadNode/types.ts b/skyvern-frontend/src/routes/workflows/editor/nodes/DownloadNode/types.ts index 01ddc4dc..8d7e9c21 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/DownloadNode/types.ts +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/DownloadNode/types.ts @@ -1,4 +1,5 @@ import type { Node } from "@xyflow/react"; +import { SKYVERN_DOWNLOAD_DIRECTORY } from "../../constants"; export type DownloadNodeData = { url: string; @@ -11,5 +12,5 @@ export type DownloadNode = Node; export const downloadNodeDefaultData: DownloadNodeData = { editable: true, label: "", - url: "SKYVERN_DOWNLOAD_DIRECTORY", + url: SKYVERN_DOWNLOAD_DIRECTORY, } as const; diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/SendEmailNode.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/SendEmailNode.tsx index 74fac1dd..14acf5d1 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/SendEmailNode.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/SendEmailNode.tsx @@ -23,7 +23,6 @@ function SendEmailNode({ id, data }: NodeProps) { const deleteNodeCallback = useDeleteNodeCallback(); const [label, setLabel] = useState(data.label); const [inputs, setInputs] = useState({ - sender: data.sender, recipients: data.recipients, subject: data.subject, body: data.body, @@ -83,20 +82,6 @@ function SendEmailNode({ id, data }: NodeProps) { }} /> -
- - { - if (!data.editable) { - return; - } - handleChange("sender", event.target.value); - }} - value={inputs.sender} - placeholder="example@gmail.com" - className="nopan" - /> -
) { } handleChange("fileAttachments", event.target.value); }} + disabled className="nopan" />
diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/types.ts b/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/types.ts index 1a72b229..ee2e85fe 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/types.ts +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/SendEmailNode/types.ts @@ -1,4 +1,12 @@ import type { Node } from "@xyflow/react"; +import { + EMAIL_BLOCK_SENDER, + SKYVERN_DOWNLOAD_DIRECTORY, + SMTP_HOST_PARAMETER_KEY, + SMTP_PASSWORD_PARAMETER_KEY, + SMTP_PORT_PARAMETER_KEY, + SMTP_USERNAME_PARAMETER_KEY, +} from "../../constants"; export type SendEmailNodeData = { recipients: string; @@ -20,8 +28,12 @@ export const sendEmailNodeDefaultData: SendEmailNodeData = { recipients: "", subject: "", body: "", - fileAttachments: "", + fileAttachments: SKYVERN_DOWNLOAD_DIRECTORY, editable: true, label: "", - sender: "", + sender: EMAIL_BLOCK_SENDER, + smtpHostSecretParameterKey: SMTP_HOST_PARAMETER_KEY, + smtpPortSecretParameterKey: SMTP_PORT_PARAMETER_KEY, + smtpUsernameSecretParameterKey: SMTP_USERNAME_PARAMETER_KEY, + smtpPasswordSecretParameterKey: SMTP_PASSWORD_PARAMETER_KEY, } as const; diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/UploadNode/types.ts b/skyvern-frontend/src/routes/workflows/editor/nodes/UploadNode/types.ts index 88d2a918..5646ecf0 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/UploadNode/types.ts +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/UploadNode/types.ts @@ -1,4 +1,5 @@ import type { Node } from "@xyflow/react"; +import { SKYVERN_DOWNLOAD_DIRECTORY } from "../../constants"; export type UploadNodeData = { path: string; @@ -11,5 +12,5 @@ export type UploadNode = Node; export const uploadNodeDefaultData: UploadNodeData = { editable: true, label: "", - path: "SKYVERN_DOWNLOAD_DIRECTORY", + path: SKYVERN_DOWNLOAD_DIRECTORY, } as const; diff --git a/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts b/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts index a9c1e04e..597d3978 100644 --- a/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts +++ b/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts @@ -3,7 +3,18 @@ import { Edge } from "@xyflow/react"; import { nanoid } from "nanoid"; import type { WorkflowBlock } from "../types/workflowTypes"; import { BlockYAML, ParameterYAML } from "../types/workflowYamlTypes"; -import { REACT_FLOW_EDGE_Z_INDEX } from "./constants"; +import { + EMAIL_BLOCK_SENDER, + REACT_FLOW_EDGE_Z_INDEX, + SMTP_HOST_AWS_KEY, + SMTP_HOST_PARAMETER_KEY, + SMTP_PASSWORD_AWS_KEY, + SMTP_PASSWORD_PARAMETER_KEY, + SMTP_PORT_AWS_KEY, + SMTP_PORT_PARAMETER_KEY, + SMTP_USERNAME_AWS_KEY, + SMTP_USERNAME_PARAMETER_KEY, +} from "./constants"; import { AppNode, nodeTypes } from "./nodes"; import { codeBlockNodeDefaultData } from "./nodes/CodeBlockNode/types"; import { downloadNodeDefaultData } from "./nodes/DownloadNode/types"; @@ -471,7 +482,7 @@ function getWorkflowBlock( file_attachments: node.data.fileAttachments.split(","), recipients: node.data.recipients.split(","), subject: node.data.subject, - sender: node.data.sender, + sender: node.data.sender === "" ? EMAIL_BLOCK_SENDER : node.data.sender, smtp_host_secret_parameter_key: node.data.smtpHostSecretParameterKey, smtp_port_secret_parameter_key: node.data.smtpPortSecretParameterKey, smtp_username_secret_parameter_key: @@ -657,6 +668,52 @@ function getUpdatedNodesAfterLabelUpdateForParameterKeys( }); } +const sendEmailExpectedParameters = [ + { + key: SMTP_HOST_PARAMETER_KEY, + aws_key: SMTP_HOST_AWS_KEY, + parameter_type: "aws_secret", + }, + { + key: SMTP_PORT_PARAMETER_KEY, + aws_key: SMTP_PORT_AWS_KEY, + parameter_type: "aws_secret", + }, + { + key: SMTP_USERNAME_PARAMETER_KEY, + aws_key: SMTP_USERNAME_AWS_KEY, + parameter_type: "aws_secret", + }, + { + key: SMTP_PASSWORD_PARAMETER_KEY, + aws_key: SMTP_PASSWORD_AWS_KEY, + parameter_type: "aws_secret", + }, +] as const; + +function getAdditionalParametersForEmailBlock( + blocks: Array, + parameters: Array, +): Array { + const emailBlocks = blocks.filter( + (block) => block.block_type === "send_email", + ); + if (emailBlocks.length === 0) { + return []; + } + const sendEmailParameters = sendEmailExpectedParameters.flatMap( + (parameter) => { + const existingParameter = parameters.find((p) => p.key === parameter.key); + if (existingParameter) { + return []; + } + return [parameter]; + }, + ); + + return sendEmailParameters; +} + export { createNode, generateNodeData, @@ -667,4 +724,5 @@ export { convertEchoParameters, getOutputParameterKey, getUpdatedNodesAfterLabelUpdateForParameterKeys, + getAdditionalParametersForEmailBlock, };