import { useContext, useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { makeStyles, Theme } from '@material-ui/core'; import { useNavigationHook } from '@/hooks'; import { ALL_ROUTER_TYPES } from '@/router/Types'; import RouteTabList from '@/components/customTabList/RouteTabList'; import DatabaseTree from '@/pages/databases/tree'; import { ITab } from '@/components/customTabList/Types'; import Partitions from './collections/partitions/Partitions'; import Overview from './collections/overview/Overview'; import Data from './collections/data/CollectionData'; import Segments from './collections/segments/Segments'; import Properties from './collections/properties/Properties'; import Search from './collections/search/Search'; import { dataContext, authContext } from '@/context'; import Collections from './collections/Collections'; import StatusIcon, { LoadingType } from '@/components/status/StatusIcon'; import { ConsistencyLevelEnum, DYNAMIC_FIELD } from '@/consts'; import RefreshButton from './RefreshButton'; import CopyButton from '@/components/advancedSearch/CopyButton'; import { SearchParams } from './types'; import { CollectionObject, CollectionFullObject } from '@server/types'; const useStyles = makeStyles((theme: Theme) => ({ wrapper: { flexDirection: 'row', }, tree: { boxShadow: 'none', flexBasis: theme.spacing(28), width: theme.spacing(28), flexGrow: 0, flexShrink: 0, height: 'calc(100vh - 96px)', overflow: 'auto', boxSizing: 'border-box', padding: theme.spacing(0, 2, 0, 0), }, tab: { flexGrow: 1, flexShrink: 1, overflowX: 'auto', padding: theme.spacing(0, 2), }, headerIcon: { marginLeft: theme.spacing(0.5), '& svg': { fontSize: 15, color: theme.palette.primary.main, }, }, })); // Databases page(tree and tabs) const Databases = () => { // context const { database, collections, loading, fetchCollection } = useContext(dataContext); // UI state const [searchParams, setSearchParams] = useState( [] as SearchParams[] ); // init search params useEffect(() => { collections.forEach(c => { // find search params for the collection const searchParam = searchParams.find( s => s.collection.collection_name === c.collection_name ); // if search params not found, and the schema is ready, create new search params if (!searchParam && c.schema) { setSearchParams(prevParams => { const scalarFields = c.schema.scalarFields.map(s => s.name); return [ ...prevParams, { collection: c, searchParams: c.schema.vectorFields.map(v => { return { anns_field: v.name, params: {}, data: '', expanded: c.schema.vectorFields.length === 1, field: v, selected: c.schema.vectorFields.length === 1, }; }), globalParams: { topK: 50, consistency_level: ConsistencyLevelEnum.Bounded, filter: '', rerank: 'rrf', rrfParams: { k: 60 }, weightedParams: { weights: Array(c.schema.vectorFields.length).fill(0.5), }, output_fields: c.schema.enable_dynamic_field ? [...scalarFields, DYNAMIC_FIELD] : scalarFields, }, searchResult: null, searchLatency: 0, }, ]; }); } else { // update collection setSearchParams(prevParams => { return prevParams.map(s => { if (s.collection.collection_name === c.collection_name) { // update field in search params const searchParams = s.searchParams.map(sp => { const field = c.schema?.vectorFields.find( v => v.name === sp.anns_field ); if (field) { return { ...sp, field }; } return sp; }); // update collection const collection = c; return { ...s, searchParams, collection }; } return s; }); }); } }); // delete search params for the collection that is not in the collections setSearchParams(prevParams => { return prevParams.filter(s => collections.find( c => c.collection_name === s.collection.collection_name ) ); }); }, [collections]); // get current collection from url const params = useParams(); const { databaseName = '', collectionName = '', collectionPage = '', } = params; // get style const classes = useStyles(); // update navigation useNavigationHook(ALL_ROUTER_TYPES.DATABASES, { collectionName, databaseName, extra: ( <> { await fetchCollection(collectionName); }} /> ), }); const setCollectionSearchParams = (params: SearchParams) => { setSearchParams(prevParams => { return prevParams.map(s => { if ( s.collection.collection_name === params.collection.collection_name ) { return { ...params }; } return s; }); }); }; // render return (
{loading ? ( ) : ( )}
{!collectionName && ( )} {collectionName && ( s.collection.collection_name === collectionName )! } setSearchParams={setCollectionSearchParams} collections={collections} /> )}
); }; // Database tab pages const DatabasesTab = (props: { databaseName: string; tabClass: string; // tab class }) => { const { databaseName, tabClass } = props; const { t: collectionTrans } = useTranslation('collection'); const dbTab: ITab[] = [ { label: collectionTrans('collections'), component: , path: `collections`, }, ]; const actionDbTab = dbTab.findIndex(t => t.path === databaseName); return ( ); }; // Collection tab pages const CollectionTabs = (props: { collectionPage: string; // current collection page collectionName: string; // current collection name tabClass: string; // tab class collections: CollectionObject[]; // collections searchParams: SearchParams; // search params setSearchParams: (params: SearchParams) => void; // set search params }) => { // props const { collectionPage, collectionName, tabClass, collections, searchParams, setSearchParams, } = props; // context const { isManaged } = useContext(authContext); // i18n const { t: collectionTrans } = useTranslation('collection'); const collection = collections.find( i => i.collection_name === collectionName ) as CollectionFullObject; // collection tabs const collectionTabs: ITab[] = [ { label: collectionTrans('overviewTab'), component: , path: `overview`, }, { label: collectionTrans('searchTab'), component: ( ), path: `search`, }, { label: collectionTrans('dataTab'), component: ( ), path: `data`, }, { label: collectionTrans('partitionTab'), component: , path: `partitions`, }, ]; if (!isManaged) { collectionTabs.push( { label: collectionTrans('segmentsTab'), component: , path: `segments`, }, { label: collectionTrans('propertiesTab'), component: , path: `properties`, } ); } // get active collection tab const activeColTab = collectionTabs.findIndex(t => t.path === collectionPage); return ( ); }; export default Databases;