Merge pull request #6243 from Sainsburys/6180-add-tech-radar-id

Add an optional id prop and pass to load API
This commit is contained in:
Fredrik Adelöw
2021-07-01 09:55:21 +02:00
committed by GitHub
6 changed files with 58 additions and 16 deletions
+7 -1
View File
@@ -82,7 +82,9 @@ import {
} from '@backstage/plugin-tech-radar';
class MyOwnClient implements TechRadarApi {
async load(): Promise<TechRadarLoaderResponse> {
async load(id: string | undefined): Promise<TechRadarLoaderResponse> {
// if needed id prop can be used to fetch the correct data
const data = await fetch('https://mydata.json').then(res => res.json());
// maybe you'll need to do some data transformation here to make it look like TechRadarLoaderResponse
@@ -120,3 +122,7 @@ You can use the `svgProps` option to pass custom React props to the `<svg>` elem
// const { getByTestId } = render(...);
// expect(getByTestId('tech-radar-svg')).toBeInTheDocument();
```
### How do I support multiple radars
The `TechRadarPage` and `TechRadarComponent` components both take an optional `id` prop which is subsequently passed to the `load` method of the API to distinguish which radar's data to load.
+6 -5
View File
@@ -46,7 +46,7 @@ export interface RadarQuadrant {
name: string;
}
// @public
// @public (undocumented)
export interface RadarRing {
// (undocumented)
color: string;
@@ -68,8 +68,7 @@ export const Router: {
// @public (undocumented)
export interface TechRadarApi {
// (undocumented)
load: () => Promise<TechRadarLoaderResponse>;
load: (id: string | undefined) => Promise<TechRadarLoaderResponse>;
}
// @public (undocumented)
@@ -78,17 +77,19 @@ export const techRadarApiRef: ApiRef<TechRadarApi>;
// @public (undocumented)
export const TechRadarComponent: (props: TechRadarComponentProps) => JSX.Element;
// @public
// @public (undocumented)
export interface TechRadarComponentProps {
// (undocumented)
height: number;
// (undocumented)
id?: string;
// (undocumented)
svgProps?: object;
// (undocumented)
width: number;
}
// @public
// @public (undocumented)
export interface TechRadarLoaderResponse {
// (undocumented)
entries: RadarEntry[];
+9 -5
View File
@@ -23,11 +23,14 @@ export const techRadarApiRef = createApiRef<TechRadarApi>({
});
export interface TechRadarApi {
// Loads the TechRadar response data to pass through to the TechRadar component
load: () => Promise<TechRadarLoaderResponse>;
/**
* Loads the TechRadar response data to pass through to the TechRadar component.
* Takes the id prop of the TechRadarComponent or TechRadarPage to distinguish between multiple radars if needed
*/
load: (id: string | undefined) => Promise<TechRadarLoaderResponse>;
}
/**
/*
* Types related to the Radar's visualization.
*/
@@ -59,7 +62,7 @@ export interface RadarEntrySnapshot {
moved?: MovedState;
}
/**
/*
* Types related to data collection for the Radar.
*/
@@ -69,11 +72,12 @@ export interface TechRadarLoaderResponse {
entries: RadarEntry[];
}
/**
/*
* Set up the Radar as a Backstage component.
*/
export interface TechRadarComponentProps {
id?: string;
width: number;
height: number;
svgProps?: object;
@@ -27,13 +27,14 @@ import { Entry } from '../utils/types';
import { Progress } from '@backstage/core-components';
import { useApi, errorApiRef } from '@backstage/core-plugin-api';
const useTechRadarLoader = () => {
const useTechRadarLoader = (id: string | undefined) => {
const errorApi = useApi(errorApiRef);
const techRadarApi = useApi(techRadarApiRef);
const { error, value, loading } = useAsync(async () => techRadarApi.load(), [
techRadarApi,
]);
const { error, value, loading } = useAsync(
async () => techRadarApi.load(id),
[techRadarApi],
);
useEffect(() => {
if (error) {
@@ -45,7 +46,7 @@ const useTechRadarLoader = () => {
};
const RadarComponent = (props: TechRadarComponentProps): JSX.Element => {
const { loading, error, value: data } = useTechRadarLoader();
const { loading, error, value: data } = useTechRadarLoader(props.id);
const mapToEntries = (
loaderResponse: TechRadarLoaderResponse | undefined,
@@ -85,6 +85,7 @@ describe('RadarPage', () => {
height: 800,
svgProps: { 'data-testid': 'tech-radar-svg' },
};
jest.spyOn(mockClient, 'load');
const { getByText, getByTestId } = await renderInTestApp(
<ThemeProvider theme={lightTheme}>
@@ -100,6 +101,30 @@ describe('RadarPage', () => {
getByText('Pick the recommended technologies for your projects'),
).toBeInTheDocument();
expect(getByTestId('tech-radar-svg')).toBeInTheDocument();
expect(mockClient.load).toBeCalledWith(undefined);
});
it('should call load with id', async () => {
const techRadarProps = {
width: 1200,
height: 800,
svgProps: { 'data-testid': 'tech-radar-svg' },
id: 'myId',
};
jest.spyOn(mockClient, 'load');
const { getByTestId } = await renderInTestApp(
<ThemeProvider theme={lightTheme}>
<ApiProvider apis={ApiRegistry.from([[techRadarApiRef, mockClient]])}>
<RadarPage {...techRadarProps} />
</ApiProvider>
</ThemeProvider>,
);
await waitForElement(() => getByTestId('tech-radar-svg'));
expect(getByTestId('tech-radar-svg')).toBeInTheDocument();
expect(mockClient.load).toBeCalledWith('myId');
});
it('should call the errorApi if load fails', async () => {