Deactivate delete button on model table for config models (#16787)

This commit is contained in:
yuneng-jiang 2025-11-18 19:51:59 -08:00 • committed by GitHub
parent d0e806d1b3
commit 137c6b03f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 81 additions and 16 deletions

View file

@ -1,9 +1,9 @@
import * as useAuthorizedModule from "@/app/(dashboard)/hooks/useAuthorized";
import * as useTeamsModule from "@/app/(dashboard)/hooks/useTeams";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, it, expect, beforeAll, vi, beforeEach } from "vitest";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import AllModelsTab from "./AllModelsTab";
import * as useTeamsModule from "@/app/(dashboard)/hooks/useTeams";
import * as useAuthorizedModule from "@/app/(dashboard)/hooks/useAuthorized";
// Mock window.matchMedia for Ant Design components
beforeAll(() => {
@ -248,4 +248,62 @@ describe("AllModelsTab", () => {
expect(screen.getByText("Showing 1 - 1 of 1 results")).toBeInTheDocument();
});
});
it("should show disabled delete icon for config models", async () => {
// Mock useTeams hook
vi.spyOn(useTeamsModule, "default").mockReturnValue({
teams: [],
setTeams: vi.fn(),
});
const modelData = {
data: [
{
model_name: "gpt-4-config",
litellm_model_name: "gpt-4-config",
provider: "openai",
model_info: {
id: "model-config-1",
db_model: false, // Config model (no db_model)
direct_access: true,
access_via_team_ids: [],
access_groups: [],
created_by: "user-123",
created_at: "2024-01-01",
updated_at: "2024-01-01",
},
},
{
model_name: "gpt-4-db",
litellm_model_name: "gpt-4-db",
provider: "openai",
model_info: {
id: "model-db-1",
db_model: true, // DB model
direct_access: true,
access_via_team_ids: [],
access_groups: [],
created_by: "user-123",
created_at: "2024-01-01",
updated_at: "2024-01-01",
},
},
],
};
const { container } = render(<AllModelsTab {...defaultProps} modelData={modelData} />);
await waitFor(() => {
expect(screen.getByText(/Showing \d+ - \d+ of 2 results/)).toBeInTheDocument();
});
const disabledIcons = container.querySelectorAll(".opacity-50.cursor-not-allowed");
expect(disabledIcons.length).toBeGreaterThan(0);
const configModelIcon = Array.from(disabledIcons).find((icon) => {
const parent = icon.closest('[class*="actions"], [class*="flex items-center justify-end"]');
return parent !== null;
});
expect(configModelIcon).toBeTruthy();
});
});

View file

@ -300,21 +300,28 @@ export const columns = (
cell: ({ row }) => {
const model = row.original;
const canEditModel = userRole === "Admin" || model.model_info?.created_by === userID;
const isConfigModel = !model.model_info?.db_model;
return (
<div className="flex items-center justify-end gap-2 pr-4">
<Tooltip title="Delete model">
<Icon
icon={TrashIcon}
size="sm"
onClick={() => {
if (canEditModel) {
setSelectedModelId(model.model_info.id);
setEditModel(false);
}
}}
className={!canEditModel ? "opacity-50 cursor-not-allowed" : "cursor-pointer hover:text-red-600"}
/>
</Tooltip>
{isConfigModel ? (
<Tooltip title="Config model cannot be deleted on the dashboard. Please delete it from the config file.">
<Icon icon={TrashIcon} size="sm" className="opacity-50 cursor-not-allowed" />
</Tooltip>
) : (
<Tooltip title="Delete model">
<Icon
icon={TrashIcon}
size="sm"
onClick={() => {
if (canEditModel) {
setSelectedModelId(model.model_info.id);
setEditModel(false);
}
}}
className={!canEditModel ? "opacity-50 cursor-not-allowed" : "cursor-pointer hover:text-red-600"}
/>
</Tooltip>
)}
</div>
);
},