Skip to content

Commit

Permalink
VTAdmin: Support for multiple DataTable accessing same URL (vitessio#…
Browse files Browse the repository at this point in the history
…17036)

Signed-off-by: Noble Mittal <[email protected]>
  • Loading branch information
beingnoble03 authored Nov 8, 2024
1 parent 78f7db2 commit 0eb27b2
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 7 deletions.
11 changes: 9 additions & 2 deletions web/vtadmin/src/components/dataTable/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ interface Props<T> {
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,
Expand All @@ -43,12 +47,15 @@ export const DataTable = <T extends object>({
pageSize = DEFAULT_PAGE_SIZE,
renderRows,
title,
pageKey = '',
}: Props<T>) => {
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;
Expand All @@ -59,7 +66,7 @@ export const DataTable = <T extends object>({

const formatPageLink = (p: number) => ({
pathname,
search: stringify({ ...urlQuery.query, page: p === 1 ? undefined : p }),
search: stringify({ ...urlQuery.query, [pageQueryKey]: p === 1 ? undefined : p }),
});

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ export const WorkflowDetails = ({ clusterID, keyspace, name, refetchInterval }:
renderRows={renderSummaryRows}
pageSize={1}
title="Summary"
pageKey="summary"
/>
<span id="workflowStreams"></span>
<DataTable
Expand All @@ -284,6 +285,7 @@ export const WorkflowDetails = ({ clusterID, keyspace, name, refetchInterval }:
renderRows={renderStreamRows}
pageSize={10}
title="Streams"
pageKey="streams"
/>
{tableCopyStates && (
<DataTable
Expand All @@ -292,6 +294,7 @@ export const WorkflowDetails = ({ clusterID, keyspace, name, refetchInterval }:
renderRows={renderTableCopyStateRows}
pageSize={1000}
title="Table Copy State"
pageKey="tableCopyState"
/>
)}
<h3 className="mt-8 mb-4">Recent Logs</h3>
Expand All @@ -304,6 +307,7 @@ export const WorkflowDetails = ({ clusterID, keyspace, name, refetchInterval }:
renderRows={renderLogRows}
pageSize={10}
title={stream.key!}
pageKey={`${formatAlias(stream.tablet)}${stream.id}`}
/>
</div>
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
9 changes: 5 additions & 4 deletions web/vtadmin/src/hooks/useURLPagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { useURLQuery } from './useURLQuery';

export interface PaginationOpts {
totalPages: number;
pageQueryKey?: string;
}

export interface PaginationParams {
Expand All @@ -35,15 +36,15 @@ 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 });

// 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,
Expand All @@ -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,
Expand Down

0 comments on commit 0eb27b2

Please sign in to comment.