Merge pull request #3180 from BerriAI/ui_create_user_flow

[UI] Show teams as dropdown in invite user flow
This commit is contained in:
Ishaan Jaff 2024-04-19 15:27:27 -07:00 committed by GitHub
commit c7b0d59bdc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 33 additions and 42 deletions

View file

@ -145,6 +145,7 @@ const CreateKeyPage = () => {
userRole={userRole} userRole={userRole}
token={token} token={token}
keys={keys} keys={keys}
teams={teams}
accessToken={accessToken} accessToken={accessToken}
setKeys={setKeys} setKeys={setKeys}
/> />

View file

@ -1,15 +1,16 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Button, Modal, Form, Input, message, Select, InputNumber } from "antd"; import { Button, Modal, Form, Input, message, Select, InputNumber } from "antd";
import { Button as Button2 } from "@tremor/react"; import { Button as Button2, Text } from "@tremor/react";
import { userCreateCall, modelAvailableCall } from "./networking"; import { userCreateCall, modelAvailableCall } from "./networking";
const { Option } = Select; const { Option } = Select;
interface CreateuserProps { interface CreateuserProps {
userID: string; userID: string;
accessToken: string; accessToken: string;
teams: any[] | null;
} }
const Createuser: React.FC<CreateuserProps> = ({ userID, accessToken }) => { const Createuser: React.FC<CreateuserProps> = ({ userID, accessToken, teams }) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [isModalVisible, setIsModalVisible] = useState(false); const [isModalVisible, setIsModalVisible] = useState(false);
const [apiuser, setApiuser] = useState<string | null>(null); const [apiuser, setApiuser] = useState<string | null>(null);
@ -59,7 +60,7 @@ const Createuser: React.FC<CreateuserProps> = ({ userID, accessToken }) => {
message.info("Making API Call"); message.info("Making API Call");
setIsModalVisible(true); setIsModalVisible(true);
console.log("formValues in create user:", formValues); console.log("formValues in create user:", formValues);
const response = await userCreateCall(accessToken, userID, formValues); const response = await userCreateCall(accessToken, null, formValues);
console.log("user create Response:", response); console.log("user create Response:", response);
setApiuser(response["key"]); setApiuser(response["key"]);
message.success("API user Created"); message.success("API user Created");
@ -73,16 +74,18 @@ const Createuser: React.FC<CreateuserProps> = ({ userID, accessToken }) => {
return ( return (
<div> <div>
<Button2 className="mx-auto" onClick={() => setIsModalVisible(true)}> <Button2 className="mx-auto" onClick={() => setIsModalVisible(true)}>
+ Create New User + Invite User
</Button2> </Button2>
<Modal <Modal
title="Create User" title="Invite User"
visible={isModalVisible} visible={isModalVisible}
width={800} width={800}
footer={null} footer={null}
onOk={handleOk} onOk={handleOk}
onCancel={handleCancel} onCancel={handleCancel}
> >
<Text className="mb-1">Invite a user to login to the Admin UI and create Keys</Text>
<Text className="mb-6"><b>Note: SSO Setup Required for this</b></Text>
<Form <Form
form={form} form={form}
onFinish={handleCreate} onFinish={handleCreate}
@ -90,38 +93,27 @@ const Createuser: React.FC<CreateuserProps> = ({ userID, accessToken }) => {
wrapperCol={{ span: 16 }} wrapperCol={{ span: 16 }}
labelAlign="left" labelAlign="left"
> >
<Form.Item label="User ID" name="user_id"> <Form.Item label="User Email" name="user_email">
<Input placeholder="Enter User ID" /> <Input placeholder="Enter User Email" />
</Form.Item> </Form.Item>
<Form.Item label="Team ID" name="team_id"> <Form.Item label="Team ID" name="team_id">
<Input placeholder="ai_team" /> <Select
</Form.Item> placeholder="Select Team ID"
<Form.Item label="Models" name="models">
<Select
mode="multiple"
placeholder="Select models"
style={{ width: "100%" }} style={{ width: "100%" }}
> >
{userModels.map((model) => ( {teams ? (
<Option key={model} value={model}> teams.map((team: any) => (
{model} <Option key={team.team_id} value={team.team_id}>
{team.team_alias}
</Option>
))
) : (
<Option key="default" value={null}>
Default Team
</Option> </Option>
))} )}
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item label="Max Budget (USD)" name="max_budget">
<InputNumber step={0.01} precision={2} width={200} />
</Form.Item>
<Form.Item label="Tokens per minute Limit (TPM)" name="tpm_limit">
<InputNumber step={1} width={400} />
</Form.Item>
<Form.Item label="Requests per minute Limit (RPM)" name="rpm_limit">
<InputNumber step={1} width={400} />
</Form.Item>
<Form.Item label="Duration (eg: 30s, 30h, 30d)" name="duration">
<Input />
</Form.Item>
<Form.Item label="Metadata" name="metadata"> <Form.Item label="Metadata" name="metadata">
<Input.TextArea rows={4} placeholder="Enter metadata as JSON" /> <Input.TextArea rows={4} placeholder="Enter metadata as JSON" />
</Form.Item> </Form.Item>
@ -132,23 +124,19 @@ const Createuser: React.FC<CreateuserProps> = ({ userID, accessToken }) => {
</Modal> </Modal>
{apiuser && ( {apiuser && (
<Modal <Modal
title="Save Your User" title="User Created Successfully"
visible={isModalVisible} visible={isModalVisible}
onOk={handleOk} onOk={handleOk}
onCancel={handleCancel} onCancel={handleCancel}
footer={null} footer={null}
> >
<p> <p>
Please save this secret user somewhere safe and accessible. For User has been created to access your proxy. Please Ask them to Log In.
security reasons, <b>you will not be able to view it again</b>{" "}
through your LiteLLM account. If you lose this secret user, you will
need to generate a new one.
</p>
<p>
{apiuser != null
? `API user: ${apiuser}`
: "User being created, this might take 30s"}
</p> </p>
<br></br>
<p><b>Note: This Feature is only supported through SSO on the Admin UI</b></p>
</Modal> </Modal>
)} )}
</div> </div>

View file

@ -158,7 +158,7 @@ export const keyCreateCall = async (
export const userCreateCall = async ( export const userCreateCall = async (
accessToken: string, accessToken: string,
userID: string, userID: string | null,
formValues: Record<string, any> // Assuming formValues is an object formValues: Record<string, any> // Assuming formValues is an object
) => { ) => {
try { try {

View file

@ -36,6 +36,7 @@ interface ViewUserDashboardProps {
keys: any[] | null; keys: any[] | null;
userRole: string | null; userRole: string | null;
userID: string | null; userID: string | null;
teams: any[] | null;
setKeys: React.Dispatch<React.SetStateAction<Object[] | null>>; setKeys: React.Dispatch<React.SetStateAction<Object[] | null>>;
} }
@ -45,6 +46,7 @@ const ViewUserDashboard: React.FC<ViewUserDashboardProps> = ({
keys, keys,
userRole, userRole,
userID, userID,
teams,
setKeys, setKeys,
}) => { }) => {
const [userData, setUserData] = useState<null | any[]>(null); const [userData, setUserData] = useState<null | any[]>(null);
@ -151,7 +153,7 @@ const ViewUserDashboard: React.FC<ViewUserDashboardProps> = ({
return ( return (
<div style={{ width: "100%" }}> <div style={{ width: "100%" }}>
<Grid className="gap-2 p-2 h-[75vh] w-full mt-8"> <Grid className="gap-2 p-2 h-[75vh] w-full mt-8">
<CreateUser userID={userID} accessToken={accessToken} /> <CreateUser userID={userID} accessToken={accessToken} teams={teams}/>
<Card className="w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4"> <Card className="w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4">
<TabGroup> <TabGroup>
<TabList variant="line" defaultValue="1"> <TabList variant="line" defaultValue="1">