Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions ui/litellm-dashboard/eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@
"count": 1
}
},
"src/components/DefaultUserSettings.tsx": {
"src/app/(dashboard)/users/_components/DefaultUserSettings.tsx": {
"no-restricted-imports": {
"count": 1
}
Expand Down Expand Up @@ -1001,7 +1001,7 @@
"count": 1
}
},
"src/components/edit_user.tsx": {
"src/app/(dashboard)/users/_components/edit_user.tsx": {
"no-restricted-imports": {
"count": 1
}
Expand Down Expand Up @@ -1957,12 +1957,12 @@
"count": 2
}
},
"src/components/user_edit_view.test.tsx": {
"src/app/(dashboard)/users/_components/user_edit_view.test.tsx": {
"react/display-name": {
"count": 1
}
},
"src/components/user_edit_view.tsx": {
"src/app/(dashboard)/users/_components/user_edit_view.tsx": {
"no-restricted-imports": {
"count": 1
},
Expand Down Expand Up @@ -2047,28 +2047,28 @@
"count": 2
}
},
"src/components/view_users.tsx": {
"src/app/(dashboard)/users/_components/view_users.tsx": {
"no-restricted-imports": {
"count": 1
},
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/components/view_users/columns.tsx": {
"src/app/(dashboard)/users/_components/view_users/columns.tsx": {
"max-params": {
"count": 1
},
"no-restricted-imports": {
"count": 1
}
},
"src/components/view_users/table.tsx": {
"src/app/(dashboard)/users/_components/view_users/table.tsx": {
"no-restricted-imports": {
"count": 1
}
},
"src/components/view_users/user_info_view.tsx": {
"src/app/(dashboard)/users/_components/view_users/user_info_view.tsx": {
"no-restricted-imports": {
"count": 1
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi, beforeEach } from "vitest";
import { renderWithProviders, screen, waitFor } from "../../tests/test-utils";
import { renderWithProviders, screen, waitFor } from "../../../../../tests/test-utils";
import BulkEditUserModal from "./BulkEditUsers";
import { userBulkUpdateUserCall, teamBulkMemberAddCall } from "./networking";
import NotificationsManager from "./molecules/notifications_manager";
import { userBulkUpdateUserCall, teamBulkMemberAddCall } from "@/components/networking";
import NotificationsManager from "@/components/molecules/notifications_manager";

vi.mock("./networking", () => ({
vi.mock("@/components/networking", () => ({
userBulkUpdateUserCall: vi.fn(),
teamBulkMemberAddCall: vi.fn(),
}));

vi.mock("./user_edit_view", () => ({
UserEditView: ({ onSubmit, onCancel }: { onSubmit: (values: any) => void; onCancel: () => void }) => (

Check warning on line 14 in ui/litellm-dashboard/src/app/(dashboard)/users/_components/BulkEditUsers.test.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Unexpected any. Specify a different type
<div data-testid="user-edit-view">
<button onClick={() => onSubmit({ user_role: "admin", max_budget: 100 })}>Submit</button>
<button onClick={onCancel}>Cancel</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { useState } from "react";
import { Modal, Typography, Divider, Table, Select, InputNumber, Card, Space, Checkbox } from "antd";
import { userBulkUpdateUserCall, teamBulkMemberAddCall, Member } from "./networking";
import { userBulkUpdateUserCall, teamBulkMemberAddCall, Member } from "@/components/networking";
import { UserEditView } from "./user_edit_view";
import NotificationsManager from "./molecules/notifications_manager";
import NotificationsManager from "@/components/molecules/notifications_manager";
import MessageManager from "@/components/molecules/message_manager";

const { Text, Title } = Typography;
Expand All @@ -10,11 +10,11 @@
interface BulkEditUserModalProps {
open: boolean;
onCancel: () => void;
selectedUsers: any[];

Check warning on line 13 in ui/litellm-dashboard/src/app/(dashboard)/users/_components/BulkEditUsers.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Unexpected any. Specify a different type
possibleUIRoles: Record<string, Record<string, string>> | null;
accessToken: string | null;
onSuccess: () => void;
teams: any[] | null;

Check warning on line 17 in ui/litellm-dashboard/src/app/(dashboard)/users/_components/BulkEditUsers.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Unexpected any. Specify a different type
userRole: string | null;
userModels: string[];
allowAllUsers?: boolean; // Optional flag to enable "all users" mode
Expand Down Expand Up @@ -65,10 +65,10 @@
keys: [],
teams: teams || [],
}),
[teams, open],

Check warning on line 68 in ui/litellm-dashboard/src/app/(dashboard)/users/_components/BulkEditUsers.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

React Hook React.useMemo has an unnecessary dependency: 'open'. Either exclude it or remove the dependency array
);

const handleSubmit = async (formValues: any) => {

Check warning on line 71 in ui/litellm-dashboard/src/app/(dashboard)/users/_components/BulkEditUsers.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Async arrow function has a complexity of 27. Maximum allowed is 20

Check warning on line 71 in ui/litellm-dashboard/src/app/(dashboard)/users/_components/BulkEditUsers.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Unexpected any. Specify a different type
console.log("formValues", formValues);
if (!accessToken) {
NotificationsManager.fromBackend("Access token not found");
Expand All @@ -80,7 +80,7 @@
const userIds = selectedUsers.map((user) => user.user_id);

// Build the update payload - only include fields that have been changed from default/empty values
const updatePayload: any = {};

Check warning on line 83 in ui/litellm-dashboard/src/app/(dashboard)/users/_components/BulkEditUsers.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Unexpected any. Specify a different type

if (formValues.user_role && formValues.user_role !== "") {
updatePayload.user_role = formValues.user_role;
Expand Down Expand Up @@ -126,13 +126,13 @@

// Handle team additions
if (hasTeamAdditions) {
const teamResults: any[] = [];

Check warning on line 129 in ui/litellm-dashboard/src/app/(dashboard)/users/_components/BulkEditUsers.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Unexpected any. Specify a different type

for (const teamId of selectedTeams) {
try {
// Create member objects for bulk add
let members: Member[] | null = null;
if (updateAllUsers) {

Check warning on line 135 in ui/litellm-dashboard/src/app/(dashboard)/users/_components/BulkEditUsers.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Blocks are nested too deeply (5). Maximum allowed is 4
members = null;
} else {
members = selectedUsers.map((user) => ({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { act, fireEvent, render, screen, waitFor } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import DefaultUserSettings from "./DefaultUserSettings";
import * as networking from "./networking";
import * as networking from "@/components/networking";

vi.mock("./networking", () => ({
vi.mock("@/components/networking", () => ({
getInternalUserSettings: vi.fn(),
updateInternalUserSettings: vi.fn(),
modelAvailableCall: vi.fn(),
}));

vi.mock("./common_components/budget_duration_dropdown", () => ({
vi.mock("@/components/common_components/budget_duration_dropdown", () => ({
default: ({ value, onChange }: { value: string | null; onChange: (value: string | null) => void }) => (
<select data-testid="budget-duration" value={value || ""} onChange={(e) => onChange(e.target.value || null)}>
<option value="">Select duration</option>
Expand All @@ -20,7 +20,7 @@ vi.mock("./common_components/budget_duration_dropdown", () => ({
getBudgetDurationLabel: (value: string) => value,
}));

vi.mock("./key_team_helpers/fetch_available_models_team_key", () => ({
vi.mock("@/components/key_team_helpers/fetch_available_models_team_key", () => ({
getModelDisplayName: (model: string) => model,
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
import { Card, Title, Text, Divider, TextInput } from "@tremor/react";
import { Button, Typography, Spin, Switch, Select, InputNumber } from "antd";
import { PlusOutlined, DeleteOutlined } from "@ant-design/icons";
import { getInternalUserSettings, updateInternalUserSettings, modelAvailableCall } from "./networking";
import BudgetDurationDropdown, { getBudgetDurationLabel } from "./common_components/budget_duration_dropdown";
import { getModelDisplayName } from "./key_team_helpers/fetch_available_models_team_key";
import { getInternalUserSettings, updateInternalUserSettings, modelAvailableCall } from "@/components/networking";
import BudgetDurationDropdown, {
getBudgetDurationLabel,
} from "@/components/common_components/budget_duration_dropdown";
import { getModelDisplayName } from "@/components/key_team_helpers/fetch_available_models_team_key";
import { formatNumberWithCommas } from "@/utils/dataUtils";
import NotificationManager from "./molecules/notifications_manager";
import NotificationManager from "@/components/molecules/notifications_manager";

interface DefaultUserSettingsProps {
accessToken: string | null;
Expand All @@ -28,7 +30,7 @@
userRole,
}) => {
const [loading, setLoading] = useState<boolean>(true);
const [settings, setSettings] = useState<any>(null);

Check warning on line 33 in ui/litellm-dashboard/src/app/(dashboard)/users/_components/DefaultUserSettings.tsx

View workflow job for this annotation

GitHub Actions / frontend-lint

Unexpected any. Specify a different type
const [isEditing, setIsEditing] = useState<boolean>(false);
const [editedValues, setEditedValues] = useState<any>({});
const [saving, setSaving] = useState<boolean>(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { TextInput, SelectItem } from "@tremor/react";

import { Button as Button2, Modal, Form, Select as Select2, InputNumber } from "antd";

import NumericalInput from "./shared/numerical_input";
import BudgetDurationDropdown from "./common_components/budget_duration_dropdown";
import NumericalInput from "@/components/shared/numerical_input";
import BudgetDurationDropdown from "@/components/common_components/budget_duration_dropdown";

interface EditUserModalProps {
visible: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as ViewUserDashboard } from "./view_users";
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { cleanup, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "../../tests/test-utils";
import { renderWithProviders } from "../../../../../tests/test-utils";
import { UserEditView } from "./user_edit_view";

vi.mock("./key_team_helpers/fetch_available_models_team_key", () => ({
vi.mock("@/components/key_team_helpers/fetch_available_models_team_key", () => ({
getModelDisplayName: vi.fn((model: string) => model),
}));

vi.mock("../utils/roles", () => ({
vi.mock("@/utils/roles", () => ({
all_admin_roles: ["Admin", "Admin Viewer", "proxy_admin", "proxy_admin_viewer", "org_admin"],
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { InfoCircleOutlined } from "@ant-design/icons";
import { Button, SelectItem, TextInput, Textarea } from "@tremor/react";
import { Checkbox, Form, Select, Tooltip } from "antd";
import React, { useState } from "react";
import { all_admin_roles } from "../utils/roles";
import BudgetDurationDropdown from "./common_components/budget_duration_dropdown";
import { getModelDisplayName } from "./key_team_helpers/fetch_available_models_team_key";
import NumericalInput from "./shared/numerical_input";
import { all_admin_roles } from "@/utils/roles";
import BudgetDurationDropdown from "@/components/common_components/budget_duration_dropdown";
import { getModelDisplayName } from "@/components/key_team_helpers/fetch_available_models_team_key";
import NumericalInput from "@/components/shared/numerical_input";

interface UserEditViewProps {
userData: any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import ViewUserDashboard from "./view_users";

// Mock the networking module
vi.mock("./networking", () => ({
vi.mock("@/components/networking", () => ({
userListCall: vi.fn().mockResolvedValue({
users: [
{
Expand Down Expand Up @@ -45,7 +45,7 @@ vi.mock("./networking", () => ({
}));

// Mock NotificationsManager
vi.mock("./molecules/notifications_manager", () => ({
vi.mock("@/components/molecules/notifications_manager", () => ({
default: {
success: vi.fn(),
fromBackend: vi.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { useEffect, useState } from "react";

import { Button } from "antd";
import BulkEditUserModal from "./BulkEditUsers";
import { CreateUserButton } from "./CreateUserButton";
import { CreateUserButton } from "@/components/CreateUserButton";
import EditUserModal from "./edit_user";
import {
getPossibleUserRoles,
Expand All @@ -12,21 +12,21 @@ import {
userListCall,
UserListResponse,
userUpdateUserCall,
} from "./networking";
import OnboardingModal, { InvitationLink } from "./onboarding_link";
} from "@/components/networking";
import OnboardingModal, { InvitationLink } from "@/components/onboarding_link";

import { updateExistingKeys } from "@/utils/dataUtils";
import { isAdminRole, isProxyAdminRole } from "@/utils/roles";
import { useDebouncedState } from "@tanstack/react-pacer/debouncer";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { Typography } from "antd";
import DeleteResourceModal from "./common_components/DeleteResourceModal";
import NotificationsManager from "./molecules/notifications_manager";
import { modelAvailableCall, userDeleteCall } from "./networking";
import DeleteResourceModal from "@/components/common_components/DeleteResourceModal";
import NotificationsManager from "@/components/molecules/notifications_manager";
import { modelAvailableCall, userDeleteCall } from "@/components/networking";
import DefaultUserSettings from "./DefaultUserSettings";
import { columns } from "./view_users/columns";
import { UserDataTable } from "./view_users/table";
import { UserInfo } from "./view_users/types";
import { UserInfo } from "@/components/networking";
import { Skeleton } from "antd";

const { Text, Title } = Typography;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ColumnDef } from "@tanstack/react-table";
import { Badge, Grid, Icon } from "@tremor/react";
import { Tooltip, Checkbox, Tag } from "antd";
import { UserInfo } from "./types";
import { UserInfo } from "@/components/networking";
import { PencilAltIcon, TrashIcon, InformationCircleIcon, RefreshIcon } from "@heroicons/react/outline";
import { CopyOutlined } from "@ant-design/icons";
import { formatNumberWithCommas, copyToClipboard } from "@/utils/dataUtils";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { act, fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { columns } from "./columns";
import { UserDataTable } from "./table";
import { UserInfo } from "./types";
import { UserInfo } from "@/components/networking";

const defaultFilters = {
email: "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from "react";
import { Table, TableHead, TableHeaderCell, TableBody, TableRow, TableCell, Select, SelectItem } from "@tremor/react";
import { SwitchVerticalIcon, ChevronUpIcon, ChevronDownIcon } from "@heroicons/react/outline";
import { Skeleton } from "antd";
import { UserInfo } from "./types";
import { UserInfo } from "@/components/networking";
import UserInfoView from "./user_info_view";
import { columns as createColumns } from "./columns";
import { FilterInput } from "@/components/common_components/Filters/FilterInput";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const MOCK_USER_DATA_NO_TEAMS = {
teams: [],
};

vi.mock("../networking", () => {
vi.mock("@/components/networking", () => {
return {
userGetInfoV2: (...args: any[]) => mockUserGetInfoV2(...args),
userDeleteCall: vi.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ import {
teamMemberAddCall,
teamMemberDeleteCall,
Member,
} from "../networking";
} from "@/components/networking";
import { Button as AntdButton, Modal, Select as AntdSelect, Form, Tooltip } from "antd";
import { rolesWithWriteAccess } from "../../utils/roles";
import { rolesWithWriteAccess } from "@/utils/roles";
import { UserEditView } from "../user_edit_view";
import OnboardingModal, { InvitationLink } from "../onboarding_link";
import OnboardingModal, { InvitationLink } from "@/components/onboarding_link";
import { formatNumberWithCommas, copyToClipboard as utilCopyToClipboard } from "@/utils/dataUtils";
import { CopyIcon, CheckIcon } from "lucide-react";
import NotificationsManager from "../molecules/notifications_manager";
import { getBudgetDurationLabel } from "../common_components/budget_duration_dropdown";
import DeleteResourceModal from "../common_components/DeleteResourceModal";
import NotificationsManager from "@/components/molecules/notifications_manager";
import { getBudgetDurationLabel } from "@/components/common_components/budget_duration_dropdown";
import DeleteResourceModal from "@/components/common_components/DeleteResourceModal";

interface UserInfoViewProps {
userId: string;
Expand Down
2 changes: 1 addition & 1 deletion ui/litellm-dashboard/src/app/(dashboard)/users/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import ViewUserDashboard from "@/components/view_users";
import { ViewUserDashboard } from "./_components";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import { useTeams } from "@/app/(dashboard)/hooks/teams/useTeams";

Expand Down
18 changes: 16 additions & 2 deletions ui/litellm-dashboard/src/components/networking.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import MessageManager from "@/components/molecules/message_manager";
import { clearTokenCookies, storeLoginToken } from "@/utils/cookieUtils";
import { TagNewRequest, TagUpdateRequest, TagListResponse, TagInfoResponse } from "./tag_management/types";
import { Team } from "./key_team_helpers/key_list";
import { UserInfo } from "./view_users/types";
import { EmailEventSettingsResponse, EmailEventSettingsUpdateRequest } from "./email_events/types";
import type { SkillRegisterRequest } from "./claude_code_plugins/types";
import { jsonFields } from "./common_components/check_openapi_schema";
Expand Down Expand Up @@ -944,6 +943,22 @@ export const teamDeleteCall = async (accessToken: string, teamID: string) => {
}
};

export interface UserInfo {
user_id: string;
user_email: string;
user_alias: string | null;
user_role: string;
spend: number;
max_budget: number | null;
models: string[];
key_count: number;
created_at: string;
updated_at: string;
sso_user_id: string | null;
budget_duration: string | null;
metadata?: Record<string, unknown> | null;
}

export type UserListResponse = {
page: number;
page_size: number;
Expand Down Expand Up @@ -5923,7 +5938,6 @@ export const resetEmailEventSettings = async (accessToken: string) => {
}
};

export { type UserInfo } from "./view_users/types"; // Re-export UserInfo
export { type Team } from "./key_team_helpers/key_list"; // Re-export Team

export const deleteAgentCall = async (accessToken: string, agentId: string) => {
Expand Down
15 changes: 0 additions & 15 deletions ui/litellm-dashboard/src/components/view_users/types.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ vi.mock("@/utils/returnUrlUtils", async (importOriginal) => {
vi.mock("@/components/navbar", () => ({ default: stub("navbar") }));
vi.mock("@/components/user_dashboard", () => ({ default: stub("user-dashboard") }));
vi.mock("@/components/templates/model_dashboard", () => ({ default: stub("model-dashboard") }));
vi.mock("@/components/view_users", () => ({ default: stub("view-users") }));
vi.mock("@/components/teams", () => ({ default: stub("teams") }));
vi.mock("@/components/organizations", () => ({
default: stub("organizations"),
Expand Down
Loading