From 0122984608e5de3c354582730de8fcc30c9b3ee6 Mon Sep 17 00:00:00 2001 From: Jong Eun Lee Date: Thu, 20 Feb 2025 13:50:41 +0800 Subject: [PATCH] refactor: Endpoint list loading state management --- react/src/App.tsx | 7 ++- react/src/components/EndpointList.tsx | 65 +++++--------------- react/src/pages/ServingPage.tsx | 85 +++++++++++++++------------ 3 files changed, 64 insertions(+), 93 deletions(-) diff --git a/react/src/App.tsx b/react/src/App.tsx index 0140dae2df..b8bd8ddf1d 100644 --- a/react/src/App.tsx +++ b/react/src/App.tsx @@ -1,4 +1,5 @@ import AnnouncementAlert from './components/AnnouncementAlert'; +import BAICard from './components/BAICard'; import BAIErrorBoundary, { ErrorView } from './components/BAIErrorBoundary'; import { DefaultProvidersForReactRoot, @@ -15,6 +16,7 @@ import VFolderListPage from './pages/VFolderListPage'; import { Skeleton, theme } from 'antd'; import React, { Suspense } from 'react'; import { FC } from 'react'; +import { useTranslation } from 'react-i18next'; import { IndexRouteObject, RouterProvider, @@ -176,14 +178,13 @@ const router = createBrowserRouter([ const [experimentalNeoSessionList] = useBAISettingUserState( 'experimental_neo_session_list', ); + const { t } = useTranslation(); return experimentalNeoSessionList ? ( - - + } > diff --git a/react/src/components/EndpointList.tsx b/react/src/components/EndpointList.tsx index ca83b56f53..fddfd934ea 100644 --- a/react/src/components/EndpointList.tsx +++ b/react/src/components/EndpointList.tsx @@ -4,11 +4,7 @@ import { filterNonNullItems, transformSorterToOrderString, } from '../helper'; -import { - useSuspendedBackendaiClient, - useUpdatableState, - useWebUINavigate, -} from '../hooks'; +import { useSuspendedBackendaiClient, useWebUINavigate } from '../hooks'; import { useCurrentUserInfo, useCurrentUserRole } from '../hooks/backendai'; import { useBAIPaginationOptionState } from '../hooks/reactPaginationQueryOptions'; // import { getSortOrderByName } from '../hooks/reactPaginationQueryOptions'; @@ -29,23 +25,16 @@ import { CheckOutlined, CloseOutlined, DeleteOutlined, - LoadingOutlined, - ReloadOutlined, SettingOutlined, } from '@ant-design/icons'; -import { useRafInterval, useToggle } from 'ahooks'; +import { useToggle } from 'ahooks'; import { Button, Typography, theme, Radio, App, Tooltip } from 'antd'; import { ColumnType } from 'antd/lib/table'; import graphql from 'babel-plugin-relay/macro'; import { default as dayjs } from 'dayjs'; import _ from 'lodash'; import { InfoIcon } from 'lucide-react'; -import React, { - PropsWithChildren, - useState, - useTransition, - startTransition as startTransitionWithoutPendingState, -} from 'react'; +import React, { PropsWithChildren, useState, useTransition } from 'react'; import { useTranslation } from 'react-i18next'; import { useLazyLoadQuery } from 'react-relay'; import { Link } from 'react-router-dom'; @@ -75,8 +64,15 @@ type LifecycleStage = 'created&destroying' | 'destroyed'; interface EndpointListProps extends PropsWithChildren { style?: React.CSSProperties; + fetchKey?: string; + onDeleted?: (endpoint: Endpoint) => void; } -const EndpointList: React.FC = ({ style, children }) => { +const EndpointList: React.FC = ({ + style, + fetchKey, + onDeleted, + children, +}) => { const { t } = useTranslation(); const { token } = theme.useToken(); const { message, modal } = App.useApp(); @@ -98,11 +94,8 @@ const EndpointList: React.FC = ({ style, children }) => { ? `lifecycle_stage == "created" | lifecycle_stage == "destroying"` : `lifecycle_stage == "${selectedLifecycleStage}"`; - const [isRefetchPending, startRefetchTransition] = useTransition(); const [isFilterPending, startFilterTransition] = useTransition(); const [isPendingPageChange, startPageChangeTransition] = useTransition(); - const [servicesFetchKey, updateServicesFetchKey] = - useUpdatableState('initial-fetch'); const [optimisticDeletingId, setOptimisticDeletingId] = useState< string | null >(); @@ -212,9 +205,7 @@ const EndpointList: React.FC = ({ style, children }) => { row.endpoint_id && terminateModelServiceMutation.mutate(row?.endpoint_id, { onSuccess: (res) => { - startRefetchTransition(() => { - updateServicesFetchKey(); - }); + onDeleted?.(row); // FIXME: temporally refer to mutate input to message if (res.success) { message.success( @@ -318,12 +309,6 @@ const EndpointList: React.FC = ({ style, children }) => { const [hiddenColumnKeys, setHiddenColumnKeys] = useHiddenColumnKeysSetting('EndpointListPage'); - useRafInterval(() => { - startTransitionWithoutPendingState(() => { - updateServicesFetchKey(); - }); - }, 7000); - const { endpoint_list: modelServiceList } = useLazyLoadQuery( graphql` @@ -388,7 +373,7 @@ const EndpointList: React.FC = ({ style, children }) => { }, { fetchPolicy: 'network-only', - fetchKey: servicesFetchKey, + fetchKey, }, ); @@ -506,34 +491,12 @@ const EndpointList: React.FC = ({ style, children }) => { )} - - - - - , - }} + loading={isFilterPending || isPendingPageChange} scroll={{ x: 'max-content' }} rowKey={'endpoint_id'} dataSource={filterNonNullItems(modelServiceList?.items)} diff --git a/react/src/pages/ServingPage.tsx b/react/src/pages/ServingPage.tsx index 62be200740..a4937d558d 100644 --- a/react/src/pages/ServingPage.tsx +++ b/react/src/pages/ServingPage.tsx @@ -1,6 +1,10 @@ +import BAICard from '../components/BAICard'; +import BAIFetchKeyButton from '../components/BAIFetchKeyButton'; import Flex from '../components/Flex'; import { filterEmptyItem } from '../helper'; -import { Card, Skeleton, theme } from 'antd'; +import { useUpdatableState, useWebUINavigate } from '../hooks'; +import { ReloadOutlined } from '@ant-design/icons'; +import { Button, Card, Skeleton, theme } from 'antd'; import React, { Suspense } from 'react'; import { useTranslation } from 'react-i18next'; import { StringParam, useQueryParam, withDefault } from 'use-query-params'; @@ -8,7 +12,7 @@ import { StringParam, useQueryParam, withDefault } from 'use-query-params'; // FIXME: need to apply filtering type of service later type TabKey = 'services' | 'chatting'; // "running" | "finished" | "others"; -const EndpointListPage = React.lazy(() => import('./EndpointListPage')); +const EndpointList = React.lazy(() => import('../components/EndpointList')); interface ServingPageProps {} @@ -17,34 +21,36 @@ const tabParam = withDefault(StringParam, 'services'); const ServingPage: React.FC = ({ ...props }) => { const { t } = useTranslation(); const { token } = theme.useToken(); - const [curTabKey, setCurTabKey] = useQueryParam('tab', tabParam, { - updateType: 'replace', - }); + const webuiNavigate = useWebUINavigate(); + + const [fetchKey, updateFetchKey] = useUpdatableState('initial-fetch'); - const tabList = filterEmptyItem([ - { key: 'services', label: t('modelService.Services') }, - // FIXME: need to apply filtering type of service later - // { - // key: "running", - // label: t("session.Running"), - // }, - // { - // key: "finished", - // label: t("session.Finished"), - // }, - // { - // key: "others", - // label: t("session.Others"), - // }, - ]); return ( - { - setCurTabKey(key as TabKey); - }} - tabList={tabList} + + + { + updateFetchKey(); + // startRefetchTransition(() => updateServicesFetchKey()); + }} + autoUpdateDelay={7000} + /> + + + + } styles={{ body: { padding: 0, @@ -53,18 +59,19 @@ const ServingPage: React.FC = ({ ...props }) => { }, }} > - {curTabKey === 'services' ? ( - } - > - - - ) : null} - + } + > + { + updateFetchKey(); + }} + /> + + ); };