From 536834515b0536eb494e47c03380700253afd138 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Fri, 16 Apr 2021 09:26:50 -0400 Subject: [PATCH 01/17] added HasResourcesCard for system resources, and DependsOnComponentsCard/DependsOnResourcesCard for component dependencies Signed-off-by: Jonah Grimes --- .../DependsOnComponentsCard.test.tsx | 117 ++++++++++++++++++ .../DependsOnComponentsCard.tsx | 92 ++++++++++++++ .../DependsOnComponentsCard/index.ts | 17 +++ .../DependsOnResourcesCard.test.tsx | 117 ++++++++++++++++++ .../DependsOnResourcesCard.tsx | 92 ++++++++++++++ .../DependsOnResourcesCard/index.ts | 17 +++ .../HasResourcesCard.test.tsx | 117 ++++++++++++++++++ .../HasResourcesCard/HasResourcesCard.tsx | 94 ++++++++++++++ .../src/components/HasResourcesCard/index.ts | 17 +++ plugins/catalog/src/plugin.ts | 33 +++++ 10 files changed, 713 insertions(+) create mode 100644 plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx create mode 100644 plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx create mode 100644 plugins/catalog/src/components/DependsOnComponentsCard/index.ts create mode 100644 plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx create mode 100644 plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx create mode 100644 plugins/catalog/src/components/DependsOnResourcesCard/index.ts create mode 100644 plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx create mode 100644 plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx create mode 100644 plugins/catalog/src/components/HasResourcesCard/index.ts diff --git a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx new file mode 100644 index 0000000000..0a1e120eff --- /dev/null +++ b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx @@ -0,0 +1,117 @@ +/* + * 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, RELATION_DEPENDS_ON } from '@backstage/catalog-model'; +import { ApiProvider, ApiRegistry } from '@backstage/core'; +import { + CatalogApi, + catalogApiRef, + EntityProvider, +} from '@backstage/plugin-catalog-react'; +import { renderInTestApp } from '@backstage/test-utils'; +import { waitFor } from '@testing-library/react'; +import React from 'react'; +import { DependsOnComponentsCard } from './DependsOnComponentsCard'; + +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; + let Wrapper: React.ComponentType; + + beforeEach(() => { + const apis = ApiRegistry.with(catalogApiRef, catalogApi); + + Wrapper = ({ children }: { children?: React.ReactNode }) => ( + {children} + ); + }); + + afterEach(() => jest.resetAllMocks()); + + it('shows empty list if no dependencies', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-component', + namespace: 'my-namespace', + }, + relations: [], + }; + + const { getByText } = await renderInTestApp( + + + + + , + ); + + expect(getByText('Components')).toBeInTheDocument(); + expect( + getByText(/No component is a dependency of this component/i), + ).toBeInTheDocument(); + }); + + it('shows dependency components', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-component', + namespace: 'my-namespace', + }, + relations: [ + { + target: { + kind: 'Component', + namespace: 'my-namespace', + name: 'target-name', + }, + type: RELATION_DEPENDS_ON, + }, + ], + }; + catalogApi.getEntityByName.mockResolvedValue({ + apiVersion: 'v1', + kind: 'Component', + metadata: { + namespace: 'my-namespace', + name: 'target-name', + }, + spec: {}, + }); + + const { getByText } = await renderInTestApp( + + + + + , + ); + + await waitFor(() => { + expect(getByText('Components')).toBeInTheDocument(); + expect(getByText(/target-name/i)).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx new file mode 100644 index 0000000000..18c6173e17 --- /dev/null +++ b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx @@ -0,0 +1,92 @@ +/* + * 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 { ComponentEntity, RELATION_DEPENDS_ON } from '@backstage/catalog-model'; +import { + CodeSnippet, + InfoCard, + Link, + Progress, + WarningPanel, +} from '@backstage/core'; +import { Typography } from '@material-ui/core'; +import { + EntityTable, + useEntity, + useRelatedEntities, +} from '@backstage/plugin-catalog-react'; +import React from 'react'; + +type Props = { + variant?: 'gridItem'; +}; + +const columns = [ + EntityTable.columns.createEntityRefColumn({ defaultKind: 'component' }), + EntityTable.columns.createOwnerColumn(), + EntityTable.columns.createSpecTypeColumn(), + EntityTable.columns.createSpecLifecycleColumn(), + EntityTable.columns.createMetadataDescriptionColumn(), +]; + +export const DependsOnComponentsCard = ({ variant = 'gridItem' }: Props) => { + const { entity } = useEntity(); + const { entities, loading, error } = useRelatedEntities(entity, { + type: RELATION_DEPENDS_ON, + kind: 'Component', + }); + + if (loading) { + return ( + + + + ); + } + + if (error || !entities) { + return ( + + } + /> + + ); + } + + return ( + + + No component is a dependency of this component. + + + + Learn how to change this. + + + + } + columns={columns} + entities={entities as ComponentEntity[]} + /> + ); +}; diff --git a/plugins/catalog/src/components/DependsOnComponentsCard/index.ts b/plugins/catalog/src/components/DependsOnComponentsCard/index.ts new file mode 100644 index 0000000000..f46faf8198 --- /dev/null +++ b/plugins/catalog/src/components/DependsOnComponentsCard/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 { DependsOnComponentsCard } from './DependsOnComponentsCard'; diff --git a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx new file mode 100644 index 0000000000..52ccfe7862 --- /dev/null +++ b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx @@ -0,0 +1,117 @@ +/* + * 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, RELATION_DEPENDS_ON } from '@backstage/catalog-model'; +import { ApiProvider, ApiRegistry } from '@backstage/core'; +import { + CatalogApi, + catalogApiRef, + EntityProvider, +} from '@backstage/plugin-catalog-react'; +import { renderInTestApp } from '@backstage/test-utils'; +import { waitFor } from '@testing-library/react'; +import React from 'react'; +import { DependsOnResourcesCard } from './DependsOnResourcesCard'; + +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; + let Wrapper: React.ComponentType; + + beforeEach(() => { + const apis = ApiRegistry.with(catalogApiRef, catalogApi); + + Wrapper = ({ children }: { children?: React.ReactNode }) => ( + {children} + ); + }); + + afterEach(() => jest.resetAllMocks()); + + it('shows empty list if no dependencies', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-component', + namespace: 'my-namespace', + }, + relations: [], + }; + + const { getByText } = await renderInTestApp( + + + + + , + ); + + expect(getByText('Resources')).toBeInTheDocument(); + expect( + getByText(/No resource is a dependency of this component/i), + ).toBeInTheDocument(); + }); + + it('shows dependency resources', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'Component', + metadata: { + name: 'my-component', + namespace: 'my-namespace', + }, + relations: [ + { + target: { + kind: 'Resource', + namespace: 'my-namespace', + name: 'target-name', + }, + type: RELATION_DEPENDS_ON, + }, + ], + }; + catalogApi.getEntityByName.mockResolvedValue({ + apiVersion: 'v1', + kind: 'Resource', + metadata: { + namespace: 'my-namespace', + name: 'target-name', + }, + spec: {}, + }); + + const { getByText } = await renderInTestApp( + + + + + , + ); + + await waitFor(() => { + expect(getByText('Resources')).toBeInTheDocument(); + expect(getByText(/target-name/i)).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx new file mode 100644 index 0000000000..798a579b9a --- /dev/null +++ b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx @@ -0,0 +1,92 @@ +/* + * 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 { ComponentEntity, RELATION_DEPENDS_ON } from '@backstage/catalog-model'; +import { + CodeSnippet, + InfoCard, + Link, + Progress, + WarningPanel, +} from '@backstage/core'; +import { Typography } from '@material-ui/core'; +import { + EntityTable, + useEntity, + useRelatedEntities, +} from '@backstage/plugin-catalog-react'; +import React from 'react'; + +type Props = { + variant?: 'gridItem'; +}; + +const columns = [ + EntityTable.columns.createEntityRefColumn({ defaultKind: 'resource' }), + EntityTable.columns.createOwnerColumn(), + EntityTable.columns.createSpecTypeColumn(), + EntityTable.columns.createSpecLifecycleColumn(), + EntityTable.columns.createMetadataDescriptionColumn(), +]; + +export const DependsOnResourcesCard = ({ variant = 'gridItem' }: Props) => { + const { entity } = useEntity(); + const { entities, loading, error } = useRelatedEntities(entity, { + type: RELATION_DEPENDS_ON, + kind: 'Resource', + }); + + if (loading) { + return ( + + + + ); + } + + if (error || !entities) { + return ( + + } + /> + + ); + } + + return ( + + + No resource is a dependency of this component. + + + + Learn how to change this. + + + + } + columns={columns} + entities={entities as ComponentEntity[]} + /> + ); +}; diff --git a/plugins/catalog/src/components/DependsOnResourcesCard/index.ts b/plugins/catalog/src/components/DependsOnResourcesCard/index.ts new file mode 100644 index 0000000000..20062f51dd --- /dev/null +++ b/plugins/catalog/src/components/DependsOnResourcesCard/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 { DependsOnResourcesCard } from './DependsOnResourcesCard'; diff --git a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx new file mode 100644 index 0000000000..5b89dbbd6f --- /dev/null +++ b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx @@ -0,0 +1,117 @@ +/* + * 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, RELATION_HAS_PART } from '@backstage/catalog-model'; +import { ApiProvider, ApiRegistry } from '@backstage/core'; +import { + CatalogApi, + catalogApiRef, + EntityProvider, +} from '@backstage/plugin-catalog-react'; +import { renderInTestApp } from '@backstage/test-utils'; +import { waitFor } from '@testing-library/react'; +import React from 'react'; +import { HasResourcesCard } from './HasResourcesCard'; + +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; + let Wrapper: React.ComponentType; + + beforeEach(() => { + const apis = ApiRegistry.with(catalogApiRef, catalogApi); + + Wrapper = ({ children }: { children?: React.ReactNode }) => ( + {children} + ); + }); + + afterEach(() => jest.resetAllMocks()); + + it('shows empty list if no relations', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'System', + metadata: { + name: 'my-system', + namespace: 'my-namespace', + }, + relations: [], + }; + + const { getByText } = await renderInTestApp( + + + + + , + ); + + expect(getByText('Resources')).toBeInTheDocument(); + expect( + getByText(/No resource is part of this system/i), + ).toBeInTheDocument(); + }); + + it('shows related resources', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'System', + metadata: { + name: 'my-system', + namespace: 'my-namespace', + }, + relations: [ + { + target: { + kind: 'Resource', + namespace: 'my-namespace', + name: 'target-name', + }, + type: RELATION_HAS_PART, + }, + ], + }; + catalogApi.getEntityByName.mockResolvedValue({ + apiVersion: 'v1', + kind: 'Resource', + metadata: { + name: 'target-name', + namespace: 'my-namespace', + }, + spec: {}, + }); + + const { getByText } = await renderInTestApp( + + + + + , + ); + + await waitFor(() => { + expect(getByText('Resources')).toBeInTheDocument(); + expect(getByText(/target-name/i)).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx new file mode 100644 index 0000000000..7da7fc4465 --- /dev/null +++ b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx @@ -0,0 +1,94 @@ +/* + * 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 { ResourceEntity, RELATION_HAS_PART } from '@backstage/catalog-model'; +import { + CodeSnippet, + InfoCard, + Link, + Progress, + WarningPanel, +} from '@backstage/core'; +import { Typography } from '@material-ui/core'; +import { + EntityTable, + useEntity, + useRelatedEntities, +} from '@backstage/plugin-catalog-react'; +import React from 'react'; + +type Props = { + variant?: 'gridItem'; +}; + +const columns = [ + EntityTable.columns.createEntityRefColumn({ defaultKind: 'resource' }), + EntityTable.columns.createOwnerColumn(), + EntityTable.columns.createSpecTypeColumn(), + EntityTable.columns.createSpecLifecycleColumn(), + EntityTable.columns.createMetadataDescriptionColumn(), +]; + +export const HasResourcesCard = ({ + variant = 'gridItem', +}: Props) => { + const { entity } = useEntity(); + const { entities, loading, error } = useRelatedEntities(entity, { + type: RELATION_HAS_PART, + kind: 'Resource', + }); + + if (loading) { + return ( + + + + ); + } + + if (error || !entities) { + return ( + + } + /> + + ); + } + + return ( + + + No resource is part of this system. + + + + Learn how to change this. + + + + } + columns={columns} + entities={entities as ResourceEntity[]} + /> + ); +}; diff --git a/plugins/catalog/src/components/HasResourcesCard/index.ts b/plugins/catalog/src/components/HasResourcesCard/index.ts new file mode 100644 index 0000000000..48b1d419aa --- /dev/null +++ b/plugins/catalog/src/components/HasResourcesCard/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 { HasResourcesCard } from './HasResourcesCard'; diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index 20c7a865db..ba6cc3a19d 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -115,6 +115,39 @@ export const EntityHasSubcomponentsCard = catalogPlugin.provide( }), ); +export const EntityHasResourcesCard = catalogPlugin.provide( + createComponentExtension({ + component: { + lazy: () => + import('./components/HasResourcesCard').then( + m => m.HasResourcesCard, + ), + }, + }), +); + +export const EntityDependsOnComponentsCard = catalogPlugin.provide( + createComponentExtension({ + component: { + lazy: () => + import('./components/DependsOnComponentsCard').then( + m => m.DependsOnComponentsCard, + ), + }, + }), +); + +export const EntityDependsOnResourcesCard = catalogPlugin.provide( + createComponentExtension({ + component: { + lazy: () => + import('./components/DependsOnResourcesCard').then( + m => m.DependsOnResourcesCard, + ), + }, + }), +); + export const EntitySystemDiagramCard = catalogPlugin.provide( createComponentExtension({ component: { From 9304d2392ba2fdca1e78188aa56558d3243bd740 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Fri, 16 Apr 2021 09:34:04 -0400 Subject: [PATCH 02/17] added exports for EntityHasResourcesCard, EntityDependsOnComponentsCard, and EntityDependsOnResourcesCard Signed-off-by: Jonah Grimes --- plugins/catalog/src/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts index 7ab7b95dd7..2df1d2f511 100644 --- a/plugins/catalog/src/index.ts +++ b/plugins/catalog/src/index.ts @@ -25,7 +25,10 @@ export { catalogPlugin, catalogPlugin as plugin, EntityAboutCard, + EntityDependsOnComponentsCard, + EntityDependsOnResourcesCard, EntityHasComponentsCard, + EntityHasResourcesCard, EntityHasSubcomponentsCard, EntityHasSystemsCard, EntityLinksCard, From 35965ab248c3556150cf11344310504e39f23de0 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Fri, 16 Apr 2021 09:47:29 -0400 Subject: [PATCH 03/17] added EntityHasResourcesCard to system overview page, added dependencies page to display dependency components and dependency resources to service and website page layout Signed-off-by: Jonah Grimes --- .../app/src/components/catalog/EntityPage.tsx | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 601134362d..fc3719e425 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -28,6 +28,8 @@ import { import { EntityBadgesDialog } from '@backstage/plugin-badges'; import { EntityAboutCard, + EntityDependsOnComponentsCard, + EntityDependsOnResourcesCard, EntityHasComponentsCard, EntityHasSubcomponentsCard, EntityHasSystemsCard, @@ -37,6 +39,7 @@ import { EntitySwitch, isComponentType, isKind, + EntityHasResourcesCard, } from '@backstage/plugin-catalog'; import { EntityCircleCIContent, @@ -288,6 +291,17 @@ const serviceEntityPage = ( + + + + + + + + + + + @@ -336,6 +350,17 @@ const websiteEntityPage = ( {errorsContent} + + + + + + + + + + + @@ -466,6 +491,9 @@ const systemPage = ( + + + From a53f3d60338eb6fc758f86cd48935c94ae198943 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Fri, 16 Apr 2021 09:57:41 -0400 Subject: [PATCH 04/17] added changeset Signed-off-by: Jonah Grimes --- .changeset/weak-jeans-live.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/weak-jeans-live.md diff --git a/.changeset/weak-jeans-live.md b/.changeset/weak-jeans-live.md new file mode 100644 index 0000000000..f92f20199d --- /dev/null +++ b/.changeset/weak-jeans-live.md @@ -0,0 +1,9 @@ +--- +'example-app': patch +'@backstage/plugin-catalog': patch +--- + +- Added `EntityHasResourcesCard` to display resources that are part of a system. +- Added `EntityDependsOnComponentsCard` to display components that are dependencies of a component. +- Added `EntityDependsOnResourcesCard` to display resources that are dependencies of a component. +- Updated the example app to take advantage of these new components. From ab313cb14bb39e3a248b2b8da685dea25a3f19f7 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Fri, 16 Apr 2021 10:32:15 -0400 Subject: [PATCH 05/17] ran prettier to format code Signed-off-by: Jonah Grimes --- .../src/components/HasResourcesCard/HasResourcesCard.tsx | 4 +--- plugins/catalog/src/plugin.ts | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx index 7da7fc4465..ad53d9ce7f 100644 --- a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx +++ b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx @@ -42,9 +42,7 @@ const columns = [ EntityTable.columns.createMetadataDescriptionColumn(), ]; -export const HasResourcesCard = ({ - variant = 'gridItem', -}: Props) => { +export const HasResourcesCard = ({ variant = 'gridItem' }: Props) => { const { entity } = useEntity(); const { entities, loading, error } = useRelatedEntities(entity, { type: RELATION_HAS_PART, diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index ba6cc3a19d..3f4de6c67d 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -119,9 +119,7 @@ export const EntityHasResourcesCard = catalogPlugin.provide( createComponentExtension({ component: { lazy: () => - import('./components/HasResourcesCard').then( - m => m.HasResourcesCard, - ), + import('./components/HasResourcesCard').then(m => m.HasResourcesCard), }, }), ); From 2f989a972d948119e0c4c389bde3a213239cea6f Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Mon, 19 Apr 2021 09:38:20 -0400 Subject: [PATCH 06/17] removed example-app from the changeset Signed-off-by: Jonah Grimes --- .changeset/weak-jeans-live.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/weak-jeans-live.md b/.changeset/weak-jeans-live.md index f92f20199d..041021b052 100644 --- a/.changeset/weak-jeans-live.md +++ b/.changeset/weak-jeans-live.md @@ -1,5 +1,4 @@ --- -'example-app': patch '@backstage/plugin-catalog': patch --- From 4f88bf4e07f9afad7c38c1ba002f1edc398854dd Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Thu, 29 Apr 2021 13:05:57 -0400 Subject: [PATCH 07/17] Added `RelatedEntitesCard` as a base implementation of displaying entities that are related to another entity, and refactored cards that display related entities to use it. Signed-off-by: Jonah Grimes --- .changeset/weak-jeans-live.md | 10 +- .../DependsOnComponentsCard.tsx | 79 +++------------ .../DependsOnResourcesCard.tsx | 79 +++------------ .../HasComponentsCard/HasComponentsCard.tsx | 79 +++------------ .../HasResourcesCard/HasResourcesCard.tsx | 79 +++------------ .../HasSubcomponentsCard.tsx | 78 +++------------ .../HasSystemsCard/HasSystemsCard.tsx | 76 +++------------ .../RelatedEntitiesCard.tsx | 97 +++++++++++++++++++ .../RelatedEntitiesCard/constants.ts | 56 +++++++++++ .../components/RelatedEntitiesCard/index.ts | 18 ++++ 10 files changed, 267 insertions(+), 384 deletions(-) create mode 100644 plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx create mode 100644 plugins/catalog/src/components/RelatedEntitiesCard/constants.ts create mode 100644 plugins/catalog/src/components/RelatedEntitiesCard/index.ts diff --git a/.changeset/weak-jeans-live.md b/.changeset/weak-jeans-live.md index 041021b052..0d25f07cca 100644 --- a/.changeset/weak-jeans-live.md +++ b/.changeset/weak-jeans-live.md @@ -2,7 +2,11 @@ '@backstage/plugin-catalog': patch --- -- Added `EntityHasResourcesCard` to display resources that are part of a system. -- Added `EntityDependsOnComponentsCard` to display components that are dependencies of a component. -- Added `EntityDependsOnResourcesCard` to display resources that are dependencies of a component. +- Added `RelatedEntitesCard` as a base implementation of displaying entities that are related to another entity. +- Added `HasResourcesCard` to display resources that are part of a system. +- Added `DependsOnComponentsCard` to display components that are dependencies of a component. +- Added `DependsOnResourcesCard` to display resources that are dependencies of a component. +- Refactored `HasComponentsCard` to use base `RelatedEntitiesCard`. Card remains backwards compatible. +- Refactored `HasSubcomponentsCard` to use base `RelatedEntitiesCard`. Card remains backwards compatible. +- Refactored `HasSystemsCard` to use base `RelatedEntitiesCard`. Card remains backwards compatible. - Updated the example app to take advantage of these new components. diff --git a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx index 18c6173e17..41b4117792 100644 --- a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx +++ b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx @@ -14,79 +14,30 @@ * limitations under the License. */ -import { ComponentEntity, RELATION_DEPENDS_ON } from '@backstage/catalog-model'; -import { - CodeSnippet, - InfoCard, - Link, - Progress, - WarningPanel, -} from '@backstage/core'; -import { Typography } from '@material-ui/core'; -import { - EntityTable, - useEntity, - useRelatedEntities, -} from '@backstage/plugin-catalog-react'; +import { RELATION_DEPENDS_ON } from '@backstage/catalog-model'; import React from 'react'; +import { + asComponentEntities, + componentColumns, + componentHelpLink, + RelatedEntitiesCard, +} from '../RelatedEntitiesCard'; type Props = { variant?: 'gridItem'; }; -const columns = [ - EntityTable.columns.createEntityRefColumn({ defaultKind: 'component' }), - EntityTable.columns.createOwnerColumn(), - EntityTable.columns.createSpecTypeColumn(), - EntityTable.columns.createSpecLifecycleColumn(), - EntityTable.columns.createMetadataDescriptionColumn(), -]; - export const DependsOnComponentsCard = ({ variant = 'gridItem' }: Props) => { - const { entity } = useEntity(); - const { entities, loading, error } = useRelatedEntities(entity, { - type: RELATION_DEPENDS_ON, - kind: 'Component', - }); - - if (loading) { - return ( - - - - ); - } - - if (error || !entities) { - return ( - - } - /> - - ); - } - return ( - - - No component is a dependency of this component. - - - - Learn how to change this. - - - - } - columns={columns} - entities={entities as ComponentEntity[]} + title="Components" + entityKind="Component" + relationType={RELATION_DEPENDS_ON} + columns={componentColumns} + emptyMessage="No component is a dependency of this component" + emptyHelpLink={componentHelpLink} + asRenderableEntities={asComponentEntities} /> ); }; diff --git a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx index 798a579b9a..7658af1456 100644 --- a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx +++ b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx @@ -14,79 +14,30 @@ * limitations under the License. */ -import { ComponentEntity, RELATION_DEPENDS_ON } from '@backstage/catalog-model'; -import { - CodeSnippet, - InfoCard, - Link, - Progress, - WarningPanel, -} from '@backstage/core'; -import { Typography } from '@material-ui/core'; -import { - EntityTable, - useEntity, - useRelatedEntities, -} from '@backstage/plugin-catalog-react'; +import { RELATION_DEPENDS_ON } from '@backstage/catalog-model'; import React from 'react'; +import { + asResourceEntities, + componentHelpLink, + RelatedEntitiesCard, + resourceColumns, +} from '../RelatedEntitiesCard'; type Props = { variant?: 'gridItem'; }; -const columns = [ - EntityTable.columns.createEntityRefColumn({ defaultKind: 'resource' }), - EntityTable.columns.createOwnerColumn(), - EntityTable.columns.createSpecTypeColumn(), - EntityTable.columns.createSpecLifecycleColumn(), - EntityTable.columns.createMetadataDescriptionColumn(), -]; - export const DependsOnResourcesCard = ({ variant = 'gridItem' }: Props) => { - const { entity } = useEntity(); - const { entities, loading, error } = useRelatedEntities(entity, { - type: RELATION_DEPENDS_ON, - kind: 'Resource', - }); - - if (loading) { - return ( - - - - ); - } - - if (error || !entities) { - return ( - - } - /> - - ); - } - return ( - - - No resource is a dependency of this component. - - - - Learn how to change this. - - - - } - columns={columns} - entities={entities as ComponentEntity[]} + title="Resources" + entityKind="Resource" + relationType={RELATION_DEPENDS_ON} + columns={resourceColumns} + emptyMessage="No resource is a dependency of this component" + emptyHelpLink={componentHelpLink} + asRenderableEntities={asResourceEntities} /> ); }; diff --git a/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx b/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx index b6eae81f30..2f3a0572d2 100644 --- a/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx +++ b/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx @@ -14,79 +14,30 @@ * limitations under the License. */ -import { ComponentEntity, RELATION_HAS_PART } from '@backstage/catalog-model'; -import { - CodeSnippet, - InfoCard, - Link, - Progress, - WarningPanel, -} from '@backstage/core'; -import { Typography } from '@material-ui/core'; -import { - EntityTable, - useEntity, - useRelatedEntities, -} from '@backstage/plugin-catalog-react'; +import { RELATION_HAS_PART } from '@backstage/catalog-model'; import React from 'react'; +import { + asComponentEntities, + componentColumns, + componentHelpLink, + RelatedEntitiesCard, +} from '../RelatedEntitiesCard'; type Props = { variant?: 'gridItem'; }; -const columns = [ - EntityTable.columns.createEntityRefColumn({ defaultKind: 'component' }), - EntityTable.columns.createOwnerColumn(), - EntityTable.columns.createSpecTypeColumn(), - EntityTable.columns.createSpecLifecycleColumn(), - EntityTable.columns.createMetadataDescriptionColumn(), -]; - export const HasComponentsCard = ({ variant = 'gridItem' }: Props) => { - const { entity } = useEntity(); - const { entities, loading, error } = useRelatedEntities(entity, { - type: RELATION_HAS_PART, - kind: 'Component', - }); - - if (loading) { - return ( - - - - ); - } - - if (error || !entities) { - return ( - - } - /> - - ); - } - return ( - - - No component is part of this system. - - - - Learn how to change this. - - - - } - columns={columns} - entities={entities as ComponentEntity[]} + title="Components" + entityKind="Component" + relationType={RELATION_HAS_PART} + columns={componentColumns} + emptyMessage="No component is part of this system" + emptyHelpLink={componentHelpLink} + asRenderableEntities={asComponentEntities} /> ); }; diff --git a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx index ad53d9ce7f..6d33dcb419 100644 --- a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx +++ b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx @@ -14,79 +14,30 @@ * limitations under the License. */ -import { ResourceEntity, RELATION_HAS_PART } from '@backstage/catalog-model'; -import { - CodeSnippet, - InfoCard, - Link, - Progress, - WarningPanel, -} from '@backstage/core'; -import { Typography } from '@material-ui/core'; -import { - EntityTable, - useEntity, - useRelatedEntities, -} from '@backstage/plugin-catalog-react'; +import { RELATION_HAS_PART } from '@backstage/catalog-model'; import React from 'react'; +import { + asResourceEntities, + RelatedEntitiesCard, + resourceColumns, + resourceHelpLink, +} from '../RelatedEntitiesCard'; type Props = { variant?: 'gridItem'; }; -const columns = [ - EntityTable.columns.createEntityRefColumn({ defaultKind: 'resource' }), - EntityTable.columns.createOwnerColumn(), - EntityTable.columns.createSpecTypeColumn(), - EntityTable.columns.createSpecLifecycleColumn(), - EntityTable.columns.createMetadataDescriptionColumn(), -]; - export const HasResourcesCard = ({ variant = 'gridItem' }: Props) => { - const { entity } = useEntity(); - const { entities, loading, error } = useRelatedEntities(entity, { - type: RELATION_HAS_PART, - kind: 'Resource', - }); - - if (loading) { - return ( - - - - ); - } - - if (error || !entities) { - return ( - - } - /> - - ); - } - return ( - - - No resource is part of this system. - - - - Learn how to change this. - - - - } - columns={columns} - entities={entities as ResourceEntity[]} + title="Resources" + entityKind="Resource" + relationType={RELATION_HAS_PART} + columns={resourceColumns} + asRenderableEntities={asResourceEntities} + emptyMessage="No resource is part of this system" + emptyHelpLink={resourceHelpLink} /> ); }; diff --git a/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx b/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx index 41244ba3d4..5613c6a9cc 100644 --- a/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx +++ b/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx @@ -14,79 +14,29 @@ * limitations under the License. */ -import { ComponentEntity, RELATION_HAS_PART } from '@backstage/catalog-model'; -import { - CodeSnippet, - InfoCard, - Link, - Progress, - WarningPanel, -} from '@backstage/core'; -import { Typography } from '@material-ui/core'; -import { - EntityTable, - useEntity, - useRelatedEntities, -} from '@backstage/plugin-catalog-react'; +import { RELATION_HAS_PART } from '@backstage/catalog-model'; import React from 'react'; +import { + asComponentEntities, + componentColumns, + RelatedEntitiesCard, +} from '../RelatedEntitiesCard'; type Props = { variant?: 'gridItem'; }; -const columns = [ - EntityTable.columns.createEntityRefColumn({ defaultKind: 'component' }), - EntityTable.columns.createOwnerColumn(), - EntityTable.columns.createSpecTypeColumn(), - EntityTable.columns.createSpecLifecycleColumn(), - EntityTable.columns.createMetadataDescriptionColumn(), -]; - export const HasSubcomponentsCard = ({ variant = 'gridItem' }: Props) => { - const { entity } = useEntity(); - const { entities, loading, error } = useRelatedEntities(entity, { - type: RELATION_HAS_PART, - kind: 'Component', - }); - - if (loading) { - return ( - - - - ); - } - - if (error || !entities) { - return ( - - } - /> - - ); - } - return ( - - - No subcomponent is part of this component. - - - - Learn how to change this. - - - - } - columns={columns} - entities={entities as ComponentEntity[]} + title="Subcomponents" + entityKind="Component" + relationType={RELATION_HAS_PART} + columns={componentColumns} + asRenderableEntities={asComponentEntities} + emptyMessage="No subcomponent is part of this component" + emptyHelpLink="https://backstage.io/docs/features/software-catalog/descriptor-format#specsubcomponentof-optional" /> ); }; diff --git a/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx b/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx index ea4de474de..1ddb8cad5c 100644 --- a/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx +++ b/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx @@ -14,76 +14,30 @@ * limitations under the License. */ -import { RELATION_HAS_PART, SystemEntity } from '@backstage/catalog-model'; -import { - CodeSnippet, - InfoCard, - Link, - Progress, - WarningPanel, -} from '@backstage/core'; -import { Typography } from '@material-ui/core'; -import { - EntityTable, - useEntity, - useRelatedEntities, -} from '@backstage/plugin-catalog-react'; +import { RELATION_HAS_PART } from '@backstage/catalog-model'; import React from 'react'; +import { + asSystemEntities, + RelatedEntitiesCard, + systemColumns, + systemHelpLink, +} from '../RelatedEntitiesCard'; type Props = { variant?: 'gridItem'; }; -const columns = [ - EntityTable.columns.createEntityRefColumn({ defaultKind: 'system' }), - EntityTable.columns.createOwnerColumn(), - EntityTable.columns.createMetadataDescriptionColumn(), -]; - export const HasSystemsCard = ({ variant = 'gridItem' }: Props) => { - const { entity } = useEntity(); - const { entities, loading, error } = useRelatedEntities(entity, { - type: RELATION_HAS_PART, - }); - - if (loading) { - return ( - - - - ); - } - - if (error || !entities) { - return ( - - } - /> - - ); - } - return ( - - - No system is part of this domain. - - - - Learn how to change this. - - - - } - columns={columns} - entities={entities as SystemEntity[]} + title="Systems" + entityKind="System" + relationType={RELATION_HAS_PART} + columns={systemColumns} + asRenderableEntities={asSystemEntities} + emptyMessage="No system is part of this domain" + emptyHelpLink={systemHelpLink} /> ); }; diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx new file mode 100644 index 0000000000..6405faad17 --- /dev/null +++ b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx @@ -0,0 +1,97 @@ +/* + * 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 { + CodeSnippet, + InfoCard, + Link, + Progress, + TableColumn, + WarningPanel, +} from '@backstage/core'; +import { Typography } from '@material-ui/core'; +import { + EntityTable, + useEntity, + useRelatedEntities, +} from '@backstage/plugin-catalog-react'; +import React from 'react'; + +type Props = { + variant?: 'gridItem'; + title: string; + columns: TableColumn[]; + entityKind: string; + relationType: string; + emptyMessage: string; + emptyHelpLink: string; + asRenderableEntities: (entities: Entity[]) => Entity[]; +}; + +export const RelatedEntitiesCard = ({ + variant = 'gridItem', + title, + columns, + entityKind, + relationType, + emptyMessage, + emptyHelpLink, + asRenderableEntities, +}: Props) => { + const { entity } = useEntity(); + const { entities, loading, error } = useRelatedEntities(entity, { + type: relationType, + kind: entityKind, + }); + + if (loading) { + return ( + + + + ); + } + + if (error || !entities) { + return ( + + } + /> + + ); + } + + return ( + + {emptyMessage} + + Learn how to change this. + + + } + columns={columns} + entities={asRenderableEntities(entities)} + /> + ); +}; diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/constants.ts b/plugins/catalog/src/components/RelatedEntitiesCard/constants.ts new file mode 100644 index 0000000000..78e11edd9b --- /dev/null +++ b/plugins/catalog/src/components/RelatedEntitiesCard/constants.ts @@ -0,0 +1,56 @@ +/* + * 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. + * 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 { + ComponentEntity, + Entity, + ResourceEntity, + SystemEntity, +} from '@backstage/catalog-model'; +import { EntityTable } from '@backstage/plugin-catalog-react'; + +export const componentColumns = [ + EntityTable.columns.createEntityRefColumn({ defaultKind: 'component' }), + EntityTable.columns.createOwnerColumn(), + EntityTable.columns.createSpecTypeColumn(), + EntityTable.columns.createSpecLifecycleColumn(), + EntityTable.columns.createMetadataDescriptionColumn(), +]; +export const componentHelpLink = + 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-component'; +export const asComponentEntities = (entities: Entity[]) => + entities as ComponentEntity[]; + +export const resourceColumns = [ + EntityTable.columns.createEntityRefColumn({ defaultKind: 'resource' }), + EntityTable.columns.createOwnerColumn(), + EntityTable.columns.createSpecTypeColumn(), + EntityTable.columns.createSpecLifecycleColumn(), + EntityTable.columns.createMetadataDescriptionColumn(), +]; +export const resourceHelpLink = + 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-resource'; +export const asResourceEntities = (entities: Entity[]) => + entities as ResourceEntity[]; + +export const systemColumns = [ + EntityTable.columns.createEntityRefColumn({ defaultKind: 'system' }), + EntityTable.columns.createOwnerColumn(), + EntityTable.columns.createMetadataDescriptionColumn(), +]; +export const systemHelpLink = + 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-system'; +export const asSystemEntities = (entities: Entity[]) => + entities as SystemEntity[]; diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/index.ts b/plugins/catalog/src/components/RelatedEntitiesCard/index.ts new file mode 100644 index 0000000000..b2cb93c5cf --- /dev/null +++ b/plugins/catalog/src/components/RelatedEntitiesCard/index.ts @@ -0,0 +1,18 @@ +/* + * 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 { RelatedEntitiesCard } from './RelatedEntitiesCard'; +export * from './constants'; From 38df6b64f3807ae535168fc508cc393dd381aa97 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Thu, 29 Apr 2021 16:19:24 -0400 Subject: [PATCH 08/17] Added explicit variant='gridItem' to entity has dependencies cards. Signed-off-by: Jonah Grimes --- 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 fc3719e425..c1d892e061 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -294,10 +294,10 @@ const serviceEntityPage = ( - + - + @@ -353,10 +353,10 @@ const websiteEntityPage = ( - + - + From 1de4461de1961162f1b7dd717a2f57f3b8d547df Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Thu, 29 Apr 2021 17:05:19 -0400 Subject: [PATCH 09/17] Added type parameterization to allow for type safety on new RelatedEntitiesCard. Signed-off-by: Jonah Grimes --- .../DependsOnComponentsCard.tsx | 8 ++++---- .../DependsOnResourcesCard.tsx | 8 ++++---- .../HasComponentsCard/HasComponentsCard.tsx | 8 ++++---- .../HasResourcesCard/HasResourcesCard.tsx | 8 ++++---- .../HasSubcomponentsCard.tsx | 4 ++-- .../HasSystemsCard/HasSystemsCard.tsx | 8 ++++---- .../RelatedEntitiesCard.tsx | 12 ++++++------ .../components/RelatedEntitiesCard/index.ts | 2 +- .../{constants.ts => presets.ts} | 19 ++++++++++--------- 9 files changed, 39 insertions(+), 38 deletions(-) rename plugins/catalog/src/components/RelatedEntitiesCard/{constants.ts => presets.ts} (74%) diff --git a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx index 41b4117792..f837bb02ff 100644 --- a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx +++ b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx @@ -18,8 +18,8 @@ import { RELATION_DEPENDS_ON } from '@backstage/catalog-model'; import React from 'react'; import { asComponentEntities, - componentColumns, - componentHelpLink, + componentEntityColumns, + componentEntityHelpLink, RelatedEntitiesCard, } from '../RelatedEntitiesCard'; @@ -34,9 +34,9 @@ export const DependsOnComponentsCard = ({ variant = 'gridItem' }: Props) => { title="Components" entityKind="Component" relationType={RELATION_DEPENDS_ON} - columns={componentColumns} + columns={componentEntityColumns} emptyMessage="No component is a dependency of this component" - emptyHelpLink={componentHelpLink} + emptyHelpLink={componentEntityHelpLink} asRenderableEntities={asComponentEntities} /> ); diff --git a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx index 7658af1456..7b64654f20 100644 --- a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx +++ b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx @@ -18,9 +18,9 @@ import { RELATION_DEPENDS_ON } from '@backstage/catalog-model'; import React from 'react'; import { asResourceEntities, - componentHelpLink, + componentEntityHelpLink, RelatedEntitiesCard, - resourceColumns, + resourceEntityColumns, } from '../RelatedEntitiesCard'; type Props = { @@ -34,9 +34,9 @@ export const DependsOnResourcesCard = ({ variant = 'gridItem' }: Props) => { title="Resources" entityKind="Resource" relationType={RELATION_DEPENDS_ON} - columns={resourceColumns} + columns={resourceEntityColumns} emptyMessage="No resource is a dependency of this component" - emptyHelpLink={componentHelpLink} + emptyHelpLink={componentEntityHelpLink} asRenderableEntities={asResourceEntities} /> ); diff --git a/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx b/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx index 2f3a0572d2..e2fbb6ff70 100644 --- a/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx +++ b/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx @@ -18,8 +18,8 @@ import { RELATION_HAS_PART } from '@backstage/catalog-model'; import React from 'react'; import { asComponentEntities, - componentColumns, - componentHelpLink, + componentEntityColumns, + componentEntityHelpLink, RelatedEntitiesCard, } from '../RelatedEntitiesCard'; @@ -34,9 +34,9 @@ export const HasComponentsCard = ({ variant = 'gridItem' }: Props) => { title="Components" entityKind="Component" relationType={RELATION_HAS_PART} - columns={componentColumns} + columns={componentEntityColumns} emptyMessage="No component is part of this system" - emptyHelpLink={componentHelpLink} + emptyHelpLink={componentEntityHelpLink} asRenderableEntities={asComponentEntities} /> ); diff --git a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx index 6d33dcb419..be923d30a1 100644 --- a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx +++ b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx @@ -19,8 +19,8 @@ import React from 'react'; import { asResourceEntities, RelatedEntitiesCard, - resourceColumns, - resourceHelpLink, + resourceEntityColumns, + resourceEntityHelpLink, } from '../RelatedEntitiesCard'; type Props = { @@ -34,10 +34,10 @@ export const HasResourcesCard = ({ variant = 'gridItem' }: Props) => { title="Resources" entityKind="Resource" relationType={RELATION_HAS_PART} - columns={resourceColumns} + columns={resourceEntityColumns} asRenderableEntities={asResourceEntities} emptyMessage="No resource is part of this system" - emptyHelpLink={resourceHelpLink} + emptyHelpLink={resourceEntityHelpLink} /> ); }; diff --git a/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx b/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx index 5613c6a9cc..bf4aeb18cc 100644 --- a/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx +++ b/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx @@ -18,7 +18,7 @@ import { RELATION_HAS_PART } from '@backstage/catalog-model'; import React from 'react'; import { asComponentEntities, - componentColumns, + componentEntityColumns, RelatedEntitiesCard, } from '../RelatedEntitiesCard'; @@ -33,7 +33,7 @@ export const HasSubcomponentsCard = ({ variant = 'gridItem' }: Props) => { title="Subcomponents" entityKind="Component" relationType={RELATION_HAS_PART} - columns={componentColumns} + columns={componentEntityColumns} asRenderableEntities={asComponentEntities} emptyMessage="No subcomponent is part of this component" emptyHelpLink="https://backstage.io/docs/features/software-catalog/descriptor-format#specsubcomponentof-optional" diff --git a/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx b/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx index 1ddb8cad5c..b6c5bb7ca2 100644 --- a/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx +++ b/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx @@ -19,8 +19,8 @@ import React from 'react'; import { asSystemEntities, RelatedEntitiesCard, - systemColumns, - systemHelpLink, + systemEntityColumns, + systemEntityHelpLink, } from '../RelatedEntitiesCard'; type Props = { @@ -34,10 +34,10 @@ export const HasSystemsCard = ({ variant = 'gridItem' }: Props) => { title="Systems" entityKind="System" relationType={RELATION_HAS_PART} - columns={systemColumns} + columns={systemEntityColumns} asRenderableEntities={asSystemEntities} emptyMessage="No system is part of this domain" - emptyHelpLink={systemHelpLink} + emptyHelpLink={systemEntityHelpLink} /> ); }; diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx index 6405faad17..e8d1486f87 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx +++ b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx @@ -31,18 +31,18 @@ import { } from '@backstage/plugin-catalog-react'; import React from 'react'; -type Props = { +type Props = { variant?: 'gridItem'; title: string; - columns: TableColumn[]; + columns: TableColumn[]; entityKind: string; relationType: string; emptyMessage: string; emptyHelpLink: string; - asRenderableEntities: (entities: Entity[]) => Entity[]; + asRenderableEntities: (entities: Entity[]) => T[]; }; -export const RelatedEntitiesCard = ({ +export function RelatedEntitiesCard({ variant = 'gridItem', title, columns, @@ -51,7 +51,7 @@ export const RelatedEntitiesCard = ({ emptyMessage, emptyHelpLink, asRenderableEntities, -}: Props) => { +}: Props) { const { entity } = useEntity(); const { entities, loading, error } = useRelatedEntities(entity, { type: relationType, @@ -94,4 +94,4 @@ export const RelatedEntitiesCard = ({ entities={asRenderableEntities(entities)} /> ); -}; +} diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/index.ts b/plugins/catalog/src/components/RelatedEntitiesCard/index.ts index b2cb93c5cf..3104004dd6 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/index.ts +++ b/plugins/catalog/src/components/RelatedEntitiesCard/index.ts @@ -15,4 +15,4 @@ */ export { RelatedEntitiesCard } from './RelatedEntitiesCard'; -export * from './constants'; +export * from './presets'; diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/constants.ts b/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts similarity index 74% rename from plugins/catalog/src/components/RelatedEntitiesCard/constants.ts rename to plugins/catalog/src/components/RelatedEntitiesCard/presets.ts index 78e11edd9b..9d3586a7e9 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/constants.ts +++ b/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts @@ -19,38 +19,39 @@ import { ResourceEntity, SystemEntity, } from '@backstage/catalog-model'; +import { TableColumn } from '@backstage/core'; import { EntityTable } from '@backstage/plugin-catalog-react'; -export const componentColumns = [ +export const componentEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'component' }), EntityTable.columns.createOwnerColumn(), EntityTable.columns.createSpecTypeColumn(), EntityTable.columns.createSpecLifecycleColumn(), EntityTable.columns.createMetadataDescriptionColumn(), ]; -export const componentHelpLink = +export const componentEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-component'; -export const asComponentEntities = (entities: Entity[]) => +export const asComponentEntities = (entities: Entity[]): ComponentEntity[] => entities as ComponentEntity[]; -export const resourceColumns = [ +export const resourceEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'resource' }), EntityTable.columns.createOwnerColumn(), EntityTable.columns.createSpecTypeColumn(), EntityTable.columns.createSpecLifecycleColumn(), EntityTable.columns.createMetadataDescriptionColumn(), ]; -export const resourceHelpLink = +export const resourceEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-resource'; -export const asResourceEntities = (entities: Entity[]) => +export const asResourceEntities = (entities: Entity[]): ResourceEntity[] => entities as ResourceEntity[]; -export const systemColumns = [ +export const systemEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'system' }), EntityTable.columns.createOwnerColumn(), EntityTable.columns.createMetadataDescriptionColumn(), ]; -export const systemHelpLink = +export const systemEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-system'; -export const asSystemEntities = (entities: Entity[]) => +export const asSystemEntities = (entities: Entity[]): SystemEntity[] => entities as SystemEntity[]; From c9717166399101dd112ef0c38ff4c892252950e1 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Tue, 4 May 2021 16:57:17 -0400 Subject: [PATCH 10/17] Update plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Jonah Grimes --- .../src/components/HasResourcesCard/HasResourcesCard.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx index 5b89dbbd6f..fb683b6963 100644 --- a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx +++ b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx @@ -26,7 +26,7 @@ import { waitFor } from '@testing-library/react'; import React from 'react'; import { HasResourcesCard } from './HasResourcesCard'; -describe('', () => { +describe('', () => { const catalogApi: jest.Mocked = { getLocationById: jest.fn(), getEntityByName: jest.fn(), From 16a8fc50794045fc84b5c11adc6d1ae8bf30b16b Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Tue, 4 May 2021 17:13:32 -0400 Subject: [PATCH 11/17] fixed extra braces in string literal Signed-off-by: Jonah Grimes --- .../src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx index e8d1486f87..c9bf3a3c19 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx +++ b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx @@ -71,7 +71,7 @@ export function RelatedEntitiesCard({ } /> From e6348e2e9a91fc970de36a428870733a10685d53 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Tue, 4 May 2021 17:47:09 -0400 Subject: [PATCH 12/17] lower cased title when displaying unable to load error message Signed-off-by: Jonah Grimes --- .../src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx index c9bf3a3c19..feaa8c1355 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx +++ b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx @@ -71,7 +71,7 @@ export function RelatedEntitiesCard({ } /> From 0e8346d3d44f061ad25dd8d5900ace79a464ce95 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Thu, 6 May 2021 09:05:52 -0400 Subject: [PATCH 13/17] fixed failing tests due to change in implementation from getEntityByName to getEntities Signed-off-by: Jonah Grimes --- .../DependsOnComponentsCard.test.tsx | 20 +++++++++++-------- .../DependsOnResourcesCard.test.tsx | 20 +++++++++++-------- .../HasResourcesCard.test.tsx | 20 +++++++++++-------- .../RelatedEntitiesCard.tsx | 2 +- 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx index 0a1e120eff..8ea7638c8e 100644 --- a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx +++ b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx @@ -91,14 +91,18 @@ describe('', () => { }, ], }; - catalogApi.getEntityByName.mockResolvedValue({ - apiVersion: 'v1', - kind: 'Component', - metadata: { - namespace: 'my-namespace', - name: 'target-name', - }, - spec: {}, + catalogApi.getEntities.mockResolvedValue({ + items: [ + { + apiVersion: 'v1', + kind: 'Component', + metadata: { + namespace: 'my-namespace', + name: 'target-name', + }, + spec: {}, + }, + ], }); const { getByText } = await renderInTestApp( diff --git a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx index 52ccfe7862..8f425ba6aa 100644 --- a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx +++ b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx @@ -91,14 +91,18 @@ describe('', () => { }, ], }; - catalogApi.getEntityByName.mockResolvedValue({ - apiVersion: 'v1', - kind: 'Resource', - metadata: { - namespace: 'my-namespace', - name: 'target-name', - }, - spec: {}, + catalogApi.getEntities.mockResolvedValue({ + items: [ + { + apiVersion: 'v1', + kind: 'Resource', + metadata: { + namespace: 'my-namespace', + name: 'target-name', + }, + spec: {}, + }, + ], }); const { getByText } = await renderInTestApp( diff --git a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx index fb683b6963..38c8a3b5f5 100644 --- a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx +++ b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx @@ -91,14 +91,18 @@ describe('', () => { }, ], }; - catalogApi.getEntityByName.mockResolvedValue({ - apiVersion: 'v1', - kind: 'Resource', - metadata: { - name: 'target-name', - namespace: 'my-namespace', - }, - spec: {}, + catalogApi.getEntities.mockResolvedValue({ + items: [ + { + apiVersion: 'v1', + kind: 'Resource', + metadata: { + name: 'target-name', + namespace: 'my-namespace', + }, + spec: {}, + }, + ], }); const { getByText } = await renderInTestApp( diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx index feaa8c1355..c9bf3a3c19 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx +++ b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx @@ -71,7 +71,7 @@ export function RelatedEntitiesCard({ } /> From f1cca64bed686ffc766770890ef6d2f1db207c01 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Tue, 11 May 2021 09:49:05 -0400 Subject: [PATCH 14/17] migrated from WarningPanel to ResponseErrorPanel to display issues with fetching related entities Signed-off-by: Jonah Grimes --- .../RelatedEntitiesCard/RelatedEntitiesCard.tsx | 13 ++++--------- .../src/components/RelatedEntitiesCard/presets.ts | 15 +++++++++------ 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx index c9bf3a3c19..a01b7c8c8b 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx +++ b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx @@ -16,12 +16,11 @@ import { Entity } from '@backstage/catalog-model'; import { - CodeSnippet, InfoCard, Link, Progress, + ResponseErrorPanel, TableColumn, - WarningPanel, } from '@backstage/core'; import { Typography } from '@material-ui/core'; import { @@ -39,7 +38,7 @@ type Props = { relationType: string; emptyMessage: string; emptyHelpLink: string; - asRenderableEntities: (entities: Entity[]) => T[]; + asRenderableEntities: (entities: Entity[] | undefined) => T[]; }; export function RelatedEntitiesCard({ @@ -66,14 +65,10 @@ export function RelatedEntitiesCard({ ); } - if (error || !entities) { + if (error) { return ( - } - /> + ); } diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts b/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts index 9d3586a7e9..90a916e902 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts +++ b/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts @@ -31,8 +31,9 @@ export const componentEntityColumns: TableColumn[] = [ ]; export const componentEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-component'; -export const asComponentEntities = (entities: Entity[]): ComponentEntity[] => - entities as ComponentEntity[]; +export const asComponentEntities = ( + entities: Entity[] | undefined, +): ComponentEntity[] => entities as ComponentEntity[]; export const resourceEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'resource' }), @@ -43,8 +44,9 @@ export const resourceEntityColumns: TableColumn[] = [ ]; export const resourceEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-resource'; -export const asResourceEntities = (entities: Entity[]): ResourceEntity[] => - entities as ResourceEntity[]; +export const asResourceEntities = ( + entities: Entity[] | undefined, +): ResourceEntity[] => entities as ResourceEntity[]; export const systemEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'system' }), @@ -53,5 +55,6 @@ export const systemEntityColumns: TableColumn[] = [ ]; export const systemEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-system'; -export const asSystemEntities = (entities: Entity[]): SystemEntity[] => - entities as SystemEntity[]; +export const asSystemEntities = ( + entities: Entity[] | undefined, +): SystemEntity[] => entities as SystemEntity[]; From 44220f26a75fd80b131a7769322cafe9a6952624 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Tue, 11 May 2021 17:25:53 -0400 Subject: [PATCH 15/17] added handling of undefined to return an empty array Signed-off-by: Jonah Grimes --- .../RelatedEntitiesCard/RelatedEntitiesCard.tsx | 2 +- .../src/components/RelatedEntitiesCard/presets.ts | 15 ++++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx index a01b7c8c8b..9b3c6fb431 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx +++ b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx @@ -38,7 +38,7 @@ type Props = { relationType: string; emptyMessage: string; emptyHelpLink: string; - asRenderableEntities: (entities: Entity[] | undefined) => T[]; + asRenderableEntities: (entities?: Entity[]) => T[]; }; export function RelatedEntitiesCard({ diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts b/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts index 90a916e902..0d7c7f59f6 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts +++ b/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts @@ -31,9 +31,8 @@ export const componentEntityColumns: TableColumn[] = [ ]; export const componentEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-component'; -export const asComponentEntities = ( - entities: Entity[] | undefined, -): ComponentEntity[] => entities as ComponentEntity[]; +export const asComponentEntities = (entities?: Entity[]): ComponentEntity[] => + (entities as ComponentEntity[]) || new Array(); export const resourceEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'resource' }), @@ -44,9 +43,8 @@ export const resourceEntityColumns: TableColumn[] = [ ]; export const resourceEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-resource'; -export const asResourceEntities = ( - entities: Entity[] | undefined, -): ResourceEntity[] => entities as ResourceEntity[]; +export const asResourceEntities = (entities?: Entity[]): ResourceEntity[] => + (entities as ResourceEntity[]) || new Array(); export const systemEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'system' }), @@ -55,6 +53,5 @@ export const systemEntityColumns: TableColumn[] = [ ]; export const systemEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-system'; -export const asSystemEntities = ( - entities: Entity[] | undefined, -): SystemEntity[] => entities as SystemEntity[]; +export const asSystemEntities = (entities?: Entity[]): SystemEntity[] => + (entities as SystemEntity[]) || new Array(); From 39a4ba1cf75e1a392952e399cdcd37e1d2017c8f Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Wed, 12 May 2021 08:41:37 -0400 Subject: [PATCH 16/17] simplified array of resources as [] when handling undefined Signed-off-by: Jonah Grimes --- .../catalog/src/components/RelatedEntitiesCard/presets.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts b/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts index 0d7c7f59f6..e469fcb717 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts +++ b/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts @@ -32,7 +32,7 @@ export const componentEntityColumns: TableColumn[] = [ export const componentEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-component'; export const asComponentEntities = (entities?: Entity[]): ComponentEntity[] => - (entities as ComponentEntity[]) || new Array(); + (entities as ComponentEntity[]) || []; export const resourceEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'resource' }), @@ -44,7 +44,7 @@ export const resourceEntityColumns: TableColumn[] = [ export const resourceEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-resource'; export const asResourceEntities = (entities?: Entity[]): ResourceEntity[] => - (entities as ResourceEntity[]) || new Array(); + (entities as ResourceEntity[]) || []; export const systemEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'system' }), @@ -54,4 +54,4 @@ export const systemEntityColumns: TableColumn[] = [ export const systemEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-system'; export const asSystemEntities = (entities?: Entity[]): SystemEntity[] => - (entities as SystemEntity[]) || new Array(); + (entities as SystemEntity[]) || []; From 70057c1ae0d891ec3a4721a1a14abae12a36fb41 Mon Sep 17 00:00:00 2001 From: Jonah Grimes Date: Thu, 13 May 2021 09:18:51 -0400 Subject: [PATCH 17/17] moved 'undefined' handling to the RelatedEntitiesCard where it belongs Signed-off-by: Jonah Grimes --- .../RelatedEntitiesCard/RelatedEntitiesCard.tsx | 4 ++-- .../src/components/RelatedEntitiesCard/presets.ts | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx index 9b3c6fb431..f80f138515 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx +++ b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx @@ -38,7 +38,7 @@ type Props = { relationType: string; emptyMessage: string; emptyHelpLink: string; - asRenderableEntities: (entities?: Entity[]) => T[]; + asRenderableEntities: (entities: Entity[]) => T[]; }; export function RelatedEntitiesCard({ @@ -86,7 +86,7 @@ export function RelatedEntitiesCard({ } columns={columns} - entities={asRenderableEntities(entities)} + entities={asRenderableEntities(entities || [])} /> ); } diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts b/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts index e469fcb717..9d3586a7e9 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts +++ b/plugins/catalog/src/components/RelatedEntitiesCard/presets.ts @@ -31,8 +31,8 @@ export const componentEntityColumns: TableColumn[] = [ ]; export const componentEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-component'; -export const asComponentEntities = (entities?: Entity[]): ComponentEntity[] => - (entities as ComponentEntity[]) || []; +export const asComponentEntities = (entities: Entity[]): ComponentEntity[] => + entities as ComponentEntity[]; export const resourceEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'resource' }), @@ -43,8 +43,8 @@ export const resourceEntityColumns: TableColumn[] = [ ]; export const resourceEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-resource'; -export const asResourceEntities = (entities?: Entity[]): ResourceEntity[] => - (entities as ResourceEntity[]) || []; +export const asResourceEntities = (entities: Entity[]): ResourceEntity[] => + entities as ResourceEntity[]; export const systemEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'system' }), @@ -53,5 +53,5 @@ export const systemEntityColumns: TableColumn[] = [ ]; export const systemEntityHelpLink: string = 'https://backstage.io/docs/features/software-catalog/descriptor-format#kind-system'; -export const asSystemEntities = (entities?: Entity[]): SystemEntity[] => - (entities as SystemEntity[]) || []; +export const asSystemEntities = (entities: Entity[]): SystemEntity[] => + entities as SystemEntity[];