Skip to content

Commit c3fe32d

Browse files
committed
feat(FR-1683): migrate URL state management from use-query-params to nuqs for better React Transition support
1 parent 971d534 commit c3fe32d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+500
-419
lines changed

pnpm-lock.yaml

Lines changed: 158 additions & 117 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

react/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"lucide-react": "^0.552.0",
4747
"markdown-to-jsx": "^7.7.17",
4848
"marked": "^16.4.0",
49+
"nuqs": "^2.7.3",
4950
"p-queue": "^8.1.1",
5051
"prettier": "^3.6.2",
5152
"prism-react-renderer": "^2.4.1",
@@ -72,7 +73,8 @@
7273
"typescript": "^5.7.2",
7374
"use-query-params": "^2.2.1",
7475
"uuid": "^13.0.0",
75-
"web-vitals": "^3.5.2"
76+
"web-vitals": "^3.5.2",
77+
"zod": "^4.1.12"
7678
},
7779
"scripts": {
7880
"start": "craco start",

react/src/App.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import ServingPage from './pages/ServingPage';
1919
import VFolderNodeListPage from './pages/VFolderNodeListPage';
2020
import { Skeleton, theme } from 'antd';
2121
import { BAIFlex, BAICard } from 'backend.ai-ui';
22+
import { NuqsAdapter } from 'nuqs/adapters/react-router/v6';
2223
import React, { Suspense, FC } from 'react';
2324
import { useTranslation } from 'react-i18next';
2425
import {
@@ -558,7 +559,11 @@ const router = createBrowserRouter([
558559
]);
559560

560561
const App: FC = () => {
561-
return <RouterProvider router={router} />;
562+
return (
563+
<NuqsAdapter>
564+
<RouterProvider router={router} />
565+
</NuqsAdapter>
566+
);
562567
};
563568

564569
export default App;

react/src/RelayEnvironment.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ const fetchFn: FetchFunction = async (
6969
}
7070
})) || {};
7171

72+
if (result.errors) {
73+
// NOTE: Starting from Relay 18.1.0, the error returned by @catch directive no longer has a message field,
74+
// so we store the original message in the extensions.rawErrorMessage field.
75+
// https://github.com/facebook/relay/releases/tag/v18.1.0
76+
result.errors.forEach((error: any) => {
77+
if (error.extensions && error.message) {
78+
error.extensions.rawErrorMessage = error.message;
79+
}
80+
});
81+
}
82+
7283
return result;
7384
};
7485

