Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
bdbe8d1
feat: import useTableUrlState
fabio-silva Jun 24, 2026
0fe7a2e
chore: lint
fabio-silva Jun 24, 2026
fa98e11
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jun 28, 2026
83984a6
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jun 28, 2026
25d8204
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jul 6, 2026
e4eeb57
chore: simplify code
fabio-silva Jul 6, 2026
1dd909e
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jul 7, 2026
a5ef9be
chore: update @percona/percona-ui
fabio-silva Jul 7, 2026
1736744
Merge branch 'PMM-14848-table-url-params' of https://github.com/perco…
fabio-silva Jul 7, 2026
5e5650b
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jul 7, 2026
1c25d84
chore: remove duplicate const
fabio-silva Jul 7, 2026
5169316
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jul 7, 2026
7aa1020
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jul 7, 2026
1dc9fdc
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jul 13, 2026
c4a58e1
PMM-14848 move sessions URL state constant
cursoragent Jul 13, 2026
0b3e2b0
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jul 13, 2026
c119f22
chore: format
fabio-silva Jul 13, 2026
c773985
Merge branch 'main' into PMM-14848-table-url-params
mattiasimonato Jul 14, 2026
0e2e8ae
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jul 14, 2026
a2e1edf
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jul 14, 2026
16355b0
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jul 29, 2026
7e08bec
fix: allow search on QAN while typing
fabio-silva Jul 30, 2026
c2ed921
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Jul 30, 2026
963024c
Merge branch 'main' into PMM-14848-table-url-params
fabio-silva Aug 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ui/apps/pmm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"@mui/icons-material": "^7.3.7",
"@mui/material": "^7.3.7",
"@mui/x-date-pickers": "^7.5.0",
"@percona/percona-ui": "1.0.22",
"@percona/percona-ui": "1.0.23",
"@pmm/shared": "*",
"@reactour/tour": "^3.8.0",
"@tanstack/react-query": "^5.45.1",
Expand Down
97 changes: 97 additions & 0 deletions ui/apps/pmm/src/hooks/utils/useTableUrlState.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { renderHook } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';
import reactRouter from 'react-router-dom';
import { useTableUrlState } from './useTableUrlState';

const { usePerconaTableUrlState } = vi.hoisted(() => ({
usePerconaTableUrlState: vi.fn(),
}));

vi.mock('@percona/percona-ui', async (importOriginal) => {
const actual = await importOriginal<typeof import('@percona/percona-ui')>();
return {
...actual,
usePerconaTableUrlState,
};
});

const setup = (params: string) => {
const searchParams = new URLSearchParams(params);
const setSearchParams = vi.fn();

vi.spyOn(reactRouter, 'useSearchParams').mockReturnValue([searchParams, setSearchParams]);
vi.mocked(usePerconaTableUrlState).mockReturnValue({
tableState: {
state: {
columnFilters: [],
globalFilter: '',
sorting: [],
pagination: { pageIndex: 0, pageSize: 10 },
},
onColumnFiltersChange: vi.fn(),
onGlobalFilterChange: vi.fn(),
onSortingChange: vi.fn(),
onPaginationChange: vi.fn(),
},
tableProps: {
state: {
columnFilters: [],
globalFilter: '',
sorting: [],
pagination: { pageIndex: 0, pageSize: 10 },
showColumnFilters: false,
showGlobalFilter: false,
},
onColumnFiltersChange: vi.fn(),
onGlobalFilterChange: vi.fn(),
onSortingChange: vi.fn(),
onPaginationChange: vi.fn(),
onShowColumnFiltersChange: vi.fn(),
onShowGlobalFilterChange: vi.fn(),
},
});

return { searchParams, setSearchParams };
};

describe('useTableUrlState', () => {
it('passes react-router search params to percona useTableUrlState', () => {
const { searchParams, setSearchParams } = setup(
'serviceIds=123&overview.sort=queryText:desc'
);

renderHook(() =>
useTableUrlState({
paramPrefix: 'overview',
})
);

expect(usePerconaTableUrlState).toHaveBeenCalledWith({
searchParams,
setSearchParams,
paramPrefix: 'overview',
});
});

it('forwards optional hook configuration', () => {
const { searchParams, setSearchParams } = setup('');

renderHook(() =>
useTableUrlState({
paramPrefix: 'sessions',
debounceMs: 500,
replace: false,
sync: { pagination: false },
})
);

expect(usePerconaTableUrlState).toHaveBeenCalledWith({
searchParams,
setSearchParams,
paramPrefix: 'sessions',
debounceMs: 500,
replace: false,
sync: { pagination: false },
});
});
});
25 changes: 25 additions & 0 deletions ui/apps/pmm/src/hooks/utils/useTableUrlState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useSearchParams } from 'react-router-dom';
import {
usePerconaTableUrlState,
type UsePerconaTableUrlStateOptions,
type UsePerconaTableUrlStateResult,
} from '@percona/percona-ui';

export type UseTableUrlStateOptions = Omit<
UsePerconaTableUrlStateOptions,
'searchParams' | 'setSearchParams'
>;

export type UseTableUrlStateResult = UsePerconaTableUrlStateResult;

export const useTableUrlState = (
options: UseTableUrlStateOptions = {}
): UseTableUrlStateResult => {
const [searchParams, setSearchParams] = useSearchParams();

return usePerconaTableUrlState({
searchParams,
setSearchParams,
...options,
});
};
7 changes: 6 additions & 1 deletion ui/apps/pmm/src/pages/rta/overview/RealtimeOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,12 @@ const RealtimeOverviewPage: FC = () => {
});
}

