diff --git a/ui/app/_fallbacks/enterprise/components/prompt-deployments/promptDeploymentView.tsx b/ui/app/_fallbacks/enterprise/components/prompt-deployments/promptDeploymentView.tsx index 628e44439a..62b121798a 100644 --- a/ui/app/_fallbacks/enterprise/components/prompt-deployments/promptDeploymentView.tsx +++ b/ui/app/_fallbacks/enterprise/components/prompt-deployments/promptDeploymentView.tsx @@ -1,7 +1,7 @@ import { Router } from "lucide-react"; import ContactUsView from "../views/contactUsView"; -export default function PromptDeploymentView() { +export default function PromptDeploymentView(_props?: { omitTitle?: boolean }) { return (
+ + Deployments + + + + + + ); +} diff --git a/ui/app/workspace/routing-rules/views/routingRuleSheet.tsx b/ui/app/workspace/routing-rules/views/routingRuleSheet.tsx index b4786b0764..0cd7bc055f 100644 --- a/ui/app/workspace/routing-rules/views/routingRuleSheet.tsx +++ b/ui/app/workspace/routing-rules/views/routingRuleSheet.tsx @@ -3,36 +3,54 @@ * Create/Edit form for routing rules */ -import { useState, useEffect, useCallback } from "react"; -import { useForm } from "react-hook-form"; -import { RuleGroupType } from "react-querybuilder"; -import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@/components/ui/sheet"; +"use client"; + import { Button } from "@/components/ui/button"; -import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; -import { Textarea } from "@/components/ui/textarea"; +import { Label } from "@/components/ui/label"; +import { ModelMultiselect } from "@/components/ui/modelMultiselect"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { Separator } from "@/components/ui/separator"; +import { + Sheet, + SheetContent, + SheetDescription, + SheetHeader, + SheetTitle, +} from "@/components/ui/sheet"; import { Switch } from "@/components/ui/switch"; -import { ModelMultiselect } from "@/components/ui/modelMultiselect"; -import { X, Save, Plus, Trash2 } from "lucide-react"; +import { Textarea } from "@/components/ui/textarea"; +import { ProviderIconType, RenderProviderIcon } from "@/lib/constants/icons"; +import { getProviderLabel } from "@/lib/constants/logs"; +import { getErrorMessage } from "@/lib/store"; +import { + useGetCustomersQuery, + useGetTeamsQuery, + useGetVirtualKeysQuery, +} from "@/lib/store/apis/governanceApi"; +import { useGetAllKeysQuery, useGetProvidersQuery } from "@/lib/store/apis/providersApi"; +import { + useCreateRoutingRuleMutation, + useGetRoutingRulesQuery, + useUpdateRoutingRuleMutation, +} from "@/lib/store/apis/routingRulesApi"; import { - RoutingRule, - RoutingRuleFormData, - RoutingTargetFormData, DEFAULT_ROUTING_RULE_FORM_DATA, DEFAULT_ROUTING_TARGET, ROUTING_RULE_SCOPES, + RoutingRule, + RoutingRuleFormData, + RoutingTargetFormData, } from "@/lib/types/routingRules"; -import { useCreateRoutingRuleMutation, useUpdateRoutingRuleMutation, useGetRoutingRulesQuery } from "@/lib/store/apis/routingRulesApi"; -import { useGetVirtualKeysQuery, useGetTeamsQuery, useGetCustomersQuery } from "@/lib/store/apis/governanceApi"; -import { useGetProvidersQuery, useGetAllKeysQuery } from "@/lib/store/apis/providersApi"; +import { + validateRateLimitAndBudgetRules, + validateRoutingRules +} from "@/lib/utils/celConverterRouting"; +import { Plus, Save, Trash2, X } from "lucide-react"; +import { useCallback, useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; +import { RuleGroupType } from "react-querybuilder"; import { toast } from "sonner"; -import { Suspense, lazy } from "react"; -import { ProviderIconType, RenderProviderIcon } from "@/lib/constants/icons"; -import { getProviderLabel } from "@/lib/constants/logs"; -import { Separator } from "@/components/ui/separator"; -import { getErrorMessage } from "@/lib/store"; -import { validateRoutingRules, validateRateLimitAndBudgetRules } from "@/lib/utils/celConverterRouting"; interface RoutingRuleDialogProps { open: boolean; diff --git a/ui/components/prompts/fragments/settingsPanel.tsx b/ui/components/prompts/fragments/settingsPanel.tsx index c1b06433ba..17921fee8f 100644 --- a/ui/components/prompts/fragments/settingsPanel.tsx +++ b/ui/components/prompts/fragments/settingsPanel.tsx @@ -1,8 +1,8 @@ +import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"; import { ComboboxSelect } from "@/components/ui/combobox"; import ModelParameters from "@/components/ui/custom/modelParameters"; import { Label } from "@/components/ui/label"; import { ModelMultiselect } from "@/components/ui/modelMultiselect"; -import { ScrollArea } from "@/components/ui/scrollArea"; import { Separator } from "@/components/ui/separator"; import { Skeleton } from "@/components/ui/skeleton"; import { getProviderLabel } from "@/lib/constants/logs"; @@ -10,8 +10,9 @@ import { useGetVirtualKeysQuery } from "@/lib/store"; import { useGetAllKeysQuery, useGetProvidersQuery } from "@/lib/store/apis/providersApi"; import { ModelProviderName } from "@/lib/types/config"; import { ModelParams } from "@/lib/types/prompts"; -import PromptDeploymentView from "@enterprise/components/prompt-deployments/promptDeploymentView"; -import { useCallback, useMemo } from "react"; +import { cn } from "@/lib/utils"; +import { PromptDeploymentsAccordionItem } from "@enterprise/components/prompt-deployments/promptDeploymentsAccordionItem"; +import { useCallback, useMemo, useState } from "react"; import { ApiKeySelectorView } from "../components/apiKeySelectorView"; import { VariablesTableView } from "../components/variablesTableView"; import { usePromptContext } from "../context"; @@ -26,6 +27,9 @@ export function SettingsPanel() { setModelParams: onModelParamsChange, apiKeyId, setApiKeyId, + variables, + setVariables, + selectedPromptId, } = usePromptContext(); const onProviderChange = useCallback( @@ -113,6 +117,11 @@ export function SettingsPanel() { [onModelParamsChange], ); + const hasModel = Boolean(model); + + type SettingsSection = "parameters" | "deployments"; + const [openSection, setOpenSection] = useState("parameters"); + if (isInitialLoading) { return (
@@ -131,66 +140,98 @@ export function SettingsPanel() { } return ( -
- -
-
- - v && onProviderChange(v)} - placeholder="Select provider" - hideClear - /> -
- -
- - 0 ? filterKeys : undefined} - vks={filterVks} - value={model} - onChange={(v) => onModelChange(v)} - isSingleSelect - unfiltered - placeholder={!provider ? "Select a provider first" : "Select model"} - disabled={!provider} - /> -
- - {(providerKeys.length > 0 || providerVirtualKeys.length > 0) && !!provider && ( - onApiKeyIdChange(v ?? "__auto__")} - disabled={!provider} - /> - )} - - {Object.keys(variables).length > 0 && ( - <> - - - - )} - - {model && ( - <> - - -
- - +
+
+ { + if (v === "parameters" || v === "deployments") { + setOpenSection(v); + } else { + setOpenSection(undefined); + } + }} + className="flex min-h-0 flex-1 flex-col" + > + + + Configuration + + +
+
+ + v && onProviderChange(v)} + placeholder="Select provider" + hideClear + /> +
+ +
+ + 0 ? filterKeys : undefined} + vks={filterVks} + value={model} + onChange={(v) => onModelChange(v)} + isSingleSelect + placeholder={!provider ? "Select a provider first" : "Select model"} + disabled={!provider} + unfiltered={true} + /> +
+ + {(providerKeys.length > 0 || providerVirtualKeys.length > 0) && !!provider && ( + onApiKeyIdChange(v ?? "__auto__")} + disabled={!provider} + /> + )} + + {Object.keys(variables).length > 0 && ( + <> + + + + )} + + {hasModel && ( + <> + +
+ +
+ + )}
- - )} - - -
- + + + {selectedPromptId && } + +
); } \ No newline at end of file diff --git a/ui/components/ui/accordion.tsx b/ui/components/ui/accordion.tsx index b6a0c9f886..65360d9211 100644 --- a/ui/components/ui/accordion.tsx +++ b/ui/components/ui/accordion.tsx @@ -14,27 +14,38 @@ function AccordionItem({ className, ...props }: React.ComponentProps) { return ( - + svg]:rotate-180", + "focus-visible:border-ring focus-visible:ring-ring/50 flex w-full min-w-0 flex-1 items-center justify-between gap-2 rounded-sm py-4 text-left text-sm font-medium transition-colors outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180", className, )} {...props} > {children} - + ); } -function AccordionContent({ className, children, ...props }: React.ComponentProps) { +function AccordionContent({ + className, + containerClassName, + children, + ...props +}: React.ComponentProps & { + /** Classes merged onto the Radix content wrapper (outer). `className` still targets the inner div. */ + containerClassName?: string; +}) { return (
{children}
@@ -42,4 +53,4 @@ function AccordionContent({ className, children, ...props }: React.ComponentProp ); } -export { Accordion, AccordionContent, AccordionItem, AccordionTrigger }; \ No newline at end of file +export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };