fix: make onboarding match designs (#163)
* implement custom value when custom is active on model selector * changed ibm logo to watsonx * set endpoint selector as custom * changed IBM to IBM watsonx.ai * upload copies on ibm onboarding * disable select on disabled button * changed use env open ai api key style * Changed width to match designs * disable default tag * made selector full width and made default disappear * removed ! * removed onboarding toast * fix card border radius
This commit is contained in:
parent
522b8b8159
commit
28dbca4ba0
8 changed files with 287 additions and 238 deletions
|
|
@ -37,7 +37,7 @@ export function LabelWrapper({
|
|||
>
|
||||
<Label
|
||||
htmlFor={id}
|
||||
className="!text-mmd font-medium flex items-center gap-1.5"
|
||||
className={cn("font-medium flex items-center gap-1.5", description ? "!text-sm" : "!text-mmd")}
|
||||
>
|
||||
{label}
|
||||
{required && <span className="text-red-500">*</span>}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,24 @@ export default function IBMLogo(props: React.SVGProps<SVGSVGElement>) {
|
|||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<title>IBM Logo</title>
|
||||
<path
|
||||
d="M15.696 10.9901C15.7213 10.9901 15.7356 10.979 15.7356 10.9552V10.9313C15.7356 10.9076 15.7213 10.8964 15.696 10.8964H15.6359V10.9901H15.696ZM15.6359 11.1649H15.5552V10.8329H15.7055C15.7799 10.8329 15.8179 10.8773 15.8179 10.9378C15.8179 10.9901 15.7942 11.0235 15.7577 11.0378L15.8321 11.1649H15.7436L15.6818 11.0504H15.6359V11.1649ZM15.9255 11.0171V10.9759C15.9255 10.8424 15.821 10.7376 15.6833 10.7376C15.5456 10.7376 15.4412 10.8424 15.4412 10.9759V11.0171C15.4412 11.1505 15.5456 11.2554 15.6833 11.2554C15.821 11.2554 15.9255 11.1505 15.9255 11.0171ZM15.3668 10.9964C15.3668 10.8107 15.5077 10.6693 15.6833 10.6693C15.859 10.6693 16 10.8107 16 10.9964C16 11.1823 15.859 11.3237 15.6833 11.3237C15.5077 11.3237 15.3668 11.1823 15.3668 10.9964ZM10.8069 5.74885L10.6627 5.33301H8.28904V5.74885H10.8069ZM11.0821 6.54285L10.9379 6.12691H8.28904V6.54285H11.0821ZM12.8481 11.3067H14.9203V10.8908H12.8481V11.3067ZM12.8481 10.5126H14.9203V10.0968H12.8481V10.5126ZM12.8481 9.71873H14.0914V9.3028H12.8481V9.71873ZM12.8481 8.92474H14.0914V8.50889H12.8481V8.92474ZM12.8481 8.13084H14.0914V7.7149H11.7212L11.6047 8.05102L11.4882 7.7149H9.11794V8.13084H10.3613V7.74863L10.4951 8.13084H12.7143L12.8481 7.74863V8.13084ZM14.0914 6.921H11.9964L11.8522 7.33675H14.0914V6.921ZM9.11794 8.92474H10.3613V8.50889H9.11794V8.92474ZM9.11794 9.71873H10.3613V9.3028H9.11794V9.71873ZM8.28904 10.5126H10.3613V10.0968H8.28904V10.5126ZM8.28904 11.3067H10.3613V10.8908H8.28904V11.3067ZM12.5466 5.33301L12.4025 5.74885H14.9203V5.33301H12.5466ZM12.1273 6.54285H14.9203V6.12691H12.2714L12.1273 6.54285ZM9.11794 7.33675H11.3572L11.213 6.921H9.11794V7.33675ZM10.7727 8.92474H12.4366L12.5821 8.50889H10.6272L10.7727 8.92474ZM11.0505 9.71873H12.1588L12.3042 9.3028H10.9051L11.0505 9.71873ZM11.3283 10.5126H11.881L12.0265 10.0969H11.1828L11.3283 10.5126ZM11.604 11.3067L11.7487 10.8908H11.4606L11.604 11.3067ZM3.31561 11.3026L6.36754 11.3067C6.78195 11.3067 7.15365 11.1491 7.43506 10.8908H3.31561V11.3026ZM6.55592 9.3028V9.71873H7.94994C7.94994 9.57477 7.93029 9.43551 7.89456 9.3028H6.55592ZM4.14452 9.71873H5.38783V9.3028H4.14452V9.71873ZM6.55592 7.33675H7.89456C7.93029 7.20422 7.94994 7.06486 7.94994 6.921H6.55592V7.33675ZM4.14452 7.33675H5.38783V6.9209H4.14452V7.33675ZM6.36754 5.33301H3.31561V5.74885H7.43506C7.15365 5.49061 6.77892 5.33301 6.36754 5.33301ZM7.73778 6.12691H3.31561V6.54285H7.90448C7.86839 6.39502 7.81172 6.25539 7.73778 6.12691ZM4.14452 7.7149V8.13084H7.39152C7.5292 8.01333 7.64621 7.87268 7.73732 7.7149H4.14452ZM7.39152 8.50889H4.14452V8.92474H7.73732C7.64621 8.76695 7.5292 8.62631 7.39152 8.50889ZM3.31561 10.5126H7.73778C7.81172 10.3843 7.86839 10.2447 7.90448 10.0969H3.31561V10.5126ZM0 5.74885H2.90121V5.33301H0V5.74885ZM0 6.54285H2.90121V6.12691H0V6.54285ZM0.828996 7.33684H2.0723V6.921H0.828996V7.33684ZM0.828996 8.13084H2.0723V7.7149H0.828996V8.13084ZM0.828996 8.92474H2.0723V8.50889H0.828996V8.92474ZM0.828996 9.71873H2.0723V9.3028H0.828996V9.71873ZM0 10.5126H2.90121V10.0968H0V10.5126ZM0 11.3067H2.90121V10.8908H0V11.3067Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<title>IBM watsonx.ai Logo</title>
|
||||
<g clip-path="url(#clip0_2620_2081)">
|
||||
<path
|
||||
d="M13 12.0007C12.4477 12.0007 12 12.4484 12 13.0007C12 13.0389 12.0071 13.0751 12.0112 13.1122C10.8708 14.0103 9.47165 14.5007 8 14.5007C5.86915 14.5007 4 12.5146 4 10.2507C4 7.90722 5.9065 6.00072 8.25 6.00072H8.5V5.00072H8.25C5.3552 5.00072 3 7.35592 3 10.2507C3 11.1927 3.2652 12.0955 3.71855 12.879C2.3619 11.6868 1.5 9.94447 1.5 8.00072C1.5 6.94312 1.74585 5.93432 2.23095 5.00292L1.34375 4.54102C0.79175 5.60157 0.5 6.79787 0.5 8.00072C0.5 12.1362 3.8645 15.5007 8 15.5007C9.6872 15.5007 11.2909 14.9411 12.6024 13.9176C12.7244 13.9706 12.8586 14.0007 13 14.0007C13.5523 14.0007 14 13.553 14 13.0007C14 12.4484 13.5523 12.0007 13 12.0007Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path d="M6.5 11V10H5.5V11H6.5Z" fill="currentColor" />
|
||||
<path d="M10.5 6V5H9.5V6H10.5Z" fill="currentColor" />
|
||||
<path
|
||||
d="M8 0.5C6.3128 0.5 4.7091 1.05965 3.3976 2.0831C3.2756 2.0301 3.14145 2 3 2C2.4477 2 2 2.4477 2 3C2 3.5523 2.4477 4 3 4C3.5523 4 4 3.5523 4 3C4 2.9618 3.9929 2.9256 3.98875 2.88855C5.12915 1.9904 6.52835 1.5 8 1.5C10.1308 1.5 12 3.4861 12 5.75C12 8.0935 10.0935 10 7.75 10H7.5V11H7.75C10.6448 11 13 8.6448 13 5.75C13 4.80735 12.7339 3.90415 12.28 3.12035C13.6375 4.3125 14.5 6.05555 14.5 8C14.5 9.0576 14.2541 10.0664 13.769 10.9978L14.6562 11.4597C15.2083 10.3991 15.5 9.20285 15.5 8C15.5 3.8645 12.1355 0.5 8 0.5Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2620_2081">
|
||||
<rect width="16" height="16" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|||
import * as React from "react";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none disabled:select-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const Card = React.forwardRef<
|
|||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-lg border border-border bg-card text-card-foreground shadow-sm",
|
||||
"rounded-xl border border-border bg-card text-card-foreground shadow-sm",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ export function IBMOnboarding({
|
|||
<ModelSelector
|
||||
options={options}
|
||||
value={endpoint}
|
||||
custom
|
||||
onValueChange={setEndpoint}
|
||||
searchPlaceholder="Search endpoint..."
|
||||
noOptionsPlaceholder="No endpoints available"
|
||||
|
|
@ -118,8 +119,17 @@ export function IBMOnboarding({
|
|||
/>
|
||||
</LabelWrapper>
|
||||
<LabelInput
|
||||
label="IBM API key"
|
||||
helperText="The API key for your watsonx.ai account."
|
||||
label="watsonx Project ID"
|
||||
helperText="Project ID for the model"
|
||||
id="project-id"
|
||||
required
|
||||
placeholder="your-project-id"
|
||||
value={projectId}
|
||||
onChange={(e) => setProjectId(e.target.value)}
|
||||
/>
|
||||
<LabelInput
|
||||
label="watsonx API key"
|
||||
helperText="API key to access watsonx.ai"
|
||||
id="api-key"
|
||||
type="password"
|
||||
required
|
||||
|
|
@ -127,15 +137,6 @@ export function IBMOnboarding({
|
|||
value={apiKey}
|
||||
onChange={(e) => setApiKey(e.target.value)}
|
||||
/>
|
||||
<LabelInput
|
||||
label="IBM Project ID"
|
||||
helperText="The project ID for your watsonx.ai account."
|
||||
id="project-id"
|
||||
required
|
||||
placeholder="your-project-id"
|
||||
value={projectId}
|
||||
onChange={(e) => setProjectId(e.target.value)}
|
||||
/>
|
||||
{isLoadingModels && (
|
||||
<p className="text-mmd text-muted-foreground">
|
||||
Validating configuration...
|
||||
|
|
|
|||
|
|
@ -1,115 +1,158 @@
|
|||
import { CheckIcon, ChevronsUpDownIcon } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "@/components/ui/command";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function ModelSelector({
|
||||
options,
|
||||
value,
|
||||
onValueChange,
|
||||
icon,
|
||||
placeholder = "Select model...",
|
||||
searchPlaceholder = "Search model...",
|
||||
noOptionsPlaceholder = "No models available",
|
||||
options,
|
||||
value,
|
||||
onValueChange,
|
||||
icon,
|
||||
placeholder = "Select model...",
|
||||
searchPlaceholder = "Search model...",
|
||||
noOptionsPlaceholder = "No models available",
|
||||
custom = false,
|
||||
}: {
|
||||
options: {
|
||||
value: string;
|
||||
label: string;
|
||||
default?: boolean;
|
||||
}[];
|
||||
value: string;
|
||||
icon?: React.ReactNode;
|
||||
placeholder?: string;
|
||||
searchPlaceholder?: string;
|
||||
noOptionsPlaceholder?: string;
|
||||
onValueChange: (value: string) => void;
|
||||
options: {
|
||||
value: string;
|
||||
label: string;
|
||||
default?: boolean;
|
||||
}[];
|
||||
value: string;
|
||||
icon?: React.ReactNode;
|
||||
placeholder?: string;
|
||||
searchPlaceholder?: string;
|
||||
noOptionsPlaceholder?: string;
|
||||
custom?: boolean;
|
||||
onValueChange: (value: string) => void;
|
||||
}) {
|
||||
const [open, setOpen] = useState(false);
|
||||
useEffect(() => {
|
||||
if (value && !options.find((option) => option.value === value)) {
|
||||
onValueChange("");
|
||||
}
|
||||
}, [options, value, onValueChange]);
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
{/** biome-ignore lint/a11y/useSemanticElements: has to be a Button */}
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
disabled={options.length === 0}
|
||||
aria-expanded={open}
|
||||
className="w-full gap-2 justify-between font-normal text-sm"
|
||||
>
|
||||
{value ? (
|
||||
<div className="flex items-center gap-2">
|
||||
{icon && <div className="w-4 h-4">{icon}</div>}
|
||||
{options.find((framework) => framework.value === value)?.label}
|
||||
{options.find((framework) => framework.value === value)
|
||||
?.default && (
|
||||
<span className="text-xs text-foreground p-1 rounded-md bg-muted">
|
||||
Default
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
) : options.length === 0 ? (
|
||||
noOptionsPlaceholder
|
||||
) : (
|
||||
placeholder
|
||||
)}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" className="w-[400px] p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder={searchPlaceholder} />
|
||||
<CommandList>
|
||||
<CommandEmpty>{noOptionsPlaceholder}</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{options.map((option) => (
|
||||
<CommandItem
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
onSelect={(currentValue) => {
|
||||
if (currentValue !== value) {
|
||||
onValueChange(currentValue);
|
||||
}
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
value === option.value ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
<div className="flex items-center gap-2">
|
||||
{option.label}
|
||||
{option.default && (
|
||||
<span className="text-xs text-foreground p-1 rounded-md bg-muted">
|
||||
Default
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [searchValue, setSearchValue] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (value && (!options.find((option) => option.value === value) && !custom)) {
|
||||
onValueChange("");
|
||||
}
|
||||
}, [options, value, custom, onValueChange]);
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
{/** biome-ignore lint/a11y/useSemanticElements: has to be a Button */}
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
disabled={options.length === 0}
|
||||
aria-expanded={open}
|
||||
className="w-full gap-2 justify-between font-normal text-sm"
|
||||
>
|
||||
{value ? (
|
||||
<div className="flex items-center gap-2">
|
||||
{icon && <div className="w-4 h-4">{icon}</div>}
|
||||
{options.find((framework) => framework.value === value)?.label ||
|
||||
value}
|
||||
{/* {options.find((framework) => framework.value === value)
|
||||
?.default && (
|
||||
<span className="text-xs text-foreground p-1 rounded-md bg-muted">
|
||||
Default
|
||||
</span>
|
||||
)} */}
|
||||
{custom &&
|
||||
value &&
|
||||
!options.find((framework) => framework.value === value) && (
|
||||
<Badge variant="outline" className="text-xs">
|
||||
CUSTOM
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
) : options.length === 0 ? (
|
||||
noOptionsPlaceholder
|
||||
) : (
|
||||
placeholder
|
||||
)}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" className=" p-0 w-[var(--radix-popover-trigger-width)]">
|
||||
<Command>
|
||||
<CommandInput
|
||||
placeholder={searchPlaceholder}
|
||||
value={searchValue}
|
||||
onValueChange={setSearchValue}
|
||||
/>
|
||||
<CommandList>
|
||||
<CommandEmpty>{noOptionsPlaceholder}</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{options.map((option) => (
|
||||
<CommandItem
|
||||
key={option.value}
|
||||
value={option.value}
|
||||
onSelect={(currentValue) => {
|
||||
if (currentValue !== value) {
|
||||
onValueChange(currentValue);
|
||||
}
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
value === option.value ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
<div className="flex items-center gap-2">
|
||||
{option.label}
|
||||
{/* {option.default && (
|
||||
<span className="text-xs text-foreground p-1 rounded-md bg-muted"> // DISABLING DEFAULT TAG FOR NOW
|
||||
Default
|
||||
</span>
|
||||
)} */}
|
||||
</div>
|
||||
</CommandItem>
|
||||
))}
|
||||
{custom &&
|
||||
searchValue &&
|
||||
!options.find((option) => option.value === searchValue) && (
|
||||
<CommandItem
|
||||
value={searchValue}
|
||||
onSelect={(currentValue) => {
|
||||
if (currentValue !== value) {
|
||||
onValueChange(currentValue);
|
||||
}
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
value === searchValue ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
<div className="flex items-center gap-2">
|
||||
{searchValue}
|
||||
<span className="text-xs text-foreground p-1 rounded-md bg-muted">
|
||||
Custom
|
||||
</span>
|
||||
</div>
|
||||
</CommandItem>
|
||||
)}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useState } from "react";
|
|||
import { LabelInput } from "@/components/label-input";
|
||||
import { LabelWrapper } from "@/components/label-wrapper";
|
||||
import OpenAILogo from "@/components/logo/openai-logo";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { useDebouncedValue } from "@/lib/debounce";
|
||||
import type { OnboardingVariables } from "../../api/mutations/useOnboardingMutation";
|
||||
import { useGetOpenAIModelsQuery } from "../../api/queries/useGetModelsQuery";
|
||||
|
|
@ -11,121 +11,114 @@ import { useUpdateSettings } from "../hooks/useUpdateSettings";
|
|||
import { AdvancedOnboarding } from "./advanced";
|
||||
|
||||
export function OpenAIOnboarding({
|
||||
setSettings,
|
||||
sampleDataset,
|
||||
setSampleDataset,
|
||||
setSettings,
|
||||
sampleDataset,
|
||||
setSampleDataset,
|
||||
}: {
|
||||
setSettings: (settings: OnboardingVariables) => void;
|
||||
sampleDataset: boolean;
|
||||
setSampleDataset: (dataset: boolean) => void;
|
||||
setSettings: (settings: OnboardingVariables) => void;
|
||||
sampleDataset: boolean;
|
||||
setSampleDataset: (dataset: boolean) => void;
|
||||
}) {
|
||||
const [apiKey, setApiKey] = useState("");
|
||||
const [getFromEnv, setGetFromEnv] = useState(true);
|
||||
const debouncedApiKey = useDebouncedValue(apiKey, 500);
|
||||
const [apiKey, setApiKey] = useState("");
|
||||
const [getFromEnv, setGetFromEnv] = useState(true);
|
||||
const debouncedApiKey = useDebouncedValue(apiKey, 500);
|
||||
|
||||
// Fetch models from API when API key is provided
|
||||
const {
|
||||
data: modelsData,
|
||||
isLoading: isLoadingModels,
|
||||
error: modelsError,
|
||||
} = useGetOpenAIModelsQuery(
|
||||
getFromEnv
|
||||
? { apiKey: "" }
|
||||
: debouncedApiKey
|
||||
? { apiKey: debouncedApiKey }
|
||||
: undefined,
|
||||
{ enabled: debouncedApiKey !== "" || getFromEnv },
|
||||
);
|
||||
// Use custom hook for model selection logic
|
||||
const {
|
||||
languageModel,
|
||||
embeddingModel,
|
||||
setLanguageModel,
|
||||
setEmbeddingModel,
|
||||
languageModels,
|
||||
embeddingModels,
|
||||
} = useModelSelection(modelsData);
|
||||
const handleSampleDatasetChange = (dataset: boolean) => {
|
||||
setSampleDataset(dataset);
|
||||
};
|
||||
// Fetch models from API when API key is provided
|
||||
const {
|
||||
data: modelsData,
|
||||
isLoading: isLoadingModels,
|
||||
error: modelsError,
|
||||
} = useGetOpenAIModelsQuery(
|
||||
getFromEnv
|
||||
? { apiKey: "" }
|
||||
: debouncedApiKey
|
||||
? { apiKey: debouncedApiKey }
|
||||
: undefined,
|
||||
{ enabled: debouncedApiKey !== "" || getFromEnv },
|
||||
);
|
||||
// Use custom hook for model selection logic
|
||||
const {
|
||||
languageModel,
|
||||
embeddingModel,
|
||||
setLanguageModel,
|
||||
setEmbeddingModel,
|
||||
languageModels,
|
||||
embeddingModels,
|
||||
} = useModelSelection(modelsData);
|
||||
const handleSampleDatasetChange = (dataset: boolean) => {
|
||||
setSampleDataset(dataset);
|
||||
};
|
||||
|
||||
const handleGetFromEnvChange = (fromEnv: boolean) => {
|
||||
setGetFromEnv(fromEnv);
|
||||
if (fromEnv) {
|
||||
setApiKey("");
|
||||
}
|
||||
setLanguageModel("");
|
||||
setEmbeddingModel("");
|
||||
};
|
||||
const handleGetFromEnvChange = (fromEnv: boolean) => {
|
||||
setGetFromEnv(fromEnv);
|
||||
if (fromEnv) {
|
||||
setApiKey("");
|
||||
}
|
||||
setLanguageModel("");
|
||||
setEmbeddingModel("");
|
||||
};
|
||||
|
||||
// Update settings when values change
|
||||
useUpdateSettings(
|
||||
"openai",
|
||||
{
|
||||
apiKey,
|
||||
languageModel,
|
||||
embeddingModel,
|
||||
},
|
||||
setSettings,
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<div className="space-y-5">
|
||||
<LabelWrapper
|
||||
label="Use environment OpenAI API key"
|
||||
id="get-api-key"
|
||||
helperText={
|
||||
<>
|
||||
Reuse the key from your environment config.
|
||||
<br />
|
||||
Uncheck to enter a different key.
|
||||
</>
|
||||
}
|
||||
flex
|
||||
start
|
||||
>
|
||||
<Checkbox
|
||||
checked={getFromEnv}
|
||||
onCheckedChange={handleGetFromEnvChange}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
{!getFromEnv && (
|
||||
<div className="space-y-1">
|
||||
<LabelInput
|
||||
label="OpenAI API key"
|
||||
helperText="The API key for your OpenAI account."
|
||||
className={modelsError ? "!border-destructive" : ""}
|
||||
id="api-key"
|
||||
type="password"
|
||||
required
|
||||
placeholder="sk-..."
|
||||
value={apiKey}
|
||||
onChange={(e) => setApiKey(e.target.value)}
|
||||
/>
|
||||
{isLoadingModels && (
|
||||
<p className="text-mmd text-muted-foreground">
|
||||
Validating API key...
|
||||
</p>
|
||||
)}
|
||||
{modelsError && (
|
||||
<p className="text-mmd text-destructive">
|
||||
Invalid OpenAI API key. Verify or replace the key.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<AdvancedOnboarding
|
||||
icon={<OpenAILogo className="w-4 h-4" />}
|
||||
languageModels={languageModels}
|
||||
embeddingModels={embeddingModels}
|
||||
languageModel={languageModel}
|
||||
embeddingModel={embeddingModel}
|
||||
sampleDataset={sampleDataset}
|
||||
setLanguageModel={setLanguageModel}
|
||||
setSampleDataset={handleSampleDatasetChange}
|
||||
setEmbeddingModel={setEmbeddingModel}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
// Update settings when values change
|
||||
useUpdateSettings(
|
||||
"openai",
|
||||
{
|
||||
apiKey,
|
||||
languageModel,
|
||||
embeddingModel,
|
||||
},
|
||||
setSettings,
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<div className="space-y-5">
|
||||
<LabelWrapper
|
||||
label="Use environment OpenAI API key"
|
||||
id="get-api-key"
|
||||
description="Reuse the key from your environment config. Turn off to enter a different key."
|
||||
flex
|
||||
>
|
||||
<Switch
|
||||
checked={getFromEnv}
|
||||
onCheckedChange={handleGetFromEnvChange}
|
||||
/>
|
||||
</LabelWrapper>
|
||||
{!getFromEnv && (
|
||||
<div className="space-y-1">
|
||||
<LabelInput
|
||||
label="OpenAI API key"
|
||||
helperText="The API key for your OpenAI account."
|
||||
className={modelsError ? "!border-destructive" : ""}
|
||||
id="api-key"
|
||||
type="password"
|
||||
required
|
||||
placeholder="sk-..."
|
||||
value={apiKey}
|
||||
onChange={(e) => setApiKey(e.target.value)}
|
||||
/>
|
||||
{isLoadingModels && (
|
||||
<p className="text-mmd text-muted-foreground">
|
||||
Validating API key...
|
||||
</p>
|
||||
)}
|
||||
{modelsError && (
|
||||
<p className="text-mmd text-destructive">
|
||||
Invalid OpenAI API key. Verify or replace the key.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<AdvancedOnboarding
|
||||
icon={<OpenAILogo className="w-4 h-4" />}
|
||||
languageModels={languageModels}
|
||||
embeddingModels={embeddingModels}
|
||||
languageModel={languageModel}
|
||||
embeddingModel={embeddingModel}
|
||||
sampleDataset={sampleDataset}
|
||||
setLanguageModel={setLanguageModel}
|
||||
setSampleDataset={handleSampleDatasetChange}
|
||||
setEmbeddingModel={setEmbeddingModel}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ function OnboardingPage() {
|
|||
// Mutations
|
||||
const onboardingMutation = useOnboardingMutation({
|
||||
onSuccess: (data) => {
|
||||
toast.success("Onboarding completed successfully!");
|
||||
console.log("Onboarding completed successfully", data);
|
||||
router.push(redirect);
|
||||
},
|
||||
|
|
@ -137,7 +136,7 @@ function OnboardingPage() {
|
|||
Connect a model provider
|
||||
</h1>
|
||||
</div>
|
||||
<Card className="w-full max-w-[580px]">
|
||||
<Card className="w-full max-w-[600px]">
|
||||
<Tabs
|
||||
defaultValue={modelProvider}
|
||||
onValueChange={handleSetModelProvider}
|
||||
|
|
@ -150,7 +149,7 @@ function OnboardingPage() {
|
|||
</TabsTrigger>
|
||||
<TabsTrigger value="watsonx">
|
||||
<IBMLogo className="w-4 h-4" />
|
||||
IBM
|
||||
IBM watsonx.ai
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="ollama">
|
||||
<OllamaLogo className="w-4 h-4" />
|
||||
|
|
@ -192,7 +191,7 @@ function OnboardingPage() {
|
|||
disabled={!isComplete}
|
||||
loading={onboardingMutation.isPending}
|
||||
>
|
||||
Complete
|
||||
<span className="select-none">Complete</span>
|
||||
</Button>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue