@backstage-community/plugin-cost-insights 0.26.0 → 0.28.0

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.
Files changed (158) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/alerts/ProjectGrowthAlert.esm.js.map +1 -1
  3. package/dist/alerts/UnlabeledDataflowAlert.esm.js.map +1 -1
  4. package/dist/alpha/plugin.esm.js +2 -1
  5. package/dist/alpha/plugin.esm.js.map +1 -1
  6. package/dist/alpha/router.esm.js +1 -0
  7. package/dist/alpha/router.esm.js.map +1 -1
  8. package/dist/alpha.d.ts +31 -10
  9. package/dist/api/CostInsightsApi.esm.js.map +1 -1
  10. package/dist/components/ActionItems/ActionItemCard.esm.js.map +1 -1
  11. package/dist/components/ActionItems/ActionItems.esm.js.map +1 -1
  12. package/dist/components/AlertInsights/AlertDialog.esm.js.map +1 -1
  13. package/dist/components/AlertInsights/AlertInsights.esm.js.map +1 -1
  14. package/dist/components/AlertInsights/AlertInsightsHeader.esm.js.map +1 -1
  15. package/dist/components/AlertInsights/AlertInsightsSection.esm.js.map +1 -1
  16. package/dist/components/AlertInsights/AlertInsightsSectionHeader.esm.js.map +1 -1
  17. package/dist/components/AlertInsights/AlertStatusSummary.esm.js.map +1 -1
  18. package/dist/components/AlertInsights/AlertStatusSummaryButton.esm.js.map +1 -1
  19. package/dist/components/AlertInstructionsLayout/AlertInstructionsLayout.esm.js.map +1 -1
  20. package/dist/components/BarChart/BarChart.esm.js.map +1 -1
  21. package/dist/components/BarChart/BarChartLabel.esm.js.map +1 -1
  22. package/dist/components/BarChart/BarChartLegend.esm.js.map +1 -1
  23. package/dist/components/BarChart/BarChartStepper.esm.js.map +1 -1
  24. package/dist/components/BarChart/BarChartStepperButton.esm.js.map +1 -1
  25. package/dist/components/BarChart/BarChartSteps.esm.js.map +1 -1
  26. package/dist/components/BarChart/BarChartTick.esm.js.map +1 -1
  27. package/dist/components/BarChart/BarChartTooltip.esm.js.map +1 -1
  28. package/dist/components/BarChart/BarChartTooltipItem.esm.js.map +1 -1
  29. package/dist/components/CopyUrlToClipboard/CopyUrlToClipboard.esm.js.map +1 -1
  30. package/dist/components/CostGrowth/CostGrowth.esm.js +11 -2
  31. package/dist/components/CostGrowth/CostGrowth.esm.js.map +1 -1
  32. package/dist/components/CostGrowth/CostGrowthIndicator.esm.js.map +1 -1
  33. package/dist/components/CostInsightsHeader/CostInsightsHeader.esm.js.map +1 -1
  34. package/dist/components/CostInsightsLayout/CostInsightsLayout.esm.js.map +1 -1
  35. package/dist/components/CostInsightsNavigation/CostInsightsNavigation.esm.js.map +1 -1
  36. package/dist/components/CostInsightsPage/CostInsightsPage.esm.js +5 -1
  37. package/dist/components/CostInsightsPage/CostInsightsPage.esm.js.map +1 -1
  38. package/dist/components/CostInsightsPage/CostInsightsPageRoot.esm.js.map +1 -1
  39. package/dist/components/CostInsightsPage/CostInsightsThemeProvider.esm.js.map +1 -1
  40. package/dist/components/CostInsightsPage/index.esm.js +5 -1
  41. package/dist/components/CostInsightsPage/index.esm.js.map +1 -1
  42. package/dist/components/CostInsightsPage/selector.esm.js +1 -1
  43. package/dist/components/CostInsightsPage/selector.esm.js.map +1 -1
  44. package/dist/components/CostInsightsTabs/CostInsightsTabs.esm.js.map +1 -1
  45. package/dist/components/CostInsightsTabs/selector.esm.js.map +1 -1
  46. package/dist/components/CostOverviewCard/CostOverviewBreakdownChart.esm.js +20 -6
  47. package/dist/components/CostOverviewCard/CostOverviewBreakdownChart.esm.js.map +1 -1
  48. package/dist/components/CostOverviewCard/CostOverviewCard.esm.js +17 -4
  49. package/dist/components/CostOverviewCard/CostOverviewCard.esm.js.map +1 -1
  50. package/dist/components/CostOverviewCard/CostOverviewChart.esm.js +1 -1
  51. package/dist/components/CostOverviewCard/CostOverviewChart.esm.js.map +1 -1
  52. package/dist/components/CostOverviewCard/CostOverviewHeader.esm.js.map +1 -1
  53. package/dist/components/CostOverviewCard/CostOverviewLegend.esm.js +11 -3
  54. package/dist/components/CostOverviewCard/CostOverviewLegend.esm.js.map +1 -1
  55. package/dist/components/CostOverviewCard/selector.esm.js +3 -2
  56. package/dist/components/CostOverviewCard/selector.esm.js.map +1 -1
  57. package/dist/components/CurrencySelect/CurrencySelect.esm.js.map +1 -1
  58. package/dist/components/EntityCosts/EntityCosts.esm.js +5 -1
  59. package/dist/components/EntityCosts/EntityCosts.esm.js.map +1 -1
  60. package/dist/components/EntityCosts/index.esm.js +5 -1
  61. package/dist/components/EntityCosts/index.esm.js.map +1 -1
  62. package/dist/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.esm.js.map +1 -1
  63. package/dist/components/LabelDataflowInstructionsPage/index.esm.js +5 -1
  64. package/dist/components/LabelDataflowInstructionsPage/index.esm.js.map +1 -1
  65. package/dist/components/LegendItem/LegendItem.esm.js.map +1 -1
  66. package/dist/components/MetricSelect/MetricSelect.esm.js.map +1 -1
  67. package/dist/components/PeriodSelect/DateRangePicker.esm.js +218 -0
  68. package/dist/components/PeriodSelect/DateRangePicker.esm.js.map +1 -0
  69. package/dist/components/ProductInsights/ProductInsights.esm.js +9 -2
  70. package/dist/components/ProductInsights/ProductInsights.esm.js.map +1 -1
  71. package/dist/components/ProductInsightsCard/ProductEntityDialog.esm.js.map +1 -1
  72. package/dist/components/ProductInsightsCard/ProductEntityTable.esm.js.map +1 -1
  73. package/dist/components/ProductInsightsCard/ProductInsightsCard.esm.js +32 -8
  74. package/dist/components/ProductInsightsCard/ProductInsightsCard.esm.js.map +1 -1
  75. package/dist/components/ProductInsightsCard/ProductInsightsCardList.esm.js.map +1 -1
  76. package/dist/components/ProductInsightsCard/ProductInsightsChart.esm.js +24 -4
  77. package/dist/components/ProductInsightsCard/ProductInsightsChart.esm.js.map +1 -1
  78. package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.esm.js.map +1 -1
  79. package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertChart.esm.js.map +1 -1
  80. package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js +1 -1
  81. package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js.map +1 -1
  82. package/dist/components/ProjectGrowthInstructionsPage/index.esm.js +5 -1
  83. package/dist/components/ProjectGrowthInstructionsPage/index.esm.js.map +1 -1
  84. package/dist/components/ProjectSelect/ProjectSelect.esm.js.map +1 -1
  85. package/dist/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.esm.js.map +1 -1
  86. package/dist/components/WhyCostsMatter/WhyCostsMatter.esm.js.map +1 -1
  87. package/dist/example/alerts/KubernetesMigrationAlert.esm.js.map +1 -1
  88. package/dist/example/client.esm.js +1 -1
  89. package/dist/example/client.esm.js.map +1 -1
  90. package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.esm.js.map +1 -1
  91. package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.esm.js +1 -0
  92. package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.esm.js.map +1 -1
  93. package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.esm.js +1 -0
  94. package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.esm.js.map +1 -1
  95. package/dist/example/forms/KubernetesMigrationDismissForm.esm.js.map +1 -1
  96. package/dist/forms/AlertAcceptForm.esm.js.map +1 -1
  97. package/dist/forms/AlertDismissForm.esm.js.map +1 -1
  98. package/dist/forms/AlertSnoozeForm.esm.js.map +1 -1
  99. package/dist/hooks/useConfig.esm.js +2 -2
  100. package/dist/hooks/useConfig.esm.js.map +1 -1
  101. package/dist/hooks/useCurrency.esm.js +1 -1
  102. package/dist/hooks/useCurrency.esm.js.map +1 -1
  103. package/dist/hooks/useFilters.esm.js +1 -1
  104. package/dist/hooks/useFilters.esm.js.map +1 -1
  105. package/dist/hooks/useGroups.esm.js +1 -1
  106. package/dist/hooks/useGroups.esm.js.map +1 -1
  107. package/dist/hooks/useLastCompleteBillingDate.esm.js +1 -1
  108. package/dist/hooks/useLastCompleteBillingDate.esm.js.map +1 -1
  109. package/dist/hooks/useLoading.esm.js +1 -1
  110. package/dist/hooks/useLoading.esm.js.map +1 -1
  111. package/dist/hooks/useScroll.esm.js +1 -1
  112. package/dist/hooks/useScroll.esm.js.map +1 -1
  113. package/dist/index.d.ts +16 -2
  114. package/dist/index.esm.js +1 -0
  115. package/dist/index.esm.js.map +1 -1
  116. package/dist/plugin.esm.js +1 -1
  117. package/dist/plugin.esm.js.map +1 -1
  118. package/dist/routes.esm.js.map +1 -1
  119. package/dist/testUtils/filters.esm.js.map +1 -1
  120. package/dist/testUtils/loading.esm.js.map +1 -1
  121. package/dist/testUtils/mockData.esm.js.map +1 -1
  122. package/dist/testUtils/products.esm.js.map +1 -1
  123. package/dist/testUtils/providers.esm.js.map +1 -1
  124. package/dist/testUtils/testUtils.esm.js +30 -11
  125. package/dist/testUtils/testUtils.esm.js.map +1 -1
  126. package/dist/types/Alert.esm.js.map +1 -1
  127. package/dist/types/ChangeStatistic.esm.js.map +1 -1
  128. package/dist/types/CurrencyType.esm.js.map +1 -1
  129. package/dist/types/DateFormat.esm.js.map +1 -1
  130. package/dist/types/Duration.esm.js +1 -0
  131. package/dist/types/Duration.esm.js.map +1 -1
  132. package/dist/types/Icon.esm.js.map +1 -1
  133. package/dist/utils/alerts.esm.js.map +1 -1
  134. package/dist/utils/assert.esm.js.map +1 -1
  135. package/dist/utils/change.esm.js +20 -6
  136. package/dist/utils/change.esm.js.map +1 -1
  137. package/dist/utils/charts.esm.js.map +1 -1
  138. package/dist/utils/config.esm.js.map +1 -1
  139. package/dist/utils/currency.esm.js +6 -1
  140. package/dist/utils/currency.esm.js.map +1 -1
  141. package/dist/utils/duration.esm.js +41 -5
  142. package/dist/utils/duration.esm.js.map +1 -1
  143. package/dist/utils/filters.esm.js.map +1 -1
  144. package/dist/utils/formatters.esm.js +25 -4
  145. package/dist/utils/formatters.esm.js.map +1 -1
  146. package/dist/utils/grammar.esm.js.map +1 -1
  147. package/dist/utils/graphs.esm.js +1 -1
  148. package/dist/utils/graphs.esm.js.map +1 -1
  149. package/dist/utils/history.esm.js.map +1 -1
  150. package/dist/utils/loading.esm.js.map +1 -1
  151. package/dist/utils/navigation.esm.js.map +1 -1
  152. package/dist/utils/scroll.esm.js.map +1 -1
  153. package/dist/utils/sort.esm.js.map +1 -1
  154. package/dist/utils/styles.esm.js.map +1 -1
  155. package/dist/utils/sum.esm.js.map +1 -1
  156. package/package.json +15 -13
  157. package/dist/components/PeriodSelect/PeriodSelect.esm.js +0 -72
  158. package/dist/components/PeriodSelect/PeriodSelect.esm.js.map +0 -1
@@ -16,7 +16,7 @@ import '../hooks/useLoading.esm.js';
16
16
  import '../hooks/useScroll.esm.js';
17
17
  import '../hooks/useLastCompleteBillingDate.esm.js';
18
18
  import '../utils/currency.esm.js';
19
- import { aggregationFor, changeOf, trendlineOf, getGroupedProducts, getGroupedProjects, entityOf } from '../testUtils/testUtils.esm.js';
19
+ import { aggregationFor, trendlineOf, changeOf, getGroupedProjects, getGroupedProducts, entityOf } from '../testUtils/testUtils.esm.js';
20
20
 
