import React, { useState, useEffect } from 'react'; import { Table, TableHead, TableHeaderCell, TableBody, TableRow, TableCell, Card, Text, Badge, Icon, Grid, Col, Button, TabGroup, TabList, Tab, TabPanels, TabPanel, } from "@tremor/react"; import NumericalInput from "./shared/numerical_input"; import { Input } from "antd"; import { Modal, Form, Tooltip, Select as Select2 } from "antd"; import { InfoCircleOutlined } from '@ant-design/icons'; import { PencilAltIcon, TrashIcon, RefreshIcon } from "@heroicons/react/outline"; import { TextInput } from "@tremor/react"; import { getModelDisplayName } from './key_team_helpers/fetch_available_models_team_key'; import { message } from 'antd'; import OrganizationInfoView from './organization/organization_view'; import { Organization, organizationListCall, organizationCreateCall, organizationDeleteCall } from './networking'; interface OrganizationsTableProps { organizations: Organization[]; userRole: string; userModels: string[]; accessToken: string | null; lastRefreshed?: string; handleRefreshClick?: () => void; currentOrg?: any; guardrailsList?: string[]; setOrganizations: (organizations: Organization[]) => void; premiumUser: boolean; } export const fetchOrganizations = async (accessToken: string, setOrganizations: (organizations: Organization[]) => void) => { const organizations = await organizationListCall(accessToken); setOrganizations(organizations); }; const OrganizationsTable: React.FC = ({ organizations, userRole, userModels, accessToken, lastRefreshed, handleRefreshClick, currentOrg, guardrailsList = [], setOrganizations, premiumUser }) => { const [selectedOrgId, setSelectedOrgId] = useState(null); const [editOrg, setEditOrg] = useState(false); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [orgToDelete, setOrgToDelete] = useState(null); const [isOrgModalVisible, setIsOrgModalVisible] = useState(false); const [form] = Form.useForm(); useEffect(() => { if (organizations.length === 0 && accessToken) { fetchOrganizations(accessToken, setOrganizations); } }, [organizations, accessToken]); const handleDelete = (orgId: string | null) => { if (!orgId) return; setOrgToDelete(orgId); setIsDeleteModalOpen(true); }; const confirmDelete = async () => { if (!orgToDelete || !accessToken) return; try { await organizationDeleteCall(accessToken, orgToDelete); message.success('Organization deleted successfully'); setIsDeleteModalOpen(false); setOrgToDelete(null); // Refresh organizations list fetchOrganizations(accessToken, setOrganizations); } catch (error) { console.error('Error deleting organization:', error); } }; const cancelDelete = () => { setIsDeleteModalOpen(false); setOrgToDelete(null); }; const handleCreate = async (values: any) => { try { if (!accessToken) return; console.log(`values in organizations new create call: ${JSON.stringify(values)}`); await organizationCreateCall(accessToken, values); setIsOrgModalVisible(false); form.resetFields(); // Refresh organizations list fetchOrganizations(accessToken, setOrganizations); } catch (error) { console.error('Error creating organization:', error); } }; const handleCancel = () => { setIsOrgModalVisible(false); form.resetFields(); }; if (!premiumUser) { return (
This is a LiteLLM Enterprise feature, and requires a valid key to use. Get a trial key here.
); } if (selectedOrgId) { return ( { setSelectedOrgId(null); setEditOrg(false); }} accessToken={accessToken} is_org_admin={true} // You'll need to implement proper org admin check is_proxy_admin={userRole === "Admin"} userModels={userModels} editOrg={editOrg} /> ); } return (
Your Organizations
{lastRefreshed && Last Refreshed: {lastRefreshed}}
Click on “Organization ID” to view organization details. Organization ID Organization Name Created Spend (USD) Budget (USD) Models TPM / RPM Limits Info Actions {organizations && organizations.length > 0 ? organizations .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()) .map((org: Organization) => (
{org.organization_alias} {org.created_at ? new Date(org.created_at).toLocaleDateString() : "N/A"} {org.spend} {org.litellm_budget_table?.max_budget !== null && org.litellm_budget_table?.max_budget !== undefined ? org.litellm_budget_table?.max_budget : "No limit"} {Array.isArray(org.models) && (
{org.models.length === 0 ? ( All Proxy Models ) : ( org.models.map((model, index) => model === "all-proxy-models" ? ( All Proxy Models ) : ( {model.length > 30 ? `${getModelDisplayName(model).slice(0, 30)}...` : getModelDisplayName(model)} ) ) )}
)}
TPM: {org.litellm_budget_table?.tpm_limit ? org.litellm_budget_table?.tpm_limit : "Unlimited"}
RPM: {org.litellm_budget_table?.rpm_limit ? org.litellm_budget_table?.rpm_limit : "Unlimited"}
{org.members?.length || 0} Members {userRole === "Admin" && ( <> { setSelectedOrgId(org.organization_id); setEditOrg(true); }} /> handleDelete(org.organization_id)} icon={TrashIcon} size="sm" /> )}
)) : null}
{(userRole === "Admin" || userRole === "Org Admin") && (
All Proxy Models {userModels && userModels.length > 0 && userModels.map((model) => ( {getModelDisplayName(model)} ))} daily weekly monthly
)}
{isDeleteModalOpen ? (

Delete Organization

Are you sure you want to delete this organization?

) : <>}
); }; export default OrganizationsTable;