From 075808940c0b033f14477d705867d6e4ae0cc930 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Mon, 20 Sep 2021 12:42:31 +0200 Subject: [PATCH] Review comments Signed-off-by: Oliver Sand --- .changeset/wicked-pugs-speak.md | 8 ------- .../app/src/components/catalog/EntityPage.tsx | 14 ++++------- plugins/catalog-graph/api-report.md | 14 +++++------ plugins/catalog-graph/package.json | 4 +++- .../CatalogGraphCard.test.tsx | 1 + .../CatalogGraphCard/CatalogGraphCard.tsx | 24 +++++++++---------- .../CatalogGraphPage.test.tsx | 1 + .../CatalogGraphPage/CatalogGraphPage.tsx | 10 ++++---- .../SelectedKindsFilter.test.tsx | 14 ++++++++--- .../CatalogGraphPage/SelectedKindsFilter.tsx | 2 +- .../SelectedRelationsFilter.test.tsx | 12 +++++----- .../SelectedRelationsFilter.tsx | 5 +--- .../useCatalogGraphPage.test.ts | 20 +++++++++++++--- .../CatalogGraphPage/useCatalogGraphPage.ts | 2 +- .../EntityRelationsGraph.test.tsx | 3 ++- .../EntityRelationsGraph.tsx | 6 ++--- .../components/EntityRelationsGraph/index.ts | 2 +- .../EntityRelationsGraph/relations.ts | 2 +- .../components/EntityRelationsGraph/types.ts | 2 +- .../useEntityRelationGraph.test.ts | 4 +++- .../useEntityRelationGraph.ts | 5 ++-- .../useEntityRelationNodesAndEdges.test.ts | 6 +++-- .../useEntityRelationNodesAndEdges.ts | 11 +++++---- .../useEntityStore.test.ts | 7 ++++-- .../EntityRelationsGraph/useEntityStore.ts | 9 +++---- plugins/catalog-graph/src/plugin.ts | 2 +- 26 files changed, 107 insertions(+), 83 deletions(-) delete mode 100644 .changeset/wicked-pugs-speak.md diff --git a/.changeset/wicked-pugs-speak.md b/.changeset/wicked-pugs-speak.md deleted file mode 100644 index 620be91773..0000000000 --- a/.changeset/wicked-pugs-speak.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/plugin-catalog-graph': patch ---- - -Add new plugin `@backstage/plugin-catalog-graph`. The catalog graph visualizes -the relations between entities, like ownership, grouping or API relationships. - -For more details on adding the plugin to your Backstage instance, [see the README](https://github.com/backstage/backstage/blob/master/plugins/catalog-graph/README.md). diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 7ccfb059ea..62fdcf4d3f 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -47,7 +47,6 @@ import { EntityOrphanWarning, EntityProcessingErrorsPanel, EntitySwitch, - EntitySystemDiagramCard, hasCatalogProcessingErrors, isComponentType, isKind, @@ -265,7 +264,7 @@ const overviewContent = ( - + @@ -476,7 +475,7 @@ const apiPage = ( - + @@ -545,7 +544,7 @@ const systemPage = ( - + @@ -559,14 +558,11 @@ const systemPage = ( - - - - + diff --git a/plugins/catalog-graph/api-report.md b/plugins/catalog-graph/api-report.md index 9131c45ba3..fd9999dc4a 100644 --- a/plugins/catalog-graph/api-report.md +++ b/plugins/catalog-graph/api-report.md @@ -14,6 +14,9 @@ import { MouseEvent as MouseEvent_2 } from 'react'; import { MouseEventHandler } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; +// @public +export const ALL_RELATION_PAIRS: RelationPairs; + // @public export const CatalogGraphPage: ({ relationPairs, @@ -72,7 +75,7 @@ export const EntityCatalogGraphCard: ({ kinds, relations, direction, - maxHeight, + height, title, }: { variant?: InfoCardVariants | undefined; @@ -83,7 +86,7 @@ export const EntityCatalogGraphCard: ({ kinds?: string[] | undefined; relations?: string[] | undefined; direction?: Direction | undefined; - maxHeight?: number | undefined; + height?: number | undefined; title?: string | undefined; }) => JSX.Element; @@ -101,7 +104,7 @@ export type EntityNode = DependencyGraphTypes.DependencyNode<{ namespace: string; focused?: boolean; color?: 'primary' | 'secondary' | 'default'; - onClick?: MouseEventHandler; + onClick?: MouseEventHandler; }>; // @public @@ -125,15 +128,12 @@ export const EntityRelationsGraph: ({ relations?: string[] | undefined; direction?: Direction | undefined; onNodeClick?: - | ((value: EntityNode, event: MouseEvent_2) => void) + | ((value: EntityNode, event: MouseEvent_2) => void) | undefined; relationPairs?: RelationPairs | undefined; className?: string | undefined; }) => JSX.Element; -// @public -export const RELATION_PAIRS: RelationPairs; - // @public export type RelationPairs = [string, string][]; ``` diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 19cd658e28..6073d6be91 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -3,7 +3,8 @@ "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", - "private": true, + "license": "Apache-2.0", + "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -29,6 +30,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", + "@types/react": "*", "react": "^16.13.1", "react-dom": "^16.13.1", "react-use": "^17.2.4", diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx index 514f8c2cf5..8207517e03 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx @@ -56,6 +56,7 @@ describe('', () => { getLocationByEntity: jest.fn(), addLocation: jest.fn(), removeLocationById: jest.fn(), + refreshEntity: jest.fn(), }; apis = ApiRegistry.with(catalogApiRef, catalog); diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx index bb61e622e4..abb10d4008 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx @@ -31,15 +31,15 @@ import { EntityNode, EntityRelationsGraph, RelationPairs, - RELATION_PAIRS, + ALL_RELATION_PAIRS, } from '../EntityRelationsGraph'; -const useStyles = makeStyles({ - card: ({ maxHeight }) => ({ +const useStyles = makeStyles({ + card: ({ height }) => ({ display: 'flex', flexDirection: 'column', - maxHeight, - minHeight: 0, + maxHeight: height, + minHeight: height, }), graph: { flex: 1, @@ -49,14 +49,14 @@ const useStyles = makeStyles({ export const CatalogGraphCard = ({ variant = 'gridItem', - relationPairs = RELATION_PAIRS, + relationPairs = ALL_RELATION_PAIRS, maxDepth = 1, unidirectional = true, mergeRelations = true, kinds, relations, direction = Direction.LEFT_RIGHT, - maxHeight, + height, title = 'Relations', }: { variant?: InfoCardVariants; @@ -67,7 +67,7 @@ export const CatalogGraphCard = ({ kinds?: string[]; relations?: string[]; direction?: Direction; - maxHeight?: number; + height?: number; title?: string; }) => { const { entity } = useEntity(); @@ -75,14 +75,14 @@ export const CatalogGraphCard = ({ const catalogEntityRoute = useRouteRef(catalogEntityRouteRef); const catalogGraphRoute = useRouteRef(catalogGraphRouteRef); const navigate = useNavigate(); - const classes = useStyles({ maxHeight }); + const classes = useStyles({ height }); const onNodeClick = useCallback( - (node: EntityNode, _: MouseEvent) => { + (node: EntityNode, _: MouseEvent) => { const nodeEntityName = parseEntityRef(node.id); const path = catalogEntityRoute({ - kind: nodeEntityName.kind.toLowerCase(), - namespace: nodeEntityName.namespace.toLowerCase(), + kind: nodeEntityName.kind.toLocaleLowerCase('en-US'), + namespace: nodeEntityName.namespace.toLocaleLowerCase('en-US'), name: nodeEntityName.name, }); navigate(path); diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx index 8902c49845..c291faadbd 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx @@ -86,6 +86,7 @@ describe('', () => { getLocationByEntity: jest.fn(), addLocation: jest.fn(), removeLocationById: jest.fn(), + refreshEntity: jest.fn(), }; const apis = ApiRegistry.with(catalogApiRef, catalog); diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx index 53b7a80414..0ad50a8174 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx @@ -35,7 +35,7 @@ import { EntityNode, EntityRelationsGraph, RelationPairs, - RELATION_PAIRS, + ALL_RELATION_PAIRS, } from '../EntityRelationsGraph'; import { DirectionFilter } from './DirectionFilter'; import { MaxDepthFilter } from './MaxDepthFilter'; @@ -97,7 +97,7 @@ const useStyles = makeStyles(theme => ({ })); export const CatalogGraphPage = ({ - relationPairs = RELATION_PAIRS, + relationPairs = ALL_RELATION_PAIRS, initialState, }: { relationPairs?: RelationPairs; @@ -134,13 +134,13 @@ export const CatalogGraphPage = ({ toggleShowFilters, } = useCatalogGraphPage({ initialState }); const onNodeClick = useCallback( - (node: EntityNode, event: MouseEvent) => { + (node: EntityNode, event: MouseEvent) => { const nodeEntityName = parseEntityRef(node.id); if (event.shiftKey) { const path = catalogEntityRoute({ - kind: nodeEntityName.kind.toLowerCase(), - namespace: nodeEntityName.namespace.toLowerCase(), + kind: nodeEntityName.kind.toLocaleLowerCase('en-US'), + namespace: nodeEntityName.namespace.toLocaleLowerCase('en-US'), name: nodeEntityName.name, }); navigate(path); diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedKindsFilter.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedKindsFilter.test.tsx index 71613fab71..c98c77c975 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedKindsFilter.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedKindsFilter.test.tsx @@ -23,21 +23,29 @@ import { SelectedKindsFilter } from './SelectedKindsFilter'; jest.mock('@backstage/core-plugin-api'); jest.mock('@backstage/plugin-catalog-react'); -const useApi = useApiMocked as jest.Mock; -const useEntityKinds = useEntityKindsMocked as jest.Mock; +const useApi = useApiMocked as jest.Mock>; +const useEntityKinds = useEntityKindsMocked as jest.Mock< + ReturnType +>; describe('', () => { beforeEach(() => { useApi.mockReturnValue({}); useEntityKinds.mockReturnValue({ + loading: false, kinds: ['API', 'Component', 'System', 'Domain', 'Resource'], + error: undefined, }); }); afterEach(() => jest.resetAllMocks()); test('should not explode while loading', () => { - useEntityKinds.mockReturnValue({}); + useEntityKinds.mockReturnValue({ + loading: true, + kinds: undefined, + error: undefined, + }); const { baseElement } = render( {}} />, ); diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedKindsFilter.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedKindsFilter.tsx index 333f0d6795..87ba8e77bf 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedKindsFilter.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedKindsFilter.tsx @@ -55,7 +55,7 @@ export const SelectedKindsFilter = ({ value, onChange }: Props) => { }, [error, alertApi]); const normalizedKinds = useMemo( - () => (kinds ? kinds.map(k => k.toLowerCase()) : kinds), + () => (kinds ? kinds.map(k => k.toLocaleLowerCase('en-US')) : kinds), [kinds], ); diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedRelationsFilter.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedRelationsFilter.test.tsx index a5be4a708b..49f264fc0d 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedRelationsFilter.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedRelationsFilter.test.tsx @@ -21,14 +21,14 @@ import { import { render, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { RELATION_PAIRS } from '../EntityRelationsGraph'; +import { ALL_RELATION_PAIRS } from '../EntityRelationsGraph'; import { SelectedRelationsFilter } from './SelectedRelationsFilter'; describe('', () => { test('should render current value', () => { const { getByText } = render( {}} />, @@ -42,7 +42,7 @@ describe('', () => { const onChange = jest.fn(); const { getByText, getByLabelText } = render( , @@ -69,8 +69,8 @@ describe('', () => { const onChange = jest.fn(); const { getByText, getByLabelText } = render( p).filter( + relationPairs={ALL_RELATION_PAIRS} + value={ALL_RELATION_PAIRS.flatMap(p => p).filter( r => r !== RELATION_HAS_MEMBER, )} onChange={onChange} @@ -94,7 +94,7 @@ describe('', () => { const onChange = jest.fn(); const { getByRole } = render( , diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedRelationsFilter.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedRelationsFilter.tsx index f49d5248b3..839bfbe425 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedRelationsFilter.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/SelectedRelationsFilter.tsx @@ -46,10 +46,7 @@ export const SelectedRelationsFilter = ({ onChange, }: Props) => { const classes = useStyles(); - const relations = useMemo( - () => relationPairs.flatMap(r => r), - [relationPairs], - ); + const relations = useMemo(() => relationPairs.flat(), [relationPairs]); const handleChange = useCallback( (_: unknown, v: string[]) => { diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts b/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts index 46ea667c14..f536190e43 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts @@ -26,14 +26,24 @@ jest.mock('react-router', () => ({ jest.spyOn(window.history, 'replaceState'); jest.spyOn(window.history, 'pushState'); -const useLocation = useLocationMocked as jest.Mock; -const windowHistoryReplaceState = window.history.replaceState as jest.Mock; -const windowHistoryPushState = window.history.replaceState as jest.Mock; +const useLocation = useLocationMocked as jest.Mock< + ReturnType +>; +const windowHistoryReplaceState = window.history.replaceState as jest.Mock< + ReturnType +>; +const windowHistoryPushState = window.history.pushState as jest.Mock< + ReturnType +>; describe('useCatalogGraphPage', () => { beforeEach(() => { useLocation.mockReturnValue({ search: '?', + state: {}, + key: '', + pathname: '', + hash: '', }); }); @@ -71,6 +81,10 @@ describe('useCatalogGraphPage', () => { useLocation.mockReturnValueOnce({ search: '?rootEntityRefs[]=b:d/c&maxDepth=2&direction=RL&mergeRelations=false&unidirectional=false&showFilters=false&selectedKinds[]=api&selectedRelations[]=memberOf', + state: {}, + key: '', + pathname: '', + hash: '', }); const { result } = renderHook(() => useCatalogGraphPage({})); diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.ts b/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.ts index b23a218f50..e802a672c6 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.ts +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.ts @@ -104,7 +104,7 @@ export function useCatalogGraphPage({ (Array.isArray(query.selectedKinds) ? query.selectedKinds : initialState?.selectedKinds - )?.map(k => k.toLowerCase()), + )?.map(k => k.toLocaleLowerCase('en-US')), ); const [unidirectional, setUnidirectional] = useState(() => typeof query.unidirectional === 'string' diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx index 20211df7cd..fe3bef3e84 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx @@ -40,7 +40,7 @@ describe('', () => { }); beforeEach(() => { - const entities: { [key: string]: Entity } = { + const entities: { [ref: string]: Entity } = { 'b:d/c': { apiVersion: 'a', kind: 'b', @@ -155,6 +155,7 @@ describe('', () => { getLocationByEntity: jest.fn(), addLocation: jest.fn(), removeLocationById: jest.fn(), + refreshEntity: jest.fn(), }; const apis = ApiRegistry.with(catalogApiRef, catalog); diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx index 9dc54e00b2..0f1e72d8b2 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx @@ -24,7 +24,7 @@ import classNames from 'classnames'; import React, { MouseEvent, useEffect, useMemo } from 'react'; import { CustomLabel } from './CustomLabel'; import { CustomNode } from './CustomNode'; -import { RelationPairs, RELATION_PAIRS } from './relations'; +import { RelationPairs, ALL_RELATION_PAIRS } from './relations'; import { Direction, EntityNode } from './types'; import { useEntityRelationNodesAndEdges } from './useEntityRelationNodesAndEdges'; @@ -73,7 +73,7 @@ export const EntityRelationsGraph = ({ relations, direction = Direction.LEFT_RIGHT, onNodeClick, - relationPairs = RELATION_PAIRS, + relationPairs = ALL_RELATION_PAIRS, className, }: { rootEntityNames: EntityName | EntityName[]; @@ -83,7 +83,7 @@ export const EntityRelationsGraph = ({ kinds?: string[]; relations?: string[]; direction?: Direction; - onNodeClick?: (value: EntityNode, event: MouseEvent) => void; + onNodeClick?: (value: EntityNode, event: MouseEvent) => void; relationPairs?: RelationPairs; className?: string; }) => { diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts index a8b8c3d1b1..63ac9c2eac 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ export { EntityRelationsGraph } from './EntityRelationsGraph'; -export { RELATION_PAIRS } from './relations'; +export { ALL_RELATION_PAIRS } from './relations'; export type { RelationPairs } from './relations'; export { Direction } from './types'; export type { EntityEdge, EntityNode } from './types'; diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/relations.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/relations.ts index 054cf79c9f..ed847d7143 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/relations.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/relations.ts @@ -49,7 +49,7 @@ export type RelationPairs = [string, string][]; * * @public */ -export const RELATION_PAIRS: RelationPairs = [ +export const ALL_RELATION_PAIRS: RelationPairs = [ [RELATION_OWNER_OF, RELATION_OWNED_BY], [RELATION_CONSUMES_API, RELATION_API_CONSUMED_BY], [RELATION_API_PROVIDED_BY, RELATION_PROVIDES_API], diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/types.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/types.ts index b5a65580c0..d6bda71a33 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/types.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/types.ts @@ -67,7 +67,7 @@ export type EntityNode = DependencyGraphTypes.DependencyNode<{ /** * Optional click handler. */ - onClick?: MouseEventHandler; + onClick?: MouseEventHandler; }>; export type GraphEdge = DependencyGraphTypes.GraphEdge; diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts index ef5ceaf293..bf6fc9ee3f 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts @@ -26,7 +26,9 @@ import { useEntityStore as useEntityStoreMocked } from './useEntityStore'; jest.mock('./useEntityStore'); -const useEntityStore = useEntityStoreMocked as jest.Mock; +const useEntityStore = useEntityStoreMocked as jest.Mock< + ReturnType +>; describe('useEntityRelationGraph', () => { const requestEntities = jest.fn(); diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.ts index f7de4b2c1a..e0d393168b 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.ts @@ -33,7 +33,7 @@ export function useEntityRelationGraph({ kinds?: string[]; }; }): { - entities?: { [key: string]: Entity }; + entities?: { [ref: string]: Entity }; loading: boolean; error?: Error; } { @@ -63,7 +63,8 @@ export function useEntityRelationGraph({ for (const rel of entity.relations) { if ( (!relations || relations.includes(rel.type)) && - (!kinds || kinds.includes(rel.target.kind.toLowerCase())) + (!kinds || + kinds.includes(rel.target.kind.toLocaleLowerCase('en-US'))) ) { const relationEntityRef = stringifyEntityRef(rel.target); diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts index 297cb44dd6..37073352d6 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts @@ -28,11 +28,13 @@ import { useEntityRelationNodesAndEdges } from './useEntityRelationNodesAndEdges jest.mock('./useEntityRelationGraph'); -const useEntityRelationGraph = useEntityRelationGraphMocked as jest.Mock; +const useEntityRelationGraph = useEntityRelationGraphMocked as jest.Mock< + ReturnType +>; describe('useEntityRelationNodesAndEdges', () => { beforeEach(() => { - const entities: { [key: string]: Entity } = { + const entities: { [ref: string]: Entity } = { 'b:d/c': { apiVersion: 'a', kind: 'b', diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts index adda230e94..4fc00c5353 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts @@ -19,7 +19,7 @@ import { } from '@backstage/catalog-model'; import { MouseEvent, useState } from 'react'; import { useDebounce } from 'react-use'; -import { RelationPairs, RELATION_PAIRS } from './relations'; +import { RelationPairs, ALL_RELATION_PAIRS } from './relations'; import { EntityEdge, EntityNode } from './types'; import { useEntityRelationGraph } from './useEntityRelationGraph'; @@ -34,7 +34,7 @@ export function useEntityRelationNodesAndEdges({ kinds, relations, onNodeClick, - relationPairs = RELATION_PAIRS, + relationPairs = ALL_RELATION_PAIRS, }: { rootEntityRefs: string[]; maxDepth?: number; @@ -42,7 +42,7 @@ export function useEntityRelationNodesAndEdges({ mergeRelations?: boolean; kinds?: string[]; relations?: string[]; - onNodeClick?: (value: EntityNode, event: MouseEvent) => void; + onNodeClick?: (value: EntityNode, event: MouseEvent) => void; relationPairs?: RelationPairs; }): { loading: boolean; @@ -112,7 +112,10 @@ export function useEntityRelationNodesAndEdges({ return; } - if (kinds && !kinds.includes(rel.target.kind.toLowerCase())) { + if ( + kinds && + !kinds.includes(rel.target.kind.toLocaleLowerCase('en-US')) + ) { return; } diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts index d0f63fdc2b..2675469c15 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts @@ -14,13 +14,15 @@ * limitations under the License. */ import { Entity } from '@backstage/catalog-model'; -import { useApi } from '@backstage/core-plugin-api'; +import { useApi as useApiMocked } from '@backstage/core-plugin-api'; import { CatalogApi } from '@backstage/plugin-catalog-react'; import { act, renderHook } from '@testing-library/react-hooks'; import { useEntityStore } from './useEntityStore'; jest.mock('@backstage/core-plugin-api'); +const useApi = useApiMocked as jest.Mocked; + describe('useEntityStore', () => { let catalogApi: jest.Mocked; @@ -34,9 +36,10 @@ describe('useEntityStore', () => { getLocationByEntity: jest.fn(), addLocation: jest.fn(), removeLocationById: jest.fn(), + refreshEntity: jest.fn(), }; - (useApi as jest.Mock).mockReturnValue(catalogApi); + useApi.mockReturnValue(catalogApi); }); afterEach(() => jest.resetAllMocks()); diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts index 8637cd6627..476c10b84f 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts @@ -23,11 +23,13 @@ import { useAsyncFn } from 'react-use'; // TODO: This is a good use case for a graphql API, once it is available in the // future. +const limiter = limiterFactory(10); + /** * Ensures that a set of requested entities is loaded. */ export function useEntityStore(): { - entities: { [key: string]: Entity }; + entities: { [ref: string]: Entity }; loading: boolean; error?: Error; requestEntities: Dispatch; @@ -39,12 +41,12 @@ export function useEntityStore(): { cachedEntities: new Map(), }); const [entities, setEntities] = useState<{ - [key: string]: Entity; + [ref: string]: Entity; }>({}); const updateEntities = useCallback(() => { const { cachedEntities, requestedEntities } = state.current; - const filteredEntities: { [key: string]: Entity } = {}; + const filteredEntities: { [ref: string]: Entity } = {}; requestedEntities.forEach(entityRef => { const entity = cachedEntities.get(entityRef); @@ -56,7 +58,6 @@ export function useEntityStore(): { }, [state, setEntities]); const [asyncState, fetch] = useAsyncFn(async () => { - const limiter = limiterFactory(10); const { requestedEntities, outstandingEntities, cachedEntities } = state.current; diff --git a/plugins/catalog-graph/src/plugin.ts b/plugins/catalog-graph/src/plugin.ts index b804ce1e63..7629caabee 100644 --- a/plugins/catalog-graph/src/plugin.ts +++ b/plugins/catalog-graph/src/plugin.ts @@ -21,7 +21,7 @@ import { catalogEntityRouteRef, catalogGraphRouteRef } from './routes'; * @public */ export const catalogGraphPlugin = createPlugin({ - id: '@internal/catalog-graph', + id: 'catalog-graph', routes: { catalogGraph: catalogGraphRouteRef, },