setSearchParams({ serviceIds: newServiceIds });
setSearchParams((prev) => {
const next = new URLSearchParams(prev);
next.delete('serviceIds');
newServiceIds.forEach((id) => next.append('serviceIds', id));
return next;
});
};

if (isLoading) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ export const OVERVIEW_TABLE_COLUMNS: MRT_ColumnDef<QueryData>[] = [
accessorKey: 'queryExecutionDurationMs',
filterVariant: 'range',
filterFn: 'timeRangeFilterFn',
muiTableHeadCellFilterTextFieldProps: {
inputProps: { step: 0.25, type: 'number' },
muiFilterTextFieldProps: {
type: 'text',
inputProps: { inputMode: 'decimal' },
},
Cell: ({ cell }) =>
cell.getValue() ? (
Expand Down
29 changes: 15 additions & 14 deletions ui/apps/pmm/src/pages/rta/overview/table/OverviewTable.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import {
type MRT_Row,
type MaterialReactTableProps,
} from 'material-react-table';
import { FC } from 'react';
import { type MRT_Row, MaterialReactTableProps } from 'material-react-table';
import { Table, useNavigableRows } from '@percona/percona-ui';
import type { FC } from 'react';
import type { QueryData } from 'types/rta.types';
import { QueryData } from 'types/rta.types';
import { OVERVIEW_TABLE_COLUMNS } from './OverviewTable.constants';
import { RealtimeTableWrapper } from 'pages/rta/components/rta-table-wrapper';
import { boxClasses } from '@mui/material/Box';
import { Messages } from './OverviewTable.messages';
import { filterElapsedTime } from './OverviewTable.utils';
import { useTableUrlState } from 'hooks/utils/useTableUrlState';

const OVERVIEW_TABLE_URL_STATE_OPTIONS = {
paramPrefix: 'overview',
defaults: {
pagination: { pageIndex: 0, pageSize: 25 },
}
};

interface Props {
queries: QueryData[];
Expand All @@ -26,21 +31,16 @@ const OverviewTable: FC<Props> = ({
actions,
onRowHover,
}) => {
const { tableProps, refresh } = useNavigableRows<QueryData>({
const { tableProps: navigableTableProps, refresh } = useNavigableRows<QueryData>({
data: queries,
onChange: onNavigableQueriesChange,
});
const { tableProps: urlStateTableProps } = useTableUrlState(OVERVIEW_TABLE_URL_STATE_OPTIONS);

return (
<RealtimeTableWrapper>
<Table
tableName="realtime-overview-table"
initialState={{
pagination: {
pageSize: 25,
pageIndex: 0,
},
}}
columns={OVERVIEW_TABLE_COLUMNS}
data={queries}
noDataMessage={Messages.noData}
Expand All @@ -53,7 +53,8 @@ const OverviewTable: FC<Props> = ({
},
},
}}
{...tableProps}
{...navigableTableProps}
{...urlStateTableProps}
enableStickyHeader
enableGlobalFilter={false}
enableHiding={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import { enqueueSnackbar } from 'notistack';
import { RealtimeTableWrapper } from 'pages/rta/components/rta-table-wrapper';
import { useUser } from 'contexts/user';
import { Navigate } from 'react-router-dom';
import { useTableUrlState } from 'hooks/utils/useTableUrlState';

const SESSIONS_TABLE_URL_STATE_OPTIONS = {
Comment thread
fabio-silva marked this conversation as resolved.
Outdated
paramPrefix: 'sessions',
};

const SessionsTable: FC = () => {
const { user } = useUser();
Expand All @@ -38,6 +43,10 @@ const SessionsTable: FC = () => {
[rowSelection, rows]
);
const { mutateAsync: stopSessions } = useStopSessions();
const { tableProps } = useTableUrlState({
...SESSIONS_TABLE_URL_STATE_OPTIONS,
additionalState: { rowSelection },
});

const closeModal = () => {
setModal(null);
Expand Down Expand Up @@ -129,9 +138,6 @@ const SessionsTable: FC = () => {
...(user?.isPMMAdmin ? ['mrt-row-actions'] : []),
],
}}
state={{
rowSelection,
}}
positionToolbarAlertBanner="none"
getRowId={(row) => row.sessionId}
noDataMessage={Messages.empty}
Expand Down Expand Up @@ -163,7 +169,7 @@ const SessionsTable: FC = () => {
color="inherit"
size="small"
data-testid="open-stop-modal"
onClick={() => openStopModal(row.original)}
onClick={() => openStopModal(row.original as SessionRow)}
>
{Messages.stop}
</Button>
Expand Down Expand Up @@ -223,6 +229,7 @@ const SessionsTable: FC = () => {
</Stack>
)
}
{...tableProps}
/>
<StopSessionModal
open={modal === 'stop'}
Expand Down
26 changes: 13 additions & 13 deletions ui/apps/pmm/src/utils/testStubs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,19 @@ export const TEST_USER_VIEWER: User = {
},
};

export const TEST_USER_ANONYMOUS: User = {
...TEST_USER_VIEWER,
id: 0,
login: 'anonymous',
name: 'Anonymous',
isAnonymous: true,
isPMMAdmin: false,
info: {
...TEST_USER_ADMIN.info,
userId: 0,
},
};

export const TEST_SERVICE: BaseService = {
serviceId: 'service-1',
serviceName: 'Service 1',
Expand Down Expand Up @@ -166,16 +179,3 @@ export const TEST_MONGO_DB_QUERY_DATA: QueryData = {
username: 'username',
},
};

export const TEST_USER_ANONYMOUS: User = {
...TEST_USER_VIEWER,
id: 0,
login: 'anonymous',
name: 'Anonymous',
isAnonymous: true,
isPMMAdmin: false,
info: {
...TEST_USER_ADMIN.info,
userId: 0,
},
};
Loading
Loading