mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-24 00:52:24 +00:00
fix(ui): derive team metadata schema labels from live key values
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
3089f2acc6
commit
3fb02ee537
2 changed files with 40 additions and 1 deletions
|
|
@ -307,6 +307,28 @@ describe("MetadataKeyValueFields with a declared schema", () => {
|
|||
expect(screen.getByTestId("metadata-schema-label")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should keep duplicate keys in a free-form row", async () => {
|
||||
const user = userEvent.setup();
|
||||
const onFinish = vi.fn();
|
||||
render(<Harness onFinish={onFinish} schemaFields={[{ key: "cost_center", label: "Cost Center" }]} />);
|
||||
|
||||
expect(await screen.findByTestId("metadata-schema-label")).toHaveTextContent("Cost Center");
|
||||
await user.click(screen.getByRole("button", { name: /add key-value pair/i }));
|
||||
fireEvent.change(screen.getByPlaceholderText("Key"), { target: { value: "cost_center" } });
|
||||
|
||||
expect(screen.getAllByPlaceholderText("Key")).toHaveLength(1);
|
||||
expect(screen.getByPlaceholderText("Key")).toHaveValue("cost_center");
|
||||
expect(screen.getAllByLabelText("Remove key-value pair")).toHaveLength(1);
|
||||
expect(screen.getAllByTestId("metadata-schema-label")).toHaveLength(1);
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Save" }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText("Duplicate key")).toBeInTheDocument();
|
||||
});
|
||||
expect(onFinish).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should show a skeleton instead of the editor while the schema is loading", () => {
|
||||
render(<Harness onFinish={vi.fn()} schemaLoading />);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { CircleMinus, Plus } from "lucide-react";
|
|||
import React, { useEffect, useRef } from "react";
|
||||
import {
|
||||
useFieldArray,
|
||||
useWatch,
|
||||
type Control,
|
||||
type FieldArrayPath,
|
||||
type FieldPath,
|
||||
|
|
@ -87,6 +88,10 @@ const MetadataKeyValueFields = <TFieldValues extends FieldValues>({
|
|||
schemaLoading = false,
|
||||
}: MetadataKeyValueFieldsProps<TFieldValues>) => {
|
||||
const { fields, append, remove } = useFieldArray({ control, name });
|
||||
const watchedPairs = (useWatch({ control, name: name as unknown as FieldPath<TFieldValues> }) ?? []) as readonly (
|
||||
| Partial<MetadataPair>
|
||||
| undefined
|
||||
)[];
|
||||
const seededRef = useRef(false);
|
||||
const schemaLabelsByKey = new Map(schemaFields.map((field) => [field.key, field.label || field.key]));
|
||||
|
||||
|
|
@ -114,10 +119,22 @@ const MetadataKeyValueFields = <TFieldValues extends FieldValues>({
|
|||
);
|
||||
}
|
||||
|
||||
const getSchemaLabel = (index: number): string | undefined => {
|
||||
const key = watchedPairs[index]?.key;
|
||||
if (
|
||||
key === undefined ||
|
||||
!schemaLabelsByKey.has(key) ||
|
||||
watchedPairs.findIndex((pair) => pair?.key === key) !== index
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
return schemaLabelsByKey.get(key);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{fields.map((field, index) => {
|
||||
const schemaLabel = schemaLabelsByKey.get((field as unknown as Partial<MetadataPair>).key ?? "");
|
||||
const schemaLabel = getSchemaLabel(index);
|
||||
return (
|
||||
<div key={field.id} className="mb-2 flex items-start gap-2">
|
||||
{schemaLabel === undefined ? (
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue