Users/teams: Update to be compatible with react router 6 (#93163)

* UserCreatePage: Make compatible with react router 6

* ServiceAccountPage.test: Make compatible with react router 6

* Update TeamPages
This commit is contained in:
Alex Khomenko 2024-09-11 10:02:11 +03:00 committed by GitHub
parent cb372d3fa8
commit 25ebb5b76f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 42 additions and 29 deletions

View File

@ -1,6 +1,6 @@
import { useCallback } from 'react';
import { useForm } from 'react-hook-form';
import { useHistory } from 'react-router-dom';
import { useNavigate } from 'react-router-dom-v5-compat';
import { NavModelItem } from '@grafana/data';
import { getBackendSrv } from '@grafana/runtime';
@ -24,7 +24,7 @@ const pageNav: NavModelItem = {
};
const UserCreatePage = () => {
const history = useHistory();
const navigate = useNavigate();
const {
handleSubmit,
register,
@ -35,9 +35,9 @@ const UserCreatePage = () => {
async (data: UserDTO) => {
const { id } = await createUser(data);
history.push(`/admin/users/edit/${id}`);
navigate(`/admin/users/edit/${id}`);
},
[history]
[navigate]
);
return (

View File

@ -1,6 +1,5 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { History, Location } from 'history';
import { TestProvider } from 'test/helpers/TestProvider';
import { RouteDescriptor } from 'app/core/navigation/types';
@ -24,6 +23,12 @@ const setup = (propOverrides: Partial<Props>) => {
const loadServiceAccountTokensMock = jest.fn();
const updateServiceAccountMock = jest.fn();
const mockLocation = {
search: '',
pathname: '',
state: undefined,
hash: '',
};
const props: Props = {
serviceAccount: {} as ServiceAccountDTO,
tokens: [],
@ -34,8 +39,20 @@ const setup = (propOverrides: Partial<Props>) => {
path: '/org/serviceaccounts/1',
url: 'http://localhost:3000/org/serviceaccounts/1',
},
history: {} as History,
location: {} as Location,
history: {
length: 0,
action: 'PUSH',
location: mockLocation,
push: jest.fn(),
replace: jest.fn(),
go: jest.fn(),
goBack: jest.fn(),
goForward: jest.fn(),
block: jest.fn(),
listen: jest.fn(),
createHref: jest.fn(),
},
location: mockLocation,
queryParams: {},
route: {} as RouteDescriptor,
timezone: '',

View File

@ -1,9 +1,7 @@
import { screen } from '@testing-library/react';
import { Route, Router } from 'react-router-dom';
import { useParams } from 'react-router-dom-v5-compat';
import { render } from 'test/test-utils';
import { locationService } from '@grafana/runtime';
import TeamPages from './TeamPages';
import { getMockTeam } from './__mocks__/teamMocks';
@ -58,18 +56,16 @@ jest.mock('./TeamGroupSync', () => {
return () => <div>Team group sync</div>;
});
jest.mock('react-router-dom-v5-compat', () => ({
...jest.requireActual('react-router-dom-v5-compat'),
useParams: jest.fn(),
}));
const setup = (propOverrides: { teamId?: number; pageName?: string } = {}) => {
const pageName = propOverrides.pageName ?? 'members';
const teamId = propOverrides.teamId ?? 1;
locationService.push({ pathname: `/org/teams/edit/${teamId}/${pageName}` });
render(
<Router history={locationService.getHistory()}>
<Route path="/org/teams/edit/:id/:page?">
<TeamPages />
</Route>
</Router>
);
(useParams as jest.Mock).mockReturnValue({ id: `${teamId}`, page: pageName });
render(<TeamPages />);
};
describe('TeamPages', () => {

View File

@ -1,6 +1,6 @@
import { createSelector } from '@reduxjs/toolkit';
import { memo, useMemo, useRef } from 'react';
import { useParams } from 'react-router';
import { memo, useRef } from 'react';
import { useParams } from 'react-router-dom-v5-compat';
import { useAsync } from 'react-use';
import { featureEnabled } from '@grafana/runtime';
@ -18,10 +18,10 @@ import { loadTeam } from './state/actions';
import { getTeamLoadingNav } from './state/navModel';
import { getTeam } from './state/selectors';
interface TeamPageRouteParams {
type TeamPageRouteParams = {
id: string;
page?: string;
}
};
enum PageTypes {
Members = 'members',
@ -32,7 +32,7 @@ enum PageTypes {
const PAGES = ['members', 'settings', 'groupsync'];
const teamSelector = createSelector(
[(state: StoreState) => state.team, (_: StoreState, teamId: number) => teamId],
[(state: StoreState) => state.team, (_: StoreState, teamId: string) => teamId],
(team, teamId) => getTeam(team, teamId)
);
@ -40,7 +40,7 @@ const pageNavSelector = createSelector(
[
(state: StoreState) => state.navIndex,
(_state: StoreState, pageName: string) => pageName,
(_state: StoreState, _pageName: string, teamId: number) => teamId,
(_state: StoreState, _pageName: string, teamId: string) => teamId,
],
(navIndex, pageName, teamId) => {
const teamLoadingNav = getTeamLoadingNav(pageName);
@ -50,8 +50,7 @@ const pageNavSelector = createSelector(
const TeamPages = memo(() => {
const isSyncEnabled = useRef(featureEnabled('teamsync'));
const params = useParams<TeamPageRouteParams>();
const teamId = useMemo(() => parseInt(params.id, 10), [params]);
const { id: teamId = '', page } = useParams<TeamPageRouteParams>();
const team = useSelector((state) => teamSelector(state, teamId));
let defaultPage = 'members';
@ -59,7 +58,7 @@ const TeamPages = memo(() => {
if (!team || !contextSrv.hasPermissionInMetadata(AccessControlAction.ActionTeamsPermissionsRead, team)) {
defaultPage = 'settings';
}
const pageName = params.page ?? defaultPage;
const pageName = page ?? defaultPage;
const pageNav = useSelector((state) => pageNavSelector(state, pageName, teamId));
const dispatch = useDispatch();
@ -83,6 +82,7 @@ const TeamPages = memo(() => {
if (canReadTeamPermissions) {
return <TeamPermissions team={team!} />;
}
return null;
case PageTypes.Settings:
return canReadTeam && <TeamSettings team={team!} />;
case PageTypes.GroupSync:

View File

@ -60,7 +60,7 @@ export function loadTeams(initial = false): ThunkResult<void> {
const loadTeamsWithDebounce = debounce((dispatch) => dispatch(loadTeams()), 500);
export function loadTeam(id: number): ThunkResult<Promise<void>> {
export function loadTeam(id: string | number): ThunkResult<Promise<void>> {
return async (dispatch) => {
const response = await getBackendSrv().get(`/api/teams/${id}`, accessControlQueryParam());
dispatch(teamLoaded(response));