@red-hat-developer-hub/backstage-plugin-scorecard 2.6.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +3 -1
- package/dist/alpha/extensions/homePageCards.esm.js +18 -1
- package/dist/alpha/extensions/homePageCards.esm.js.map +1 -1
- package/dist/alpha.d.ts +1 -1
- package/dist/alpha.esm.js +3 -2
- package/dist/alpha.esm.js.map +1 -1
- package/dist/api/index.esm.js +45 -1
- package/dist/api/index.esm.js.map +1 -1
- package/dist/components/AggregatedMetricCards/AggregatedMetricCard.esm.js +32 -0
- package/dist/components/AggregatedMetricCards/AggregatedMetricCard.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/AverageCard/AverageCardComponent.esm.js +170 -0
- package/dist/components/AggregatedMetricCards/AverageCard/AverageCardComponent.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/AverageCard/AverageCardPieCenterLabel.esm.js +58 -0
- package/dist/components/AggregatedMetricCards/AverageCard/AverageCardPieCenterLabel.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/AverageCard/DonutChartTooltipContent.esm.js +30 -0
- package/dist/components/AggregatedMetricCards/AverageCard/DonutChartTooltipContent.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/AverageCard/LegendTooltipContent.esm.js +39 -0
- package/dist/components/AggregatedMetricCards/AverageCard/LegendTooltipContent.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/AverageCard/TooltipContent.esm.js +36 -0
- package/dist/components/AggregatedMetricCards/AverageCard/TooltipContent.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/StatusGroupedCard/StatusGroupedCardComponent.esm.js +102 -0
- package/dist/components/AggregatedMetricCards/StatusGroupedCard/StatusGroupedCardComponent.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/UnsupportedAggregationType.esm.js +29 -0
- package/dist/components/AggregatedMetricCards/UnsupportedAggregationType.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/components/CardChartContainer.esm.js +31 -0
- package/dist/components/AggregatedMetricCards/components/CardChartContainer.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/components/CardInfoButton.esm.js +46 -0
- package/dist/components/AggregatedMetricCards/components/CardInfoButton.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/components/CardLegendContent.esm.js +24 -0
- package/dist/components/AggregatedMetricCards/components/CardLegendContent.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/components/CardPieTooltipContent.esm.js +16 -0
- package/dist/components/AggregatedMetricCards/components/CardPieTooltipContent.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/components/CardSubheader.esm.js +47 -0
- package/dist/components/AggregatedMetricCards/components/CardSubheader.esm.js.map +1 -0
- package/dist/components/AggregatedMetricCards/components/CardTooltip.esm.js +36 -0
- package/dist/components/AggregatedMetricCards/components/CardTooltip.esm.js.map +1 -0
- package/dist/components/Common/CardLoading.esm.js +3 -1
- package/dist/components/Common/CardLoading.esm.js.map +1 -1
- package/dist/components/ScorecardHomepageSection/CustomLegend.esm.js +10 -15
- package/dist/components/ScorecardHomepageSection/CustomLegend.esm.js.map +1 -1
- package/dist/components/ScorecardHomepageSection/CustomTooltip.esm.js +7 -2
- package/dist/components/ScorecardHomepageSection/CustomTooltip.esm.js.map +1 -1
- package/dist/components/ScorecardHomepageSection/ResponsivePieChart.esm.js +3 -2
- package/dist/components/ScorecardHomepageSection/ResponsivePieChart.esm.js.map +1 -1
- package/dist/components/ScorecardHomepageSection/ScorecardHomepageCard.esm.js +14 -3
- package/dist/components/ScorecardHomepageSection/ScorecardHomepageCard.esm.js.map +1 -1
- package/dist/components/ScorecardPage/EntitiesTable/EntitiesTable.esm.js +72 -64
- package/dist/components/ScorecardPage/EntitiesTable/EntitiesTable.esm.js.map +1 -1
- package/dist/components/ScorecardPage/EntitiesTable/EntitiesTableWrapper.esm.js +2 -2
- package/dist/components/ScorecardPage/EntitiesTable/EntitiesTableWrapper.esm.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/translations/de.esm.js +11 -2
- package/dist/translations/de.esm.js.map +1 -1
- package/dist/translations/es.esm.js +11 -2
- package/dist/translations/es.esm.js.map +1 -1
- package/dist/translations/fr.esm.js +11 -2
- package/dist/translations/fr.esm.js.map +1 -1
- package/dist/translations/it.esm.js +11 -2
- package/dist/translations/it.esm.js.map +1 -1
- package/dist/translations/ja.esm.js +11 -2
- package/dist/translations/ja.esm.js.map +1 -1
- package/dist/translations/ref.esm.js +15 -4
- package/dist/translations/ref.esm.js.map +1 -1
- package/dist/types/{index.d-WA6f0Uad.d.ts → index.d-pCF5Ectg.d.ts} +10 -2
- package/dist/utils/formatPercentage.esm.js +6 -0
- package/dist/utils/formatPercentage.esm.js.map +1 -0
- package/package.json +2 -2
- package/dist/components/ScorecardHomepageSection/ScorecardHomepageCardComponent.esm.js +0 -172
- package/dist/components/ScorecardHomepageSection/ScorecardHomepageCardComponent.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @red-hat-developer-hub/backstage-plugin-scorecard
|
|
2
2
|
|
|
3
|
+
## 2.7.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 91e724f: Expose scorecard entity calculation health on drill-down and aggregation APIs, and align the drill-down warning plus homepage subheader with those counts.
|
|
8
|
+
- Updated dependencies [91e724f]
|
|
9
|
+
- @red-hat-developer-hub/backstage-plugin-scorecard-common@2.7.1
|
|
10
|
+
|
|
11
|
+
## 2.7.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- bf72ffc: Adds `**average**` as an aggregation KPI type alongside `**statusGrouped**`, with configurable `**options.statusScores**` and optional `**options.thresholds**` (same shape as metric thresholds) for homepage donut coloring against `**averageScore × 100**`, with built-in defaults when omitted.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [bf72ffc]
|
|
20
|
+
- @red-hat-developer-hub/backstage-plugin-scorecard-common@2.7.0
|
|
21
|
+
|
|
3
22
|
## 2.6.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ The plugin supports both the **legacy** Backstage frontend and the **New Fronten
|
|
|
6
6
|
**Features:**
|
|
7
7
|
|
|
8
8
|
- **Entity scorecard tab** — View scorecard metrics on catalog entity pages (components, websites, etc.).
|
|
9
|
-
- **Scorecard homepage card** — Show aggregated KPIs on the home page (e.g. GitHub open PRs, Jira open issues).
|
|
9
|
+
- **Scorecard homepage card** — Show aggregated KPIs on the home page (e.g. GitHub open PRs, Jira open issues). Supports **`statusGrouped`** (multi-slice pie) and **`average`** (weighted health donut) KPI types configured under **`scorecard.aggregationKPIs`**.
|
|
10
10
|
- **Scorecard Entities page** — Drill down from an aggregated metric to see the list of entities contributing to that metric, with entity-level values and status, so you can identify services impacting the KPI and investigate issues.
|
|
11
11
|
|
|
12
12
|
## Getting started
|
|
@@ -310,6 +310,8 @@ The plugin exports **`ScorecardHomepageCard`** (see [`plugin.ts`](./src/plugin.t
|
|
|
310
310
|
|
|
311
311
|
Define KPI ids and optional labels under **`scorecard.aggregationKPIs`** so each card can call **`GET /aggregations/<aggregationId>`** with a stable id. See [Scorecard backend README — Aggregation KPIs](../scorecard-backend/README.md#aggregation-kpis-homepage-and-get-aggregations). If you omit a KPI entry, use the **metric id** as `aggregationId` (default status-grouped aggregation).
|
|
312
312
|
|
|
313
|
+
**`type: average`** KPIs require **`options.statusScores`** (weights per threshold rule key). Optionally set **`options.thresholds`** so the API returns **`aggregationChartDisplayColor`** for the headline percentage. Behavior, validation, and drill-down notes are described in [aggregation.md](../scorecard-backend/docs/aggregation.md).
|
|
314
|
+
|
|
313
315
|
#### Card props
|
|
314
316
|
|
|
315
317
|
The supported model is **a single `aggregationId` string** whose value is either:
|
|
@@ -32,6 +32,9 @@ function AggregatedCardWithGithubFilecheckLicenseContent() {
|
|
|
32
32
|
function AggregatedCardWithGithubFilecheckCodeownersContent() {
|
|
33
33
|
return /* @__PURE__ */ jsx(ScorecardHomepageCardWithProvider, { aggregationId: "filecheck.codeowners" });
|
|
34
34
|
}
|
|
35
|
+
function AggregatedCardWithGithubOpenPrsWeightedContent() {
|
|
36
|
+
return /* @__PURE__ */ jsx(ScorecardHomepageCardWithProvider, { aggregationId: "openPrsWeightedKpi" });
|
|
37
|
+
}
|
|
35
38
|
function BorderlessHomeWidgetRenderer({ Content }) {
|
|
36
39
|
return /* @__PURE__ */ jsx(Content, {});
|
|
37
40
|
}
|
|
@@ -119,6 +122,20 @@ const aggregatedCardWithGithubFilecheckCodeownersWidget = HomePageWidgetBlueprin
|
|
|
119
122
|
})
|
|
120
123
|
}
|
|
121
124
|
});
|
|
125
|
+
const aggregatedCardWithGithubOpenPrsWeightedWidget = HomePageWidgetBlueprint.make({
|
|
126
|
+
name: "scorecard-github-open-prs-weighted",
|
|
127
|
+
params: {
|
|
128
|
+
name: "AggregatedCardWithGithubOpenPrsWeighted",
|
|
129
|
+
title: "Scorecard: GitHub open PRs (weighted health)",
|
|
130
|
+
layout: defaultCardLayout,
|
|
131
|
+
componentProps: {
|
|
132
|
+
Renderer: BorderlessHomeWidgetRenderer
|
|
133
|
+
},
|
|
134
|
+
components: () => Promise.resolve({
|
|
135
|
+
Content: AggregatedCardWithGithubOpenPrsWeightedContent
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
});
|
|
122
139
|
|
|
123
|
-
export { aggregatedCardWithDefaultAggregationWidget, aggregatedCardWithDeprecatedMetricIdWidget, aggregatedCardWithGithubFilecheckCodeownersWidget, aggregatedCardWithGithubFilecheckLicenseWidget, aggregatedCardWithGithubOpenPrsWidget, aggregatedCardWithJiraOpenIssuesWidget };
|
|
140
|
+
export { aggregatedCardWithDefaultAggregationWidget, aggregatedCardWithDeprecatedMetricIdWidget, aggregatedCardWithGithubFilecheckCodeownersWidget, aggregatedCardWithGithubFilecheckLicenseWidget, aggregatedCardWithGithubOpenPrsWeightedWidget, aggregatedCardWithGithubOpenPrsWidget, aggregatedCardWithJiraOpenIssuesWidget };
|
|
124
141
|
//# sourceMappingURL=homePageCards.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"homePageCards.esm.js","sources":["../../../src/alpha/extensions/homePageCards.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { HomePageWidgetBlueprint } from '@backstage/plugin-home-react/alpha';\nimport type { RendererProps } from '@backstage/plugin-home-react';\nimport { ScorecardHomepageCardWithProvider } from '../../components/ScorecardHomepageSection';\n\nconst defaultCardLayout = {\n width: {\n minColumns: 3,\n maxColumns: 12,\n defaultColumns: 4,\n },\n height: {\n minRows: 5,\n maxRows: 12,\n defaultRows: 6,\n },\n} as const;\n\nfunction AggregatedCardWithDeprecatedMetricIdContent() {\n return <ScorecardHomepageCardWithProvider metricId=\"jira.open_issues\" />;\n}\n\nfunction AggregatedCardWithDefaultAggregationContent() {\n return <ScorecardHomepageCardWithProvider aggregationId=\"github.open_prs\" />;\n}\n\nfunction AggregatedCardWithJiraOpenIssuesContent() {\n return <ScorecardHomepageCardWithProvider aggregationId=\"openIssuesKpi\" />;\n}\n\nfunction AggregatedCardWithGithubOpenPrsContent() {\n return <ScorecardHomepageCardWithProvider aggregationId=\"openPrsKpi\" />;\n}\n\nfunction AggregatedCardWithGithubFilecheckLicenseContent() {\n return (\n <ScorecardHomepageCardWithProvider aggregationId=\"licenseFileExistsKpi\" />\n );\n}\n\nfunction AggregatedCardWithGithubFilecheckCodeownersContent() {\n return (\n <ScorecardHomepageCardWithProvider aggregationId=\"filecheck.codeowners\" />\n );\n}\n\nfunction BorderlessHomeWidgetRenderer({ Content }: RendererProps) {\n return <Content />;\n}\n\n/**\n * NFS widget: AggregatedCardWithDeprecatedMetricId.\n * @alpha\n */\nexport const aggregatedCardWithDeprecatedMetricIdWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-deprecated-metric-id',\n params: {\n name: 'AggregatedCardWithDeprecatedMetricId',\n title: 'Scorecard: With deprecated metricId property (Jira)',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithDeprecatedMetricIdContent,\n }),\n },\n });\n\n/**\n * NFS widget: AggregatedCardWithDefaultAggregation.\n * @alpha\n */\nexport const aggregatedCardWithDefaultAggregationWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-default-aggregation',\n params: {\n name: 'AggregatedCardWithDefaultAggregation',\n title: 'Scorecard: With default aggregation config (GitHub)',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithDefaultAggregationContent,\n }),\n },\n });\n\n/**\n * NFS widget: AggregatedCardWithJiraOpenIssues.\n * @alpha\n */\nexport const aggregatedCardWithJiraOpenIssuesWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-jira-open-issues',\n params: {\n name: 'AggregatedCardWithJiraOpenIssues',\n title: 'Scorecard: Jira open blocking tickets',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithJiraOpenIssuesContent,\n }),\n },\n });\n\n/**\n * NFS widget: AggregatedCardWithGithubOpenPrs.\n * @alpha\n */\nexport const aggregatedCardWithGithubOpenPrsWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-github-open-prs',\n params: {\n name: 'AggregatedCardWithGithubOpenPrs',\n title: 'Scorecard: GitHub open PRs',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithGithubOpenPrsContent,\n }),\n },\n });\n\n/**\n * NFS widget: AggregatedCardWithGithubFilecheckLicense.\n * @alpha\n */\nexport const aggregatedCardWithGithubFilecheckLicenseWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-github-filecheck-license',\n params: {\n name: 'AggregatedCardWithGithubFilecheckLicense',\n title: 'Scorecard: LICENSE file exists',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithGithubFilecheckLicenseContent,\n }),\n },\n });\n\n/**\n * NFS widget: AggregatedCardWithGithubFilecheckCodeowners.\n * @alpha\n */\nexport const aggregatedCardWithGithubFilecheckCodeownersWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-github-filecheck-codeowners',\n params: {\n name: 'AggregatedCardWithGithubFilecheckCodeowners',\n title: 'Scorecard: CODEOWNERS file exists',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithGithubFilecheckCodeownersContent,\n }),\n },\n });\n"],"names":[],"mappings":";;;;AAoBA,MAAM,iBAAoB,GAAA;AAAA,EACxB,KAAO,EAAA;AAAA,IACL,UAAY,EAAA,CAAA;AAAA,IACZ,UAAY,EAAA,EAAA;AAAA,IACZ,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,OAAS,EAAA,CAAA;AAAA,IACT,OAAS,EAAA,EAAA;AAAA,IACT,WAAa,EAAA;AAAA;AAEjB,CAAA;AAEA,SAAS,2CAA8C,GAAA;AACrD,EAAO,uBAAA,GAAA,CAAC,iCAAkC,EAAA,EAAA,QAAA,EAAS,kBAAmB,EAAA,CAAA;AACxE;AAEA,SAAS,2CAA8C,GAAA;AACrD,EAAO,uBAAA,GAAA,CAAC,iCAAkC,EAAA,EAAA,aAAA,EAAc,iBAAkB,EAAA,CAAA;AAC5E;AAEA,SAAS,uCAA0C,GAAA;AACjD,EAAO,uBAAA,GAAA,CAAC,iCAAkC,EAAA,EAAA,aAAA,EAAc,eAAgB,EAAA,CAAA;AAC1E;AAEA,SAAS,sCAAyC,GAAA;AAChD,EAAO,uBAAA,GAAA,CAAC,iCAAkC,EAAA,EAAA,aAAA,EAAc,YAAa,EAAA,CAAA;AACvE;AAEA,SAAS,+CAAkD,GAAA;AACzD,EACE,uBAAA,GAAA,CAAC,iCAAkC,EAAA,EAAA,aAAA,EAAc,sBAAuB,EAAA,CAAA;AAE5E;AAEA,SAAS,kDAAqD,GAAA;AAC5D,EACE,uBAAA,GAAA,CAAC,iCAAkC,EAAA,EAAA,aAAA,EAAc,sBAAuB,EAAA,CAAA;AAE5E;AAEA,SAAS,4BAAA,CAA6B,EAAE,OAAA,EAA0B,EAAA;AAChE,EAAA,2BAAQ,OAAQ,EAAA,EAAA,CAAA;AAClB;AAMa,MAAA,0CAAA,GACX,wBAAwB,IAAK,CAAA;AAAA,EAC3B,IAAM,EAAA,gCAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,sCAAA;AAAA,IACN,KAAO,EAAA,qDAAA;AAAA,IACP,MAAQ,EAAA,iBAAA;AAAA,IACR,cAAgB,EAAA;AAAA,MACd,QAAU,EAAA;AAAA,KACZ;AAAA,IACA,UAAA,EAAY,MACV,OAAA,CAAQ,OAAQ,CAAA;AAAA,MACd,OAAS,EAAA;AAAA,KACV;AAAA;AAEP,CAAC;AAMU,MAAA,0CAAA,GACX,wBAAwB,IAAK,CAAA;AAAA,EAC3B,IAAM,EAAA,+BAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,sCAAA;AAAA,IACN,KAAO,EAAA,qDAAA;AAAA,IACP,MAAQ,EAAA,iBAAA;AAAA,IACR,cAAgB,EAAA;AAAA,MACd,QAAU,EAAA;AAAA,KACZ;AAAA,IACA,UAAA,EAAY,MACV,OAAA,CAAQ,OAAQ,CAAA;AAAA,MACd,OAAS,EAAA;AAAA,KACV;AAAA;AAEP,CAAC;AAMU,MAAA,sCAAA,GACX,wBAAwB,IAAK,CAAA;AAAA,EAC3B,IAAM,EAAA,4BAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,kCAAA;AAAA,IACN,KAAO,EAAA,uCAAA;AAAA,IACP,MAAQ,EAAA,iBAAA;AAAA,IACR,cAAgB,EAAA;AAAA,MACd,QAAU,EAAA;AAAA,KACZ;AAAA,IACA,UAAA,EAAY,MACV,OAAA,CAAQ,OAAQ,CAAA;AAAA,MACd,OAAS,EAAA;AAAA,KACV;AAAA;AAEP,CAAC;AAMU,MAAA,qCAAA,GACX,wBAAwB,IAAK,CAAA;AAAA,EAC3B,IAAM,EAAA,2BAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,iCAAA;AAAA,IACN,KAAO,EAAA,4BAAA;AAAA,IACP,MAAQ,EAAA,iBAAA;AAAA,IACR,cAAgB,EAAA;AAAA,MACd,QAAU,EAAA;AAAA,KACZ;AAAA,IACA,UAAA,EAAY,MACV,OAAA,CAAQ,OAAQ,CAAA;AAAA,MACd,OAAS,EAAA;AAAA,KACV;AAAA;AAEP,CAAC;AAMU,MAAA,8CAAA,GACX,wBAAwB,IAAK,CAAA;AAAA,EAC3B,IAAM,EAAA,oCAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,0CAAA;AAAA,IACN,KAAO,EAAA,gCAAA;AAAA,IACP,MAAQ,EAAA,iBAAA;AAAA,IACR,cAAgB,EAAA;AAAA,MACd,QAAU,EAAA;AAAA,KACZ;AAAA,IACA,UAAA,EAAY,MACV,OAAA,CAAQ,OAAQ,CAAA;AAAA,MACd,OAAS,EAAA;AAAA,KACV;AAAA;AAEP,CAAC;AAMU,MAAA,iDAAA,GACX,wBAAwB,IAAK,CAAA;AAAA,EAC3B,IAAM,EAAA,uCAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,6CAAA;AAAA,IACN,KAAO,EAAA,mCAAA;AAAA,IACP,MAAQ,EAAA,iBAAA;AAAA,IACR,cAAgB,EAAA;AAAA,MACd,QAAU,EAAA;AAAA,KACZ;AAAA,IACA,UAAA,EAAY,MACV,OAAA,CAAQ,OAAQ,CAAA;AAAA,MACd,OAAS,EAAA;AAAA,KACV;AAAA;AAEP,CAAC;;;;"}
|
|
1
|
+
{"version":3,"file":"homePageCards.esm.js","sources":["../../../src/alpha/extensions/homePageCards.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { HomePageWidgetBlueprint } from '@backstage/plugin-home-react/alpha';\nimport type { RendererProps } from '@backstage/plugin-home-react';\nimport { ScorecardHomepageCardWithProvider } from '../../components/ScorecardHomepageSection';\n\nconst defaultCardLayout = {\n width: {\n minColumns: 3,\n maxColumns: 12,\n defaultColumns: 4,\n },\n height: {\n minRows: 5,\n maxRows: 12,\n defaultRows: 6,\n },\n} as const;\n\nfunction AggregatedCardWithDeprecatedMetricIdContent() {\n return <ScorecardHomepageCardWithProvider metricId=\"jira.open_issues\" />;\n}\n\nfunction AggregatedCardWithDefaultAggregationContent() {\n return <ScorecardHomepageCardWithProvider aggregationId=\"github.open_prs\" />;\n}\n\nfunction AggregatedCardWithJiraOpenIssuesContent() {\n return <ScorecardHomepageCardWithProvider aggregationId=\"openIssuesKpi\" />;\n}\n\nfunction AggregatedCardWithGithubOpenPrsContent() {\n return <ScorecardHomepageCardWithProvider aggregationId=\"openPrsKpi\" />;\n}\n\nfunction AggregatedCardWithGithubFilecheckLicenseContent() {\n return (\n <ScorecardHomepageCardWithProvider aggregationId=\"licenseFileExistsKpi\" />\n );\n}\n\nfunction AggregatedCardWithGithubFilecheckCodeownersContent() {\n return (\n <ScorecardHomepageCardWithProvider aggregationId=\"filecheck.codeowners\" />\n );\n}\n\nfunction AggregatedCardWithGithubOpenPrsWeightedContent() {\n return (\n <ScorecardHomepageCardWithProvider aggregationId=\"openPrsWeightedKpi\" />\n );\n}\n\nfunction BorderlessHomeWidgetRenderer({ Content }: RendererProps) {\n return <Content />;\n}\n\n/**\n * NFS widget: AggregatedCardWithDeprecatedMetricId.\n * @alpha\n */\nexport const aggregatedCardWithDeprecatedMetricIdWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-deprecated-metric-id',\n params: {\n name: 'AggregatedCardWithDeprecatedMetricId',\n title: 'Scorecard: With deprecated metricId property (Jira)',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithDeprecatedMetricIdContent,\n }),\n },\n });\n\n/**\n * NFS widget: AggregatedCardWithDefaultAggregation.\n * @alpha\n */\nexport const aggregatedCardWithDefaultAggregationWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-default-aggregation',\n params: {\n name: 'AggregatedCardWithDefaultAggregation',\n title: 'Scorecard: With default aggregation config (GitHub)',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithDefaultAggregationContent,\n }),\n },\n });\n\n/**\n * NFS widget: AggregatedCardWithJiraOpenIssues.\n * @alpha\n */\nexport const aggregatedCardWithJiraOpenIssuesWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-jira-open-issues',\n params: {\n name: 'AggregatedCardWithJiraOpenIssues',\n title: 'Scorecard: Jira open blocking tickets',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithJiraOpenIssuesContent,\n }),\n },\n });\n\n/**\n * NFS widget: AggregatedCardWithGithubOpenPrs.\n * @alpha\n */\nexport const aggregatedCardWithGithubOpenPrsWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-github-open-prs',\n params: {\n name: 'AggregatedCardWithGithubOpenPrs',\n title: 'Scorecard: GitHub open PRs',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithGithubOpenPrsContent,\n }),\n },\n });\n\n/**\n * NFS widget: AggregatedCardWithGithubFilecheckLicense.\n * @alpha\n */\nexport const aggregatedCardWithGithubFilecheckLicenseWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-github-filecheck-license',\n params: {\n name: 'AggregatedCardWithGithubFilecheckLicense',\n title: 'Scorecard: LICENSE file exists',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithGithubFilecheckLicenseContent,\n }),\n },\n });\n\n/**\n * NFS widget: AggregatedCardWithGithubFilecheckCodeowners.\n * @alpha\n */\nexport const aggregatedCardWithGithubFilecheckCodeownersWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-github-filecheck-codeowners',\n params: {\n name: 'AggregatedCardWithGithubFilecheckCodeowners',\n title: 'Scorecard: CODEOWNERS file exists',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithGithubFilecheckCodeownersContent,\n }),\n },\n });\n\n/**\n * NFS widget: AggregatedCardWithGithubOpenPrsWeighted.\n * @alpha\n */\nexport const aggregatedCardWithGithubOpenPrsWeightedWidget =\n HomePageWidgetBlueprint.make({\n name: 'scorecard-github-open-prs-weighted',\n params: {\n name: 'AggregatedCardWithGithubOpenPrsWeighted',\n title: 'Scorecard: GitHub open PRs (weighted health)',\n layout: defaultCardLayout,\n componentProps: {\n Renderer: BorderlessHomeWidgetRenderer,\n },\n components: () =>\n Promise.resolve({\n Content: AggregatedCardWithGithubOpenPrsWeightedContent,\n }),\n },\n });\n"],"names":[],"mappings":"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"}
|
package/dist/alpha.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
|
|
3
3
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
4
|
-
export { a as scorecardTranslationRef, s as scorecardTranslations } from './types/index.d-
|
|
4
|
+
export { a as scorecardTranslationRef, s as scorecardTranslations } from './types/index.d-pCF5Ectg.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* The primary Scorecard frontend plugin.
|
package/dist/alpha.esm.js
CHANGED
|
@@ -4,7 +4,7 @@ import { scorecardDrillDownRouteRef, rootRouteRef } from './routes.esm.js';
|
|
|
4
4
|
import { scorecardTranslations } from './translations/index.esm.js';
|
|
5
5
|
import { scorecardApi } from './alpha/extensions/api.esm.js';
|
|
6
6
|
import { scorecardEntityContent } from './alpha/extensions/entityTab.esm.js';
|
|
7
|
-
import { aggregatedCardWithDeprecatedMetricIdWidget, aggregatedCardWithDefaultAggregationWidget, aggregatedCardWithJiraOpenIssuesWidget, aggregatedCardWithGithubOpenPrsWidget, aggregatedCardWithGithubFilecheckLicenseWidget, aggregatedCardWithGithubFilecheckCodeownersWidget } from './alpha/extensions/homePageCards.esm.js';
|
|
7
|
+
import { aggregatedCardWithDeprecatedMetricIdWidget, aggregatedCardWithDefaultAggregationWidget, aggregatedCardWithJiraOpenIssuesWidget, aggregatedCardWithGithubOpenPrsWidget, aggregatedCardWithGithubFilecheckLicenseWidget, aggregatedCardWithGithubFilecheckCodeownersWidget, aggregatedCardWithGithubOpenPrsWeightedWidget } from './alpha/extensions/homePageCards.esm.js';
|
|
8
8
|
import { scorecardPage } from './alpha/extensions/scorecardPage.esm.js';
|
|
9
9
|
export { scorecardTranslationRef } from './translations/ref.esm.js';
|
|
10
10
|
|
|
@@ -37,7 +37,8 @@ const scorecardHomeModule = createFrontendModule({
|
|
|
37
37
|
aggregatedCardWithJiraOpenIssuesWidget,
|
|
38
38
|
aggregatedCardWithGithubOpenPrsWidget,
|
|
39
39
|
aggregatedCardWithGithubFilecheckLicenseWidget,
|
|
40
|
-
aggregatedCardWithGithubFilecheckCodeownersWidget
|
|
40
|
+
aggregatedCardWithGithubFilecheckCodeownersWidget,
|
|
41
|
+
aggregatedCardWithGithubOpenPrsWeightedWidget
|
|
41
42
|
]
|
|
42
43
|
});
|
|
43
44
|
|
package/dist/alpha.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha.esm.js","sources":["../src/alpha/index.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createFrontendModule,\n createFrontendPlugin,\n} from '@backstage/frontend-plugin-api';\nimport { TranslationBlueprint } from '@backstage/plugin-app-react';\nimport { rootRouteRef, scorecardDrillDownRouteRef } from '../routes';\nimport { scorecardTranslations } from '../translations';\nimport { scorecardApi } from './extensions/api';\nimport { scorecardEntityContent } from './extensions/entityTab';\nimport {\n aggregatedCardWithDeprecatedMetricIdWidget,\n aggregatedCardWithDefaultAggregationWidget,\n aggregatedCardWithGithubOpenPrsWidget,\n aggregatedCardWithJiraOpenIssuesWidget,\n aggregatedCardWithGithubFilecheckLicenseWidget,\n aggregatedCardWithGithubFilecheckCodeownersWidget,\n} from './extensions/homePageCards';\nimport { scorecardPage } from './extensions/scorecardPage';\n\n/**\n * Extension for Scorecard translations.\n */\nconst scorecardTranslation = TranslationBlueprint.make({\n params: {\n resource: scorecardTranslations,\n },\n});\n\n/**\n * The primary Scorecard frontend plugin.\n * @alpha\n */\nexport default createFrontendPlugin({\n pluginId: 'scorecard',\n extensions: [scorecardApi, scorecardPage],\n routes: {\n root: rootRouteRef,\n drillDown: scorecardDrillDownRouteRef,\n },\n});\n\n/**\n * Catalog module that automatically injects the Scorecard tab into the Catalog.\n * @alpha\n */\nexport const scorecardCatalogModule = createFrontendModule({\n pluginId: 'catalog',\n extensions: [scorecardEntityContent],\n});\n\n/**\n * App module that automatically registers Scorecard translations.\n * @alpha\n */\nexport const scorecardTranslationsModule = createFrontendModule({\n pluginId: 'app',\n extensions: [scorecardTranslation],\n});\n\n/**\n * Home module that contributes scorecard homepage widget and layout.\n * @alpha\n */\nexport const scorecardHomeModule = createFrontendModule({\n pluginId: 'home',\n extensions: [\n aggregatedCardWithDeprecatedMetricIdWidget,\n aggregatedCardWithDefaultAggregationWidget,\n aggregatedCardWithJiraOpenIssuesWidget,\n aggregatedCardWithGithubOpenPrsWidget,\n aggregatedCardWithGithubFilecheckLicenseWidget,\n aggregatedCardWithGithubFilecheckCodeownersWidget,\n ],\n});\n\n/**\n * Re-exporting translations for external usage.\n * @alpha\n */\nexport * from '../translations';\n"],"names":[],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"alpha.esm.js","sources":["../src/alpha/index.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createFrontendModule,\n createFrontendPlugin,\n} from '@backstage/frontend-plugin-api';\nimport { TranslationBlueprint } from '@backstage/plugin-app-react';\nimport { rootRouteRef, scorecardDrillDownRouteRef } from '../routes';\nimport { scorecardTranslations } from '../translations';\nimport { scorecardApi } from './extensions/api';\nimport { scorecardEntityContent } from './extensions/entityTab';\nimport {\n aggregatedCardWithDeprecatedMetricIdWidget,\n aggregatedCardWithDefaultAggregationWidget,\n aggregatedCardWithGithubOpenPrsWidget,\n aggregatedCardWithJiraOpenIssuesWidget,\n aggregatedCardWithGithubFilecheckLicenseWidget,\n aggregatedCardWithGithubFilecheckCodeownersWidget,\n aggregatedCardWithGithubOpenPrsWeightedWidget,\n} from './extensions/homePageCards';\nimport { scorecardPage } from './extensions/scorecardPage';\n\n/**\n * Extension for Scorecard translations.\n */\nconst scorecardTranslation = TranslationBlueprint.make({\n params: {\n resource: scorecardTranslations,\n },\n});\n\n/**\n * The primary Scorecard frontend plugin.\n * @alpha\n */\nexport default createFrontendPlugin({\n pluginId: 'scorecard',\n extensions: [scorecardApi, scorecardPage],\n routes: {\n root: rootRouteRef,\n drillDown: scorecardDrillDownRouteRef,\n },\n});\n\n/**\n * Catalog module that automatically injects the Scorecard tab into the Catalog.\n * @alpha\n */\nexport const scorecardCatalogModule = createFrontendModule({\n pluginId: 'catalog',\n extensions: [scorecardEntityContent],\n});\n\n/**\n * App module that automatically registers Scorecard translations.\n * @alpha\n */\nexport const scorecardTranslationsModule = createFrontendModule({\n pluginId: 'app',\n extensions: [scorecardTranslation],\n});\n\n/**\n * Home module that contributes scorecard homepage widget and layout.\n * @alpha\n */\nexport const scorecardHomeModule = createFrontendModule({\n pluginId: 'home',\n extensions: [\n aggregatedCardWithDeprecatedMetricIdWidget,\n aggregatedCardWithDefaultAggregationWidget,\n aggregatedCardWithJiraOpenIssuesWidget,\n aggregatedCardWithGithubOpenPrsWidget,\n aggregatedCardWithGithubFilecheckLicenseWidget,\n aggregatedCardWithGithubFilecheckCodeownersWidget,\n aggregatedCardWithGithubOpenPrsWeightedWidget,\n ],\n});\n\n/**\n * Re-exporting translations for external usage.\n * @alpha\n */\nexport * from '../translations';\n"],"names":[],"mappings":";;;;;;;;;;AAuCA,MAAM,oBAAA,GAAuB,qBAAqB,IAAK,CAAA;AAAA,EACrD,MAAQ,EAAA;AAAA,IACN,QAAU,EAAA;AAAA;AAEd,CAAC,CAAA;AAMD,YAAe,oBAAqB,CAAA;AAAA,EAClC,QAAU,EAAA,WAAA;AAAA,EACV,UAAA,EAAY,CAAC,YAAA,EAAc,aAAa,CAAA;AAAA,EACxC,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,YAAA;AAAA,IACN,SAAW,EAAA;AAAA;AAEf,CAAC,CAAA;AAMM,MAAM,yBAAyB,oBAAqB,CAAA;AAAA,EACzD,QAAU,EAAA,SAAA;AAAA,EACV,UAAA,EAAY,CAAC,sBAAsB;AACrC,CAAC;AAMM,MAAM,8BAA8B,oBAAqB,CAAA;AAAA,EAC9D,QAAU,EAAA,KAAA;AAAA,EACV,UAAA,EAAY,CAAC,oBAAoB;AACnC,CAAC;AAMM,MAAM,sBAAsB,oBAAqB,CAAA;AAAA,EACtD,QAAU,EAAA,MAAA;AAAA,EACV,UAAY,EAAA;AAAA,IACV,0CAAA;AAAA,IACA,0CAAA;AAAA,IACA,sCAAA;AAAA,IACA,qCAAA;AAAA,IACA,8CAAA;AAAA,IACA,iDAAA;AAAA,IACA;AAAA;AAEJ,CAAC;;;;"}
|
package/dist/api/index.esm.js
CHANGED
|
@@ -72,7 +72,51 @@ class ScorecardApiClient {
|
|
|
72
72
|
"Invalid response format from aggregated scorecard API"
|
|
73
73
|
);
|
|
74
74
|
}
|
|
75
|
-
|
|
75
|
+
const resultRaw = data.result;
|
|
76
|
+
if (resultRaw === null || typeof resultRaw !== "object" || Array.isArray(resultRaw)) {
|
|
77
|
+
throw new TypeError(
|
|
78
|
+
"Invalid response format from aggregated scorecard API: result must be a non-null object"
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
const requireFiniteNumber = (value, fieldName) => {
|
|
82
|
+
const n = Number(value ?? 0);
|
|
83
|
+
if (!Number.isFinite(n)) {
|
|
84
|
+
throw new TypeError(
|
|
85
|
+
`Invalid aggregated scorecard API response: ${fieldName} must be a finite number`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return n;
|
|
89
|
+
};
|
|
90
|
+
const resultRecord = resultRaw;
|
|
91
|
+
const timestampValue = resultRecord.timestamp;
|
|
92
|
+
let timestamp;
|
|
93
|
+
if (typeof timestampValue === "string") {
|
|
94
|
+
timestamp = timestampValue;
|
|
95
|
+
} else if (typeof timestampValue === "number" && Number.isFinite(timestampValue)) {
|
|
96
|
+
timestamp = String(timestampValue);
|
|
97
|
+
} else if (typeof timestampValue === "bigint") {
|
|
98
|
+
timestamp = timestampValue.toString();
|
|
99
|
+
} else if (timestampValue instanceof Date) {
|
|
100
|
+
timestamp = timestampValue.toISOString();
|
|
101
|
+
} else {
|
|
102
|
+
timestamp = "";
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
...data,
|
|
106
|
+
result: {
|
|
107
|
+
...resultRecord,
|
|
108
|
+
total: requireFiniteNumber(resultRecord.total, "total"),
|
|
109
|
+
entitiesConsidered: requireFiniteNumber(
|
|
110
|
+
resultRecord.entitiesConsidered,
|
|
111
|
+
"entitiesConsidered"
|
|
112
|
+
),
|
|
113
|
+
calculationErrorCount: requireFiniteNumber(
|
|
114
|
+
resultRecord.calculationErrorCount,
|
|
115
|
+
"calculationErrorCount"
|
|
116
|
+
),
|
|
117
|
+
timestamp
|
|
118
|
+
}
|
|
119
|
+
};
|
|
76
120
|
} catch (error) {
|
|
77
121
|
if (error instanceof Error) {
|
|
78
122
|
throw error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../../src/api/index.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createApiRef,\n FetchApi,\n DiscoveryApi,\n} from '@backstage/core-plugin-api';\nimport type {\n MetricResult,\n AggregatedMetricResult,\n AggregationMetadata,\n Metric,\n EntityMetricDetailResponse,\n} from '@red-hat-developer-hub/backstage-plugin-scorecard-common';\n\nimport type { GetAggregatedScorecardEntitiesOptions } from '../components/types';\n\nexport { ScorecardQueryProvider } from './ScorecardQueryProvider';\n\nimport type {\n ScorecardApi,\n ScorecardApiClientOptions,\n ScorecardOptions,\n} from './types';\n\nexport const scorecardApiRef = createApiRef<ScorecardApi>({\n id: 'plugin.scorecard.service',\n});\n\n/**\n * Client implementation for the Scorecard API.\n * @public\n */\nexport class ScorecardApiClient implements ScorecardApi {\n private readonly fetchApi: FetchApi;\n private readonly discoveryApi: DiscoveryApi;\n\n constructor(options: ScorecardApiClientOptions) {\n this.fetchApi = options.fetchApi;\n this.discoveryApi = options.discoveryApi;\n }\n\n async getBaseUrl(): Promise<string> {\n return await this.discoveryApi.getBaseUrl('scorecard');\n }\n\n async getScorecards({\n entity,\n metricIds,\n }: ScorecardOptions): Promise<MetricResult[]> {\n if (\n !entity?.kind ||\n !entity?.metadata?.namespace ||\n !entity?.metadata?.name\n ) {\n throw new Error(\n 'Entity missing required properties for scorecard lookup',\n );\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = new URL(\n `${baseUrl}/metrics/catalog/${entity.kind}/${entity.metadata.namespace}/${entity.metadata.name}`,\n );\n\n if (metricIds) {\n url.searchParams.set('metricIds', metricIds.join(','));\n }\n\n try {\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to fetch scorecards: ${response.status} ${response.statusText}. ${errorText}`,\n );\n }\n\n const data = await response.json();\n\n if (!Array.isArray(data)) {\n throw new Error('Invalid response format from scorecard API');\n }\n\n return data;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(`Unexpected error fetching scorecards: ${String(error)}`);\n }\n }\n\n async getAggregatedScorecard(\n aggregationId: string,\n ): Promise<AggregatedMetricResult> {\n if (!aggregationId || aggregationId.trim() === '') {\n throw new Error('Aggregation ID is required for aggregated scorecards');\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = new URL(`${baseUrl}/aggregations/${aggregationId}`);\n\n try {\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to fetch aggregated scorecards: ${response.status} ${response.statusText}. ${errorText}`,\n );\n }\n\n const data = await response.json();\n\n if (\n !data ||\n Array.isArray(data) ||\n typeof data !== 'object' ||\n !('result' in data) ||\n !('metadata' in data) ||\n !('id' in data) ||\n !('status' in data)\n ) {\n throw new TypeError(\n 'Invalid response format from aggregated scorecard API',\n );\n }\n\n return data;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(\n `Unexpected error fetching aggregated scorecards: ${String(error)}`,\n );\n }\n }\n\n async getMetrics(options?: {\n metricIds?: string[];\n }): Promise<{ metrics: Metric[] }> {\n const { metricIds } = options || {};\n\n const isMetricIds =\n metricIds && Array.isArray(metricIds) && metricIds.length > 0;\n\n const baseUrl = await this.getBaseUrl();\n const url = new URL(`${baseUrl}/metrics`);\n\n if (isMetricIds) {\n url.searchParams.set('metricIds', metricIds.join(','));\n }\n\n try {\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to fetch metric: ${response.status} ${response.statusText}. ${errorText}`,\n );\n }\n\n const data = await response.json();\n\n if (\n !data ||\n Array.isArray(data) ||\n typeof data !== 'object' ||\n !('metrics' in data) ||\n !Array.isArray(data.metrics)\n ) {\n throw new TypeError('Invalid response format from metrics API');\n }\n\n return data;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(`Unexpected error fetching metric: ${String(error)}`);\n }\n }\n\n async getAggregatedScorecardEntities(\n options: GetAggregatedScorecardEntitiesOptions,\n ): Promise<EntityMetricDetailResponse> {\n const {\n metricId,\n page,\n pageSize,\n ownershipEntityRefs = [],\n orderBy = null,\n order = 'asc',\n } = options;\n\n if (!metricId) {\n throw new Error('Metric ID is required for aggregated scorecards');\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = new URL(\n `${baseUrl}/metrics/${metricId}/catalog/aggregations/entities`,\n );\n if (page) {\n url.searchParams.append('page', page.toString());\n }\n if (pageSize) {\n url.searchParams.append('pageSize', pageSize.toString());\n }\n if (ownershipEntityRefs.length > 0) {\n for (const ownershipEntityRef of ownershipEntityRefs) {\n url.searchParams.append('owner', ownershipEntityRef);\n }\n }\n if (orderBy) {\n url.searchParams.append('sortBy', orderBy);\n url.searchParams.append('sortOrder', order);\n }\n\n try {\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to fetch aggregated scorecards: ${response.status} ${response.statusText}. ${errorText}`,\n );\n }\n\n const data = await response.json();\n\n if (!data || Array.isArray(data) || typeof data !== 'object') {\n throw new TypeError(\n 'Invalid response format from aggregated scorecard API',\n );\n }\n\n return data;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(\n `Unexpected error fetching aggregated scorecards: ${String(error)}`,\n );\n }\n }\n\n async getAggregationMetadata(\n aggregationId: string,\n ): Promise<AggregationMetadata> {\n if (!aggregationId || aggregationId.trim() === '') {\n throw new Error('Aggregation ID is required for aggregation metadata');\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = new URL(`${baseUrl}/aggregations/${aggregationId}/metadata`);\n\n try {\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to fetch aggregation metadata: ${response.status} ${response.statusText}. ${errorText}`,\n );\n }\n\n const data = await response.json();\n\n if (\n !data ||\n Array.isArray(data) ||\n typeof data !== 'object' ||\n !('title' in data) ||\n !('description' in data) ||\n !('type' in data) ||\n !('aggregationType' in data)\n ) {\n throw new TypeError(\n 'Invalid response format from aggregation metadata API',\n );\n }\n\n return data as AggregationMetadata;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(\n `Unexpected error fetching aggregation metadata: ${String(error)}`,\n );\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../src/api/index.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createApiRef,\n FetchApi,\n DiscoveryApi,\n} from '@backstage/core-plugin-api';\nimport type {\n MetricResult,\n AggregatedMetricResult,\n AggregationMetadata,\n Metric,\n EntityMetricDetailResponse,\n} from '@red-hat-developer-hub/backstage-plugin-scorecard-common';\n\nimport type { GetAggregatedScorecardEntitiesOptions } from '../components/types';\n\nexport { ScorecardQueryProvider } from './ScorecardQueryProvider';\n\nimport type {\n ScorecardApi,\n ScorecardApiClientOptions,\n ScorecardOptions,\n} from './types';\n\nexport const scorecardApiRef = createApiRef<ScorecardApi>({\n id: 'plugin.scorecard.service',\n});\n\n/**\n * Client implementation for the Scorecard API.\n * @public\n */\nexport class ScorecardApiClient implements ScorecardApi {\n private readonly fetchApi: FetchApi;\n private readonly discoveryApi: DiscoveryApi;\n\n constructor(options: ScorecardApiClientOptions) {\n this.fetchApi = options.fetchApi;\n this.discoveryApi = options.discoveryApi;\n }\n\n async getBaseUrl(): Promise<string> {\n return await this.discoveryApi.getBaseUrl('scorecard');\n }\n\n async getScorecards({\n entity,\n metricIds,\n }: ScorecardOptions): Promise<MetricResult[]> {\n if (\n !entity?.kind ||\n !entity?.metadata?.namespace ||\n !entity?.metadata?.name\n ) {\n throw new Error(\n 'Entity missing required properties for scorecard lookup',\n );\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = new URL(\n `${baseUrl}/metrics/catalog/${entity.kind}/${entity.metadata.namespace}/${entity.metadata.name}`,\n );\n\n if (metricIds) {\n url.searchParams.set('metricIds', metricIds.join(','));\n }\n\n try {\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to fetch scorecards: ${response.status} ${response.statusText}. ${errorText}`,\n );\n }\n\n const data = await response.json();\n\n if (!Array.isArray(data)) {\n throw new Error('Invalid response format from scorecard API');\n }\n\n return data;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(`Unexpected error fetching scorecards: ${String(error)}`);\n }\n }\n\n async getAggregatedScorecard(\n aggregationId: string,\n ): Promise<AggregatedMetricResult> {\n if (!aggregationId || aggregationId.trim() === '') {\n throw new Error('Aggregation ID is required for aggregated scorecards');\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = new URL(`${baseUrl}/aggregations/${aggregationId}`);\n\n try {\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to fetch aggregated scorecards: ${response.status} ${response.statusText}. ${errorText}`,\n );\n }\n\n const data = await response.json();\n\n if (\n !data ||\n Array.isArray(data) ||\n typeof data !== 'object' ||\n !('result' in data) ||\n !('metadata' in data) ||\n !('id' in data) ||\n !('status' in data)\n ) {\n throw new TypeError(\n 'Invalid response format from aggregated scorecard API',\n );\n }\n\n const resultRaw = data.result;\n if (\n resultRaw === null ||\n typeof resultRaw !== 'object' ||\n Array.isArray(resultRaw)\n ) {\n throw new TypeError(\n 'Invalid response format from aggregated scorecard API: result must be a non-null object',\n );\n }\n\n const requireFiniteNumber = (value: unknown, fieldName: string) => {\n const n = Number(value ?? 0);\n if (!Number.isFinite(n)) {\n throw new TypeError(\n `Invalid aggregated scorecard API response: ${fieldName} must be a finite number`,\n );\n }\n return n;\n };\n\n const resultRecord = resultRaw as Record<string, unknown>;\n const timestampValue = resultRecord.timestamp;\n let timestamp: string;\n if (typeof timestampValue === 'string') {\n timestamp = timestampValue;\n } else if (\n typeof timestampValue === 'number' &&\n Number.isFinite(timestampValue)\n ) {\n timestamp = String(timestampValue);\n } else if (typeof timestampValue === 'bigint') {\n timestamp = timestampValue.toString();\n } else if (timestampValue instanceof Date) {\n timestamp = timestampValue.toISOString();\n } else {\n timestamp = '';\n }\n\n return {\n ...data,\n result: {\n ...resultRecord,\n total: requireFiniteNumber(resultRecord.total, 'total'),\n entitiesConsidered: requireFiniteNumber(\n resultRecord.entitiesConsidered,\n 'entitiesConsidered',\n ),\n calculationErrorCount: requireFiniteNumber(\n resultRecord.calculationErrorCount,\n 'calculationErrorCount',\n ),\n timestamp,\n },\n } as AggregatedMetricResult;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(\n `Unexpected error fetching aggregated scorecards: ${String(error)}`,\n );\n }\n }\n\n async getMetrics(options?: {\n metricIds?: string[];\n }): Promise<{ metrics: Metric[] }> {\n const { metricIds } = options || {};\n\n const isMetricIds =\n metricIds && Array.isArray(metricIds) && metricIds.length > 0;\n\n const baseUrl = await this.getBaseUrl();\n const url = new URL(`${baseUrl}/metrics`);\n\n if (isMetricIds) {\n url.searchParams.set('metricIds', metricIds.join(','));\n }\n\n try {\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to fetch metric: ${response.status} ${response.statusText}. ${errorText}`,\n );\n }\n\n const data = await response.json();\n\n if (\n !data ||\n Array.isArray(data) ||\n typeof data !== 'object' ||\n !('metrics' in data) ||\n !Array.isArray(data.metrics)\n ) {\n throw new TypeError('Invalid response format from metrics API');\n }\n\n return data;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(`Unexpected error fetching metric: ${String(error)}`);\n }\n }\n\n async getAggregatedScorecardEntities(\n options: GetAggregatedScorecardEntitiesOptions,\n ): Promise<EntityMetricDetailResponse> {\n const {\n metricId,\n page,\n pageSize,\n ownershipEntityRefs = [],\n orderBy = null,\n order = 'asc',\n } = options;\n\n if (!metricId) {\n throw new Error('Metric ID is required for aggregated scorecards');\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = new URL(\n `${baseUrl}/metrics/${metricId}/catalog/aggregations/entities`,\n );\n if (page) {\n url.searchParams.append('page', page.toString());\n }\n if (pageSize) {\n url.searchParams.append('pageSize', pageSize.toString());\n }\n if (ownershipEntityRefs.length > 0) {\n for (const ownershipEntityRef of ownershipEntityRefs) {\n url.searchParams.append('owner', ownershipEntityRef);\n }\n }\n if (orderBy) {\n url.searchParams.append('sortBy', orderBy);\n url.searchParams.append('sortOrder', order);\n }\n\n try {\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to fetch aggregated scorecards: ${response.status} ${response.statusText}. ${errorText}`,\n );\n }\n\n const data = await response.json();\n\n if (!data || Array.isArray(data) || typeof data !== 'object') {\n throw new TypeError(\n 'Invalid response format from aggregated scorecard API',\n );\n }\n\n return data;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(\n `Unexpected error fetching aggregated scorecards: ${String(error)}`,\n );\n }\n }\n\n async getAggregationMetadata(\n aggregationId: string,\n ): Promise<AggregationMetadata> {\n if (!aggregationId || aggregationId.trim() === '') {\n throw new Error('Aggregation ID is required for aggregation metadata');\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = new URL(`${baseUrl}/aggregations/${aggregationId}/metadata`);\n\n try {\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to fetch aggregation metadata: ${response.status} ${response.statusText}. ${errorText}`,\n );\n }\n\n const data = await response.json();\n\n if (\n !data ||\n Array.isArray(data) ||\n typeof data !== 'object' ||\n !('title' in data) ||\n !('description' in data) ||\n !('type' in data) ||\n !('aggregationType' in data)\n ) {\n throw new TypeError(\n 'Invalid response format from aggregation metadata API',\n );\n }\n\n return data as AggregationMetadata;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(\n `Unexpected error fetching aggregation metadata: ${String(error)}`,\n );\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { aggregationTypes } from '@red-hat-developer-hub/backstage-plugin-scorecard-common';
|
|
3
|
+
import { StatusGroupedCardComponent } from './StatusGroupedCard/StatusGroupedCardComponent.esm.js';
|
|
4
|
+
import { AverageCardComponent } from './AverageCard/AverageCardComponent.esm.js';
|
|
5
|
+
import { UnsupportedAggregationType } from './UnsupportedAggregationType.esm.js';
|
|
6
|
+
|
|
7
|
+
const AggregatedMetricCard = (props) => {
|
|
8
|
+
switch (props.scorecard.metadata.aggregationType) {
|
|
9
|
+
case aggregationTypes.statusGrouped:
|
|
10
|
+
return /* @__PURE__ */ jsx(
|
|
11
|
+
StatusGroupedCardComponent,
|
|
12
|
+
{
|
|
13
|
+
...props
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
case aggregationTypes.average:
|
|
17
|
+
return /* @__PURE__ */ jsx(AverageCardComponent, { ...props });
|
|
18
|
+
default:
|
|
19
|
+
return /* @__PURE__ */ jsx(
|
|
20
|
+
UnsupportedAggregationType,
|
|
21
|
+
{
|
|
22
|
+
cardTitle: props.cardTitle,
|
|
23
|
+
description: props.description,
|
|
24
|
+
dataTestId: props.dataTestId,
|
|
25
|
+
aggregationType: String(props.scorecard.metadata.aggregationType)
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export { AggregatedMetricCard };
|
|
32
|
+
//# sourceMappingURL=AggregatedMetricCard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AggregatedMetricCard.esm.js","sources":["../../../src/components/AggregatedMetricCards/AggregatedMetricCard.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { aggregationTypes } from '@red-hat-developer-hub/backstage-plugin-scorecard-common';\nimport { StatusGroupedCardComponent } from './StatusGroupedCard/StatusGroupedCardComponent';\nimport { AverageCardComponent } from './AverageCard/AverageCardComponent';\nimport type { AverageCardComponentProps } from './AverageCard/types';\nimport type { StatusGroupedCardComponentProps } from './StatusGroupedCard/types';\nimport { UnsupportedAggregationType } from './UnsupportedAggregationType';\n\nexport type AggregatedMetricCardProps =\n | StatusGroupedCardComponentProps\n | AverageCardComponentProps;\n\nexport const AggregatedMetricCard = (props: AggregatedMetricCardProps) => {\n switch (props.scorecard.metadata.aggregationType) {\n case aggregationTypes.statusGrouped:\n return (\n <StatusGroupedCardComponent\n {...(props as StatusGroupedCardComponentProps)}\n />\n );\n case aggregationTypes.average:\n return <AverageCardComponent {...(props as AverageCardComponentProps)} />;\n default:\n return (\n <UnsupportedAggregationType\n cardTitle={props.cardTitle}\n description={props.description}\n dataTestId={props.dataTestId}\n aggregationType={String(props.scorecard.metadata.aggregationType)}\n />\n );\n }\n};\n"],"names":[],"mappings":";;;;;;AA2Ba,MAAA,oBAAA,GAAuB,CAAC,KAAqC,KAAA;AACxE,EAAQ,QAAA,KAAA,CAAM,SAAU,CAAA,QAAA,CAAS,eAAiB;AAAA,IAChD,KAAK,gBAAiB,CAAA,aAAA;AACpB,MACE,uBAAA,GAAA;AAAA,QAAC,0BAAA;AAAA,QAAA;AAAA,UACE,GAAI;AAAA;AAAA,OACP;AAAA,IAEJ,KAAK,gBAAiB,CAAA,OAAA;AACpB,MAAO,uBAAA,GAAA,CAAC,oBAAsB,EAAA,EAAA,GAAI,KAAqC,EAAA,CAAA;AAAA,IACzE;AACE,MACE,uBAAA,GAAA;AAAA,QAAC,0BAAA;AAAA,QAAA;AAAA,UACC,WAAW,KAAM,CAAA,SAAA;AAAA,UACjB,aAAa,KAAM,CAAA,WAAA;AAAA,UACnB,YAAY,KAAM,CAAA,UAAA;AAAA,UAClB,eAAiB,EAAA,MAAA,CAAO,KAAM,CAAA,SAAA,CAAU,SAAS,eAAe;AAAA;AAAA,OAClE;AAAA;AAGR;;;;"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { useTheme } from '@mui/material/styles';
|
|
4
|
+
import { CardWrapper } from '../../Common/CardWrapper.esm.js';
|
|
5
|
+
import { SCORECARD_ERROR_STATE_COLOR } from '../../../utils/constants.esm.js';
|
|
6
|
+
import 'date-fns';
|
|
7
|
+
import { resolveStatusColor } from '../../../utils/statusUtils.esm.js';
|
|
8
|
+
import { getThresholdRuleColor } from '../../../utils/thresholdUtils.esm.js';
|
|
9
|
+
import { ResponsivePieChart } from '../../ScorecardHomepageSection/ResponsivePieChart.esm.js';
|
|
10
|
+
import { CardInfoButton } from '../components/CardInfoButton.esm.js';
|
|
11
|
+
import { CardSubheader } from '../components/CardSubheader.esm.js';
|
|
12
|
+
import { CardChartContainer } from '../components/CardChartContainer.esm.js';
|
|
13
|
+
import { CardTooltip } from '../components/CardTooltip.esm.js';
|
|
14
|
+
import { LegendTooltipContent } from './LegendTooltipContent.esm.js';
|
|
15
|
+
import { DonutChartTooltipContent } from './DonutChartTooltipContent.esm.js';
|
|
16
|
+
import { CardLegendContent } from '../components/CardLegendContent.esm.js';
|
|
17
|
+
import { AverageCardPieCenterLabel } from './AverageCardPieCenterLabel.esm.js';
|
|
18
|
+
import { formatPercentage } from '../../../utils/formatPercentage.esm.js';
|
|
19
|
+
|
|
20
|
+
const AVERAGE_SCORE_SLICE = "averageScoreFill";
|
|
21
|
+
const AVERAGE_REMAINDER_SLICE = "averageScoreRemainder";
|
|
22
|
+
function clampPercentForDonut(rawPercent) {
|
|
23
|
+
const fill = Math.min(100, Math.max(0, rawPercent));
|
|
24
|
+
return { fill, remainder: 100 - fill };
|
|
25
|
+
}
|
|
26
|
+
const AverageCardComponent = ({
|
|
27
|
+
scorecard,
|
|
28
|
+
cardTitle,
|
|
29
|
+
description,
|
|
30
|
+
aggregationId,
|
|
31
|
+
showSubheader = true,
|
|
32
|
+
showInfo = true,
|
|
33
|
+
dataTestId
|
|
34
|
+
}) => {
|
|
35
|
+
const theme = useTheme();
|
|
36
|
+
const [activeIndex, setActiveIndex] = useState(null);
|
|
37
|
+
const [tooltipPosition, setTooltipPosition] = useState(null);
|
|
38
|
+
const [centerTooltipPosition, setCenterTooltipPosition] = useState(null);
|
|
39
|
+
const updateCenterTooltipPosition = (e) => {
|
|
40
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
41
|
+
setCenterTooltipPosition({
|
|
42
|
+
left: rect.left + rect.width / 2,
|
|
43
|
+
top: rect.top
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
const rawPercent = scorecard.result.averageScore * 100;
|
|
47
|
+
const { fill: chartFillPercent, remainder: chartRemainderPercent } = clampPercentForDonut(rawPercent);
|
|
48
|
+
const centerPercentLabel = `${formatPercentage(rawPercent)}%`;
|
|
49
|
+
const arcResolvedColor = resolveStatusColor(
|
|
50
|
+
theme,
|
|
51
|
+
scorecard.result.aggregationChartDisplayColor
|
|
52
|
+
);
|
|
53
|
+
const averagePieData = [
|
|
54
|
+
{
|
|
55
|
+
name: AVERAGE_SCORE_SLICE,
|
|
56
|
+
value: chartFillPercent,
|
|
57
|
+
color: arcResolvedColor
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: AVERAGE_REMAINDER_SLICE,
|
|
61
|
+
value: chartRemainderPercent,
|
|
62
|
+
color: theme.palette.grey[300]
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
const statusPieData = scorecard.result.values?.map((value) => ({
|
|
66
|
+
name: value.name,
|
|
67
|
+
value: value.count,
|
|
68
|
+
score: value.score,
|
|
69
|
+
color: resolveStatusColor(
|
|
70
|
+
theme,
|
|
71
|
+
getThresholdRuleColor(scorecard.result.thresholds.rules, value.name) ?? SCORECARD_ERROR_STATE_COLOR
|
|
72
|
+
)
|
|
73
|
+
})) ?? [];
|
|
74
|
+
const subheader = showSubheader ? /* @__PURE__ */ jsx(
|
|
75
|
+
CardSubheader,
|
|
76
|
+
{
|
|
77
|
+
aggregationId,
|
|
78
|
+
scorecardId: scorecard.id,
|
|
79
|
+
entitiesCount: scorecard.result.total,
|
|
80
|
+
entitiesConsidered: scorecard.result.entitiesConsidered,
|
|
81
|
+
calculationErrorCount: scorecard.result.calculationErrorCount
|
|
82
|
+
}
|
|
83
|
+
) : null;
|
|
84
|
+
const info = showInfo ? /* @__PURE__ */ jsx(CardInfoButton, { timestamp: scorecard.result.timestamp }) : null;
|
|
85
|
+
return /* @__PURE__ */ jsx(
|
|
86
|
+
CardWrapper,
|
|
87
|
+
{
|
|
88
|
+
title: cardTitle,
|
|
89
|
+
dataTestId,
|
|
90
|
+
subheader,
|
|
91
|
+
description,
|
|
92
|
+
info,
|
|
93
|
+
children: /* @__PURE__ */ jsxs(CardChartContainer, { children: [
|
|
94
|
+
/* @__PURE__ */ jsx(
|
|
95
|
+
ResponsivePieChart,
|
|
96
|
+
{
|
|
97
|
+
pieData: averagePieData,
|
|
98
|
+
LabelContent: (props) => /* @__PURE__ */ jsx(
|
|
99
|
+
AverageCardPieCenterLabel,
|
|
100
|
+
{
|
|
101
|
+
...props,
|
|
102
|
+
centerPercentLabel,
|
|
103
|
+
arcResolvedColor,
|
|
104
|
+
setActiveIndex,
|
|
105
|
+
setTooltipPosition,
|
|
106
|
+
updateCenterTooltipPosition,
|
|
107
|
+
setCenterTooltipPosition
|
|
108
|
+
}
|
|
109
|
+
),
|
|
110
|
+
legendContent: (props) => /* @__PURE__ */ jsx(
|
|
111
|
+
CardLegendContent,
|
|
112
|
+
{
|
|
113
|
+
...props,
|
|
114
|
+
activeIndex,
|
|
115
|
+
setActiveIndex,
|
|
116
|
+
setTooltipPosition,
|
|
117
|
+
pieData: statusPieData
|
|
118
|
+
}
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
),
|
|
122
|
+
centerTooltipPosition && /* @__PURE__ */ jsx(
|
|
123
|
+
CardTooltip,
|
|
124
|
+
{
|
|
125
|
+
tooltipPosition: centerTooltipPosition,
|
|
126
|
+
pieData: averagePieData,
|
|
127
|
+
payload: [
|
|
128
|
+
{
|
|
129
|
+
name: AVERAGE_SCORE_SLICE,
|
|
130
|
+
value: 1,
|
|
131
|
+
payload: averagePieData[0]
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
customContent: /* @__PURE__ */ jsx(
|
|
135
|
+
DonutChartTooltipContent,
|
|
136
|
+
{
|
|
137
|
+
weightedSum: scorecard.result.averageWeightedSum,
|
|
138
|
+
maxPossible: scorecard.result.averageMaxPossible
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
),
|
|
143
|
+
activeIndex !== null && tooltipPosition && statusPieData[activeIndex] && /* @__PURE__ */ jsx(
|
|
144
|
+
CardTooltip,
|
|
145
|
+
{
|
|
146
|
+
tooltipPosition,
|
|
147
|
+
pieData: statusPieData,
|
|
148
|
+
payload: [
|
|
149
|
+
{
|
|
150
|
+
name: statusPieData[activeIndex].name,
|
|
151
|
+
value: statusPieData[activeIndex].value || 1,
|
|
152
|
+
payload: statusPieData[activeIndex]
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
customContent: /* @__PURE__ */ jsx(
|
|
156
|
+
LegendTooltipContent,
|
|
157
|
+
{
|
|
158
|
+
row: statusPieData[activeIndex],
|
|
159
|
+
maxPossible: scorecard.result.averageMaxPossible
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
] })
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export { AverageCardComponent };
|
|
170
|
+
//# sourceMappingURL=AverageCardComponent.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AverageCardComponent.esm.js","sources":["../../../../src/components/AggregatedMetricCards/AverageCard/AverageCardComponent.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useState } from 'react';\nimport type { MouseEvent } from 'react';\n\nimport { useTheme } from '@mui/material/styles';\n\nimport { CardWrapper } from '../../Common/CardWrapper';\nimport type { PieData } from '../../types';\nimport {\n getThresholdRuleColor,\n resolveStatusColor,\n SCORECARD_ERROR_STATE_COLOR,\n} from '../../../utils';\nimport { ResponsivePieChart } from '../../ScorecardHomepageSection/ResponsivePieChart';\nimport { CardInfoButton } from '../components/CardInfoButton';\nimport { CardSubheader } from '../components/CardSubheader';\nimport { CardChartContainer } from '../components/CardChartContainer';\nimport { CardTooltip } from '../components/CardTooltip';\nimport { LegendTooltipContent } from './LegendTooltipContent';\nimport { DonutChartTooltipContent } from './DonutChartTooltipContent';\nimport type { AverageCardComponentProps, TooltipPosition } from './types';\nimport { CardLegendContent } from '../components/CardLegendContent';\nimport { AverageCardPieCenterLabel } from './AverageCardPieCenterLabel';\nimport { formatPercentage } from '../../../utils/formatPercentage';\n\nconst AVERAGE_SCORE_SLICE = 'averageScoreFill';\nconst AVERAGE_REMAINDER_SLICE = 'averageScoreRemainder';\n\nfunction clampPercentForDonut(rawPercent: number): {\n fill: number;\n remainder: number;\n} {\n const fill = Math.min(100, Math.max(0, rawPercent));\n return { fill, remainder: 100 - fill };\n}\n\nexport const AverageCardComponent = ({\n scorecard,\n cardTitle,\n description,\n aggregationId,\n showSubheader = true,\n showInfo = true,\n dataTestId,\n}: AverageCardComponentProps) => {\n const theme = useTheme();\n\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const [tooltipPosition, setTooltipPosition] =\n useState<TooltipPosition | null>(null);\n const [centerTooltipPosition, setCenterTooltipPosition] =\n useState<TooltipPosition | null>(null);\n\n const updateCenterTooltipPosition = (e: MouseEvent<SVGCircleElement>) => {\n const rect = e.currentTarget.getBoundingClientRect();\n setCenterTooltipPosition({\n left: rect.left + rect.width / 2,\n top: rect.top,\n });\n };\n\n const rawPercent = scorecard.result.averageScore * 100;\n const { fill: chartFillPercent, remainder: chartRemainderPercent } =\n clampPercentForDonut(rawPercent);\n\n const centerPercentLabel = `${formatPercentage(rawPercent)}%`;\n\n const arcResolvedColor = resolveStatusColor(\n theme,\n scorecard.result.aggregationChartDisplayColor,\n );\n\n const averagePieData: PieData[] = [\n {\n name: AVERAGE_SCORE_SLICE,\n value: chartFillPercent,\n color: arcResolvedColor,\n },\n {\n name: AVERAGE_REMAINDER_SLICE,\n value: chartRemainderPercent,\n color: theme.palette.grey[300],\n },\n ];\n\n const statusPieData: PieData[] =\n scorecard.result.values?.map(value => ({\n name: value.name,\n value: value.count,\n score: value.score,\n color: resolveStatusColor(\n theme,\n getThresholdRuleColor(scorecard.result.thresholds.rules, value.name) ??\n SCORECARD_ERROR_STATE_COLOR,\n ),\n })) ?? [];\n\n const subheader = showSubheader ? (\n <CardSubheader\n aggregationId={aggregationId}\n scorecardId={scorecard.id}\n entitiesCount={scorecard.result.total}\n entitiesConsidered={scorecard.result.entitiesConsidered}\n calculationErrorCount={scorecard.result.calculationErrorCount}\n />\n ) : null;\n\n const info = showInfo ? (\n <CardInfoButton timestamp={scorecard.result.timestamp} />\n ) : null;\n\n return (\n <CardWrapper\n title={cardTitle}\n dataTestId={dataTestId}\n subheader={subheader}\n description={description}\n info={info}\n >\n <CardChartContainer>\n <ResponsivePieChart\n pieData={averagePieData}\n LabelContent={props => (\n <AverageCardPieCenterLabel\n {...props}\n centerPercentLabel={centerPercentLabel}\n arcResolvedColor={arcResolvedColor}\n setActiveIndex={setActiveIndex}\n setTooltipPosition={setTooltipPosition}\n updateCenterTooltipPosition={updateCenterTooltipPosition}\n setCenterTooltipPosition={setCenterTooltipPosition}\n />\n )}\n legendContent={props => (\n <CardLegendContent\n {...props}\n activeIndex={activeIndex}\n setActiveIndex={setActiveIndex}\n setTooltipPosition={setTooltipPosition}\n pieData={statusPieData}\n />\n )}\n />\n\n {centerTooltipPosition && (\n <CardTooltip\n tooltipPosition={centerTooltipPosition}\n pieData={averagePieData}\n payload={[\n {\n name: AVERAGE_SCORE_SLICE,\n value: 1,\n payload: averagePieData[0],\n },\n ]}\n customContent={\n <DonutChartTooltipContent\n weightedSum={scorecard.result.averageWeightedSum}\n maxPossible={scorecard.result.averageMaxPossible}\n />\n }\n />\n )}\n\n {activeIndex !== null &&\n tooltipPosition &&\n statusPieData[activeIndex] && (\n <CardTooltip\n tooltipPosition={tooltipPosition}\n pieData={statusPieData}\n payload={[\n {\n name: statusPieData[activeIndex].name,\n value: statusPieData[activeIndex].value || 1,\n payload: statusPieData[activeIndex],\n },\n ]}\n customContent={\n <LegendTooltipContent\n row={statusPieData[activeIndex]}\n maxPossible={scorecard.result.averageMaxPossible}\n />\n }\n />\n )}\n </CardChartContainer>\n </CardWrapper>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
function AverageCardPieCenterLabel({
|
|
4
|
+
cx,
|
|
5
|
+
cy,
|
|
6
|
+
index,
|
|
7
|
+
centerPercentLabel,
|
|
8
|
+
arcResolvedColor,
|
|
9
|
+
setActiveIndex,
|
|
10
|
+
setTooltipPosition,
|
|
11
|
+
updateCenterTooltipPosition,
|
|
12
|
+
setCenterTooltipPosition
|
|
13
|
+
}) {
|
|
14
|
+
if (cx === void 0 || cx === null || cy === void 0 || cy === null || index === void 0 || index !== 0) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const cxNum = Number(cx);
|
|
18
|
+
const cyNum = Number(cy);
|
|
19
|
+
return /* @__PURE__ */ jsxs("g", { style: { cursor: "pointer" }, children: [
|
|
20
|
+
/* @__PURE__ */ jsx(
|
|
21
|
+
"circle",
|
|
22
|
+
{
|
|
23
|
+
cx: cxNum,
|
|
24
|
+
cy: cyNum,
|
|
25
|
+
r: 52,
|
|
26
|
+
fill: "transparent",
|
|
27
|
+
stroke: "none",
|
|
28
|
+
pointerEvents: "all",
|
|
29
|
+
"data-testid": "average-card-center-percent-hit-area",
|
|
30
|
+
onMouseEnter: (e) => {
|
|
31
|
+
setActiveIndex(null);
|
|
32
|
+
setTooltipPosition(null);
|
|
33
|
+
updateCenterTooltipPosition(e);
|
|
34
|
+
},
|
|
35
|
+
onMouseMove: updateCenterTooltipPosition,
|
|
36
|
+
onMouseLeave: () => setCenterTooltipPosition(null)
|
|
37
|
+
}
|
|
38
|
+
),
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
"text",
|
|
41
|
+
{
|
|
42
|
+
x: cxNum,
|
|
43
|
+
y: cyNum,
|
|
44
|
+
textAnchor: "middle",
|
|
45
|
+
dominantBaseline: "middle",
|
|
46
|
+
fill: arcResolvedColor,
|
|
47
|
+
fontSize: 24,
|
|
48
|
+
fontWeight: 500,
|
|
49
|
+
pointerEvents: "none",
|
|
50
|
+
"data-testid": "average-card-center-percent",
|
|
51
|
+
children: centerPercentLabel
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
] });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { AverageCardPieCenterLabel };
|
|
58
|
+
//# sourceMappingURL=AverageCardPieCenterLabel.esm.js.map
|
package/dist/components/AggregatedMetricCards/AverageCard/AverageCardPieCenterLabel.esm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AverageCardPieCenterLabel.esm.js","sources":["../../../../src/components/AggregatedMetricCards/AverageCard/AverageCardPieCenterLabel.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PieLabelRenderProps } from 'recharts';\nimport { TooltipPosition } from './types';\n\ntype AverageCardPieCenterLabelProps = PieLabelRenderProps & {\n centerPercentLabel: string;\n arcResolvedColor: string;\n setActiveIndex: (index: number | null) => void;\n setTooltipPosition: (position: TooltipPosition | null) => void;\n updateCenterTooltipPosition: (e: React.MouseEvent<SVGCircleElement>) => void;\n setCenterTooltipPosition: (position: TooltipPosition | null) => void;\n};\n\nexport function AverageCardPieCenterLabel({\n cx,\n cy,\n index,\n centerPercentLabel,\n arcResolvedColor,\n setActiveIndex,\n setTooltipPosition,\n updateCenterTooltipPosition,\n setCenterTooltipPosition,\n}: AverageCardPieCenterLabelProps) {\n if (\n cx === undefined ||\n cx === null ||\n cy === undefined ||\n cy === null ||\n index === undefined ||\n index !== 0\n ) {\n return null;\n }\n const cxNum = Number(cx);\n const cyNum = Number(cy);\n return (\n <g style={{ cursor: 'pointer' }}>\n <circle\n cx={cxNum}\n cy={cyNum}\n r={52}\n fill=\"transparent\"\n stroke=\"none\"\n pointerEvents=\"all\"\n data-testid=\"average-card-center-percent-hit-area\"\n onMouseEnter={e => {\n setActiveIndex(null);\n setTooltipPosition(null);\n updateCenterTooltipPosition(e);\n }}\n onMouseMove={updateCenterTooltipPosition}\n onMouseLeave={() => setCenterTooltipPosition(null)}\n />\n <text\n x={cxNum}\n y={cyNum}\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fill={arcResolvedColor}\n fontSize={24}\n fontWeight={500}\n pointerEvents=\"none\"\n data-testid=\"average-card-center-percent\"\n >\n {centerPercentLabel}\n </text>\n </g>\n );\n}\n"],"names":[],"mappings":";;AA4BO,SAAS,yBAA0B,CAAA;AAAA,EACxC,EAAA;AAAA,EACA,EAAA;AAAA,EACA,KAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,cAAA;AAAA,EACA,kBAAA;AAAA,EACA,2BAAA;AAAA,EACA;AACF,CAAmC,EAAA;AACjC,EACE,IAAA,EAAA,KAAO,MACP,IAAA,EAAA,KAAO,IACP,IAAA,EAAA,KAAO,MACP,IAAA,EAAA,KAAO,IACP,IAAA,KAAA,KAAU,MACV,IAAA,KAAA,KAAU,CACV,EAAA;AACA,IAAO,OAAA,IAAA;AAAA;AAET,EAAM,MAAA,KAAA,GAAQ,OAAO,EAAE,CAAA;AACvB,EAAM,MAAA,KAAA,GAAQ,OAAO,EAAE,CAAA;AACvB,EAAA,4BACG,GAAE,EAAA,EAAA,KAAA,EAAO,EAAE,MAAA,EAAQ,WAClB,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,EAAI,EAAA,KAAA;AAAA,QACJ,EAAI,EAAA,KAAA;AAAA,QACJ,CAAG,EAAA,EAAA;AAAA,QACH,IAAK,EAAA,aAAA;AAAA,QACL,MAAO,EAAA,MAAA;AAAA,QACP,aAAc,EAAA,KAAA;AAAA,QACd,aAAY,EAAA,sCAAA;AAAA,QACZ,cAAc,CAAK,CAAA,KAAA;AACjB,UAAA,cAAA,CAAe,IAAI,CAAA;AACnB,UAAA,kBAAA,CAAmB,IAAI,CAAA;AACvB,UAAA,2BAAA,CAA4B,CAAC,CAAA;AAAA,SAC/B;AAAA,QACA,WAAa,EAAA,2BAAA;AAAA,QACb,YAAA,EAAc,MAAM,wBAAA,CAAyB,IAAI;AAAA;AAAA,KACnD;AAAA,oBACA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,CAAG,EAAA,KAAA;AAAA,QACH,CAAG,EAAA,KAAA;AAAA,QACH,UAAW,EAAA,QAAA;AAAA,QACX,gBAAiB,EAAA,QAAA;AAAA,QACjB,IAAM,EAAA,gBAAA;AAAA,QACN,QAAU,EAAA,EAAA;AAAA,QACV,UAAY,EAAA,GAAA;AAAA,QACZ,aAAc,EAAA,MAAA;AAAA,QACd,aAAY,EAAA,6BAAA;AAAA,QAEX,QAAA,EAAA;AAAA;AAAA;AACH,GACF,EAAA,CAAA;AAEJ;;;;"}
|