From e2dcf5474c4cff22d6ae72dc18136631d878a5e8 Mon Sep 17 00:00:00 2001 From: Shuchang Zheng Date: Tue, 4 Mar 2025 11:46:07 -0500 Subject: [PATCH] Add item id field in parameters panel (#1883) Co-authored-by: Muhammed Salih Altun --- .../routes/workflows/editor/FlowRenderer.tsx | 1 + .../workflows/editor/WorkflowEditor.tsx | 1 + .../panels/WorkflowParameterAddPanel.tsx | 88 +++++++++++++------ .../panels/WorkflowParameterEditPanel.tsx | 87 +++++++++++------- .../routes/workflows/editor/panels/util.ts | 13 +++ .../src/routes/workflows/editor/types.ts | 5 +- .../workflows/editor/workflowEditorUtils.ts | 1 + .../routes/workflows/types/workflowTypes.ts | 5 +- .../workflows/types/workflowYamlTypes.ts | 5 +- 9 files changed, 142 insertions(+), 64 deletions(-) create mode 100644 skyvern-frontend/src/routes/workflows/editor/panels/util.ts diff --git a/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx b/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx index f452bc5e..f4947d0e 100644 --- a/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx @@ -152,6 +152,7 @@ function convertToParametersYAML( key: parameter.key, description: parameter.description || null, bitwarden_collection_id: parameter.collectionId, + bitwarden_item_id: parameter.itemId, url_parameter_key: parameter.urlParameterKey, bitwarden_client_id_aws_secret_key: BITWARDEN_CLIENT_ID_AWS_SECRET_KEY, diff --git a/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx b/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx index 4d26f452..183fb49f 100644 --- a/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/WorkflowEditor.tsx @@ -131,6 +131,7 @@ function WorkflowEditor() { key: parameter.key, parameterType: WorkflowEditorParameterTypes.Credential, collectionId: parameter.bitwarden_collection_id, + itemId: parameter.bitwarden_item_id, urlParameterKey: parameter.url_parameter_key, description: parameter.description, }; diff --git a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterAddPanel.tsx b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterAddPanel.tsx index def8a544..219526fe 100644 --- a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterAddPanel.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterAddPanel.tsx @@ -25,6 +25,7 @@ import { ScrollArea, ScrollAreaViewport } from "@/components/ui/scroll-area"; import CloudContext from "@/store/CloudContext"; import { CredentialSelector } from "../../components/CredentialSelector"; import { SwitchBar } from "@/components/SwitchBar"; +import { validateBitwardenLoginCredential } from "./util"; type Props = { type: WorkflowEditorParameterType; @@ -62,7 +63,9 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) { const [key, setKey] = useState(""); const [urlParameterKey, setUrlParameterKey] = useState(""); const [description, setDescription] = useState(""); - const [collectionId, setCollectionId] = useState(""); + const [bitwardenCollectionId, setBitwardenCollectionId] = useState(""); + const [bitwardenLoginCredentialItemId, setBitwardenLoginCredentialItemId] = + useState(""); const [parameterType, setParameterType] = useState("string"); const [defaultValueState, setDefaultValueState] = useState<{ @@ -82,7 +85,8 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) { const [identityKey, setIdentityKey] = useState(""); const [identityFields, setIdentityFields] = useState(""); - const [itemId, setItemId] = useState(""); + const [sensitiveInformationItemId, setSensitiveInformationItemId] = + useState(""); const [credentialId, setCredentialId] = useState(""); @@ -217,8 +221,17 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) {
setCollectionId(e.target.value)} + value={bitwardenCollectionId} + onChange={(e) => setBitwardenCollectionId(e.target.value)} + /> +
+
+ + + setBitwardenLoginCredentialItemId(e.target.value) + } />
@@ -253,8 +266,8 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) {
setCollectionId(e.target.value)} + value={bitwardenCollectionId} + onChange={(e) => setBitwardenCollectionId(e.target.value)} />
@@ -264,15 +277,17 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) {
setItemId(e.target.value)} + value={sensitiveInformationItemId} + onChange={(e) => + setSensitiveInformationItemId(e.target.value) + } />
setCollectionId(e.target.value)} + value={bitwardenCollectionId} + onChange={(e) => setBitwardenCollectionId(e.target.value)} />
@@ -333,12 +348,38 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) { : null, }); } - if ( - (type === "credential" && credentialType === "bitwarden") || - type === "secret" || - type === "creditCardData" - ) { - if (!collectionId) { + if (type === "credential" && credentialType === "bitwarden") { + const errorMessage = validateBitwardenLoginCredential( + bitwardenCollectionId, + bitwardenLoginCredentialItemId, + urlParameterKey, + ); + if (errorMessage) { + toast({ + variant: "destructive", + title: "Failed to save parameter", + description: errorMessage, + }); + return; + } + onSave({ + key, + parameterType: "credential", + collectionId: + bitwardenCollectionId === "" + ? null + : bitwardenCollectionId, + itemId: + bitwardenLoginCredentialItemId === "" + ? null + : bitwardenLoginCredentialItemId, + urlParameterKey: + urlParameterKey === "" ? null : urlParameterKey, + description, + }); + } + if (type === "secret" || type === "creditCardData") { + if (!bitwardenCollectionId) { toast({ variant: "destructive", title: "Failed to save parameter", @@ -347,20 +388,11 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) { return; } } - if (type === "credential" && credentialType === "bitwarden") { - onSave({ - key, - parameterType: "credential", - collectionId, - urlParameterKey, - description, - }); - } if (type === "secret") { onSave({ key, parameterType: "secret", - collectionId, + collectionId: bitwardenCollectionId, identityFields: identityFields .split(",") .filter((s) => s.length > 0) @@ -373,8 +405,8 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) { onSave({ key, parameterType: "creditCardData", - collectionId, - itemId, + collectionId: bitwardenCollectionId, + itemId: sensitiveInformationItemId, description, }); } diff --git a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx index b9c91a11..cbf6b3f5 100644 --- a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowParameterEditPanel.tsx @@ -1,11 +1,9 @@ -import { Cross2Icon } from "@radix-ui/react-icons"; -import { Label } from "@/components/ui/label"; +import { SwitchBar } from "@/components/SwitchBar"; +import { Button } from "@/components/ui/button"; +import { Checkbox } from "@/components/ui/checkbox"; import { Input } from "@/components/ui/input"; -import { useState, useContext } from "react"; -import { - WorkflowEditorParameterType, - WorkflowParameterValueType, -} from "../../types/workflowTypes"; +import { Label } from "@/components/ui/label"; +import { ScrollArea, ScrollAreaViewport } from "@/components/ui/scroll-area"; import { Select, SelectContent, @@ -14,21 +12,24 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; -import { Button } from "@/components/ui/button"; -import { Checkbox } from "@/components/ui/checkbox"; -import { getDefaultValueForParameterType } from "../workflowEditorUtils"; -import { WorkflowParameterInput } from "../../WorkflowParameterInput"; import { toast } from "@/components/ui/use-toast"; -import { SourceParameterKeySelector } from "../../components/SourceParameterKeySelector"; -import { ScrollArea, ScrollAreaViewport } from "@/components/ui/scroll-area"; import CloudContext from "@/store/CloudContext"; +import { Cross2Icon } from "@radix-ui/react-icons"; +import { useContext, useState } from "react"; import { CredentialSelector } from "../../components/CredentialSelector"; -import { SwitchBar } from "@/components/SwitchBar"; +import { SourceParameterKeySelector } from "../../components/SourceParameterKeySelector"; +import { + WorkflowEditorParameterType, + WorkflowParameterValueType, +} from "../../types/workflowTypes"; +import { WorkflowParameterInput } from "../../WorkflowParameterInput"; import { parameterIsBitwardenCredential, parameterIsSkyvernCredential, ParametersState, } from "../types"; +import { getDefaultValueForParameterType } from "../workflowEditorUtils"; +import { validateBitwardenLoginCredential } from "./util"; type Props = { type: WorkflowEditorParameterType; @@ -80,7 +81,7 @@ function WorkflowParameterEditPanel({ isBitwardenCredential ? "bitwarden" : "skyvern", ); const [urlParameterKey, setUrlParameterKey] = useState( - isBitwardenCredential ? initialValues.urlParameterKey : "", + isBitwardenCredential ? initialValues.urlParameterKey ?? "" : "", ); const [description, setDescription] = useState( initialValues.description ?? "", @@ -89,7 +90,7 @@ function WorkflowParameterEditPanel({ isBitwardenCredential || initialValues.parameterType === "secret" || initialValues.parameterType === "creditCardData" - ? initialValues.collectionId + ? initialValues.collectionId ?? "" : "", ); const [parameterType, setParameterType] = @@ -142,6 +143,9 @@ function WorkflowParameterEditPanel({ isSkyvernCredential ? initialValues.credentialId : "", ); + const [bitwardenLoginCredentialItemId, setBitwardenLoginCredentialItemId] = + useState(isBitwardenCredential ? initialValues.itemId ?? "" : ""); + return ( @@ -277,6 +281,15 @@ function WorkflowParameterEditPanel({ onChange={(e) => setCollectionId(e.target.value)} /> +
+ + + setBitwardenLoginCredentialItemId(e.target.value) + } + /> +
)} {type === "context" && ( @@ -389,11 +402,34 @@ function WorkflowParameterEditPanel({ : null, }); } - if ( - (type === "credential" && credentialType === "bitwarden") || - type === "secret" || - type === "creditCardData" - ) { + if (type === "credential" && credentialType === "bitwarden") { + const errorMessage = validateBitwardenLoginCredential( + collectionId, + bitwardenLoginCredentialItemId, + urlParameterKey, + ); + if (errorMessage) { + toast({ + variant: "destructive", + title: "Failed to save parameter", + description: errorMessage, + }); + return; + } + onSave({ + key, + parameterType: "credential", + itemId: + bitwardenLoginCredentialItemId === "" + ? null + : bitwardenLoginCredentialItemId, + urlParameterKey: + urlParameterKey === "" ? null : urlParameterKey, + collectionId: collectionId === "" ? null : collectionId, + description, + }); + } + if (type === "secret" || type === "creditCardData") { if (!collectionId) { toast({ variant: "destructive", @@ -403,15 +439,6 @@ function WorkflowParameterEditPanel({ return; } } - if (type === "credential" && credentialType === "bitwarden") { - onSave({ - key, - parameterType: "credential", - urlParameterKey, - collectionId, - description, - }); - } if (type === "secret") { onSave({ key, diff --git a/skyvern-frontend/src/routes/workflows/editor/panels/util.ts b/skyvern-frontend/src/routes/workflows/editor/panels/util.ts new file mode 100644 index 00000000..6da06f2c --- /dev/null +++ b/skyvern-frontend/src/routes/workflows/editor/panels/util.ts @@ -0,0 +1,13 @@ +export function validateBitwardenLoginCredential( + collectionId: string | null, + itemId: string | null, + urlParameterKey: string | null, +): string | null { + if (!collectionId && !itemId) { + return "Collection ID or Item ID is required"; + } + if (collectionId && !urlParameterKey) { + return "URL Parameter Key is required when collection ID is used"; + } + return null; +} diff --git a/skyvern-frontend/src/routes/workflows/editor/types.ts b/skyvern-frontend/src/routes/workflows/editor/types.ts index 3db1eb6a..13c59a2f 100644 --- a/skyvern-frontend/src/routes/workflows/editor/types.ts +++ b/skyvern-frontend/src/routes/workflows/editor/types.ts @@ -4,8 +4,9 @@ export type BitwardenLoginCredential = { key: string; description?: string | null; parameterType: "credential"; - collectionId: string; - urlParameterKey: string; + collectionId: string | null; + itemId: string | null; + urlParameterKey: string | null; }; export type SkyvernCredential = { diff --git a/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts b/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts index 5d447e3a..68cc9cd8 100644 --- a/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts +++ b/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts @@ -1505,6 +1505,7 @@ function convertParametersToParameterYAML( ...base, parameter_type: WorkflowParameterTypes.Bitwarden_Login_Credential, bitwarden_collection_id: parameter.bitwarden_collection_id, + bitwarden_item_id: parameter.bitwarden_item_id, url_parameter_key: parameter.url_parameter_key, bitwarden_client_id_aws_secret_key: parameter.bitwarden_client_id_aws_secret_key, diff --git a/skyvern-frontend/src/routes/workflows/types/workflowTypes.ts b/skyvern-frontend/src/routes/workflows/types/workflowTypes.ts index e807fb25..58110298 100644 --- a/skyvern-frontend/src/routes/workflows/types/workflowTypes.ts +++ b/skyvern-frontend/src/routes/workflows/types/workflowTypes.ts @@ -23,8 +23,9 @@ export type BitwardenLoginCredentialParameter = WorkflowParameterBase & { bitwarden_client_id_aws_secret_key: string; bitwarden_client_secret_aws_secret_key: string; bitwarden_master_password_aws_secret_key: string; - bitwarden_collection_id: string; - url_parameter_key: string; + bitwarden_collection_id: string | null; + bitwarden_item_id: string | null; + url_parameter_key: string | null; created_at: string; modified_at: string; deleted_at: string | null; diff --git a/skyvern-frontend/src/routes/workflows/types/workflowYamlTypes.ts b/skyvern-frontend/src/routes/workflows/types/workflowYamlTypes.ts index e7c5a748..f6b4b297 100644 --- a/skyvern-frontend/src/routes/workflows/types/workflowYamlTypes.ts +++ b/skyvern-frontend/src/routes/workflows/types/workflowYamlTypes.ts @@ -40,8 +40,9 @@ export type WorkflowParameterYAML = ParameterYAMLBase & { export type BitwardenLoginCredentialParameterYAML = ParameterYAMLBase & { parameter_type: "bitwarden_login_credential"; - bitwarden_collection_id: string; - url_parameter_key: string; + bitwarden_collection_id: string | null; + bitwarden_item_id: string | null; + url_parameter_key: string | null; bitwarden_client_id_aws_secret_key: string; bitwarden_client_secret_aws_secret_key: string; bitwarden_master_password_aws_secret_key: string;