@red-hat-developer-hub/backstage-plugin-scorecard 2.5.0 → 2.5.2
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 +15 -0
- package/README.md +37 -15
- package/dist/alpha/extensions/homePageCards.esm.js +5 -5
- package/dist/alpha/extensions/homePageCards.esm.js.map +1 -1
- package/dist/alpha/extensions/scorecardPage.esm.js +1 -1
- package/dist/alpha/extensions/scorecardPage.esm.js.map +1 -1
- package/dist/api/ScorecardQueryProvider.esm.js +32 -0
- package/dist/api/ScorecardQueryProvider.esm.js.map +1 -0
- package/dist/api/index.esm.js +3 -0
- package/dist/api/index.esm.js.map +1 -1
- package/dist/components/ScorecardHomepageSection/ErrorStatePanel.esm.js +1 -1
- package/dist/components/ScorecardHomepageSection/ErrorStatePanel.esm.js.map +1 -1
- package/dist/components/ScorecardHomepageSection/ScorecardHomepageCard.esm.js +7 -2
- package/dist/components/ScorecardHomepageSection/ScorecardHomepageCard.esm.js.map +1 -1
- package/dist/components/ScorecardHomepageSection/index.esm.js +1 -1
- package/dist/components/ScorecardIcon/ScorecardIcon.esm.js +9 -1
- package/dist/components/ScorecardIcon/ScorecardIcon.esm.js.map +1 -1
- package/dist/components/ScorecardPage/EntitiesTable/EntitiesRow.esm.js +13 -3
- package/dist/components/ScorecardPage/EntitiesTable/EntitiesRow.esm.js.map +1 -1
- package/dist/components/ScorecardPage/EntitiesTable/EntitiesTable.esm.js +24 -13
- package/dist/components/ScorecardPage/EntitiesTable/EntitiesTable.esm.js.map +1 -1
- package/dist/components/ScorecardPage/EntitiesTable/cells/MetricStatusCell.esm.js +9 -2
- package/dist/components/ScorecardPage/EntitiesTable/cells/MetricStatusCell.esm.js.map +1 -1
- package/dist/components/ScorecardPage/ScorecardPage.esm.js +7 -2
- package/dist/components/ScorecardPage/ScorecardPage.esm.js.map +1 -1
- package/dist/hooks/useAggregatedScorecard.esm.js +27 -31
- package/dist/hooks/useAggregatedScorecard.esm.js.map +1 -1
- package/dist/hooks/useAggregatedScorecardEntities.esm.js +40 -44
- package/dist/hooks/useAggregatedScorecardEntities.esm.js.map +1 -1
- package/dist/hooks/useAggregationMetadata.esm.js +27 -31
- package/dist/hooks/useAggregationMetadata.esm.js.map +1 -1
- package/dist/hooks/useMetric.esm.js +25 -29
- package/dist/hooks/useMetric.esm.js.map +1 -1
- package/dist/hooks/useOwnershipEntityRefs.esm.js +6 -1
- package/dist/hooks/useOwnershipEntityRefs.esm.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/pages/ScorecardPage.esm.js +1 -1
- package/dist/plugin.esm.js +2 -2
- package/dist/plugin.esm.js.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @red-hat-developer-hub/backstage-plugin-scorecard
|
|
2
2
|
|
|
3
|
+
## 2.5.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 501e099: Removed Backstage registration requirement for default Scorecard icons
|
|
8
|
+
- @red-hat-developer-hub/backstage-plugin-scorecard-common@2.5.2
|
|
9
|
+
|
|
10
|
+
## 2.5.1
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- f6f7bcf: add threshold-based status colors to entities table
|
|
15
|
+
- 0fda0c7: fixed the scorecard-homepage-cards default layout for nfs
|
|
16
|
+
- @red-hat-developer-hub/backstage-plugin-scorecard-common@2.5.1
|
|
17
|
+
|
|
3
18
|
## 2.5.0
|
|
4
19
|
|
|
5
20
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -136,8 +136,8 @@ To align with the legacy EntityPage (Scorecard on component pages and default en
|
|
|
136
136
|
config:
|
|
137
137
|
customizable: true
|
|
138
138
|
widgetLayout:
|
|
139
|
-
|
|
140
|
-
priority:
|
|
139
|
+
AggregatedCardWithDeprecatedMetricId:
|
|
140
|
+
priority: 410
|
|
141
141
|
breakpoints:
|
|
142
142
|
xl: { w: 4, h: 6 }
|
|
143
143
|
lg: { w: 4, h: 6 }
|
|
@@ -145,8 +145,26 @@ To align with the legacy EntityPage (Scorecard on component pages and default en
|
|
|
145
145
|
sm: { w: 4, h: 6 }
|
|
146
146
|
xs: { w: 4, h: 6 }
|
|
147
147
|
xxs: { w: 4, h: 6 }
|
|
148
|
-
|
|
149
|
-
priority:
|
|
148
|
+
AggregatedCardWithDefaultAggregation:
|
|
149
|
+
priority: 420
|
|
150
|
+
breakpoints:
|
|
151
|
+
xl: { w: 4, h: 6, x: 4 }
|
|
152
|
+
lg: { w: 4, h: 6, x: 4 }
|
|
153
|
+
md: { w: 4, h: 6, x: 4 }
|
|
154
|
+
sm: { w: 4, h: 6, x: 4 }
|
|
155
|
+
xs: { w: 4, h: 6, x: 4 }
|
|
156
|
+
xxs: { w: 4, h: 6, x: 4 }
|
|
157
|
+
AggregatedCardWithJiraOpenIssues:
|
|
158
|
+
priority: 430
|
|
159
|
+
breakpoints:
|
|
160
|
+
xl: { w: 4, h: 6 }
|
|
161
|
+
lg: { w: 4, h: 6 }
|
|
162
|
+
md: { w: 4, h: 6 }
|
|
163
|
+
sm: { w: 4, h: 6 }
|
|
164
|
+
xs: { w: 4, h: 6 }
|
|
165
|
+
xxs: { w: 4, h: 6 }
|
|
166
|
+
AggregatedCardWithGithubOpenPrs:
|
|
167
|
+
priority: 440
|
|
150
168
|
breakpoints:
|
|
151
169
|
xl: { w: 4, h: 6, x: 4 }
|
|
152
170
|
lg: { w: 4, h: 6, x: 4 }
|
|
@@ -156,12 +174,14 @@ To align with the legacy EntityPage (Scorecard on component pages and default en
|
|
|
156
174
|
xxs: { w: 4, h: 6, x: 4 }
|
|
157
175
|
```
|
|
158
176
|
|
|
159
|
-
The home module contributes
|
|
177
|
+
The home module contributes four widgets:
|
|
160
178
|
|
|
161
|
-
- `
|
|
162
|
-
- `
|
|
179
|
+
- `AggregatedCardWithDeprecatedMetricId` (title: **Scorecard: With deprecated metricId property (Jira)**)
|
|
180
|
+
- `AggregatedCardWithDefaultAggregation` (title: **Scorecard: With default aggregation config (GitHub)**)
|
|
181
|
+
- `AggregatedCardWithJiraOpenIssues` (title: **Scorecard: Jira open blocking tickets**)
|
|
182
|
+
- `AggregatedCardWithGithubOpenPrs` (title: **Scorecard: GitHub open PRs**)
|
|
163
183
|
|
|
164
|
-
These widgets render the
|
|
184
|
+
These widgets render the `ScorecardHomepageCard` component used in legacy apps, preconfigured with different aggregation/metric configurations.
|
|
165
185
|
|
|
166
186
|
##### Modules and extensions (NFS)
|
|
167
187
|
|
|
@@ -169,18 +189,20 @@ The following modules and extensions are available from `@red-hat-developer-hub/
|
|
|
169
189
|
|
|
170
190
|
**Modules**
|
|
171
191
|
|
|
172
|
-
| Module | Description
|
|
173
|
-
| ----------------------------- |
|
|
174
|
-
| `scorecardHomeModule` | Registers Scorecard homepage widgets for the home plugin (`
|
|
175
|
-
| `scorecardCatalogModule` | Registers the Scorecard entity tab with the catalog plugin. Add to your app's `features`. Which entities show the tab is configured via `app.extensions` (see step 3).
|
|
176
|
-
| `scorecardTranslationsModule` | Registers Scorecard translations with the app. Add to your app's `features`.
|
|
192
|
+
| Module | Description |
|
|
193
|
+
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
194
|
+
| `scorecardHomeModule` | Registers Scorecard homepage widgets for the home plugin (`AggregatedCardWithDeprecatedMetricId`, `AggregatedCardWithDefaultAggregation`, `AggregatedCardWithJiraOpenIssues`, and `AggregatedCardWithGithubOpenPrs`). |
|
|
195
|
+
| `scorecardCatalogModule` | Registers the Scorecard entity tab with the catalog plugin. Add to your app's `features`. Which entities show the tab is configured via `app.extensions` (see step 3). |
|
|
196
|
+
| `scorecardTranslationsModule` | Registers Scorecard translations with the app. Add to your app's `features`. |
|
|
177
197
|
|
|
178
198
|
**Extensions**
|
|
179
199
|
|
|
180
200
|
- `api:scorecard` — Scorecard API (provided by the plugin; auto-discovered when the plugin is installed).
|
|
181
201
|
- `entity-content:catalog/entity-content-scorecard` — Scorecard tab on catalog entity pages. Configure with `allowedFilters` in `app.extensions` to limit by kind and optionally type.
|
|
182
|
-
- `home-page-widget:home/scorecard-
|
|
183
|
-
- `home-page-widget:home/scorecard-
|
|
202
|
+
- `home-page-widget:home/scorecard-deprecated-metric-id` — Homepage widget using deprecated metricId property (Jira open issues).
|
|
203
|
+
- `home-page-widget:home/scorecard-default-aggregation` — Homepage widget using default aggregation config (GitHub open PRs).
|
|
204
|
+
- `home-page-widget:home/scorecard-jira-open-issues` — Homepage widget showing Jira open blocking tickets.
|
|
205
|
+
- `home-page-widget:home/scorecard-github-open-prs` — Homepage widget showing GitHub open PRs.
|
|
184
206
|
|
|
185
207
|
#### Legacy app
|
|
186
208
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { HomePageWidgetBlueprint } from '@backstage/plugin-home-react/alpha';
|
|
3
|
-
import {
|
|
3
|
+
import { ScorecardHomepageCardWithProvider } from '../../components/ScorecardHomepageSection/ScorecardHomepageCard.esm.js';
|
|
4
4
|
|
|
5
5
|
const defaultCardLayout = {
|
|
6
6
|
width: {
|
|
@@ -15,16 +15,16 @@ const defaultCardLayout = {
|
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
17
|
function AggregatedCardWithDeprecatedMetricIdContent() {
|
|
18
|
-
return /* @__PURE__ */ jsx(
|
|
18
|
+
return /* @__PURE__ */ jsx(ScorecardHomepageCardWithProvider, { metricId: "jira.open_issues" });
|
|
19
19
|
}
|
|
20
20
|
function AggregatedCardWithDefaultAggregationContent() {
|
|
21
|
-
return /* @__PURE__ */ jsx(
|
|
21
|
+
return /* @__PURE__ */ jsx(ScorecardHomepageCardWithProvider, { aggregationId: "github.open_prs" });
|
|
22
22
|
}
|
|
23
23
|
function AggregatedCardWithJiraOpenIssuesContent() {
|
|
24
|
-
return /* @__PURE__ */ jsx(
|
|
24
|
+
return /* @__PURE__ */ jsx(ScorecardHomepageCardWithProvider, { aggregationId: "openIssuesKpi" });
|
|
25
25
|
}
|
|
26
26
|
function AggregatedCardWithGithubOpenPrsContent() {
|
|
27
|
-
return /* @__PURE__ */ jsx(
|
|
27
|
+
return /* @__PURE__ */ jsx(ScorecardHomepageCardWithProvider, { aggregationId: "openPrsKpi" });
|
|
28
28
|
}
|
|
29
29
|
function BorderlessHomeWidgetRenderer({ Content }) {
|
|
30
30
|
return /* @__PURE__ */ jsx(Content, {});
|
|
@@ -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 {
|
|
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 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"],"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,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;;;;"}
|
|
@@ -6,7 +6,7 @@ const scorecardPage = PageBlueprint.make({
|
|
|
6
6
|
params: {
|
|
7
7
|
path: "/scorecard/aggregations/:aggregationId/metrics/:metricId",
|
|
8
8
|
routeRef: scorecardDrillDownRouteRef,
|
|
9
|
-
loader: () => import('../../pages/ScorecardPage.esm.js').then((m) => /* @__PURE__ */ jsx(m.
|
|
9
|
+
loader: () => import('../../pages/ScorecardPage.esm.js').then((m) => /* @__PURE__ */ jsx(m.ScorecardPageWithProvider, {}))
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
12
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scorecardPage.esm.js","sources":["../../../src/alpha/extensions/scorecardPage.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 { PageBlueprint } from '@backstage/frontend-plugin-api';\nimport { scorecardDrillDownRouteRef } from '../../routes';\n\n/**\n * NFS page extension for the Scorecard drill-down page.\n * @alpha\n */\nexport const scorecardPage = PageBlueprint.make({\n params: {\n path: '/scorecard/aggregations/:aggregationId/metrics/:metricId',\n routeRef: scorecardDrillDownRouteRef,\n loader: () =>\n import('../../pages/ScorecardPage').then(m => <m.
|
|
1
|
+
{"version":3,"file":"scorecardPage.esm.js","sources":["../../../src/alpha/extensions/scorecardPage.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 { PageBlueprint } from '@backstage/frontend-plugin-api';\nimport { scorecardDrillDownRouteRef } from '../../routes';\n\n/**\n * NFS page extension for the Scorecard drill-down page.\n * @alpha\n */\nexport const scorecardPage = PageBlueprint.make({\n params: {\n path: '/scorecard/aggregations/:aggregationId/metrics/:metricId',\n routeRef: scorecardDrillDownRouteRef,\n loader: () =>\n import('../../pages/ScorecardPage').then(m => (\n <m.ScorecardPageWithProvider />\n )),\n },\n});\n"],"names":[],"mappings":";;;;AAuBa,MAAA,aAAA,GAAgB,cAAc,IAAK,CAAA;AAAA,EAC9C,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,0DAAA;AAAA,IACN,QAAU,EAAA,0BAAA;AAAA,IACV,MAAA,EAAQ,MACN,OAAO,kCAA2B,CAAA,CAAE,IAAK,CAAA,CAAA,CAAA,qBACtC,GAAA,CAAA,CAAA,CAAE,yBAAF,EAAA,EAA4B,CAC9B;AAAA;AAEP,CAAC;;;;"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
|
|
4
|
+
|
|
5
|
+
let queryClient;
|
|
6
|
+
function getQueryClient() {
|
|
7
|
+
if (!queryClient) {
|
|
8
|
+
queryClient = new QueryClient({
|
|
9
|
+
defaultOptions: {
|
|
10
|
+
queries: {
|
|
11
|
+
staleTime: 5 * 60 * 1e3,
|
|
12
|
+
// 5 minutes
|
|
13
|
+
gcTime: 5 * 60 * 1e3,
|
|
14
|
+
// 5 minutes
|
|
15
|
+
retry: 1,
|
|
16
|
+
refetchOnWindowFocus: false
|
|
17
|
+
// do not refetch when window regains focus
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return queryClient;
|
|
23
|
+
}
|
|
24
|
+
const ScorecardQueryProvider = ({
|
|
25
|
+
children
|
|
26
|
+
}) => {
|
|
27
|
+
const client = useMemo(() => getQueryClient(), []);
|
|
28
|
+
return /* @__PURE__ */ jsx(QueryClientProvider, { client, children });
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export { ScorecardQueryProvider };
|
|
32
|
+
//# sourceMappingURL=ScorecardQueryProvider.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScorecardQueryProvider.esm.js","sources":["../../src/api/ScorecardQueryProvider.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 { useMemo } from 'react';\nimport type { ReactNode } from 'react';\n\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\n\nlet queryClient: QueryClient | undefined;\n\nfunction getQueryClient() {\n if (!queryClient) {\n queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 5 * 60 * 1000, // 5 minutes\n gcTime: 5 * 60 * 1000, // 5 minutes\n retry: 1,\n refetchOnWindowFocus: false, // do not refetch when window regains focus\n },\n },\n });\n }\n return queryClient;\n}\n\n/**\n * uses a singleton QueryClient to ensure cache is shared across all scorecard components.\n * @public\n */\nexport const ScorecardQueryProvider = ({\n children,\n}: {\n readonly children: ReactNode;\n}) => {\n const client = useMemo(() => getQueryClient(), []);\n\n return <QueryClientProvider client={client}>{children}</QueryClientProvider>;\n};\n"],"names":[],"mappings":";;;;AAqBA,IAAI,WAAA;AAEJ,SAAS,cAAiB,GAAA;AACxB,EAAA,IAAI,CAAC,WAAa,EAAA;AAChB,IAAA,WAAA,GAAc,IAAI,WAAY,CAAA;AAAA,MAC5B,cAAgB,EAAA;AAAA,QACd,OAAS,EAAA;AAAA,UACP,SAAA,EAAW,IAAI,EAAK,GAAA,GAAA;AAAA;AAAA,UACpB,MAAA,EAAQ,IAAI,EAAK,GAAA,GAAA;AAAA;AAAA,UACjB,KAAO,EAAA,CAAA;AAAA,UACP,oBAAsB,EAAA;AAAA;AAAA;AACxB;AACF,KACD,CAAA;AAAA;AAEH,EAAO,OAAA,WAAA;AACT;AAMO,MAAM,yBAAyB,CAAC;AAAA,EACrC;AACF,CAEM,KAAA;AACJ,EAAA,MAAM,SAAS,OAAQ,CAAA,MAAM,cAAe,EAAA,EAAG,EAAE,CAAA;AAEjD,EAAO,uBAAA,GAAA,CAAC,mBAAoB,EAAA,EAAA,MAAA,EAAiB,QAAS,EAAA,CAAA;AACxD;;;;"}
|
package/dist/api/index.esm.js
CHANGED
|
@@ -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\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 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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"}
|
|
@@ -18,7 +18,7 @@ const ErrorStatePanel = ({
|
|
|
18
18
|
data,
|
|
19
19
|
isLoading,
|
|
20
20
|
error: metadataError
|
|
21
|
-
} = useAggregationMetadata(aggregationId);
|
|
21
|
+
} = useAggregationMetadata({ aggregationId });
|
|
22
22
|
const { title: cardTitle, description: cardDescription } = useMetricDisplayLabels({
|
|
23
23
|
id: aggregationId,
|
|
24
24
|
title: data?.title ?? "",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorStatePanel.esm.js","sources":["../../../src/components/ScorecardHomepageSection/ErrorStatePanel.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 { useMemo } from 'react';\nimport { ResponseErrorPanel } from '@backstage/core-components';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { EmptyStatePanel } from './EmptyStatePanel';\nimport { useMetricDisplayLabels } from '../../hooks/useMetricDisplayLabels';\nimport { CardLoading } from '../Common/CardLoading';\nimport { useAggregationMetadata } from '../../hooks/useAggregationMetadata';\n\nexport const ErrorStatePanel = ({\n error,\n aggregationId,\n showSubheader = true,\n cardDataTestId,\n}: {\n error: Error;\n aggregationId: string;\n showSubheader?: boolean;\n cardDataTestId?: string;\n}) => {\n const { t } = useTranslation();\n\n const {\n data,\n isLoading,\n error: metadataError,\n } = useAggregationMetadata(aggregationId);\n\n const { title: cardTitle, description: cardDescription } =\n useMetricDisplayLabels({\n id: aggregationId,\n title: data?.title ?? '',\n description: data?.description ?? '',\n });\n\n const getErrorPanelContent = useMemo(() => {\n const isMissingPermission = error.message?.includes('NotAllowedError');\n if (isMissingPermission) {\n return {\n label: t('errors.missingPermission'),\n tooltipContent: t('errors.missingPermissionMessage'),\n };\n }\n\n const isUserNotFoundInCatalog =\n error.message?.includes('NotFoundError') &&\n error.message?.includes('User entity not found in catalog');\n if (isUserNotFoundInCatalog) {\n return {\n label: t('errors.metricDataUnavailable'),\n tooltipContent: t('errors.userNotFoundInCatalogMessage'),\n };\n }\n\n const isAuthenticationError = error.message?.includes(\n 'AuthenticationError',\n );\n if (isAuthenticationError) {\n return {\n label: t('errors.authenticationError'),\n tooltipContent: t('errors.authenticationErrorMessage'),\n };\n }\n\n return { label: '', tooltipContent: '' };\n }, [error, t]);\n\n if (isLoading) {\n return <CardLoading dataTestId={cardDataTestId} />;\n }\n\n if (metadataError) {\n return <ResponseErrorPanel error={metadataError} />;\n }\n\n const { label, tooltipContent } = getErrorPanelContent;\n\n if (label && tooltipContent) {\n return (\n <EmptyStatePanel\n label={label}\n cardTitle={cardTitle}\n cardDescription={cardDescription}\n tooltipContent={tooltipContent}\n showSubheader={showSubheader}\n dataTestId={cardDataTestId}\n />\n );\n }\n\n return <ResponseErrorPanel error={error} />;\n};\n"],"names":[],"mappings":";;;;;;;;;AAwBO,MAAM,kBAAkB,CAAC;AAAA,EAC9B,KAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAgB,GAAA,IAAA;AAAA,EAChB;AACF,CAKM,KAAA;AACJ,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAE7B,EAAM,MAAA;AAAA,IACJ,IAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAO,EAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"ErrorStatePanel.esm.js","sources":["../../../src/components/ScorecardHomepageSection/ErrorStatePanel.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 { useMemo } from 'react';\nimport { ResponseErrorPanel } from '@backstage/core-components';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { EmptyStatePanel } from './EmptyStatePanel';\nimport { useMetricDisplayLabels } from '../../hooks/useMetricDisplayLabels';\nimport { CardLoading } from '../Common/CardLoading';\nimport { useAggregationMetadata } from '../../hooks/useAggregationMetadata';\n\nexport const ErrorStatePanel = ({\n error,\n aggregationId,\n showSubheader = true,\n cardDataTestId,\n}: {\n error: Error;\n aggregationId: string;\n showSubheader?: boolean;\n cardDataTestId?: string;\n}) => {\n const { t } = useTranslation();\n\n const {\n data,\n isLoading,\n error: metadataError,\n } = useAggregationMetadata({ aggregationId });\n\n const { title: cardTitle, description: cardDescription } =\n useMetricDisplayLabels({\n id: aggregationId,\n title: data?.title ?? '',\n description: data?.description ?? '',\n });\n\n const getErrorPanelContent = useMemo(() => {\n const isMissingPermission = error.message?.includes('NotAllowedError');\n if (isMissingPermission) {\n return {\n label: t('errors.missingPermission'),\n tooltipContent: t('errors.missingPermissionMessage'),\n };\n }\n\n const isUserNotFoundInCatalog =\n error.message?.includes('NotFoundError') &&\n error.message?.includes('User entity not found in catalog');\n if (isUserNotFoundInCatalog) {\n return {\n label: t('errors.metricDataUnavailable'),\n tooltipContent: t('errors.userNotFoundInCatalogMessage'),\n };\n }\n\n const isAuthenticationError = error.message?.includes(\n 'AuthenticationError',\n );\n if (isAuthenticationError) {\n return {\n label: t('errors.authenticationError'),\n tooltipContent: t('errors.authenticationErrorMessage'),\n };\n }\n\n return { label: '', tooltipContent: '' };\n }, [error, t]);\n\n if (isLoading) {\n return <CardLoading dataTestId={cardDataTestId} />;\n }\n\n if (metadataError) {\n return <ResponseErrorPanel error={metadataError} />;\n }\n\n const { label, tooltipContent } = getErrorPanelContent;\n\n if (label && tooltipContent) {\n return (\n <EmptyStatePanel\n label={label}\n cardTitle={cardTitle}\n cardDescription={cardDescription}\n tooltipContent={tooltipContent}\n showSubheader={showSubheader}\n dataTestId={cardDataTestId}\n />\n );\n }\n\n return <ResponseErrorPanel error={error} />;\n};\n"],"names":[],"mappings":";;;;;;;;;AAwBO,MAAM,kBAAkB,CAAC;AAAA,EAC9B,KAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAgB,GAAA,IAAA;AAAA,EAChB;AACF,CAKM,KAAA;AACJ,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAE7B,EAAM,MAAA;AAAA,IACJ,IAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAO,EAAA;AAAA,GACL,GAAA,sBAAA,CAAuB,EAAE,aAAA,EAAe,CAAA;AAE5C,EAAA,MAAM,EAAE,KAAO,EAAA,SAAA,EAAW,WAAa,EAAA,eAAA,KACrC,sBAAuB,CAAA;AAAA,IACrB,EAAI,EAAA,aAAA;AAAA,IACJ,KAAA,EAAO,MAAM,KAAS,IAAA,EAAA;AAAA,IACtB,WAAA,EAAa,MAAM,WAAe,IAAA;AAAA,GACnC,CAAA;AAEH,EAAM,MAAA,oBAAA,GAAuB,QAAQ,MAAM;AACzC,IAAA,MAAM,mBAAsB,GAAA,KAAA,CAAM,OAAS,EAAA,QAAA,CAAS,iBAAiB,CAAA;AACrE,IAAA,IAAI,mBAAqB,EAAA;AACvB,MAAO,OAAA;AAAA,QACL,KAAA,EAAO,EAAE,0BAA0B,CAAA;AAAA,QACnC,cAAA,EAAgB,EAAE,iCAAiC;AAAA,OACrD;AAAA;AAGF,IAAM,MAAA,uBAAA,GACJ,MAAM,OAAS,EAAA,QAAA,CAAS,eAAe,CACvC,IAAA,KAAA,CAAM,OAAS,EAAA,QAAA,CAAS,kCAAkC,CAAA;AAC5D,IAAA,IAAI,uBAAyB,EAAA;AAC3B,MAAO,OAAA;AAAA,QACL,KAAA,EAAO,EAAE,8BAA8B,CAAA;AAAA,QACvC,cAAA,EAAgB,EAAE,qCAAqC;AAAA,OACzD;AAAA;AAGF,IAAM,MAAA,qBAAA,GAAwB,MAAM,OAAS,EAAA,QAAA;AAAA,MAC3C;AAAA,KACF;AACA,IAAA,IAAI,qBAAuB,EAAA;AACzB,MAAO,OAAA;AAAA,QACL,KAAA,EAAO,EAAE,4BAA4B,CAAA;AAAA,QACrC,cAAA,EAAgB,EAAE,mCAAmC;AAAA,OACvD;AAAA;AAGF,IAAA,OAAO,EAAE,KAAA,EAAO,EAAI,EAAA,cAAA,EAAgB,EAAG,EAAA;AAAA,GACtC,EAAA,CAAC,KAAO,EAAA,CAAC,CAAC,CAAA;AAEb,EAAA,IAAI,SAAW,EAAA;AACb,IAAO,uBAAA,GAAA,CAAC,WAAY,EAAA,EAAA,UAAA,EAAY,cAAgB,EAAA,CAAA;AAAA;AAGlD,EAAA,IAAI,aAAe,EAAA;AACjB,IAAO,uBAAA,GAAA,CAAC,kBAAmB,EAAA,EAAA,KAAA,EAAO,aAAe,EAAA,CAAA;AAAA;AAGnD,EAAM,MAAA,EAAE,KAAO,EAAA,cAAA,EAAmB,GAAA,oBAAA;AAElC,EAAA,IAAI,SAAS,cAAgB,EAAA;AAC3B,IACE,uBAAA,GAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,KAAA;AAAA,QACA,SAAA;AAAA,QACA,eAAA;AAAA,QACA,cAAA;AAAA,QACA,aAAA;AAAA,QACA,UAAY,EAAA;AAAA;AAAA,KACd;AAAA;AAIJ,EAAO,uBAAA,GAAA,CAAC,sBAAmB,KAAc,EAAA,CAAA;AAC3C;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import '../../api/index.esm.js';
|
|
2
3
|
import { ScorecardHomepageCardComponent } from './ScorecardHomepageCardComponent.esm.js';
|
|
3
4
|
import { useAggregatedScorecard } from '../../hooks/useAggregatedScorecard.esm.js';
|
|
4
5
|
import { useTranslation } from '../../hooks/useTranslation.esm.js';
|
|
@@ -6,6 +7,7 @@ import { ErrorStatePanel } from './ErrorStatePanel.esm.js';
|
|
|
6
7
|
import { EmptyStatePanel } from './EmptyStatePanel.esm.js';
|
|
7
8
|
import { useMetricDisplayLabels } from '../../hooks/useMetricDisplayLabels.esm.js';
|
|
8
9
|
import { CardLoading } from '../Common/CardLoading.esm.js';
|
|
10
|
+
import { ScorecardQueryProvider } from '../../api/ScorecardQueryProvider.esm.js';
|
|
9
11
|
|
|
10
12
|
const ScorecardHomepageCard = ({
|
|
11
13
|
metricId,
|
|
@@ -15,7 +17,9 @@ const ScorecardHomepageCard = ({
|
|
|
15
17
|
}) => {
|
|
16
18
|
const { t } = useTranslation();
|
|
17
19
|
const resolvedScorecardId = aggregationId || metricId || "";
|
|
18
|
-
const { data, isLoading, error } = useAggregatedScorecard(
|
|
20
|
+
const { data, isLoading, error } = useAggregatedScorecard({
|
|
21
|
+
aggregationId: resolvedScorecardId
|
|
22
|
+
});
|
|
19
23
|
const aggregatedMetricDetails = data ? {
|
|
20
24
|
id: resolvedScorecardId,
|
|
21
25
|
title: data.metadata.title,
|
|
@@ -69,6 +73,7 @@ const ScorecardHomepageCard = ({
|
|
|
69
73
|
data.id
|
|
70
74
|
);
|
|
71
75
|
};
|
|
76
|
+
const ScorecardHomepageCardWithProvider = (props) => /* @__PURE__ */ jsx(ScorecardQueryProvider, { children: /* @__PURE__ */ jsx(ScorecardHomepageCard, { ...props }) });
|
|
72
77
|
|
|
73
|
-
export { ScorecardHomepageCard };
|
|
78
|
+
export { ScorecardHomepageCard, ScorecardHomepageCardWithProvider };
|
|
74
79
|
//# sourceMappingURL=ScorecardHomepageCard.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScorecardHomepageCard.esm.js","sources":["../../../src/components/ScorecardHomepageSection/ScorecardHomepageCard.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 { ScorecardHomepageCardComponent } from './ScorecardHomepageCardComponent';\nimport { useAggregatedScorecard } from '../../hooks/useAggregatedScorecard';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { ErrorStatePanel } from './ErrorStatePanel';\nimport { EmptyStatePanel } from './EmptyStatePanel';\nimport { Metric } from '@red-hat-developer-hub/backstage-plugin-scorecard-common';\nimport { useMetricDisplayLabels } from '../../hooks/useMetricDisplayLabels';\nimport { CardLoading } from '../Common/CardLoading';\n\nexport const ScorecardHomepageCard = ({\n metricId,\n aggregationId,\n showSubheader = true,\n showInfo = true,\n}: {\n metricId?: string;\n aggregationId?: string;\n showSubheader?: boolean;\n showInfo?: boolean;\n}) => {\n const { t } = useTranslation();\n\n // Deprecated logic to support both metricId and aggregationId. Only aggregationId will be used in the future.\n const resolvedScorecardId = aggregationId || metricId || '';\n\n const { data, isLoading, error }
|
|
1
|
+
{"version":3,"file":"ScorecardHomepageCard.esm.js","sources":["../../../src/components/ScorecardHomepageSection/ScorecardHomepageCard.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 { ScorecardQueryProvider } from '../../api';\nimport { ScorecardHomepageCardComponent } from './ScorecardHomepageCardComponent';\nimport { useAggregatedScorecard } from '../../hooks/useAggregatedScorecard';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { ErrorStatePanel } from './ErrorStatePanel';\nimport { EmptyStatePanel } from './EmptyStatePanel';\nimport { Metric } from '@red-hat-developer-hub/backstage-plugin-scorecard-common';\nimport { useMetricDisplayLabels } from '../../hooks/useMetricDisplayLabels';\nimport { CardLoading } from '../Common/CardLoading';\n\nexport const ScorecardHomepageCard = ({\n metricId,\n aggregationId,\n showSubheader = true,\n showInfo = true,\n}: {\n metricId?: string;\n aggregationId?: string;\n showSubheader?: boolean;\n showInfo?: boolean;\n}) => {\n const { t } = useTranslation();\n\n // Deprecated logic to support both metricId and aggregationId. Only aggregationId will be used in the future.\n const resolvedScorecardId = aggregationId || metricId || '';\n\n const { data, isLoading, error } = useAggregatedScorecard({\n aggregationId: resolvedScorecardId,\n });\n\n const aggregatedMetricDetails = data\n ? ({\n id: resolvedScorecardId,\n title: data.metadata.title,\n description: data.metadata.description,\n } as Pick<Metric, 'id' | 'title' | 'description'>)\n : undefined;\n\n const { title, description } = useMetricDisplayLabels(\n aggregatedMetricDetails,\n );\n\n const cardDataTestId = `scorecard-homepage-card-${resolvedScorecardId}`;\n\n if (isLoading) {\n return <CardLoading dataTestId={cardDataTestId} />;\n }\n\n if (error) {\n return (\n <ErrorStatePanel\n error={error}\n showSubheader={showSubheader}\n aggregationId={resolvedScorecardId}\n cardDataTestId={cardDataTestId}\n />\n );\n }\n\n if (!data) {\n return null;\n }\n\n if (data.result?.total === 0) {\n return (\n <EmptyStatePanel\n showSubheader={showSubheader}\n cardTitle={title}\n cardDescription={description}\n label={t('errors.noDataFound')}\n tooltipContent={t('errors.noDataFoundMessage')}\n dataTestId={cardDataTestId}\n />\n );\n }\n\n return (\n <ScorecardHomepageCardComponent\n key={data.id}\n showSubheader={showSubheader}\n showInfo={showInfo}\n cardTitle={title}\n description={description}\n scorecard={data}\n aggregationId={resolvedScorecardId}\n dataTestId={cardDataTestId}\n />\n );\n};\n\n/**\n * ScorecardHomepageCard wrapped with QueryClientProvider so it works\n * when rendered outside a tree that already has a provider (e.g. on the homepage).\n */\nexport const ScorecardHomepageCardWithProvider = (props: {\n metricId?: string;\n aggregationId?: string;\n showSubheader?: boolean;\n showInfo?: boolean;\n}) => (\n <ScorecardQueryProvider>\n <ScorecardHomepageCard {...props} />\n </ScorecardQueryProvider>\n);\n"],"names":[],"mappings":";;;;;;;;;;;AA0BO,MAAM,wBAAwB,CAAC;AAAA,EACpC,QAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAgB,GAAA,IAAA;AAAA,EAChB,QAAW,GAAA;AACb,CAKM,KAAA;AACJ,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAG7B,EAAM,MAAA,mBAAA,GAAsB,iBAAiB,QAAY,IAAA,EAAA;AAEzD,EAAA,MAAM,EAAE,IAAA,EAAM,SAAW,EAAA,KAAA,KAAU,sBAAuB,CAAA;AAAA,IACxD,aAAe,EAAA;AAAA,GAChB,CAAA;AAED,EAAA,MAAM,0BAA0B,IAC3B,GAAA;AAAA,IACC,EAAI,EAAA,mBAAA;AAAA,IACJ,KAAA,EAAO,KAAK,QAAS,CAAA,KAAA;AAAA,IACrB,WAAA,EAAa,KAAK,QAAS,CAAA;AAAA,GAE7B,GAAA,MAAA;AAEJ,EAAM,MAAA,EAAE,KAAO,EAAA,WAAA,EAAgB,GAAA,sBAAA;AAAA,IAC7B;AAAA,GACF;AAEA,EAAM,MAAA,cAAA,GAAiB,2BAA2B,mBAAmB,CAAA,CAAA;AAErE,EAAA,IAAI,SAAW,EAAA;AACb,IAAO,uBAAA,GAAA,CAAC,WAAY,EAAA,EAAA,UAAA,EAAY,cAAgB,EAAA,CAAA;AAAA;AAGlD,EAAA,IAAI,KAAO,EAAA;AACT,IACE,uBAAA,GAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,KAAA;AAAA,QACA,aAAA;AAAA,QACA,aAAe,EAAA,mBAAA;AAAA,QACf;AAAA;AAAA,KACF;AAAA;AAIJ,EAAA,IAAI,CAAC,IAAM,EAAA;AACT,IAAO,OAAA,IAAA;AAAA;AAGT,EAAI,IAAA,IAAA,CAAK,MAAQ,EAAA,KAAA,KAAU,CAAG,EAAA;AAC5B,IACE,uBAAA,GAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,aAAA;AAAA,QACA,SAAW,EAAA,KAAA;AAAA,QACX,eAAiB,EAAA,WAAA;AAAA,QACjB,KAAA,EAAO,EAAE,oBAAoB,CAAA;AAAA,QAC7B,cAAA,EAAgB,EAAE,2BAA2B,CAAA;AAAA,QAC7C,UAAY,EAAA;AAAA;AAAA,KACd;AAAA;AAIJ,EACE,uBAAA,GAAA;AAAA,IAAC,8BAAA;AAAA,IAAA;AAAA,MAEC,aAAA;AAAA,MACA,QAAA;AAAA,MACA,SAAW,EAAA,KAAA;AAAA,MACX,WAAA;AAAA,MACA,SAAW,EAAA,IAAA;AAAA,MACX,aAAe,EAAA,mBAAA;AAAA,MACf,UAAY,EAAA;AAAA,KAAA;AAAA,IAPP,IAAK,CAAA;AAAA,GAQZ;AAEJ;AAMa,MAAA,iCAAA,GAAoC,CAAC,KAMhD,qBAAA,GAAA,CAAC,0BACC,QAAC,kBAAA,GAAA,CAAA,qBAAA,EAAA,EAAuB,GAAG,KAAA,EAAO,CACpC,EAAA;;;;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { ScorecardHomepageCard } from './ScorecardHomepageCard.esm.js';
|
|
1
|
+
export { ScorecardHomepageCard, ScorecardHomepageCardWithProvider } from './ScorecardHomepageCard.esm.js';
|
|
2
2
|
//# sourceMappingURL=index.esm.js.map
|
|
@@ -2,7 +2,15 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useApp } from '@backstage/core-plugin-api';
|
|
3
3
|
import Box from '@mui/material/Box';
|
|
4
4
|
import MuiIcon from '@mui/material/Icon';
|
|
5
|
+
import ScorecardErrorStatusIcon from '@mui/icons-material/DangerousOutlined';
|
|
6
|
+
import ScorecardWarningStatusIcon from '@mui/icons-material/WarningAmber';
|
|
7
|
+
import ScorecardSuccessStatusIcon from '@mui/icons-material/CheckCircleOutline';
|
|
5
8
|
|
|
9
|
+
const builtInIcons = {
|
|
10
|
+
scorecardSuccessStatusIcon: ScorecardSuccessStatusIcon,
|
|
11
|
+
scorecardWarningStatusIcon: ScorecardWarningStatusIcon,
|
|
12
|
+
scorecardErrorStatusIcon: ScorecardErrorStatusIcon
|
|
13
|
+
};
|
|
6
14
|
const ScorecardIcon = ({
|
|
7
15
|
icon,
|
|
8
16
|
size = "small",
|
|
@@ -12,7 +20,7 @@ const ScorecardIcon = ({
|
|
|
12
20
|
if (!icon) {
|
|
13
21
|
return null;
|
|
14
22
|
}
|
|
15
|
-
const SystemIcon = app.getSystemIcon(icon);
|
|
23
|
+
const SystemIcon = app.getSystemIcon(icon) ?? builtInIcons[icon];
|
|
16
24
|
if (SystemIcon) {
|
|
17
25
|
return /* @__PURE__ */ jsx(Box, { sx: { display: "flex", alignItems: "center", ...sx }, children: /* @__PURE__ */ jsx(SystemIcon, { fontSize: size }) });
|
|
18
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScorecardIcon.esm.js","sources":["../../../src/components/ScorecardIcon/ScorecardIcon.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 */\nimport { useApp } from '@backstage/core-plugin-api';\nimport Box from '@mui/material/Box';\nimport MuiIcon from '@mui/material/Icon';\nimport type { SxProps, Theme } from '@mui/material/styles';\n\n/**\n * @public\n */\nexport interface ScorecardIconProps {\n icon: string;\n size?: 'small' | 'medium' | 'large';\n sx?: SxProps<Theme>;\n}\n\n/**\n * @public\n */\nexport const ScorecardIcon = ({\n icon,\n size = 'small',\n sx,\n}: ScorecardIconProps) => {\n const app = useApp();\n if (!icon) {\n return null;\n }\n\n const SystemIcon = app.getSystemIcon(icon);\n if (SystemIcon) {\n return (\n <Box sx={{ display: 'flex', alignItems: 'center', ...sx }}>\n <SystemIcon fontSize={size} />\n </Box>\n );\n }\n\n if (icon.startsWith('<svg')) {\n const svgDataUri = `data:image/svg+xml;base64,${btoa(icon)}`;\n return (\n <MuiIcon fontSize={size} sx={sx}>\n <img src={svgDataUri} alt=\"\" />\n </MuiIcon>\n );\n }\n\n if (\n icon.startsWith('data:') ||\n icon.startsWith('https://') ||\n icon.startsWith('http://') ||\n icon.startsWith('/')\n ) {\n return (\n <MuiIcon fontSize={size} baseClassName=\"material-icons-outlined\" sx={sx}>\n <img src={icon} alt=\"\" height=\"100%\" width=\"100%\" />\n </MuiIcon>\n );\n }\n\n return (\n <MuiIcon fontSize={size} baseClassName=\"material-icons-outlined\" sx={sx}>\n {icon}\n </MuiIcon>\n );\n};\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ScorecardIcon.esm.js","sources":["../../../src/components/ScorecardIcon/ScorecardIcon.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 */\nimport { useApp } from '@backstage/core-plugin-api';\nimport Box from '@mui/material/Box';\nimport MuiIcon from '@mui/material/Icon';\nimport type { SvgIconComponent } from '@mui/icons-material';\nimport type { SxProps, Theme } from '@mui/material/styles';\nimport {\n ScorecardSuccessStatusIcon,\n ScorecardWarningStatusIcon,\n ScorecardErrorStatusIcon,\n} from '../..';\n\nconst builtInIcons: Record<string, SvgIconComponent> = {\n scorecardSuccessStatusIcon: ScorecardSuccessStatusIcon,\n scorecardWarningStatusIcon: ScorecardWarningStatusIcon,\n scorecardErrorStatusIcon: ScorecardErrorStatusIcon,\n};\n\n/**\n * @public\n */\nexport interface ScorecardIconProps {\n icon: string;\n size?: 'small' | 'medium' | 'large';\n sx?: SxProps<Theme>;\n}\n\n/**\n * @public\n */\nexport const ScorecardIcon = ({\n icon,\n size = 'small',\n sx,\n}: ScorecardIconProps) => {\n const app = useApp();\n if (!icon) {\n return null;\n }\n\n const SystemIcon = app.getSystemIcon(icon) ?? builtInIcons[icon];\n if (SystemIcon) {\n return (\n <Box sx={{ display: 'flex', alignItems: 'center', ...sx }}>\n <SystemIcon fontSize={size} />\n </Box>\n );\n }\n\n if (icon.startsWith('<svg')) {\n const svgDataUri = `data:image/svg+xml;base64,${btoa(icon)}`;\n return (\n <MuiIcon fontSize={size} sx={sx}>\n <img src={svgDataUri} alt=\"\" />\n </MuiIcon>\n );\n }\n\n if (\n icon.startsWith('data:') ||\n icon.startsWith('https://') ||\n icon.startsWith('http://') ||\n icon.startsWith('/')\n ) {\n return (\n <MuiIcon fontSize={size} baseClassName=\"material-icons-outlined\" sx={sx}>\n <img src={icon} alt=\"\" height=\"100%\" width=\"100%\" />\n </MuiIcon>\n );\n }\n\n return (\n <MuiIcon fontSize={size} baseClassName=\"material-icons-outlined\" sx={sx}>\n {icon}\n </MuiIcon>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AA0BA,MAAM,YAAiD,GAAA;AAAA,EACrD,0BAA4B,EAAA,0BAAA;AAAA,EAC5B,0BAA4B,EAAA,0BAAA;AAAA,EAC5B,wBAA0B,EAAA;AAC5B,CAAA;AAcO,MAAM,gBAAgB,CAAC;AAAA,EAC5B,IAAA;AAAA,EACA,IAAO,GAAA,OAAA;AAAA,EACP;AACF,CAA0B,KAAA;AACxB,EAAA,MAAM,MAAM,MAAO,EAAA;AACnB,EAAA,IAAI,CAAC,IAAM,EAAA;AACT,IAAO,OAAA,IAAA;AAAA;AAGT,EAAA,MAAM,aAAa,GAAI,CAAA,aAAA,CAAc,IAAI,CAAA,IAAK,aAAa,IAAI,CAAA;AAC/D,EAAA,IAAI,UAAY,EAAA;AACd,IAAA,uBACG,GAAA,CAAA,GAAA,EAAA,EAAI,EAAI,EAAA,EAAE,SAAS,MAAQ,EAAA,UAAA,EAAY,QAAU,EAAA,GAAG,IACnD,EAAA,QAAA,kBAAA,GAAA,CAAC,UAAW,EAAA,EAAA,QAAA,EAAU,MAAM,CAC9B,EAAA,CAAA;AAAA;AAIJ,EAAI,IAAA,IAAA,CAAK,UAAW,CAAA,MAAM,CAAG,EAAA;AAC3B,IAAA,MAAM,UAAa,GAAA,CAAA,0BAAA,EAA6B,IAAK,CAAA,IAAI,CAAC,CAAA,CAAA;AAC1D,IACE,uBAAA,GAAA,CAAC,OAAQ,EAAA,EAAA,QAAA,EAAU,IAAM,EAAA,EAAA,EACvB,QAAC,kBAAA,GAAA,CAAA,KAAA,EAAA,EAAI,GAAK,EAAA,UAAA,EAAY,GAAI,EAAA,EAAA,EAAG,CAC/B,EAAA,CAAA;AAAA;AAIJ,EAAA,IACE,IAAK,CAAA,UAAA,CAAW,OAAO,CAAA,IACvB,KAAK,UAAW,CAAA,UAAU,CAC1B,IAAA,IAAA,CAAK,WAAW,SAAS,CAAA,IACzB,IAAK,CAAA,UAAA,CAAW,GAAG,CACnB,EAAA;AACA,IAAA,2BACG,OAAQ,EAAA,EAAA,QAAA,EAAU,IAAM,EAAA,aAAA,EAAc,2BAA0B,EAC/D,EAAA,QAAA,kBAAA,GAAA,CAAC,KAAI,EAAA,EAAA,GAAA,EAAK,MAAM,GAAI,EAAA,EAAA,EAAG,QAAO,MAAO,EAAA,KAAA,EAAM,QAAO,CACpD,EAAA,CAAA;AAAA;AAIJ,EAAA,2BACG,OAAQ,EAAA,EAAA,QAAA,EAAU,MAAM,aAAc,EAAA,yBAAA,EAA0B,IAC9D,QACH,EAAA,IAAA,EAAA,CAAA;AAEJ;;;;"}
|
|
@@ -2,8 +2,9 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import TableRow from '@mui/material/TableRow';
|
|
3
3
|
import TableCell from '@mui/material/TableCell';
|
|
4
4
|
import { useTheme } from '@mui/material/styles';
|
|
5
|
+
import { SCORECARD_ERROR_STATE_COLOR } from '../../../utils/constants.esm.js';
|
|
5
6
|
import { getLastUpdatedLabel } from '../../../utils/entityTableUtils.esm.js';
|
|
6
|
-
import '
|
|
7
|
+
import { getThresholdRuleColor } from '../../../utils/thresholdUtils.esm.js';
|
|
7
8
|
import { useTranslation } from '../../../hooks/useTranslation.esm.js';
|
|
8
9
|
import { useLanguage } from '../../../hooks/useLanguage.esm.js';
|
|
9
10
|
import { MetricStatusCell } from './cells/MetricStatusCell.esm.js';
|
|
@@ -12,11 +13,13 @@ import { EntityNameCell } from './cells/EntityNameCell.esm.js';
|
|
|
12
13
|
|
|
13
14
|
const EntitiesRow = ({
|
|
14
15
|
entity,
|
|
15
|
-
entityMetadataMap
|
|
16
|
+
entityMetadataMap,
|
|
17
|
+
thresholdRules
|
|
16
18
|
}) => {
|
|
17
19
|
const theme = useTheme();
|
|
18
20
|
const { t } = useTranslation();
|
|
19
21
|
const locale = useLanguage();
|
|
22
|
+
const statusColor = getThresholdRuleColor(thresholdRules, entity?.status ?? "") ?? SCORECARD_ERROR_STATE_COLOR;
|
|
20
23
|
return /* @__PURE__ */ jsxs(
|
|
21
24
|
TableRow,
|
|
22
25
|
{
|
|
@@ -25,7 +28,14 @@ const EntitiesRow = ({
|
|
|
25
28
|
borderBottom: (muiTheme) => `1px solid ${muiTheme.palette.grey[300]}`
|
|
26
29
|
},
|
|
27
30
|
children: [
|
|
28
|
-
/* @__PURE__ */ jsx(TableCell, { width: "12%", children: /* @__PURE__ */ jsx(
|
|
31
|
+
/* @__PURE__ */ jsx(TableCell, { width: "12%", children: /* @__PURE__ */ jsx(
|
|
32
|
+
MetricStatusCell,
|
|
33
|
+
{
|
|
34
|
+
status: entity?.status ?? void 0,
|
|
35
|
+
theme,
|
|
36
|
+
statusColor
|
|
37
|
+
}
|
|
38
|
+
) }),
|
|
29
39
|
/* @__PURE__ */ jsx(TableCell, { width: "8%", children: entity.metricValue || entity.metricValue === 0 ? entity.metricValue : t("entitiesPage.entitiesTable.unavailable") }),
|
|
30
40
|
/* @__PURE__ */ jsx(TableCell, { width: "28%", children: /* @__PURE__ */ jsx(
|
|
31
41
|
EntityNameCell,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntitiesRow.esm.js","sources":["../../../../src/components/ScorecardPage/EntitiesTable/EntitiesRow.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 type {
|
|
1
|
+
{"version":3,"file":"EntitiesRow.esm.js","sources":["../../../../src/components/ScorecardPage/EntitiesTable/EntitiesRow.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 type {\n EntityMetricDetail,\n ThresholdRule,\n} from '@red-hat-developer-hub/backstage-plugin-scorecard-common';\n\nimport TableRow from '@mui/material/TableRow';\nimport TableCell from '@mui/material/TableCell';\nimport { useTheme } from '@mui/material/styles';\n\nimport {\n getLastUpdatedLabel,\n getThresholdRuleColor,\n SCORECARD_ERROR_STATE_COLOR,\n} from '../../../utils';\nimport { useTranslation } from '../../../hooks/useTranslation';\nimport { EntityMetadataMap } from '../../../components/types';\nimport { useLanguage } from '../../../hooks/useLanguage';\n\nimport { MetricStatusCell } from './cells/MetricStatusCell';\nimport { OwnerCell } from './cells/OwnerCell';\nimport { EntityNameCell } from './cells/EntityNameCell';\n\nexport const EntitiesRow = ({\n entity,\n entityMetadataMap,\n thresholdRules,\n}: {\n entity: EntityMetricDetail;\n entityMetadataMap: EntityMetadataMap;\n thresholdRules: ThresholdRule[];\n}) => {\n const theme = useTheme();\n const { t } = useTranslation();\n const locale = useLanguage();\n\n const statusColor =\n getThresholdRuleColor(thresholdRules, entity?.status ?? '') ??\n SCORECARD_ERROR_STATE_COLOR;\n\n return (\n <TableRow\n key={entity.entityRef}\n sx={{\n '&:nth-of-type(odd)': { backgroundColor: 'inherit' },\n borderBottom: (muiTheme: any) =>\n `1px solid ${muiTheme.palette.grey[300]}`,\n }}\n >\n <TableCell width=\"12%\">\n <MetricStatusCell\n status={entity?.status ?? undefined}\n theme={theme}\n statusColor={statusColor}\n />\n </TableCell>\n\n <TableCell width=\"8%\">\n {entity.metricValue || entity.metricValue === 0\n ? entity.metricValue\n : t('entitiesPage.entitiesTable.unavailable')}\n </TableCell>\n\n <TableCell width=\"28%\">\n <EntityNameCell\n entityRef={entity.entityRef}\n entityMetadata={entityMetadataMap[entity.entityRef]}\n />\n </TableCell>\n\n <TableCell width=\"20%\">\n <OwnerCell ownerRef={entity.owner} />\n </TableCell>\n\n <TableCell width=\"12%\">{entity.entityKind}</TableCell>\n\n <TableCell width=\"20%\">\n {entity.timestamp\n ? getLastUpdatedLabel(entity.timestamp, locale)\n : '--'}\n </TableCell>\n </TableRow>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;AAsCO,MAAM,cAAc,CAAC;AAAA,EAC1B,MAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAIM,KAAA;AACJ,EAAA,MAAM,QAAQ,QAAS,EAAA;AACvB,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAC7B,EAAA,MAAM,SAAS,WAAY,EAAA;AAE3B,EAAA,MAAM,cACJ,qBAAsB,CAAA,cAAA,EAAgB,MAAQ,EAAA,MAAA,IAAU,EAAE,CAC1D,IAAA,2BAAA;AAEF,EACE,uBAAA,IAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MAEC,EAAI,EAAA;AAAA,QACF,oBAAA,EAAsB,EAAE,eAAA,EAAiB,SAAU,EAAA;AAAA,QACnD,YAAA,EAAc,CAAC,QACb,KAAA,CAAA,UAAA,EAAa,SAAS,OAAQ,CAAA,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,OAC3C;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAC,GAAA,CAAA,SAAA,EAAA,EAAU,OAAM,KACf,EAAA,QAAA,kBAAA,GAAA;AAAA,UAAC,gBAAA;AAAA,UAAA;AAAA,YACC,MAAA,EAAQ,QAAQ,MAAU,IAAA,MAAA;AAAA,YAC1B,KAAA;AAAA,YACA;AAAA;AAAA,SAEJ,EAAA,CAAA;AAAA,wBAEC,GAAA,CAAA,SAAA,EAAA,EAAU,KAAM,EAAA,IAAA,EACd,QAAO,EAAA,MAAA,CAAA,WAAA,IAAe,MAAO,CAAA,WAAA,KAAgB,CAC1C,GAAA,MAAA,CAAO,WACP,GAAA,CAAA,CAAE,wCAAwC,CAChD,EAAA,CAAA;AAAA,wBAEA,GAAA,CAAC,SAAU,EAAA,EAAA,KAAA,EAAM,KACf,EAAA,QAAA,kBAAA,GAAA;AAAA,UAAC,cAAA;AAAA,UAAA;AAAA,YACC,WAAW,MAAO,CAAA,SAAA;AAAA,YAClB,cAAA,EAAgB,iBAAkB,CAAA,MAAA,CAAO,SAAS;AAAA;AAAA,SAEtD,EAAA,CAAA;AAAA,wBAEA,GAAA,CAAC,aAAU,KAAM,EAAA,KAAA,EACf,8BAAC,SAAU,EAAA,EAAA,QAAA,EAAU,MAAO,CAAA,KAAA,EAAO,CACrC,EAAA,CAAA;AAAA,wBAEC,GAAA,CAAA,SAAA,EAAA,EAAU,KAAM,EAAA,KAAA,EAAO,iBAAO,UAAW,EAAA,CAAA;AAAA,wBAE1C,GAAA,CAAC,SAAU,EAAA,EAAA,KAAA,EAAM,KACd,EAAA,QAAA,EAAA,MAAA,CAAO,SACJ,GAAA,mBAAA,CAAoB,MAAO,CAAA,SAAA,EAAW,MAAM,CAAA,GAC5C,IACN,EAAA;AAAA;AAAA,KAAA;AAAA,IAtCK,MAAO,CAAA;AAAA,GAuCd;AAEJ;;;;"}
|