Add new workflow parameter type in UI, credential (#1897)
This commit is contained in:
@@ -5,6 +5,7 @@ import { CodeEditor } from "./components/CodeEditor";
|
|||||||
import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea";
|
import { AutoResizingTextarea } from "@/components/AutoResizingTextarea/AutoResizingTextarea";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { WorkflowParameterValueType } from "./types/workflowTypes";
|
import { WorkflowParameterValueType } from "./types/workflowTypes";
|
||||||
|
import { CredentialSelector } from "./components/CredentialSelector";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
type: WorkflowParameterValueType;
|
type: WorkflowParameterValueType;
|
||||||
@@ -80,6 +81,16 @@ function WorkflowParameterInput({ type, value, onChange }: Props) {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === "credential_id") {
|
||||||
|
const credentialId = value as string | null;
|
||||||
|
return (
|
||||||
|
<CredentialSelector
|
||||||
|
value={credentialId ?? ""}
|
||||||
|
onChange={(value) => onChange(value)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { WorkflowParameterInput };
|
export { WorkflowParameterInput };
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import { useCredentialsQuery } from "../hooks/useCredentialsQuery";
|
||||||
|
import { useWorkflowParametersState } from "../editor/useWorkflowParametersState";
|
||||||
|
import { WorkflowParameterValueType } from "../types/workflowTypes";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
value: string;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
function CredentialParameterSourceSelector({ value, onChange }: Props) {
|
||||||
|
const { data: credentials, isFetching } = useCredentialsQuery();
|
||||||
|
const [workflowParameters] = useWorkflowParametersState();
|
||||||
|
const workflowParametersOfTypeCredentialId = workflowParameters.filter(
|
||||||
|
(parameter) =>
|
||||||
|
parameter.parameterType === "workflow" &&
|
||||||
|
parameter.dataType === WorkflowParameterValueType.CredentialId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isFetching) {
|
||||||
|
return <Skeleton className="h-10 w-full" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!credentials) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const credentialOptions = credentials?.map((credential) => ({
|
||||||
|
label: credential.name,
|
||||||
|
value: credential.credential_id,
|
||||||
|
type: "credential",
|
||||||
|
}));
|
||||||
|
|
||||||
|
const workflowParameterOptionsOfTypeCredentialId =
|
||||||
|
workflowParametersOfTypeCredentialId.map((parameter) => ({
|
||||||
|
label: parameter.key,
|
||||||
|
value: parameter.key,
|
||||||
|
type: "parameter",
|
||||||
|
}));
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
...credentialOptions,
|
||||||
|
...workflowParameterOptionsOfTypeCredentialId,
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select value={value} onValueChange={onChange}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a credential" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{options.map((option) => (
|
||||||
|
<SelectItem key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { CredentialParameterSourceSelector };
|
||||||
@@ -16,7 +16,7 @@ type Props = {
|
|||||||
onChange?: (value: string) => void;
|
onChange?: (value: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
function CredentialParameterSelector({ value, onChange }: Props) {
|
function LoginBlockCredentialSelector({ value, onChange }: Props) {
|
||||||
const [workflowParameters, setWorkflowParameters] =
|
const [workflowParameters, setWorkflowParameters] =
|
||||||
useWorkflowParametersState();
|
useWorkflowParametersState();
|
||||||
const credentialParameters = workflowParameters.filter(
|
const credentialParameters = workflowParameters.filter(
|
||||||
@@ -104,4 +104,4 @@ function CredentialParameterSelector({ value, onChange }: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { CredentialParameterSelector };
|
export { LoginBlockCredentialSelector };
|
||||||
@@ -29,13 +29,12 @@ import { EditableNodeTitle } from "../components/EditableNodeTitle";
|
|||||||
import { NodeActionMenu } from "../NodeActionMenu";
|
import { NodeActionMenu } from "../NodeActionMenu";
|
||||||
import { errorMappingExampleValue } from "../types";
|
import { errorMappingExampleValue } from "../types";
|
||||||
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
import { WorkflowBlockIcon } from "../WorkflowBlockIcon";
|
||||||
import { CredentialParameterSelector } from "./CredentialParameterSelector";
|
|
||||||
import type { LoginNode } from "./types";
|
import type { LoginNode } from "./types";
|
||||||
import { ParametersMultiSelect } from "../TaskNode/ParametersMultiSelect";
|
import { ParametersMultiSelect } from "../TaskNode/ParametersMultiSelect";
|
||||||
import { AppNode } from "..";
|
import { AppNode } from "..";
|
||||||
import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils";
|
import { getAvailableOutputParameterKeys } from "../../workflowEditorUtils";
|
||||||
import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow";
|
import { useIsFirstBlockInWorkflow } from "../../hooks/useIsFirstNodeInWorkflow";
|
||||||
|
import { LoginBlockCredentialSelector } from "./LoginBlockCredentialSelector";
|
||||||
function LoginNode({ id, data }: NodeProps<LoginNode>) {
|
function LoginNode({ id, data }: NodeProps<LoginNode>) {
|
||||||
const { updateNodeData } = useReactFlow();
|
const { updateNodeData } = useReactFlow();
|
||||||
const { editable } = data;
|
const { editable } = data;
|
||||||
@@ -152,7 +151,7 @@ function LoginNode({ id, data }: NodeProps<LoginNode>) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label className="text-xs text-slate-300">Credential</Label>
|
<Label className="text-xs text-slate-300">Credential</Label>
|
||||||
<CredentialParameterSelector
|
<LoginBlockCredentialSelector
|
||||||
value={
|
value={
|
||||||
data.parameterKeys.length > 0
|
data.parameterKeys.length > 0
|
||||||
? data.parameterKeys[0]
|
? data.parameterKeys[0]
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import { Cross2Icon } from "@radix-ui/react-icons";
|
import { SwitchBar } from "@/components/SwitchBar";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { useContext, useState } from "react";
|
import { Label } from "@/components/ui/label";
|
||||||
import {
|
import { ScrollArea, ScrollAreaViewport } from "@/components/ui/scroll-area";
|
||||||
WorkflowEditorParameterType,
|
|
||||||
WorkflowParameterValueType,
|
|
||||||
} from "../../types/workflowTypes";
|
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
@@ -14,17 +12,19 @@ import {
|
|||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { ParametersState } from "../types";
|
|
||||||
import { WorkflowParameterInput } from "../../WorkflowParameterInput";
|
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
|
||||||
import { getDefaultValueForParameterType } from "../workflowEditorUtils";
|
|
||||||
import { toast } from "@/components/ui/use-toast";
|
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 CloudContext from "@/store/CloudContext";
|
||||||
import { CredentialSelector } from "../../components/CredentialSelector";
|
import { Cross2Icon } from "@radix-ui/react-icons";
|
||||||
import { SwitchBar } from "@/components/SwitchBar";
|
import { useContext, useState } from "react";
|
||||||
|
import { CredentialParameterSourceSelector } from "../../components/CredentialParameterSourceSelector";
|
||||||
|
import { SourceParameterKeySelector } from "../../components/SourceParameterKeySelector";
|
||||||
|
import {
|
||||||
|
WorkflowEditorParameterType,
|
||||||
|
WorkflowParameterValueType,
|
||||||
|
} from "../../types/workflowTypes";
|
||||||
|
import { WorkflowParameterInput } from "../../WorkflowParameterInput";
|
||||||
|
import { ParametersState } from "../types";
|
||||||
|
import { getDefaultValueForParameterType } from "../workflowEditorUtils";
|
||||||
import { validateBitwardenLoginCredential } from "./util";
|
import { validateBitwardenLoginCredential } from "./util";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -39,6 +39,7 @@ const workflowParameterTypeOptions = [
|
|||||||
{ label: "integer", value: WorkflowParameterValueType.Integer },
|
{ label: "integer", value: WorkflowParameterValueType.Integer },
|
||||||
{ label: "boolean", value: WorkflowParameterValueType.Boolean },
|
{ label: "boolean", value: WorkflowParameterValueType.Boolean },
|
||||||
{ label: "file", value: WorkflowParameterValueType.FileURL },
|
{ label: "file", value: WorkflowParameterValueType.FileURL },
|
||||||
|
{ label: "credential", value: WorkflowParameterValueType.CredentialId },
|
||||||
{ label: "JSON", value: WorkflowParameterValueType.JSON },
|
{ label: "JSON", value: WorkflowParameterValueType.JSON },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -299,7 +300,7 @@ function WorkflowParameterAddPanel({ type, onClose, onSave }: Props) {
|
|||||||
isCloud && (
|
isCloud && (
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<Label className="text-xs text-slate-300">Credential</Label>
|
<Label className="text-xs text-slate-300">Credential</Label>
|
||||||
<CredentialSelector
|
<CredentialParameterSourceSelector
|
||||||
value={credentialId}
|
value={credentialId}
|
||||||
onChange={(value) => setCredentialId(value)}
|
onChange={(value) => setCredentialId(value)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { toast } from "@/components/ui/use-toast";
|
|||||||
import CloudContext from "@/store/CloudContext";
|
import CloudContext from "@/store/CloudContext";
|
||||||
import { Cross2Icon } from "@radix-ui/react-icons";
|
import { Cross2Icon } from "@radix-ui/react-icons";
|
||||||
import { useContext, useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
import { CredentialSelector } from "../../components/CredentialSelector";
|
import { CredentialParameterSourceSelector } from "../../components/CredentialParameterSourceSelector";
|
||||||
import { SourceParameterKeySelector } from "../../components/SourceParameterKeySelector";
|
import { SourceParameterKeySelector } from "../../components/SourceParameterKeySelector";
|
||||||
import {
|
import {
|
||||||
WorkflowEditorParameterType,
|
WorkflowEditorParameterType,
|
||||||
@@ -44,6 +44,7 @@ const workflowParameterTypeOptions = [
|
|||||||
{ label: "integer", value: WorkflowParameterValueType.Integer },
|
{ label: "integer", value: WorkflowParameterValueType.Integer },
|
||||||
{ label: "boolean", value: WorkflowParameterValueType.Boolean },
|
{ label: "boolean", value: WorkflowParameterValueType.Boolean },
|
||||||
{ label: "file", value: WorkflowParameterValueType.FileURL },
|
{ label: "file", value: WorkflowParameterValueType.FileURL },
|
||||||
|
{ label: "credential", value: WorkflowParameterValueType.CredentialId },
|
||||||
{ label: "JSON", value: WorkflowParameterValueType.JSON },
|
{ label: "JSON", value: WorkflowParameterValueType.JSON },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -353,7 +354,7 @@ function WorkflowParameterEditPanel({
|
|||||||
isCloud && (
|
isCloud && (
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<Label className="text-xs text-slate-300">Credential</Label>
|
<Label className="text-xs text-slate-300">Credential</Label>
|
||||||
<CredentialSelector
|
<CredentialParameterSourceSelector
|
||||||
value={credentialId}
|
value={credentialId}
|
||||||
onChange={(value) => setCredentialId(value)}
|
onChange={(value) => setCredentialId(value)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1438,6 +1438,9 @@ function getDefaultValueForParameterType(
|
|||||||
case "file_url": {
|
case "file_url": {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
case "credential_id": {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ export const WorkflowParameterValueType = {
|
|||||||
Boolean: "boolean",
|
Boolean: "boolean",
|
||||||
JSON: "json",
|
JSON: "json",
|
||||||
FileURL: "file_url",
|
FileURL: "file_url",
|
||||||
|
CredentialId: "credential_id",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type WorkflowParameterValueType =
|
export type WorkflowParameterValueType =
|
||||||
|
|||||||
Reference in New Issue
Block a user