mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
Fix Filter Dropdown UX Issue - Load Initial Options (#13858)
* move the filter component to molecules * load initial options
This commit is contained in:
parent
67621d3381
commit
0aa1371903
3 changed files with 47 additions and 5 deletions
|
|
@ -7,8 +7,8 @@ import { Button } from "@tremor/react"
|
|||
import KeyInfoView from "./templates/key_info_view"
|
||||
import { Tooltip } from "antd"
|
||||
import { Team, KeyResponse } from "./key_team_helpers/key_list"
|
||||
import FilterComponent from "./common_components/filter"
|
||||
import { FilterOption } from "./common_components/filter"
|
||||
import FilterComponent from "./molecules/filter"
|
||||
import { FilterOption } from "./molecules/filter"
|
||||
import { keyListCall, Organization, userListCall } from "./networking"
|
||||
import { createTeamSearchFunction } from "./key_team_helpers/team_search_fn"
|
||||
import { createOrgSearchFunction } from "./key_team_helpers/organization_search_fn"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useCallback } from "react";
|
||||
import React, { useState, useCallback, useEffect } from "react";
|
||||
import { Button, Input, Select } from "antd";
|
||||
import { FilterIcon } from "@heroicons/react/outline";
|
||||
import debounce from "lodash/debounce";
|
||||
|
|
@ -43,6 +43,9 @@ const FilterComponent: React.FC<FilterComponentProps> = ({
|
|||
const [searchInputValueMap, setSearchInputValueMap] = useState<{
|
||||
[key: string]: string;
|
||||
}>({});
|
||||
const [initialOptionsLoaded, setInitialOptionsLoaded] = useState<{
|
||||
[key: string]: boolean;
|
||||
}>({});
|
||||
|
||||
const debouncedSearch = useCallback(
|
||||
debounce(async (value: string, option: FilterOption) => {
|
||||
|
|
@ -62,6 +65,36 @@ const FilterComponent: React.FC<FilterComponentProps> = ({
|
|||
[]
|
||||
);
|
||||
|
||||
// Load initial options for searchable filters
|
||||
const loadInitialOptions = useCallback(async (option: FilterOption) => {
|
||||
if (!option.isSearchable || !option.searchFn || initialOptionsLoaded[option.name]) return;
|
||||
|
||||
setSearchLoadingMap((prev) => ({ ...prev, [option.name]: true }));
|
||||
setInitialOptionsLoaded((prev) => ({ ...prev, [option.name]: true }));
|
||||
|
||||
try {
|
||||
// Load initial options with empty search to get some default results
|
||||
const results = await option.searchFn("");
|
||||
setSearchOptionsMap((prev) => ({ ...prev, [option.name]: results }));
|
||||
} catch (error) {
|
||||
console.error("Error loading initial options:", error);
|
||||
setSearchOptionsMap((prev) => ({ ...prev, [option.name]: [] }));
|
||||
} finally {
|
||||
setSearchLoadingMap((prev) => ({ ...prev, [option.name]: false }));
|
||||
}
|
||||
}, [initialOptionsLoaded]);
|
||||
|
||||
// Load initial options when filters are shown
|
||||
useEffect(() => {
|
||||
if (showFilters) {
|
||||
options.forEach(option => {
|
||||
if (option.isSearchable && !initialOptionsLoaded[option.name]) {
|
||||
loadInitialOptions(option);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [showFilters, options, loadInitialOptions, initialOptionsLoaded]);
|
||||
|
||||
const handleFilterChange = (name: string, value: string) => {
|
||||
const newValues = {
|
||||
...tempValues,
|
||||
|
|
@ -80,6 +113,13 @@ const FilterComponent: React.FC<FilterComponentProps> = ({
|
|||
onResetFilters();
|
||||
};
|
||||
|
||||
// Handle dropdown open to load initial options
|
||||
const handleDropdownVisibleChange = (open: boolean, option: FilterOption) => {
|
||||
if (open && option.isSearchable && !initialOptionsLoaded[option.name]) {
|
||||
loadInitialOptions(option);
|
||||
}
|
||||
};
|
||||
|
||||
// Define the order of filters
|
||||
const orderedFilters = [
|
||||
"Team ID",
|
||||
|
|
@ -125,6 +165,7 @@ const FilterComponent: React.FC<FilterComponentProps> = ({
|
|||
placeholder={`Search ${option.label || option.name}...`}
|
||||
value={tempValues[option.name] || undefined}
|
||||
onChange={(value) => handleFilterChange(option.name, value)}
|
||||
onDropdownVisibleChange={(open) => handleDropdownVisibleChange(open, option)}
|
||||
onSearch={(value) => {
|
||||
setSearchInputValueMap((prev) => ({
|
||||
...prev,
|
||||
|
|
@ -138,6 +179,7 @@ const FilterComponent: React.FC<FilterComponentProps> = ({
|
|||
loading={searchLoadingMap[option.name]}
|
||||
options={searchOptionsMap[option.name] || []}
|
||||
allowClear
|
||||
notFoundContent={searchLoadingMap[option.name] ? "Loading..." : "No results found"}
|
||||
/>
|
||||
) : option.options ? (
|
||||
<Select
|
||||
|
|
@ -18,8 +18,8 @@ import KeyInfoView from "../templates/key_info_view"
|
|||
import { SessionView } from "./SessionView"
|
||||
import { VectorStoreViewer } from "./VectorStoreViewer"
|
||||
import { GuardrailViewer } from "./GuardrailViewer"
|
||||
import FilterComponent from "../common_components/filter"
|
||||
import { FilterOption } from "../common_components/filter"
|
||||
import FilterComponent from "../molecules/filter"
|
||||
import { FilterOption } from "../molecules/filter"
|
||||
import { useLogFilterLogic } from "./log_filter_logic"
|
||||
import { fetchAllKeyAliases } from "../key_team_helpers/filter_helpers"
|
||||
import { Tab, TabGroup, TabList, TabPanels, TabPanel, Text, Switch } from "@tremor/react"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue