From aa8db01acb2645fe89b5bd9ec248a603b08c510c Mon Sep 17 00:00:00 2001 From: David Weber Date: Wed, 20 Apr 2022 23:14:31 +0200 Subject: [PATCH] feat: add new component `EntityTechInsightsScorecardCard` The `EntityTechInsightsScorecardCard` can be used in the overview of the `EntityPage` page or display multiple individual `EntityTechInsightsScorecardCard` in `EntityLayout.Route`. Signed-off-by: David Weber --- .changeset/cool-mice-sit.md | 5 ++ plugins/tech-insights/README.md | 41 ++++++++++-- plugins/tech-insights/api-report.md | 11 +++ .../ScorecardsCard.tsx} | 6 +- .../index.ts | 2 +- .../ScorecardsContent/ScorecardContent.tsx | 67 +++++++++++++++++++ .../src/components/ScorecardsContent/index.ts | 17 +++++ .../ScorecardInfo.tsx} | 55 +++++++++------ .../src/components/ScorecardsInfo/index.ts | 17 +++++ plugins/tech-insights/src/index.ts | 1 + plugins/tech-insights/src/plugin.ts | 14 +++- 11 files changed, 205 insertions(+), 31 deletions(-) create mode 100644 .changeset/cool-mice-sit.md rename plugins/tech-insights/src/components/{ScorecardsOverview/ScorecardsOverview.tsx => ScorecardsCard/ScorecardsCard.tsx} (93%) rename plugins/tech-insights/src/components/{ScorecardsOverview => ScorecardsCard}/index.ts (91%) create mode 100644 plugins/tech-insights/src/components/ScorecardsContent/ScorecardContent.tsx create mode 100644 plugins/tech-insights/src/components/ScorecardsContent/index.ts rename plugins/tech-insights/src/components/{ScorecardsOverview/ChecksOverview.tsx => ScorecardsInfo/ScorecardInfo.tsx} (64%) create mode 100644 plugins/tech-insights/src/components/ScorecardsInfo/index.ts diff --git a/.changeset/cool-mice-sit.md b/.changeset/cool-mice-sit.md new file mode 100644 index 0000000000..321b5fcf0b --- /dev/null +++ b/.changeset/cool-mice-sit.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-insights': patch +--- + +Add new component `EntityTechInsightsScorecardCard`, which can be used in the overview of the `EntityPage` page or display multiple individual `EntityTechInsightsScorecardCard` in `EntityLayout.Route`. diff --git a/plugins/tech-insights/README.md b/plugins/tech-insights/README.md index a305ef5dc7..6c13622e1f 100644 --- a/plugins/tech-insights/README.md +++ b/plugins/tech-insights/README.md @@ -38,10 +38,6 @@ const serviceEntityPage = ( title="Customized title for the scorecard" description="Small description about scorecards" /> - ... @@ -50,8 +46,45 @@ const serviceEntityPage = ( It is not obligatory to pass title and description props to `EntityTechInsightsScorecardContent`. If those are left out, default values from `defaultCheckResultRenderers` in `CheckResultRenderer` will be taken, hence `Boolean scorecard` and `This card represents an overview of default boolean Backstage checks`. +If you like to display multiple cards in a `EntityLayout.Route` use `EntityTechInsightsScorecardCard`. + You can pass an array `checksId` as a prop with the [Fact Retrievers ids](../tech-insights-backend#creating-fact-retrievers) to limit which checks you want to show in this card, If you don't pass, the default value is show all checks. +```tsx + +``` + +If you want to show checks in the overview of an entity use `EntityTechInsightsScorecardCard`. + +```tsx +// packages/app/src/components/catalog/EntityPage.tsx + +import { EntityTechInsightsScorecardCard } from '@backstage/plugin-tech-insights'; + +const overviewContent = ( + + {entityWarningContent} + + + + + + + ... + + + + +); +``` + ## Boolean Scorecard Example If you follow the [Backend Example](https://github.com/backstage/backstage/tree/master/plugins/tech-insights-backend#backend-example), once the needed facts have been generated the boolean scorecard will look like this: diff --git a/plugins/tech-insights/api-report.md b/plugins/tech-insights/api-report.md index 9574efca28..3e099493b6 100644 --- a/plugins/tech-insights/api-report.md +++ b/plugins/tech-insights/api-report.md @@ -30,6 +30,17 @@ export type CheckResultRenderer = { component: React_2.ReactElement; }; +// @public (undocumented) +export const EntityTechInsightsScorecardCard: ({ + title, + description, + checksId, +}: { + title?: string | undefined; + description?: string | undefined; + checksId?: string[] | undefined; +}) => JSX.Element; + // @public (undocumented) export const EntityTechInsightsScorecardContent: ({ title, diff --git a/plugins/tech-insights/src/components/ScorecardsOverview/ScorecardsOverview.tsx b/plugins/tech-insights/src/components/ScorecardsCard/ScorecardsCard.tsx similarity index 93% rename from plugins/tech-insights/src/components/ScorecardsOverview/ScorecardsOverview.tsx rename to plugins/tech-insights/src/components/ScorecardsCard/ScorecardsCard.tsx index 53cf826e78..f6bc4b0cb5 100644 --- a/plugins/tech-insights/src/components/ScorecardsOverview/ScorecardsOverview.tsx +++ b/plugins/tech-insights/src/components/ScorecardsCard/ScorecardsCard.tsx @@ -19,11 +19,11 @@ import { useParams } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; import { Progress } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; -import { ChecksOverview } from './ChecksOverview'; +import { ScorecardInfo } from '../ScorecardsInfo'; import Alert from '@material-ui/lab/Alert'; import { techInsightsApiRef } from '../../api/TechInsightsApi'; -export const ScorecardsOverview = ({ +export const ScorecardsCard = ({ title, description, checksId, @@ -45,7 +45,7 @@ export const ScorecardsOverview = ({ } return ( - ({ + contentScorecards: { + paddingLeft: 0, + paddingRight: 0, + }, +})); + +export const ScorecardsContent = ({ + title, + description, + checksId, +}: { + title?: string; + description?: string; + checksId?: string[]; +}) => { + const classes = useStyles(); + const api = useApi(techInsightsApiRef); + const { namespace, kind, name } = useParams(); + const { value, loading, error } = useAsync( + async () => await api.runChecks({ namespace, kind, name }, checksId), + ); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + return ( + + + + + + ); +}; diff --git a/plugins/tech-insights/src/components/ScorecardsContent/index.ts b/plugins/tech-insights/src/components/ScorecardsContent/index.ts new file mode 100644 index 0000000000..fcdfb0b694 --- /dev/null +++ b/plugins/tech-insights/src/components/ScorecardsContent/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { ScorecardsContent } from './ScorecardContent'; diff --git a/plugins/tech-insights/src/components/ScorecardsOverview/ChecksOverview.tsx b/plugins/tech-insights/src/components/ScorecardsInfo/ScorecardInfo.tsx similarity index 64% rename from plugins/tech-insights/src/components/ScorecardsOverview/ChecksOverview.tsx rename to plugins/tech-insights/src/components/ScorecardsInfo/ScorecardInfo.tsx index d153c690eb..2c5abb3596 100644 --- a/plugins/tech-insights/src/components/ScorecardsOverview/ChecksOverview.tsx +++ b/plugins/tech-insights/src/components/ScorecardsInfo/ScorecardInfo.tsx @@ -17,17 +17,13 @@ import React from 'react'; import { makeStyles, Grid, Typography } from '@material-ui/core'; import { useApi } from '@backstage/core-plugin-api'; -import { Content, Page, InfoCard } from '@backstage/core-components'; +import { InfoCard } from '@backstage/core-components'; import { CheckResult } from '@backstage/plugin-tech-insights-common'; import { techInsightsApiRef } from '../../api/TechInsightsApi'; import { BackstageTheme } from '@backstage/theme'; import { Alert } from '@material-ui/lab'; const useStyles = makeStyles((theme: BackstageTheme) => ({ - contentScorecards: { - paddingLeft: 0, - paddingRight: 0, - }, subheader: { fontWeight: 'bold', paddingLeft: theme.spacing(0.5), @@ -40,12 +36,37 @@ type Checks = { description?: string; }; -export const ChecksOverview = ({ checks, title, description }: Checks) => { +const infoCard = ( + title: Checks['title'], + description: Checks['description'], + className: string, + element: JSX.Element, +) => ( + + + + {description} + + + {element} + + + +); + +export const ScorecardInfo = ({ checks, title, description }: Checks) => { const classes = useStyles(); const api = useApi(techInsightsApiRef); + if (!checks.length) { - return No checks have any data yet.; + return infoCard( + title, + description, + classes.subheader, + No checks have any data yet., + ); } + const checkRenderType = api.getScorecardsDefinition( checks[0].check.type, checks, @@ -54,21 +75,11 @@ export const ChecksOverview = ({ checks, title, description }: Checks) => { ); if (checkRenderType) { - return ( - - - - - - {checkRenderType.description} - - - {checkRenderType.component} - - - - - + return infoCard( + checkRenderType.title, + checkRenderType.description, + classes.subheader, + checkRenderType.component, ); } diff --git a/plugins/tech-insights/src/components/ScorecardsInfo/index.ts b/plugins/tech-insights/src/components/ScorecardsInfo/index.ts new file mode 100644 index 0000000000..21928465e0 --- /dev/null +++ b/plugins/tech-insights/src/components/ScorecardsInfo/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { ScorecardInfo } from './ScorecardInfo'; diff --git a/plugins/tech-insights/src/index.ts b/plugins/tech-insights/src/index.ts index b59ac453ce..bc7c2ce26c 100644 --- a/plugins/tech-insights/src/index.ts +++ b/plugins/tech-insights/src/index.ts @@ -16,6 +16,7 @@ export { techInsightsPlugin, EntityTechInsightsScorecardContent, + EntityTechInsightsScorecardCard, } from './plugin'; export { techInsightsApiRef } from './api/TechInsightsApi'; diff --git a/plugins/tech-insights/src/plugin.ts b/plugins/tech-insights/src/plugin.ts index 0c2da63670..961519cd97 100644 --- a/plugins/tech-insights/src/plugin.ts +++ b/plugins/tech-insights/src/plugin.ts @@ -49,7 +49,19 @@ export const EntityTechInsightsScorecardContent = techInsightsPlugin.provide( createRoutableExtension({ name: 'EntityTechInsightsScorecardContent', component: () => - import('./components/ScorecardsOverview').then(m => m.ScorecardsOverview), + import('./components/ScorecardsContent').then(m => m.ScorecardsContent), + mountPoint: rootRouteRef, + }), +); + +/** + * @public + */ +export const EntityTechInsightsScorecardCard = techInsightsPlugin.provide( + createRoutableExtension({ + name: 'EntityTechInsightsScorecardCard', + component: () => + import('./components/ScorecardsCard').then(m => m.ScorecardsCard), mountPoint: rootRouteRef, }), );