mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-11 03:38:38 +00:00
fix(ui): wrap selected models in model picker instead of single responsive row
This commit is contained in:
parent
49ca04d8c3
commit
a66e4b247d
3 changed files with 19 additions and 50 deletions
|
|
@ -37,3 +37,8 @@ body {
|
|||
.custom-border {
|
||||
border: 1px solid var(--neutral-border);
|
||||
}
|
||||
|
||||
.model-select-multi .ant-select-selector {
|
||||
max-height: 132px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,21 +33,20 @@ vi.mock("antd", async (importOriginal) => {
|
|||
"data-testid": dataTestId,
|
||||
allowClear,
|
||||
maxTagCount,
|
||||
maxTagPlaceholder,
|
||||
mode,
|
||||
className,
|
||||
...props
|
||||
}: any) => {
|
||||
// Simulate maxTagCount responsive behavior - if value length > 5, call maxTagPlaceholder
|
||||
const shouldShowPlaceholder = maxTagCount === "responsive" && Array.isArray(value) && value.length > 5;
|
||||
const visibleValues = shouldShowPlaceholder ? value.slice(0, 5) : value;
|
||||
const omittedValues = shouldShowPlaceholder ? value.slice(5).map((v: string) => ({ value: v, label: v })) : [];
|
||||
|
||||
return (
|
||||
<div data-testid={dataTestId || "model-select"}>
|
||||
<div
|
||||
data-testid={dataTestId || "model-select"}
|
||||
data-classname={className}
|
||||
data-max-tag-count={maxTagCount ?? ""}
|
||||
>
|
||||
<select
|
||||
multiple={mode === "multiple"}
|
||||
role="listbox"
|
||||
value={visibleValues}
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
const selectedValues = Array.from(e.target.selectedOptions, (option) => option.value);
|
||||
onChange(mode === "multiple" ? selectedValues : selectedValues[0]);
|
||||
|
|
@ -67,16 +66,12 @@ vi.mock("antd", async (importOriginal) => {
|
|||
</optgroup>
|
||||
))}
|
||||
</select>
|
||||
{shouldShowPlaceholder && maxTagPlaceholder && (
|
||||
<div data-testid="max-tag-placeholder">{maxTagPlaceholder(omittedValues)}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
Skeleton: {
|
||||
Input: ({ active, block }: any) => <div data-testid="skeleton-input" data-active={active} data-block={block} />,
|
||||
},
|
||||
Tooltip: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -546,36 +541,13 @@ describe("ModelSelect", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("should render maxTagPlaceholder when many items are selected", async () => {
|
||||
// Create many models to trigger maxTagCount responsive behavior
|
||||
const manyModels: ProxyModel[] = Array.from({ length: 20 }, (_, i) => ({
|
||||
id: `model-${i}`,
|
||||
object: "model",
|
||||
created: 1234567890,
|
||||
owned_by: "test",
|
||||
}));
|
||||
|
||||
mockUseAllProxyModels.mockReturnValue({
|
||||
data: { data: manyModels },
|
||||
isLoading: false,
|
||||
} as any);
|
||||
|
||||
const selectedValues = manyModels.slice(0, 10).map((m) => m.id);
|
||||
|
||||
it("wraps selected tags instead of collapsing them onto a single responsive row", async () => {
|
||||
renderWithProviders(
|
||||
<ModelSelect
|
||||
onChange={mockOnChange}
|
||||
value={selectedValues}
|
||||
context="user"
|
||||
options={{ showAllProxyModelsOverride: true }}
|
||||
/>,
|
||||
<ModelSelect onChange={mockOnChange} context="user" options={{ showAllProxyModelsOverride: true }} />,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId("model-select")).toBeInTheDocument();
|
||||
// Verify maxTagPlaceholder is rendered with omitted values
|
||||
expect(screen.getByTestId("max-tag-placeholder")).toBeInTheDocument();
|
||||
expect(screen.getByText(/\+5 more/)).toBeInTheDocument();
|
||||
});
|
||||
const select = await screen.findByTestId("model-select");
|
||||
expect(select).toHaveAttribute("data-classname", "model-select-multi");
|
||||
expect(select.getAttribute("data-max-tag-count")).toBe("");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { ProxyModel, useAllProxyModels } from "@/app/(dashboard)/hooks/models/us
|
|||
import { useOrganization } from "@/app/(dashboard)/hooks/organizations/useOrganizations";
|
||||
import { useTeam } from "@/app/(dashboard)/hooks/teams/useTeams";
|
||||
import { useCurrentUser } from "@/app/(dashboard)/hooks/users/useCurrentUser";
|
||||
import { Select, Skeleton, Tooltip, type SelectProps } from "antd";
|
||||
import { Select, Skeleton, type SelectProps } from "antd";
|
||||
import { Organization, Team } from "../networking";
|
||||
import { splitWildcardModels } from "./modelUtils";
|
||||
|
||||
|
|
@ -208,15 +208,7 @@ export const ModelSelect = (props: ModelSelectProps) => {
|
|||
mode="multiple"
|
||||
placeholder="Select Models"
|
||||
allowClear
|
||||
maxTagCount="responsive"
|
||||
maxTagPlaceholder={(omittedValues) => (
|
||||
<Tooltip
|
||||
styles={{ root: { pointerEvents: "none" } }}
|
||||
title={omittedValues.map(({ value }) => value).join(", ")}
|
||||
>
|
||||
<span>+{omittedValues.length} more</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
className="model-select-multi"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue