Introduce useRouteRefParams to core-api to retrieve typed route params
Signed-off-by: Oliver Sand <oliver.sand@sda-se.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
---
|
||||
'@backstage/core-api': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
'@backstage/plugin-github-actions': patch
|
||||
'@backstage/plugin-jenkins': patch
|
||||
---
|
||||
|
||||
Introduce `useRouteRefParams` to `core-api` to retrieve typed route parameters.
|
||||
@@ -14,35 +14,35 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import React, {
|
||||
Context,
|
||||
PropsWithChildren,
|
||||
ReactElement,
|
||||
useContext,
|
||||
Context,
|
||||
} from 'react';
|
||||
import { MemoryRouter, Routes } from 'react-router-dom';
|
||||
import { render } from '@testing-library/react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { VersionedValue } from '../lib/versionedValues';
|
||||
import { getGlobalSingleton } from '../lib/globalObject';
|
||||
import { MemoryRouter, Route, Routes } from 'react-router-dom';
|
||||
import { createRoutableExtension } from '../extensions';
|
||||
import {
|
||||
childDiscoverer,
|
||||
routeElementDiscoverer,
|
||||
traverseElementTree,
|
||||
} from '../extensions/traversal';
|
||||
import { getGlobalSingleton } from '../lib/globalObject';
|
||||
import { VersionedValue } from '../lib/versionedValues';
|
||||
import { createPlugin } from '../plugin';
|
||||
import {
|
||||
routePathCollector,
|
||||
routeParentCollector,
|
||||
routeObjectCollector,
|
||||
routeParentCollector,
|
||||
routePathCollector,
|
||||
} from './collectors';
|
||||
import { validateRoutes } from './validation';
|
||||
import { useRouteRef, RoutingProvider } from './hooks';
|
||||
import { createExternalRouteRef } from './ExternalRouteRef';
|
||||
import { RoutingProvider, useRouteRef, useRouteRefParams } from './hooks';
|
||||
import { createRouteRef, RouteRefConfig } from './RouteRef';
|
||||
import { RouteResolver } from './RouteResolver';
|
||||
import { createExternalRouteRef } from './ExternalRouteRef';
|
||||
import { AnyRouteRef, RouteFunc, RouteRef, ExternalRouteRef } from './types';
|
||||
import { AnyRouteRef, ExternalRouteRef, RouteFunc, RouteRef } from './types';
|
||||
import { validateRoutes } from './validation';
|
||||
|
||||
const mockConfig = (extra?: Partial<RouteRefConfig<{}>>) => ({
|
||||
path: '/unused',
|
||||
@@ -370,3 +370,36 @@ describe('v1 consumer', () => {
|
||||
expect(renderedHook.result.current?.({ x: 'my-x' })).toBe('/bar/my-x');
|
||||
});
|
||||
});
|
||||
|
||||
describe('useRouteRefParams', () => {
|
||||
it('should provide types params', () => {
|
||||
const routeRef = createRouteRef({
|
||||
id: 'ref1',
|
||||
params: ['a', 'b'],
|
||||
});
|
||||
|
||||
const Page = () => {
|
||||
const params: { a: string; b: string } = useRouteRefParams(routeRef);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<span>{params.a}</span>
|
||||
<span>{params.b}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const { getByText } = render(
|
||||
<MemoryRouter initialEntries={['/foo/bar']}>
|
||||
<Routes>
|
||||
<Route path="/:a/:b">
|
||||
<Page />
|
||||
</Route>
|
||||
</Routes>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
expect(getByText('foo')).toBeInTheDocument();
|
||||
expect(getByText('bar')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@ import React, {
|
||||
useMemo,
|
||||
Context,
|
||||
} from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useLocation, useParams } from 'react-router-dom';
|
||||
import {
|
||||
BackstageRouteObject,
|
||||
RouteRef,
|
||||
@@ -111,3 +111,9 @@ export const RoutingProvider = ({
|
||||
</RoutingContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export function useRouteRefParams<Params extends AnyParams>(
|
||||
_routeRef: RouteRef<Params> | SubRouteRef<Params>,
|
||||
): Params {
|
||||
return useParams() as Params;
|
||||
}
|
||||
|
||||
@@ -14,17 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { createExternalRouteRef } from './ExternalRouteRef';
|
||||
export { FlatRoutes } from './FlatRoutes';
|
||||
export { useRouteRef, useRouteRefParams } from './hooks';
|
||||
export { createRouteRef } from './RouteRef';
|
||||
export type { RouteRefConfig } from './RouteRef';
|
||||
export { createSubRouteRef } from './SubRouteRef';
|
||||
export type {
|
||||
RouteRef,
|
||||
SubRouteRef,
|
||||
AbsoluteRouteRef,
|
||||
ConcreteRoute,
|
||||
MutableRouteRef,
|
||||
ExternalRouteRef,
|
||||
MutableRouteRef,
|
||||
RouteRef,
|
||||
SubRouteRef,
|
||||
} from './types';
|
||||
export { FlatRoutes } from './FlatRoutes';
|
||||
export { createRouteRef } from './RouteRef';
|
||||
export { createSubRouteRef } from './SubRouteRef';
|
||||
export { createExternalRouteRef } from './ExternalRouteRef';
|
||||
export type { RouteRefConfig } from './RouteRef';
|
||||
export { useRouteRef } from './hooks';
|
||||
|
||||
@@ -13,12 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { useParams } from 'react-router';
|
||||
import { useRouteRefParams } from '@backstage/core';
|
||||
import { entityRouteRef } from '../routes';
|
||||
|
||||
/**
|
||||
* Grabs entity kind, namespace, and name from the location
|
||||
*/
|
||||
export const useEntityCompoundName = () => {
|
||||
const { kind, namespace, name } = useParams();
|
||||
const { kind, namespace, name } = useRouteRefParams(entityRouteRef);
|
||||
return { kind, namespace, name };
|
||||
};
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { useApi } from '@backstage/core';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useApi, useRouteRefParams } from '@backstage/core';
|
||||
import { useAsync } from 'react-use';
|
||||
import { githubActionsApiRef } from '../../api';
|
||||
import { buildRouteRef } from '../../plugin';
|
||||
|
||||
export const useWorkflowRunsDetails = ({
|
||||
hostname,
|
||||
@@ -28,7 +28,7 @@ export const useWorkflowRunsDetails = ({
|
||||
repo: string;
|
||||
}) => {
|
||||
const api = useApi(githubActionsApiRef);
|
||||
const { id } = useParams();
|
||||
const { id } = useRouteRefParams(buildRouteRef);
|
||||
const details = useAsync(async () => {
|
||||
return repo && owner
|
||||
? api.getWorkflowRun({
|
||||
|
||||
@@ -33,6 +33,7 @@ export const rootRouteRef = createRouteRef({
|
||||
|
||||
export const buildRouteRef = createRouteRef({
|
||||
path: ':id',
|
||||
params: ['id'],
|
||||
title: 'GitHub Actions Workflow Run',
|
||||
});
|
||||
|
||||
|
||||
@@ -13,25 +13,25 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Breadcrumbs, Content, Link } from '@backstage/core';
|
||||
import { Breadcrumbs, Content, Link, useRouteRefParams } from '@backstage/core';
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
Paper,
|
||||
TableContainer,
|
||||
Table,
|
||||
TableRow,
|
||||
TableCell,
|
||||
TableBody,
|
||||
Link as MaterialLink,
|
||||
Paper,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableRow,
|
||||
Typography,
|
||||
} from '@material-ui/core';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import ExternalLinkIcon from '@material-ui/icons/Launch';
|
||||
import React from 'react';
|
||||
import { buildRouteRef } from '../../plugin';
|
||||
import { JenkinsRunStatus } from '../BuildsPage/lib/Status';
|
||||
import { useBuildWithSteps } from '../useBuildWithSteps';
|
||||
import { useProjectSlugFromEntity } from '../useProjectSlugFromEntity';
|
||||
import { JenkinsRunStatus } from '../BuildsPage/lib/Status';
|
||||
import ExternalLinkIcon from '@material-ui/icons/Launch';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
root: {
|
||||
@@ -48,7 +48,7 @@ const useStyles = makeStyles(theme => ({
|
||||
|
||||
const BuildWithStepsView = () => {
|
||||
const projectName = useProjectSlugFromEntity();
|
||||
const { branch, buildNumber } = useParams();
|
||||
const { branch, buildNumber } = useRouteRefParams(buildRouteRef);
|
||||
const classes = useStyles();
|
||||
const buildPath = `${projectName}/${branch}/${buildNumber}`;
|
||||
const [{ value }] = useBuildWithSteps(buildPath);
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
createPlugin,
|
||||
createRouteRef,
|
||||
createApiFactory,
|
||||
discoveryApiRef,
|
||||
createRoutableExtension,
|
||||
createComponentExtension,
|
||||
createPlugin,
|
||||
createRoutableExtension,
|
||||
createRouteRef,
|
||||
discoveryApiRef,
|
||||
} from '@backstage/core';
|
||||
import { jenkinsApiRef, JenkinsApi } from './api';
|
||||
import { JenkinsApi, jenkinsApiRef } from './api';
|
||||
|
||||
export const rootRouteRef = createRouteRef({
|
||||
path: '',
|
||||
@@ -31,6 +31,7 @@ export const rootRouteRef = createRouteRef({
|
||||
|
||||
export const buildRouteRef = createRouteRef({
|
||||
path: 'run/:branch/:buildNumber',
|
||||
params: ['branch', 'buildNumber'],
|
||||
title: 'Jenkins run',
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user