mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-19 00:01:29 +00:00
fix(ui): show the saved team in read mode before the model query refetches
Read mode built the Team display from the react-query snapshot while save only wrote localModelData, so the old team flashed until the parent's invalidation refetched. Read the team from localModelData like the neighbouring fields and look up its alias from the local team id. The regression test also waits for the Select trigger to report expanded before clicking an option, because Base UI opens the popup asynchronously and keeps the closed popup mounted, which made back-to-back option clicks flaky.
This commit is contained in:
parent
790c3ab71b
commit
5156dbc67f
3 changed files with 41 additions and 7 deletions
|
|
@ -818,8 +818,8 @@ const ModelInfoEditForm: React.FC<ModelInfoEditFormProps> = ({
|
|||
) : (
|
||||
<Display>
|
||||
{teamAlias
|
||||
? `${teamAlias} (${modelData.model_info.team_id})`
|
||||
: modelData.model_info.team_id || "Not Set"}
|
||||
? `${teamAlias} (${localModelData.model_info?.team_id})`
|
||||
: localModelData.model_info?.team_id || "Not Set"}
|
||||
</Display>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1509,6 +1509,11 @@ describe("ModelInfoView", () => {
|
|||
expect(await screen.findByRole("button", { name: /save changes/i })).toBeInTheDocument();
|
||||
};
|
||||
|
||||
const openSelect = async (user: ReturnType<typeof userEvent.setup>, triggerText: string) => {
|
||||
await user.click(await screen.findByText(triggerText));
|
||||
await screen.findByRole("combobox", { expanded: true });
|
||||
};
|
||||
|
||||
const save = async (user: ReturnType<typeof userEvent.setup>) => {
|
||||
await user.click(screen.getByRole("button", { name: /save changes/i }));
|
||||
await waitFor(() => expect(mockModelPatchUpdateCall).toHaveBeenCalled());
|
||||
|
|
@ -1660,7 +1665,7 @@ describe("ModelInfoView", () => {
|
|||
const user = userEvent.setup();
|
||||
await enterEditMode(user);
|
||||
|
||||
await user.click(screen.getByText("alpha (team-1)"));
|
||||
await openSelect(user, "alpha (team-1)");
|
||||
await user.click(await screen.findByText("beta (team-2)"));
|
||||
|
||||
const payload = await save(user);
|
||||
|
|
@ -1668,6 +1673,33 @@ describe("ModelInfoView", () => {
|
|||
expect(payload.model_info.team_id).toBe("team-2");
|
||||
});
|
||||
|
||||
it("shows the picked team in read mode right after saving", async () => {
|
||||
mockUseTeams.mockReturnValue({
|
||||
data: [
|
||||
{ team_id: "team-1", team_alias: "alpha" },
|
||||
{ team_id: "team-2", team_alias: "beta" },
|
||||
],
|
||||
isLoading: false,
|
||||
error: null,
|
||||
});
|
||||
const teamModel = {
|
||||
...defaultModelData,
|
||||
model_info: { ...defaultModelData.model_info, team_id: "team-1" },
|
||||
};
|
||||
mockUseModelsInfo.mockReturnValue({ data: { data: [teamModel] }, isLoading: false, error: null });
|
||||
mockModelInfoV1Call.mockResolvedValue({ data: [teamModel] });
|
||||
const user = userEvent.setup();
|
||||
await enterEditMode(user);
|
||||
|
||||
await openSelect(user, "alpha (team-1)");
|
||||
await user.click(await screen.findByText("beta (team-2)"));
|
||||
await save(user);
|
||||
|
||||
expect(await screen.findByRole("button", { name: /edit settings/i })).toBeInTheDocument();
|
||||
expect(screen.getByText("beta (team-2)")).toBeInTheDocument();
|
||||
expect(screen.queryByText("alpha (team-1)")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows the Team ID placeholder for a model with no team", async () => {
|
||||
mockUseTeams.mockReturnValue({
|
||||
data: [{ team_id: "team-1", team_alias: "alpha" }],
|
||||
|
|
@ -1734,7 +1766,7 @@ describe("ModelInfoView", () => {
|
|||
const user = userEvent.setup();
|
||||
await enterEditMode(user);
|
||||
|
||||
await user.click(await screen.findByText("selected-credential"));
|
||||
await openSelect(user, "selected-credential");
|
||||
await user.click(await screen.findByText("other-credential"));
|
||||
|
||||
const payload = await save(user);
|
||||
|
|
@ -1770,7 +1802,7 @@ describe("ModelInfoView", () => {
|
|||
const user = userEvent.setup();
|
||||
await enterEditMode(user);
|
||||
|
||||
await user.click(screen.getByText("Select existing health check model"));
|
||||
await openSelect(user, "Select existing health check model");
|
||||
await user.click(await screen.findByText("openai/gpt-4o"));
|
||||
|
||||
const payload = await save(user);
|
||||
|
|
|
|||
|
|
@ -115,7 +115,9 @@ export default function ModelInfoView({
|
|||
// Keep modelData variable name for backwards compatibility
|
||||
const modelData = transformedModelData;
|
||||
|
||||
const teamAlias = teams?.find((team) => team.team_id === modelData?.model_info?.team_id)?.team_alias || null;
|
||||
const aliasForTeam = (teamId: string | null | undefined): string | null =>
|
||||
teams?.find((team) => team.team_id === teamId)?.team_alias || null;
|
||||
const teamAlias = aliasForTeam(modelData?.model_info?.team_id);
|
||||
const rawModelInfoEntries = Object.entries(modelData?.model_info ?? {}).flatMap((entry) =>
|
||||
entry[0] === "team_id" && teamAlias ? [entry, ["team_alias", teamAlias]] : [entry],
|
||||
);
|
||||
|
|
@ -724,7 +726,7 @@ export default function ModelInfoView({
|
|||
<ModelInfoEditForm
|
||||
localModelData={localModelData}
|
||||
modelData={modelData}
|
||||
teamAlias={teamAlias}
|
||||
teamAlias={aliasForTeam(localModelData.model_info?.team_id)}
|
||||
accessToken={accessToken}
|
||||
isEditing={isEditing}
|
||||
isSaving={isSaving}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue