From 45a72eaa84d90983597a467a922e677e72e5a5f1 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 11 Feb 2021 16:15:20 -0500 Subject: [PATCH 01/40] Create new system page with diagram card Signed-off-by: Adam Harvey --- packages/app/src/components/catalog/EntityPage.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index fb56b40e68..1f0749bfbc 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -38,6 +38,7 @@ import { EntityHasSystemsCard, EntityLinksCard, EntityPageLayout, + SystemDiagram, } from '@backstage/plugin-catalog'; import { EntityProvider, useEntity } from '@backstage/plugin-catalog-react'; import { @@ -441,6 +442,9 @@ const SystemOverviewContent = ({ entity }: { entity: SystemEntity }) => ( + + + @@ -457,6 +461,11 @@ const SystemEntityPage = ({ entity }: { entity: Entity }) => ( title="Overview" element={} /> + } + /> ); @@ -478,6 +487,11 @@ const DomainEntityPage = ({ entity }: { entity: Entity }) => ( title="Overview" element={} /> + } + /> ); From 84a90447a83c726053feb9695c9f368dc760ceef Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 11 Feb 2021 16:44:23 -0500 Subject: [PATCH 02/40] Add SystemDiagram Signed-off-by: Adam Harvey --- .../SystemDiagram/SystemDiagram.tsx | 123 ++++++++++++++++++ .../src/components/SystemDiagram/index.ts | 17 +++ 2 files changed, 140 insertions(+) create mode 100644 plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx create mode 100644 plugins/catalog/src/components/SystemDiagram/index.ts diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx new file mode 100644 index 0000000000..ef3fd4bc2a --- /dev/null +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -0,0 +1,123 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { + DependencyGraph, + DependencyGraphTypes, + InfoCard, + Progress, + useApi, +} from '@backstage/core'; +import { Alert } from '@material-ui/lab'; +import React from 'react'; +import { useAsync } from 'react-use'; + +type SystemDiagramProps = { + entity: Entity; + variant?: string; +}; + +export function SystemDiagram({ entity }: SystemDiagramProps) { + const catalogApi = useApi(catalogApiRef); + const { loading, error, value: catalogResponse } = useAsync(() => { + return catalogApi.getEntities({ + filter: { + kind: ['Component', 'API', 'Resource', 'System', 'Domain'], + }, + }); + }, [catalogApi]); + + const systemNodes = []; + const systemEdges = []; + + if (catalogResponse && catalogResponse.items) { + // push the system knowing this was called with it + systemNodes.push({ id: `system:${entity.metadata.name}` }); + + // console.log('Found ' + catalogResponse.items.length + ' catalog items...'); + // loop through and push any found elements into the graph arrays + for (const catalogItem of catalogResponse.items) { + // console.log('Checking ' + catalogItem.metadata.name + '...'); + + // Process anything assigned to the system + // if (catalogItem.spec?.system && catalogItem.spec.system === entity.metadata.name) { + // systemNodes.push( { id: (catalogItem.kind + ':' + catalogItem.metadata.name).toLowerCase() } ); + // systemEdges.push( { from: (catalogItem.kind + ':' + catalogItem.metadata.name).toLowerCase(), + // to: ('system:' + entity.metadata.name).toLowerCase(), + // label: 'specd'}) + // } + + // Process relationships + if (catalogItem.relations) { + // console.log( + // 'Checking relations for ' + catalogItem.metadata.name + '...', + // ); + for (const relation of catalogItem.relations) { + // console.log(' - relation ' + relation.target.kind + '...'); + if ( + relation.target.kind === 'system' && + relation.target.name === entity.metadata.name + ) { + // console.log( + // ' + pushing a ' + catalogItem.kind + ' to the nodes...', + // ); + systemNodes.push({ + id: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), + }); + // this duplicates showing the relationship, which isn't valuable + // if (relation.type === 'partOf') { + // systemEdges.push({ + // from: (catalogItem.kind + ':' + catalogItem.metadata.name).toLowerCase(), + // to: (relation.target.kind + ':' + relation.target.name).toLowerCase(), + // label: relation.type, + // }); + // } + if (relation.type === 'hasPart') { + systemEdges.push({ + from: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), + to: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), + label: relation.type, + }); + } + } + } + } + } + } + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + // console.log('Resulting arrays:'); + // console.log(systemNodes); + // console.log(systemEdges); + + return ( + + + + ); +} diff --git a/plugins/catalog/src/components/SystemDiagram/index.ts b/plugins/catalog/src/components/SystemDiagram/index.ts new file mode 100644 index 0000000000..eee5479b5f --- /dev/null +++ b/plugins/catalog/src/components/SystemDiagram/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { SystemDiagram } from './SystemDiagram'; From 0cd7081d8da99f088c1dd76ad786dfc046b1e0c0 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 11 Feb 2021 20:35:57 -0500 Subject: [PATCH 03/40] Add export Signed-off-by: Adam Harvey --- plugins/catalog/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts index 800c5c4693..72e33defe7 100644 --- a/plugins/catalog/src/index.ts +++ b/plugins/catalog/src/index.ts @@ -17,6 +17,7 @@ export { AboutCard } from './components/AboutCard'; export { EntityLayout } from './components/EntityLayout'; export { EntityPageLayout } from './components/EntityPageLayout'; +export { SystemDiagram } from './components/SystemDiagram'; export * from './components/EntitySwitch'; export { Router } from './components/Router'; export { From 10d67a06370988fa9f50652e4d463168107c549c Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 11 Feb 2021 22:09:21 -0500 Subject: [PATCH 04/40] Refactor and clean up Signed-off-by: Adam Harvey --- .../SystemDiagram/SystemDiagram.tsx | 97 +++++++++---------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index ef3fd4bc2a..56f0946f35 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -42,57 +42,61 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { }); }, [catalogApi]); + const currentSystemName = entity.metadata.name; + const currentSystemNode = `system:${entity.metadata.name}`.toLowerCase(); const systemNodes = []; const systemEdges = []; if (catalogResponse && catalogResponse.items) { - // push the system knowing this was called with it - systemNodes.push({ id: `system:${entity.metadata.name}` }); - - // console.log('Found ' + catalogResponse.items.length + ' catalog items...'); - // loop through and push any found elements into the graph arrays for (const catalogItem of catalogResponse.items) { - // console.log('Checking ' + catalogItem.metadata.name + '...'); + // pick out the system itself + if (catalogItem.metadata.name === entity.metadata.name) { + systemNodes.push({ + id: currentSystemNode, + }); - // Process anything assigned to the system - // if (catalogItem.spec?.system && catalogItem.spec.system === entity.metadata.name) { - // systemNodes.push( { id: (catalogItem.kind + ':' + catalogItem.metadata.name).toLowerCase() } ); - // systemEdges.push( { from: (catalogItem.kind + ':' + catalogItem.metadata.name).toLowerCase(), - // to: ('system:' + entity.metadata.name).toLowerCase(), - // label: 'specd'}) - // } + // check if the system it has an assigned domain + // even if the domain object doesn't exist in the catalog, display it in the map + if (catalogItem.spec?.domain) { + systemNodes.push({ + id: `domain:${catalogItem.spec.domain}`.toLowerCase(), + }); + systemEdges.push({ + from: currentSystemNode, + to: `domain:${catalogItem.spec.domain}`.toLowerCase(), + label: 'part of', + }); + } + } - // Process relationships - if (catalogItem.relations) { - // console.log( - // 'Checking relations for ' + catalogItem.metadata.name + '...', - // ); - for (const relation of catalogItem.relations) { - // console.log(' - relation ' + relation.target.kind + '...'); - if ( - relation.target.kind === 'system' && - relation.target.name === entity.metadata.name - ) { - // console.log( - // ' + pushing a ' + catalogItem.kind + ' to the nodes...', - // ); - systemNodes.push({ - id: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), - }); - // this duplicates showing the relationship, which isn't valuable - // if (relation.type === 'partOf') { - // systemEdges.push({ - // from: (catalogItem.kind + ':' + catalogItem.metadata.name).toLowerCase(), - // to: (relation.target.kind + ':' + relation.target.name).toLowerCase(), - // label: relation.type, - // }); - // } - if (relation.type === 'hasPart') { - systemEdges.push({ - from: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), - to: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), - label: relation.type, - }); + // process any component assigned to the system + if (catalogItem.spec?.system === currentSystemName) { + systemNodes.push({ + id: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), + }); + + // check relations of the entity to see if it maps to anything in our map + // note those elements which are relations may, or may not, be explicitly + // assigned to the system + if (catalogItem.relations) { + for (const relation of catalogItem.relations) { + switch (relation.type) { + case 'providesApi': + systemEdges.push({ + to: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), + from: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), + label: 'provides API', + }); + break; + case 'partOf': + systemEdges.push({ + from: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), + to: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), + label: 'part of', + }); + break; + default: + break; } } } @@ -106,16 +110,11 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { return {error.message}; } - // console.log('Resulting arrays:'); - // console.log(systemNodes); - // console.log(systemEdges); - return ( From aa58c01e2cc08c3ca26ec3e87088f8ac5935e31e Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 11 Feb 2021 22:29:53 -0500 Subject: [PATCH 05/40] Add changeset Signed-off-by: Adam Harvey --- .changeset/perfect-coats-train.md | 60 +++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 .changeset/perfect-coats-train.md diff --git a/.changeset/perfect-coats-train.md b/.changeset/perfect-coats-train.md new file mode 100644 index 0000000000..a8c62d6264 --- /dev/null +++ b/.changeset/perfect-coats-train.md @@ -0,0 +1,60 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Adds a new `SystemDiagram` component to mvisually map all elements in a system. + +To use this new component, a new system entity page would need to be added to the `packages/app/src/components/catalog/EntityPage.tsx` file. + +For example, + +```tsx +const SystemOverviewContent = ({ entity }: { entity: Entity }) => ( + + + + + + + + +); + +const SystemEntityPage = ({ entity }: { entity: Entity }) => ( + + } + /> + } + /> + +); +``` + +And the addition of a new switch case to the `EntityPage`: + +```diff +-export const EntityPage = () => { +- const { entity } = useEntity(); +- +- switch (entity?.kind?.toLowerCase()) { +- case 'component': +- return ; +- case 'api': +- return ; +- case 'group': +- return ; +- case 'user': +- return ; ++ case 'system': ++ return ; +- default: +- return ; +- } +-}; +``` From 84fd2b8a4900ae486d5d291e1d8da03fe852a9a4 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 11 Feb 2021 22:31:16 -0500 Subject: [PATCH 06/40] Fix typo Signed-off-by: Adam Harvey --- .changeset/perfect-coats-train.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/perfect-coats-train.md b/.changeset/perfect-coats-train.md index a8c62d6264..f76778bcb0 100644 --- a/.changeset/perfect-coats-train.md +++ b/.changeset/perfect-coats-train.md @@ -2,7 +2,7 @@ '@backstage/plugin-catalog': patch --- -Adds a new `SystemDiagram` component to mvisually map all elements in a system. +Adds a new `SystemDiagram` component to visually map all elements in a system. To use this new component, a new system entity page would need to be added to the `packages/app/src/components/catalog/EntityPage.tsx` file. @@ -36,7 +36,7 @@ const SystemEntityPage = ({ entity }: { entity: Entity }) => ( ); ``` -And the addition of a new switch case to the `EntityPage`: +And the addition of a new switch case to the `EntityPage` object: ```diff -export const EntityPage = () => { From 63ba593edf31637ad9e3817a687e320438a7610a Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 11 Feb 2021 22:32:13 -0500 Subject: [PATCH 07/40] Update copyright year Signed-off-by: Adam Harvey --- plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx | 2 +- plugins/catalog/src/components/SystemDiagram/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index 56f0946f35..8523e3c4bd 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2020 Spotify AB + * Copyright 2021 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/plugins/catalog/src/components/SystemDiagram/index.ts b/plugins/catalog/src/components/SystemDiagram/index.ts index eee5479b5f..e086aed507 100644 --- a/plugins/catalog/src/components/SystemDiagram/index.ts +++ b/plugins/catalog/src/components/SystemDiagram/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 Spotify AB + * Copyright 2021 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 8eac71c77a22f0778b7a97c9e2c59de78d0c54d7 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 11 Feb 2021 22:33:57 -0500 Subject: [PATCH 08/40] Clarify comments Signed-off-by: Adam Harvey --- .../src/components/SystemDiagram/SystemDiagram.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index 8523e3c4bd..ff9ed10812 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -55,7 +55,7 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { id: currentSystemNode, }); - // check if the system it has an assigned domain + // check if the system has an assigned domain // even if the domain object doesn't exist in the catalog, display it in the map if (catalogItem.spec?.domain) { systemNodes.push({ @@ -69,14 +69,14 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { } } - // process any component assigned to the system + // process any entity assigned to the system if (catalogItem.spec?.system === currentSystemName) { systemNodes.push({ id: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), }); - // check relations of the entity to see if it maps to anything in our map - // note those elements which are relations may, or may not, be explicitly + // check relations of the entity to see if it relates to other entities + // note those relations may, or may not, be explicitly // assigned to the system if (catalogItem.relations) { for (const relation of catalogItem.relations) { From 131bfdea1494b47fccfd133e6c2b19794579e118 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 12 Feb 2021 13:33:04 -0500 Subject: [PATCH 09/40] Add horizontal padding Signed-off-by: Adam Harvey --- plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index ff9ed10812..6cd37918e1 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -115,6 +115,7 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { From 578ddb1d002ecc482d9fd13a8df677f462cdf9b5 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 12 Feb 2021 13:34:47 -0500 Subject: [PATCH 10/40] Move diagram to tab Signed-off-by: Adam Harvey --- packages/app/src/components/catalog/EntityPage.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 1f0749bfbc..56d99104ca 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -442,8 +442,8 @@ const SystemOverviewContent = ({ entity }: { entity: SystemEntity }) => ( - - + + @@ -492,6 +492,11 @@ const DomainEntityPage = ({ entity }: { entity: Entity }) => ( title="Docs" element={} /> + } + /> ); From 0a241bab6c679535ce2bbb56273527ac4c32b581 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 18 Feb 2021 15:07:34 -0500 Subject: [PATCH 11/40] Update changeset diff Signed-off-by: Adam Harvey --- .changeset/perfect-coats-train.md | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.changeset/perfect-coats-train.md b/.changeset/perfect-coats-train.md index f76778bcb0..4fe74acd5f 100644 --- a/.changeset/perfect-coats-train.md +++ b/.changeset/perfect-coats-train.md @@ -39,22 +39,22 @@ const SystemEntityPage = ({ entity }: { entity: Entity }) => ( And the addition of a new switch case to the `EntityPage` object: ```diff --export const EntityPage = () => { -- const { entity } = useEntity(); -- -- switch (entity?.kind?.toLowerCase()) { -- case 'component': -- return ; -- case 'api': -- return ; -- case 'group': -- return ; -- case 'user': -- return ; + export const EntityPage = () => { + const { entity } = useEntity(); + + switch (entity?.kind?.toLowerCase()) { + case 'component': + return ; + case 'api': + return ; + case 'group': + return ; + case 'user': + return ; + case 'system': + return ; -- default: -- return ; -- } --}; + default: + return ; + } + }; ``` From 9562b7bc8dda553a5a3e5b54f4f00c8086c7fa44 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 18 Feb 2021 15:28:22 -0500 Subject: [PATCH 12/40] Ref relations by constants Signed-off-by: Adam Harvey --- .../src/components/SystemDiagram/SystemDiagram.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index 6cd37918e1..b466e28a0c 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -14,7 +14,11 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; +import { + Entity, + RELATION_PROVIDES_API, + RELATION_PART_OF, +} from '@backstage/catalog-model'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { DependencyGraph, @@ -81,14 +85,14 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { if (catalogItem.relations) { for (const relation of catalogItem.relations) { switch (relation.type) { - case 'providesApi': + case RELATION_PROVIDES_API: systemEdges.push({ to: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), from: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), label: 'provides API', }); break; - case 'partOf': + case RELATION_PART_OF: systemEdges.push({ from: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), to: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), From ce891171dab6eae7b343ec573db8223c258281c1 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 18 Feb 2021 16:08:17 -0500 Subject: [PATCH 13/40] Adjust grid breakpoints for system Signed-off-by: Adam Harvey --- packages/app/src/components/catalog/EntityPage.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 56d99104ca..2958a3399b 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -439,16 +439,16 @@ const GroupEntityPage = ({ entity }: { entity: Entity }) => ( const SystemOverviewContent = ({ entity }: { entity: SystemEntity }) => ( - + - + - + - + From d1661c4dd59d85ca01cf4f9b2949415f65df4c9c Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 18 Feb 2021 16:10:49 -0500 Subject: [PATCH 14/40] Remove unused variant Signed-off-by: Adam Harvey --- plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index b466e28a0c..159e20fd54 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -33,7 +33,6 @@ import { useAsync } from 'react-use'; type SystemDiagramProps = { entity: Entity; - variant?: string; }; export function SystemDiagram({ entity }: SystemDiagramProps) { From 3e1a039dbb9519f6f2c1b65e72552936b481fd80 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 18 Feb 2021 21:39:46 -0500 Subject: [PATCH 15/40] Type cast arrays and common node func Signed-off-by: Adam Harvey --- .../src/components/SystemDiagram/SystemDiagram.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index 159e20fd54..b243e44423 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -35,6 +35,10 @@ type SystemDiagramProps = { entity: Entity; }; +const getEntityNodeId = (entity: Entity) => { + return `${entity.kind}:${entity.metadata.name}`.toLowerCase(); +}; + export function SystemDiagram({ entity }: SystemDiagramProps) { const catalogApi = useApi(catalogApiRef); const { loading, error, value: catalogResponse } = useAsync(() => { @@ -47,8 +51,8 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { const currentSystemName = entity.metadata.name; const currentSystemNode = `system:${entity.metadata.name}`.toLowerCase(); - const systemNodes = []; - const systemEdges = []; + const systemNodes = new Array<{ id: string }>(); + const systemEdges = new Array<{ from: string; to: string; label: string }>(); if (catalogResponse && catalogResponse.items) { for (const catalogItem of catalogResponse.items) { @@ -75,7 +79,7 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { // process any entity assigned to the system if (catalogItem.spec?.system === currentSystemName) { systemNodes.push({ - id: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), + id: getEntityNodeId(catalogItem), }); // check relations of the entity to see if it relates to other entities @@ -86,14 +90,14 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { switch (relation.type) { case RELATION_PROVIDES_API: systemEdges.push({ - to: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), from: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), + to: getEntityNodeId(catalogItem), label: 'provides API', }); break; case RELATION_PART_OF: systemEdges.push({ - from: `${catalogItem.kind}:${catalogItem.metadata.name}`.toLowerCase(), + from: getEntityNodeId(catalogItem), to: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), label: 'part of', }); From c7dfeb7c9e4edf8a2f0aa2609e46d070e2bac2e5 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Tue, 23 Feb 2021 23:52:52 -0500 Subject: [PATCH 16/40] Add instruction messaging Signed-off-by: Adam Harvey --- .../SystemDiagram/SystemDiagram.tsx | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index b243e44423..bb37388022 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -27,7 +27,9 @@ import { Progress, useApi, } from '@backstage/core'; +import { Box, Typography } from '@material-ui/core'; import { Alert } from '@material-ui/lab'; +import ZoomOutMap from '@material-ui/icons/ZoomOutMap'; import React from 'react'; import { useAsync } from 'react-use'; @@ -90,8 +92,8 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { switch (relation.type) { case RELATION_PROVIDES_API: systemEdges.push({ - from: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), - to: getEntityNodeId(catalogItem), + from: getEntityNodeId(catalogItem), + to: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), label: 'provides API', }); break; @@ -119,12 +121,22 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { return ( - +
+ +
+ + + Use pinch & zoom + to move around the diagram. +
); } From ac92da3202e14c7025dfa37fec5ad5b3ac899c86 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 24 Feb 2021 21:39:24 -0500 Subject: [PATCH 17/40] Refactor relationship querying Signed-off-by: Adam Harvey --- .../SystemDiagram/SystemDiagram.tsx | 58 ++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index bb37388022..d9a5a04a38 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -19,7 +19,10 @@ import { RELATION_PROVIDES_API, RELATION_PART_OF, } from '@backstage/catalog-model'; -import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { + catalogApiRef, + getEntityRelations, +} from '@backstage/plugin-catalog-react'; import { DependencyGraph, DependencyGraphTypes, @@ -84,31 +87,34 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { id: getEntityNodeId(catalogItem), }); - // check relations of the entity to see if it relates to other entities - // note those relations may, or may not, be explicitly - // assigned to the system - if (catalogItem.relations) { - for (const relation of catalogItem.relations) { - switch (relation.type) { - case RELATION_PROVIDES_API: - systemEdges.push({ - from: getEntityNodeId(catalogItem), - to: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), - label: 'provides API', - }); - break; - case RELATION_PART_OF: - systemEdges.push({ - from: getEntityNodeId(catalogItem), - to: `${relation.target.kind}:${relation.target.name}`.toLowerCase(), - label: 'part of', - }); - break; - default: - break; - } - } - } + // Check relations of the entity assigned to this system to see + // if it relates to other entities. + // Note those relations may, or may not, be explicitly + // assigned to the system. + + const catalogItemRelations_partOf = getEntityRelations( + catalogItem, + RELATION_PART_OF, + ); + catalogItemRelations_partOf.forEach(foundRelation => + systemEdges.push({ + from: getEntityNodeId(catalogItem), + to: `${foundRelation.kind}:${foundRelation.name}`.toLowerCase(), + label: 'part of', + }), + ); + + const catalogItemRelations_providesApi = getEntityRelations( + catalogItem, + RELATION_PROVIDES_API, + ); + catalogItemRelations_providesApi.forEach(foundRelation => + systemEdges.push({ + from: getEntityNodeId(catalogItem), + to: `${foundRelation.kind}:${foundRelation.name}`.toLowerCase(), + label: 'provides API', + }), + ); } } } From 541d7e0e51f7b97dd8a6010e126cdd3f4c1ea8bf Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 24 Feb 2021 22:45:58 -0500 Subject: [PATCH 18/40] Refactor with better name processing Signed-off-by: Adam Harvey --- .../SystemDiagram/SystemDiagram.tsx | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index d9a5a04a38..dcdad78c71 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -18,6 +18,7 @@ import { Entity, RELATION_PROVIDES_API, RELATION_PART_OF, + serializeEntityRef, } from '@backstage/catalog-model'; import { catalogApiRef, @@ -40,9 +41,21 @@ type SystemDiagramProps = { entity: Entity; }; -const getEntityNodeId = (entity: Entity) => { - return `${entity.kind}:${entity.metadata.name}`.toLowerCase(); -}; +function simplifiedEntityName( + ref: + | Entity + | { + kind?: string; + namespace?: string; + name: string; + }, +): string { + // Simplify the diagram output by hiding only the default namespace + return serializeEntityRef(ref) + .toString() + .toLowerCase() + .replace(':default/', ':'); +} export function SystemDiagram({ entity }: SystemDiagramProps) { const catalogApi = useApi(catalogApiRef); @@ -55,36 +68,43 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { }, [catalogApi]); const currentSystemName = entity.metadata.name; - const currentSystemNode = `system:${entity.metadata.name}`.toLowerCase(); + const currentSystemNode = simplifiedEntityName(entity); const systemNodes = new Array<{ id: string }>(); const systemEdges = new Array<{ from: string; to: string; label: string }>(); if (catalogResponse && catalogResponse.items) { for (const catalogItem of catalogResponse.items) { // pick out the system itself - if (catalogItem.metadata.name === entity.metadata.name) { + if (catalogItem.metadata.name === currentSystemName) { systemNodes.push({ id: currentSystemNode, }); // check if the system has an assigned domain // even if the domain object doesn't exist in the catalog, display it in the map - if (catalogItem.spec?.domain) { + const catalogItemDomain = getEntityRelations( + catalogItem, + RELATION_PART_OF, + { kind: 'domain' }, + ); + catalogItemDomain.forEach(foundDomain => systemNodes.push({ - id: `domain:${catalogItem.spec.domain}`.toLowerCase(), - }); + id: simplifiedEntityName(foundDomain), + }), + ); + catalogItemDomain.forEach(foundDomain => systemEdges.push({ from: currentSystemNode, - to: `domain:${catalogItem.spec.domain}`.toLowerCase(), + to: simplifiedEntityName(foundDomain), label: 'part of', - }); - } + }), + ); } // process any entity assigned to the system if (catalogItem.spec?.system === currentSystemName) { systemNodes.push({ - id: getEntityNodeId(catalogItem), + id: simplifiedEntityName(catalogItem), }); // Check relations of the entity assigned to this system to see @@ -98,8 +118,8 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { ); catalogItemRelations_partOf.forEach(foundRelation => systemEdges.push({ - from: getEntityNodeId(catalogItem), - to: `${foundRelation.kind}:${foundRelation.name}`.toLowerCase(), + from: simplifiedEntityName(catalogItem), + to: simplifiedEntityName(foundRelation), label: 'part of', }), ); @@ -110,8 +130,8 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { ); catalogItemRelations_providesApi.forEach(foundRelation => systemEdges.push({ - from: getEntityNodeId(catalogItem), - to: `${foundRelation.kind}:${foundRelation.name}`.toLowerCase(), + from: simplifiedEntityName(catalogItem), + to: simplifiedEntityName(foundRelation), label: 'provides API', }), ); From a29737eb9238851880d49036b5bf1c33887969d9 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 24 Feb 2021 22:58:30 -0500 Subject: [PATCH 19/40] Simplify rendering Signed-off-by: Adam Harvey --- .../src/components/SystemDiagram/SystemDiagram.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index dcdad78c71..d2b59fcd11 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -147,14 +147,12 @@ export function SystemDiagram({ entity }: SystemDiagramProps) { return ( -
- -
+ Date: Wed, 24 Feb 2021 23:07:21 -0500 Subject: [PATCH 20/40] Add description Signed-off-by: Adam Harvey --- .../catalog/src/components/SystemDiagram/SystemDiagram.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index d2b59fcd11..3d966a2f8b 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -57,6 +57,10 @@ function simplifiedEntityName( .replace(':default/', ':'); } +/** + * Dynamically generates a diagram of a system, its assigned entities, + * and relationships of those entities. + */ export function SystemDiagram({ entity }: SystemDiagramProps) { const catalogApi = useApi(catalogApiRef); const { loading, error, value: catalogResponse } = useAsync(() => { From 9e0bf09f5fd0f00ba0e45c96801f56671d3f8fc3 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 12 Mar 2021 16:30:16 -0500 Subject: [PATCH 21/40] Fix entity page Signed-off-by: Adam Harvey --- packages/app/src/components/catalog/EntityPage.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 2958a3399b..40ed04b30c 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -465,7 +465,12 @@ const SystemEntityPage = ({ entity }: { entity: Entity }) => ( path="/docs/*" title="Docs" element={} - /> + /> + } + /> ); @@ -492,11 +497,6 @@ const DomainEntityPage = ({ entity }: { entity: Entity }) => ( title="Docs" element={} /> - } - /> ); From 3fd41d6d5427d036986efa71a3611a0eafd796d3 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Sat, 13 Mar 2021 13:40:33 -0500 Subject: [PATCH 22/40] Add test for component Signed-off-by: Adam Harvey --- .../SystemDiagram/SystemDiagram.test.tsx | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx new file mode 100644 index 0000000000..648df0cff3 --- /dev/null +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx @@ -0,0 +1,99 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { catalogApiRef } from '@backstage/catalog-client'; +import { Entity, RELATION_HAS_PART } from '@backstage/catalog-model'; +import { CatalogApi, EntityProvider } from '@backstage/plugin-catalog-react'; +import { renderInTestApp } from '@backstage/test-utils'; +import { waitFor } from '@testing-library/react'; +import React from 'react'; +import { SystemDiagram } from './SystemDiagram'; + +describe('', () => { + const catalogApi: jest.Mocked = { + getLocationById: jest.fn(), + getEntityByName: jest.fn(), + getEntities: jest.fn(), + addLocation: jest.fn(), + getLocationByEntity: jest.fn(), + removeEntityByUid: jest.fn(), + } as any; + + afterEach(() => jest.resetAllMocks()); + + it('shows empty list if no relations', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Domain', + metadata: { + name: 'my-domain', + namespace: 'my-namespace', + }, + relations: [], + }; + + const { getByText } = await renderInTestApp( + + + , + ); + + expect(getByText('System Diagram')).toBeInTheDocument(); + // expect(getByText('Systems')).toBeInTheDocument(); + // expect(getByText(/No system is part of this domain/i)).toBeInTheDocument(); + }); + + it('shows related systems', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Domain', + metadata: { + name: 'my-domain', + namespace: 'my-namespace', + }, + relations: [ + { + target: { + kind: 'System', + namespace: 'my-namespace', + name: 'target-name', + }, + type: RELATION_HAS_PART, + }, + ], + }; + catalogApi.getEntityByName.mockResolvedValue({ + apiVersion: 'v1', + kind: 'System', + metadata: { + name: 'target-name', + namespace: 'my-namespace', + }, + spec: {}, + }); + + const { getByText } = await renderInTestApp( + + + , + ); + + await waitFor(() => { + expect(getByText('Systems')).toBeInTheDocument(); + expect(getByText(/target-name/i)).toBeInTheDocument(); + }); + }); +}); From cc3de518db0405237e2ceaa44e57a14f041075c2 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Sat, 13 Mar 2021 13:58:12 -0500 Subject: [PATCH 23/40] Remove docs tab Signed-off-by: Adam Harvey --- packages/app/src/components/catalog/EntityPage.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 40ed04b30c..0582b28a74 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -461,11 +461,6 @@ const SystemEntityPage = ({ entity }: { entity: Entity }) => ( title="Overview" element={} /> - } - /> Date: Sat, 13 Mar 2021 13:58:36 -0500 Subject: [PATCH 24/40] Remove links widget Signed-off-by: Adam Harvey --- packages/app/src/components/catalog/EntityPage.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 0582b28a74..a0ee9f296a 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -442,9 +442,6 @@ const SystemOverviewContent = ({ entity }: { entity: SystemEntity }) => ( - - - From d40fd8127d80964e54925b1a39ae207caeb38b2b Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Sat, 13 Mar 2021 14:02:56 -0500 Subject: [PATCH 25/40] Remove extraneous breakpoints Signed-off-by: Adam Harvey --- packages/app/src/components/catalog/EntityPage.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index a0ee9f296a..d1d83e48f9 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -439,13 +439,13 @@ const GroupEntityPage = ({ entity }: { entity: Entity }) => ( const SystemOverviewContent = ({ entity }: { entity: SystemEntity }) => ( - + - + - + From 155940e89a03f6ed8f7960658a13339896a55a75 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Sat, 13 Mar 2021 14:03:54 -0500 Subject: [PATCH 26/40] Remove added docs tab from domain entity Signed-off-by: Adam Harvey --- packages/app/src/components/catalog/EntityPage.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index d1d83e48f9..f417fa82b8 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -484,11 +484,6 @@ const DomainEntityPage = ({ entity }: { entity: Entity }) => ( title="Overview" element={} /> - } - /> ); From c4b2bca09bcaad9fad996e0eced770d6593f567d Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Tue, 16 Mar 2021 11:26:01 -0400 Subject: [PATCH 27/40] Simplify changeset Signed-off-by: Adam Harvey --- .changeset/perfect-coats-train.md | 64 ++++++++----------------------- 1 file changed, 15 insertions(+), 49 deletions(-) diff --git a/.changeset/perfect-coats-train.md b/.changeset/perfect-coats-train.md index 4fe74acd5f..25b19fb45c 100644 --- a/.changeset/perfect-coats-train.md +++ b/.changeset/perfect-coats-train.md @@ -4,57 +4,23 @@ Adds a new `SystemDiagram` component to visually map all elements in a system. -To use this new component, a new system entity page would need to be added to the `packages/app/src/components/catalog/EntityPage.tsx` file. +To use this new component, you can add a new tab with the component on to the System Entity Page in your `packages/app/src/components/catalog/EntityPage.tsx` file. For example, -```tsx -const SystemOverviewContent = ({ entity }: { entity: Entity }) => ( - - - - - - - - -); - -const SystemEntityPage = ({ entity }: { entity: Entity }) => ( - - } - /> - } - /> - -); -``` - -And the addition of a new switch case to the `EntityPage` object: - ```diff - export const EntityPage = () => { - const { entity } = useEntity(); - - switch (entity?.kind?.toLowerCase()) { - case 'component': - return ; - case 'api': - return ; - case 'group': - return ; - case 'user': - return ; -+ case 'system': -+ return ; - default: - return ; - } - }; + const SystemEntityPage = ({ entity }: { entity: Entity }) => ( + + } + /> ++ } ++ /> + + ); ``` From 77b6161b4dbe0701456e591b6c07f3c83df8e034 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Tue, 16 Mar 2021 11:26:12 -0400 Subject: [PATCH 28/40] Add broken test suite Signed-off-by: Adam Harvey --- .../SystemDiagram/SystemDiagram.test.tsx | 91 +++++++++++-------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx index 648df0cff3..5cc29d63b0 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx @@ -14,86 +14,101 @@ * limitations under the License. */ -import { catalogApiRef } from '@backstage/catalog-client'; -import { Entity, RELATION_HAS_PART } from '@backstage/catalog-model'; -import { CatalogApi, EntityProvider } from '@backstage/plugin-catalog-react'; +import { ApiProvider, ApiRegistry } from '@backstage/core'; +import { + catalogApiRef, + CatalogApi, + getEntityRelations, + EntityProvider, +} from '@backstage/plugin-catalog-react'; +import { Entity, EntityName, RELATION_PART_OF } from '@backstage/catalog-model'; + import { renderInTestApp } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; import React from 'react'; import { SystemDiagram } from './SystemDiagram'; describe('', () => { - const catalogApi: jest.Mocked = { - getLocationById: jest.fn(), - getEntityByName: jest.fn(), - getEntities: jest.fn(), - addLocation: jest.fn(), - getLocationByEntity: jest.fn(), - removeEntityByUid: jest.fn(), - } as any; + const catalogApi: Partial = { + getEntities: () => + Promise.resolve({ + items: [ + // { + // apiVersion: 'backstage.io/v1alpha1', + // kind: 'System', + // metadata: { + // name: 'my-system', + // }, + // spec: { + // owner: 'tools@example.com', + // }, + // }, + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'Entity2', + }, + spec: { + owner: 'not-tools@example.com', + type: 'service', + system: 'my-system', + }, + }, + ] as Entity[], + }), + }; afterEach(() => jest.resetAllMocks()); it('shows empty list if no relations', async () => { const entity: Entity = { apiVersion: 'v1', - kind: 'Domain', + kind: 'System', metadata: { - name: 'my-domain', - namespace: 'my-namespace', + name: 'my-system', + // namespace: 'my-namespace', }, relations: [], }; const { getByText } = await renderInTestApp( - + - , + , ); expect(getByText('System Diagram')).toBeInTheDocument(); - // expect(getByText('Systems')).toBeInTheDocument(); - // expect(getByText(/No system is part of this domain/i)).toBeInTheDocument(); + expect(getByText('my-system')).not.toBeInTheDocument(); }); it('shows related systems', async () => { const entity: Entity = { apiVersion: 'v1', - kind: 'Domain', + kind: 'System', metadata: { - name: 'my-domain', + name: 'my-system', namespace: 'my-namespace', }, relations: [ { target: { - kind: 'System', + kind: 'Domain', namespace: 'my-namespace', - name: 'target-name', + name: 'my-domain', }, - type: RELATION_HAS_PART, + type: RELATION_PART_OF, }, ], }; - catalogApi.getEntityByName.mockResolvedValue({ - apiVersion: 'v1', - kind: 'System', - metadata: { - name: 'target-name', - namespace: 'my-namespace', - }, - spec: {}, - }); const { getByText } = await renderInTestApp( - + - , + , ); - await waitFor(() => { - expect(getByText('Systems')).toBeInTheDocument(); - expect(getByText(/target-name/i)).toBeInTheDocument(); - }); + expect(getByText('System Diagram')).toBeInTheDocument(); + expect(getByText('my-system')).toBeInTheDocument(); }); }); From 7d922eb29697dba7bee56ca9b5d09126fa9dd169 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Mon, 22 Mar 2021 21:49:31 -0400 Subject: [PATCH 29/40] Still broken tests Signed-off-by: Adam Harvey --- .../SystemDiagram/SystemDiagram.test.tsx | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx index 5cc29d63b0..bca8d97b05 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx @@ -15,16 +15,9 @@ */ import { ApiProvider, ApiRegistry } from '@backstage/core'; -import { - catalogApiRef, - CatalogApi, - getEntityRelations, - EntityProvider, -} from '@backstage/plugin-catalog-react'; -import { Entity, EntityName, RELATION_PART_OF } from '@backstage/catalog-model'; - +import { catalogApiRef, CatalogApi } from '@backstage/plugin-catalog-react'; +import { Entity, RELATION_PART_OF } from '@backstage/catalog-model'; import { renderInTestApp } from '@backstage/test-utils'; -import { waitFor } from '@testing-library/react'; import React from 'react'; import { SystemDiagram } from './SystemDiagram'; @@ -33,21 +26,23 @@ describe('', () => { getEntities: () => Promise.resolve({ items: [ - // { - // apiVersion: 'backstage.io/v1alpha1', - // kind: 'System', - // metadata: { - // name: 'my-system', - // }, - // spec: { - // owner: 'tools@example.com', - // }, - // }, + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'System', + metadata: { + name: 'my-system', + namespace: 'my-namespace', + }, + spec: { + owner: 'tools@example.com', + }, + }, { apiVersion: 'backstage.io/v1alpha1', kind: 'Component', metadata: { name: 'Entity2', + namespace: 'my-namespace', }, spec: { owner: 'not-tools@example.com', @@ -57,6 +52,11 @@ describe('', () => { }, ] as Entity[], }), + // need to mock this? + // getEntityRelations: (Entity, string) => + // Promise.resolve({ + + // }), }; afterEach(() => jest.resetAllMocks()); @@ -67,7 +67,6 @@ describe('', () => { kind: 'System', metadata: { name: 'my-system', - // namespace: 'my-namespace', }, relations: [], }; @@ -79,7 +78,7 @@ describe('', () => { ); expect(getByText('System Diagram')).toBeInTheDocument(); - expect(getByText('my-system')).not.toBeInTheDocument(); + // expect(getByText('my-system')).not.toBeInTheDocument(); }); it('shows related systems', async () => { From 6ccee05f4689c990df2c740eb1cf1ec0885e56c7 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Tue, 23 Mar 2021 11:16:12 -0400 Subject: [PATCH 30/40] Fix tests Signed-off-by: Adam Harvey --- .../SystemDiagram/SystemDiagram.test.tsx | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx index bca8d97b05..cd38384645 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx @@ -22,6 +22,15 @@ import React from 'react'; import { SystemDiagram } from './SystemDiagram'; describe('', () => { + beforeAll(() => { + Object.defineProperty(window.SVGElement.prototype, 'getBBox', { + value: () => ({ width: 100, height: 100 }), + configurable: true, + }); + }); + + afterEach(() => jest.resetAllMocks()); + const catalogApi: Partial = { getEntities: () => Promise.resolve({ @@ -41,7 +50,7 @@ describe('', () => { apiVersion: 'backstage.io/v1alpha1', kind: 'Component', metadata: { - name: 'Entity2', + name: 'my-entity', namespace: 'my-namespace', }, spec: { @@ -50,35 +59,43 @@ describe('', () => { system: 'my-system', }, }, + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'System', + metadata: { + name: 'my-system2', + namespace: 'my-namespace2', + }, + spec: { + owner: 'tools@example.com', + }, + }, ] as Entity[], }), - // need to mock this? - // getEntityRelations: (Entity, string) => - // Promise.resolve({ - - // }), }; - afterEach(() => jest.resetAllMocks()); - it('shows empty list if no relations', async () => { const entity: Entity = { apiVersion: 'v1', kind: 'System', metadata: { - name: 'my-system', + name: 'my-system2', + namespace: 'my-namespace2', }, relations: [], }; - const { getByText } = await renderInTestApp( + const { queryByText } = await renderInTestApp( , ); - expect(getByText('System Diagram')).toBeInTheDocument(); - // expect(getByText('my-system')).not.toBeInTheDocument(); + expect(queryByText(/System Diagram/)).toBeInTheDocument(); + expect(queryByText(/system:my-namespace2\/my-system2/)).toBeInTheDocument(); + expect( + queryByText(/component:my-namespace\/my-entity/), + ).not.toBeInTheDocument(); }); it('shows related systems', async () => { @@ -108,6 +125,7 @@ describe('', () => { ); expect(getByText('System Diagram')).toBeInTheDocument(); - expect(getByText('my-system')).toBeInTheDocument(); + expect(getByText('system:my-namespace/my-system')).toBeInTheDocument(); + expect(getByText('component:my-namespace/my-entity')).toBeInTheDocument(); }); }); From 740143b30645fd917fb293da010f92dab58473bc Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Tue, 23 Mar 2021 11:55:14 -0400 Subject: [PATCH 31/40] Refactor query of system elements Signed-off-by: Adam Harvey --- .../SystemDiagram/SystemDiagram.test.tsx | 71 ++++------ .../SystemDiagram/SystemDiagram.tsx | 130 +++++++++--------- 2 files changed, 90 insertions(+), 111 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx index cd38384645..ed9b12e3e5 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx @@ -31,50 +31,14 @@ describe('', () => { afterEach(() => jest.resetAllMocks()); - const catalogApi: Partial = { - getEntities: () => - Promise.resolve({ - items: [ - { - apiVersion: 'backstage.io/v1alpha1', - kind: 'System', - metadata: { - name: 'my-system', - namespace: 'my-namespace', - }, - spec: { - owner: 'tools@example.com', - }, - }, - { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: 'my-entity', - namespace: 'my-namespace', - }, - spec: { - owner: 'not-tools@example.com', - type: 'service', - system: 'my-system', - }, - }, - { - apiVersion: 'backstage.io/v1alpha1', - kind: 'System', - metadata: { - name: 'my-system2', - namespace: 'my-namespace2', - }, - spec: { - owner: 'tools@example.com', - }, - }, - ] as Entity[], - }), - }; - it('shows empty list if no relations', async () => { + const catalogApi: Partial = { + getEntities: () => + Promise.resolve({ + items: [] as Entity[], + }), + }; + const entity: Entity = { apiVersion: 'v1', kind: 'System', @@ -99,6 +63,27 @@ describe('', () => { }); it('shows related systems', async () => { + const catalogApi: Partial = { + getEntities: () => + Promise.resolve({ + items: [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-entity', + namespace: 'my-namespace', + }, + spec: { + owner: 'not-tools@example.com', + type: 'service', + system: 'my-system', + }, + }, + ] as Entity[], + }), + }; + const entity: Entity = { apiVersion: 'v1', kind: 'System', diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx index 3d966a2f8b..47ada9003d 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx @@ -62,84 +62,78 @@ function simplifiedEntityName( * and relationships of those entities. */ export function SystemDiagram({ entity }: SystemDiagramProps) { - const catalogApi = useApi(catalogApiRef); - const { loading, error, value: catalogResponse } = useAsync(() => { - return catalogApi.getEntities({ - filter: { - kind: ['Component', 'API', 'Resource', 'System', 'Domain'], - }, - }); - }, [catalogApi]); - const currentSystemName = entity.metadata.name; const currentSystemNode = simplifiedEntityName(entity); const systemNodes = new Array<{ id: string }>(); const systemEdges = new Array<{ from: string; to: string; label: string }>(); + const catalogApi = useApi(catalogApiRef); + const { loading, error, value: catalogResponse } = useAsync(() => { + return catalogApi.getEntities({ + filter: { + kind: ['Component', 'API', 'Resource', 'System', 'Domain'], + ['spec.system']: currentSystemName, + }, + }); + }, [catalogApi]); + + // pick out the system itself + systemNodes.push({ + id: currentSystemNode, + }); + + // check if the system has an assigned domain + // even if the domain object doesn't exist in the catalog, display it in the map + const catalogItemDomain = getEntityRelations(entity, RELATION_PART_OF, { + kind: 'domain', + }); + catalogItemDomain.forEach(foundDomain => + systemNodes.push({ + id: simplifiedEntityName(foundDomain), + }), + ); + catalogItemDomain.forEach(foundDomain => + systemEdges.push({ + from: currentSystemNode, + to: simplifiedEntityName(foundDomain), + label: 'part of', + }), + ); + if (catalogResponse && catalogResponse.items) { for (const catalogItem of catalogResponse.items) { - // pick out the system itself - if (catalogItem.metadata.name === currentSystemName) { - systemNodes.push({ - id: currentSystemNode, - }); + systemNodes.push({ + id: simplifiedEntityName(catalogItem), + }); - // check if the system has an assigned domain - // even if the domain object doesn't exist in the catalog, display it in the map - const catalogItemDomain = getEntityRelations( - catalogItem, - RELATION_PART_OF, - { kind: 'domain' }, - ); - catalogItemDomain.forEach(foundDomain => - systemNodes.push({ - id: simplifiedEntityName(foundDomain), - }), - ); - catalogItemDomain.forEach(foundDomain => - systemEdges.push({ - from: currentSystemNode, - to: simplifiedEntityName(foundDomain), - label: 'part of', - }), - ); - } + // Check relations of the entity assigned to this system to see + // if it relates to other entities. + // Note those relations may, or may not, be explicitly + // assigned to the system. + const catalogItemRelations_partOf = getEntityRelations( + catalogItem, + RELATION_PART_OF, + ); + catalogItemRelations_partOf.forEach(foundRelation => + systemEdges.push({ + from: simplifiedEntityName(catalogItem), + to: simplifiedEntityName(foundRelation), + label: 'part of', + }), + ); - // process any entity assigned to the system - if (catalogItem.spec?.system === currentSystemName) { - systemNodes.push({ - id: simplifiedEntityName(catalogItem), - }); + const catalogItemRelations_providesApi = getEntityRelations( + catalogItem, + RELATION_PROVIDES_API, + ); - // Check relations of the entity assigned to this system to see - // if it relates to other entities. - // Note those relations may, or may not, be explicitly - // assigned to the system. - - const catalogItemRelations_partOf = getEntityRelations( - catalogItem, - RELATION_PART_OF, - ); - catalogItemRelations_partOf.forEach(foundRelation => - systemEdges.push({ - from: simplifiedEntityName(catalogItem), - to: simplifiedEntityName(foundRelation), - label: 'part of', - }), - ); - - const catalogItemRelations_providesApi = getEntityRelations( - catalogItem, - RELATION_PROVIDES_API, - ); - catalogItemRelations_providesApi.forEach(foundRelation => - systemEdges.push({ - from: simplifiedEntityName(catalogItem), - to: simplifiedEntityName(foundRelation), - label: 'provides API', - }), - ); - } + catalogItemRelations_providesApi.forEach(foundRelation => + systemEdges.push({ + from: simplifiedEntityName(catalogItem), + to: simplifiedEntityName(foundRelation), + label: 'provides API', + }), + ); } } From 865e76d9b65caa2cc18649f379e93531c94838a7 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Tue, 23 Mar 2021 16:27:41 -0400 Subject: [PATCH 32/40] Refactor for composability pattern Signed-off-by: Adam Harvey --- .changeset/perfect-coats-train.md | 6 +++--- packages/app/src/components/catalog/EntityPage.tsx | 4 ++-- .../EntitySystemDiagramCard.test.tsx} | 8 ++++---- .../EntitySystemDiagramCard.tsx} | 4 ++-- .../{SystemDiagram => EntitySystemDiagramCard}/index.ts | 2 +- plugins/catalog/src/index.ts | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) rename plugins/catalog/src/components/{SystemDiagram/SystemDiagram.test.tsx => EntitySystemDiagramCard/EntitySystemDiagramCard.test.tsx} (93%) rename plugins/catalog/src/components/{SystemDiagram/SystemDiagram.tsx => EntitySystemDiagramCard/EntitySystemDiagramCard.tsx} (97%) rename plugins/catalog/src/components/{SystemDiagram => EntitySystemDiagramCard}/index.ts (89%) diff --git a/.changeset/perfect-coats-train.md b/.changeset/perfect-coats-train.md index 25b19fb45c..98b558e8d6 100644 --- a/.changeset/perfect-coats-train.md +++ b/.changeset/perfect-coats-train.md @@ -2,9 +2,9 @@ '@backstage/plugin-catalog': patch --- -Adds a new `SystemDiagram` component to visually map all elements in a system. +Adds a new `EntitySystemDiagramCard` component to visually map all elements in a system. -To use this new component, you can add a new tab with the component on to the System Entity Page in your `packages/app/src/components/catalog/EntityPage.tsx` file. +To use this new component with the legacy composability pattern, you can add a new tab with the component on to the System Entity Page in your `packages/app/src/components/catalog/EntityPage.tsx` file. For example, @@ -19,7 +19,7 @@ For example, + } ++ element={} + /> ); diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index f417fa82b8..2d0bde2a7a 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -38,7 +38,7 @@ import { EntityHasSystemsCard, EntityLinksCard, EntityPageLayout, - SystemDiagram, + EntitySystemDiagramCard, } from '@backstage/plugin-catalog'; import { EntityProvider, useEntity } from '@backstage/plugin-catalog-react'; import { @@ -461,7 +461,7 @@ const SystemEntityPage = ({ entity }: { entity: Entity }) => ( } + element={} /> ); diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx b/plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.test.tsx similarity index 93% rename from plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx rename to plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.test.tsx index ed9b12e3e5..8a5434db8b 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.test.tsx +++ b/plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.test.tsx @@ -19,9 +19,9 @@ import { catalogApiRef, CatalogApi } from '@backstage/plugin-catalog-react'; import { Entity, RELATION_PART_OF } from '@backstage/catalog-model'; import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; -import { SystemDiagram } from './SystemDiagram'; +import { EntitySystemDiagramCard } from './EntitySystemDiagramCard'; -describe('', () => { +describe('', () => { beforeAll(() => { Object.defineProperty(window.SVGElement.prototype, 'getBBox', { value: () => ({ width: 100, height: 100 }), @@ -51,7 +51,7 @@ describe('', () => { const { queryByText } = await renderInTestApp( - + , ); @@ -105,7 +105,7 @@ describe('', () => { const { getByText } = await renderInTestApp( - + , ); diff --git a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx b/plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.tsx similarity index 97% rename from plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx rename to plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.tsx index 47ada9003d..4231ee22ff 100644 --- a/plugins/catalog/src/components/SystemDiagram/SystemDiagram.tsx +++ b/plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.tsx @@ -37,7 +37,7 @@ import ZoomOutMap from '@material-ui/icons/ZoomOutMap'; import React from 'react'; import { useAsync } from 'react-use'; -type SystemDiagramProps = { +type EntitySystemDiagramProps = { entity: Entity; }; @@ -61,7 +61,7 @@ function simplifiedEntityName( * Dynamically generates a diagram of a system, its assigned entities, * and relationships of those entities. */ -export function SystemDiagram({ entity }: SystemDiagramProps) { +export function EntitySystemDiagramCard({ entity }: EntitySystemDiagramProps) { const currentSystemName = entity.metadata.name; const currentSystemNode = simplifiedEntityName(entity); const systemNodes = new Array<{ id: string }>(); diff --git a/plugins/catalog/src/components/SystemDiagram/index.ts b/plugins/catalog/src/components/EntitySystemDiagramCard/index.ts similarity index 89% rename from plugins/catalog/src/components/SystemDiagram/index.ts rename to plugins/catalog/src/components/EntitySystemDiagramCard/index.ts index e086aed507..b9a924a511 100644 --- a/plugins/catalog/src/components/SystemDiagram/index.ts +++ b/plugins/catalog/src/components/EntitySystemDiagramCard/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { SystemDiagram } from './SystemDiagram'; +export { EntitySystemDiagramCard } from './EntitySystemDiagramCard'; diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts index 72e33defe7..2494e5ba28 100644 --- a/plugins/catalog/src/index.ts +++ b/plugins/catalog/src/index.ts @@ -17,7 +17,7 @@ export { AboutCard } from './components/AboutCard'; export { EntityLayout } from './components/EntityLayout'; export { EntityPageLayout } from './components/EntityPageLayout'; -export { SystemDiagram } from './components/SystemDiagram'; +export { EntitySystemDiagramCard } from './components/EntitySystemDiagramCard'; export * from './components/EntitySwitch'; export { Router } from './components/Router'; export { From f9ab2bb4decb723fa52144ab57ae8a261baed7d3 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Tue, 23 Mar 2021 21:12:20 -0400 Subject: [PATCH 33/40] Second composibility refactor Signed-off-by: Adam Harvey --- .../SystemDiagramCard.test.tsx} | 8 ++++---- .../SystemDiagramCard.tsx} | 4 ++-- .../index.ts | 2 +- plugins/catalog/src/index.ts | 2 +- plugins/catalog/src/plugin.ts | 9 +++++++++ 5 files changed, 17 insertions(+), 8 deletions(-) rename plugins/catalog/src/components/{EntitySystemDiagramCard/EntitySystemDiagramCard.test.tsx => SystemDiagramCard/SystemDiagramCard.test.tsx} (93%) rename plugins/catalog/src/components/{EntitySystemDiagramCard/EntitySystemDiagramCard.tsx => SystemDiagramCard/SystemDiagramCard.tsx} (97%) rename plugins/catalog/src/components/{EntitySystemDiagramCard => SystemDiagramCard}/index.ts (89%) diff --git a/plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.test.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx similarity index 93% rename from plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.test.tsx rename to plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx index 8a5434db8b..ed1a1a69ea 100644 --- a/plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.test.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx @@ -19,9 +19,9 @@ import { catalogApiRef, CatalogApi } from '@backstage/plugin-catalog-react'; import { Entity, RELATION_PART_OF } from '@backstage/catalog-model'; import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; -import { EntitySystemDiagramCard } from './EntitySystemDiagramCard'; +import { SystemDiagramCard } from './SystemDiagramCard'; -describe('', () => { +describe('', () => { beforeAll(() => { Object.defineProperty(window.SVGElement.prototype, 'getBBox', { value: () => ({ width: 100, height: 100 }), @@ -51,7 +51,7 @@ describe('', () => { const { queryByText } = await renderInTestApp( - + , ); @@ -105,7 +105,7 @@ describe('', () => { const { getByText } = await renderInTestApp( - + , ); diff --git a/plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx similarity index 97% rename from plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.tsx rename to plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index 4231ee22ff..bec2e844c8 100644 --- a/plugins/catalog/src/components/EntitySystemDiagramCard/EntitySystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -37,7 +37,7 @@ import ZoomOutMap from '@material-ui/icons/ZoomOutMap'; import React from 'react'; import { useAsync } from 'react-use'; -type EntitySystemDiagramProps = { +type SystemDiagramProps = { entity: Entity; }; @@ -61,7 +61,7 @@ function simplifiedEntityName( * Dynamically generates a diagram of a system, its assigned entities, * and relationships of those entities. */ -export function EntitySystemDiagramCard({ entity }: EntitySystemDiagramProps) { +export function SystemDiagramCard({ entity }: SystemDiagramProps) { const currentSystemName = entity.metadata.name; const currentSystemNode = simplifiedEntityName(entity); const systemNodes = new Array<{ id: string }>(); diff --git a/plugins/catalog/src/components/EntitySystemDiagramCard/index.ts b/plugins/catalog/src/components/SystemDiagramCard/index.ts similarity index 89% rename from plugins/catalog/src/components/EntitySystemDiagramCard/index.ts rename to plugins/catalog/src/components/SystemDiagramCard/index.ts index b9a924a511..6d86b31b68 100644 --- a/plugins/catalog/src/components/EntitySystemDiagramCard/index.ts +++ b/plugins/catalog/src/components/SystemDiagramCard/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { EntitySystemDiagramCard } from './EntitySystemDiagramCard'; +export { SystemDiagramCard } from './SystemDiagramCard'; diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts index 2494e5ba28..7ab7b95dd7 100644 --- a/plugins/catalog/src/index.ts +++ b/plugins/catalog/src/index.ts @@ -17,7 +17,6 @@ export { AboutCard } from './components/AboutCard'; export { EntityLayout } from './components/EntityLayout'; export { EntityPageLayout } from './components/EntityPageLayout'; -export { EntitySystemDiagramCard } from './components/EntitySystemDiagramCard'; export * from './components/EntitySwitch'; export { Router } from './components/Router'; export { @@ -30,4 +29,5 @@ export { EntityHasSubcomponentsCard, EntityHasSystemsCard, EntityLinksCard, + EntitySystemDiagramCard, } from './plugin'; diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index 19dc778280..20c7a865db 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -114,3 +114,12 @@ export const EntityHasSubcomponentsCard = catalogPlugin.provide( }, }), ); + +export const EntitySystemDiagramCard = catalogPlugin.provide( + createComponentExtension({ + component: { + lazy: () => + import('./components/SystemDiagramCard').then(m => m.SystemDiagramCard), + }, + }), +); From 4491ba231fe55a3913962200cad3f7d39205c321 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 25 Mar 2021 09:50:35 -0400 Subject: [PATCH 34/40] Refactor entity collection Signed-off-by: Adam Harvey --- .changeset/perfect-coats-train.md | 2 +- packages/app/src/components/catalog/EntityPage.tsx | 2 +- .../SystemDiagramCard/SystemDiagramCard.test.tsx | 14 +++++++++++--- .../SystemDiagramCard/SystemDiagramCard.tsx | 8 +++----- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/.changeset/perfect-coats-train.md b/.changeset/perfect-coats-train.md index 98b558e8d6..7a089e870f 100644 --- a/.changeset/perfect-coats-train.md +++ b/.changeset/perfect-coats-train.md @@ -19,7 +19,7 @@ For example, + } ++ element={} + /> ); diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 2d0bde2a7a..e46186bbe0 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -461,7 +461,7 @@ const SystemEntityPage = ({ entity }: { entity: Entity }) => ( } + element={} /> ); diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx index ed1a1a69ea..baa8c667d2 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx @@ -15,7 +15,11 @@ */ import { ApiProvider, ApiRegistry } from '@backstage/core'; -import { catalogApiRef, CatalogApi } from '@backstage/plugin-catalog-react'; +import { + catalogApiRef, + CatalogApi, + EntityProvider, +} from '@backstage/plugin-catalog-react'; import { Entity, RELATION_PART_OF } from '@backstage/catalog-model'; import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; @@ -51,7 +55,9 @@ describe('', () => { const { queryByText } = await renderInTestApp( - + + + , ); @@ -105,7 +111,9 @@ describe('', () => { const { getByText } = await renderInTestApp( - + + + , ); diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index bec2e844c8..698476fe93 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -23,6 +23,7 @@ import { import { catalogApiRef, getEntityRelations, + useEntity, } from '@backstage/plugin-catalog-react'; import { DependencyGraph, @@ -37,10 +38,6 @@ import ZoomOutMap from '@material-ui/icons/ZoomOutMap'; import React from 'react'; import { useAsync } from 'react-use'; -type SystemDiagramProps = { - entity: Entity; -}; - function simplifiedEntityName( ref: | Entity @@ -61,7 +58,8 @@ function simplifiedEntityName( * Dynamically generates a diagram of a system, its assigned entities, * and relationships of those entities. */ -export function SystemDiagramCard({ entity }: SystemDiagramProps) { +export function SystemDiagramCard() { + const { entity } = useEntity(); const currentSystemName = entity.metadata.name; const currentSystemNode = simplifiedEntityName(entity); const systemNodes = new Array<{ id: string }>(); From 30391799963663c78375136ff8e7ee687d77ac0d Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 25 Mar 2021 09:53:38 -0400 Subject: [PATCH 35/40] Use WarningPanel Signed-off-by: Adam Harvey --- .../components/SystemDiagramCard/SystemDiagramCard.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index 698476fe93..e2c48fe521 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -31,9 +31,9 @@ import { InfoCard, Progress, useApi, + WarningPanel, } from '@backstage/core'; import { Box, Typography } from '@material-ui/core'; -import { Alert } from '@material-ui/lab'; import ZoomOutMap from '@material-ui/icons/ZoomOutMap'; import React from 'react'; import { useAsync } from 'react-use'; @@ -138,7 +138,11 @@ export function SystemDiagramCard() { if (loading) { return ; } else if (error) { - return {error.message}; + return ( + + {error.message} + + ); } return ( From 5a5b0bf7a9b9679949743c3308ca822b0b24849c Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 25 Mar 2021 11:04:47 -0400 Subject: [PATCH 36/40] Update changeset Signed-off-by: Adam Harvey --- .changeset/perfect-coats-train.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/perfect-coats-train.md b/.changeset/perfect-coats-train.md index 7a089e870f..9357f51370 100644 --- a/.changeset/perfect-coats-train.md +++ b/.changeset/perfect-coats-train.md @@ -10,7 +10,7 @@ For example, ```diff const SystemEntityPage = ({ entity }: { entity: Entity }) => ( - + } + /> - + ); ``` From aabd999a1a9efad6071bbb6ecb1053c8fc2bb72e Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 26 Mar 2021 09:32:39 -0400 Subject: [PATCH 37/40] Update localization Signed-off-by: Adam Harvey --- .../src/components/SystemDiagramCard/SystemDiagramCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index e2c48fe521..4297f67f79 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -50,7 +50,7 @@ function simplifiedEntityName( // Simplify the diagram output by hiding only the default namespace return serializeEntityRef(ref) .toString() - .toLowerCase() + .toLocaleLowerCase('en-US') .replace(':default/', ':'); } From 534f0fe8cb5988dd3a8dc4783e9026fdd01aef0b Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 26 Mar 2021 09:33:15 -0400 Subject: [PATCH 38/40] Simplify filter Signed-off-by: Adam Harvey --- .../src/components/SystemDiagramCard/SystemDiagramCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index 4297f67f79..b26e042472 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -70,7 +70,7 @@ export function SystemDiagramCard() { return catalogApi.getEntities({ filter: { kind: ['Component', 'API', 'Resource', 'System', 'Domain'], - ['spec.system']: currentSystemName, + 'spec.system': currentSystemName, }, }); }, [catalogApi]); From c0a6a25cc8d460ca1d9c510a4d1fb07fa0fa0737 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 26 Mar 2021 09:34:07 -0400 Subject: [PATCH 39/40] Update async deps Signed-off-by: Adam Harvey --- .../src/components/SystemDiagramCard/SystemDiagramCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index b26e042472..9ec0e47bee 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -73,7 +73,7 @@ export function SystemDiagramCard() { 'spec.system': currentSystemName, }, }); - }, [catalogApi]); + }, [catalogApi, currentSystemName]); // pick out the system itself systemNodes.push({ From 4ef1ba84d21d5fe42f1a077e7cc45b806d865e6d Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Fri, 26 Mar 2021 09:40:19 -0400 Subject: [PATCH 40/40] Change error reporting component Signed-off-by: Adam Harvey --- .../components/SystemDiagramCard/SystemDiagramCard.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index 9ec0e47bee..df20e910aa 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -31,7 +31,7 @@ import { InfoCard, Progress, useApi, - WarningPanel, + ResponseErrorPanel, } from '@backstage/core'; import { Box, Typography } from '@material-ui/core'; import ZoomOutMap from '@material-ui/icons/ZoomOutMap'; @@ -138,11 +138,7 @@ export function SystemDiagramCard() { if (loading) { return ; } else if (error) { - return ( - - {error.message} - - ); + return ; } return (