@backstage-community/plugin-cost-insights 0.15.1 → 0.16.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 (150) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/alerts/ProjectGrowthAlert.esm.js +2 -2
  3. package/dist/alerts/ProjectGrowthAlert.esm.js.map +1 -1
  4. package/dist/alerts/UnlabeledDataflowAlert.esm.js +2 -2
  5. package/dist/alerts/UnlabeledDataflowAlert.esm.js.map +1 -1
  6. package/dist/components/ActionItems/ActionItemCard.esm.js +3 -3
  7. package/dist/components/ActionItems/ActionItemCard.esm.js.map +1 -1
  8. package/dist/components/ActionItems/ActionItems.esm.js +52 -41
  9. package/dist/components/ActionItems/ActionItems.esm.js.map +1 -1
  10. package/dist/components/AlertInsights/AlertDialog.esm.js +79 -58
  11. package/dist/components/AlertInsights/AlertDialog.esm.js.map +1 -1
  12. package/dist/components/AlertInsights/AlertInsights.esm.js +57 -44
  13. package/dist/components/AlertInsights/AlertInsights.esm.js.map +1 -1
  14. package/dist/components/AlertInsights/AlertInsightsHeader.esm.js +10 -2
  15. package/dist/components/AlertInsights/AlertInsightsHeader.esm.js.map +1 -1
  16. package/dist/components/AlertInsights/AlertInsightsSection.esm.js +42 -34
  17. package/dist/components/AlertInsights/AlertInsightsSection.esm.js.map +1 -1
  18. package/dist/components/AlertInsights/AlertInsightsSectionHeader.esm.js +23 -12
  19. package/dist/components/AlertInsights/AlertInsightsSectionHeader.esm.js.map +1 -1
  20. package/dist/components/AlertInsights/AlertStatusSummary.esm.js +63 -55
  21. package/dist/components/AlertInsights/AlertStatusSummary.esm.js.map +1 -1
  22. package/dist/components/AlertInsights/AlertStatusSummaryButton.esm.js +7 -6
  23. package/dist/components/AlertInsights/AlertStatusSummaryButton.esm.js.map +1 -1
  24. package/dist/components/AlertInstructionsLayout/AlertInstructionsLayout.esm.js +23 -17
  25. package/dist/components/AlertInstructionsLayout/AlertInstructionsLayout.esm.js.map +1 -1
  26. package/dist/components/BarChart/BarChart.esm.js +83 -78
  27. package/dist/components/BarChart/BarChart.esm.js.map +1 -1
  28. package/dist/components/BarChart/BarChartLabel.esm.js +8 -5
  29. package/dist/components/BarChart/BarChartLabel.esm.js.map +1 -1
  30. package/dist/components/BarChart/BarChartLegend.esm.js +20 -16
  31. package/dist/components/BarChart/BarChartLegend.esm.js.map +1 -1
  32. package/dist/components/BarChart/BarChartStepper.esm.js +51 -48
  33. package/dist/components/BarChart/BarChartStepper.esm.js.map +1 -1
  34. package/dist/components/BarChart/BarChartStepperButton.esm.js +6 -5
  35. package/dist/components/BarChart/BarChartStepperButton.esm.js.map +1 -1
  36. package/dist/components/BarChart/BarChartSteps.esm.js +3 -3
  37. package/dist/components/BarChart/BarChartSteps.esm.js.map +1 -1
  38. package/dist/components/BarChart/BarChartTick.esm.js +5 -5
  39. package/dist/components/BarChart/BarChartTick.esm.js.map +1 -1
  40. package/dist/components/BarChart/BarChartTooltip.esm.js +27 -14
  41. package/dist/components/BarChart/BarChartTooltip.esm.js.map +1 -1
  42. package/dist/components/BarChart/BarChartTooltipItem.esm.js +11 -6
  43. package/dist/components/BarChart/BarChartTooltipItem.esm.js.map +1 -1
  44. package/dist/components/CopyUrlToClipboard/CopyUrlToClipboard.esm.js +3 -2
  45. package/dist/components/CopyUrlToClipboard/CopyUrlToClipboard.esm.js.map +1 -1
  46. package/dist/components/CostGrowth/CostGrowth.esm.js +26 -7
  47. package/dist/components/CostGrowth/CostGrowth.esm.js.map +1 -1
  48. package/dist/components/CostGrowth/CostGrowthIndicator.esm.js +6 -2
  49. package/dist/components/CostGrowth/CostGrowthIndicator.esm.js.map +1 -1
  50. package/dist/components/CostInsightsHeader/CostInsightsHeader.esm.js +77 -8
  51. package/dist/components/CostInsightsHeader/CostInsightsHeader.esm.js.map +1 -1
  52. package/dist/components/CostInsightsLayout/CostInsightsLayout.esm.js +16 -10
  53. package/dist/components/CostInsightsLayout/CostInsightsLayout.esm.js.map +1 -1
  54. package/dist/components/CostInsightsNavigation/CostInsightsNavigation.esm.js +41 -35
  55. package/dist/components/CostInsightsNavigation/CostInsightsNavigation.esm.js.map +1 -1
  56. package/dist/components/CostInsightsPage/CostInsightsPage.esm.js +116 -79
  57. package/dist/components/CostInsightsPage/CostInsightsPage.esm.js.map +1 -1
  58. package/dist/components/CostInsightsPage/CostInsightsPageRoot.esm.js +2 -2
  59. package/dist/components/CostInsightsPage/CostInsightsPageRoot.esm.js.map +1 -1
  60. package/dist/components/CostInsightsPage/CostInsightsThemeProvider.esm.js +5 -5
  61. package/dist/components/CostInsightsPage/CostInsightsThemeProvider.esm.js.map +1 -1
  62. package/dist/components/CostInsightsTabs/CostInsightsTabs.esm.js +58 -51
  63. package/dist/components/CostInsightsTabs/CostInsightsTabs.esm.js.map +1 -1
  64. package/dist/components/CostOverviewCard/CostOverviewBreakdownChart.esm.js +74 -59
  65. package/dist/components/CostOverviewCard/CostOverviewBreakdownChart.esm.js.map +1 -1
  66. package/dist/components/CostOverviewCard/CostOverviewCard.esm.js +45 -35
  67. package/dist/components/CostOverviewCard/CostOverviewCard.esm.js.map +1 -1
  68. package/dist/components/CostOverviewCard/CostOverviewChart.esm.js +86 -73
  69. package/dist/components/CostOverviewCard/CostOverviewChart.esm.js.map +1 -1
  70. package/dist/components/CostOverviewCard/CostOverviewHeader.esm.js +11 -6
  71. package/dist/components/CostOverviewCard/CostOverviewHeader.esm.js.map +1 -1
  72. package/dist/components/CostOverviewCard/CostOverviewLegend.esm.js +21 -15
  73. package/dist/components/CostOverviewCard/CostOverviewLegend.esm.js.map +1 -1
  74. package/dist/components/CurrencySelect/CurrencySelect.esm.js +24 -21
  75. package/dist/components/CurrencySelect/CurrencySelect.esm.js.map +1 -1
  76. package/dist/components/EntityCosts/EntityCosts.esm.js +8 -7
  77. package/dist/components/EntityCosts/EntityCosts.esm.js.map +1 -1
  78. package/dist/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.esm.js +65 -20
  79. package/dist/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.esm.js.map +1 -1
  80. package/dist/components/LegendItem/LegendItem.esm.js +34 -29
  81. package/dist/components/LegendItem/LegendItem.esm.js.map +1 -1
  82. package/dist/components/MetricSelect/MetricSelect.esm.js +19 -14
  83. package/dist/components/MetricSelect/MetricSelect.esm.js.map +1 -1
  84. package/dist/components/PeriodSelect/PeriodSelect.esm.js +15 -15
  85. package/dist/components/PeriodSelect/PeriodSelect.esm.js.map +1 -1
  86. package/dist/components/ProductInsights/ProductInsights.esm.js +12 -8
  87. package/dist/components/ProductInsights/ProductInsights.esm.js.map +1 -1
  88. package/dist/components/ProductInsightsCard/ProductEntityDialog.esm.js +20 -15
  89. package/dist/components/ProductInsightsCard/ProductEntityDialog.esm.js.map +1 -1
  90. package/dist/components/ProductInsightsCard/ProductEntityTable.esm.js +9 -9
  91. package/dist/components/ProductInsightsCard/ProductEntityTable.esm.js.map +1 -1
  92. package/dist/components/ProductInsightsCard/ProductInsightsCard.esm.js +25 -15
  93. package/dist/components/ProductInsightsCard/ProductInsightsCard.esm.js.map +1 -1
  94. package/dist/components/ProductInsightsCard/ProductInsightsCardList.esm.js +14 -14
  95. package/dist/components/ProductInsightsCard/ProductInsightsCardList.esm.js.map +1 -1
  96. package/dist/components/ProductInsightsCard/ProductInsightsChart.esm.js +43 -35
  97. package/dist/components/ProductInsightsCard/ProductInsightsChart.esm.js.map +1 -1
  98. package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.esm.js +5 -5
  99. package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.esm.js.map +1 -1
  100. package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertChart.esm.js +5 -2
  101. package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertChart.esm.js.map +1 -1
  102. package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js +55 -9
  103. package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js.map +1 -1
  104. package/dist/components/ProjectSelect/ProjectSelect.esm.js +15 -15
  105. package/dist/components/ProjectSelect/ProjectSelect.esm.js.map +1 -1
  106. package/dist/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.esm.js +12 -9
  107. package/dist/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.esm.js.map +1 -1
  108. package/dist/components/WhyCostsMatter/WhyCostsMatter.esm.js +40 -10
  109. package/dist/components/WhyCostsMatter/WhyCostsMatter.esm.js.map +1 -1
  110. package/dist/example/alerts/KubernetesMigrationAlert.esm.js +10 -3
  111. package/dist/example/alerts/KubernetesMigrationAlert.esm.js.map +1 -1
  112. package/dist/example/client.esm.js +1 -1
  113. package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.esm.js +20 -17
  114. package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.esm.js.map +1 -1
  115. package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.esm.js +3 -2
  116. package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.esm.js.map +1 -1
  117. package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.esm.js +14 -9
  118. package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.esm.js.map +1 -1
  119. package/dist/example/forms/KubernetesMigrationDismissForm.esm.js +21 -17
  120. package/dist/example/forms/KubernetesMigrationDismissForm.esm.js.map +1 -1
  121. package/dist/forms/AlertAcceptForm.esm.js +5 -4
  122. package/dist/forms/AlertAcceptForm.esm.js.map +1 -1
  123. package/dist/forms/AlertDismissForm.esm.js +47 -38
  124. package/dist/forms/AlertDismissForm.esm.js.map +1 -1
  125. package/dist/forms/AlertSnoozeForm.esm.js +20 -16
  126. package/dist/forms/AlertSnoozeForm.esm.js.map +1 -1
  127. package/dist/hooks/useConfig.esm.js +3 -2
  128. package/dist/hooks/useConfig.esm.js.map +1 -1
  129. package/dist/hooks/useCurrency.esm.js +6 -3
  130. package/dist/hooks/useCurrency.esm.js.map +1 -1
  131. package/dist/hooks/useFilters.esm.js +10 -7
  132. package/dist/hooks/useFilters.esm.js.map +1 -1
  133. package/dist/hooks/useGroups.esm.js +7 -4
  134. package/dist/hooks/useGroups.esm.js.map +1 -1
  135. package/dist/hooks/useLastCompleteBillingDate.esm.js +8 -7
  136. package/dist/hooks/useLastCompleteBillingDate.esm.js.map +1 -1
  137. package/dist/hooks/useLoading.esm.js +6 -2
  138. package/dist/hooks/useLoading.esm.js.map +1 -1
  139. package/dist/hooks/useScroll.esm.js +6 -3
  140. package/dist/hooks/useScroll.esm.js.map +1 -1
  141. package/dist/index.d.ts +17 -17
  142. package/dist/index.esm.js +2 -1
  143. package/dist/index.esm.js.map +1 -1
  144. package/dist/testUtils/providers.esm.js +3 -3
  145. package/dist/testUtils/providers.esm.js.map +1 -1
  146. package/dist/utils/navigation.esm.js +10 -10
  147. package/dist/utils/navigation.esm.js.map +1 -1
  148. package/dist/utils/scroll.esm.js +3 -2
  149. package/dist/utils/scroll.esm.js.map +1 -1
  150. package/package.json +18 -11
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectGrowthInstructionsPage.esm.js","sources":["../../../src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.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 React from 'react';\nimport { DateTime } from 'luxon';\nimport Box from '@material-ui/core/Box';\nimport Typography from '@material-ui/core/Typography';\nimport { AlertInstructionsLayout } from '../AlertInstructionsLayout';\nimport { ProductInsightsChart } from '../ProductInsightsCard';\nimport {\n Alert,\n DEFAULT_DATE_FORMAT,\n Duration,\n ProjectGrowthData,\n} from '../../types';\nimport {\n Entity,\n Product,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { ProjectGrowthAlert } from '../../alerts';\nimport { InfoCard } from '@backstage/core-components';\n\nconst today = DateTime.now().toFormat(DEFAULT_DATE_FORMAT);\n\nexport const ProjectGrowthInstructionsPage = () => {\n const alertData: ProjectGrowthData = {\n project: 'example-project',\n periodStart: 'Q1 2020',\n periodEnd: 'Q2 2020',\n aggregation: [60000, 120000],\n change: {\n ratio: 1,\n amount: 60000,\n },\n products: [\n {\n id: 'Compute Engine',\n aggregation: [58000, 118000],\n },\n {\n id: 'Cloud Dataflow',\n aggregation: [1200, 1500],\n },\n {\n id: 'Cloud Storage',\n aggregation: [800, 500],\n },\n ],\n };\n\n const projectGrowthAlert: Alert = new ProjectGrowthAlert(alertData);\n\n const product: Product = {\n kind: 'ComputeEngine',\n name: 'Compute Engine',\n };\n\n const entity: Entity = {\n id: 'example-id',\n aggregation: [20_000, 60_000],\n change: {\n ratio: 3,\n amount: 40_000,\n },\n entities: {\n service: [\n {\n id: 'service-one',\n aggregation: [18_200, 58_500],\n entities: {},\n change: { ratio: 2.21, amount: 40_300 },\n },\n {\n id: 'service-two',\n aggregation: [1200, 1300],\n entities: {},\n change: { ratio: 0.083, amount: 100 },\n },\n {\n id: 'service-three',\n aggregation: [600, 200],\n entities: {},\n change: { ratio: -0.666, amount: -400 },\n },\n ],\n },\n };\n\n return (\n <AlertInstructionsLayout title=\"Investigating Growth\">\n <Typography variant=\"h1\">Investigating cloud cost growth</Typography>\n <Typography paragraph>\n Cost Insights shows an alert when costs for a particular billing entity,\n such as a GCP project, have grown at a rate faster than our alerting\n threshold. The responsible team should follow this guide to decide\n whether this warrants further investigation.\n </Typography>\n\n <Box mt={4}>\n <Typography variant=\"h3\">Is the growth expected?</Typography>\n <Typography paragraph>\n The first question to ask is whether growth is expected. Perhaps a new\n product has been deployed, or additional regions added for\n reliability.\n </Typography>\n <Typography paragraph>\n Many services increase cost linearly with load. Has the demand\n increased? This may happen as you open new markets, or run marketing\n offers. Costs should be compared against a business metric, such as\n daily users, to normalize natural increases from business growth.\n </Typography>\n <Typography paragraph>\n Seasonal variance may also cause cost growth; yearly campaigns, an\n increase in demand during certain times of year.\n </Typography>\n <Typography paragraph>\n Cloud costs will often go up before they go down, in the case of\n migrations. Teams moving to new infrastructure may run in both the old\n and new environment during the migration.\n </Typography>\n </Box>\n\n <Box mt={4}>\n <Typography variant=\"h3\">Is the growth significant?</Typography>\n <Typography paragraph>\n Next, evaluate whether the growth is significant. This helps avoid\n premature optimization, where cost in engineering time is more than\n would be saved from the optimization over a reasonable time frame.\n </Typography>\n <Typography paragraph>\n We recommend reframing the cost growth itself in terms of engineering\n time. How much engineering time, for an <i>average</i> fully-loaded\n engineer cost at the company, is being overspent each month? Compare\n this to expected engineering time for optimization to decide whether\n the optimization is worthwhile.\n </Typography>\n </Box>\n\n <Box mt={4}>\n <Typography variant=\"h3\">\n Identifying which cloud product contributed most\n </Typography>\n <Typography paragraph>\n For projects meeting the alert threshold, Cost Insights shows a cost\n comparison of cloud products over the examined time period:\n </Typography>\n <Box mt={2} mb={2}>\n {projectGrowthAlert.element}\n </Box>\n <Typography paragraph>\n This allows you to quickly see which cloud products contributed to the\n growth in cloud costs.\n </Typography>\n </Box>\n\n <Box mt={4}>\n <Typography variant=\"h3\">\n Identifying the responsible workload\n </Typography>\n <Typography paragraph>\n After identifying the cloud product, use the corresponding product\n panel in Cost Insights to find a particular workload (or <i>entity</i>\n ) that has grown in cost:\n </Typography>\n <Box mt={2} mb={2}>\n <InfoCard title={product.name} subheader=\"3 entities, sorted by cost\">\n <ProductInsightsChart\n billingDate={today}\n duration={Duration.P3M}\n entity={entity}\n />\n </InfoCard>\n </Box>\n <Typography paragraph>\n From here, you can dig into commit history or deployment logs to find\n probable causes of an unexpected spike in cost.\n </Typography>\n </Box>\n\n <Box mt={4}>\n <Typography variant=\"h3\">Optimizing the workload</Typography>\n <Typography paragraph>\n Workload optimization varies between cloud products, but there are a\n few general optimization areas to consider:\n </Typography>\n <Typography variant=\"h5\">Retention</Typography>\n <Typography paragraph>\n Is the workload or storage necessary? Truly idle or unused resources\n can be cleaned up for immediate cost savings. For storage, how long do\n we need the data? Many cloud products support retention policies to\n automatically delete data after a certain time period.\n </Typography>\n <Typography variant=\"h5\">Efficiency</Typography>\n <Typography paragraph>\n Is the workload using cloud resources efficiently? For compute\n resources, do the utilization metrics look reasonable? Autoscaling\n infrastructure, such as Kubernetes, can run workloads more efficiently\n without compromising reliability.\n </Typography>\n <Typography variant=\"h5\">Lifecycle</Typography>\n <Typography paragraph>\n Is the workload using an optimal pricing model? Some cloud products\n offer better pricing for data that is accessed less frequently.\n </Typography>\n </Box>\n </AlertInstructionsLayout>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ProjectGrowthInstructionsPage.esm.js","sources":["../../../src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.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 { DateTime } from 'luxon';\nimport Box from '@material-ui/core/Box';\nimport Typography from '@material-ui/core/Typography';\nimport { AlertInstructionsLayout } from '../AlertInstructionsLayout';\nimport { ProductInsightsChart } from '../ProductInsightsCard';\nimport {\n Alert,\n DEFAULT_DATE_FORMAT,\n Duration,\n ProjectGrowthData,\n} from '../../types';\nimport {\n Entity,\n Product,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { ProjectGrowthAlert } from '../../alerts';\nimport { InfoCard } from '@backstage/core-components';\n\nconst today = DateTime.now().toFormat(DEFAULT_DATE_FORMAT);\n\nexport const ProjectGrowthInstructionsPage = () => {\n const alertData: ProjectGrowthData = {\n project: 'example-project',\n periodStart: 'Q1 2020',\n periodEnd: 'Q2 2020',\n aggregation: [60000, 120000],\n change: {\n ratio: 1,\n amount: 60000,\n },\n products: [\n {\n id: 'Compute Engine',\n aggregation: [58000, 118000],\n },\n {\n id: 'Cloud Dataflow',\n aggregation: [1200, 1500],\n },\n {\n id: 'Cloud Storage',\n aggregation: [800, 500],\n },\n ],\n };\n\n const projectGrowthAlert: Alert = new ProjectGrowthAlert(alertData);\n\n const product: Product = {\n kind: 'ComputeEngine',\n name: 'Compute Engine',\n };\n\n const entity: Entity = {\n id: 'example-id',\n aggregation: [20_000, 60_000],\n change: {\n ratio: 3,\n amount: 40_000,\n },\n entities: {\n service: [\n {\n id: 'service-one',\n aggregation: [18_200, 58_500],\n entities: {},\n change: { ratio: 2.21, amount: 40_300 },\n },\n {\n id: 'service-two',\n aggregation: [1200, 1300],\n entities: {},\n change: { ratio: 0.083, amount: 100 },\n },\n {\n id: 'service-three',\n aggregation: [600, 200],\n entities: {},\n change: { ratio: -0.666, amount: -400 },\n },\n ],\n },\n };\n\n return (\n <AlertInstructionsLayout title=\"Investigating Growth\">\n <Typography variant=\"h1\">Investigating cloud cost growth</Typography>\n <Typography paragraph>\n Cost Insights shows an alert when costs for a particular billing entity,\n such as a GCP project, have grown at a rate faster than our alerting\n threshold. The responsible team should follow this guide to decide\n whether this warrants further investigation.\n </Typography>\n\n <Box mt={4}>\n <Typography variant=\"h3\">Is the growth expected?</Typography>\n <Typography paragraph>\n The first question to ask is whether growth is expected. Perhaps a new\n product has been deployed, or additional regions added for\n reliability.\n </Typography>\n <Typography paragraph>\n Many services increase cost linearly with load. Has the demand\n increased? This may happen as you open new markets, or run marketing\n offers. Costs should be compared against a business metric, such as\n daily users, to normalize natural increases from business growth.\n </Typography>\n <Typography paragraph>\n Seasonal variance may also cause cost growth; yearly campaigns, an\n increase in demand during certain times of year.\n </Typography>\n <Typography paragraph>\n Cloud costs will often go up before they go down, in the case of\n migrations. Teams moving to new infrastructure may run in both the old\n and new environment during the migration.\n </Typography>\n </Box>\n\n <Box mt={4}>\n <Typography variant=\"h3\">Is the growth significant?</Typography>\n <Typography paragraph>\n Next, evaluate whether the growth is significant. This helps avoid\n premature optimization, where cost in engineering time is more than\n would be saved from the optimization over a reasonable time frame.\n </Typography>\n <Typography paragraph>\n We recommend reframing the cost growth itself in terms of engineering\n time. How much engineering time, for an <i>average</i> fully-loaded\n engineer cost at the company, is being overspent each month? Compare\n this to expected engineering time for optimization to decide whether\n the optimization is worthwhile.\n </Typography>\n </Box>\n\n <Box mt={4}>\n <Typography variant=\"h3\">\n Identifying which cloud product contributed most\n </Typography>\n <Typography paragraph>\n For projects meeting the alert threshold, Cost Insights shows a cost\n comparison of cloud products over the examined time period:\n </Typography>\n <Box mt={2} mb={2}>\n {projectGrowthAlert.element}\n </Box>\n <Typography paragraph>\n This allows you to quickly see which cloud products contributed to the\n growth in cloud costs.\n </Typography>\n </Box>\n\n <Box mt={4}>\n <Typography variant=\"h3\">\n Identifying the responsible workload\n </Typography>\n <Typography paragraph>\n After identifying the cloud product, use the corresponding product\n panel in Cost Insights to find a particular workload (or <i>entity</i>\n ) that has grown in cost:\n </Typography>\n <Box mt={2} mb={2}>\n <InfoCard title={product.name} subheader=\"3 entities, sorted by cost\">\n <ProductInsightsChart\n billingDate={today}\n duration={Duration.P3M}\n entity={entity}\n />\n </InfoCard>\n </Box>\n <Typography paragraph>\n From here, you can dig into commit history or deployment logs to find\n probable causes of an unexpected spike in cost.\n </Typography>\n </Box>\n\n <Box mt={4}>\n <Typography variant=\"h3\">Optimizing the workload</Typography>\n <Typography paragraph>\n Workload optimization varies between cloud products, but there are a\n few general optimization areas to consider:\n </Typography>\n <Typography variant=\"h5\">Retention</Typography>\n <Typography paragraph>\n Is the workload or storage necessary? Truly idle or unused resources\n can be cleaned up for immediate cost savings. For storage, how long do\n we need the data? Many cloud products support retention policies to\n automatically delete data after a certain time period.\n </Typography>\n <Typography variant=\"h5\">Efficiency</Typography>\n <Typography paragraph>\n Is the workload using cloud resources efficiently? For compute\n resources, do the utilization metrics look reasonable? Autoscaling\n infrastructure, such as Kubernetes, can run workloads more efficiently\n without compromising reliability.\n </Typography>\n <Typography variant=\"h5\">Lifecycle</Typography>\n <Typography paragraph>\n Is the workload using an optimal pricing model? Some cloud products\n offer better pricing for data that is accessed less frequently.\n </Typography>\n </Box>\n </AlertInstructionsLayout>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsx } from 'react/jsx-runtime';
2
2
  import MenuItem from '@material-ui/core/MenuItem';
3
3
  import Select from '@material-ui/core/Select';
4
4
  import { useSelectStyles } from '../../utils/styles.esm.js';
@@ -18,9 +18,9 @@ const ProjectSelect = ({
18
18
  const renderValue = (value) => {
19
19
  const proj = value;
20
20
  const projectObj = projects.find((p) => p.id === proj);
21
- return /* @__PURE__ */ React.createElement("b", { "data-testid": `selected-${proj}` }, proj === "all" ? "All Projects" : projectObj?.name ?? proj);
21
+ return /* @__PURE__ */ jsx("b", { "data-testid": `selected-${proj}`, children: proj === "all" ? "All Projects" : projectObj?.name ?? proj });
22
22
  };
23
- return /* @__PURE__ */ React.createElement(
23
+ return /* @__PURE__ */ jsx(
24
24
  Select,
25
25
  {
26
26
  className: classes.select,
@@ -28,18 +28,18 @@ const ProjectSelect = ({
28
28
  value: project ?? "all",
29
29
  renderValue,
30
30
  onChange: handleOnChange,
31
- "data-testid": "project-filter-select"
32
- },
33
- [{ id: "all" }, ...projectOptions].map((proj) => /* @__PURE__ */ React.createElement(
34
- MenuItem,
35
- {
36
- className: `${classes.menuItem} compact`,
37
- key: proj.id,
38
- value: proj.id,
39
- "data-testid": `option-${proj.id}`
40
- },
41
- proj.id === "all" ? "All Projects" : proj.name ?? proj.id
42
- ))
31
+ "data-testid": "project-filter-select",
32
+ children: [{ id: "all" }, ...projectOptions].map((proj) => /* @__PURE__ */ jsx(
33
+ MenuItem,
34
+ {
35
+ className: `${classes.menuItem} compact`,
36
+ value: proj.id,
37
+ "data-testid": `option-${proj.id}`,
38
+ children: proj.id === "all" ? "All Projects" : proj.name ?? proj.id
39
+ },
40
+ proj.id
41
+ ))
42
+ }
43
43
  );
44
44
  };
45
45
 
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectSelect.esm.js","sources":["../../../src/components/ProjectSelect/ProjectSelect.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 React from 'react';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Select from '@material-ui/core/Select';\nimport {\n Maybe,\n Project,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { useSelectStyles as useStyles } from '../../utils/styles';\n\ntype ProjectSelectProps = {\n project: Maybe<string>;\n projects: Array<Project>;\n onSelect: (project: Maybe<string>) => void;\n};\n\nexport const ProjectSelect = ({\n project,\n projects,\n onSelect,\n}: ProjectSelectProps) => {\n const classes = useStyles();\n\n const projectOptions = projects\n .filter(p => p.id)\n .sort((a, b) =>\n ((a.name ?? a.id) as string).localeCompare((b.name ?? b.id) as string),\n );\n\n const handleOnChange = (e: React.ChangeEvent<{ value: unknown }>) => {\n onSelect(e.target.value as string);\n };\n\n const renderValue = (value: unknown) => {\n const proj = value as string;\n const projectObj = projects.find(p => p.id === proj);\n return (\n <b data-testid={`selected-${proj}`}>\n {proj === 'all' ? 'All Projects' : projectObj?.name ?? proj}\n </b>\n );\n };\n\n return (\n <Select\n className={classes.select}\n variant=\"outlined\"\n value={project ?? 'all'}\n renderValue={renderValue}\n onChange={handleOnChange}\n data-testid=\"project-filter-select\"\n >\n {[{ id: 'all' }, ...projectOptions].map(proj => (\n <MenuItem\n className={`${classes.menuItem} compact`}\n key={proj.id}\n value={proj.id}\n data-testid={`option-${proj.id}`}\n >\n {proj.id === 'all' ? 'All Projects' : proj.name ?? proj.id}\n </MenuItem>\n ))}\n </Select>\n );\n};\n"],"names":["useStyles"],"mappings":";;;;;AA8BO,MAAM,gBAAgB,CAAC;AAAA,EAC5B,OAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAA0B,KAAA;AACxB,EAAA,MAAM,UAAUA,eAAU,EAAA;AAE1B,EAAA,MAAM,iBAAiB,QACpB,CAAA,MAAA,CAAO,CAAK,CAAA,KAAA,CAAA,CAAE,EAAE,CAChB,CAAA,IAAA;AAAA,IAAK,CAAC,CAAG,EAAA,CAAA,KAAA,CACN,CAAE,CAAA,IAAA,IAAQ,CAAE,CAAA,EAAA,EAAe,aAAe,CAAA,CAAA,CAAE,IAAQ,IAAA,CAAA,CAAE,EAAa;AAAA,GACvE;AAEF,EAAM,MAAA,cAAA,GAAiB,CAAC,CAA6C,KAAA;AACnE,IAAS,QAAA,CAAA,CAAA,CAAE,OAAO,KAAe,CAAA;AAAA,GACnC;AAEA,EAAM,MAAA,WAAA,GAAc,CAAC,KAAmB,KAAA;AACtC,IAAA,MAAM,IAAO,GAAA,KAAA;AACb,IAAA,MAAM,aAAa,QAAS,CAAA,IAAA,CAAK,CAAK,CAAA,KAAA,CAAA,CAAE,OAAO,IAAI,CAAA;AACnD,IACE,uBAAA,KAAA,CAAA,aAAA,CAAC,GAAE,EAAA,EAAA,aAAA,EAAa,CAAY,SAAA,EAAA,IAAI,CAC7B,CAAA,EAAA,EAAA,IAAA,KAAS,KAAQ,GAAA,cAAA,GAAiB,UAAY,EAAA,IAAA,IAAQ,IACzD,CAAA;AAAA,GAEJ;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,WAAW,OAAQ,CAAA,MAAA;AAAA,MACnB,OAAQ,EAAA,UAAA;AAAA,MACR,OAAO,OAAW,IAAA,KAAA;AAAA,MAClB,WAAA;AAAA,MACA,QAAU,EAAA,cAAA;AAAA,MACV,aAAY,EAAA;AAAA,KAAA;AAAA,IAEX,CAAC,EAAE,EAAI,EAAA,KAAA,IAAS,GAAG,cAAc,CAAE,CAAA,GAAA,CAAI,CACtC,IAAA,qBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,CAAG,EAAA,OAAA,CAAQ,QAAQ,CAAA,QAAA,CAAA;AAAA,QAC9B,KAAK,IAAK,CAAA,EAAA;AAAA,QACV,OAAO,IAAK,CAAA,EAAA;AAAA,QACZ,aAAA,EAAa,CAAU,OAAA,EAAA,IAAA,CAAK,EAAE,CAAA;AAAA,OAAA;AAAA,MAE7B,KAAK,EAAO,KAAA,KAAA,GAAQ,cAAiB,GAAA,IAAA,CAAK,QAAQ,IAAK,CAAA;AAAA,KAE3D;AAAA,GACH;AAEJ;;;;"}
1
+ {"version":3,"file":"ProjectSelect.esm.js","sources":["../../../src/components/ProjectSelect/ProjectSelect.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 type { ChangeEvent } from 'react';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Select from '@material-ui/core/Select';\nimport {\n Maybe,\n Project,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { useSelectStyles as useStyles } from '../../utils/styles';\n\ntype ProjectSelectProps = {\n project: Maybe<string>;\n projects: Array<Project>;\n onSelect: (project: Maybe<string>) => void;\n};\n\nexport const ProjectSelect = ({\n project,\n projects,\n onSelect,\n}: ProjectSelectProps) => {\n const classes = useStyles();\n\n const projectOptions = projects\n .filter(p => p.id)\n .sort((a, b) =>\n ((a.name ?? a.id) as string).localeCompare((b.name ?? b.id) as string),\n );\n\n const handleOnChange = (e: ChangeEvent<{ value: unknown }>) => {\n onSelect(e.target.value as string);\n };\n\n const renderValue = (value: unknown) => {\n const proj = value as string;\n const projectObj = projects.find(p => p.id === proj);\n return (\n <b data-testid={`selected-${proj}`}>\n {proj === 'all' ? 'All Projects' : projectObj?.name ?? proj}\n </b>\n );\n };\n\n return (\n <Select\n className={classes.select}\n variant=\"outlined\"\n value={project ?? 'all'}\n renderValue={renderValue}\n onChange={handleOnChange}\n data-testid=\"project-filter-select\"\n >\n {[{ id: 'all' }, ...projectOptions].map(proj => (\n <MenuItem\n className={`${classes.menuItem} compact`}\n key={proj.id}\n value={proj.id}\n data-testid={`option-${proj.id}`}\n >\n {proj.id === 'all' ? 'All Projects' : proj.name ?? proj.id}\n </MenuItem>\n ))}\n </Select>\n );\n};\n"],"names":["useStyles"],"mappings":";;;;;AA8BO,MAAM,gBAAgB,CAAC;AAAA,EAC5B,OAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAA0B,KAAA;AACxB,EAAA,MAAM,UAAUA,eAAU,EAAA;AAE1B,EAAA,MAAM,iBAAiB,QACpB,CAAA,MAAA,CAAO,CAAK,CAAA,KAAA,CAAA,CAAE,EAAE,CAChB,CAAA,IAAA;AAAA,IAAK,CAAC,CAAG,EAAA,CAAA,KAAA,CACN,CAAE,CAAA,IAAA,IAAQ,CAAE,CAAA,EAAA,EAAe,aAAe,CAAA,CAAA,CAAE,IAAQ,IAAA,CAAA,CAAE,EAAa;AAAA,GACvE;AAEF,EAAM,MAAA,cAAA,GAAiB,CAAC,CAAuC,KAAA;AAC7D,IAAS,QAAA,CAAA,CAAA,CAAE,OAAO,KAAe,CAAA;AAAA,GACnC;AAEA,EAAM,MAAA,WAAA,GAAc,CAAC,KAAmB,KAAA;AACtC,IAAA,MAAM,IAAO,GAAA,KAAA;AACb,IAAA,MAAM,aAAa,QAAS,CAAA,IAAA,CAAK,CAAK,CAAA,KAAA,CAAA,CAAE,OAAO,IAAI,CAAA;AACnD,IACE,uBAAA,GAAA,CAAC,GAAE,EAAA,EAAA,aAAA,EAAa,CAAY,SAAA,EAAA,IAAI,CAC7B,CAAA,EAAA,QAAA,EAAA,IAAA,KAAS,KAAQ,GAAA,cAAA,GAAiB,UAAY,EAAA,IAAA,IAAQ,IACzD,EAAA,CAAA;AAAA,GAEJ;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,WAAW,OAAQ,CAAA,MAAA;AAAA,MACnB,OAAQ,EAAA,UAAA;AAAA,MACR,OAAO,OAAW,IAAA,KAAA;AAAA,MAClB,WAAA;AAAA,MACA,QAAU,EAAA,cAAA;AAAA,MACV,aAAY,EAAA,uBAAA;AAAA,MAEX,QAAA,EAAA,CAAC,EAAE,EAAI,EAAA,KAAA,IAAS,GAAG,cAAc,CAAE,CAAA,GAAA,CAAI,CACtC,IAAA,qBAAA,GAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,CAAG,EAAA,OAAA,CAAQ,QAAQ,CAAA,QAAA,CAAA;AAAA,UAE9B,OAAO,IAAK,CAAA,EAAA;AAAA,UACZ,aAAA,EAAa,CAAU,OAAA,EAAA,IAAA,CAAK,EAAE,CAAA,CAAA;AAAA,UAE7B,eAAK,EAAO,KAAA,KAAA,GAAQ,cAAiB,GAAA,IAAA,CAAK,QAAQ,IAAK,CAAA;AAAA,SAAA;AAAA,QAJnD,IAAK,CAAA;AAAA,OAMb;AAAA;AAAA,GACH;AAEJ;;;;"}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import pluralize from 'pluralize';
3
3
  import Box from '@material-ui/core/Box';
4
4
  import { BarChart } from '../BarChart/BarChart.esm.js';
@@ -27,14 +27,17 @@ const UnlabeledDataflowAlertCard = ({
27
27
  previous: project.unlabeledCost,
28
28
  current: project.labeledCost
29
29
  }));
30
- return /* @__PURE__ */ React.createElement(InfoCard, { title: "Label Dataflow", subheader }, /* @__PURE__ */ React.createElement(Box, { className: classes.wrapper }, /* @__PURE__ */ React.createElement(
31
- BarChartLegend,
32
- {
33
- costStart: alert.unlabeledCost,
34
- costEnd: alert.labeledCost,
35
- options
36
- }
37
- ), /* @__PURE__ */ React.createElement(BarChart, { resources, options })));
30
+ return /* @__PURE__ */ jsx(InfoCard, { title: "Label Dataflow", subheader, children: /* @__PURE__ */ jsxs(Box, { className: classes.wrapper, children: [
31
+ /* @__PURE__ */ jsx(
32
+ BarChartLegend,
33
+ {
34
+ costStart: alert.unlabeledCost,
35
+ costEnd: alert.labeledCost,
36
+ options
37
+ }
38
+ ),
39
+ /* @__PURE__ */ jsx(BarChart, { resources, options })
40
+ ] }) });
38
41
  };
39
42
 
40
43
  export { UnlabeledDataflowAlertCard };
@@ -1 +1 @@
1
- {"version":3,"file":"UnlabeledDataflowAlertCard.esm.js","sources":["../../../src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.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 React from 'react';\nimport pluralize from 'pluralize';\nimport Box from '@material-ui/core/Box';\nimport { BarChart, BarChartLegend } from '../BarChart';\nimport { UnlabeledDataflowData, ResourceData } from '../../types';\nimport { useBarChartLayoutStyles as useStyles } from '../../utils/styles';\nimport { InfoCard } from '@backstage/core-components';\n\ntype UnlabeledDataflowAlertProps = {\n alert: UnlabeledDataflowData;\n};\n\nexport const UnlabeledDataflowAlertCard = ({\n alert,\n}: UnlabeledDataflowAlertProps) => {\n const classes = useStyles();\n const projects = pluralize('project', alert.projects.length, true);\n const subheader = `\n Showing costs from ${projects} with unlabeled Dataflow jobs in the last 30 days.\n `;\n const options = {\n previousName: 'Unlabeled Cost',\n currentName: 'Labeled Cost',\n };\n\n const resources: ResourceData[] = alert.projects.map(project => ({\n name: project.id,\n previous: project.unlabeledCost,\n current: project.labeledCost,\n }));\n\n return (\n <InfoCard title=\"Label Dataflow\" subheader={subheader}>\n <Box className={classes.wrapper}>\n <BarChartLegend\n costStart={alert.unlabeledCost}\n costEnd={alert.labeledCost}\n options={options}\n />\n <BarChart resources={resources} options={options} />\n </Box>\n </InfoCard>\n );\n};\n"],"names":["useStyles"],"mappings":";;;;;;;;;;;;AA4BO,MAAM,6BAA6B,CAAC;AAAA,EACzC;AACF,CAAmC,KAAA;AACjC,EAAA,MAAM,UAAUA,uBAAU,EAAA;AAC1B,EAAA,MAAM,WAAW,SAAU,CAAA,SAAA,EAAW,KAAM,CAAA,QAAA,CAAS,QAAQ,IAAI,CAAA;AACjE,EAAA,MAAM,SAAY,GAAA;AAAA,uBAAA,EACK,QAAQ,CAAA;AAAA,EAAA,CAAA;AAE/B,EAAA,MAAM,OAAU,GAAA;AAAA,IACd,YAAc,EAAA,gBAAA;AAAA,IACd,WAAa,EAAA;AAAA,GACf;AAEA,EAAA,MAAM,SAA4B,GAAA,KAAA,CAAM,QAAS,CAAA,GAAA,CAAI,CAAY,OAAA,MAAA;AAAA,IAC/D,MAAM,OAAQ,CAAA,EAAA;AAAA,IACd,UAAU,OAAQ,CAAA,aAAA;AAAA,IAClB,SAAS,OAAQ,CAAA;AAAA,GACjB,CAAA,CAAA;AAEF,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,YAAS,KAAM,EAAA,gBAAA,EAAiB,6BAC9B,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,SAAW,EAAA,OAAA,CAAQ,OACtB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,WAAW,KAAM,CAAA,aAAA;AAAA,MACjB,SAAS,KAAM,CAAA,WAAA;AAAA,MACf;AAAA;AAAA,qBAED,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,SAAsB,EAAA,OAAA,EAAkB,CACpD,CACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"UnlabeledDataflowAlertCard.esm.js","sources":["../../../src/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.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 pluralize from 'pluralize';\nimport Box from '@material-ui/core/Box';\nimport { BarChart, BarChartLegend } from '../BarChart';\nimport { UnlabeledDataflowData, ResourceData } from '../../types';\nimport { useBarChartLayoutStyles as useStyles } from '../../utils/styles';\nimport { InfoCard } from '@backstage/core-components';\n\ntype UnlabeledDataflowAlertProps = {\n alert: UnlabeledDataflowData;\n};\n\nexport const UnlabeledDataflowAlertCard = ({\n alert,\n}: UnlabeledDataflowAlertProps) => {\n const classes = useStyles();\n const projects = pluralize('project', alert.projects.length, true);\n const subheader = `\n Showing costs from ${projects} with unlabeled Dataflow jobs in the last 30 days.\n `;\n const options = {\n previousName: 'Unlabeled Cost',\n currentName: 'Labeled Cost',\n };\n\n const resources: ResourceData[] = alert.projects.map(project => ({\n name: project.id,\n previous: project.unlabeledCost,\n current: project.labeledCost,\n }));\n\n return (\n <InfoCard title=\"Label Dataflow\" subheader={subheader}>\n <Box className={classes.wrapper}>\n <BarChartLegend\n costStart={alert.unlabeledCost}\n costEnd={alert.labeledCost}\n options={options}\n />\n <BarChart resources={resources} options={options} />\n </Box>\n </InfoCard>\n );\n};\n"],"names":["useStyles"],"mappings":";;;;;;;;;;;;AA2BO,MAAM,6BAA6B,CAAC;AAAA,EACzC;AACF,CAAmC,KAAA;AACjC,EAAA,MAAM,UAAUA,uBAAU,EAAA;AAC1B,EAAA,MAAM,WAAW,SAAU,CAAA,SAAA,EAAW,KAAM,CAAA,QAAA,CAAS,QAAQ,IAAI,CAAA;AACjE,EAAA,MAAM,SAAY,GAAA;AAAA,uBAAA,EACK,QAAQ,CAAA;AAAA,EAAA,CAAA;AAE/B,EAAA,MAAM,OAAU,GAAA;AAAA,IACd,YAAc,EAAA,gBAAA;AAAA,IACd,WAAa,EAAA;AAAA,GACf;AAEA,EAAA,MAAM,SAA4B,GAAA,KAAA,CAAM,QAAS,CAAA,GAAA,CAAI,CAAY,OAAA,MAAA;AAAA,IAC/D,MAAM,OAAQ,CAAA,EAAA;AAAA,IACd,UAAU,OAAQ,CAAA,aAAA;AAAA,IAClB,SAAS,OAAQ,CAAA;AAAA,GACjB,CAAA,CAAA;AAEF,EACE,uBAAA,GAAA,CAAC,YAAS,KAAM,EAAA,gBAAA,EAAiB,WAC/B,QAAC,kBAAA,IAAA,CAAA,GAAA,EAAA,EAAI,SAAW,EAAA,OAAA,CAAQ,OACtB,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,cAAA;AAAA,MAAA;AAAA,QACC,WAAW,KAAM,CAAA,aAAA;AAAA,QACjB,SAAS,KAAM,CAAA,WAAA;AAAA,QACf;AAAA;AAAA,KACF;AAAA,oBACA,GAAA,CAAC,QAAS,EAAA,EAAA,SAAA,EAAsB,OAAkB,EAAA;AAAA,GAAA,EACpD,CACF,EAAA,CAAA;AAEJ;;;;"}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import Typography from '@material-ui/core/Typography';
3
3
  import Box from '@material-ui/core/Box';
4
4
  import Grid from '@material-ui/core/Grid';
@@ -6,15 +6,45 @@ import Container from '@material-ui/core/Container';
6
6
  import Divider from '@material-ui/core/Divider';
7
7
 
8
8
  const WhyCostsMatter = () => {
9
- return /* @__PURE__ */ React.createElement(Box, { mt: 10, mb: 4 }, /* @__PURE__ */ React.createElement(Container, { maxWidth: "md" }, /* @__PURE__ */ React.createElement(Box, { mt: 2, mb: 2 }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5", align: "center", gutterBottom: true }, "Why cloud costs matter")), /* @__PURE__ */ React.createElement(Grid, { container: true, alignContent: "space-around", spacing: 3, wrap: "nowrap" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, "Sustainability", " ", /* @__PURE__ */ React.createElement(Typography, { component: "span", role: "img", "aria-label": "globe" }, "\u{1F30E}")), /* @__PURE__ */ React.createElement(Typography, null, "Reducing cloud usage improves our carbon footprint.")), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Divider, { orientation: "vertical" })), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, "Revenue", " ", /* @__PURE__ */ React.createElement(
10
- Typography,
11
- {
12
- component: "span",
13
- role: "img",
14
- "aria-label": "money-with-wings"
15
- },
16
- "\u{1F4B8}"
17
- )), /* @__PURE__ */ React.createElement(Typography, null, "Keeping cloud costs well-tuned prevents infrastructure from eating into revenue.")), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Divider, { orientation: "vertical" })), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, "Innovation", " ", /* @__PURE__ */ React.createElement(Typography, { component: "span", role: "img", "aria-label": "medal" }, "\u{1F947}")), /* @__PURE__ */ React.createElement(Typography, null, "The more we save, the more we can reinvest in speed and innovation.")))));
9
+ return /* @__PURE__ */ jsx(Box, { mt: 10, mb: 4, children: /* @__PURE__ */ jsxs(Container, { maxWidth: "md", children: [
10
+ /* @__PURE__ */ jsx(Box, { mt: 2, mb: 2, children: /* @__PURE__ */ jsx(Typography, { variant: "h5", align: "center", gutterBottom: true, children: "Why cloud costs matter" }) }),
11
+ /* @__PURE__ */ jsxs(Grid, { container: true, alignContent: "space-around", spacing: 3, wrap: "nowrap", children: [
12
+ /* @__PURE__ */ jsxs(Grid, { item: true, children: [
13
+ /* @__PURE__ */ jsxs(Typography, { variant: "h6", children: [
14
+ "Sustainability",
15
+ " ",
16
+ /* @__PURE__ */ jsx(Typography, { component: "span", role: "img", "aria-label": "globe", children: "\u{1F30E}" })
17
+ ] }),
18
+ /* @__PURE__ */ jsx(Typography, { children: "Reducing cloud usage improves our carbon footprint." })
19
+ ] }),
20
+ /* @__PURE__ */ jsx(Grid, { item: true, children: /* @__PURE__ */ jsx(Divider, { orientation: "vertical" }) }),
21
+ /* @__PURE__ */ jsxs(Grid, { item: true, children: [
22
+ /* @__PURE__ */ jsxs(Typography, { variant: "h6", children: [
23
+ "Revenue",
24
+ " ",
25
+ /* @__PURE__ */ jsx(
26
+ Typography,
27
+ {
28
+ component: "span",
29
+ role: "img",
30
+ "aria-label": "money-with-wings",
31
+ children: "\u{1F4B8}"
32
+ }
33
+ )
34
+ ] }),
35
+ /* @__PURE__ */ jsx(Typography, { children: "Keeping cloud costs well-tuned prevents infrastructure from eating into revenue." })
36
+ ] }),
37
+ /* @__PURE__ */ jsx(Grid, { item: true, children: /* @__PURE__ */ jsx(Divider, { orientation: "vertical" }) }),
38
+ /* @__PURE__ */ jsxs(Grid, { item: true, children: [
39
+ /* @__PURE__ */ jsxs(Typography, { variant: "h6", children: [
40
+ "Innovation",
41
+ " ",
42
+ /* @__PURE__ */ jsx(Typography, { component: "span", role: "img", "aria-label": "medal", children: "\u{1F947}" })
43
+ ] }),
44
+ /* @__PURE__ */ jsx(Typography, { children: "The more we save, the more we can reinvest in speed and innovation." })
45
+ ] })
46
+ ] })
47
+ ] }) });
18
48
  };
