From 0eb27b28435ebdcda3f1d39b0c26ba2efda668a2 Mon Sep 17 00:00:00 2001 From: Noble Mittal <62551163+beingnoble03@users.noreply.github.com> Date: Fri, 8 Nov 2024 22:02:44 +0530 Subject: [PATCH] VTAdmin: Support for multiple DataTable accessing same URL (#17036) Signed-off-by: Noble Mittal --- web/vtadmin/src/components/dataTable/DataTable.tsx | 11 +++++++++-- .../components/routes/workflow/WorkflowDetails.tsx | 4 ++++ .../src/components/routes/workflow/WorkflowVDiff.tsx | 2 +- web/vtadmin/src/hooks/useURLPagination.ts | 9 +++++---- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/web/vtadmin/src/components/dataTable/DataTable.tsx b/web/vtadmin/src/components/dataTable/DataTable.tsx index ed14067bd34..9e863a6aa54 100644 --- a/web/vtadmin/src/components/dataTable/DataTable.tsx +++ b/web/vtadmin/src/components/dataTable/DataTable.tsx @@ -31,6 +31,10 @@ interface Props { pageSize?: number; renderRows: (rows: T[]) => JSX.Element[]; title?: string; + // Pass a unique `pageKey` for each DataTable, in case multiple + // DataTables access the same URL. This will be used to + // access page number from the URL. + pageKey?: string; } // Generally, page sizes of ~100 rows are fine in terms of performance, @@ -43,12 +47,15 @@ export const DataTable = ({ pageSize = DEFAULT_PAGE_SIZE, renderRows, title, + pageKey = '', }: Props) => { const { pathname } = useLocation(); const urlQuery = useURLQuery(); + const pageQueryKey = `${pageKey}page`; + const totalPages = Math.ceil(data.length / pageSize); - const { page } = useURLPagination({ totalPages }); + const { page } = useURLPagination({ totalPages, pageQueryKey }); const startIndex = (page - 1) * pageSize; const endIndex = startIndex + pageSize; @@ -59,7 +66,7 @@ export const DataTable = ({ const formatPageLink = (p: number) => ({ pathname, - search: stringify({ ...urlQuery.query, page: p === 1 ? undefined : p }), + search: stringify({ ...urlQuery.query, [pageQueryKey]: p === 1 ? undefined : p }), }); return ( diff --git a/web/vtadmin/src/components/routes/workflow/WorkflowDetails.tsx b/web/vtadmin/src/components/routes/workflow/WorkflowDetails.tsx index c45fb86c053..10257aa7265 100644 --- a/web/vtadmin/src/components/routes/workflow/WorkflowDetails.tsx +++ b/web/vtadmin/src/components/routes/workflow/WorkflowDetails.tsx @@ -276,6 +276,7 @@ export const WorkflowDetails = ({ clusterID, keyspace, name, refetchInterval }: renderRows={renderSummaryRows} pageSize={1} title="Summary" + pageKey="summary" /> {tableCopyStates && ( )}

Recent Logs

@@ -304,6 +307,7 @@ export const WorkflowDetails = ({ clusterID, keyspace, name, refetchInterval }: renderRows={renderLogRows} pageSize={10} title={stream.key!} + pageKey={`${formatAlias(stream.tablet)}${stream.id}`} /> )) diff --git a/web/vtadmin/src/components/routes/workflow/WorkflowVDiff.tsx b/web/vtadmin/src/components/routes/workflow/WorkflowVDiff.tsx index f3ec33488b6..f23fb2290d7 100644 --- a/web/vtadmin/src/components/routes/workflow/WorkflowVDiff.tsx +++ b/web/vtadmin/src/components/routes/workflow/WorkflowVDiff.tsx @@ -83,7 +83,7 @@ export const WorkflowVDiff = ({ clusterID, keyspace, name }: Props) => { const isStatusEmpty = !lastVDiffStatus || - (Object.keys(lastVDiffStatus.shard_report).length === 1 && + (Object.keys(lastVDiffStatus.shard_report).length > 0 && !lastVDiffStatus.shard_report[Object.keys(lastVDiffStatus.shard_report)[0]].state); const renderRows = (rows: typeof shardReports) => { diff --git a/web/vtadmin/src/hooks/useURLPagination.ts b/web/vtadmin/src/hooks/useURLPagination.ts index ddccdc43b07..b6681e1fd41 100644 --- a/web/vtadmin/src/hooks/useURLPagination.ts +++ b/web/vtadmin/src/hooks/useURLPagination.ts @@ -20,6 +20,7 @@ import { useURLQuery } from './useURLQuery'; export interface PaginationOpts { totalPages: number; + pageQueryKey?: string; } export interface PaginationParams { @@ -35,7 +36,7 @@ const FIRST_PAGE = 1; * - use pagination in some way * - encode pagination state in the URL (e.g., /some/route?page=123) */ -export const useURLPagination = ({ totalPages }: PaginationOpts): PaginationParams => { +export const useURLPagination = ({ totalPages, pageQueryKey = 'page' }: PaginationOpts): PaginationParams => { const history = useHistory(); const location = useLocation(); const { query, replaceQuery } = useURLQuery({ parseNumbers: true }); @@ -43,7 +44,7 @@ export const useURLPagination = ({ totalPages }: PaginationOpts): PaginationPara // A slight nuance here -- if `page` is not in the URL at all, then we can assume // it's the first page. This makes for slightly nicer URLs for the first/default page: // "/foo" instead of "/foo?page=1". No redirect required. - const page = !('page' in query) || query.page === null ? FIRST_PAGE : query.page; + const page = !(pageQueryKey in query) || query[pageQueryKey] === null ? FIRST_PAGE : query[pageQueryKey]; useEffect(() => { // If the value in the URL *is* defined but is negative, non-numeric, @@ -53,9 +54,9 @@ export const useURLPagination = ({ totalPages }: PaginationOpts): PaginationPara if (isPageTooBig || isPageTooSmall || typeof page !== 'number') { // Replace history so the invalid value is not persisted in browser history - replaceQuery({ page: FIRST_PAGE }); + replaceQuery({ [pageQueryKey]: FIRST_PAGE }); } - }, [page, totalPages, history, location.pathname, query, replaceQuery]); + }, [page, pageQueryKey, totalPages, history, location.pathname, query, replaceQuery]); return { page,