react/src/components/AgentList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
} from '../helper';
1313
import { INITIAL_FETCH_KEY, useSuspendedBackendaiClient } from '../hooks';
1414
import { ResourceSlotName, useResourceSlotsDetails } from '../hooks/backendai';
15-
import { useBAIPaginationOptionStateOnSearchParam } from '../hooks/reactPaginationQueryOptions';
15+
import { useBAIPaginationOptionStateOnSearchParamLegacy } from '../hooks/reactPaginationQueryOptions';
1616
import { useHiddenColumnKeysSetting } from '../hooks/useHiddenColumnKeysSetting';
1717
import { useThemeMode } from '../hooks/useThemeMode';
1818
import AgentDetailModal from './AgentDetailModal';
@@ -84,7 +84,7 @@ const AgentList: React.FC<AgentListProps> = ({
8484
baiPaginationOption,
8585
tablePaginationOption,
8686
setTablePaginationOption,
87-
} = useBAIPaginationOptionStateOnSearchParam({
87+
} = useBAIPaginationOptionStateOnSearchParamLegacy({
8888
current: 1,
8989
pageSize: 10,
9090
});

react/src/components/AgentSummaryList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
} from '../helper';
1010
import { INITIAL_FETCH_KEY, useFetchKey } from '../hooks';
1111
import { ResourceSlotName, useResourceSlotsDetails } from '../hooks/backendai';
12-
import { useBAIPaginationOptionStateOnSearchParam } from '../hooks/reactPaginationQueryOptions';
12+
import { useBAIPaginationOptionStateOnSearchParamLegacy } from '../hooks/reactPaginationQueryOptions';
1313
import { useResourceGroupsForCurrentProject } from '../hooks/useCurrentProject';
1414
import { useHiddenColumnKeysSetting } from '../hooks/useHiddenColumnKeysSetting';
1515
import BAIProgressWithLabel from './BAIProgressWithLabel';
@@ -62,7 +62,7 @@ const AgentSummaryList: React.FC<AgentSummaryListProps> = ({
6262
baiPaginationOption,
6363
tablePaginationOption,
6464
setTablePaginationOption,
65-
} = useBAIPaginationOptionStateOnSearchParam({
65+
} = useBAIPaginationOptionStateOnSearchParamLegacy({
6666
current: 1,
6767
pageSize: 20,
6868
});

react/src/components/ContainerRegistryList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
useFetchKey,
1010
useSuspendedBackendaiClient,
1111
} from '../hooks';
12-
import { useBAIPaginationOptionStateOnSearchParam } from '../hooks/reactPaginationQueryOptions';
12+
import { useBAIPaginationOptionStateOnSearchParamLegacy } from '../hooks/reactPaginationQueryOptions';
1313
import { useSetBAINotification } from '../hooks/useBAINotification';
1414
import { useHiddenColumnKeysSetting } from '../hooks/useHiddenColumnKeysSetting';
1515
import { usePainKiller } from '../hooks/usePainKiller';
@@ -78,7 +78,7 @@ const ContainerRegistryList: React.FC<{
7878
baiPaginationOption,
7979
tablePaginationOption,
8080
setTablePaginationOption,
81-
} = useBAIPaginationOptionStateOnSearchParam({
81+
} = useBAIPaginationOptionStateOnSearchParamLegacy({
8282
current: 1,
8383
pageSize: 20,
8484
});

react/src/components/PendingSessionNodeList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
PendingSessionNodeListQuery$variables,
1414
} from 'src/__generated__/PendingSessionNodeListQuery.graphql';
1515
import { INITIAL_FETCH_KEY, useFetchKey, useWebUINavigate } from 'src/hooks';
16-
import { useBAIPaginationOptionStateOnSearchParam } from 'src/hooks/reactPaginationQueryOptions';
16+
import { useBAIPaginationOptionStateOnSearchParamLegacy } from 'src/hooks/reactPaginationQueryOptions';
1717
import { useBAISettingUserState } from 'src/hooks/useBAISetting';
1818
import { useCurrentResourceGroupValue } from 'src/hooks/useCurrentProject';
1919

@@ -36,7 +36,7 @@ const PendingSessionNodeList: React.FC = () => {
3636
baiPaginationOption,
3737
tablePaginationOption,
3838
setTablePaginationOption,
39-
} = useBAIPaginationOptionStateOnSearchParam({
39+
} = useBAIPaginationOptionStateOnSearchParamLegacy({
4040
current: 1,
4141
pageSize: 10,
4242
});

react/src/components/SessionNodes.tsx

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,46 @@ import { useTranslation } from 'react-i18next';
2626
import { graphql, useFragment } from 'react-relay';
2727

2828
export type SessionNodeInList = NonNullable<SessionNodesFragment$data[number]>;
29+
30+
const availableSessionSorterKeys = [
31+
'name',
32+
'scaling_group',
33+
'type',
34+
'cluster_mode',
35+
'created_at',
36+
'agent_ids',
37+
] as const;
38+
39+
export const availableSessionSorterValues = [
40+
...availableSessionSorterKeys,
41+
...availableSessionSorterKeys.map((key) => `-${key}` as const),
42+
] as const;
43+
44+
const isEnableSorter = (key: string) => {
45+
return _.includes(availableSessionSorterKeys, key);
46+
};
47+
2948
interface SessionNodesProps
30-
extends Omit<BAITableProps<SessionNodeInList>, 'dataSource' | 'columns'> {
49+
extends Omit<
50+
BAITableProps<SessionNodeInList>,
51+
'dataSource' | 'columns' | 'onChangeOrder'
52+
> {
3153
sessionsFrgmt: SessionNodesFragment$key;
3254
onClickSessionName?: (session: SessionNodeInList) => void;
3355
disableSorter?: boolean;
56+
onChangeOrder?: (
57+
order: (typeof availableSessionSorterValues)[number] | null,
58+
) => void;
3459
}
3560

3661
const SessionNodes: React.FC<SessionNodesProps> = ({
3762
sessionsFrgmt,
3863
onClickSessionName,
3964
disableSorter,
65+
onChangeOrder,
4066
...tableProps
4167
}) => {
68+
'use memo';
4269
const { t } = useTranslation();
4370
const userRole = useCurrentUserRole();
4471
const baiClient = useSuspendedBackendaiClient();
@@ -101,7 +128,7 @@ const SessionNodes: React.FC<SessionNodesProps> = ({
101128
name
102129
);
103130
},
104-
sorter: true,
131+
sorter: isEnableSorter('name'),
105132
required: true,
106133
fixed: 'left',
107134
},
@@ -182,7 +209,7 @@ const SessionNodes: React.FC<SessionNodesProps> = ({
182209
dataIndex: 'scaling_group',
183210
title: t('session.ResourceGroup'),
184211
defaultHidden: true,
185-
sorter: true,
212+
sorter: isEnableSorter('scaling_group'),
186213
render: (__, session) =>
187214
session.scaling_group ? session.scaling_group : '-',
188215
},
@@ -191,15 +218,15 @@ const SessionNodes: React.FC<SessionNodesProps> = ({
191218
dataIndex: 'type',
192219
title: t('session.SessionType'),
193220
defaultHidden: true,
194-
sorter: true,
221+
sorter: isEnableSorter('type'),
195222
render: (__, session) => <BAISessionTypeTag sessionFrgmt={session} />,
196223
},
197224
{
198225
key: 'cluster_mode',
199226
dataIndex: 'cluster_mode',
200227
title: t('session.ClusterMode'),
201228
defaultHidden: true,
202-
sorter: true,
229+
sorter: isEnableSorter('cluster_mode'),
203230
render: (__, session) => (
204231
<BAISessionClusterMode sessionFrgmt={session} />
205232
),
@@ -209,15 +236,15 @@ const SessionNodes: React.FC<SessionNodesProps> = ({
209236
dataIndex: 'created_at',
210237
title: t('session.CreatedAt'),
211238
defaultHidden: true,
212-
sorter: true,
239+
sorter: isEnableSorter('created_at'),
213240
render: (created_at: string) => dayjs(created_at).format('LLL') || '-',
214241
},
215242
(userRole === 'superadmin' || !baiClient._config.hideAgents) && {
216243
key: 'agent',
217244
dataIndex: 'agent_ids',
218245
title: t('session.Agent'),
219246
defaultHidden: false,
220-
sorter: true,
247+
sorter: isEnableSorter('agent_ids'),
221248
render: (__, session) => <BAISessionAgentIds sessionFrgmt={session} />,
222249
},
223250
userRole === 'superadmin' &&
@@ -242,6 +269,13 @@ const SessionNodes: React.FC<SessionNodesProps> = ({
242269
dataSource={filteredSessions}
243270
columns={columns}
244271
scroll={{ x: 'max-content' }}
272+
onChangeOrder={(order) => {
273+
onChangeOrder?.(
274+
(order || null) as
275+
| (typeof availableSessionSorterValues)[number]
276+
| null,
277+
);
278+
}}
245279
{...tableProps}
246280
/>
247281
</>

react/src/components/StorageProxyList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
toFixedFloorWithoutTrailingZeros,
66
} from '../helper';
77
import { INITIAL_FETCH_KEY, useFetchKey } from '../hooks';
8-
import { useBAIPaginationOptionStateOnSearchParam } from '../hooks/reactPaginationQueryOptions';
8+
import { useBAIPaginationOptionStateOnSearchParamLegacy } from '../hooks/reactPaginationQueryOptions';
99
import BAIFetchKeyButton from './BAIFetchKeyButton';
1010
import BAIProgressWithLabel from './BAIProgressWithLabel';
1111
import DoubleTag from './DoubleTag';
@@ -77,7 +77,7 @@ const StorageProxyList = () => {
7777
baiPaginationOption,
7878
tablePaginationOption,
7979
setTablePaginationOption,
80-
} = useBAIPaginationOptionStateOnSearchParam({
80+
} = useBAIPaginationOptionStateOnSearchParamLegacy({
8181
current: 1,
8282
pageSize: 10,
8383
});

0 commit comments

Comments
 (0)