19
49
 
20
50
  export { WhyCostsMatter };
@@ -1 +1 @@
1
- {"version":3,"file":"WhyCostsMatter.esm.js","sources":["../../../src/components/WhyCostsMatter/WhyCostsMatter.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 React from 'react';\nimport Typography from '@material-ui/core/Typography';\nimport Box from '@material-ui/core/Box';\nimport Grid from '@material-ui/core/Grid';\nimport Container from '@material-ui/core/Container';\nimport Divider from '@material-ui/core/Divider';\n\nexport const WhyCostsMatter = () => {\n return (\n <Box mt={10} mb={4}>\n <Container maxWidth=\"md\">\n <Box mt={2} mb={2}>\n <Typography variant=\"h5\" align=\"center\" gutterBottom>\n Why cloud costs matter\n </Typography>\n </Box>\n <Grid container alignContent=\"space-around\" spacing={3} wrap=\"nowrap\">\n <Grid item>\n <Typography variant=\"h6\">\n Sustainability{' '}\n <Typography component=\"span\" role=\"img\" aria-label=\"globe\">\n 🌎\n </Typography>\n </Typography>\n <Typography>\n Reducing cloud usage improves our carbon footprint.\n </Typography>\n </Grid>\n <Grid item>\n <Divider orientation=\"vertical\" />\n </Grid>\n <Grid item>\n <Typography variant=\"h6\">\n Revenue{' '}\n <Typography\n component=\"span\"\n role=\"img\"\n aria-label=\"money-with-wings\"\n >\n 💸\n </Typography>\n </Typography>\n <Typography>\n Keeping cloud costs well-tuned prevents infrastructure from eating\n into revenue.\n </Typography>\n </Grid>\n <Grid item>\n <Divider orientation=\"vertical\" />\n </Grid>\n <Grid item>\n <Typography variant=\"h6\">\n Innovation{' '}\n <Typography component=\"span\" role=\"img\" aria-label=\"medal\">\n 🥇\n </Typography>\n </Typography>\n <Typography>\n The more we save, the more we can reinvest in speed and\n innovation.\n </Typography>\n </Grid>\n </Grid>\n </Container>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;AAuBO,MAAM,iBAAiB,MAAM;AAClC,EAAA,2CACG,GAAI,EAAA,EAAA,EAAA,EAAI,EAAI,EAAA,EAAA,EAAI,qBACd,KAAA,CAAA,aAAA,CAAA,SAAA,EAAA,EAAU,QAAS,EAAA,IAAA,EAAA,sCACjB,GAAI,EAAA,EAAA,EAAA,EAAI,GAAG,EAAI,EAAA,CAAA,EAAA,sCACb,UAAW,EAAA,EAAA,OAAA,EAAQ,IAAK,EAAA,KAAA,EAAM,UAAS,YAAY,EAAA,IAAA,EAAA,EAAC,wBAErD,CACF,CAAA,sCACC,IAAK,EAAA,EAAA,SAAA,EAAS,IAAC,EAAA,YAAA,EAAa,gBAAe,OAAS,EAAA,CAAA,EAAG,MAAK,QAC3D,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAK,IAAI,EAAA,IAAA,EAAA,kBACP,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,IAAK,EAAA,EAAA,gBAAA,EACR,GACf,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,SAAU,EAAA,MAAA,EAAO,IAAK,EAAA,KAAA,EAAM,cAAW,OAAQ,EAAA,EAAA,WAE3D,CACF,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,kBAAW,qDAEZ,CACF,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAK,IAAI,EAAA,IAAA,EAAA,sCACP,OAAQ,EAAA,EAAA,WAAA,EAAY,YAAW,CAClC,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,MAAI,IACR,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,IAAA,EAAA,EAAK,WACf,GACR,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,SAAU,EAAA,MAAA;AAAA,MACV,IAAK,EAAA,KAAA;AAAA,MACL,YAAW,EAAA;AAAA,KAAA;AAAA,IACZ;AAAA,GAGH,mBACC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,IAAA,EAAW,kFAGZ,CACF,CAAA,sCACC,IAAK,EAAA,EAAA,IAAA,EAAI,wBACP,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAQ,aAAY,UAAW,EAAA,CAClC,mBACC,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,MAAI,IACR,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,IAAA,EAAA,EAAK,cACZ,GACX,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,SAAU,EAAA,MAAA,EAAO,MAAK,KAAM,EAAA,YAAA,EAAW,WAAQ,WAE3D,CACF,mBACC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,IAAA,EAAW,qEAGZ,CACF,CACF,CACF,CACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"WhyCostsMatter.esm.js","sources":["../../../src/components/WhyCostsMatter/WhyCostsMatter.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 Typography from '@material-ui/core/Typography';\nimport Box from '@material-ui/core/Box';\nimport Grid from '@material-ui/core/Grid';\nimport Container from '@material-ui/core/Container';\nimport Divider from '@material-ui/core/Divider';\n\nexport const WhyCostsMatter = () => {\n return (\n <Box mt={10} mb={4}>\n <Container maxWidth=\"md\">\n <Box mt={2} mb={2}>\n <Typography variant=\"h5\" align=\"center\" gutterBottom>\n Why cloud costs matter\n </Typography>\n </Box>\n <Grid container alignContent=\"space-around\" spacing={3} wrap=\"nowrap\">\n <Grid item>\n <Typography variant=\"h6\">\n Sustainability{' '}\n <Typography component=\"span\" role=\"img\" aria-label=\"globe\">\n 🌎\n </Typography>\n </Typography>\n <Typography>\n Reducing cloud usage improves our carbon footprint.\n </Typography>\n </Grid>\n <Grid item>\n <Divider orientation=\"vertical\" />\n </Grid>\n <Grid item>\n <Typography variant=\"h6\">\n Revenue{' '}\n <Typography\n component=\"span\"\n role=\"img\"\n aria-label=\"money-with-wings\"\n >\n 💸\n </Typography>\n </Typography>\n <Typography>\n Keeping cloud costs well-tuned prevents infrastructure from eating\n into revenue.\n </Typography>\n </Grid>\n <Grid item>\n <Divider orientation=\"vertical\" />\n </Grid>\n <Grid item>\n <Typography variant=\"h6\">\n Innovation{' '}\n <Typography component=\"span\" role=\"img\" aria-label=\"medal\">\n 🥇\n </Typography>\n </Typography>\n <Typography>\n The more we save, the more we can reinvest in speed and\n innovation.\n </Typography>\n </Grid>\n </Grid>\n </Container>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;AAsBO,MAAM,iBAAiB,MAAM;AAClC,EACE,uBAAA,GAAA,CAAC,OAAI,EAAI,EAAA,EAAA,EAAI,IAAI,CACf,EAAA,QAAA,kBAAA,IAAA,CAAC,SAAU,EAAA,EAAA,QAAA,EAAS,IAClB,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,GAAI,EAAA,EAAA,EAAA,EAAI,CAAG,EAAA,EAAA,EAAI,GACd,QAAC,kBAAA,GAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,IAAA,EAAK,KAAM,EAAA,QAAA,EAAS,YAAY,EAAA,IAAA,EAAC,oCAErD,CACF,EAAA,CAAA;AAAA,oBACA,IAAA,CAAC,QAAK,SAAS,EAAA,IAAA,EAAC,cAAa,cAAe,EAAA,OAAA,EAAS,CAAG,EAAA,IAAA,EAAK,QAC3D,EAAA,QAAA,EAAA;AAAA,sBAAC,IAAA,CAAA,IAAA,EAAA,EAAK,MAAI,IACR,EAAA,QAAA,EAAA;AAAA,wBAAC,IAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,IAAK,EAAA,QAAA,EAAA;AAAA,UAAA,gBAAA;AAAA,UACR,GAAA;AAAA,0BACf,GAAA,CAAC,cAAW,SAAU,EAAA,MAAA,EAAO,MAAK,KAAM,EAAA,YAAA,EAAW,SAAQ,QAE3D,EAAA,WAAA,EAAA;AAAA,SACF,EAAA,CAAA;AAAA,wBACA,GAAA,CAAC,cAAW,QAEZ,EAAA,qDAAA,EAAA;AAAA,OACF,EAAA,CAAA;AAAA,sBACA,GAAA,CAAC,QAAK,IAAI,EAAA,IAAA,EACR,8BAAC,OAAQ,EAAA,EAAA,WAAA,EAAY,YAAW,CAClC,EAAA,CAAA;AAAA,sBACA,IAAA,CAAC,IAAK,EAAA,EAAA,IAAA,EAAI,IACR,EAAA,QAAA,EAAA;AAAA,wBAAC,IAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,IAAK,EAAA,QAAA,EAAA;AAAA,UAAA,SAAA;AAAA,UACf,GAAA;AAAA,0BACR,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,SAAU,EAAA,MAAA;AAAA,cACV,IAAK,EAAA,KAAA;AAAA,cACL,YAAW,EAAA,kBAAA;AAAA,cACZ,QAAA,EAAA;AAAA;AAAA;AAED,SACF,EAAA,CAAA;AAAA,wBACA,GAAA,CAAC,cAAW,QAGZ,EAAA,kFAAA,EAAA;AAAA,OACF,EAAA,CAAA;AAAA,sBACA,GAAA,CAAC,QAAK,IAAI,EAAA,IAAA,EACR,8BAAC,OAAQ,EAAA,EAAA,WAAA,EAAY,YAAW,CAClC,EAAA,CAAA;AAAA,sBACA,IAAA,CAAC,IAAK,EAAA,EAAA,IAAA,EAAI,IACR,EAAA,QAAA,EAAA;AAAA,wBAAC,IAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,IAAK,EAAA,QAAA,EAAA;AAAA,UAAA,YAAA;AAAA,UACZ,GAAA;AAAA,0BACX,GAAA,CAAC,cAAW,SAAU,EAAA,MAAA,EAAO,MAAK,KAAM,EAAA,YAAA,EAAW,SAAQ,QAE3D,EAAA,WAAA,EAAA;AAAA,SACF,EAAA,CAAA;AAAA,wBACA,GAAA,CAAC,cAAW,QAGZ,EAAA,qEAAA,EAAA;AAAA,OACF,EAAA;AAAA,KACF,EAAA;AAAA,GAAA,EACF,CACF,EAAA,CAAA;AAEJ;;;;"}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import pluralize from 'pluralize';
3
3
  import Typography from '@material-ui/core/Typography';
4
4
  import { KubernetesMigrationAlertCard } from '../components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.esm.js';
@@ -19,7 +19,14 @@ class KubernetesMigrationAlert {
19
19
  this.data = data;
20
20
  }
21
21
  get title() {
22
- return /* @__PURE__ */ React.createElement(Typography, { component: "span" }, "Consider migrating", " ", pluralize("service", this.data.services.length, true), " to Kubernetes", " ", /* @__PURE__ */ React.createElement(Lifecycle, { shorthand: true }));
22
+ return /* @__PURE__ */ jsxs(Typography, { component: "span", children: [
23
+ "Consider migrating",
24
+ " ",
25
+ pluralize("service", this.data.services.length, true),
26
+ " to Kubernetes",
27
+ " ",
28
+ /* @__PURE__ */ jsx(Lifecycle, { shorthand: true })
29
+ ] });
23
30
  }
24
31
  get element() {
25
32
  const subheader = `${pluralize(
@@ -27,7 +34,7 @@ class KubernetesMigrationAlert {
27
34
  this.data.services.length,
28
35
  true
29
36
  )}, sorted by cost`;
30
- return /* @__PURE__ */ React.createElement(
37
+ return /* @__PURE__ */ jsx(
31
38
  KubernetesMigrationAlertCard,
32
39
  {
33
40
  data: this.data,
@@ -1 +1 @@
1
- {"version":3,"file":"KubernetesMigrationAlert.esm.js","sources":["../../../src/example/alerts/KubernetesMigrationAlert.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 React from 'react';\nimport pluralize from 'pluralize';\nimport Typography from '@material-ui/core/Typography';\nimport { KubernetesMigrationAlertCard } from '../components';\nimport { CostInsightsApi } from '../../api';\nimport {\n Alert,\n AlertForm,\n AlertOptions,\n AlertStatus,\n AlertSnoozeFormData,\n} from '../../types';\nimport {\n ChangeStatistic,\n Entity,\n} from '@backstage-community/plugin-cost-insights-common';\nimport {\n KubernetesMigrationDismissForm,\n KubernetesMigrationDismissFormData,\n} from '../forms';\nimport { Lifecycle } from '@backstage/core-components';\n\nexport interface KubernetesMigrationData {\n startDate: string;\n endDate: string;\n change: ChangeStatistic;\n services: Array<Entity>;\n}\n\nexport interface KubernetesMigrationApi extends Alert {\n api: CostInsightsApi;\n data: KubernetesMigrationData;\n}\n\n/**\n * This is an example of an Alert implementation using optional event hooks.\n *\n * Event hooks can be used to enable users to dismiss, snooze, or accept an action item\n * - or any combination thereof. Defining a hook will generate default UI - button, dialog and\n * form. Cost Insights does not preserve client side alert state - each hook is expected to return a new set of alerts.\n *\n * Snoozed, accepted, etc. alerts should define a corresponding status property. Alerts will be aggregated\n * by status in a collapsed view below Alert Insights section and a badge will appear in Action Items\n * showing the total alerts of that status.\n *\n * Customizing Alerts\n * Default forms can be overridden in two ways - by setting a form property to null or defining a custom component.\n *\n * If a form property is set to null, the Dialog will not render a form. This can be useful in scenarios\n * where data isn't needed from the user such as when a user accepts an action item's recommendation.\n *\n * If a form property is set to a React component, the Dialog will render the form component in place of the default form.\n * Form components must return valid form elements, and accept a ref and onSubmit event handler.\n * Custom forms must implement the corresponding event hook. See /forms for example implementations.\n */\n\nexport class KubernetesMigrationAlert implements KubernetesMigrationApi {\n api: CostInsightsApi;\n data: KubernetesMigrationData;\n\n subtitle =\n 'Services running on Kubernetes are estimated to save 50% or more compared to Compute Engine.';\n\n // Dialog will not render a form if form property set to null.\n AcceptForm = null;\n // Overrides default Dismiss form with a custom form component.\n DismissForm: AlertForm<\n KubernetesMigrationAlert,\n KubernetesMigrationDismissFormData\n > = KubernetesMigrationDismissForm;\n\n constructor(api: CostInsightsApi, data: KubernetesMigrationData) {\n this.api = api;\n this.data = data;\n }\n\n get title() {\n return (\n <Typography component=\"span\">\n Consider migrating{' '}\n {pluralize('service', this.data.services.length, true)} to Kubernetes{' '}\n <Lifecycle shorthand />\n </Typography>\n );\n }\n\n get element() {\n const subheader = `${pluralize(\n 'Service',\n this.data.services.length,\n true,\n )}, sorted by cost`;\n return (\n <KubernetesMigrationAlertCard\n data={this.data}\n title=\"Migrate to Kubernetes\"\n subheader={subheader}\n currentProduct=\"Compute Engine\"\n comparedProduct=\"Kubernetes\"\n />\n );\n }\n\n /* Fires when the onSubmit event is raised on a Dismiss form. Displays custom dismiss form. */\n async onDismissed(\n options: AlertOptions<KubernetesMigrationDismissFormData>,\n ): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Dismissed,\n },\n ]),\n );\n }\n\n /* Fires when the onSubmit event is raised on a Snooze form. Displays default snooze form. */\n async onSnoozed(\n options: AlertOptions<AlertSnoozeFormData>,\n ): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Snoozed,\n },\n ]),\n );\n }\n\n /* Fires when the Accept button is clicked. Dialog does not render a form. See KubernetesMigrationAlert.AcceptForm */\n async onAccepted(options: AlertOptions<null>): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Accepted,\n },\n ]),\n );\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"KubernetesMigrationAlert.esm.js","sources":["../../../src/example/alerts/KubernetesMigrationAlert.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 pluralize from 'pluralize';\nimport Typography from '@material-ui/core/Typography';\nimport { KubernetesMigrationAlertCard } from '../components';\nimport { CostInsightsApi } from '../../api';\nimport {\n Alert,\n AlertForm,\n AlertOptions,\n AlertStatus,\n AlertSnoozeFormData,\n} from '../../types';\nimport {\n ChangeStatistic,\n Entity,\n} from '@backstage-community/plugin-cost-insights-common';\nimport {\n KubernetesMigrationDismissForm,\n KubernetesMigrationDismissFormData,\n} from '../forms';\nimport { Lifecycle } from '@backstage/core-components';\n\nexport interface KubernetesMigrationData {\n startDate: string;\n endDate: string;\n change: ChangeStatistic;\n services: Array<Entity>;\n}\n\nexport interface KubernetesMigrationApi extends Alert {\n api: CostInsightsApi;\n data: KubernetesMigrationData;\n}\n\n/**\n * This is an example of an Alert implementation using optional event hooks.\n *\n * Event hooks can be used to enable users to dismiss, snooze, or accept an action item\n * - or any combination thereof. Defining a hook will generate default UI - button, dialog and\n * form. Cost Insights does not preserve client side alert state - each hook is expected to return a new set of alerts.\n *\n * Snoozed, accepted, etc. alerts should define a corresponding status property. Alerts will be aggregated\n * by status in a collapsed view below Alert Insights section and a badge will appear in Action Items\n * showing the total alerts of that status.\n *\n * Customizing Alerts\n * Default forms can be overridden in two ways - by setting a form property to null or defining a custom component.\n *\n * If a form property is set to null, the Dialog will not render a form. This can be useful in scenarios\n * where data isn't needed from the user such as when a user accepts an action item's recommendation.\n *\n * If a form property is set to a React component, the Dialog will render the form component in place of the default form.\n * Form components must return valid form elements, and accept a ref and onSubmit event handler.\n * Custom forms must implement the corresponding event hook. See /forms for example implementations.\n */\n\nexport class KubernetesMigrationAlert implements KubernetesMigrationApi {\n api: CostInsightsApi;\n data: KubernetesMigrationData;\n\n subtitle =\n 'Services running on Kubernetes are estimated to save 50% or more compared to Compute Engine.';\n\n // Dialog will not render a form if form property set to null.\n AcceptForm = null;\n // Overrides default Dismiss form with a custom form component.\n DismissForm: AlertForm<\n KubernetesMigrationAlert,\n KubernetesMigrationDismissFormData\n > = KubernetesMigrationDismissForm;\n\n constructor(api: CostInsightsApi, data: KubernetesMigrationData) {\n this.api = api;\n this.data = data;\n }\n\n get title() {\n return (\n <Typography component=\"span\">\n Consider migrating{' '}\n {pluralize('service', this.data.services.length, true)} to Kubernetes{' '}\n <Lifecycle shorthand />\n </Typography>\n );\n }\n\n get element() {\n const subheader = `${pluralize(\n 'Service',\n this.data.services.length,\n true,\n )}, sorted by cost`;\n return (\n <KubernetesMigrationAlertCard\n data={this.data}\n title=\"Migrate to Kubernetes\"\n subheader={subheader}\n currentProduct=\"Compute Engine\"\n comparedProduct=\"Kubernetes\"\n />\n );\n }\n\n /* Fires when the onSubmit event is raised on a Dismiss form. Displays custom dismiss form. */\n async onDismissed(\n options: AlertOptions<KubernetesMigrationDismissFormData>,\n ): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Dismissed,\n },\n ]),\n );\n }\n\n /* Fires when the onSubmit event is raised on a Snooze form. Displays default snooze form. */\n async onSnoozed(\n options: AlertOptions<AlertSnoozeFormData>,\n ): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Snoozed,\n },\n ]),\n );\n }\n\n /* Fires when the Accept button is clicked. Dialog does not render a form. See KubernetesMigrationAlert.AcceptForm */\n async onAccepted(options: AlertOptions<null>): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Accepted,\n },\n ]),\n );\n }\n}\n"],"names":[],"mappings":";;;;;;;;AAuEO,MAAM,wBAA2D,CAAA;AAAA,EACtE,GAAA;AAAA,EACA,IAAA;AAAA,EAEA,QACE,GAAA,8FAAA;AAAA;AAAA,EAGF,UAAa,GAAA,IAAA;AAAA;AAAA,EAEb,WAGI,GAAA,8BAAA;AAAA,EAEJ,WAAA,CAAY,KAAsB,IAA+B,EAAA;AAC/D,IAAA,IAAA,CAAK,GAAM,GAAA,GAAA;AACX,IAAA,IAAA,CAAK,IAAO,GAAA,IAAA;AAAA;AACd,EAEA,IAAI,KAAQ,GAAA;AACV,IACE,uBAAA,IAAA,CAAC,UAAW,EAAA,EAAA,SAAA,EAAU,MAAO,EAAA,QAAA,EAAA;AAAA,MAAA,oBAAA;AAAA,MACR,GAAA;AAAA,MAClB,UAAU,SAAW,EAAA,IAAA,CAAK,IAAK,CAAA,QAAA,CAAS,QAAQ,IAAI,CAAA;AAAA,MAAE,gBAAA;AAAA,MAAe,GAAA;AAAA,sBACtE,GAAA,CAAC,SAAU,EAAA,EAAA,SAAA,EAAS,IAAC,EAAA;AAAA,KACvB,EAAA,CAAA;AAAA;AAEJ,EAEA,IAAI,OAAU,GAAA;AACZ,IAAA,MAAM,YAAY,CAAG,EAAA,SAAA;AAAA,MACnB,SAAA;AAAA,MACA,IAAA,CAAK,KAAK,QAAS,CAAA,MAAA;AAAA,MACnB;AAAA,KACD,CAAA,gBAAA,CAAA;AACD,IACE,uBAAA,GAAA;AAAA,MAAC,4BAAA;AAAA,MAAA;AAAA,QACC,MAAM,IAAK,CAAA,IAAA;AAAA,QACX,KAAM,EAAA,uBAAA;AAAA,QACN,SAAA;AAAA,QACA,cAAe,EAAA,gBAAA;AAAA,QACf,eAAgB,EAAA;AAAA;AAAA,KAClB;AAAA;AAEJ;AAAA,EAGA,MAAM,YACJ,OACkB,EAAA;AAClB,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,GAAI,CAAA,SAAA,CAAU,QAAQ,KAAK,CAAA;AACrD,IAAA,OAAO,IAAI,OAAA;AAAA,MAAQ,CAAA,OAAA,KACjB,UAAW,CAAA,OAAA,EAAS,GAAK,EAAA;AAAA,QACvB,GAAG,MAAO,CAAA,MAAA,CAAO,OAAK,CAAE,CAAA,KAAA,KAAU,KAAK,KAAK,CAAA;AAAA,QAC5C;AAAA,UACE,OAAO,IAAK,CAAA,KAAA;AAAA,UACZ,UAAU,IAAK,CAAA,QAAA;AAAA,UACf,QAAQ,WAAY,CAAA;AAAA;AACtB,OACD;AAAA,KACH;AAAA;AACF;AAAA,EAGA,MAAM,UACJ,OACkB,EAAA;AAClB,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,GAAI,CAAA,SAAA,CAAU,QAAQ,KAAK,CAAA;AACrD,IAAA,OAAO,IAAI,OAAA;AAAA,MAAQ,CAAA,OAAA,KACjB,UAAW,CAAA,OAAA,EAAS,GAAK,EAAA;AAAA,QACvB,GAAG,MAAO,CAAA,MAAA,CAAO,OAAK,CAAE,CAAA,KAAA,KAAU,KAAK,KAAK,CAAA;AAAA,QAC5C;AAAA,UACE,OAAO,IAAK,CAAA,KAAA;AAAA,UACZ,UAAU,IAAK,CAAA,QAAA;AAAA,UACf,QAAQ,WAAY,CAAA;AAAA;AACtB,OACD;AAAA,KACH;AAAA;AACF;AAAA,EAGA,MAAM,WAAW,OAA+C,EAAA;AAC9D,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,GAAI,CAAA,SAAA,CAAU,QAAQ,KAAK,CAAA;AACrD,IAAA,OAAO,IAAI,OAAA;AAAA,MAAQ,CAAA,OAAA,KACjB,UAAW,CAAA,OAAA,EAAS,GAAK,EAAA;AAAA,QACvB,GAAG,MAAO,CAAA,MAAA,CAAO,OAAK,CAAE,CAAA,KAAA,KAAU,KAAK,KAAK,CAAA;AAAA,QAC5C;AAAA,UACE,OAAO,IAAK,CAAA,KAAA;AAAA,UACZ,UAAU,IAAK,CAAA,QAAA;AAAA,UACf,QAAQ,WAAY,CAAA;AAAA;AACtB,OACD;AAAA,KACH;AAAA;AAEJ;;;;"}
@@ -7,7 +7,7 @@ import { UnlabeledDataflowAlert } from '../alerts/UnlabeledDataflowAlert.esm.js'
7
7
  import '../testUtils/products.esm.js';
8
8
  import '../testUtils/filters.esm.js';
9
9
  import '../testUtils/loading.esm.js';
10
- import 'react';
10
+ import 'react/jsx-runtime';
11
11
  import '../hooks/useConfig.esm.js';
12
12
  import '../hooks/useCurrency.esm.js';
13
13
  import '../hooks/useFilters.esm.js';
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import Box from '@material-ui/core/Box';
3
3
  import { KubernetesMigrationBarChartLegend } from './KubernetesMigrationBarChartLegend.esm.js';
4
4
  import { KubernetesMigrationBarChart } from './KubernetesMigrationBarChart.esm.js';
@@ -11,22 +11,25 @@ const KubernetesMigrationAlertCard = ({
11
11
  currentProduct,
12
12
  comparedProduct
13
13
  }) => {
14
- return /* @__PURE__ */ React.createElement(InfoCard, { title, subheader }, /* @__PURE__ */ React.createElement(Box, { display: "flex", flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { paddingY: 1 }, /* @__PURE__ */ React.createElement(
15
- KubernetesMigrationBarChartLegend,
16
- {
17
- startDate: data.startDate,
18
- change: data.change,
19
- currentProduct,
20
- comparedProduct
21
- }
22
- )), /* @__PURE__ */ React.createElement(Box, { paddingY: 1 }, /* @__PURE__ */ React.createElement(
23
- KubernetesMigrationBarChart,
24
- {
25
- services: data.services,
26
- currentProduct,
27
- comparedProduct
28
- }
29
- ))));
14
+ return /* @__PURE__ */ jsx(InfoCard, { title, subheader, children: /* @__PURE__ */ jsxs(Box, { display: "flex", flexDirection: "column", children: [
15
+ /* @__PURE__ */ jsx(Box, { paddingY: 1, children: /* @__PURE__ */ jsx(
16
+ KubernetesMigrationBarChartLegend,
17
+ {
18
+ startDate: data.startDate,
19
+ change: data.change,
20
+ currentProduct,
21
+ comparedProduct
22
+ }
23
+ ) }),
24
+ /* @__PURE__ */ jsx(Box, { paddingY: 1, children: /* @__PURE__ */ jsx(
25
+ KubernetesMigrationBarChart,
26
+ {
27
+ services: data.services,
28
+ currentProduct,
29
+ comparedProduct
30
+ }
31
+ ) })
32
+ ] }) });
30
33
  };
31
34
 
32
35
  export { KubernetesMigrationAlertCard };
@@ -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 React from 'react';\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":";;;;;;AA+BO,MAAM,+BAA+B,CAAC;AAAA,EAC3C,IAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAqC,KAAA;AACnC,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,KAAc,EAAA,SAAA,EAAA,kBACrB,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,OAAQ,EAAA,MAAA,EAAO,aAAc,EAAA,QAAA,EAAA,kBAC/B,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,UAAU,CACb,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,iCAAA;AAAA,IAAA;AAAA,MACC,WAAW,IAAK,CAAA,SAAA;AAAA,MAChB,QAAQ,IAAK,CAAA,MAAA;AAAA,MACb,cAAA;AAAA,MACA;AAAA;AAAA,GAEJ,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,UAAU,CACb,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,2BAAA;AAAA,IAAA;AAAA,MACC,UAAU,IAAK,CAAA,QAAA;AAAA,MACf,cAAA;AAAA,MACA;AAAA;AAAA,GAEJ,CACF,CACF,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,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,4 +1,5 @@
1
- import React from 'react';
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import 'react';
2
3
  import '@material-ui/core/Avatar';
3
4
  import '@material-ui/core/Tooltip';
4
5
  import '@material-ui/core/IconButton';
@@ -97,7 +98,7 @@ const KubernetesMigrationBarChart = ({
97
98
  previous: service.aggregation[0],
98
99
  current: service.aggregation[1]
99
100
  }));
100
- return /* @__PURE__ */ React.createElement(BarChart, { resources, options });
101
+ return /* @__PURE__ */ jsx(BarChart, { resources, options });
101
102
  };
102
103
 
103
104
  export { KubernetesMigrationBarChart };
@@ -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 React from 'react';\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCO,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,KAAA,CAAA,aAAA,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,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,6 +1,7 @@
1
- import React from 'react';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import Box from '@material-ui/core/Box';
3
3
  import { useTheme } from '@material-ui/core/styles';
4
+ import 'react';
4
5
  import '@material-ui/core/Avatar';
5
6
  import '@material-ui/core/Tooltip';
6
7
  import '@material-ui/core/IconButton';
@@ -93,14 +94,18 @@ const KubernetesMigrationBarChartLegend = ({
93
94
  startDate
94
95
  }) => {
95
96
  const theme = useTheme();
96
- return /* @__PURE__ */ React.createElement(Box, { display: "flex", flexDirection: "row" }, /* @__PURE__ */ React.createElement(Box, { marginRight: 2 }, /* @__PURE__ */ React.createElement(
97
- LegendItem,
98
- {
99
- title: monthOf(startDate),
100
- markerColor: theme.palette.magenta
101
- },
102
- currentProduct
103
- )), /* @__PURE__ */ React.createElement(Box, { marginRight: 2 }, /* @__PURE__ */ React.createElement(LegendItem, { title: "Estimated Cost", markerColor: theme.palette.yellow }, comparedProduct)), /* @__PURE__ */ React.createElement(LegendItem, { title: "Total Savings" }, /* @__PURE__ */ React.createElement(CostGrowth, { change, duration: Duration.P30D })));
97
+ return /* @__PURE__ */ jsxs(Box, { display: "flex", flexDirection: "row", children: [
98
+ /* @__PURE__ */ jsx(Box, { marginRight: 2, children: /* @__PURE__ */ jsx(
99
+ LegendItem,
100
+ {
101
+ title: monthOf(startDate),
102
+ markerColor: theme.palette.magenta,
103
+ children: currentProduct
104
+ }
105
+ ) }),
106
+ /* @__PURE__ */ jsx(Box, { marginRight: 2, children: /* @__PURE__ */ jsx(LegendItem, { title: "Estimated Cost", markerColor: theme.palette.yellow, children: comparedProduct }) }),
107
+ /* @__PURE__ */ jsx(LegendItem, { title: "Total Savings", children: /* @__PURE__ */ jsx(CostGrowth, { change, duration: Duration.P30D }) })
108
+ ] });
104
109
  };
105
110
 
106
111
  export { KubernetesMigrationBarChartLegend };
@@ -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 React from 'react';\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BO,MAAM,oCAAoC,CAAC;AAAA,EAChD,cAAA;AAAA,EACA,eAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAoC,KAAA;AAClC,EAAA,MAAM,QAAQ,QAA4B,EAAA;AAC1C,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,OAAQ,EAAA,MAAA,EAAO,eAAc,KAChC,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,WAAA,EAAa,CAChB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,QAAQ,SAAS,CAAA;AAAA,MACxB,WAAA,EAAa,MAAM,OAAQ,CAAA;AAAA,KAAA;AAAA,IAE1B;AAAA,GAEL,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,WAAa,EAAA,CAAA,EAAA,kBACf,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,KAAM,EAAA,gBAAA,EAAiB,WAAa,EAAA,KAAA,CAAM,OAAQ,CAAA,MAAA,EAAA,EAC3D,eACH,CACF,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,KAAA,EAAM,eAChB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,MAAA,EAAgB,QAAU,EAAA,QAAA,CAAS,IAAM,EAAA,CACvD,CACF,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,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,4 +1,5 @@
1
- import React, { forwardRef, useState, useEffect } from 'react';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { forwardRef, useState, useEffect } from 'react';
2
3
  import Checkbox from '@material-ui/core/Checkbox';
3
4
  import FormControl from '@material-ui/core/FormControl';
4
5
  import FormControlLabel from '@material-ui/core/FormControlLabel';
@@ -34,22 +35,25 @@ const KubernetesMigrationDismissForm = forwardRef(({ onSubmit, disableSubmit, al
34
35
  }, [services, disableSubmit]);
35
36
  return (
36
37
  /* All custom forms must accept a ref and implement an onSubmit handler. */
37
- /* @__PURE__ */ React.createElement("form", { ref, onSubmit: onFormSubmit }, /* @__PURE__ */ React.createElement(FormControl, { component: "fieldset", fullWidth: true }, /* @__PURE__ */ React.createElement(Typography, { color: "textPrimary" }, /* @__PURE__ */ React.createElement("b", null, "Or choose which services to dismiss this alert for.")), /* @__PURE__ */ React.createElement(FormGroup, null, alert.data.services.map((service, index) => /* @__PURE__ */ React.createElement(
38
- FormControlLabel,
39
- {
40
- key: `example-option-${index}`,
41
- label: service.id,
42
- value: service.id,
43
- control: /* @__PURE__ */ React.createElement(
44
- Checkbox,
45
- {
46
- color: "primary",
47
- checked: services.some((p) => p.id === service.id),
48
- onChange: onCheckboxChange
49
- }
50
- )
51
- }
52
- )))))
38
+ /* @__PURE__ */ jsx("form", { ref, onSubmit: onFormSubmit, children: /* @__PURE__ */ jsxs(FormControl, { component: "fieldset", fullWidth: true, children: [
39
+ /* @__PURE__ */ jsx(Typography, { color: "textPrimary", children: /* @__PURE__ */ jsx("b", { children: "Or choose which services to dismiss this alert for." }) }),
40
+ /* @__PURE__ */ jsx(FormGroup, { children: alert.data.services.map((service, index) => /* @__PURE__ */ jsx(
41
+ FormControlLabel,
42
+ {
43
+ label: service.id,
44
+ value: service.id,
45
+ control: /* @__PURE__ */ jsx(
46
+ Checkbox,
47
+ {
48
+ color: "primary",
49
+ checked: services.some((p) => p.id === service.id),
50
+ onChange: onCheckboxChange
51
+ }
52
+ )
53
+ },
54
+ `example-option-${index}`
55
+ )) })
56
+ ] }) })
53
57
  );
54
58
  });
55
59