21
21
  class ExampleCostInsightsClient {
22
22
  request(_, res) {
@@ -1 +1 @@
1
- {"version":3,"file":"client.esm.js","sources":["../../src/example/client.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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/* eslint-disable no-restricted-imports */\n\nimport { DateTime } from 'luxon';\nimport { CostInsightsApi, ProductInsightsOptions } from '../api';\nimport {\n Alert,\n DEFAULT_DATE_FORMAT,\n ProjectGrowthData,\n UnlabeledDataflowData,\n} from '../types';\nimport {\n Entity,\n Group,\n MetricData,\n Project,\n Cost,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { KubernetesMigrationAlert } from './alerts';\nimport { ProjectGrowthAlert, UnlabeledDataflowAlert } from '../alerts';\nimport {\n aggregationFor,\n changeOf,\n entityOf,\n getGroupedProducts,\n getGroupedProjects,\n trendlineOf,\n} from '../testUtils';\n\n/** @public */\nexport class ExampleCostInsightsClient implements CostInsightsApi {\n private request(_: any, res: any): Promise<any> {\n return new Promise(resolve => setTimeout(resolve, 0, res));\n }\n\n getLastCompleteBillingDate(): Promise<string> {\n return Promise.resolve(\n DateTime.now().minus({ days: 1 }).toFormat(DEFAULT_DATE_FORMAT),\n );\n }\n\n async getUserGroups(userId: string): Promise<Group[]> {\n const groups: Group[] = await this.request({ userId }, [\n { id: 'group-a', name: 'Group A' },\n { id: 'group-b', name: 'Group B' },\n ]);\n\n return groups;\n }\n\n async getGroupProjects(group: string): Promise<Project[]> {\n const projects: Project[] = await this.request({ group }, [\n { id: 'project-a' },\n { id: 'project-b' },\n { id: 'project-c' },\n ]);\n\n return projects;\n }\n\n async getDailyMetricData(\n metric: string,\n intervals: string,\n ): Promise<MetricData> {\n const aggregation = aggregationFor(intervals, 100_000).map(entry => ({\n ...entry,\n amount: Math.round(entry.amount),\n }));\n\n const cost: MetricData = await this.request(\n { metric, intervals },\n {\n format: 'number',\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n },\n );\n\n return cost;\n }\n\n async getCatalogEntityDailyCost(\n entityRef: string,\n intervals: string,\n ): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 8_000);\n const groupDailyCost: Cost = await this.request(\n { entityRef, intervals },\n {\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily cost grouped by cloud product OR by project / billing account.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n project: getGroupedProjects(intervals),\n },\n },\n );\n\n return groupDailyCost;\n }\n\n async getGroupDailyCost(group: string, intervals: string): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 8_000);\n const groupDailyCost: Cost = await this.request(\n { group, intervals },\n {\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily cost grouped by cloud product OR by project / billing account.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n project: getGroupedProjects(intervals),\n },\n },\n );\n\n return groupDailyCost;\n }\n\n async getProjectDailyCost(project: string, intervals: string): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 1_500);\n const projectDailyCost: Cost = await this.request(\n { project, intervals },\n {\n id: 'project-a',\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily project cost grouped by cloud product.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n },\n },\n );\n\n return projectDailyCost;\n }\n\n async getProductInsights(options: ProductInsightsOptions): Promise<Entity> {\n const productInsights: Entity = await this.request(\n options,\n entityOf(options.product),\n );\n\n return productInsights;\n }\n\n async getAlerts(group: string): Promise<Alert[]> {\n const projectGrowthData: ProjectGrowthData = {\n project: 'example-project',\n periodStart: '2020-Q2',\n periodEnd: '2020-Q3',\n aggregation: [60_000, 120_000],\n change: {\n ratio: 1,\n amount: 60_000,\n },\n products: [\n { id: 'Compute Engine', aggregation: [58_000, 118_000] },\n { id: 'Cloud Dataflow', aggregation: [1200, 1500] },\n { id: 'Cloud Storage', aggregation: [800, 500] },\n ],\n };\n\n const unlabeledDataflowData: UnlabeledDataflowData = {\n periodStart: '2020-09-01',\n periodEnd: '2020-09-30',\n labeledCost: 6_200,\n unlabeledCost: 7_000,\n projects: [\n {\n id: 'example-project-1',\n unlabeledCost: 5_000,\n labeledCost: 3_000,\n },\n {\n id: 'example-project-2',\n unlabeledCost: 2_000,\n labeledCost: 3_200,\n },\n ],\n };\n\n const today = DateTime.now();\n const alerts: Alert[] = await this.request({ group }, [\n new ProjectGrowthAlert(projectGrowthData),\n new UnlabeledDataflowAlert(unlabeledDataflowData),\n new KubernetesMigrationAlert(this, {\n startDate: today.minus({ days: 30 }).toFormat(DEFAULT_DATE_FORMAT),\n endDate: today.toFormat(DEFAULT_DATE_FORMAT),\n change: {\n ratio: 0,\n amount: 0,\n },\n services: [\n {\n id: 'service-a',\n aggregation: [20_000, 10_000],\n change: {\n ratio: -0.5,\n amount: -10_000,\n },\n entities: {},\n },\n {\n id: 'service-b',\n aggregation: [30_000, 15_000],\n change: {\n ratio: -0.5,\n amount: -15_000,\n },\n entities: {},\n },\n ],\n }),\n ]);\n\n return alerts;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.esm.js","sources":["../../src/example/client.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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/* eslint-disable no-restricted-imports */\n\nimport { DateTime } from 'luxon';\nimport { CostInsightsApi, ProductInsightsOptions } from '../api';\nimport {\n Alert,\n DEFAULT_DATE_FORMAT,\n ProjectGrowthData,\n UnlabeledDataflowData,\n} from '../types';\nimport {\n Entity,\n Group,\n MetricData,\n Project,\n Cost,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { KubernetesMigrationAlert } from './alerts';\nimport { ProjectGrowthAlert, UnlabeledDataflowAlert } from '../alerts';\nimport {\n aggregationFor,\n changeOf,\n entityOf,\n getGroupedProducts,\n getGroupedProjects,\n trendlineOf,\n} from '../testUtils';\n\n/** @public */\nexport class ExampleCostInsightsClient implements CostInsightsApi {\n private request(_: any, res: any): Promise<any> {\n return new Promise(resolve => setTimeout(resolve, 0, res));\n }\n\n getLastCompleteBillingDate(): Promise<string> {\n return Promise.resolve(\n DateTime.now().minus({ days: 1 }).toFormat(DEFAULT_DATE_FORMAT),\n );\n }\n\n async getUserGroups(userId: string): Promise<Group[]> {\n const groups: Group[] = await this.request({ userId }, [\n { id: 'group-a', name: 'Group A' },\n { id: 'group-b', name: 'Group B' },\n ]);\n\n return groups;\n }\n\n async getGroupProjects(group: string): Promise<Project[]> {\n const projects: Project[] = await this.request({ group }, [\n { id: 'project-a' },\n { id: 'project-b' },\n { id: 'project-c' },\n ]);\n\n return projects;\n }\n\n async getDailyMetricData(\n metric: string,\n intervals: string,\n ): Promise<MetricData> {\n const aggregation = aggregationFor(intervals, 100_000).map(entry => ({\n ...entry,\n amount: Math.round(entry.amount),\n }));\n\n const cost: MetricData = await this.request(\n { metric, intervals },\n {\n format: 'number',\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n },\n );\n\n return cost;\n }\n\n async getCatalogEntityDailyCost(\n entityRef: string,\n intervals: string,\n ): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 8_000);\n const groupDailyCost: Cost = await this.request(\n { entityRef, intervals },\n {\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily cost grouped by cloud product OR by project / billing account.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n project: getGroupedProjects(intervals),\n },\n },\n );\n\n return groupDailyCost;\n }\n\n async getGroupDailyCost(group: string, intervals: string): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 8_000);\n const groupDailyCost: Cost = await this.request(\n { group, intervals },\n {\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily cost grouped by cloud product OR by project / billing account.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n project: getGroupedProjects(intervals),\n },\n },\n );\n\n return groupDailyCost;\n }\n\n async getProjectDailyCost(project: string, intervals: string): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 1_500);\n const projectDailyCost: Cost = await this.request(\n { project, intervals },\n {\n id: 'project-a',\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily project cost grouped by cloud product.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n },\n },\n );\n\n return projectDailyCost;\n }\n\n async getProductInsights(options: ProductInsightsOptions): Promise<Entity> {\n const productInsights: Entity = await this.request(\n options,\n entityOf(options.product),\n );\n\n return productInsights;\n }\n\n async getAlerts(group: string): Promise<Alert[]> {\n const projectGrowthData: ProjectGrowthData = {\n project: 'example-project',\n periodStart: '2020-Q2',\n periodEnd: '2020-Q3',\n aggregation: [60_000, 120_000],\n change: {\n ratio: 1,\n amount: 60_000,\n },\n products: [\n { id: 'Compute Engine', aggregation: [58_000, 118_000] },\n { id: 'Cloud Dataflow', aggregation: [1200, 1500] },\n { id: 'Cloud Storage', aggregation: [800, 500] },\n ],\n };\n\n const unlabeledDataflowData: UnlabeledDataflowData = {\n periodStart: '2020-09-01',\n periodEnd: '2020-09-30',\n labeledCost: 6_200,\n unlabeledCost: 7_000,\n projects: [\n {\n id: 'example-project-1',\n unlabeledCost: 5_000,\n labeledCost: 3_000,\n },\n {\n id: 'example-project-2',\n unlabeledCost: 2_000,\n labeledCost: 3_200,\n },\n ],\n };\n\n const today = DateTime.now();\n const alerts: Alert[] = await this.request({ group }, [\n new ProjectGrowthAlert(projectGrowthData),\n new UnlabeledDataflowAlert(unlabeledDataflowData),\n new KubernetesMigrationAlert(this, {\n startDate: today.minus({ days: 30 }).toFormat(DEFAULT_DATE_FORMAT),\n endDate: today.toFormat(DEFAULT_DATE_FORMAT),\n change: {\n ratio: 0,\n amount: 0,\n },\n services: [\n {\n id: 'service-a',\n aggregation: [20_000, 10_000],\n change: {\n ratio: -0.5,\n amount: -10_000,\n },\n entities: {},\n },\n {\n id: 'service-b',\n aggregation: [30_000, 15_000],\n change: {\n ratio: -0.5,\n amount: -15_000,\n },\n entities: {},\n },\n ],\n }),\n ]);\n\n return alerts;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"KubernetesMigrationAlertCard.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 Box from '@material-ui/core/Box';\nimport { KubernetesMigrationBarChartLegend } from './KubernetesMigrationBarChartLegend';\nimport { KubernetesMigrationBarChart } from './KubernetesMigrationBarChart';\nimport { KubernetesMigrationData } from '../../alerts';\nimport { InfoCard } from '@backstage/core-components';\n\ntype KubernetesMigrationAlertProps = {\n data: KubernetesMigrationData;\n title: string;\n subheader: string;\n currentProduct: string;\n comparedProduct: string;\n};\n\nexport const KubernetesMigrationAlertCard = ({\n data,\n title,\n subheader,\n currentProduct,\n comparedProduct,\n}: KubernetesMigrationAlertProps) => {\n return (\n <InfoCard title={title} subheader={subheader}>\n <Box display=\"flex\" flexDirection=\"column\">\n <Box paddingY={1}>\n <KubernetesMigrationBarChartLegend\n startDate={data.startDate}\n change={data.change}\n currentProduct={currentProduct}\n comparedProduct={comparedProduct}\n />\n </Box>\n <Box paddingY={1}>\n <KubernetesMigrationBarChart\n services={data.services}\n currentProduct={currentProduct}\n comparedProduct={comparedProduct}\n />\n </Box>\n </Box>\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;AA8BO,MAAM,+BAA+B,CAAC;AAAA,EAC3C,IAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAqC,KAAA;AACnC,EACE,uBAAA,GAAA,CAAC,YAAS,KAAc,EAAA,SAAA,EACtB,+BAAC,GAAI,EAAA,EAAA,OAAA,EAAQ,MAAO,EAAA,aAAA,EAAc,QAChC,EAAA,QAAA,EAAA;AAAA,oBAAC,GAAA,CAAA,GAAA,EAAA,EAAI,UAAU,CACb,EAAA,QAAA,kBAAA,GAAA;AAAA,MAAC,iCAAA;AAAA,MAAA;AAAA,QACC,WAAW,IAAK,CAAA,SAAA;AAAA,QAChB,QAAQ,IAAK,CAAA,MAAA;AAAA,QACb,cAAA;AAAA,QACA;AAAA;AAAA,KAEJ,EAAA,CAAA;AAAA,oBACA,GAAA,CAAC,GAAI,EAAA,EAAA,QAAA,EAAU,CACb,EAAA,QAAA,kBAAA,GAAA;AAAA,MAAC,2BAAA;AAAA,MAAA;AAAA,QACC,UAAU,IAAK,CAAA,QAAA;AAAA,QACf,cAAA;AAAA,QACA;AAAA;AAAA,KAEJ,EAAA;AAAA,GAAA,EACF,CACF,EAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"KubernetesMigrationAlertCard.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 Box from '@material-ui/core/Box';\nimport { KubernetesMigrationBarChartLegend } from './KubernetesMigrationBarChartLegend';\nimport { KubernetesMigrationBarChart } from './KubernetesMigrationBarChart';\nimport { KubernetesMigrationData } from '../../alerts';\nimport { InfoCard } from '@backstage/core-components';\n\ntype KubernetesMigrationAlertProps = {\n data: KubernetesMigrationData;\n title: string;\n subheader: string;\n currentProduct: string;\n comparedProduct: string;\n};\n\nexport const KubernetesMigrationAlertCard = ({\n data,\n title,\n subheader,\n currentProduct,\n comparedProduct,\n}: KubernetesMigrationAlertProps) => {\n return (\n <InfoCard title={title} subheader={subheader}>\n <Box display=\"flex\" flexDirection=\"column\">\n <Box paddingY={1}>\n <KubernetesMigrationBarChartLegend\n startDate={data.startDate}\n change={data.change}\n currentProduct={currentProduct}\n comparedProduct={comparedProduct}\n />\n </Box>\n <Box paddingY={1}>\n <KubernetesMigrationBarChart\n services={data.services}\n currentProduct={currentProduct}\n comparedProduct={comparedProduct}\n />\n </Box>\n </Box>\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;AA8BO,MAAM,+BAA+B,CAAC;AAAA,EAC3C,IAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA,KAAqC;AACnC,EAAA,uBACE,GAAA,CAAC,YAAS,KAAA,EAAc,SAAA,EACtB,+BAAC,GAAA,EAAA,EAAI,OAAA,EAAQ,MAAA,EAAO,aAAA,EAAc,QAAA,EAChC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,GAAA,EAAA,EAAI,UAAU,CAAA,EACb,QAAA,kBAAA,GAAA;AAAA,MAAC,iCAAA;AAAA,MAAA;AAAA,QACC,WAAW,IAAA,CAAK,SAAA;AAAA,QAChB,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,cAAA;AAAA,QACA;AAAA;AAAA,KACF,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,GAAA,EAAA,EAAI,QAAA,EAAU,CAAA,EACb,QAAA,kBAAA,GAAA;AAAA,MAAC,2BAAA;AAAA,MAAA;AAAA,QACC,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,cAAA;AAAA,QACA;AAAA;AAAA,KACF,EACF;AAAA,GAAA,EACF,CAAA,EACF,CAAA;AAEJ;;;;"}
@@ -76,6 +76,7 @@ import '@material-ui/core/Tabs';
76
76
  import 'recharts';
77
77
  import '@material-ui/core/styles/colorManipulator';
78
78
  import '@material-ui/icons/Fullscreen';
79
+ import '../../../components/PeriodSelect/DateRangePicker.esm.js';
79
80
  import '@material-ui/core/CircularProgress';
80
81
  import '@backstage/core-components';
81
82
  import '@material-ui/core/Menu';
@@ -1 +1 @@
1
- {"version":3,"file":"KubernetesMigrationBarChart.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 { BarChart } from '../../../components';\nimport {\n BarChartOptions,\n CostInsightsTheme,\n ResourceData,\n} from '../../../types';\nimport { Entity } from '@backstage-community/plugin-cost-insights-common';\nimport { useTheme } from '@material-ui/core/styles';\n\ntype MigrationBarChartProps = {\n currentProduct: string;\n comparedProduct: string;\n services: Array<Entity>;\n};\n\nexport const KubernetesMigrationBarChart = ({\n currentProduct,\n comparedProduct,\n services,\n}: MigrationBarChartProps) => {\n const theme = useTheme<CostInsightsTheme>();\n\n const options: BarChartOptions = {\n previousFill: theme.palette.magenta,\n currentFill: theme.palette.yellow,\n previousName: comparedProduct,\n currentName: currentProduct,\n };\n\n const resources: ResourceData[] = services.map(service => ({\n name: service.id,\n previous: service.aggregation[0],\n current: service.aggregation[1],\n }));\n\n return <BarChart resources={resources} options={options} />;\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BO,MAAM,8BAA8B,CAAC;AAAA,EAC1C,cAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,CAA8B,KAAA;AAC5B,EAAA,MAAM,QAAQ,QAA4B,EAAA;AAE1C,EAAA,MAAM,OAA2B,GAAA;AAAA,IAC/B,YAAA,EAAc,MAAM,OAAQ,CAAA,OAAA;AAAA,IAC5B,WAAA,EAAa,MAAM,OAAQ,CAAA,MAAA;AAAA,IAC3B,YAAc,EAAA,eAAA;AAAA,IACd,WAAa,EAAA;AAAA,GACf;AAEA,EAAM,MAAA,SAAA,GAA4B,QAAS,CAAA,GAAA,CAAI,CAAY,OAAA,MAAA;AAAA,IACzD,MAAM,OAAQ,CAAA,EAAA;AAAA,IACd,QAAA,EAAU,OAAQ,CAAA,WAAA,CAAY,CAAC,CAAA;AAAA,IAC/B,OAAA,EAAS,OAAQ,CAAA,WAAA,CAAY,CAAC;AAAA,GAC9B,CAAA,CAAA;AAEF,EAAO,uBAAA,GAAA,CAAC,QAAS,EAAA,EAAA,SAAA,EAAsB,OAAkB,EAAA,CAAA;AAC3D;;;;"}
1
+ {"version":3,"file":"KubernetesMigrationBarChart.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 { BarChart } from '../../../components';\nimport {\n BarChartOptions,\n CostInsightsTheme,\n ResourceData,\n} from '../../../types';\nimport { Entity } from '@backstage-community/plugin-cost-insights-common';\nimport { useTheme } from '@material-ui/core/styles';\n\ntype MigrationBarChartProps = {\n currentProduct: string;\n comparedProduct: string;\n services: Array<Entity>;\n};\n\nexport const KubernetesMigrationBarChart = ({\n currentProduct,\n comparedProduct,\n services,\n}: MigrationBarChartProps) => {\n const theme = useTheme<CostInsightsTheme>();\n\n const options: BarChartOptions = {\n previousFill: theme.palette.magenta,\n currentFill: theme.palette.yellow,\n previousName: comparedProduct,\n currentName: currentProduct,\n };\n\n const resources: ResourceData[] = services.map(service => ({\n name: service.id,\n previous: service.aggregation[0],\n current: service.aggregation[1],\n }));\n\n return <BarChart resources={resources} options={options} />;\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BO,MAAM,8BAA8B,CAAC;AAAA,EAC1C,cAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,CAAA,KAA8B;AAC5B,EAAA,MAAM,QAAQ,QAAA,EAA4B;AAE1C,EAAA,MAAM,OAAA,GAA2B;AAAA,IAC/B,YAAA,EAAc,MAAM,OAAA,CAAQ,OAAA;AAAA,IAC5B,WAAA,EAAa,MAAM,OAAA,CAAQ,MAAA;AAAA,IAC3B,YAAA,EAAc,eAAA;AAAA,IACd,WAAA,EAAa;AAAA,GACf;AAEA,EAAA,MAAM,SAAA,GAA4B,QAAA,CAAS,GAAA,CAAI,CAAA,OAAA,MAAY;AAAA,IACzD,MAAM,OAAA,CAAQ,EAAA;AAAA,IACd,QAAA,EAAU,OAAA,CAAQ,WAAA,CAAY,CAAC,CAAA;AAAA,IAC/B,OAAA,EAAS,OAAA,CAAQ,WAAA,CAAY,CAAC;AAAA,GAChC,CAAE,CAAA;AAEF,EAAA,uBAAO,GAAA,CAAC,QAAA,EAAA,EAAS,SAAA,EAAsB,OAAA,EAAkB,CAAA;AAC3D;;;;"}
@@ -82,6 +82,7 @@ import '@material-ui/core/Tab';
82
82
  import '@material-ui/core/Tabs';
83
83
  import '@material-ui/core/styles/colorManipulator';
84
84
  import '@material-ui/icons/Fullscreen';
85
+ import '../../../components/PeriodSelect/DateRangePicker.esm.js';
85
86
  import '@material-ui/core/CircularProgress';
86
87
  import '@backstage/core-components';
87
88
  import '@material-ui/core/Menu';
@@ -1 +1 @@
1
- {"version":3,"file":"KubernetesMigrationBarChartLegend.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 Box from '@material-ui/core/Box';\nimport { useTheme } from '@material-ui/core/styles';\nimport { CostGrowth, LegendItem } from '../../../components';\nimport { CostInsightsTheme, Duration } from '../../../types';\nimport { ChangeStatistic } from '@backstage-community/plugin-cost-insights-common';\nimport { monthOf } from '../../../utils/formatters';\n\nexport type MigrationBarChartLegendProps = {\n change: ChangeStatistic;\n startDate: string;\n currentProduct: string;\n comparedProduct: string;\n};\n\nexport const KubernetesMigrationBarChartLegend = ({\n currentProduct,\n comparedProduct,\n change,\n startDate,\n}: MigrationBarChartLegendProps) => {\n const theme = useTheme<CostInsightsTheme>();\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n <Box marginRight={2}>\n <LegendItem\n title={monthOf(startDate)}\n markerColor={theme.palette.magenta}\n >\n {currentProduct}\n </LegendItem>\n </Box>\n <Box marginRight={2}>\n <LegendItem title=\"Estimated Cost\" markerColor={theme.palette.yellow}>\n {comparedProduct}\n </LegendItem>\n </Box>\n <LegendItem title=\"Total Savings\">\n <CostGrowth change={change} duration={Duration.P30D} />\n </LegendItem>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BO,MAAM,oCAAoC,CAAC;AAAA,EAChD,cAAA;AAAA,EACA,eAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAoC,KAAA;AAClC,EAAA,MAAM,QAAQ,QAA4B,EAAA;AAC1C,EAAA,uBACG,IAAA,CAAA,GAAA,EAAA,EAAI,OAAQ,EAAA,MAAA,EAAO,eAAc,KAChC,EAAA,QAAA,EAAA;AAAA,oBAAC,GAAA,CAAA,GAAA,EAAA,EAAI,aAAa,CAChB,EAAA,QAAA,kBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,QAAQ,SAAS,CAAA;AAAA,QACxB,WAAA,EAAa,MAAM,OAAQ,CAAA,OAAA;AAAA,QAE1B,QAAA,EAAA;AAAA;AAAA,KAEL,EAAA,CAAA;AAAA,oBACC,GAAA,CAAA,GAAA,EAAA,EAAI,WAAa,EAAA,CAAA,EAChB,QAAC,kBAAA,GAAA,CAAA,UAAA,EAAA,EAAW,KAAM,EAAA,gBAAA,EAAiB,WAAa,EAAA,KAAA,CAAM,OAAQ,CAAA,MAAA,EAC3D,2BACH,CACF,EAAA,CAAA;AAAA,oBACA,GAAA,CAAC,UAAW,EAAA,EAAA,KAAA,EAAM,eAChB,EAAA,QAAA,kBAAA,GAAA,CAAC,cAAW,MAAgB,EAAA,QAAA,EAAU,QAAS,CAAA,IAAA,EAAM,CACvD,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"KubernetesMigrationBarChartLegend.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 Box from '@material-ui/core/Box';\nimport { useTheme } from '@material-ui/core/styles';\nimport { CostGrowth, LegendItem } from '../../../components';\nimport { CostInsightsTheme, Duration } from '../../../types';\nimport { ChangeStatistic } from '@backstage-community/plugin-cost-insights-common';\nimport { monthOf } from '../../../utils/formatters';\n\nexport type MigrationBarChartLegendProps = {\n change: ChangeStatistic;\n startDate: string;\n currentProduct: string;\n comparedProduct: string;\n};\n\nexport const KubernetesMigrationBarChartLegend = ({\n currentProduct,\n comparedProduct,\n change,\n startDate,\n}: MigrationBarChartLegendProps) => {\n const theme = useTheme<CostInsightsTheme>();\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n <Box marginRight={2}>\n <LegendItem\n title={monthOf(startDate)}\n markerColor={theme.palette.magenta}\n >\n {currentProduct}\n </LegendItem>\n </Box>\n <Box marginRight={2}>\n <LegendItem title=\"Estimated Cost\" markerColor={theme.palette.yellow}>\n {comparedProduct}\n </LegendItem>\n </Box>\n <LegendItem title=\"Total Savings\">\n <CostGrowth change={change} duration={Duration.P30D} />\n </LegendItem>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BO,MAAM,oCAAoC,CAAC;AAAA,EAChD,cAAA;AAAA,EACA,eAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,KAAoC;AAClC,EAAA,MAAM,QAAQ,QAAA,EAA4B;AAC1C,EAAA,uBACE,IAAA,CAAC,GAAA,EAAA,EAAI,OAAA,EAAQ,MAAA,EAAO,eAAc,KAAA,EAChC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,GAAA,EAAA,EAAI,aAAa,CAAA,EAChB,QAAA,kBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,QAAQ,SAAS,CAAA;AAAA,QACxB,WAAA,EAAa,MAAM,OAAA,CAAQ,OAAA;AAAA,QAE1B,QAAA,EAAA;AAAA;AAAA,KACH,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,GAAA,EAAA,EAAI,WAAA,EAAa,CAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAM,gBAAA,EAAiB,WAAA,EAAa,KAAA,CAAM,OAAA,CAAQ,MAAA,EAC3D,2BACH,CAAA,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAM,eAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,cAAW,MAAA,EAAgB,QAAA,EAAU,QAAA,CAAS,IAAA,EAAM,CAAA,EACvD;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"KubernetesMigrationDismissForm.esm.js","sources":["../../../src/example/forms/KubernetesMigrationDismissForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n ChangeEvent,\n} from 'react';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport FormGroup from '@material-ui/core/FormGroup';\nimport Typography from '@material-ui/core/Typography';\nimport { AlertFormProps } from '../../types';\nimport { Entity } from '@backstage-community/plugin-cost-insights-common';\nimport { KubernetesMigrationAlert } from '../alerts';\nimport { findAlways } from '../../utils/assert';\n\nexport type KubernetesMigrationDismissFormData = {\n services: Entity[];\n};\n\nexport type KubernetesMigrationDismissFormProps = AlertFormProps<\n KubernetesMigrationAlert,\n KubernetesMigrationDismissFormData\n>;\n\nexport const KubernetesMigrationDismissForm = forwardRef<\n HTMLFormElement,\n KubernetesMigrationDismissFormProps\n>(({ onSubmit, disableSubmit, alert }, ref) => {\n const [services, setServices] = useState<Entity[]>(alert.data.services);\n\n const onFormSubmit: FormEventHandler = e => {\n /* Remember to prevent default form behavior */\n e.preventDefault();\n onSubmit({ services: services });\n };\n\n const onCheckboxChange = (\n e: ChangeEvent<HTMLInputElement>,\n checked: boolean,\n ) => {\n if (checked) {\n const service = findAlways(\n alert.data.services,\n s => s.id === e.target.value,\n );\n setServices(prevServices => prevServices.concat(service));\n } else {\n setServices(prevServices =>\n prevServices.filter(p => p.id !== e.target.value),\n );\n }\n };\n\n /* Submit button is disabled by default. Use props.disableSubmit to toggle disabled state. */\n useEffect(() => {\n if (services.length) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n }, [services, disableSubmit]);\n\n return (\n /* All custom forms must accept a ref and implement an onSubmit handler. */\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>Or choose which services to dismiss this alert for.</b>\n </Typography>\n <FormGroup>\n {alert.data.services.map((service, index) => (\n <FormControlLabel\n key={`example-option-${index}`}\n label={service.id}\n value={service.id}\n control={\n <Checkbox\n color=\"primary\"\n checked={services.some(p => p.id === service.id)}\n onChange={onCheckboxChange}\n />\n }\n />\n ))}\n </FormGroup>\n </FormControl>\n </form>\n );\n});\n"],"names":[],"mappings":";;;;;;;;;AA0Ca,MAAA,8BAAA,GAAiC,WAG5C,CAAC,EAAE,UAAU,aAAe,EAAA,KAAA,IAAS,GAAQ,KAAA;AAC7C,EAAA,MAAM,CAAC,QAAU,EAAA,WAAW,IAAI,QAAmB,CAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAEtE,EAAA,MAAM,eAAiC,CAAK,CAAA,KAAA;AAE1C,IAAA,CAAA,CAAE,cAAe,EAAA;AACjB,IAAS,QAAA,CAAA,EAAE,UAAoB,CAAA;AAAA,GACjC;AAEA,EAAM,MAAA,gBAAA,GAAmB,CACvB,CAAA,EACA,OACG,KAAA;AACH,IAAA,IAAI,OAAS,EAAA;AACX,MAAA,MAAM,OAAU,GAAA,UAAA;AAAA,QACd,MAAM,IAAK,CAAA,QAAA;AAAA,QACX,CAAK,CAAA,KAAA,CAAA,CAAE,EAAO,KAAA,CAAA,CAAE,MAAO,CAAA;AAAA,OACzB;AACA,MAAA,WAAA,CAAY,CAAgB,YAAA,KAAA,YAAA,CAAa,MAAO,CAAA,OAAO,CAAC,CAAA;AAAA,KACnD,MAAA;AACL,MAAA,WAAA;AAAA,QAAY,CAAA,YAAA,KACV,aAAa,MAAO,CAAA,CAAA,CAAA,KAAK,EAAE,EAAO,KAAA,CAAA,CAAE,OAAO,KAAK;AAAA,OAClD;AAAA;AACF,GACF;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAS,MAAQ,EAAA;AACnB,MAAA,aAAA,CAAc,KAAK,CAAA;AAAA,KACd,MAAA;AACL,MAAA,aAAA,CAAc,IAAI,CAAA;AAAA;AACpB,GACC,EAAA,CAAC,QAAU,EAAA,aAAa,CAAC,CAAA;AAE5B,EAAA;AAAA;AAAA,oBAEE,GAAA,CAAC,MAAK,EAAA,EAAA,GAAA,EAAU,QAAU,EAAA,YAAA,EACxB,+BAAC,WAAY,EAAA,EAAA,SAAA,EAAU,UAAW,EAAA,SAAA,EAAS,IACzC,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,cAAW,KAAM,EAAA,aAAA,EAChB,QAAC,kBAAA,GAAA,CAAA,GAAA,EAAA,EAAE,iEAAmD,CACxD,EAAA,CAAA;AAAA,sBACA,GAAA,CAAC,aACE,QAAM,EAAA,KAAA,CAAA,IAAA,CAAK,SAAS,GAAI,CAAA,CAAC,SAAS,KACjC,qBAAA,GAAA;AAAA,QAAC,gBAAA;AAAA,QAAA;AAAA,UAEC,OAAO,OAAQ,CAAA,EAAA;AAAA,UACf,OAAO,OAAQ,CAAA,EAAA;AAAA,UACf,OACE,kBAAA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,KAAM,EAAA,SAAA;AAAA,cACN,SAAS,QAAS,CAAA,IAAA,CAAK,OAAK,CAAE,CAAA,EAAA,KAAO,QAAQ,EAAE,CAAA;AAAA,cAC/C,QAAU,EAAA;AAAA;AAAA;AACZ,SAAA;AAAA,QARG,kBAAkB,KAAK,CAAA;AAAA,OAW/B,CACH,EAAA;AAAA,KAAA,EACF,CACF,EAAA;AAAA;AAEJ,CAAC;;;;"}
1
+ {"version":3,"file":"KubernetesMigrationDismissForm.esm.js","sources":["../../../src/example/forms/KubernetesMigrationDismissForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n ChangeEvent,\n} from 'react';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport FormGroup from '@material-ui/core/FormGroup';\nimport Typography from '@material-ui/core/Typography';\nimport { AlertFormProps } from '../../types';\nimport { Entity } from '@backstage-community/plugin-cost-insights-common';\nimport { KubernetesMigrationAlert } from '../alerts';\nimport { findAlways } from '../../utils/assert';\n\nexport type KubernetesMigrationDismissFormData = {\n services: Entity[];\n};\n\nexport type KubernetesMigrationDismissFormProps = AlertFormProps<\n KubernetesMigrationAlert,\n KubernetesMigrationDismissFormData\n>;\n\nexport const KubernetesMigrationDismissForm = forwardRef<\n HTMLFormElement,\n KubernetesMigrationDismissFormProps\n>(({ onSubmit, disableSubmit, alert }, ref) => {\n const [services, setServices] = useState<Entity[]>(alert.data.services);\n\n const onFormSubmit: FormEventHandler = e => {\n /* Remember to prevent default form behavior */\n e.preventDefault();\n onSubmit({ services: services });\n };\n\n const onCheckboxChange = (\n e: ChangeEvent<HTMLInputElement>,\n checked: boolean,\n ) => {\n if (checked) {\n const service = findAlways(\n alert.data.services,\n s => s.id === e.target.value,\n );\n setServices(prevServices => prevServices.concat(service));\n } else {\n setServices(prevServices =>\n prevServices.filter(p => p.id !== e.target.value),\n );\n }\n };\n\n /* Submit button is disabled by default. Use props.disableSubmit to toggle disabled state. */\n useEffect(() => {\n if (services.length) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n }, [services, disableSubmit]);\n\n return (\n /* All custom forms must accept a ref and implement an onSubmit handler. */\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>Or choose which services to dismiss this alert for.</b>\n </Typography>\n <FormGroup>\n {alert.data.services.map((service, index) => (\n <FormControlLabel\n key={`example-option-${index}`}\n label={service.id}\n value={service.id}\n control={\n <Checkbox\n color=\"primary\"\n checked={services.some(p => p.id === service.id)}\n onChange={onCheckboxChange}\n />\n }\n />\n ))}\n </FormGroup>\n </FormControl>\n </form>\n );\n});\n"],"names":[],"mappings":";;;;;;;;;AA0CO,MAAM,8BAAA,GAAiC,WAG5C,CAAC,EAAE,UAAU,aAAA,EAAe,KAAA,IAAS,GAAA,KAAQ;AAC7C,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,IAAI,QAAA,CAAmB,KAAA,CAAM,KAAK,QAAQ,CAAA;AAEtE,EAAA,MAAM,eAAiC,CAAA,CAAA,KAAK;AAE1C,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,QAAA,CAAS,EAAE,UAAoB,CAAA;AAAA,EACjC,CAAA;AAEA,EAAA,MAAM,gBAAA,GAAmB,CACvB,CAAA,EACA,OAAA,KACG;AACH,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,OAAA,GAAU,UAAA;AAAA,QACd,MAAM,IAAA,CAAK,QAAA;AAAA,QACX,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,KAAO,CAAA,CAAE,MAAA,CAAO;AAAA,OACzB;AACA,MAAA,WAAA,CAAY,CAAA,YAAA,KAAgB,YAAA,CAAa,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA,IAC1D,CAAA,MAAO;AACL,MAAA,WAAA;AAAA,QAAY,CAAA,YAAA,KACV,aAAa,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,EAAA,KAAO,CAAA,CAAE,OAAO,KAAK;AAAA,OAClD;AAAA,IACF;AAAA,EACF,CAAA;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,MAAA,aAAA,CAAc,KAAK,CAAA;AAAA,IACrB,CAAA,MAAO;AACL,MAAA,aAAA,CAAc,IAAI,CAAA;AAAA,IACpB;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,aAAa,CAAC,CAAA;AAE5B,EAAA;AAAA;AAAA,oBAEE,GAAA,CAAC,MAAA,EAAA,EAAK,GAAA,EAAU,QAAA,EAAU,YAAA,EACxB,+BAAC,WAAA,EAAA,EAAY,SAAA,EAAU,UAAA,EAAW,SAAA,EAAS,IAAA,EACzC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,cAAW,KAAA,EAAM,aAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,iEAAmD,CAAA,EACxD,CAAA;AAAA,sBACA,GAAA,CAAC,aACE,QAAA,EAAA,KAAA,CAAM,IAAA,CAAK,SAAS,GAAA,CAAI,CAAC,SAAS,KAAA,qBACjC,GAAA;AAAA,QAAC,gBAAA;AAAA,QAAA;AAAA,UAEC,OAAO,OAAA,CAAQ,EAAA;AAAA,UACf,OAAO,OAAA,CAAQ,EAAA;AAAA,UACf,OAAA,kBACE,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,KAAA,EAAM,SAAA;AAAA,cACN,SAAS,QAAA,CAAS,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,QAAQ,EAAE,CAAA;AAAA,cAC/C,QAAA,EAAU;AAAA;AAAA;AACZ,SAAA;AAAA,QARG,kBAAkB,KAAK,CAAA;AAAA,OAW/B,CAAA,EACH;AAAA,KAAA,EACF,CAAA,EACF;AAAA;AAEJ,CAAC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"AlertAcceptForm.esm.js","sources":["../../src/forms/AlertAcceptForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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, forwardRef, ChangeEvent, FormEventHandler } from 'react';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport { Alert, AlertFormProps } from '../types';\n\nexport type AlertAcceptFormProps = AlertFormProps<Alert, null>;\n\nexport const AlertAcceptForm = forwardRef<\n HTMLFormElement,\n AlertAcceptFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const [checked, setChecked] = useState(false);\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n onSubmit(null);\n };\n\n const onChecked = (_: ChangeEvent<HTMLInputElement>, isChecked: boolean) => {\n setChecked(isChecked);\n disableSubmit(!isChecked);\n };\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <FormControlLabel\n label=\"My team can commit to making this change soon, or has already.\"\n value={checked}\n control={\n <Checkbox color=\"primary\" checked={checked} onChange={onChecked} />\n }\n />\n </FormControl>\n </form>\n );\n});\n"],"names":[],"mappings":";;;;;;AAwBO,MAAM,kBAAkB,UAG7B,CAAA,CAAC,EAAE,QAAU,EAAA,aAAA,IAAiB,GAAQ,KAAA;AACtC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAE5C,EAAA,MAAM,eAAiC,CAAK,CAAA,KAAA;AAC1C,IAAA,CAAA,CAAE,cAAe,EAAA;AACjB,IAAA,QAAA,CAAS,IAAI,CAAA;AAAA,GACf;AAEA,EAAM,MAAA,SAAA,GAAY,CAAC,CAAA,EAAkC,SAAuB,KAAA;AAC1E,IAAA,UAAA,CAAW,SAAS,CAAA;AACpB,IAAA,aAAA,CAAc,CAAC,SAAS,CAAA;AAAA,GAC1B;AAEA,EACE,uBAAA,GAAA,CAAC,MAAK,EAAA,EAAA,GAAA,EAAU,QAAU,EAAA,YAAA,EACxB,8BAAC,WAAY,EAAA,EAAA,SAAA,EAAU,UAAW,EAAA,SAAA,EAAS,IACzC,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,KAAM,EAAA,gEAAA;AAAA,MACN,KAAO,EAAA,OAAA;AAAA,MACP,yBACG,GAAA,CAAA,QAAA,EAAA,EAAS,OAAM,SAAU,EAAA,OAAA,EAAkB,UAAU,SAAW,EAAA;AAAA;AAAA,KAGvE,CACF,EAAA,CAAA;AAEJ,CAAC;;;;"}
1
+ {"version":3,"file":"AlertAcceptForm.esm.js","sources":["../../src/forms/AlertAcceptForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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, forwardRef, ChangeEvent, FormEventHandler } from 'react';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport { Alert, AlertFormProps } from '../types';\n\nexport type AlertAcceptFormProps = AlertFormProps<Alert, null>;\n\nexport const AlertAcceptForm = forwardRef<\n HTMLFormElement,\n AlertAcceptFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const [checked, setChecked] = useState(false);\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n onSubmit(null);\n };\n\n const onChecked = (_: ChangeEvent<HTMLInputElement>, isChecked: boolean) => {\n setChecked(isChecked);\n disableSubmit(!isChecked);\n };\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <FormControlLabel\n label=\"My team can commit to making this change soon, or has already.\"\n value={checked}\n control={\n <Checkbox color=\"primary\" checked={checked} onChange={onChecked} />\n }\n />\n </FormControl>\n </form>\n );\n});\n"],"names":[],"mappings":";;;;;;AAwBO,MAAM,kBAAkB,UAAA,CAG7B,CAAC,EAAE,QAAA,EAAU,aAAA,IAAiB,GAAA,KAAQ;AACtC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAE5C,EAAA,MAAM,eAAiC,CAAA,CAAA,KAAK;AAC1C,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,QAAA,CAAS,IAAI,CAAA;AAAA,EACf,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,CAAC,CAAA,EAAkC,SAAA,KAAuB;AAC1E,IAAA,UAAA,CAAW,SAAS,CAAA;AACpB,IAAA,aAAA,CAAc,CAAC,SAAS,CAAA;AAAA,EAC1B,CAAA;AAEA,EAAA,uBACE,GAAA,CAAC,MAAA,EAAA,EAAK,GAAA,EAAU,QAAA,EAAU,YAAA,EACxB,8BAAC,WAAA,EAAA,EAAY,SAAA,EAAU,UAAA,EAAW,SAAA,EAAS,IAAA,EACzC,QAAA,kBAAA,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,gEAAA;AAAA,MACN,KAAA,EAAO,OAAA;AAAA,MACP,yBACE,GAAA,CAAC,QAAA,EAAA,EAAS,OAAM,SAAA,EAAU,OAAA,EAAkB,UAAU,SAAA,EAAW;AAAA;AAAA,KAGvE,CAAA,EACF,CAAA;AAEJ,CAAC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"AlertDismissForm.esm.js","sources":["../../src/forms/AlertDismissForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 ChangeEvent,\n useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n} from 'react';\nimport Box from '@material-ui/core/Box';\nimport Collapse from '@material-ui/core/Collapse';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport TextField from '@material-ui/core/TextField';\nimport Typography from '@material-ui/core/Typography';\nimport Radio from '@material-ui/core/Radio';\nimport RadioGroup from '@material-ui/core/RadioGroup';\nimport {\n Alert,\n AlertFormProps,\n AlertDismissReason,\n AlertDismissOptions,\n AlertDismissFormData,\n} from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useAlertDialogStyles as useStyles } from '../utils/styles';\n\nexport type AlertDismissFormProps = AlertFormProps<Alert, AlertDismissFormData>;\n\nexport const AlertDismissForm = forwardRef<\n HTMLFormElement,\n AlertDismissFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const classes = useStyles();\n const [other, setOther] = useState<Maybe<string>>(null);\n const [feedback, setFeedback] = useState<Maybe<string>>(null);\n const [reason, setReason] = useState<AlertDismissReason>(\n AlertDismissReason.Resolved,\n );\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n if (reason) {\n onSubmit({\n other: other,\n reason: reason,\n feedback: feedback,\n });\n }\n };\n\n const onReasonChange = (_: ChangeEvent<HTMLInputElement>, value: string) => {\n if (other) {\n setOther(null);\n }\n setReason(value as AlertDismissReason);\n };\n\n const onOtherChange = (e: ChangeEvent<HTMLInputElement>) => {\n return e.target.value\n ? setOther(e.target.value as AlertDismissReason)\n : setOther(null);\n };\n\n const onFeedbackChange = (e: ChangeEvent<HTMLInputElement>) => {\n return e.target.value\n ? setFeedback(e.target.value as AlertDismissReason)\n : setFeedback(null);\n };\n\n useEffect(() => {\n function validateDismissForm() {\n if (reason === AlertDismissReason.Other) {\n if (other) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n } else if (reason) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n }\n\n validateDismissForm();\n }, [reason, other, disableSubmit]);\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>Reason for dismissing?</b>\n </Typography>\n <Box mb={1}>\n <RadioGroup\n name=\"dismiss-alert-reasons\"\n value={reason}\n onChange={onReasonChange}\n >\n {AlertDismissOptions.map(option => (\n <FormControlLabel\n key={`dismiss-alert-option-${option.reason}`}\n label={option.label}\n value={option.reason}\n control={<Radio className={classes.radio} />}\n />\n ))}\n </RadioGroup>\n <Collapse in={reason === AlertDismissReason.Other}>\n <Box ml={4}>\n <TextField\n id=\"dismiss-alert-option-other\"\n variant=\"outlined\"\n multiline\n fullWidth\n rows={4}\n value={other ?? ''}\n onChange={onOtherChange}\n />\n </Box>\n </Collapse>\n </Box>\n <Typography gutterBottom>\n <b>Any other feedback you can provide?</b>\n </Typography>\n <TextField\n id=\"dismiss-alert-feedback\"\n variant=\"outlined\"\n multiline\n rows={4}\n fullWidth\n value={feedback ?? ''}\n onChange={onFeedbackChange}\n />\n </FormControl>\n </form>\n );\n});\n"],"names":["useStyles"],"mappings":"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"}
1
+ {"version":3,"file":"AlertDismissForm.esm.js","sources":["../../src/forms/AlertDismissForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 ChangeEvent,\n useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n} from 'react';\nimport Box from '@material-ui/core/Box';\nimport Collapse from '@material-ui/core/Collapse';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport TextField from '@material-ui/core/TextField';\nimport Typography from '@material-ui/core/Typography';\nimport Radio from '@material-ui/core/Radio';\nimport RadioGroup from '@material-ui/core/RadioGroup';\nimport {\n Alert,\n AlertFormProps,\n AlertDismissReason,\n AlertDismissOptions,\n AlertDismissFormData,\n} from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useAlertDialogStyles as useStyles } from '../utils/styles';\n\nexport type AlertDismissFormProps = AlertFormProps<Alert, AlertDismissFormData>;\n\nexport const AlertDismissForm = forwardRef<\n HTMLFormElement,\n AlertDismissFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const classes = useStyles();\n const [other, setOther] = useState<Maybe<string>>(null);\n const [feedback, setFeedback] = useState<Maybe<string>>(null);\n const [reason, setReason] = useState<AlertDismissReason>(\n AlertDismissReason.Resolved,\n );\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n if (reason) {\n onSubmit({\n other: other,\n reason: reason,\n feedback: feedback,\n });\n }\n };\n\n const onReasonChange = (_: ChangeEvent<HTMLInputElement>, value: string) => {\n if (other) {\n setOther(null);\n }\n setReason(value as AlertDismissReason);\n };\n\n const onOtherChange = (e: ChangeEvent<HTMLInputElement>) => {\n return e.target.value\n ? setOther(e.target.value as AlertDismissReason)\n : setOther(null);\n };\n\n const onFeedbackChange = (e: ChangeEvent<HTMLInputElement>) => {\n return e.target.value\n ? setFeedback(e.target.value as AlertDismissReason)\n : setFeedback(null);\n };\n\n useEffect(() => {\n function validateDismissForm() {\n if (reason === AlertDismissReason.Other) {\n if (other) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n } else if (reason) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n }\n\n validateDismissForm();\n }, [reason, other, disableSubmit]);\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>Reason for dismissing?</b>\n </Typography>\n <Box mb={1}>\n <RadioGroup\n name=\"dismiss-alert-reasons\"\n value={reason}\n onChange={onReasonChange}\n >\n {AlertDismissOptions.map(option => (\n <FormControlLabel\n key={`dismiss-alert-option-${option.reason}`}\n label={option.label}\n value={option.reason}\n control={<Radio className={classes.radio} />}\n />\n ))}\n </RadioGroup>\n <Collapse in={reason === AlertDismissReason.Other}>\n <Box ml={4}>\n <TextField\n id=\"dismiss-alert-option-other\"\n variant=\"outlined\"\n multiline\n fullWidth\n rows={4}\n value={other ?? ''}\n onChange={onOtherChange}\n />\n </Box>\n </Collapse>\n </Box>\n <Typography gutterBottom>\n <b>Any other feedback you can provide?</b>\n </Typography>\n <TextField\n id=\"dismiss-alert-feedback\"\n variant=\"outlined\"\n multiline\n rows={4}\n fullWidth\n value={feedback ?? ''}\n onChange={onFeedbackChange}\n />\n </FormControl>\n </form>\n );\n});\n"],"names":["useStyles"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AlertSnoozeForm.esm.js","sources":["../../src/forms/AlertSnoozeForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 ChangeEvent,\n useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n} from 'react';\nimport { DateTime } from 'luxon';\nimport Box from '@material-ui/core/Box';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport RadioGroup from '@material-ui/core/RadioGroup';\nimport Radio from '@material-ui/core/Radio';\nimport Typography from '@material-ui/core/Typography';\nimport {\n Alert,\n AlertFormProps,\n Duration,\n DEFAULT_DATE_FORMAT,\n AlertSnoozeFormData,\n AlertSnoozeOptions,\n} from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useAlertDialogStyles as useStyles } from '../utils/styles';\nimport { intervalsOf } from '../utils/duration';\n\nexport type AlertSnoozeFormProps = AlertFormProps<Alert, AlertSnoozeFormData>;\n\nexport const AlertSnoozeForm = forwardRef<\n HTMLFormElement,\n AlertSnoozeFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const classes = useStyles();\n const [duration, setDuration] = useState<Maybe<Duration>>(Duration.P7D);\n\n useEffect(() => disableSubmit(false), [disableSubmit]);\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n if (duration) {\n const repeatInterval = 1;\n const today = DateTime.now().toFormat(DEFAULT_DATE_FORMAT);\n onSubmit({\n intervals: intervalsOf(duration, today, repeatInterval),\n });\n }\n };\n\n const onSnoozeDurationChange = (\n _: ChangeEvent<HTMLInputElement>,\n value: string,\n ) => {\n setDuration(value as Duration);\n };\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>For how long?</b>\n </Typography>\n <Box mb={1}>\n <RadioGroup\n name=\"snooze-alert-options\"\n value={duration}\n onChange={onSnoozeDurationChange}\n >\n {AlertSnoozeOptions.map(option => (\n <FormControlLabel\n key={`snooze-alert-option-${option.duration}`}\n label={option.label}\n value={option.duration}\n control={<Radio className={classes.radio} />}\n />\n ))}\n </RadioGroup>\n </Box>\n </FormControl>\n </form>\n );\n});\n"],"names":["useStyles"],"mappings":";;;;;;;;;;;;;;;AA4CO,MAAM,kBAAkB,UAG7B,CAAA,CAAC,EAAE,QAAU,EAAA,aAAA,IAAiB,GAAQ,KAAA;AACtC,EAAA,MAAM,UAAUA,oBAAU,EAAA;AAC1B,EAAA,MAAM,CAAC,QAAU,EAAA,WAAW,CAAI,GAAA,QAAA,CAA0B,SAAS,GAAG,CAAA;AAEtE,EAAA,SAAA,CAAU,MAAM,aAAc,CAAA,KAAK,CAAG,EAAA,CAAC,aAAa,CAAC,CAAA;AAErD,EAAA,MAAM,eAAiC,CAAK,CAAA,KAAA;AAC1C,IAAA,CAAA,CAAE,cAAe,EAAA;AACjB,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,MAAM,cAAiB,GAAA,CAAA;AACvB,MAAA,MAAM,KAAQ,GAAA,QAAA,CAAS,GAAI,EAAA,CAAE,SAAS,mBAAmB,CAAA;AACzD,MAAS,QAAA,CAAA;AAAA,QACP,SAAW,EAAA,WAAA,CAAY,QAAU,EAAA,KAAA,EAAO,cAAc;AAAA,OACvD,CAAA;AAAA;AACH,GACF;AAEA,EAAM,MAAA,sBAAA,GAAyB,CAC7B,CAAA,EACA,KACG,KAAA;AACH,IAAA,WAAA,CAAY,KAAiB,CAAA;AAAA,GAC/B;AAEA,EACE,uBAAA,GAAA,CAAC,MAAK,EAAA,EAAA,GAAA,EAAU,QAAU,EAAA,YAAA,EACxB,+BAAC,WAAY,EAAA,EAAA,SAAA,EAAU,UAAW,EAAA,SAAA,EAAS,IACzC,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,cAAW,KAAM,EAAA,aAAA,EAChB,QAAC,kBAAA,GAAA,CAAA,GAAA,EAAA,EAAE,2BAAa,CAClB,EAAA,CAAA;AAAA,oBACA,GAAA,CAAC,GAAI,EAAA,EAAA,EAAA,EAAI,CACP,EAAA,QAAA,kBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,IAAK,EAAA,sBAAA;AAAA,QACL,KAAO,EAAA,QAAA;AAAA,QACP,QAAU,EAAA,sBAAA;AAAA,QAET,QAAA,EAAA,kBAAA,CAAmB,IAAI,CACtB,MAAA,qBAAA,GAAA;AAAA,UAAC,gBAAA;AAAA,UAAA;AAAA,YAEC,OAAO,MAAO,CAAA,KAAA;AAAA,YACd,OAAO,MAAO,CAAA,QAAA;AAAA,YACd,OAAS,kBAAA,GAAA,CAAC,KAAM,EAAA,EAAA,SAAA,EAAW,QAAQ,KAAO,EAAA;AAAA,WAAA;AAAA,UAHrC,CAAA,oBAAA,EAAuB,OAAO,QAAQ,CAAA;AAAA,SAK9C;AAAA;AAAA,KAEL,EAAA;AAAA,GAAA,EACF,CACF,EAAA,CAAA;AAEJ,CAAC;;;;"}
1
+ {"version":3,"file":"AlertSnoozeForm.esm.js","sources":["../../src/forms/AlertSnoozeForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 ChangeEvent,\n useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n} from 'react';\nimport { DateTime } from 'luxon';\nimport Box from '@material-ui/core/Box';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport RadioGroup from '@material-ui/core/RadioGroup';\nimport Radio from '@material-ui/core/Radio';\nimport Typography from '@material-ui/core/Typography';\nimport {\n Alert,\n AlertFormProps,\n Duration,\n DEFAULT_DATE_FORMAT,\n AlertSnoozeFormData,\n AlertSnoozeOptions,\n} from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useAlertDialogStyles as useStyles } from '../utils/styles';\nimport { intervalsOf } from '../utils/duration';\n\nexport type AlertSnoozeFormProps = AlertFormProps<Alert, AlertSnoozeFormData>;\n\nexport const AlertSnoozeForm = forwardRef<\n HTMLFormElement,\n AlertSnoozeFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const classes = useStyles();\n const [duration, setDuration] = useState<Maybe<Duration>>(Duration.P7D);\n\n useEffect(() => disableSubmit(false), [disableSubmit]);\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n if (duration) {\n const repeatInterval = 1;\n const today = DateTime.now().toFormat(DEFAULT_DATE_FORMAT);\n onSubmit({\n intervals: intervalsOf(duration, today, repeatInterval),\n });\n }\n };\n\n const onSnoozeDurationChange = (\n _: ChangeEvent<HTMLInputElement>,\n value: string,\n ) => {\n setDuration(value as Duration);\n };\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>For how long?</b>\n </Typography>\n <Box mb={1}>\n <RadioGroup\n name=\"snooze-alert-options\"\n value={duration}\n onChange={onSnoozeDurationChange}\n >\n {AlertSnoozeOptions.map(option => (\n <FormControlLabel\n key={`snooze-alert-option-${option.duration}`}\n label={option.label}\n value={option.duration}\n control={<Radio className={classes.radio} />}\n />\n ))}\n </RadioGroup>\n </Box>\n </FormControl>\n </form>\n );\n});\n"],"names":["useStyles"],"mappings":";;;;;;;;;;;;;;;AA4CO,MAAM,kBAAkB,UAAA,CAG7B,CAAC,EAAE,QAAA,EAAU,aAAA,IAAiB,GAAA,KAAQ;AACtC,EAAA,MAAM,UAAUA,oBAAA,EAAU;AAC1B,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,QAAA,CAA0B,SAAS,GAAG,CAAA;AAEtE,EAAA,SAAA,CAAU,MAAM,aAAA,CAAc,KAAK,CAAA,EAAG,CAAC,aAAa,CAAC,CAAA;AAErD,EAAA,MAAM,eAAiC,CAAA,CAAA,KAAK;AAC1C,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,cAAA,GAAiB,CAAA;AACvB,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,EAAI,CAAE,SAAS,mBAAmB,CAAA;AACzD,MAAA,QAAA,CAAS;AAAA,QACP,SAAA,EAAW,WAAA,CAAY,QAAA,EAAU,KAAA,EAAO,cAAc;AAAA,OACvD,CAAA;AAAA,IACH;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,sBAAA,GAAyB,CAC7B,CAAA,EACA,KAAA,KACG;AACH,IAAA,WAAA,CAAY,KAAiB,CAAA;AAAA,EAC/B,CAAA;AAEA,EAAA,uBACE,GAAA,CAAC,MAAA,EAAA,EAAK,GAAA,EAAU,QAAA,EAAU,YAAA,EACxB,+BAAC,WAAA,EAAA,EAAY,SAAA,EAAU,UAAA,EAAW,SAAA,EAAS,IAAA,EACzC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,cAAW,KAAA,EAAM,aAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,2BAAa,CAAA,EAClB,CAAA;AAAA,oBACA,GAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAI,CAAA,EACP,QAAA,kBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,sBAAA;AAAA,QACL,KAAA,EAAO,QAAA;AAAA,QACP,QAAA,EAAU,sBAAA;AAAA,QAET,QAAA,EAAA,kBAAA,CAAmB,IAAI,CAAA,MAAA,qBACtB,GAAA;AAAA,UAAC,gBAAA;AAAA,UAAA;AAAA,YAEC,OAAO,MAAA,CAAO,KAAA;AAAA,YACd,OAAO,MAAA,CAAO,QAAA;AAAA,YACd,OAAA,kBAAS,GAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAW,QAAQ,KAAA,EAAO;AAAA,WAAA;AAAA,UAHrC,CAAA,oBAAA,EAAuB,OAAO,QAAQ,CAAA;AAAA,SAK9C;AAAA;AAAA,KACH,EACF;AAAA,GAAA,EACF,CAAA,EACF,CAAA;AAEJ,CAAC;;;;"}
@@ -1,10 +1,10 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { createContext, useState, useEffect, useContext } from 'react';
2
+ import { useState, useEffect, createContext, useContext } from 'react';
3
3
  import '../types/Alert.esm.js';
4
4
  import { EngineerThreshold } from '../types/ChangeStatistic.esm.js';
5
5
  import { getIcon } from '../utils/navigation.esm.js';
6
6
  import { validateMetrics, validateCurrencies } from '../utils/config.esm.js';
7
- import { createCurrencyFormat, defaultCurrencies } from '../utils/currency.esm.js';
7
+ import { defaultCurrencies, createCurrencyFormat } from '../utils/currency.esm.js';
8
8
  import { useApi, configApiRef } from '@backstage/core-plugin-api';
9
9
 
10
10
  const ConfigContext = createContext(
@@ -1 +1 @@
1
- {"version":3,"file":"useConfig.esm.js","sources":["../../src/hooks/useConfig.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport { Config as BackstageConfig } from '@backstage/config';\nimport { Currency, EngineerThreshold, Icon } from '../types';\nimport {\n Metric,\n Product,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { getIcon } from '../utils/navigation';\nimport { validateCurrencies, validateMetrics } from '../utils/config';\nimport { createCurrencyFormat, defaultCurrencies } from '../utils/currency';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\n/*\n * Config schema 2021-08-05\n *\n * costInsights:\n * engineerCost: 200000\n * products:\n * productA:\n * name: Product A\n * icon: storage\n * productB:\n * name: Product B\n * icon: data\n * metrics:\n * metricA:\n * name: Metric A\n * default: true\n * metricB:\n * name: Metric B\n * baseCurrency:\n * locale: nl-NL\n * options:\n * currency: EUR\n * minimumFractionDigits: 3\n * currencies:\n * currencyA:\n * label: Currency A\n * unit: Unit A\n * currencyB:\n * label: Currency B\n * kind: CURRENCY_B\n * unit: Unit B\n * prefix: B\n * rate: 3.5\n */\n\n/** @public */\nexport type ConfigContextProps = {\n baseCurrency: Intl.NumberFormat;\n metrics: Metric[];\n products: Product[];\n icons: Icon[];\n engineerCost: number;\n engineerThreshold: number;\n hideTrendLine: boolean;\n currencies: Currency[];\n};\n\nexport const ConfigContext = createContext<ConfigContextProps | undefined>(\n undefined,\n);\n\nconst defaultState: ConfigContextProps = {\n baseCurrency: createCurrencyFormat(),\n metrics: [],\n products: [],\n icons: [],\n engineerCost: 0,\n engineerThreshold: EngineerThreshold,\n hideTrendLine: false,\n currencies: defaultCurrencies,\n};\n\nexport const ConfigProvider = ({ children }: PropsWithChildren<{}>) => {\n const c: BackstageConfig = useApi(configApiRef);\n const [config, setConfig] = useState(defaultState);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n function getProducts(): Product[] {\n const products = c.getOptionalConfig('costInsights.products');\n if (products) {\n return products.keys().map(key => ({\n kind: key,\n name: products.getString(`${key}.name`),\n aggregation: [0, 0],\n }));\n }\n return [];\n }\n\n function getMetrics(): Metric[] {\n const metrics = c.getOptionalConfig('costInsights.metrics');\n if (metrics) {\n return metrics.keys().map(key => ({\n kind: key,\n name: metrics.getString(`${key}.name`),\n default: metrics.getOptionalBoolean(`${key}.default`) ?? false,\n }));\n }\n\n return [];\n }\n\n function getBaseCurrency(): Intl.NumberFormat {\n const baseCurrency = c.getOptionalConfig('costInsights.baseCurrency');\n if (baseCurrency) {\n const options = baseCurrency.getOptionalConfig('options');\n return new Intl.NumberFormat(\n baseCurrency.getOptionalString('locale'),\n options\n ? {\n localeMatcher: options.getOptionalString('localeMatcher'),\n style: 'currency',\n currency: options.getOptionalString('currency'),\n currencySign: options.getOptionalString('currencySign'),\n useGrouping: options.getOptionalBoolean('useGrouping'),\n minimumIntegerDigits: options.getOptionalNumber(\n 'minimumIntegerDigits',\n ),\n minimumFractionDigits: options.getOptionalNumber(\n 'minimumFractionDigits',\n ),\n maximumFractionDigits: options.getOptionalNumber(\n 'maximumFractionDigits',\n ),\n minimumSignificantDigits: options.getOptionalNumber(\n 'minimumSignificantDigits',\n ),\n maximumSignificantDigits: options.getOptionalNumber(\n 'maximumSignificantDigits',\n ),\n }\n : undefined,\n );\n }\n\n return defaultState.baseCurrency;\n }\n\n function getCurrencies(): Currency[] {\n const currencies = c.getOptionalConfig('costInsights.currencies');\n if (currencies) {\n return currencies.keys().map(key => ({\n label: currencies.getString(`${key}.label`),\n unit: currencies.getString(`${key}.unit`),\n kind: currencies.getOptionalString(`${key}.kind`) || null,\n prefix: currencies.getOptionalString(`${key}.prefix`),\n rate: currencies.getOptionalNumber(`${key}.rate`),\n }));\n }\n\n return defaultCurrencies;\n }\n\n function getIcons(): Icon[] {\n const products = c.getOptionalConfig('costInsights.products');\n if (products) {\n return products.keys().map(k => ({\n kind: k,\n component: getIcon(products.getOptionalString(`${k}.icon`)),\n }));\n }\n return [];\n }\n\n function getEngineerCost(): number {\n return c.getNumber('costInsights.engineerCost');\n }\n\n function getEngineerThreshold(): number {\n return (\n c.getOptionalNumber('costInsights.engineerThreshold') ??\n defaultState.engineerThreshold\n );\n }\n\n function getHideTrendLine(): boolean {\n return (\n c.getOptionalBoolean('costInsights.hideTrendLine') ??\n defaultState.hideTrendLine\n );\n }\n\n function getConfig() {\n const baseCurrency = getBaseCurrency();\n const products = getProducts();\n const metrics = getMetrics();\n const engineerCost = getEngineerCost();\n const engineerThreshold = getEngineerThreshold();\n const hideTrendLine = getHideTrendLine();\n const icons = getIcons();\n const currencies = getCurrencies();\n\n validateMetrics(metrics);\n validateCurrencies(currencies);\n\n setConfig(prevState => ({\n ...prevState,\n baseCurrency,\n metrics,\n products,\n engineerCost,\n engineerThreshold,\n hideTrendLine,\n icons,\n currencies,\n }));\n\n setLoading(false);\n }\n\n getConfig();\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (loading) {\n return null;\n }\n\n return (\n <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>\n );\n};\n\nexport function useConfig(): ConfigContextProps {\n const config = useContext(ConfigContext);\n return config ? config : assertNever();\n}\n\nfunction assertNever(): never {\n throw new Error('Cannot use useConfig outside of ConfigProvider');\n}\n"],"names":[],"mappings":";;;;;;;;;AAiFO,MAAM,aAAgB,GAAA,aAAA;AAAA,EAC3B,KAAA;AACF;AAEA,MAAM,YAAmC,GAAA;AAAA,EACvC,cAAc,oBAAqB,EAAA;AAAA,EACnC,SAAS,EAAC;AAAA,EACV,UAAU,EAAC;AAAA,EACX,OAAO,EAAC;AAAA,EACR,YAAc,EAAA,CAAA;AAAA,EACd,iBAAmB,EAAA,iBAAA;AAAA,EACnB,aAAe,EAAA,KAAA;AAAA,EACf,UAAY,EAAA;AACd,CAAA;AAEO,MAAM,cAAiB,GAAA,CAAC,EAAE,QAAA,EAAsC,KAAA;AACrE,EAAM,MAAA,CAAA,GAAqB,OAAO,YAAY,CAAA;AAC9C,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAS,YAAY,CAAA;AACjD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAE3C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,SAAS,WAAyB,GAAA;AAChC,MAAM,MAAA,QAAA,GAAW,CAAE,CAAA,iBAAA,CAAkB,uBAAuB,CAAA;AAC5D,MAAA,IAAI,QAAU,EAAA;AACZ,QAAA,OAAO,QAAS,CAAA,IAAA,EAAO,CAAA,GAAA,CAAI,CAAQ,GAAA,MAAA;AAAA,UACjC,IAAM,EAAA,GAAA;AAAA,UACN,IAAM,EAAA,QAAA,CAAS,SAAU,CAAA,CAAA,EAAG,GAAG,CAAO,KAAA,CAAA,CAAA;AAAA,UACtC,WAAA,EAAa,CAAC,CAAA,EAAG,CAAC;AAAA,SAClB,CAAA,CAAA;AAAA;AAEJ,MAAA,OAAO,EAAC;AAAA;AAGV,IAAA,SAAS,UAAuB,GAAA;AAC9B,MAAM,MAAA,OAAA,GAAU,CAAE,CAAA,iBAAA,CAAkB,sBAAsB,CAAA;AAC1D,MAAA,IAAI,OAAS,EAAA;AACX,QAAA,OAAO,OAAQ,CAAA,IAAA,EAAO,CAAA,GAAA,CAAI,CAAQ,GAAA,MAAA;AAAA,UAChC,IAAM,EAAA,GAAA;AAAA,UACN,IAAM,EAAA,OAAA,CAAQ,SAAU,CAAA,CAAA,EAAG,GAAG,CAAO,KAAA,CAAA,CAAA;AAAA,UACrC,SAAS,OAAQ,CAAA,kBAAA,CAAmB,CAAG,EAAA,GAAG,UAAU,CAAK,IAAA;AAAA,SACzD,CAAA,CAAA;AAAA;AAGJ,MAAA,OAAO,EAAC;AAAA;AAGV,IAAA,SAAS,eAAqC,GAAA;AAC5C,MAAM,MAAA,YAAA,GAAe,CAAE,CAAA,iBAAA,CAAkB,2BAA2B,CAAA;AACpE,MAAA,IAAI,YAAc,EAAA;AAChB,QAAM,MAAA,OAAA,GAAU,YAAa,CAAA,iBAAA,CAAkB,SAAS,CAAA;AACxD,QAAA,OAAO,IAAI,IAAK,CAAA,YAAA;AAAA,UACd,YAAA,CAAa,kBAAkB,QAAQ,CAAA;AAAA,UACvC,OACI,GAAA;AAAA,YACE,aAAA,EAAe,OAAQ,CAAA,iBAAA,CAAkB,eAAe,CAAA;AAAA,YACxD,KAAO,EAAA,UAAA;AAAA,YACP,QAAA,EAAU,OAAQ,CAAA,iBAAA,CAAkB,UAAU,CAAA;AAAA,YAC9C,YAAA,EAAc,OAAQ,CAAA,iBAAA,CAAkB,cAAc,CAAA;AAAA,YACtD,WAAA,EAAa,OAAQ,CAAA,kBAAA,CAAmB,aAAa,CAAA;AAAA,YACrD,sBAAsB,OAAQ,CAAA,iBAAA;AAAA,cAC5B;AAAA,aACF;AAAA,YACA,uBAAuB,OAAQ,CAAA,iBAAA;AAAA,cAC7B;AAAA,aACF;AAAA,YACA,uBAAuB,OAAQ,CAAA,iBAAA;AAAA,cAC7B;AAAA,aACF;AAAA,YACA,0BAA0B,OAAQ,CAAA,iBAAA;AAAA,cAChC;AAAA,aACF;AAAA,YACA,0BAA0B,OAAQ,CAAA,iBAAA;AAAA,cAChC;AAAA;AACF,WAEF,GAAA,KAAA;AAAA,SACN;AAAA;AAGF,MAAA,OAAO,YAAa,CAAA,YAAA;AAAA;AAGtB,IAAA,SAAS,aAA4B,GAAA;AACnC,MAAM,MAAA,UAAA,GAAa,CAAE,CAAA,iBAAA,CAAkB,yBAAyB,CAAA;AAChE,MAAA,IAAI,UAAY,EAAA;AACd,QAAA,OAAO,UAAW,CAAA,IAAA,EAAO,CAAA,GAAA,CAAI,CAAQ,GAAA,MAAA;AAAA,UACnC,KAAO,EAAA,UAAA,CAAW,SAAU,CAAA,CAAA,EAAG,GAAG,CAAQ,MAAA,CAAA,CAAA;AAAA,UAC1C,IAAM,EAAA,UAAA,CAAW,SAAU,CAAA,CAAA,EAAG,GAAG,CAAO,KAAA,CAAA,CAAA;AAAA,UACxC,MAAM,UAAW,CAAA,iBAAA,CAAkB,CAAG,EAAA,GAAG,OAAO,CAAK,IAAA,IAAA;AAAA,UACrD,MAAQ,EAAA,UAAA,CAAW,iBAAkB,CAAA,CAAA,EAAG,GAAG,CAAS,OAAA,CAAA,CAAA;AAAA,UACpD,IAAM,EAAA,UAAA,CAAW,iBAAkB,CAAA,CAAA,EAAG,GAAG,CAAO,KAAA,CAAA;AAAA,SAChD,CAAA,CAAA;AAAA;AAGJ,MAAO,OAAA,iBAAA;AAAA;AAGT,IAAA,SAAS,QAAmB,GAAA;AAC1B,MAAM,MAAA,QAAA,GAAW,CAAE,CAAA,iBAAA,CAAkB,uBAAuB,CAAA;AAC5D,MAAA,IAAI,QAAU,EAAA;AACZ,QAAA,OAAO,QAAS,CAAA,IAAA,EAAO,CAAA,GAAA,CAAI,CAAM,CAAA,MAAA;AAAA,UAC/B,IAAM,EAAA,CAAA;AAAA,UACN,WAAW,OAAQ,CAAA,QAAA,CAAS,kBAAkB,CAAG,EAAA,CAAC,OAAO,CAAC;AAAA,SAC1D,CAAA,CAAA;AAAA;AAEJ,MAAA,OAAO,EAAC;AAAA;AAGV,IAAA,SAAS,eAA0B,GAAA;AACjC,MAAO,OAAA,CAAA,CAAE,UAAU,2BAA2B,CAAA;AAAA;AAGhD,IAAA,SAAS,oBAA+B,GAAA;AACtC,MAAA,OACE,CAAE,CAAA,iBAAA,CAAkB,gCAAgC,CAAA,IACpD,YAAa,CAAA,iBAAA;AAAA;AAIjB,IAAA,SAAS,gBAA4B,GAAA;AACnC,MAAA,OACE,CAAE,CAAA,kBAAA,CAAmB,4BAA4B,CAAA,IACjD,YAAa,CAAA,aAAA;AAAA;AAIjB,IAAA,SAAS,SAAY,GAAA;AACnB,MAAA,MAAM,eAAe,eAAgB,EAAA;AACrC,MAAA,MAAM,WAAW,WAAY,EAAA;AAC7B,MAAA,MAAM,UAAU,UAAW,EAAA;AAC3B,MAAA,MAAM,eAAe,eAAgB,EAAA;AACrC,MAAA,MAAM,oBAAoB,oBAAqB,EAAA;AAC/C,MAAA,MAAM,gBAAgB,gBAAiB,EAAA;AACvC,MAAA,MAAM,QAAQ,QAAS,EAAA;AACvB,MAAA,MAAM,aAAa,aAAc,EAAA;AAEjC,MAAA,eAAA,CAAgB,OAAO,CAAA;AACvB,MAAA,kBAAA,CAAmB,UAAU,CAAA;AAE7B,MAAA,SAAA,CAAU,CAAc,SAAA,MAAA;AAAA,QACtB,GAAG,SAAA;AAAA,QACH,YAAA;AAAA,QACA,OAAA;AAAA,QACA,QAAA;AAAA,QACA,YAAA;AAAA,QACA,iBAAA;AAAA,QACA,aAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OACA,CAAA,CAAA;AAEF,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAGlB,IAAU,SAAA,EAAA;AAAA,GACZ,EAAG,EAAE,CAAA;AAEL,EAAA,IAAI,OAAS,EAAA;AACX,IAAO,OAAA,IAAA;AAAA;AAGT,EAAA,2BACG,aAAc,CAAA,QAAA,EAAd,EAAuB,KAAA,EAAO,QAAS,QAAS,EAAA,CAAA;AAErD;AAEO,SAAS,SAAgC,GAAA;AAC9C,EAAM,MAAA,MAAA,GAAS,WAAW,aAAa,CAAA;AACvC,EAAO,OAAA,MAAA,GAAS,SAAS,WAAY,EAAA;AACvC;AAEA,SAAS,WAAqB,GAAA;AAC5B,EAAM,MAAA,IAAI,MAAM,gDAAgD,CAAA;AAClE;;;;"}
1
+ {"version":3,"file":"useConfig.esm.js","sources":["../../src/hooks/useConfig.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport { Config as BackstageConfig } from '@backstage/config';\nimport { Currency, EngineerThreshold, Icon } from '../types';\nimport {\n Metric,\n Product,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { getIcon } from '../utils/navigation';\nimport { validateCurrencies, validateMetrics } from '../utils/config';\nimport { createCurrencyFormat, defaultCurrencies } from '../utils/currency';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\n/*\n * Config schema 2021-08-05\n *\n * costInsights:\n * engineerCost: 200000\n * products:\n * productA:\n * name: Product A\n * icon: storage\n * productB:\n * name: Product B\n * icon: data\n * metrics:\n * metricA:\n * name: Metric A\n * default: true\n * metricB:\n * name: Metric B\n * baseCurrency:\n * locale: nl-NL\n * options:\n * currency: EUR\n * minimumFractionDigits: 3\n * currencies:\n * currencyA:\n * label: Currency A\n * unit: Unit A\n * currencyB:\n * label: Currency B\n * kind: CURRENCY_B\n * unit: Unit B\n * prefix: B\n * rate: 3.5\n */\n\n/** @public */\nexport type ConfigContextProps = {\n baseCurrency: Intl.NumberFormat;\n metrics: Metric[];\n products: Product[];\n icons: Icon[];\n engineerCost: number;\n engineerThreshold: number;\n hideTrendLine: boolean;\n currencies: Currency[];\n};\n\nexport const ConfigContext = createContext<ConfigContextProps | undefined>(\n undefined,\n);\n\nconst defaultState: ConfigContextProps = {\n baseCurrency: createCurrencyFormat(),\n metrics: [],\n products: [],\n icons: [],\n engineerCost: 0,\n engineerThreshold: EngineerThreshold,\n hideTrendLine: false,\n currencies: defaultCurrencies,\n};\n\nexport const ConfigProvider = ({ children }: PropsWithChildren<{}>) => {\n const c: BackstageConfig = useApi(configApiRef);\n const [config, setConfig] = useState(defaultState);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n function getProducts(): Product[] {\n const products = c.getOptionalConfig('costInsights.products');\n if (products) {\n return products.keys().map(key => ({\n kind: key,\n name: products.getString(`${key}.name`),\n aggregation: [0, 0],\n }));\n }\n return [];\n }\n\n function getMetrics(): Metric[] {\n const metrics = c.getOptionalConfig('costInsights.metrics');\n if (metrics) {\n return metrics.keys().map(key => ({\n kind: key,\n name: metrics.getString(`${key}.name`),\n default: metrics.getOptionalBoolean(`${key}.default`) ?? false,\n }));\n }\n\n return [];\n }\n\n function getBaseCurrency(): Intl.NumberFormat {\n const baseCurrency = c.getOptionalConfig('costInsights.baseCurrency');\n if (baseCurrency) {\n const options = baseCurrency.getOptionalConfig('options');\n return new Intl.NumberFormat(\n baseCurrency.getOptionalString('locale'),\n options\n ? ({\n localeMatcher: options.getOptionalString('localeMatcher'),\n style: 'currency',\n currency: options.getOptionalString('currency'),\n currencySign: options.getOptionalString('currencySign'),\n useGrouping: options.getOptionalBoolean('useGrouping'),\n minimumIntegerDigits: options.getOptionalNumber(\n 'minimumIntegerDigits',\n ),\n minimumFractionDigits: options.getOptionalNumber(\n 'minimumFractionDigits',\n ),\n maximumFractionDigits: options.getOptionalNumber(\n 'maximumFractionDigits',\n ),\n minimumSignificantDigits: options.getOptionalNumber(\n 'minimumSignificantDigits',\n ),\n maximumSignificantDigits: options.getOptionalNumber(\n 'maximumSignificantDigits',\n ),\n } as Intl.NumberFormatOptions)\n : undefined,\n );\n }\n\n return defaultState.baseCurrency;\n }\n\n function getCurrencies(): Currency[] {\n const currencies = c.getOptionalConfig('costInsights.currencies');\n if (currencies) {\n return currencies.keys().map(key => ({\n label: currencies.getString(`${key}.label`),\n unit: currencies.getString(`${key}.unit`),\n kind: currencies.getOptionalString(`${key}.kind`) || null,\n prefix: currencies.getOptionalString(`${key}.prefix`),\n rate: currencies.getOptionalNumber(`${key}.rate`),\n }));\n }\n\n return defaultCurrencies;\n }\n\n function getIcons(): Icon[] {\n const products = c.getOptionalConfig('costInsights.products');\n if (products) {\n return products.keys().map(k => ({\n kind: k,\n component: getIcon(products.getOptionalString(`${k}.icon`)),\n }));\n }\n return [];\n }\n\n function getEngineerCost(): number {\n return c.getNumber('costInsights.engineerCost');\n }\n\n function getEngineerThreshold(): number {\n return (\n c.getOptionalNumber('costInsights.engineerThreshold') ??\n defaultState.engineerThreshold\n );\n }\n\n function getHideTrendLine(): boolean {\n return (\n c.getOptionalBoolean('costInsights.hideTrendLine') ??\n defaultState.hideTrendLine\n );\n }\n\n function getConfig() {\n const baseCurrency = getBaseCurrency();\n const products = getProducts();\n const metrics = getMetrics();\n const engineerCost = getEngineerCost();\n const engineerThreshold = getEngineerThreshold();\n const hideTrendLine = getHideTrendLine();\n const icons = getIcons();\n const currencies = getCurrencies();\n\n validateMetrics(metrics);\n validateCurrencies(currencies);\n\n setConfig(prevState => ({\n ...prevState,\n baseCurrency,\n metrics,\n products,\n engineerCost,\n engineerThreshold,\n hideTrendLine,\n icons,\n currencies,\n }));\n\n setLoading(false);\n }\n\n getConfig();\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (loading) {\n return null;\n }\n\n return (\n <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>\n );\n};\n\nexport function useConfig(): ConfigContextProps {\n const config = useContext(ConfigContext);\n return config ? config : assertNever();\n}\n\nfunction assertNever(): never {\n throw new Error('Cannot use useConfig outside of ConfigProvider');\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { createContext, useState, useContext } from 'react';
2
+ import { useState, createContext, useContext } from 'react';
3
3
  import { useConfig } from './useConfig.esm.js';
4
4
 
5
5
  const CurrencyContext = createContext(
@@ -1 +1 @@
1
- {"version":3,"file":"useCurrency.esm.js","sources":["../../src/hooks/useCurrency.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 {\n createContext,\n Dispatch,\n SetStateAction,\n useState,\n useContext,\n PropsWithChildren,\n} from 'react';\nimport { Currency } from '../types';\nimport { useConfig } from './useConfig';\n\n/** @public */\nexport type CurrencyContextProps = {\n currency: Currency;\n setCurrency: Dispatch<SetStateAction<Currency>>;\n};\n\nexport const CurrencyContext = createContext<CurrencyContextProps | undefined>(\n undefined,\n);\n\nexport const CurrencyProvider = ({ children }: PropsWithChildren<{}>) => {\n const config = useConfig();\n const currencies = config.currencies;\n const engineers = currencies.find(currency => currency.kind === null);\n const [currency, setCurrency] = useState<Currency>(\n engineers || currencies[0],\n );\n return (\n <CurrencyContext.Provider value={{ currency, setCurrency }}>\n {children}\n </CurrencyContext.Provider>\n );\n};\n\nexport function useCurrency(): [Currency, Dispatch<SetStateAction<Currency>>] {\n const context = useContext(CurrencyContext);\n\n if (!context) {\n assertNever();\n }\n\n return [context.currency, context.setCurrency];\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useCurrency outside of CurrencyProvider');\n}\n"],"names":["currency"],"mappings":";;;;AAgCO,MAAM,eAAkB,GAAA,aAAA;AAAA,EAC7B,KAAA;AACF;AAEO,MAAM,gBAAmB,GAAA,CAAC,EAAE,QAAA,EAAsC,KAAA;AACvE,EAAA,MAAM,SAAS,SAAU,EAAA;AACzB,EAAA,MAAM,aAAa,MAAO,CAAA,UAAA;AAC1B,EAAA,MAAM,YAAY,UAAW,CAAA,IAAA,CAAK,CAAAA,SAAYA,KAAAA,SAAAA,CAAS,SAAS,IAAI,CAAA;AACpE,EAAM,MAAA,CAAC,QAAU,EAAA,WAAW,CAAI,GAAA,QAAA;AAAA,IAC9B,SAAA,IAAa,WAAW,CAAC;AAAA,GAC3B;AACA,EACE,uBAAA,GAAA,CAAC,gBAAgB,QAAhB,EAAA,EAAyB,OAAO,EAAE,QAAA,EAAU,WAAY,EAAA,EACtD,QACH,EAAA,CAAA;AAEJ;AAEO,SAAS,WAA8D,GAAA;AAC5E,EAAM,MAAA,OAAA,GAAU,WAAW,eAAe,CAAA;AAE1C,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAY,WAAA,EAAA;AAAA;AAGd,EAAA,OAAO,CAAC,OAAA,CAAQ,QAAU,EAAA,OAAA,CAAQ,WAAW,CAAA;AAC/C;AAEA,SAAS,WAAqB,GAAA;AAC5B,EAAA,MAAM,MAAM,oDAAoD,CAAA;AAClE;;;;"}
1
+ {"version":3,"file":"useCurrency.esm.js","sources":["../../src/hooks/useCurrency.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 {\n createContext,\n Dispatch,\n SetStateAction,\n useState,\n useContext,\n PropsWithChildren,\n} from 'react';\nimport { Currency } from '../types';\nimport { useConfig } from './useConfig';\n\n/** @public */\nexport type CurrencyContextProps = {\n currency: Currency;\n setCurrency: Dispatch<SetStateAction<Currency>>;\n};\n\nexport const CurrencyContext = createContext<CurrencyContextProps | undefined>(\n undefined,\n);\n\nexport const CurrencyProvider = ({ children }: PropsWithChildren<{}>) => {\n const config = useConfig();\n const currencies = config.currencies;\n const engineers = currencies.find(currency => currency.kind === null);\n const [currency, setCurrency] = useState<Currency>(\n engineers || currencies[0],\n );\n return (\n <CurrencyContext.Provider value={{ currency, setCurrency }}>\n {children}\n </CurrencyContext.Provider>\n );\n};\n\nexport function useCurrency(): [Currency, Dispatch<SetStateAction<Currency>>] {\n const context = useContext(CurrencyContext);\n\n if (!context) {\n assertNever();\n }\n\n return [context.currency, context.setCurrency];\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useCurrency outside of CurrencyProvider');\n}\n"],"names":["currency"],"mappings":";;;;AAgCO,MAAM,eAAA,GAAkB,aAAA;AAAA,EAC7B;AACF;AAEO,MAAM,gBAAA,GAAmB,CAAC,EAAE,QAAA,EAAS,KAA6B;AACvE,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,aAAa,MAAA,CAAO,UAAA;AAC1B,EAAA,MAAM,YAAY,UAAA,CAAW,IAAA,CAAK,CAAAA,SAAAA,KAAYA,SAAAA,CAAS,SAAS,IAAI,CAAA;AACpE,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,QAAA;AAAA,IAC9B,SAAA,IAAa,WAAW,CAAC;AAAA,GAC3B;AACA,EAAA,uBACE,GAAA,CAAC,gBAAgB,QAAA,EAAhB,EAAyB,OAAO,EAAE,QAAA,EAAU,WAAA,EAAY,EACtD,QAAA,EACH,CAAA;AAEJ;AAEO,SAAS,WAAA,GAA8D;AAC5E,EAAA,MAAM,OAAA,GAAU,WAAW,eAAe,CAAA;AAE1C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,WAAA,EAAY;AAAA,EACd;AAEA,EAAA,OAAO,CAAC,OAAA,CAAQ,QAAA,EAAU,OAAA,CAAQ,WAAW,CAAA;AAC/C;AAEA,SAAS,WAAA,GAAqB;AAC5B,EAAA,MAAM,MAAM,oDAAoD,CAAA;AAClE;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { createContext, useState, useEffect, useContext } from 'react';
2
+ import { useState, useEffect, createContext, useContext } from 'react';
3
3
  import Alert from '@material-ui/lab/Alert';
4
4
  import { useNavigate, useLocation } from 'react-router-dom';
5
5
  import { validate, getInitialPageState, getInitialProductState, stringify } from '../utils/history.esm.js';
@@ -1 +1 @@
1
- {"version":3,"file":"useFilters.esm.js","sources":["../../src/hooks/useFilters.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 createContext,\n Dispatch,\n PropsWithChildren,\n SetStateAction,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport { PageFilters, ProductFilters } from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport {\n stringify,\n validate,\n getInitialPageState,\n getInitialProductState,\n} from '../utils/history';\nimport { useGroups } from './useGroups';\nimport { useConfig } from './useConfig';\n\nexport type FilterContextProps = {\n pageFilters: PageFilters;\n productFilters: ProductFilters;\n setPageFilters: Dispatch<SetStateAction<Maybe<PageFilters>>>;\n setProductFilters: Dispatch<SetStateAction<Maybe<ProductFilters>>>;\n};\n\nexport type MapFiltersToProps<T> = (props: FilterContextProps) => T;\n\nexport const FilterContext = createContext<FilterContextProps | undefined>(\n undefined,\n);\n\nexport const FilterProvider = ({ children }: PropsWithChildren<{}>) => {\n const config = useConfig();\n const navigate = useNavigate();\n const location = useLocation();\n const groups = useGroups();\n const [error, setError] = useState<Maybe<Error>>(null);\n const [pageFilters, setPageFilters] = useState<Maybe<PageFilters>>(null);\n const [productFilters, setProductFilters] =\n useState<Maybe<ProductFilters>>(null);\n\n useEffect(() => {\n async function setPageFiltersFromLocation() {\n try {\n // strip extraneous parameters, validate and transform\n const queryParams = await validate(location.search);\n const defaultMetric = config.metrics.find(m => m.default)?.kind ?? null;\n\n // Group or project parameters should override defaults\n const initialPageState = getInitialPageState(groups, queryParams);\n const initialProductState = getInitialProductState(config);\n\n setProductFilters(initialProductState);\n setPageFilters({ ...initialPageState, metric: defaultMetric });\n } catch (e) {\n setError(e);\n }\n }\n\n setPageFiltersFromLocation();\n }, [groups]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n function setLocationFromPageFilters(filters: PageFilters) {\n const queryString = stringify({\n group: filters.group,\n ...(filters.project ? { project: filters.project } : {}),\n });\n // TODO Remove workaround once issue is resolved in react-router\n // (https://github.com/ReactTraining/react-router/issues/7496)\n // navigate({ ...location, search: queryString });\n navigate({ ...location, search: `?${queryString}` });\n }\n\n if (pageFilters) {\n setLocationFromPageFilters(pageFilters);\n }\n }, [pageFilters]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n // Wait for filters to load\n if (!pageFilters || !productFilters) {\n return null;\n }\n\n return (\n <FilterContext.Provider\n value={{ pageFilters, productFilters, setPageFilters, setProductFilters }}\n >\n {children}\n </FilterContext.Provider>\n );\n};\n\nexport function useFilters<T>(mapFiltersToProps: MapFiltersToProps<T>): T {\n const context = useContext(FilterContext);\n return context ? mapFiltersToProps(context) : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useFilters outside of FilterProvider');\n}\n"],"names":[],"mappings":";;;;;;;;AA+CO,MAAM,aAAgB,GAAA,aAAA;AAAA,EAC3B,KAAA;AACF;AAEO,MAAM,cAAiB,GAAA,CAAC,EAAE,QAAA,EAAsC,KAAA;AACrE,EAAA,MAAM,SAAS,SAAU,EAAA;AACzB,EAAA,MAAM,WAAW,WAAY,EAAA;AAC7B,EAAA,MAAM,WAAW,WAAY,EAAA;AAC7B,EAAA,MAAM,SAAS,SAAU,EAAA;AACzB,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAA6B,IAAI,CAAA;AACvE,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GACtC,SAAgC,IAAI,CAAA;AAEtC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,eAAe,0BAA6B,GAAA;AAC1C,MAAI,IAAA;AAEF,QAAA,MAAM,WAAc,GAAA,MAAM,QAAS,CAAA,QAAA,CAAS,MAAM,CAAA;AAClD,QAAM,MAAA,aAAA,GAAgB,OAAO,OAAQ,CAAA,IAAA,CAAK,OAAK,CAAE,CAAA,OAAO,GAAG,IAAQ,IAAA,IAAA;AAGnE,QAAM,MAAA,gBAAA,GAAmB,mBAAoB,CAAA,MAAA,EAAQ,WAAW,CAAA;AAChE,QAAM,MAAA,mBAAA,GAAsB,uBAAuB,MAAM,CAAA;AAEzD,QAAA,iBAAA,CAAkB,mBAAmB,CAAA;AACrC,QAAA,cAAA,CAAe,EAAE,GAAG,gBAAkB,EAAA,MAAA,EAAQ,eAAe,CAAA;AAAA,eACtD,CAAG,EAAA;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AAAA;AACZ;AAGF,IAA2B,0BAAA,EAAA;AAAA,GAC7B,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,SAAS,2BAA2B,OAAsB,EAAA;AACxD,MAAA,MAAM,cAAc,SAAU,CAAA;AAAA,QAC5B,OAAO,OAAQ,CAAA,KAAA;AAAA,QACf,GAAI,QAAQ,OAAU,GAAA,EAAE,SAAS,OAAQ,CAAA,OAAA,KAAY;AAAC,OACvD,CAAA;AAID,MAAA,QAAA,CAAS,EAAE,GAAG,QAAA,EAAU,QAAQ,CAAI,CAAA,EAAA,WAAW,IAAI,CAAA;AAAA;AAGrD,IAAA,IAAI,WAAa,EAAA;AACf,MAAA,0BAAA,CAA2B,WAAW,CAAA;AAAA;AACxC,GACF,EAAG,CAAC,WAAW,CAAC,CAAA;AAEhB,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,uBAAQ,GAAA,CAAA,KAAA,EAAA,EAAM,QAAS,EAAA,OAAA,EAAS,gBAAM,OAAQ,EAAA,CAAA;AAAA;AAIhD,EAAI,IAAA,CAAC,WAAe,IAAA,CAAC,cAAgB,EAAA;AACnC,IAAO,OAAA,IAAA;AAAA;AAGT,EACE,uBAAA,GAAA;AAAA,IAAC,aAAc,CAAA,QAAA;AAAA,IAAd;AAAA,MACC,KAAO,EAAA,EAAE,WAAa,EAAA,cAAA,EAAgB,gBAAgB,iBAAkB,EAAA;AAAA,MAEvE;AAAA;AAAA,GACH;AAEJ;AAEO,SAAS,WAAc,iBAA4C,EAAA;AACxE,EAAM,MAAA,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAA,OAAO,OAAU,GAAA,iBAAA,CAAkB,OAAO,CAAA,GAAI,WAAY,EAAA;AAC5D;AAEA,SAAS,WAAqB,GAAA;AAC5B,EAAA,MAAM,MAAM,iDAAiD,CAAA;AAC/D;;;;"}
1
+ {"version":3,"file":"useFilters.esm.js","sources":["../../src/hooks/useFilters.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 createContext,\n Dispatch,\n PropsWithChildren,\n SetStateAction,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport { PageFilters, ProductFilters } from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport {\n stringify,\n validate,\n getInitialPageState,\n getInitialProductState,\n} from '../utils/history';\nimport { useGroups } from './useGroups';\nimport { useConfig } from './useConfig';\n\nexport type FilterContextProps = {\n pageFilters: PageFilters;\n productFilters: ProductFilters;\n setPageFilters: Dispatch<SetStateAction<Maybe<PageFilters>>>;\n setProductFilters: Dispatch<SetStateAction<Maybe<ProductFilters>>>;\n};\n\nexport type MapFiltersToProps<T> = (props: FilterContextProps) => T;\n\nexport const FilterContext = createContext<FilterContextProps | undefined>(\n undefined,\n);\n\nexport const FilterProvider = ({ children }: PropsWithChildren<{}>) => {\n const config = useConfig();\n const navigate = useNavigate();\n const location = useLocation();\n const groups = useGroups();\n const [error, setError] = useState<Maybe<Error>>(null);\n const [pageFilters, setPageFilters] = useState<Maybe<PageFilters>>(null);\n const [productFilters, setProductFilters] =\n useState<Maybe<ProductFilters>>(null);\n\n useEffect(() => {\n async function setPageFiltersFromLocation() {\n try {\n // strip extraneous parameters, validate and transform\n const queryParams = await validate(location.search);\n const defaultMetric = config.metrics.find(m => m.default)?.kind ?? null;\n\n // Group or project parameters should override defaults\n const initialPageState = getInitialPageState(groups, queryParams);\n const initialProductState = getInitialProductState(config);\n\n setProductFilters(initialProductState);\n setPageFilters({ ...initialPageState, metric: defaultMetric });\n } catch (e) {\n setError(e);\n }\n }\n\n setPageFiltersFromLocation();\n }, [groups]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n function setLocationFromPageFilters(filters: PageFilters) {\n const queryString = stringify({\n group: filters.group,\n ...(filters.project ? { project: filters.project } : {}),\n });\n // TODO Remove workaround once issue is resolved in react-router\n // (https://github.com/ReactTraining/react-router/issues/7496)\n // navigate({ ...location, search: queryString });\n navigate({ ...location, search: `?${queryString}` });\n }\n\n if (pageFilters) {\n setLocationFromPageFilters(pageFilters);\n }\n }, [pageFilters]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n // Wait for filters to load\n if (!pageFilters || !productFilters) {\n return null;\n }\n\n return (\n <FilterContext.Provider\n value={{ pageFilters, productFilters, setPageFilters, setProductFilters }}\n >\n {children}\n </FilterContext.Provider>\n );\n};\n\nexport function useFilters<T>(mapFiltersToProps: MapFiltersToProps<T>): T {\n const context = useContext(FilterContext);\n return context ? mapFiltersToProps(context) : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useFilters outside of FilterProvider');\n}\n"],"names":[],"mappings":";;;;;;;;AA+CO,MAAM,aAAA,GAAgB,aAAA;AAAA,EAC3B;AACF;AAEO,MAAM,cAAA,GAAiB,CAAC,EAAE,QAAA,EAAS,KAA6B;AACrE,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAA6B,IAAI,CAAA;AACvE,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GACtC,SAAgC,IAAI,CAAA;AAEtC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,eAAe,0BAAA,GAA6B;AAC1C,MAAA,IAAI;AAEF,QAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA;AAClD,QAAA,MAAM,aAAA,GAAgB,OAAO,OAAA,CAAQ,IAAA,CAAK,OAAK,CAAA,CAAE,OAAO,GAAG,IAAA,IAAQ,IAAA;AAGnE,QAAA,MAAM,gBAAA,GAAmB,mBAAA,CAAoB,MAAA,EAAQ,WAAW,CAAA;AAChE,QAAA,MAAM,mBAAA,GAAsB,uBAAuB,MAAM,CAAA;AAEzD,QAAA,iBAAA,CAAkB,mBAAmB,CAAA;AACrC,QAAA,cAAA,CAAe,EAAE,GAAG,gBAAA,EAAkB,MAAA,EAAQ,eAAe,CAAA;AAAA,MAC/D,SAAS,CAAA,EAAG;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AAAA,MACZ;AAAA,IACF;AAEA,IAAA,0BAAA,EAA2B;AAAA,EAC7B,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,SAAS,2BAA2B,OAAA,EAAsB;AACxD,MAAA,MAAM,cAAc,SAAA,CAAU;AAAA,QAC5B,OAAO,OAAA,CAAQ,KAAA;AAAA,QACf,GAAI,QAAQ,OAAA,GAAU,EAAE,SAAS,OAAA,CAAQ,OAAA,KAAY;AAAC,OACvD,CAAA;AAID,MAAA,QAAA,CAAS,EAAE,GAAG,QAAA,EAAU,QAAQ,CAAA,CAAA,EAAI,WAAW,IAAI,CAAA;AAAA,IACrD;AAEA,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,0BAAA,CAA2B,WAAW,CAAA;AAAA,IACxC;AAAA,EACF,CAAA,EAAG,CAAC,WAAW,CAAC,CAAA;AAEhB,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAS,OAAA,EAAS,gBAAM,OAAA,EAAQ,CAAA;AAAA,EAChD;AAGA,EAAA,IAAI,CAAC,WAAA,IAAe,CAAC,cAAA,EAAgB;AACnC,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,aAAA,CAAc,QAAA;AAAA,IAAd;AAAA,MACC,KAAA,EAAO,EAAE,WAAA,EAAa,cAAA,EAAgB,gBAAgB,iBAAA,EAAkB;AAAA,MAEvE;AAAA;AAAA,GACH;AAEJ;AAEO,SAAS,WAAc,iBAAA,EAA4C;AACxE,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAA,OAAO,OAAA,GAAU,iBAAA,CAAkB,OAAO,CAAA,GAAI,WAAA,EAAY;AAC5D;AAEA,SAAS,WAAA,GAAqB;AAC5B,EAAA,MAAM,MAAM,iDAAiD,CAAA;AAC/D;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { createContext, useState, useEffect, useContext } from 'react';
2
+ import { useState, useEffect, createContext, useContext } from 'react';
3
3
  import Alert from '@material-ui/lab/Alert';
4
4
  import { costInsightsApiRef } from '../api/CostInsightsApi.esm.js';
5
5
  import { useLoading } from './useLoading.esm.js';
@@ -1 +1 @@
1
- {"version":3,"file":"useGroups.esm.js","sources":["../../src/hooks/useGroups.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport { costInsightsApiRef } from '../api';\nimport { MapLoadingToProps, useLoading } from './useLoading';\nimport { Group, Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { DefaultLoadingAction } from '../utils/loading';\nimport { useApi, identityApiRef } from '@backstage/core-plugin-api';\nimport { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model';\n\ntype GroupsProviderLoadingProps = {\n dispatchLoadingGroups: (isLoading: boolean) => void;\n};\n\nconst mapLoadingToProps: MapLoadingToProps<GroupsProviderLoadingProps> = ({\n dispatch,\n}) => ({\n dispatchLoadingGroups: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.UserGroups]: isLoading }),\n});\n\nexport type GroupsContextProps = {\n groups: Group[];\n};\n\nexport const GroupsContext = createContext<GroupsContextProps | undefined>(\n undefined,\n);\n\nexport const GroupsProvider = ({ children }: PropsWithChildren<{}>) => {\n const identityApi = useApi(identityApiRef);\n const client = useApi(costInsightsApiRef);\n const [error, setError] = useState<Maybe<Error>>(null);\n const { dispatchLoadingGroups } = useLoading(mapLoadingToProps);\n\n const [groups, setGroups] = useState<Maybe<Group[]>>(null);\n\n useEffect(() => {\n dispatchLoadingGroups(true);\n\n async function getUserGroups() {\n try {\n const { userEntityRef } = await identityApi.getBackstageIdentity();\n const { name: userId } = parseEntityRef(userEntityRef, {\n defaultKind: 'User',\n defaultNamespace: DEFAULT_NAMESPACE,\n });\n const g = await client.getUserGroups(userId);\n setGroups(g);\n } catch (e) {\n setError(e);\n } finally {\n dispatchLoadingGroups(false);\n }\n }\n\n getUserGroups();\n }, [client]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n if (!groups) return null;\n\n return (\n <GroupsContext.Provider value={{ groups: groups }}>\n {children}\n </GroupsContext.Provider>\n );\n};\n\nexport function useGroups(): Group[] {\n const context = useContext(GroupsContext);\n return context ? context.groups : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useGroups outside of GroupsProvider');\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCA,MAAM,oBAAmE,CAAC;AAAA,EACxE;AACF,CAAO,MAAA;AAAA,EACL,qBAAA,EAAuB,CAAC,SAAA,KACtB,QAAS,CAAA,EAAE,CAAC,oBAAqB,CAAA,UAAU,GAAG,SAAA,EAAW;AAC7D,CAAA,CAAA;AAMO,MAAM,aAAgB,GAAA,aAAA;AAAA,EAC3B,KAAA;AACF;AAEO,MAAM,cAAiB,GAAA,CAAC,EAAE,QAAA,EAAsC,KAAA;AACrE,EAAM,MAAA,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAM,MAAA,MAAA,GAAS,OAAO,kBAAkB,CAAA;AACxC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,EAAE,qBAAA,EAA0B,GAAA,UAAA,CAAW,iBAAiB,CAAA;AAE9D,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAyB,IAAI,CAAA;AAEzD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,qBAAA,CAAsB,IAAI,CAAA;AAE1B,IAAA,eAAe,aAAgB,GAAA;AAC7B,MAAI,IAAA;AACF,QAAA,MAAM,EAAE,aAAA,EAAkB,GAAA,MAAM,YAAY,oBAAqB,EAAA;AACjE,QAAA,MAAM,EAAE,IAAA,EAAM,MAAO,EAAA,GAAI,eAAe,aAAe,EAAA;AAAA,UACrD,WAAa,EAAA,MAAA;AAAA,UACb,gBAAkB,EAAA;AAAA,SACnB,CAAA;AACD,QAAA,MAAM,CAAI,GAAA,MAAM,MAAO,CAAA,aAAA,CAAc,MAAM,CAAA;AAC3C,QAAA,SAAA,CAAU,CAAC,CAAA;AAAA,eACJ,CAAG,EAAA;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AAAA,OACV,SAAA;AACA,QAAA,qBAAA,CAAsB,KAAK,CAAA;AAAA;AAC7B;AAGF,IAAc,aAAA,EAAA;AAAA,GAChB,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,uBAAQ,GAAA,CAAA,KAAA,EAAA,EAAM,QAAS,EAAA,OAAA,EAAS,gBAAM,OAAQ,EAAA,CAAA;AAAA;AAGhD,EAAI,IAAA,CAAC,QAAe,OAAA,IAAA;AAEpB,EACE,uBAAA,GAAA,CAAC,cAAc,QAAd,EAAA,EAAuB,OAAO,EAAE,MAAA,IAC9B,QACH,EAAA,CAAA;AAEJ;AAEO,SAAS,SAAqB,GAAA;AACnC,EAAM,MAAA,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAO,OAAA,OAAA,GAAU,OAAQ,CAAA,MAAA,GAAS,WAAY,EAAA;AAChD;AAEA,SAAS,WAAqB,GAAA;AAC5B,EAAA,MAAM,MAAM,gDAAgD,CAAA;AAC9D;;;;"}
1
+ {"version":3,"file":"useGroups.esm.js","sources":["../../src/hooks/useGroups.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport { costInsightsApiRef } from '../api';\nimport { MapLoadingToProps, useLoading } from './useLoading';\nimport { Group, Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { DefaultLoadingAction } from '../utils/loading';\nimport { useApi, identityApiRef } from '@backstage/core-plugin-api';\nimport { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model';\n\ntype GroupsProviderLoadingProps = {\n dispatchLoadingGroups: (isLoading: boolean) => void;\n};\n\nconst mapLoadingToProps: MapLoadingToProps<GroupsProviderLoadingProps> = ({\n dispatch,\n}) => ({\n dispatchLoadingGroups: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.UserGroups]: isLoading }),\n});\n\nexport type GroupsContextProps = {\n groups: Group[];\n};\n\nexport const GroupsContext = createContext<GroupsContextProps | undefined>(\n undefined,\n);\n\nexport const GroupsProvider = ({ children }: PropsWithChildren<{}>) => {\n const identityApi = useApi(identityApiRef);\n const client = useApi(costInsightsApiRef);\n const [error, setError] = useState<Maybe<Error>>(null);\n const { dispatchLoadingGroups } = useLoading(mapLoadingToProps);\n\n const [groups, setGroups] = useState<Maybe<Group[]>>(null);\n\n useEffect(() => {\n dispatchLoadingGroups(true);\n\n async function getUserGroups() {\n try {\n const { userEntityRef } = await identityApi.getBackstageIdentity();\n const { name: userId } = parseEntityRef(userEntityRef, {\n defaultKind: 'User',\n defaultNamespace: DEFAULT_NAMESPACE,\n });\n const g = await client.getUserGroups(userId);\n setGroups(g);\n } catch (e) {\n setError(e);\n } finally {\n dispatchLoadingGroups(false);\n }\n }\n\n getUserGroups();\n }, [client]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n if (!groups) return null;\n\n return (\n <GroupsContext.Provider value={{ groups: groups }}>\n {children}\n </GroupsContext.Provider>\n );\n};\n\nexport function useGroups(): Group[] {\n const context = useContext(GroupsContext);\n return context ? context.groups : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useGroups outside of GroupsProvider');\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCA,MAAM,oBAAmE,CAAC;AAAA,EACxE;AACF,CAAA,MAAO;AAAA,EACL,qBAAA,EAAuB,CAAC,SAAA,KACtB,QAAA,CAAS,EAAE,CAAC,oBAAA,CAAqB,UAAU,GAAG,SAAA,EAAW;AAC7D,CAAA,CAAA;AAMO,MAAM,aAAA,GAAgB,aAAA;AAAA,EAC3B;AACF;AAEO,MAAM,cAAA,GAAiB,CAAC,EAAE,QAAA,EAAS,KAA6B;AACrE,EAAA,MAAM,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAA,MAAM,MAAA,GAAS,OAAO,kBAAkB,CAAA;AACxC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,EAAE,qBAAA,EAAsB,GAAI,UAAA,CAAW,iBAAiB,CAAA;AAE9D,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAyB,IAAI,CAAA;AAEzD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,qBAAA,CAAsB,IAAI,CAAA;AAE1B,IAAA,eAAe,aAAA,GAAgB;AAC7B,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,YAAY,oBAAA,EAAqB;AACjE,QAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAO,GAAI,eAAe,aAAA,EAAe;AAAA,UACrD,WAAA,EAAa,MAAA;AAAA,UACb,gBAAA,EAAkB;AAAA,SACnB,CAAA;AACD,QAAA,MAAM,CAAA,GAAI,MAAM,MAAA,CAAO,aAAA,CAAc,MAAM,CAAA;AAC3C,QAAA,SAAA,CAAU,CAAC,CAAA;AAAA,MACb,SAAS,CAAA,EAAG;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AAAA,MACZ,CAAA,SAAE;AACA,QAAA,qBAAA,CAAsB,KAAK,CAAA;AAAA,MAC7B;AAAA,IACF;AAEA,IAAA,aAAA,EAAc;AAAA,EAChB,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAS,OAAA,EAAS,gBAAM,OAAA,EAAQ,CAAA;AAAA,EAChD;AAEA,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAEpB,EAAA,uBACE,GAAA,CAAC,cAAc,QAAA,EAAd,EAAuB,OAAO,EAAE,MAAA,IAC9B,QAAA,EACH,CAAA;AAEJ;AAEO,SAAS,SAAA,GAAqB;AACnC,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAA,OAAO,OAAA,GAAU,OAAA,CAAQ,MAAA,GAAS,WAAA,EAAY;AAChD;AAEA,SAAS,WAAA,GAAqB;AAC5B,EAAA,MAAM,MAAM,gDAAgD,CAAA;AAC9D;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { createContext, useState, useEffect, useContext } from 'react';
2
+ import { useState, useEffect, createContext, useContext } from 'react';
3
3
  import * as yup from 'yup';
4
4
  import Alert from '@material-ui/lab/Alert';
5
5
  import { costInsightsApiRef } from '../api/CostInsightsApi.esm.js';
@@ -1 +1 @@
1
- {"version":3,"file":"useLastCompleteBillingDate.esm.js","sources":["../../src/hooks/useLastCompleteBillingDate.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport * as yup from 'yup';\nimport Alert from '@material-ui/lab/Alert';\nimport { costInsightsApiRef } from '../api';\nimport { MapLoadingToProps, useLoading } from './useLoading';\nimport { DefaultLoadingAction } from '../utils/loading';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useApi } from '@backstage/core-plugin-api';\n\ntype BillingDateProviderLoadingProps = {\n dispatchLoadingBillingDate: (isLoading: boolean) => void;\n};\n\nconst mapLoadingToProps: MapLoadingToProps<BillingDateProviderLoadingProps> = ({\n dispatch,\n}) => ({\n dispatchLoadingBillingDate: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.LastCompleteBillingDate]: isLoading }),\n});\n\nexport type BillingDateContextProps = {\n lastCompleteBillingDate: string; // YYYY-MM-DD\n};\n\nexport const BillingDateContext = createContext<\n BillingDateContextProps | undefined\n>(undefined);\n\nexport const dateRegex: RegExp = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst dateFormatSchema = yup.string().matches(dateRegex, {\n message:\n 'Unsupported billing date format: ${value}. Date should be in YYYY-MM-DD format.',\n excludeEmptyString: true,\n});\n\nexport const BillingDateProvider = ({ children }: PropsWithChildren<{}>) => {\n const client = useApi(costInsightsApiRef);\n const [error, setError] = useState<Maybe<Error>>(null);\n const { dispatchLoadingBillingDate } = useLoading(mapLoadingToProps);\n\n const [lastCompleteBillingDate, setLastCompeteBillingDate] =\n useState<Maybe<string>>(null);\n\n useEffect(() => {\n dispatchLoadingBillingDate(true);\n\n async function getLastCompleteBillingDate() {\n try {\n const d = await client.getLastCompleteBillingDate();\n const validDate = await dateFormatSchema.validate(d);\n if (validDate) setLastCompeteBillingDate(validDate);\n } catch (e) {\n setError(e);\n } finally {\n dispatchLoadingBillingDate(false);\n }\n }\n\n getLastCompleteBillingDate();\n }, [client]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n if (!lastCompleteBillingDate) return null;\n\n return (\n <BillingDateContext.Provider\n value={\n {\n lastCompleteBillingDate: lastCompleteBillingDate,\n } as BillingDateContextProps\n }\n >\n {children}\n </BillingDateContext.Provider>\n );\n};\n\nexport function useLastCompleteBillingDate(): string {\n const context = useContext(BillingDateContext);\n return context ? context.lastCompleteBillingDate : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error(\n 'Cannot use useLastCompleteBillingDate outside of BillingDateProvider',\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCA,MAAM,oBAAwE,CAAC;AAAA,EAC7E;AACF,CAAO,MAAA;AAAA,EACL,0BAAA,EAA4B,CAAC,SAAA,KAC3B,QAAS,CAAA,EAAE,CAAC,oBAAqB,CAAA,uBAAuB,GAAG,SAAA,EAAW;AAC1E,CAAA,CAAA;AAMa,MAAA,kBAAA,GAAqB,cAEhC,KAAS,CAAA;AAEJ,MAAM,SAAoB,GAAA;AACjC,MAAM,gBAAmB,GAAA,GAAA,CAAI,MAAO,EAAA,CAAE,QAAQ,SAAW,EAAA;AAAA,EACvD,OACE,EAAA,iFAAA;AAAA,EACF,kBAAoB,EAAA;AACtB,CAAC,CAAA;AAEM,MAAM,mBAAsB,GAAA,CAAC,EAAE,QAAA,EAAsC,KAAA;AAC1E,EAAM,MAAA,MAAA,GAAS,OAAO,kBAAkB,CAAA;AACxC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,EAAE,0BAAA,EAA+B,GAAA,UAAA,CAAW,iBAAiB,CAAA;AAEnE,EAAA,MAAM,CAAC,uBAAA,EAAyB,yBAAyB,CAAA,GACvD,SAAwB,IAAI,CAAA;AAE9B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,0BAAA,CAA2B,IAAI,CAAA;AAE/B,IAAA,eAAe,0BAA6B,GAAA;AAC1C,MAAI,IAAA;AACF,QAAM,MAAA,CAAA,GAAI,MAAM,MAAA,CAAO,0BAA2B,EAAA;AAClD,QAAA,MAAM,SAAY,GAAA,MAAM,gBAAiB,CAAA,QAAA,CAAS,CAAC,CAAA;AACnD,QAAI,IAAA,SAAA,4BAAqC,SAAS,CAAA;AAAA,eAC3C,CAAG,EAAA;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AAAA,OACV,SAAA;AACA,QAAA,0BAAA,CAA2B,KAAK,CAAA;AAAA;AAClC;AAGF,IAA2B,0BAAA,EAAA;AAAA,GAC7B,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,uBAAQ,GAAA,CAAA,KAAA,EAAA,EAAM,QAAS,EAAA,OAAA,EAAS,gBAAM,OAAQ,EAAA,CAAA;AAAA;AAGhD,EAAI,IAAA,CAAC,yBAAgC,OAAA,IAAA;AAErC,EACE,uBAAA,GAAA;AAAA,IAAC,kBAAmB,CAAA,QAAA;AAAA,IAAnB;AAAA,MACC,KACE,EAAA;AAAA,QACE;AAAA,OACF;AAAA,MAGD;AAAA;AAAA,GACH;AAEJ;AAEO,SAAS,0BAAqC,GAAA;AACnD,EAAM,MAAA,OAAA,GAAU,WAAW,kBAAkB,CAAA;AAC7C,EAAO,OAAA,OAAA,GAAU,OAAQ,CAAA,uBAAA,GAA0B,WAAY,EAAA;AACjE;AAEA,SAAS,WAAqB,GAAA;AAC5B,EAAM,MAAA,KAAA;AAAA,IACJ;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"useLastCompleteBillingDate.esm.js","sources":["../../src/hooks/useLastCompleteBillingDate.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport * as yup from 'yup';\nimport Alert from '@material-ui/lab/Alert';\nimport { costInsightsApiRef } from '../api';\nimport { MapLoadingToProps, useLoading } from './useLoading';\nimport { DefaultLoadingAction } from '../utils/loading';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useApi } from '@backstage/core-plugin-api';\n\ntype BillingDateProviderLoadingProps = {\n dispatchLoadingBillingDate: (isLoading: boolean) => void;\n};\n\nconst mapLoadingToProps: MapLoadingToProps<BillingDateProviderLoadingProps> = ({\n dispatch,\n}) => ({\n dispatchLoadingBillingDate: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.LastCompleteBillingDate]: isLoading }),\n});\n\nexport type BillingDateContextProps = {\n lastCompleteBillingDate: string; // YYYY-MM-DD\n};\n\nexport const BillingDateContext = createContext<\n BillingDateContextProps | undefined\n>(undefined);\n\nexport const dateRegex: RegExp = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst dateFormatSchema = yup.string().matches(dateRegex, {\n message:\n 'Unsupported billing date format: ${value}. Date should be in YYYY-MM-DD format.',\n excludeEmptyString: true,\n});\n\nexport const BillingDateProvider = ({ children }: PropsWithChildren<{}>) => {\n const client = useApi(costInsightsApiRef);\n const [error, setError] = useState<Maybe<Error>>(null);\n const { dispatchLoadingBillingDate } = useLoading(mapLoadingToProps);\n\n const [lastCompleteBillingDate, setLastCompeteBillingDate] =\n useState<Maybe<string>>(null);\n\n useEffect(() => {\n dispatchLoadingBillingDate(true);\n\n async function getLastCompleteBillingDate() {\n try {\n const d = await client.getLastCompleteBillingDate();\n const validDate = await dateFormatSchema.validate(d);\n if (validDate) setLastCompeteBillingDate(validDate);\n } catch (e) {\n setError(e);\n } finally {\n dispatchLoadingBillingDate(false);\n }\n }\n\n getLastCompleteBillingDate();\n }, [client]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n if (!lastCompleteBillingDate) return null;\n\n return (\n <BillingDateContext.Provider\n value={\n {\n lastCompleteBillingDate: lastCompleteBillingDate,\n } as BillingDateContextProps\n }\n >\n {children}\n </BillingDateContext.Provider>\n );\n};\n\nexport function useLastCompleteBillingDate(): string {\n const context = useContext(BillingDateContext);\n return context ? context.lastCompleteBillingDate : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error(\n 'Cannot use useLastCompleteBillingDate outside of BillingDateProvider',\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCA,MAAM,oBAAwE,CAAC;AAAA,EAC7E;AACF,CAAA,MAAO;AAAA,EACL,0BAAA,EAA4B,CAAC,SAAA,KAC3B,QAAA,CAAS,EAAE,CAAC,oBAAA,CAAqB,uBAAuB,GAAG,SAAA,EAAW;AAC1E,CAAA,CAAA;AAMO,MAAM,kBAAA,GAAqB,cAEhC,MAAS;AAEJ,MAAM,SAAA,GAAoB;AACjC,MAAM,gBAAA,GAAmB,GAAA,CAAI,MAAA,EAAO,CAAE,QAAQ,SAAA,EAAW;AAAA,EACvD,OAAA,EACE,iFAAA;AAAA,EACF,kBAAA,EAAoB;AACtB,CAAC,CAAA;AAEM,MAAM,mBAAA,GAAsB,CAAC,EAAE,QAAA,EAAS,KAA6B;AAC1E,EAAA,MAAM,MAAA,GAAS,OAAO,kBAAkB,CAAA;AACxC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,EAAE,0BAAA,EAA2B,GAAI,UAAA,CAAW,iBAAiB,CAAA;AAEnE,EAAA,MAAM,CAAC,uBAAA,EAAyB,yBAAyB,CAAA,GACvD,SAAwB,IAAI,CAAA;AAE9B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,0BAAA,CAA2B,IAAI,CAAA;AAE/B,IAAA,eAAe,0BAAA,GAA6B;AAC1C,MAAA,IAAI;AACF,QAAA,MAAM,CAAA,GAAI,MAAM,MAAA,CAAO,0BAAA,EAA2B;AAClD,QAAA,MAAM,SAAA,GAAY,MAAM,gBAAA,CAAiB,QAAA,CAAS,CAAC,CAAA;AACnD,QAAA,IAAI,SAAA,4BAAqC,SAAS,CAAA;AAAA,MACpD,SAAS,CAAA,EAAG;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AAAA,MACZ,CAAA,SAAE;AACA,QAAA,0BAAA,CAA2B,KAAK,CAAA;AAAA,MAClC;AAAA,IACF;AAEA,IAAA,0BAAA,EAA2B;AAAA,EAC7B,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAS,OAAA,EAAS,gBAAM,OAAA,EAAQ,CAAA;AAAA,EAChD;AAEA,EAAA,IAAI,CAAC,yBAAyB,OAAO,IAAA;AAErC,EAAA,uBACE,GAAA;AAAA,IAAC,kBAAA,CAAmB,QAAA;AAAA,IAAnB;AAAA,MACC,KAAA,EACE;AAAA,QACE;AAAA,OACF;AAAA,MAGD;AAAA;AAAA,GACH;AAEJ;AAEO,SAAS,0BAAA,GAAqC;AACnD,EAAA,MAAM,OAAA,GAAU,WAAW,kBAAkB,CAAA;AAC7C,EAAA,OAAO,OAAA,GAAU,OAAA,CAAQ,uBAAA,GAA0B,WAAA,EAAY;AACjE;AAEA,SAAS,WAAA,GAAqB;AAC5B,EAAA,MAAM,KAAA;AAAA,IACJ;AAAA,GACF;AACF;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { createContext, useMemo, useReducer, useState, useEffect, useContext } from 'react';
2
+ import { useMemo, useReducer, useState, useEffect, createContext, useContext } from 'react';
3
3
  import Backdrop from '@material-ui/core/Backdrop';
4
4
  import CircularProgress from '@material-ui/core/CircularProgress';
5
5
  import { INITIAL_LOADING_ACTIONS, DefaultLoadingAction, getDefaultState } from '../utils/loading.esm.js';
@@ -1 +1 @@
1
- {"version":3,"file":"useLoading.esm.js","sources":["../../src/hooks/useLoading.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 createContext,\n Dispatch,\n PropsWithChildren,\n SetStateAction,\n useContext,\n useEffect,\n useMemo,\n useReducer,\n useState,\n} from 'react';\nimport Backdrop from '@material-ui/core/Backdrop';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport { Loading } from '../types';\nimport {\n DefaultLoadingAction,\n getDefaultState,\n INITIAL_LOADING_ACTIONS,\n} from '../utils/loading';\nimport { useBackdropStyles as useStyles } from '../utils/styles';\nimport { useConfig } from './useConfig';\n\nexport type LoadingContextProps = {\n state: Loading;\n dispatch: Dispatch<Partial<SetStateAction<Loading>>>;\n actions: Array<string>;\n};\n\nexport type MapLoadingToProps<T> = (props: LoadingContextProps) => T;\n\nexport const LoadingContext = createContext<LoadingContextProps | undefined>(\n undefined,\n);\n\nfunction reducer(prevState: Loading, action: Partial<Loading>): Loading {\n return {\n ...prevState,\n ...action,\n } as Record<string, boolean>;\n}\n\nexport const LoadingProvider = ({ children }: PropsWithChildren<{}>) => {\n const classes = useStyles();\n const { products } = useConfig();\n const actions = useMemo(\n () =>\n INITIAL_LOADING_ACTIONS.filter(\n action =>\n products.length ||\n action !== DefaultLoadingAction.CostInsightsProducts,\n ),\n [products],\n );\n const [state, dispatch] = useReducer(reducer, getDefaultState(actions));\n const [isBackdropVisible, setBackdropVisible] = useState(false);\n\n useEffect(() => {\n function displayLoadingBackdrop() {\n // Initial page loading is handled by progress bar\n setBackdropVisible(\n !state[DefaultLoadingAction.CostInsightsInitial] &&\n Object.values(state).some(l => l),\n );\n }\n displayLoadingBackdrop();\n }, [state, setBackdropVisible]);\n\n return (\n <LoadingContext.Provider value={{ state, actions, dispatch }}>\n {children}\n <Backdrop open={isBackdropVisible} classes={classes}>\n <CircularProgress />\n </Backdrop>\n </LoadingContext.Provider>\n );\n};\n\nexport function useLoading<T>(mapLoadingToProps: MapLoadingToProps<T>): T {\n const context = useContext(LoadingContext);\n\n if (!context) {\n assertNever();\n }\n\n return mapLoadingToProps({\n state: context.state,\n actions: context.actions,\n dispatch: context.dispatch,\n });\n}\n\nfunction assertNever(): never {\n throw Error('useLoading cannot be used outside of LoadingProvider');\n}\n"],"names":["useStyles"],"mappings":";;;;;;;;AA8CO,MAAM,cAAiB,GAAA,aAAA;AAAA,EAC5B,KAAA;AACF;AAEA,SAAS,OAAA,CAAQ,WAAoB,MAAmC,EAAA;AACtE,EAAO,OAAA;AAAA,IACL,GAAG,SAAA;AAAA,IACH,GAAG;AAAA,GACL;AACF;AAEO,MAAM,eAAkB,GAAA,CAAC,EAAE,QAAA,EAAsC,KAAA;AACtE,EAAA,MAAM,UAAUA,iBAAU,EAAA;AAC1B,EAAM,MAAA,EAAE,QAAS,EAAA,GAAI,SAAU,EAAA;AAC/B,EAAA,MAAM,OAAU,GAAA,OAAA;AAAA,IACd,MACE,uBAAwB,CAAA,MAAA;AAAA,MACtB,CACE,MAAA,KAAA,QAAA,CAAS,MACT,IAAA,MAAA,KAAW,oBAAqB,CAAA;AAAA,KACpC;AAAA,IACF,CAAC,QAAQ;AAAA,GACX;AACA,EAAM,MAAA,CAAC,OAAO,QAAQ,CAAA,GAAI,WAAW,OAAS,EAAA,eAAA,CAAgB,OAAO,CAAC,CAAA;AACtE,EAAA,MAAM,CAAC,iBAAA,EAAmB,kBAAkB,CAAA,GAAI,SAAS,KAAK,CAAA;AAE9D,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,SAAS,sBAAyB,GAAA;AAEhC,MAAA,kBAAA;AAAA,QACE,CAAC,KAAM,CAAA,oBAAA,CAAqB,mBAAmB,CAAA,IAC7C,MAAO,CAAA,MAAA,CAAO,KAAK,CAAA,CAAE,IAAK,CAAA,CAAA,CAAA,KAAK,CAAC;AAAA,OACpC;AAAA;AAEF,IAAuB,sBAAA,EAAA;AAAA,GACtB,EAAA,CAAC,KAAO,EAAA,kBAAkB,CAAC,CAAA;AAE9B,EACE,uBAAA,IAAA,CAAC,eAAe,QAAf,EAAA,EAAwB,OAAO,EAAE,KAAA,EAAO,OAAS,EAAA,QAAA,EAC/C,EAAA,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,wBACA,QAAS,EAAA,EAAA,IAAA,EAAM,mBAAmB,OACjC,EAAA,QAAA,kBAAA,GAAA,CAAC,oBAAiB,CACpB,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;AAEO,SAAS,WAAc,iBAA4C,EAAA;AACxE,EAAM,MAAA,OAAA,GAAU,WAAW,cAAc,CAAA;AAEzC,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAY,WAAA,EAAA;AAAA;AAGd,EAAA,OAAO,iBAAkB,CAAA;AAAA,IACvB,OAAO,OAAQ,CAAA,KAAA;AAAA,IACf,SAAS,OAAQ,CAAA,OAAA;AAAA,IACjB,UAAU,OAAQ,CAAA;AAAA,GACnB,CAAA;AACH;AAEA,SAAS,WAAqB,GAAA;AAC5B,EAAA,MAAM,MAAM,sDAAsD,CAAA;AACpE;;;;"}
1
+ {"version":3,"file":"useLoading.esm.js","sources":["../../src/hooks/useLoading.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 createContext,\n Dispatch,\n PropsWithChildren,\n SetStateAction,\n useContext,\n useEffect,\n useMemo,\n useReducer,\n useState,\n} from 'react';\nimport Backdrop from '@material-ui/core/Backdrop';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport { Loading } from '../types';\nimport {\n DefaultLoadingAction,\n getDefaultState,\n INITIAL_LOADING_ACTIONS,\n} from '../utils/loading';\nimport { useBackdropStyles as useStyles } from '../utils/styles';\nimport { useConfig } from './useConfig';\n\nexport type LoadingContextProps = {\n state: Loading;\n dispatch: Dispatch<Partial<SetStateAction<Loading>>>;\n actions: Array<string>;\n};\n\nexport type MapLoadingToProps<T> = (props: LoadingContextProps) => T;\n\nexport const LoadingContext = createContext<LoadingContextProps | undefined>(\n undefined,\n);\n\nfunction reducer(prevState: Loading, action: Partial<Loading>): Loading {\n return {\n ...prevState,\n ...action,\n } as Record<string, boolean>;\n}\n\nexport const LoadingProvider = ({ children }: PropsWithChildren<{}>) => {\n const classes = useStyles();\n const { products } = useConfig();\n const actions = useMemo(\n () =>\n INITIAL_LOADING_ACTIONS.filter(\n action =>\n products.length ||\n action !== DefaultLoadingAction.CostInsightsProducts,\n ),\n [products],\n );\n const [state, dispatch] = useReducer(reducer, getDefaultState(actions));\n const [isBackdropVisible, setBackdropVisible] = useState(false);\n\n useEffect(() => {\n function displayLoadingBackdrop() {\n // Initial page loading is handled by progress bar\n setBackdropVisible(\n !state[DefaultLoadingAction.CostInsightsInitial] &&\n Object.values(state).some(l => l),\n );\n }\n displayLoadingBackdrop();\n }, [state, setBackdropVisible]);\n\n return (\n <LoadingContext.Provider value={{ state, actions, dispatch }}>\n {children}\n <Backdrop open={isBackdropVisible} classes={classes}>\n <CircularProgress />\n </Backdrop>\n </LoadingContext.Provider>\n );\n};\n\nexport function useLoading<T>(mapLoadingToProps: MapLoadingToProps<T>): T {\n const context = useContext(LoadingContext);\n\n if (!context) {\n assertNever();\n }\n\n return mapLoadingToProps({\n state: context.state,\n actions: context.actions,\n dispatch: context.dispatch,\n });\n}\n\nfunction assertNever(): never {\n throw Error('useLoading cannot be used outside of LoadingProvider');\n}\n"],"names":["useStyles"],"mappings":";;;;;;;;AA8CO,MAAM,cAAA,GAAiB,aAAA;AAAA,EAC5B;AACF;AAEA,SAAS,OAAA,CAAQ,WAAoB,MAAA,EAAmC;AACtE,EAAA,OAAO;AAAA,IACL,GAAG,SAAA;AAAA,IACH,GAAG;AAAA,GACL;AACF;AAEO,MAAM,eAAA,GAAkB,CAAC,EAAE,QAAA,EAAS,KAA6B;AACtE,EAAA,MAAM,UAAUA,iBAAA,EAAU;AAC1B,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,SAAA,EAAU;AAC/B,EAAA,MAAM,OAAA,GAAU,OAAA;AAAA,IACd,MACE,uBAAA,CAAwB,MAAA;AAAA,MACtB,CAAA,MAAA,KACE,QAAA,CAAS,MAAA,IACT,MAAA,KAAW,oBAAA,CAAqB;AAAA,KACpC;AAAA,IACF,CAAC,QAAQ;AAAA,GACX;AACA,EAAA,MAAM,CAAC,OAAO,QAAQ,CAAA,GAAI,WAAW,OAAA,EAAS,eAAA,CAAgB,OAAO,CAAC,CAAA;AACtE,EAAA,MAAM,CAAC,iBAAA,EAAmB,kBAAkB,CAAA,GAAI,SAAS,KAAK,CAAA;AAE9D,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,SAAS,sBAAA,GAAyB;AAEhC,MAAA,kBAAA;AAAA,QACE,CAAC,KAAA,CAAM,oBAAA,CAAqB,mBAAmB,CAAA,IAC7C,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,KAAK,CAAC;AAAA,OACpC;AAAA,IACF;AACA,IAAA,sBAAA,EAAuB;AAAA,EACzB,CAAA,EAAG,CAAC,KAAA,EAAO,kBAAkB,CAAC,CAAA;AAE9B,EAAA,uBACE,IAAA,CAAC,eAAe,QAAA,EAAf,EAAwB,OAAO,EAAE,KAAA,EAAO,OAAA,EAAS,QAAA,EAAS,EACxD,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,wBACA,QAAA,EAAA,EAAS,IAAA,EAAM,mBAAmB,OAAA,EACjC,QAAA,kBAAA,GAAA,CAAC,oBAAiB,CAAA,EACpB;AAAA,GAAA,EACF,CAAA;AAEJ;AAEO,SAAS,WAAc,iBAAA,EAA4C;AACxE,EAAA,MAAM,OAAA,GAAU,WAAW,cAAc,CAAA;AAEzC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,WAAA,EAAY;AAAA,EACd;AAEA,EAAA,OAAO,iBAAA,CAAkB;AAAA,IACvB,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,UAAU,OAAA,CAAQ;AAAA,GACnB,CAAA;AACH;AAEA,SAAS,WAAA,GAAqB;AAC5B,EAAA,MAAM,MAAM,sDAAsD,CAAA;AACpE;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { createContext, useState, useContext } from 'react';
2
+ import { useState, createContext, useContext } from 'react';
3
3
 
4
4
  const ScrollContext = createContext(
5
5
  void 0
@@ -1 +1 @@
1
- {"version":3,"file":"useScroll.esm.js","sources":["../../src/hooks/useScroll.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 {\n createContext,\n Dispatch,\n SetStateAction,\n useState,\n useContext,\n PropsWithChildren,\n} from 'react';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\n\nexport type ScrollTo = Maybe<string>;\n\nexport type ScrollContextProps = {\n scroll: ScrollTo;\n setScroll: Dispatch<SetStateAction<ScrollTo>>;\n};\n\nexport const ScrollContext = createContext<ScrollContextProps | undefined>(\n undefined,\n);\n\nexport const ScrollProvider = ({ children }: PropsWithChildren<{}>) => {\n const [scroll, setScroll] = useState<ScrollTo>(null);\n return (\n <ScrollContext.Provider value={{ scroll, setScroll }}>\n {children}\n </ScrollContext.Provider>\n );\n};\n\nexport enum ScrollType {\n AlertSummary = 'alert-status-summary',\n}\n\nexport function useScroll() {\n const context = useContext(ScrollContext);\n\n if (!context) {\n assertNever();\n }\n\n return [context.scroll, context.setScroll] as const;\n}\n\nfunction assertNever(): never {\n throw new Error(`Cannot use useScroll outside ScrollProvider`);\n}\n"],"names":["ScrollType"],"mappings":";;;AAgCO,MAAM,aAAgB,GAAA,aAAA;AAAA,EAC3B,KAAA;AACF;AAEO,MAAM,cAAiB,GAAA,CAAC,EAAE,QAAA,EAAsC,KAAA;AACrE,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAmB,IAAI,CAAA;AACnD,EACE,uBAAA,GAAA,CAAC,cAAc,QAAd,EAAA,EAAuB,OAAO,EAAE,MAAA,EAAQ,SAAU,EAAA,EAChD,QACH,EAAA,CAAA;AAEJ;AAEY,IAAA,UAAA,qBAAAA,WAAL,KAAA;AACL,EAAAA,YAAA,cAAe,CAAA,GAAA,sBAAA;AADL,EAAAA,OAAAA,WAAAA;AAAA,CAAA,EAAA,UAAA,IAAA,EAAA;AAIL,SAAS,SAAY,GAAA;AAC1B,EAAM,MAAA,OAAA,GAAU,WAAW,aAAa,CAAA;AAExC,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAY,WAAA,EAAA;AAAA;AAGd,EAAA,OAAO,CAAC,OAAA,CAAQ,MAAQ,EAAA,OAAA,CAAQ,SAAS,CAAA;AAC3C;AAEA,SAAS,WAAqB,GAAA;AAC5B,EAAM,MAAA,IAAI,MAAM,CAA6C,2CAAA,CAAA,CAAA;AAC/D;;;;"}
1
+ {"version":3,"file":"useScroll.esm.js","sources":["../../src/hooks/useScroll.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\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 {\n createContext,\n Dispatch,\n SetStateAction,\n useState,\n useContext,\n PropsWithChildren,\n} from 'react';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\n\nexport type ScrollTo = Maybe<string>;\n\nexport type ScrollContextProps = {\n scroll: ScrollTo;\n setScroll: Dispatch<SetStateAction<ScrollTo>>;\n};\n\nexport const ScrollContext = createContext<ScrollContextProps | undefined>(\n undefined,\n);\n\nexport const ScrollProvider = ({ children }: PropsWithChildren<{}>) => {\n const [scroll, setScroll] = useState<ScrollTo>(null);\n return (\n <ScrollContext.Provider value={{ scroll, setScroll }}>\n {children}\n </ScrollContext.Provider>\n );\n};\n\nexport enum ScrollType {\n AlertSummary = 'alert-status-summary',\n}\n\nexport function useScroll() {\n const context = useContext(ScrollContext);\n\n if (!context) {\n assertNever();\n }\n\n return [context.scroll, context.setScroll] as const;\n}\n\nfunction assertNever(): never {\n throw new Error(`Cannot use useScroll outside ScrollProvider`);\n}\n"],"names":["ScrollType"],"mappings":";;;AAgCO,MAAM,aAAA,GAAgB,aAAA;AAAA,EAC3B;AACF;AAEO,MAAM,cAAA,GAAiB,CAAC,EAAE,QAAA,EAAS,KAA6B;AACrE,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAmB,IAAI,CAAA;AACnD,EAAA,uBACE,GAAA,CAAC,cAAc,QAAA,EAAd,EAAuB,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAU,EAChD,QAAA,EACH,CAAA;AAEJ;AAEO,IAAK,UAAA,qBAAAA,WAAAA,KAAL;AACL,EAAAA,YAAA,cAAA,CAAA,GAAe,sBAAA;AADL,EAAA,OAAAA,WAAAA;AAAA,CAAA,EAAA,UAAA,IAAA,EAAA;AAIL,SAAS,SAAA,GAAY;AAC1B,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AAExC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,WAAA,EAAY;AAAA,EACd;AAEA,EAAA,OAAO,CAAC,OAAA,CAAQ,MAAA,EAAQ,OAAA,CAAQ,SAAS,CAAA;AAC3C;AAEA,SAAS,WAAA,GAAqB;AAC5B,EAAA,MAAM,IAAI,MAAM,CAAA,2CAAA,CAA6C,CAAA;AAC/D;;;;"}