@backstage-community/plugin-cost-insights 0.12.24 → 0.12.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +6 -6
- package/dist/alerts/ProjectGrowthAlert.esm.js +24 -0
- package/dist/alerts/ProjectGrowthAlert.esm.js.map +1 -0
- package/dist/alerts/UnlabeledDataflowAlert.esm.js +25 -0
- package/dist/alerts/UnlabeledDataflowAlert.esm.js.map +1 -0
- package/dist/api/CostInsightsApi.esm.js +8 -0
- package/dist/api/CostInsightsApi.esm.js.map +1 -0
- package/dist/components/ActionItems/ActionItemCard.esm.js +46 -0
- package/dist/components/ActionItems/ActionItemCard.esm.js.map +1 -0
- package/dist/components/ActionItems/ActionItems.esm.js +90 -0
- package/dist/components/ActionItems/ActionItems.esm.js.map +1 -0
- package/dist/components/AlertInsights/AlertDialog.esm.js +123 -0
- package/dist/components/AlertInsights/AlertDialog.esm.js.map +1 -0
- package/dist/components/AlertInsights/AlertInsights.esm.js +157 -0
- package/dist/components/AlertInsights/AlertInsights.esm.js.map +1 -0
- package/dist/components/AlertInsights/AlertInsightsHeader.esm.js +17 -0
- package/dist/components/AlertInsights/AlertInsightsHeader.esm.js.map +1 -0
- package/dist/components/AlertInsights/AlertInsightsSection.esm.js +57 -0
- package/dist/components/AlertInsights/AlertInsightsSection.esm.js.map +1 -0
- package/dist/components/AlertInsights/AlertInsightsSectionHeader.esm.js +30 -0
- package/dist/components/AlertInsights/AlertInsightsSectionHeader.esm.js.map +1 -0
- package/dist/components/AlertInsights/AlertStatusSummary.esm.js +93 -0
- package/dist/components/AlertInsights/AlertStatusSummary.esm.js.map +1 -0
- package/dist/components/AlertInsights/AlertStatusSummaryButton.esm.js +35 -0
- package/dist/components/AlertInsights/AlertStatusSummaryButton.esm.js.map +1 -0
- package/dist/components/AlertInstructionsLayout/AlertInstructionsLayout.esm.js +47 -0
- package/dist/components/AlertInstructionsLayout/AlertInstructionsLayout.esm.js.map +1 -0
- package/dist/components/BarChart/BarChart.esm.js +167 -0
- package/dist/components/BarChart/BarChart.esm.js.map +1 -0
- package/dist/components/BarChart/BarChartLabel.esm.js +31 -0
- package/dist/components/BarChart/BarChartLabel.esm.js.map +1 -0
- package/dist/components/BarChart/BarChartLegend.esm.js +47 -0
- package/dist/components/BarChart/BarChartLegend.esm.js.map +1 -0
- package/dist/components/BarChart/BarChartStepper.esm.js +91 -0
- package/dist/components/BarChart/BarChartStepper.esm.js.map +1 -0
- package/dist/components/BarChart/BarChartStepperButton.esm.js +27 -0
- package/dist/components/BarChart/BarChartStepperButton.esm.js.map +1 -0
- package/dist/components/BarChart/BarChartSteps.esm.js +25 -0
- package/dist/components/BarChart/BarChartSteps.esm.js.map +1 -0
- package/dist/components/BarChart/BarChartTick.esm.js +29 -0
- package/dist/components/BarChart/BarChartTick.esm.js.map +1 -0
- package/dist/components/BarChart/BarChartTooltip.esm.js +30 -0
- package/dist/components/BarChart/BarChartTooltip.esm.js.map +1 -0
- package/dist/components/BarChart/BarChartTooltipItem.esm.js +24 -0
- package/dist/components/BarChart/BarChartTooltipItem.esm.js.map +1 -0
- package/dist/components/CopyUrlToClipboard/CopyUrlToClipboard.esm.js +44 -0
- package/dist/components/CopyUrlToClipboard/CopyUrlToClipboard.esm.js.map +1 -0
- package/dist/components/CostGrowth/CostGrowth.esm.js +55 -0
- package/dist/components/CostGrowth/CostGrowth.esm.js.map +1 -0
- package/dist/components/CostGrowth/CostGrowthIndicator.esm.js +31 -0
- package/dist/components/CostGrowth/CostGrowthIndicator.esm.js.map +1 -0
- package/dist/components/CostInsightsHeader/CostInsightsHeader.esm.js +57 -0
- package/dist/components/CostInsightsHeader/CostInsightsHeader.esm.js.map +1 -0
- package/dist/components/CostInsightsLayout/CostInsightsLayout.esm.js +35 -0
- package/dist/components/CostInsightsLayout/CostInsightsLayout.esm.js.map +1 -0
- package/dist/components/CostInsightsNavigation/CostInsightsNavigation.esm.js +87 -0
- package/dist/components/CostInsightsNavigation/CostInsightsNavigation.esm.js.map +1 -0
- package/dist/components/CostInsightsPage/CostInsightsPage.esm.js +229 -0
- package/dist/components/CostInsightsPage/CostInsightsPage.esm.js.map +1 -0
- package/dist/components/CostInsightsPage/CostInsightsPageRoot.esm.js +15 -0
- package/dist/components/CostInsightsPage/CostInsightsPageRoot.esm.js.map +1 -0
- package/dist/components/CostInsightsPage/CostInsightsThemeProvider.esm.js +24 -0
- package/dist/components/CostInsightsPage/CostInsightsThemeProvider.esm.js.map +1 -0
- package/dist/components/CostInsightsPage/index.esm.js +2 -0
- package/dist/components/CostInsightsPage/index.esm.js.map +1 -0
- package/dist/components/CostInsightsPage/selector.esm.js +15 -0
- package/dist/components/CostInsightsPage/selector.esm.js.map +1 -0
- package/dist/components/CostInsightsTabs/CostInsightsTabs.esm.js +89 -0
- package/dist/components/CostInsightsTabs/CostInsightsTabs.esm.js.map +1 -0
- package/dist/components/CostInsightsTabs/selector.esm.js +17 -0
- package/dist/components/CostInsightsTabs/selector.esm.js.map +1 -0
- package/dist/components/CostOverviewCard/CostOverviewBreakdownChart.esm.js +196 -0
- package/dist/components/CostOverviewCard/CostOverviewBreakdownChart.esm.js.map +1 -0
- package/dist/components/CostOverviewCard/CostOverviewCard.esm.js +99 -0
- package/dist/components/CostOverviewCard/CostOverviewCard.esm.js.map +1 -0
- package/dist/components/CostOverviewCard/CostOverviewChart.esm.js +157 -0
- package/dist/components/CostOverviewCard/CostOverviewChart.esm.js.map +1 -0
- package/dist/components/CostOverviewCard/CostOverviewHeader.esm.js +25 -0
- package/dist/components/CostOverviewCard/CostOverviewHeader.esm.js.map +1 -0
- package/dist/components/CostOverviewCard/CostOverviewLegend.esm.js +54 -0
- package/dist/components/CostOverviewCard/CostOverviewLegend.esm.js.map +1 -0
- package/dist/components/CostOverviewCard/selector.esm.js +22 -0
- package/dist/components/CostOverviewCard/selector.esm.js.map +1 -0
- package/dist/components/CurrencySelect/CurrencySelect.esm.js +52 -0
- package/dist/components/CurrencySelect/CurrencySelect.esm.js.map +1 -0
- package/dist/{esm/index-BPzWHt3A.esm.js → components/EntityCosts/EntityCosts.esm.js} +14 -80
- package/dist/{esm/index-BPzWHt3A.esm.js.map → components/EntityCosts/EntityCosts.esm.js.map} +1 -1
- package/dist/components/EntityCosts/index.esm.js +2 -0
- package/dist/components/EntityCosts/index.esm.js.map +1 -0
- package/dist/{esm/index-BA6m_qFS.esm.js → components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.esm.js} +2 -79
- package/dist/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.esm.js.map +1 -0
- package/dist/components/LabelDataflowInstructionsPage/index.esm.js +2 -0
- package/dist/components/LabelDataflowInstructionsPage/index.esm.js.map +1 -0
- package/dist/components/LegendItem/LegendItem.esm.js +44 -0
- package/dist/components/LegendItem/LegendItem.esm.js.map +1 -0
- package/dist/components/MetricSelect/MetricSelect.esm.js +37 -0
- package/dist/components/MetricSelect/MetricSelect.esm.js.map +1 -0
- package/dist/components/PeriodSelect/PeriodSelect.esm.js +72 -0
- package/dist/components/PeriodSelect/PeriodSelect.esm.js.map +1 -0
- package/dist/components/ProductInsights/ProductInsights.esm.js +98 -0
- package/dist/components/ProductInsights/ProductInsights.esm.js.map +1 -0
- package/dist/components/ProductInsightsCard/ProductEntityDialog.esm.js +42 -0
- package/dist/components/ProductInsightsCard/ProductEntityDialog.esm.js.map +1 -0
- package/dist/components/ProductInsightsCard/ProductEntityTable.esm.js +139 -0
- package/dist/components/ProductInsightsCard/ProductEntityTable.esm.js.map +1 -0
- package/dist/components/ProductInsightsCard/ProductInsightsCard.esm.js +83 -0
- package/dist/components/ProductInsightsCard/ProductInsightsCard.esm.js.map +1 -0
- package/dist/components/ProductInsightsCard/ProductInsightsCardList.esm.js +34 -0
- package/dist/components/ProductInsightsCard/ProductInsightsCardList.esm.js.map +1 -0
- package/dist/components/ProductInsightsCard/ProductInsightsChart.esm.js +148 -0
- package/dist/components/ProductInsightsCard/ProductInsightsChart.esm.js.map +1 -0
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.esm.js +20 -0
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.esm.js.map +1 -0
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertChart.esm.js +46 -0
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertChart.esm.js.map +1 -0
- package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js +111 -0
- package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js.map +1 -0
- package/dist/components/ProjectGrowthInstructionsPage/index.esm.js +2 -0
- package/dist/components/ProjectGrowthInstructionsPage/index.esm.js.map +1 -0
- package/dist/components/ProjectSelect/ProjectSelect.esm.js +47 -0
- package/dist/components/ProjectSelect/ProjectSelect.esm.js.map +1 -0
- package/dist/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.esm.js +41 -0
- package/dist/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.esm.js.map +1 -0
- package/dist/components/WhyCostsMatter/WhyCostsMatter.esm.js +21 -0
- package/dist/components/WhyCostsMatter/WhyCostsMatter.esm.js.map +1 -0
- package/dist/example/alerts/KubernetesMigrationAlert.esm.js +86 -0
- package/dist/example/alerts/KubernetesMigrationAlert.esm.js.map +1 -0
- package/dist/example/client.esm.js +194 -0
- package/dist/example/client.esm.js.map +1 -0
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.esm.js +33 -0
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.esm.js.map +1 -0
- package/dist/{esm/index-BTIHr4n_.esm.js → example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.esm.js} +69 -48
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.esm.js.map +1 -0
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.esm.js +107 -0
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.esm.js.map +1 -0
- package/dist/example/forms/KubernetesMigrationDismissForm.esm.js +57 -0
- package/dist/example/forms/KubernetesMigrationDismissForm.esm.js.map +1 -0
- package/dist/forms/AlertAcceptForm.esm.js +27 -0
- package/dist/forms/AlertAcceptForm.esm.js.map +1 -0
- package/dist/forms/AlertDismissForm.esm.js +100 -0
- package/dist/forms/AlertDismissForm.esm.js.map +1 -0
- package/dist/forms/AlertSnoozeForm.esm.js +52 -0
- package/dist/forms/AlertSnoozeForm.esm.js.map +1 -0
- package/dist/hooks/useConfig.esm.js +153 -0
- package/dist/hooks/useConfig.esm.js.map +1 -0
- package/dist/hooks/useCurrency.esm.js +26 -0
- package/dist/hooks/useCurrency.esm.js.map +1 -0
- package/dist/hooks/useFilters.esm.js +67 -0
- package/dist/hooks/useFilters.esm.js.map +1 -0
- package/dist/hooks/useGroups.esm.js +55 -0
- package/dist/hooks/useGroups.esm.js.map +1 -0
- package/dist/hooks/useLastCompleteBillingDate.esm.js +65 -0
- package/dist/hooks/useLastCompleteBillingDate.esm.js.map +1 -0
- package/dist/hooks/useLoading.esm.js +54 -0
- package/dist/hooks/useLoading.esm.js.map +1 -0
- package/dist/hooks/useScroll.esm.js +24 -0
- package/dist/hooks/useScroll.esm.js.map +1 -0
- package/dist/index.esm.js +37 -22
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +55 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/testUtils/filters.esm.js +8 -0
- package/dist/testUtils/filters.esm.js.map +1 -0
- package/dist/testUtils/loading.esm.js +14 -0
- package/dist/testUtils/loading.esm.js.map +1 -0
- package/dist/testUtils/mockData.esm.js +485 -0
- package/dist/testUtils/mockData.esm.js.map +1 -0
- package/dist/testUtils/products.esm.js +49 -0
- package/dist/testUtils/products.esm.js.map +1 -0
- package/dist/testUtils/providers.esm.js +41 -0
- package/dist/testUtils/providers.esm.js.map +1 -0
- package/dist/testUtils/testUtils.esm.js +142 -0
- package/dist/testUtils/testUtils.esm.js.map +1 -0
- package/dist/types/Alert.esm.js +66 -0
- package/dist/types/Alert.esm.js.map +1 -0
- package/dist/types/ChangeStatistic.esm.js +15 -0
- package/dist/types/ChangeStatistic.esm.js.map +1 -0
- package/dist/types/CurrencyType.esm.js +10 -0
- package/dist/types/CurrencyType.esm.js.map +1 -0
- package/dist/types/DateFormat.esm.js +4 -0
- package/dist/types/DateFormat.esm.js.map +1 -0
- package/dist/types/Duration.esm.js +10 -0
- package/dist/types/Duration.esm.js.map +1 -0
- package/dist/types/Icon.esm.js +12 -0
- package/dist/types/Icon.esm.js.map +1 -0
- package/dist/utils/alerts.esm.js +72 -0
- package/dist/utils/alerts.esm.js.map +1 -0
- package/dist/utils/assert.esm.js +29 -0
- package/dist/utils/assert.esm.js.map +1 -0
- package/dist/utils/change.esm.js +58 -0
- package/dist/utils/change.esm.js.map +1 -0
- package/dist/utils/charts.esm.js +9 -0
- package/dist/utils/charts.esm.js.map +1 -0
- package/dist/utils/config.esm.js +19 -0
- package/dist/utils/config.esm.js.map +1 -0
- package/dist/utils/currency.esm.js +56 -0
- package/dist/utils/currency.esm.js.map +1 -0
- package/dist/utils/duration.esm.js +55 -0
- package/dist/utils/duration.esm.js.map +1 -0
- package/dist/utils/filters.esm.js +14 -0
- package/dist/utils/filters.esm.js.map +1 -0
- package/dist/utils/formatters.esm.js +103 -0
- package/dist/utils/formatters.esm.js.map +1 -0
- package/dist/utils/grammar.esm.js +14 -0
- package/dist/utils/grammar.esm.js.map +1 -0
- package/dist/utils/graphs.esm.js +48 -0
- package/dist/utils/graphs.esm.js.map +1 -0
- package/dist/utils/history.esm.js +32 -0
- package/dist/utils/history.esm.js.map +1 -0
- package/dist/utils/loading.esm.js +51 -0
- package/dist/utils/loading.esm.js.map +1 -0
- package/dist/utils/navigation.esm.js +56 -0
- package/dist/utils/navigation.esm.js.map +1 -0
- package/dist/utils/scroll.esm.js +38 -0
- package/dist/utils/scroll.esm.js.map +1 -0
- package/dist/utils/sort.esm.js +10 -0
- package/dist/utils/sort.esm.js.map +1 -0
- package/dist/utils/styles.esm.js +562 -0
- package/dist/utils/styles.esm.js.map +1 -0
- package/dist/utils/sum.esm.js +4 -0
- package/dist/utils/sum.esm.js.map +1 -0
- package/package.json +17 -12
- package/dist/esm/index-BA6m_qFS.esm.js.map +0 -1
- package/dist/esm/index-BFM2mP6Z.esm.js +0 -4084
- package/dist/esm/index-BFM2mP6Z.esm.js.map +0 -1
- package/dist/esm/index-BTIHr4n_.esm.js.map +0 -1
- package/dist/esm/index-DaitkcPN.esm.js +0 -1136
- package/dist/esm/index-DaitkcPN.esm.js.map +0 -1
- package/dist/esm/selector-D7iXJwd9.esm.js +0 -594
- package/dist/esm/selector-D7iXJwd9.esm.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"currency.esm.js","sources":["../../src/utils/currency.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Currency, CurrencyType, Duration } from '../types';\nimport { assertNever } from './assert';\n\nexport const rateOf = (cost: number, duration: Duration) => {\n switch (duration) {\n case Duration.P30D:\n return cost / 12;\n case Duration.P7D:\n case Duration.P90D:\n case Duration.P3M:\n return cost / 4;\n default:\n return assertNever(duration);\n }\n};\n\nexport const defaultCurrencies: Currency[] = [\n {\n kind: null,\n label: 'Engineers 🛠',\n unit: 'engineer',\n },\n {\n kind: CurrencyType.USD,\n label: 'US Dollars 💵',\n unit: 'dollar',\n prefix: '$',\n rate: 1,\n },\n {\n kind: CurrencyType.CarbonOffsetTons,\n label: 'Carbon Offset Tons ♻️⚖️s',\n unit: 'carbon offset ton',\n rate: 3.5,\n },\n {\n kind: CurrencyType.Beers,\n label: 'Beers 🍺',\n unit: 'beer',\n rate: 4.5,\n },\n {\n kind: CurrencyType.IceCream,\n label: 'Pints of Ice Cream 🍦',\n unit: 'ice cream pint',\n rate: 5.5,\n },\n];\n\nexport const createCurrencyFormat = (\n currency: string = 'USD',\n locale: string = 'en-US',\n) =>\n new Intl.NumberFormat(locale, {\n currency,\n style: 'currency',\n });\n"],"names":[],"mappings":";;;;;AAkBa,MAAA,MAAA,GAAS,CAAC,IAAA,EAAc,QAAuB,KAAA;AAC1D,EAAA,QAAQ,QAAU;AAAA,IAChB,KAAK,QAAS,CAAA,IAAA;AACZ,MAAA,OAAO,IAAO,GAAA,EAAA,CAAA;AAAA,IAChB,KAAK,QAAS,CAAA,GAAA,CAAA;AAAA,IACd,KAAK,QAAS,CAAA,IAAA,CAAA;AAAA,IACd,KAAK,QAAS,CAAA,GAAA;AACZ,MAAA,OAAO,IAAO,GAAA,CAAA,CAAA;AAAA,IAChB;AACE,MAAA,OAAO,YAAY,QAAQ,CAAA,CAAA;AAAA,GAC/B;AACF,EAAA;AAEO,MAAM,iBAAgC,GAAA;AAAA,EAC3C;AAAA,IACE,IAAM,EAAA,IAAA;AAAA,IACN,KAAO,EAAA,qBAAA;AAAA,IACP,IAAM,EAAA,UAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,MAAM,YAAa,CAAA,GAAA;AAAA,IACnB,KAAO,EAAA,sBAAA;AAAA,IACP,IAAM,EAAA,QAAA;AAAA,IACN,MAAQ,EAAA,GAAA;AAAA,IACR,IAAM,EAAA,CAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,MAAM,YAAa,CAAA,gBAAA;AAAA,IACnB,KAAO,EAAA,8CAAA;AAAA,IACP,IAAM,EAAA,mBAAA;AAAA,IACN,IAAM,EAAA,GAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,MAAM,YAAa,CAAA,KAAA;AAAA,IACnB,KAAO,EAAA,iBAAA;AAAA,IACP,IAAM,EAAA,MAAA;AAAA,IACN,IAAM,EAAA,GAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,MAAM,YAAa,CAAA,QAAA;AAAA,IACnB,KAAO,EAAA,8BAAA;AAAA,IACP,IAAM,EAAA,gBAAA;AAAA,IACN,IAAM,EAAA,GAAA;AAAA,GACR;AACF,EAAA;AAEa,MAAA,oBAAA,GAAuB,CAClC,QAAmB,GAAA,KAAA,EACnB,SAAiB,OAEjB,KAAA,IAAI,IAAK,CAAA,YAAA,CAAa,MAAQ,EAAA;AAAA,EAC5B,QAAA;AAAA,EACA,KAAO,EAAA,UAAA;AACT,CAAC;;;;"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { DateTime, Duration as Duration$1 } from 'luxon';
|
|
2
|
+
import '../types/Alert.esm.js';
|
|
3
|
+
import { DEFAULT_DATE_FORMAT } from '../types/DateFormat.esm.js';
|
|
4
|
+
import { Duration } from '../types/Duration.esm.js';
|
|
5
|
+
import { assertNever } from './assert.esm.js';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_DURATION = Duration.P30D;
|
|
8
|
+
function inclusiveStartDateOf(duration, inclusiveEndDate) {
|
|
9
|
+
switch (duration) {
|
|
10
|
+
case Duration.P7D:
|
|
11
|
+
case Duration.P30D:
|
|
12
|
+
case Duration.P90D:
|
|
13
|
+
return DateTime.fromISO(inclusiveEndDate).minus(
|
|
14
|
+
Duration$1.fromISO(duration).plus(Duration$1.fromISO(duration))
|
|
15
|
+
).toFormat(DEFAULT_DATE_FORMAT);
|
|
16
|
+
case Duration.P3M:
|
|
17
|
+
return DateTime.fromISO(inclusiveEndDate).startOf("quarter").minus(
|
|
18
|
+
Duration$1.fromISO(duration).plus(Duration$1.fromISO(duration))
|
|
19
|
+
).toFormat(DEFAULT_DATE_FORMAT);
|
|
20
|
+
default:
|
|
21
|
+
return assertNever(duration);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function exclusiveEndDateOf(duration, inclusiveEndDate) {
|
|
25
|
+
switch (duration) {
|
|
26
|
+
case Duration.P7D:
|
|
27
|
+
case Duration.P30D:
|
|
28
|
+
case Duration.P90D:
|
|
29
|
+
return DateTime.fromISO(inclusiveEndDate).plus({ days: 1 }).toFormat(DEFAULT_DATE_FORMAT);
|
|
30
|
+
case Duration.P3M:
|
|
31
|
+
return DateTime.fromISO(quarterEndDate(inclusiveEndDate)).plus({ days: 1 }).toFormat(DEFAULT_DATE_FORMAT);
|
|
32
|
+
default:
|
|
33
|
+
return assertNever(duration);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function inclusiveEndDateOf(duration, inclusiveEndDate) {
|
|
37
|
+
return DateTime.fromISO(exclusiveEndDateOf(duration, inclusiveEndDate)).minus({ days: 1 }).toFormat(DEFAULT_DATE_FORMAT);
|
|
38
|
+
}
|
|
39
|
+
function intervalsOf(duration, inclusiveEndDate, repeating = 2) {
|
|
40
|
+
return `R${repeating}/${duration}/${exclusiveEndDateOf(
|
|
41
|
+
duration,
|
|
42
|
+
inclusiveEndDate
|
|
43
|
+
)}`;
|
|
44
|
+
}
|
|
45
|
+
function quarterEndDate(inclusiveEndDate) {
|
|
46
|
+
const endDate = DateTime.fromISO(inclusiveEndDate);
|
|
47
|
+
const endOfQuarter = endDate.endOf("quarter").toFormat(DEFAULT_DATE_FORMAT);
|
|
48
|
+
if (endOfQuarter === inclusiveEndDate) {
|
|
49
|
+
return endDate.toFormat(DEFAULT_DATE_FORMAT);
|
|
50
|
+
}
|
|
51
|
+
return endDate.startOf("quarter").minus({ days: 1 }).toFormat(DEFAULT_DATE_FORMAT);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { DEFAULT_DURATION, exclusiveEndDateOf, inclusiveEndDateOf, inclusiveStartDateOf, intervalsOf, quarterEndDate };
|
|
55
|
+
//# sourceMappingURL=duration.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duration.esm.js","sources":["../../src/utils/duration.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DateTime, Duration as LuxonDuration } from 'luxon';\nimport { Duration, DEFAULT_DATE_FORMAT } from '../types';\nimport { assertNever } from './assert';\n\nexport const DEFAULT_DURATION = Duration.P30D;\n\n/**\n * Derive the start date of a given period, assuming two repeating intervals.\n *\n * @param duration - see comment on Duration enum\n * @param inclusiveEndDate - from CostInsightsApi.getLastCompleteBillingDate\n */\nexport function inclusiveStartDateOf(\n duration: Duration,\n inclusiveEndDate: string,\n): string {\n switch (duration) {\n case Duration.P7D:\n case Duration.P30D:\n case Duration.P90D:\n return DateTime.fromISO(inclusiveEndDate)\n .minus(\n LuxonDuration.fromISO(duration).plus(LuxonDuration.fromISO(duration)),\n )\n .toFormat(DEFAULT_DATE_FORMAT);\n case Duration.P3M:\n return DateTime.fromISO(inclusiveEndDate)\n .startOf('quarter')\n .minus(\n LuxonDuration.fromISO(duration).plus(LuxonDuration.fromISO(duration)),\n )\n .toFormat(DEFAULT_DATE_FORMAT);\n default:\n return assertNever(duration);\n }\n}\n\nexport function exclusiveEndDateOf(\n duration: Duration,\n inclusiveEndDate: string,\n): string {\n switch (duration) {\n case Duration.P7D:\n case Duration.P30D:\n case Duration.P90D:\n return DateTime.fromISO(inclusiveEndDate)\n .plus({ days: 1 })\n .toFormat(DEFAULT_DATE_FORMAT);\n case Duration.P3M:\n return DateTime.fromISO(quarterEndDate(inclusiveEndDate))\n .plus({ days: 1 })\n .toFormat(DEFAULT_DATE_FORMAT);\n default:\n return assertNever(duration);\n }\n}\n\nexport function inclusiveEndDateOf(\n duration: Duration,\n inclusiveEndDate: string,\n): string {\n return DateTime.fromISO(exclusiveEndDateOf(duration, inclusiveEndDate))\n .minus({ days: 1 })\n .toFormat(DEFAULT_DATE_FORMAT);\n}\n\n// https://en.wikipedia.org/wiki/ISO_8601#Repeating_intervals\nexport function intervalsOf(\n duration: Duration,\n inclusiveEndDate: string,\n repeating: number = 2,\n) {\n return `R${repeating}/${duration}/${exclusiveEndDateOf(\n duration,\n inclusiveEndDate,\n )}`;\n}\n\nexport function quarterEndDate(inclusiveEndDate: string): string {\n const endDate = DateTime.fromISO(inclusiveEndDate);\n const endOfQuarter = endDate.endOf('quarter').toFormat(DEFAULT_DATE_FORMAT);\n if (endOfQuarter === inclusiveEndDate) {\n return endDate.toFormat(DEFAULT_DATE_FORMAT);\n }\n return endDate\n .startOf('quarter')\n .minus({ days: 1 })\n .toFormat(DEFAULT_DATE_FORMAT);\n}\n"],"names":["LuxonDuration"],"mappings":";;;;;;AAoBO,MAAM,mBAAmB,QAAS,CAAA,KAAA;AAQzB,SAAA,oBAAA,CACd,UACA,gBACQ,EAAA;AACR,EAAA,QAAQ,QAAU;AAAA,IAChB,KAAK,QAAS,CAAA,GAAA,CAAA;AAAA,IACd,KAAK,QAAS,CAAA,IAAA,CAAA;AAAA,IACd,KAAK,QAAS,CAAA,IAAA;AACZ,MAAO,OAAA,QAAA,CAAS,OAAQ,CAAA,gBAAgB,CACrC,CAAA,KAAA;AAAA,QACCA,UAAA,CAAc,QAAQ,QAAQ,CAAA,CAAE,KAAKA,UAAc,CAAA,OAAA,CAAQ,QAAQ,CAAC,CAAA;AAAA,OACtE,CACC,SAAS,mBAAmB,CAAA,CAAA;AAAA,IACjC,KAAK,QAAS,CAAA,GAAA;AACZ,MAAA,OAAO,SAAS,OAAQ,CAAA,gBAAgB,CACrC,CAAA,OAAA,CAAQ,SAAS,CACjB,CAAA,KAAA;AAAA,QACCA,UAAA,CAAc,QAAQ,QAAQ,CAAA,CAAE,KAAKA,UAAc,CAAA,OAAA,CAAQ,QAAQ,CAAC,CAAA;AAAA,OACtE,CACC,SAAS,mBAAmB,CAAA,CAAA;AAAA,IACjC;AACE,MAAA,OAAO,YAAY,QAAQ,CAAA,CAAA;AAAA,GAC/B;AACF,CAAA;AAEgB,SAAA,kBAAA,CACd,UACA,gBACQ,EAAA;AACR,EAAA,QAAQ,QAAU;AAAA,IAChB,KAAK,QAAS,CAAA,GAAA,CAAA;AAAA,IACd,KAAK,QAAS,CAAA,IAAA,CAAA;AAAA,IACd,KAAK,QAAS,CAAA,IAAA;AACZ,MAAO,OAAA,QAAA,CAAS,OAAQ,CAAA,gBAAgB,CACrC,CAAA,IAAA,CAAK,EAAE,IAAA,EAAM,CAAE,EAAC,CAChB,CAAA,QAAA,CAAS,mBAAmB,CAAA,CAAA;AAAA,IACjC,KAAK,QAAS,CAAA,GAAA;AACZ,MAAA,OAAO,QAAS,CAAA,OAAA,CAAQ,cAAe,CAAA,gBAAgB,CAAC,CAAA,CACrD,IAAK,CAAA,EAAE,IAAM,EAAA,CAAA,EAAG,CAAA,CAChB,SAAS,mBAAmB,CAAA,CAAA;AAAA,IACjC;AACE,MAAA,OAAO,YAAY,QAAQ,CAAA,CAAA;AAAA,GAC/B;AACF,CAAA;AAEgB,SAAA,kBAAA,CACd,UACA,gBACQ,EAAA;AACR,EAAA,OAAO,QAAS,CAAA,OAAA,CAAQ,kBAAmB,CAAA,QAAA,EAAU,gBAAgB,CAAC,CAAA,CACnE,KAAM,CAAA,EAAE,IAAM,EAAA,CAAA,EAAG,CAAA,CACjB,SAAS,mBAAmB,CAAA,CAAA;AACjC,CAAA;AAGO,SAAS,WACd,CAAA,QAAA,EACA,gBACA,EAAA,SAAA,GAAoB,CACpB,EAAA;AACA,EAAA,OAAO,CAAI,CAAA,EAAA,SAAS,CAAI,CAAA,EAAA,QAAQ,CAAI,CAAA,EAAA,kBAAA;AAAA,IAClC,QAAA;AAAA,IACA,gBAAA;AAAA,GACD,CAAA,CAAA,CAAA;AACH,CAAA;AAEO,SAAS,eAAe,gBAAkC,EAAA;AAC/D,EAAM,MAAA,OAAA,GAAU,QAAS,CAAA,OAAA,CAAQ,gBAAgB,CAAA,CAAA;AACjD,EAAA,MAAM,eAAe,OAAQ,CAAA,KAAA,CAAM,SAAS,CAAA,CAAE,SAAS,mBAAmB,CAAA,CAAA;AAC1E,EAAA,IAAI,iBAAiB,gBAAkB,EAAA;AACrC,IAAO,OAAA,OAAA,CAAQ,SAAS,mBAAmB,CAAA,CAAA;AAAA,GAC7C;AACA,EAAO,OAAA,OAAA,CACJ,OAAQ,CAAA,SAAS,CACjB,CAAA,KAAA,CAAM,EAAE,IAAA,EAAM,CAAE,EAAC,CACjB,CAAA,QAAA,CAAS,mBAAmB,CAAA,CAAA;AACjC;;;;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import '../types/Alert.esm.js';
|
|
2
|
+
import { Duration } from '../types/Duration.esm.js';
|
|
3
|
+
|
|
4
|
+
function getDefaultPageFilters(groups) {
|
|
5
|
+
return {
|
|
6
|
+
group: groups.length ? groups[0].id : null,
|
|
7
|
+
project: null,
|
|
8
|
+
duration: Duration.P90D,
|
|
9
|
+
metric: null
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { getDefaultPageFilters };
|
|
14
|
+
//# sourceMappingURL=filters.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filters.esm.js","sources":["../../src/utils/filters.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Duration, PageFilters } from '../types';\nimport { Group } from '@backstage-community/plugin-cost-insights-common';\n\nexport function getDefaultPageFilters(groups: Group[]): PageFilters {\n return {\n group: groups.length ? groups[0].id : null,\n project: null,\n duration: Duration.P90D,\n metric: null,\n };\n}\n"],"names":[],"mappings":";;;AAmBO,SAAS,sBAAsB,MAA8B,EAAA;AAClE,EAAO,OAAA;AAAA,IACL,OAAO,MAAO,CAAA,MAAA,GAAS,MAAO,CAAA,CAAC,EAAE,EAAK,GAAA,IAAA;AAAA,IACtC,OAAS,EAAA,IAAA;AAAA,IACT,UAAU,QAAS,CAAA,IAAA;AAAA,IACnB,MAAQ,EAAA,IAAA;AAAA,GACV,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { DateTime, Duration as Duration$1 } from 'luxon';
|
|
2
|
+
import pluralize from 'pluralize';
|
|
3
|
+
import '../types/Alert.esm.js';
|
|
4
|
+
import { Duration } from '../types/Duration.esm.js';
|
|
5
|
+
import { inclusiveEndDateOf, inclusiveStartDateOf } from './duration.esm.js';
|
|
6
|
+
import { notEmpty } from './assert.esm.js';
|
|
7
|
+
|
|
8
|
+
const currencyFormatter = (currency) => {
|
|
9
|
+
const options = currency.resolvedOptions();
|
|
10
|
+
return new Intl.NumberFormat(options.locale, {
|
|
11
|
+
style: "currency",
|
|
12
|
+
currency: options.currency,
|
|
13
|
+
minimumFractionDigits: 0,
|
|
14
|
+
maximumFractionDigits: 0
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
const lengthyCurrencyFormatter = (currency) => {
|
|
18
|
+
const options = currency.resolvedOptions();
|
|
19
|
+
return new Intl.NumberFormat(options.locale, {
|
|
20
|
+
style: "currency",
|
|
21
|
+
currency: options.currency,
|
|
22
|
+
minimumFractionDigits: 0,
|
|
23
|
+
minimumSignificantDigits: 2,
|
|
24
|
+
maximumSignificantDigits: 2
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
const numberFormatter = new Intl.NumberFormat("en-US", {
|
|
28
|
+
minimumFractionDigits: 0,
|
|
29
|
+
maximumFractionDigits: 0
|
|
30
|
+
});
|
|
31
|
+
const monthFormatter = new Intl.DateTimeFormat("en-US", {
|
|
32
|
+
timeZone: "UTC",
|
|
33
|
+
month: "long",
|
|
34
|
+
year: "numeric"
|
|
35
|
+
});
|
|
36
|
+
const dateFormatter = new Intl.DateTimeFormat("en-US", {
|
|
37
|
+
timeZone: "UTC",
|
|
38
|
+
day: "numeric",
|
|
39
|
+
month: "short"
|
|
40
|
+
});
|
|
41
|
+
const monthOf = (date) => {
|
|
42
|
+
return monthFormatter.format(Date.parse(date));
|
|
43
|
+
};
|
|
44
|
+
const quarterOf = (date) => {
|
|
45
|
+
const d = DateTime.fromISO(date).isValid ? DateTime.fromISO(date) : DateTime.fromFormat(date, "yyyy-'Q'q");
|
|
46
|
+
return d.toFormat("'Q'q yyyy");
|
|
47
|
+
};
|
|
48
|
+
function formatCurrency(amount, currency) {
|
|
49
|
+
const n = Math.round(amount);
|
|
50
|
+
const numString = numberFormatter.format(n);
|
|
51
|
+
return currency ? `${numString} ${pluralize(currency, n)}` : numString;
|
|
52
|
+
}
|
|
53
|
+
function formatChange(change, options) {
|
|
54
|
+
if (notEmpty(change.ratio)) {
|
|
55
|
+
return formatPercent(
|
|
56
|
+
options?.absolute ? Math.abs(change.ratio) : change.ratio
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
if (options?.absolute) {
|
|
60
|
+
return "\u221E";
|
|
61
|
+
}
|
|
62
|
+
return change.amount >= 0 ? "\u221E" : "-\u221E";
|
|
63
|
+
}
|
|
64
|
+
function formatPercent(n) {
|
|
65
|
+
if (isNaN(n) || Math.abs(n) < 0.01) {
|
|
66
|
+
return "0%";
|
|
67
|
+
}
|
|
68
|
+
if (Math.abs(n) > 10) {
|
|
69
|
+
return `>${n < 0 ? "-" : ""}1000%`;
|
|
70
|
+
}
|
|
71
|
+
return `${(n * 100).toFixed(0)}%`;
|
|
72
|
+
}
|
|
73
|
+
function formatLastTwoLookaheadQuarters(inclusiveEndDate) {
|
|
74
|
+
const start = DateTime.fromISO(
|
|
75
|
+
inclusiveStartDateOf(Duration.P3M, inclusiveEndDate)
|
|
76
|
+
).toFormat("'Q'q yyyy");
|
|
77
|
+
const end = DateTime.fromISO(
|
|
78
|
+
inclusiveEndDateOf(Duration.P3M, inclusiveEndDate)
|
|
79
|
+
).toFormat("'Q'q yyyy");
|
|
80
|
+
return `${start} vs ${end}`;
|
|
81
|
+
}
|
|
82
|
+
const formatRelativePeriod = (duration, date, isEndDate) => {
|
|
83
|
+
const periodStart = isEndDate ? inclusiveStartDateOf(duration, date) : date;
|
|
84
|
+
const periodEnd = isEndDate ? date : inclusiveEndDateOf(duration, date);
|
|
85
|
+
const days = Duration$1.fromISO(duration).days;
|
|
86
|
+
if (![periodStart, periodEnd].includes(date)) {
|
|
87
|
+
throw new Error(`Invalid relative date ${date} for duration ${duration}`);
|
|
88
|
+
}
|
|
89
|
+
return date === periodStart ? `First ${days} Days` : `Last ${days} Days`;
|
|
90
|
+
};
|
|
91
|
+
function formatPeriod(duration, date, isEndDate) {
|
|
92
|
+
switch (duration) {
|
|
93
|
+
case Duration.P3M:
|
|
94
|
+
return quarterOf(
|
|
95
|
+
isEndDate ? inclusiveEndDateOf(duration, date) : inclusiveStartDateOf(duration, date)
|
|
96
|
+
);
|
|
97
|
+
default:
|
|
98
|
+
return formatRelativePeriod(duration, date, isEndDate);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export { currencyFormatter, dateFormatter, formatChange, formatCurrency, formatLastTwoLookaheadQuarters, formatPercent, formatPeriod, lengthyCurrencyFormatter, monthFormatter, monthOf, numberFormatter, quarterOf };
|
|
103
|
+
//# sourceMappingURL=formatters.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.esm.js","sources":["../../src/utils/formatters.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DateTime, Duration as LuxonDuration } from 'luxon';\nimport pluralize from 'pluralize';\nimport { Duration } from '../types';\nimport { ChangeStatistic } from '@backstage-community/plugin-cost-insights-common';\nimport { inclusiveEndDateOf, inclusiveStartDateOf } from './duration';\nimport { notEmpty } from './assert';\n\nexport type Period = {\n periodStart: string;\n periodEnd: string;\n};\n\nexport const currencyFormatter = (currency: Intl.NumberFormat) => {\n const options = currency.resolvedOptions();\n\n return new Intl.NumberFormat(options.locale, {\n style: 'currency',\n currency: options.currency,\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n });\n};\n\nexport const lengthyCurrencyFormatter = (currency: Intl.NumberFormat) => {\n const options = currency.resolvedOptions();\n\n return new Intl.NumberFormat(options.locale, {\n style: 'currency',\n currency: options.currency,\n minimumFractionDigits: 0,\n minimumSignificantDigits: 2,\n maximumSignificantDigits: 2,\n });\n};\n\nexport const numberFormatter = new Intl.NumberFormat('en-US', {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n});\n\nexport const monthFormatter = new Intl.DateTimeFormat('en-US', {\n timeZone: 'UTC',\n month: 'long',\n year: 'numeric',\n});\n\nexport const dateFormatter = new Intl.DateTimeFormat('en-US', {\n timeZone: 'UTC',\n day: 'numeric',\n month: 'short',\n});\n\nexport const monthOf = (date: string): string => {\n return monthFormatter.format(Date.parse(date));\n};\n\nexport const quarterOf = (date: string): string => {\n // Supports formatting yyyy-LL-dd and yyyy-'Q'q returned in alerts\n const d = DateTime.fromISO(date).isValid\n ? DateTime.fromISO(date)\n : DateTime.fromFormat(date, \"yyyy-'Q'q\");\n return d.toFormat(\"'Q'q yyyy\");\n};\n\nexport function formatCurrency(amount: number, currency?: string): string {\n const n = Math.round(amount);\n const numString = numberFormatter.format(n);\n\n return currency ? `${numString} ${pluralize(currency, n)}` : numString;\n}\n\nexport function formatChange(\n change: ChangeStatistic,\n options?: { absolute: boolean },\n): string {\n if (notEmpty(change.ratio)) {\n return formatPercent(\n options?.absolute ? Math.abs(change.ratio) : change.ratio,\n );\n }\n if (options?.absolute) {\n return '∞';\n }\n return change.amount >= 0 ? '∞' : '-∞';\n}\n\nexport function formatPercent(n: number): string {\n // Number.toFixed shows scientific notation for extreme numbers\n if (isNaN(n) || Math.abs(n) < 0.01) {\n return '0%';\n }\n\n if (Math.abs(n) > 10) {\n return `>${n < 0 ? '-' : ''}1000%`;\n }\n\n return `${(n * 100).toFixed(0)}%`;\n}\n\nexport function formatLastTwoLookaheadQuarters(inclusiveEndDate: string) {\n const start = DateTime.fromISO(\n inclusiveStartDateOf(Duration.P3M, inclusiveEndDate),\n ).toFormat(\"'Q'q yyyy\");\n const end = DateTime.fromISO(\n inclusiveEndDateOf(Duration.P3M, inclusiveEndDate),\n ).toFormat(\"'Q'q yyyy\");\n return `${start} vs ${end}`;\n}\n\nconst formatRelativePeriod = (\n duration: Duration,\n date: string,\n isEndDate: boolean,\n): string => {\n const periodStart = isEndDate ? inclusiveStartDateOf(duration, date) : date;\n const periodEnd = isEndDate ? date : inclusiveEndDateOf(duration, date);\n const days = LuxonDuration.fromISO(duration).days;\n if (![periodStart, periodEnd].includes(date)) {\n throw new Error(`Invalid relative date ${date} for duration ${duration}`);\n }\n return date === periodStart ? `First ${days} Days` : `Last ${days} Days`;\n};\n\nexport function formatPeriod(\n duration: Duration,\n date: string,\n isEndDate: boolean,\n) {\n switch (duration) {\n case Duration.P3M:\n return quarterOf(\n isEndDate\n ? inclusiveEndDateOf(duration, date)\n : inclusiveStartDateOf(duration, date),\n );\n default:\n return formatRelativePeriod(duration, date, isEndDate);\n }\n}\n"],"names":["LuxonDuration"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const vowels = {
|
|
2
|
+
a: "A",
|
|
3
|
+
e: "E",
|
|
4
|
+
i: "I",
|
|
5
|
+
o: "O",
|
|
6
|
+
u: "U"
|
|
7
|
+
};
|
|
8
|
+
const indefiniteArticleOf = (articles, word) => {
|
|
9
|
+
const firstChar = word.charAt(0).toLocaleLowerCase("en-US");
|
|
10
|
+
return firstChar in vowels ? `${articles[1]} ${word}` : `${articles[0]} ${word}`;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export { indefiniteArticleOf };
|
|
14
|
+
//# sourceMappingURL=grammar.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grammar.esm.js","sources":["../../src/utils/grammar.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst vowels = {\n a: 'A',\n e: 'E',\n i: 'I',\n o: 'O',\n u: 'U',\n};\n\nexport const indefiniteArticleOf = (\n articles: [string, string],\n word: string,\n) => {\n const firstChar = word.charAt(0).toLocaleLowerCase('en-US');\n return firstChar in vowels\n ? `${articles[1]} ${word}`\n : `${articles[0]} ${word}`;\n};\n"],"names":[],"mappings":"AAgBA,MAAM,MAAS,GAAA;AAAA,EACb,CAAG,EAAA,GAAA;AAAA,EACH,CAAG,EAAA,GAAA;AAAA,EACH,CAAG,EAAA,GAAA;AAAA,EACH,CAAG,EAAA,GAAA;AAAA,EACH,CAAG,EAAA,GAAA;AACL,CAAA,CAAA;AAEa,MAAA,mBAAA,GAAsB,CACjC,QAAA,EACA,IACG,KAAA;AACH,EAAA,MAAM,YAAY,IAAK,CAAA,MAAA,CAAO,CAAC,CAAA,CAAE,kBAAkB,OAAO,CAAA,CAAA;AAC1D,EAAA,OAAO,SAAa,IAAA,MAAA,GAChB,CAAG,EAAA,QAAA,CAAS,CAAC,CAAC,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,GACtB,CAAG,EAAA,QAAA,CAAS,CAAC,CAAC,IAAI,IAAI,CAAA,CAAA,CAAA;AAC5B;;;;"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { DataKey } from '../types/Alert.esm.js';
|
|
2
|
+
import { lengthyCurrencyFormatter, currencyFormatter, dateFormatter } from './formatters.esm.js';
|
|
3
|
+
|
|
4
|
+
const formatGraphValue = (baseCurrency) => (value, _index, format) => {
|
|
5
|
+
if (format === "number") {
|
|
6
|
+
return value.toLocaleString();
|
|
7
|
+
}
|
|
8
|
+
if (value < 1) {
|
|
9
|
+
return lengthyCurrencyFormatter(baseCurrency).format(value);
|
|
10
|
+
}
|
|
11
|
+
return currencyFormatter(baseCurrency).format(value);
|
|
12
|
+
};
|
|
13
|
+
const overviewGraphTickFormatter = (millis) => typeof millis === "number" ? dateFormatter.format(millis) : millis;
|
|
14
|
+
const tooltipItemOf = (baseCurrency) => (payload) => {
|
|
15
|
+
const value = payload.value && !isNaN(Number(payload.value)) ? baseCurrency.format(Number(payload.value)) : payload.value;
|
|
16
|
+
const fill = payload.color;
|
|
17
|
+
switch (payload.dataKey) {
|
|
18
|
+
case DataKey.Current:
|
|
19
|
+
case DataKey.Previous:
|
|
20
|
+
return {
|
|
21
|
+
label: payload.name,
|
|
22
|
+
value,
|
|
23
|
+
fill
|
|
24
|
+
};
|
|
25
|
+
default:
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const resourceOf = (entity) => ({
|
|
30
|
+
name: entity.id,
|
|
31
|
+
previous: entity.aggregation[0],
|
|
32
|
+
current: entity.aggregation[1]
|
|
33
|
+
});
|
|
34
|
+
const titleOf = (label) => {
|
|
35
|
+
return label ? String(label) : "Unlabeled";
|
|
36
|
+
};
|
|
37
|
+
const isInvalid = ({ label, payload }) => {
|
|
38
|
+
return label === void 0 || !payload || !payload.length;
|
|
39
|
+
};
|
|
40
|
+
const isLabeled = (data) => {
|
|
41
|
+
return data?.activeLabel && data?.activeLabel !== "";
|
|
42
|
+
};
|
|
43
|
+
const isUnlabeled = (data) => {
|
|
44
|
+
return data?.activeLabel === "";
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export { formatGraphValue, isInvalid, isLabeled, isUnlabeled, overviewGraphTickFormatter, resourceOf, titleOf, tooltipItemOf };
|
|
48
|
+
//# sourceMappingURL=graphs.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphs.esm.js","sources":["../../src/utils/graphs.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { TooltipProps } from 'recharts';\nimport { Payload } from 'recharts/types/component/DefaultTooltipContent';\nimport { AlertCost, DataKey, ResourceData } from '../types';\nimport { Entity } from '@backstage-community/plugin-cost-insights-common';\nimport {\n currencyFormatter,\n dateFormatter,\n lengthyCurrencyFormatter,\n} from './formatters';\n\nexport const formatGraphValue =\n (baseCurrency: Intl.NumberFormat) =>\n (value: number, _index: number, format?: string) => {\n if (format === 'number') {\n return value.toLocaleString();\n }\n\n if (value < 1) {\n return lengthyCurrencyFormatter(baseCurrency).format(value);\n }\n\n return currencyFormatter(baseCurrency).format(value);\n };\n\nexport const overviewGraphTickFormatter = (millis: string | number) =>\n typeof millis === 'number' ? dateFormatter.format(millis) : millis;\n\nexport const tooltipItemOf =\n (baseCurrency: Intl.NumberFormat) => (payload: Payload<string, string>) => {\n const value =\n payload.value && !isNaN(Number(payload.value))\n ? baseCurrency.format(Number(payload.value))\n : payload.value;\n const fill = payload.color as string;\n\n switch (payload.dataKey) {\n case DataKey.Current:\n case DataKey.Previous:\n return {\n label: payload.name,\n value: value,\n fill: fill,\n };\n default:\n return null;\n }\n };\n\nexport const resourceOf = (entity: Entity | AlertCost): ResourceData => ({\n name: entity.id,\n previous: entity.aggregation[0],\n current: entity.aggregation[1],\n});\n\nexport const titleOf = (label?: string | number) => {\n return label ? String(label) : 'Unlabeled';\n};\n\nexport const isInvalid = ({ label, payload }: TooltipProps<string, string>) => {\n // null labels are empty strings, which are valid\n return label === undefined || !payload || !payload.length;\n};\n\nexport const isLabeled = (data?: Record<'activeLabel', string | undefined>) => {\n return data?.activeLabel && data?.activeLabel !== '';\n};\n\nexport const isUnlabeled = (\n data?: Record<'activeLabel', string | undefined>,\n) => {\n return data?.activeLabel === '';\n};\n"],"names":[],"mappings":";;;AA0BO,MAAM,mBACX,CAAC,YAAA,KACD,CAAC,KAAA,EAAe,QAAgB,MAAoB,KAAA;AAClD,EAAA,IAAI,WAAW,QAAU,EAAA;AACvB,IAAA,OAAO,MAAM,cAAe,EAAA,CAAA;AAAA,GAC9B;AAEA,EAAA,IAAI,QAAQ,CAAG,EAAA;AACb,IAAA,OAAO,wBAAyB,CAAA,YAAY,CAAE,CAAA,MAAA,CAAO,KAAK,CAAA,CAAA;AAAA,GAC5D;AAEA,EAAA,OAAO,iBAAkB,CAAA,YAAY,CAAE,CAAA,MAAA,CAAO,KAAK,CAAA,CAAA;AACrD,EAAA;AAEW,MAAA,0BAAA,GAA6B,CAAC,MACzC,KAAA,OAAO,WAAW,QAAW,GAAA,aAAA,CAAc,MAAO,CAAA,MAAM,CAAI,GAAA,OAAA;AAEvD,MAAM,aACX,GAAA,CAAC,YAAoC,KAAA,CAAC,OAAqC,KAAA;AACzE,EAAA,MAAM,QACJ,OAAQ,CAAA,KAAA,IAAS,CAAC,KAAA,CAAM,OAAO,OAAQ,CAAA,KAAK,CAAC,CAAA,GACzC,aAAa,MAAO,CAAA,MAAA,CAAO,QAAQ,KAAK,CAAC,IACzC,OAAQ,CAAA,KAAA,CAAA;AACd,EAAA,MAAM,OAAO,OAAQ,CAAA,KAAA,CAAA;AAErB,EAAA,QAAQ,QAAQ,OAAS;AAAA,IACvB,KAAK,OAAQ,CAAA,OAAA,CAAA;AAAA,IACb,KAAK,OAAQ,CAAA,QAAA;AACX,MAAO,OAAA;AAAA,QACL,OAAO,OAAQ,CAAA,IAAA;AAAA,QACf,KAAA;AAAA,QACA,IAAA;AAAA,OACF,CAAA;AAAA,IACF;AACE,MAAO,OAAA,IAAA,CAAA;AAAA,GACX;AACF,EAAA;AAEW,MAAA,UAAA,GAAa,CAAC,MAA8C,MAAA;AAAA,EACvE,MAAM,MAAO,CAAA,EAAA;AAAA,EACb,QAAA,EAAU,MAAO,CAAA,WAAA,CAAY,CAAC,CAAA;AAAA,EAC9B,OAAA,EAAS,MAAO,CAAA,WAAA,CAAY,CAAC,CAAA;AAC/B,CAAA,EAAA;AAEa,MAAA,OAAA,GAAU,CAAC,KAA4B,KAAA;AAClD,EAAO,OAAA,KAAA,GAAQ,MAAO,CAAA,KAAK,CAAI,GAAA,WAAA,CAAA;AACjC,EAAA;AAEO,MAAM,SAAY,GAAA,CAAC,EAAE,KAAA,EAAO,SAA4C,KAAA;AAE7E,EAAA,OAAO,KAAU,KAAA,KAAA,CAAA,IAAa,CAAC,OAAA,IAAW,CAAC,OAAQ,CAAA,MAAA,CAAA;AACrD,EAAA;AAEa,MAAA,SAAA,GAAY,CAAC,IAAqD,KAAA;AAC7E,EAAO,OAAA,IAAA,EAAM,WAAe,IAAA,IAAA,EAAM,WAAgB,KAAA,EAAA,CAAA;AACpD,EAAA;AAEa,MAAA,WAAA,GAAc,CACzB,IACG,KAAA;AACH,EAAA,OAAO,MAAM,WAAgB,KAAA,EAAA,CAAA;AAC/B;;;;"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import qs from 'qs';
|
|
2
|
+
import * as yup from 'yup';
|
|
3
|
+
import '../types/Alert.esm.js';
|
|
4
|
+
import { Duration } from '../types/Duration.esm.js';
|
|
5
|
+
import { getDefaultPageFilters } from './filters.esm.js';
|
|
6
|
+
|
|
7
|
+
const schema = yup.object().shape({
|
|
8
|
+
group: yup.string().nullable(),
|
|
9
|
+
project: yup.string().nullable()
|
|
10
|
+
}).required();
|
|
11
|
+
const stringify = (queryParams) => qs.stringify(queryParams, { strictNullHandling: true });
|
|
12
|
+
const parse = (queryString) => qs.parse(queryString, { ignoreQueryPrefix: true, strictNullHandling: true });
|
|
13
|
+
const validate = (queryString) => {
|
|
14
|
+
return schema.validate(parse(queryString), {
|
|
15
|
+
stripUnknown: true,
|
|
16
|
+
strict: true
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
const getInitialPageState = (groups, queryParams = {}) => {
|
|
20
|
+
return {
|
|
21
|
+
...getDefaultPageFilters(groups),
|
|
22
|
+
...queryParams.project ? { project: queryParams.project } : {},
|
|
23
|
+
...queryParams.group ? { group: queryParams.group } : {}
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
const getInitialProductState = (config) => config.products.map((product) => ({
|
|
27
|
+
productType: product.kind,
|
|
28
|
+
duration: Duration.P30D
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
export { getInitialPageState, getInitialProductState, parse, stringify, validate };
|
|
32
|
+
//# sourceMappingURL=history.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.esm.js","sources":["../../src/utils/history.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport qs from 'qs';\nimport * as yup from 'yup';\nimport { Duration, PageFilters } from '../types';\nimport { Group } from '@backstage-community/plugin-cost-insights-common';\nimport { getDefaultPageFilters } from '../utils/filters';\nimport { ConfigContextProps } from '../hooks/useConfig';\n\nconst schema = yup\n .object()\n .shape({\n group: yup.string().nullable(),\n project: yup.string().nullable(),\n })\n .required();\n\nexport const stringify = (queryParams: Partial<PageFilters>) =>\n qs.stringify(queryParams, { strictNullHandling: true });\n\nexport const parse = (queryString: string): Partial<PageFilters> =>\n qs.parse(queryString, { ignoreQueryPrefix: true, strictNullHandling: true });\n\nexport const validate = (queryString: string): Promise<PageFilters> => {\n return schema.validate(parse(queryString), {\n stripUnknown: true,\n strict: true,\n }) as Promise<PageFilters>;\n};\n\nexport const getInitialPageState = (\n groups: Group[],\n queryParams: Partial<PageFilters> = {},\n) => {\n return {\n ...getDefaultPageFilters(groups),\n ...(queryParams.project ? { project: queryParams.project } : {}),\n ...(queryParams.group ? { group: queryParams.group } : {}),\n };\n};\n\nexport const getInitialProductState = (config: ConfigContextProps) =>\n config.products.map(product => ({\n productType: product.kind,\n duration: Duration.P30D,\n }));\n"],"names":[],"mappings":";;;;;;AAuBA,MAAM,MAAS,GAAA,GAAA,CACZ,MAAO,EAAA,CACP,KAAM,CAAA;AAAA,EACL,KAAO,EAAA,GAAA,CAAI,MAAO,EAAA,CAAE,QAAS,EAAA;AAAA,EAC7B,OAAS,EAAA,GAAA,CAAI,MAAO,EAAA,CAAE,QAAS,EAAA;AACjC,CAAC,EACA,QAAS,EAAA,CAAA;AAEC,MAAA,SAAA,GAAY,CAAC,WACxB,KAAA,EAAA,CAAG,UAAU,WAAa,EAAA,EAAE,kBAAoB,EAAA,IAAA,EAAM,EAAA;AAE3C,MAAA,KAAA,GAAQ,CAAC,WAAA,KACpB,EAAG,CAAA,KAAA,CAAM,WAAa,EAAA,EAAE,iBAAmB,EAAA,IAAA,EAAM,kBAAoB,EAAA,IAAA,EAAM,EAAA;AAEhE,MAAA,QAAA,GAAW,CAAC,WAA8C,KAAA;AACrE,EAAA,OAAO,MAAO,CAAA,QAAA,CAAS,KAAM,CAAA,WAAW,CAAG,EAAA;AAAA,IACzC,YAAc,EAAA,IAAA;AAAA,IACd,MAAQ,EAAA,IAAA;AAAA,GACT,CAAA,CAAA;AACH,EAAA;AAEO,MAAM,mBAAsB,GAAA,CACjC,MACA,EAAA,WAAA,GAAoC,EACjC,KAAA;AACH,EAAO,OAAA;AAAA,IACL,GAAG,sBAAsB,MAAM,CAAA;AAAA,IAC/B,GAAI,YAAY,OAAU,GAAA,EAAE,SAAS,WAAY,CAAA,OAAA,KAAY,EAAC;AAAA,IAC9D,GAAI,YAAY,KAAQ,GAAA,EAAE,OAAO,WAAY,CAAA,KAAA,KAAU,EAAC;AAAA,GAC1D,CAAA;AACF,EAAA;AAEO,MAAM,yBAAyB,CAAC,MAAA,KACrC,MAAO,CAAA,QAAA,CAAS,IAAI,CAAY,OAAA,MAAA;AAAA,EAC9B,aAAa,OAAQ,CAAA,IAAA;AAAA,EACrB,UAAU,QAAS,CAAA,IAAA;AACrB,CAAE,CAAA;;;;"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { DEFAULT_DURATION } from './duration.esm.js';
|
|
2
|
+
|
|
3
|
+
var DefaultLoadingAction = /* @__PURE__ */ ((DefaultLoadingAction2) => {
|
|
4
|
+
DefaultLoadingAction2["UserGroups"] = "user-groups";
|
|
5
|
+
DefaultLoadingAction2["LastCompleteBillingDate"] = "billing-date";
|
|
6
|
+
DefaultLoadingAction2["CostInsightsInitial"] = "cost-insights-initial";
|
|
7
|
+
DefaultLoadingAction2["CostInsightsPage"] = "cost-insights-page";
|
|
8
|
+
DefaultLoadingAction2["CostInsightsProducts"] = "cost-insights-products";
|
|
9
|
+
DefaultLoadingAction2["CostInsightsAlerts"] = "cost-insights-alerts";
|
|
10
|
+
return DefaultLoadingAction2;
|
|
11
|
+
})(DefaultLoadingAction || {});
|
|
12
|
+
const INITIAL_LOADING_ACTIONS = [
|
|
13
|
+
"user-groups" /* UserGroups */,
|
|
14
|
+
"cost-insights-initial" /* CostInsightsInitial */,
|
|
15
|
+
"cost-insights-products" /* CostInsightsProducts */
|
|
16
|
+
];
|
|
17
|
+
const getDefaultState = (loadingActions) => {
|
|
18
|
+
return loadingActions.reduce(
|
|
19
|
+
(defaultState, action) => ({ ...defaultState, [action]: true }),
|
|
20
|
+
{}
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
const getResetState = (loadingActions) => {
|
|
24
|
+
return loadingActions.reduce(
|
|
25
|
+
(defaultState, action) => ({ ...defaultState, [action]: false }),
|
|
26
|
+
{}
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
const getResetStateWithoutInitial = (loadingActions) => {
|
|
30
|
+
return loadingActions.reduce((defaultState, action) => {
|
|
31
|
+
const loadingActionState = INITIAL_LOADING_ACTIONS.includes(
|
|
32
|
+
action
|
|
33
|
+
) ? false : true;
|
|
34
|
+
return { ...defaultState, [action]: loadingActionState };
|
|
35
|
+
}, {});
|
|
36
|
+
};
|
|
37
|
+
const settledResponseOf = (responses) => {
|
|
38
|
+
return responses.map(
|
|
39
|
+
(response) => response.status === "fulfilled" ? response.value : null
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
const initialStatesOf = (products, responses) => {
|
|
43
|
+
return products.map((product, index) => ({
|
|
44
|
+
entity: responses[index],
|
|
45
|
+
product,
|
|
46
|
+
duration: DEFAULT_DURATION
|
|
47
|
+
}));
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export { DefaultLoadingAction, INITIAL_LOADING_ACTIONS, getDefaultState, getResetState, getResetStateWithoutInitial, initialStatesOf, settledResponseOf };
|
|
51
|
+
//# sourceMappingURL=loading.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loading.esm.js","sources":["../../src/utils/loading.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Duration, Loading } from '../types';\nimport {\n Entity,\n Maybe,\n Product,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { DEFAULT_DURATION } from './duration';\n\nexport type ProductState = {\n product: Product;\n entity: Maybe<Entity>;\n duration: Duration;\n};\n\nexport enum DefaultLoadingAction {\n UserGroups = 'user-groups',\n LastCompleteBillingDate = 'billing-date',\n CostInsightsInitial = 'cost-insights-initial',\n CostInsightsPage = 'cost-insights-page',\n CostInsightsProducts = 'cost-insights-products',\n CostInsightsAlerts = 'cost-insights-alerts',\n}\n\nexport const INITIAL_LOADING_ACTIONS = [\n DefaultLoadingAction.UserGroups,\n DefaultLoadingAction.CostInsightsInitial,\n DefaultLoadingAction.CostInsightsProducts,\n];\n\nexport const getDefaultState = (loadingActions: string[]): Loading => {\n return loadingActions.reduce(\n (defaultState, action) => ({ ...defaultState, [action]: true }),\n {},\n );\n};\n\nexport const getResetState = (loadingActions: string[]): Loading => {\n return loadingActions.reduce(\n (defaultState, action) => ({ ...defaultState, [action]: false }),\n {},\n );\n};\n\nexport const getResetStateWithoutInitial = (\n loadingActions: string[],\n): Loading => {\n return loadingActions.reduce((defaultState, action) => {\n const loadingActionState = (INITIAL_LOADING_ACTIONS as string[]).includes(\n action,\n )\n ? false\n : true;\n return { ...defaultState, [action]: loadingActionState };\n }, {});\n};\n\nexport const settledResponseOf = (\n responses: PromiseSettledResult<Entity | any>[],\n): Array<Maybe<Entity>> => {\n return responses.map(response =>\n response.status === 'fulfilled' ? response.value : null,\n );\n};\n\nexport const initialStatesOf = (\n products: Product[],\n responses: Array<Maybe<Entity>>,\n): ProductState[] => {\n return products.map((product, index) => ({\n entity: responses[index],\n product: product,\n duration: DEFAULT_DURATION,\n }));\n};\n"],"names":["DefaultLoadingAction"],"mappings":";;AA8BY,IAAA,oBAAA,qBAAAA,qBAAL,KAAA;AACL,EAAAA,sBAAA,YAAa,CAAA,GAAA,aAAA,CAAA;AACb,EAAAA,sBAAA,yBAA0B,CAAA,GAAA,cAAA,CAAA;AAC1B,EAAAA,sBAAA,qBAAsB,CAAA,GAAA,uBAAA,CAAA;AACtB,EAAAA,sBAAA,kBAAmB,CAAA,GAAA,oBAAA,CAAA;AACnB,EAAAA,sBAAA,sBAAuB,CAAA,GAAA,wBAAA,CAAA;AACvB,EAAAA,sBAAA,oBAAqB,CAAA,GAAA,sBAAA,CAAA;AANX,EAAAA,OAAAA,qBAAAA,CAAAA;AAAA,CAAA,EAAA,oBAAA,IAAA,EAAA,EAAA;AASL,MAAM,uBAA0B,GAAA;AAAA,EACrC,aAAA;AAAA,EACA,uBAAA;AAAA,EACA,wBAAA;AACF,EAAA;AAEa,MAAA,eAAA,GAAkB,CAAC,cAAsC,KAAA;AACpE,EAAA,OAAO,cAAe,CAAA,MAAA;AAAA,IACpB,CAAC,cAAc,MAAY,MAAA,EAAE,GAAG,YAAc,EAAA,CAAC,MAAM,GAAG,IAAK,EAAA,CAAA;AAAA,IAC7D,EAAC;AAAA,GACH,CAAA;AACF,EAAA;AAEa,MAAA,aAAA,GAAgB,CAAC,cAAsC,KAAA;AAClE,EAAA,OAAO,cAAe,CAAA,MAAA;AAAA,IACpB,CAAC,cAAc,MAAY,MAAA,EAAE,GAAG,YAAc,EAAA,CAAC,MAAM,GAAG,KAAM,EAAA,CAAA;AAAA,IAC9D,EAAC;AAAA,GACH,CAAA;AACF,EAAA;AAEa,MAAA,2BAAA,GAA8B,CACzC,cACY,KAAA;AACZ,EAAA,OAAO,cAAe,CAAA,MAAA,CAAO,CAAC,YAAA,EAAc,MAAW,KAAA;AACrD,IAAA,MAAM,qBAAsB,uBAAqC,CAAA,QAAA;AAAA,MAC/D,MAAA;AAAA,QAEE,KACA,GAAA,IAAA,CAAA;AACJ,IAAA,OAAO,EAAE,GAAG,YAAA,EAAc,CAAC,MAAM,GAAG,kBAAmB,EAAA,CAAA;AAAA,GACzD,EAAG,EAAE,CAAA,CAAA;AACP,EAAA;AAEa,MAAA,iBAAA,GAAoB,CAC/B,SACyB,KAAA;AACzB,EAAA,OAAO,SAAU,CAAA,GAAA;AAAA,IAAI,CACnB,QAAA,KAAA,QAAA,CAAS,MAAW,KAAA,WAAA,GAAc,SAAS,KAAQ,GAAA,IAAA;AAAA,GACrD,CAAA;AACF,EAAA;AAEa,MAAA,eAAA,GAAkB,CAC7B,QAAA,EACA,SACmB,KAAA;AACnB,EAAA,OAAO,QAAS,CAAA,GAAA,CAAI,CAAC,OAAA,EAAS,KAAW,MAAA;AAAA,IACvC,MAAA,EAAQ,UAAU,KAAK,CAAA;AAAA,IACvB,OAAA;AAAA,IACA,QAAU,EAAA,gBAAA;AAAA,GACV,CAAA,CAAA,CAAA;AACJ;;;;"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import MoneyIcon from '@material-ui/icons/MonetizationOn';
|
|
3
|
+
import ActionIcon from '@material-ui/icons/Whatshot';
|
|
4
|
+
import Settings from '@material-ui/icons/Settings';
|
|
5
|
+
import AccountTree from '@material-ui/icons/AccountTree';
|
|
6
|
+
import Storage from '@material-ui/icons/Storage';
|
|
7
|
+
import Search from '@material-ui/icons/Search';
|
|
8
|
+
import CloudQueue from '@material-ui/icons/CloudQueue';
|
|
9
|
+
import School from '@material-ui/icons/School';
|
|
10
|
+
import ViewHeadline from '@material-ui/icons/ViewHeadline';
|
|
11
|
+
import '../types/Alert.esm.js';
|
|
12
|
+
import { IconType } from '../types/Icon.esm.js';
|
|
13
|
+
|
|
14
|
+
var DefaultNavigation = /* @__PURE__ */ ((DefaultNavigation2) => {
|
|
15
|
+
DefaultNavigation2["CostOverviewCard"] = "cost-overview-card";
|
|
16
|
+
DefaultNavigation2["AlertInsightsHeader"] = "alert-insights-header";
|
|
17
|
+
return DefaultNavigation2;
|
|
18
|
+
})(DefaultNavigation || {});
|
|
19
|
+
const getDefaultNavigationItems = (alerts) => {
|
|
20
|
+
const items = [
|
|
21
|
+
{
|
|
22
|
+
navigation: "cost-overview-card" /* CostOverviewCard */,
|
|
23
|
+
icon: /* @__PURE__ */ React.createElement(MoneyIcon, null),
|
|
24
|
+
title: "Cost Overview"
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
if (alerts > 0) {
|
|
28
|
+
items.push({
|
|
29
|
+
navigation: "alert-insights-header" /* AlertInsightsHeader */,
|
|
30
|
+
icon: /* @__PURE__ */ React.createElement(ActionIcon, null),
|
|
31
|
+
title: "Action Items"
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return items;
|
|
35
|
+
};
|
|
36
|
+
function getIcon(icon) {
|
|
37
|
+
switch (icon) {
|
|
38
|
+
case IconType.Compute:
|
|
39
|
+
return /* @__PURE__ */ React.createElement(Settings, null);
|
|
40
|
+
case IconType.Data:
|
|
41
|
+
return /* @__PURE__ */ React.createElement(AccountTree, null);
|
|
42
|
+
case IconType.Database:
|
|
43
|
+
return /* @__PURE__ */ React.createElement(ViewHeadline, null);
|
|
44
|
+
case IconType.Storage:
|
|
45
|
+
return /* @__PURE__ */ React.createElement(Storage, null);
|
|
46
|
+
case IconType.Search:
|
|
47
|
+
return /* @__PURE__ */ React.createElement(Search, null);
|
|
48
|
+
case IconType.ML:
|
|
49
|
+
return /* @__PURE__ */ React.createElement(School, null);
|
|
50
|
+
default:
|
|
51
|
+
return /* @__PURE__ */ React.createElement(CloudQueue, null);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { DefaultNavigation, getDefaultNavigationItems, getIcon };
|
|
56
|
+
//# sourceMappingURL=navigation.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.esm.js","sources":["../../src/utils/navigation.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 MoneyIcon from '@material-ui/icons/MonetizationOn';\nimport ActionIcon from '@material-ui/icons/Whatshot';\nimport Settings from '@material-ui/icons/Settings';\nimport AccountTree from '@material-ui/icons/AccountTree';\nimport Storage from '@material-ui/icons/Storage';\nimport Search from '@material-ui/icons/Search';\nimport CloudQueue from '@material-ui/icons/CloudQueue';\nimport School from '@material-ui/icons/School';\nimport ViewHeadline from '@material-ui/icons/ViewHeadline';\nimport { IconType } from '../types';\n\nexport enum DefaultNavigation {\n CostOverviewCard = 'cost-overview-card',\n AlertInsightsHeader = 'alert-insights-header',\n}\n\nexport type NavigationItem = {\n navigation: string;\n icon: JSX.Element;\n title: string;\n};\n\nexport const getDefaultNavigationItems = (alerts: number): NavigationItem[] => {\n const items = [\n {\n navigation: DefaultNavigation.CostOverviewCard,\n icon: <MoneyIcon />,\n title: 'Cost Overview',\n },\n ];\n if (alerts > 0) {\n items.push({\n navigation: DefaultNavigation.AlertInsightsHeader,\n icon: <ActionIcon />,\n title: 'Action Items',\n });\n }\n return items;\n};\n\nexport function getIcon(icon?: string): JSX.Element {\n switch (icon) {\n case IconType.Compute:\n return <Settings />;\n case IconType.Data:\n return <AccountTree />;\n case IconType.Database:\n return <ViewHeadline />;\n case IconType.Storage:\n return <Storage />;\n case IconType.Search:\n return <Search />;\n case IconType.ML:\n return <School />;\n default:\n return <CloudQueue />;\n }\n}\n"],"names":["DefaultNavigation"],"mappings":";;;;;;;;;;;;;AA2BY,IAAA,iBAAA,qBAAAA,kBAAL,KAAA;AACL,EAAAA,mBAAA,kBAAmB,CAAA,GAAA,oBAAA,CAAA;AACnB,EAAAA,mBAAA,qBAAsB,CAAA,GAAA,uBAAA,CAAA;AAFZ,EAAAA,OAAAA,kBAAAA,CAAAA;AAAA,CAAA,EAAA,iBAAA,IAAA,EAAA,EAAA;AAWC,MAAA,yBAAA,GAA4B,CAAC,MAAqC,KAAA;AAC7E,EAAA,MAAM,KAAQ,GAAA;AAAA,IACZ;AAAA,MACE,UAAY,EAAA,oBAAA;AAAA,MACZ,IAAA,sCAAO,SAAU,EAAA,IAAA,CAAA;AAAA,MACjB,KAAO,EAAA,eAAA;AAAA,KACT;AAAA,GACF,CAAA;AACA,EAAA,IAAI,SAAS,CAAG,EAAA;AACd,IAAA,KAAA,CAAM,IAAK,CAAA;AAAA,MACT,UAAY,EAAA,uBAAA;AAAA,MACZ,IAAA,sCAAO,UAAW,EAAA,IAAA,CAAA;AAAA,MAClB,KAAO,EAAA,cAAA;AAAA,KACR,CAAA,CAAA;AAAA,GACH;AACA,EAAO,OAAA,KAAA,CAAA;AACT,EAAA;AAEO,SAAS,QAAQ,IAA4B,EAAA;AAClD,EAAA,QAAQ,IAAM;AAAA,IACZ,KAAK,QAAS,CAAA,OAAA;AACZ,MAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA,CAAA;AAAA,IACnB,KAAK,QAAS,CAAA,IAAA;AACZ,MAAA,2CAAQ,WAAY,EAAA,IAAA,CAAA,CAAA;AAAA,IACtB,KAAK,QAAS,CAAA,QAAA;AACZ,MAAA,2CAAQ,YAAa,EAAA,IAAA,CAAA,CAAA;AAAA,IACvB,KAAK,QAAS,CAAA,OAAA;AACZ,MAAA,2CAAQ,OAAQ,EAAA,IAAA,CAAA,CAAA;AAAA,IAClB,KAAK,QAAS,CAAA,MAAA;AACZ,MAAA,2CAAQ,MAAO,EAAA,IAAA,CAAA,CAAA;AAAA,IACjB,KAAK,QAAS,CAAA,EAAA;AACZ,MAAA,2CAAQ,MAAO,EAAA,IAAA,CAAA,CAAA;AAAA,IACjB;AACE,MAAA,2CAAQ,UAAW,EAAA,IAAA,CAAA,CAAA;AAAA,GACvB;AACF;;;;"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React, { useRef, useEffect } from 'react';
|
|
2
|
+
import { useScroll } from '../hooks/useScroll.esm.js';
|
|
3
|
+
|
|
4
|
+
const ScrollAnchor = ({
|
|
5
|
+
id,
|
|
6
|
+
left = 0,
|
|
7
|
+
top = -20,
|
|
8
|
+
block = "start",
|
|
9
|
+
inline = "nearest",
|
|
10
|
+
behavior = "smooth"
|
|
11
|
+
}) => {
|
|
12
|
+
const divRef = useRef(null);
|
|
13
|
+
const [scroll, setScroll] = useScroll();
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
function scrollIntoView() {
|
|
16
|
+
if (divRef.current && scroll === id) {
|
|
17
|
+
divRef.current.scrollIntoView({
|
|
18
|
+
block,
|
|
19
|
+
inline,
|
|
20
|
+
behavior
|
|
21
|
+
});
|
|
22
|
+
setScroll(null);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
scrollIntoView();
|
|
26
|
+
}, [scroll, setScroll, id, behavior, block, inline]);
|
|
27
|
+
return /* @__PURE__ */ React.createElement(
|
|
28
|
+
"div",
|
|
29
|
+
{
|
|
30
|
+
ref: divRef,
|
|
31
|
+
style: { position: "absolute", height: 0, width: 0, top, left },
|
|
32
|
+
"data-testid": `scroll-test-${id}`
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { ScrollAnchor };
|
|
38
|
+
//# sourceMappingURL=scroll.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scroll.esm.js","sources":["../../src/utils/scroll.tsx"],"sourcesContent":["/*\n * Copyright 2021 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, { useEffect, useRef } from 'react';\nimport { ScrollTo, useScroll } from '../hooks/useScroll';\n\n/*\n Utility component use in conjunction with useScroll that allows scrollable components to control behavior and offset.\n 1. ScrollAnchor must be a direct child of a scrollable component.\n 2. ScrollAnchor's parent position must be relative. \n 3. ScrollAnchor's id must be unique.\n*/\n\nexport interface ScrollAnchorProps extends ScrollIntoViewOptions {\n id: ScrollTo;\n top?: number;\n left?: number;\n}\n\nexport const ScrollAnchor = ({\n id,\n left = 0,\n top = -20,\n block = 'start',\n inline = 'nearest',\n behavior = 'smooth',\n}: ScrollAnchorProps) => {\n const divRef = useRef<HTMLDivElement>(null);\n const [scroll, setScroll] = useScroll();\n\n useEffect(() => {\n function scrollIntoView() {\n if (divRef.current && scroll === id) {\n divRef.current.scrollIntoView({\n block,\n inline,\n behavior,\n });\n setScroll(null);\n }\n }\n\n scrollIntoView();\n }, [scroll, setScroll, id, behavior, block, inline]);\n\n return (\n <div\n ref={divRef}\n style={{ position: 'absolute', height: 0, width: 0, top, left }}\n data-testid={`scroll-test-${id}`}\n />\n );\n};\n"],"names":[],"mappings":";;;AA+BO,MAAM,eAAe,CAAC;AAAA,EAC3B,EAAA;AAAA,EACA,IAAO,GAAA,CAAA;AAAA,EACP,GAAM,GAAA,CAAA,EAAA;AAAA,EACN,KAAQ,GAAA,OAAA;AAAA,EACR,MAAS,GAAA,SAAA;AAAA,EACT,QAAW,GAAA,QAAA;AACb,CAAyB,KAAA;AACvB,EAAM,MAAA,MAAA,GAAS,OAAuB,IAAI,CAAA,CAAA;AAC1C,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAU,EAAA,CAAA;AAEtC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,SAAS,cAAiB,GAAA;AACxB,MAAI,IAAA,MAAA,CAAO,OAAW,IAAA,MAAA,KAAW,EAAI,EAAA;AACnC,QAAA,MAAA,CAAO,QAAQ,cAAe,CAAA;AAAA,UAC5B,KAAA;AAAA,UACA,MAAA;AAAA,UACA,QAAA;AAAA,SACD,CAAA,CAAA;AACD,QAAA,SAAA,CAAU,IAAI,CAAA,CAAA;AAAA,OAChB;AAAA,KACF;AAEA,IAAe,cAAA,EAAA,CAAA;AAAA,GACjB,EAAG,CAAC,MAAQ,EAAA,SAAA,EAAW,IAAI,QAAU,EAAA,KAAA,EAAO,MAAM,CAAC,CAAA,CAAA;AAEnD,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAK,EAAA,MAAA;AAAA,MACL,KAAA,EAAO,EAAE,QAAU,EAAA,UAAA,EAAY,QAAQ,CAAG,EAAA,KAAA,EAAO,CAAG,EAAA,GAAA,EAAK,IAAK,EAAA;AAAA,MAC9D,aAAA,EAAa,eAAe,EAAE,CAAA,CAAA;AAAA,KAAA;AAAA,GAChC,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const aggregationSort = (a, b) => a.date.localeCompare(b.date);
|
|
2
|
+
const resourceSort = (a, b) => b.previous + b.current - (a.previous + a.current);
|
|
3
|
+
function totalAggregationSort(a, b) {
|
|
4
|
+
const [prevA, currA] = a.entity?.aggregation ?? [0, 0];
|
|
5
|
+
const [prevB, currB] = b.entity?.aggregation ?? [0, 0];
|
|
6
|
+
return prevB + currB - (prevA + currA);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export { aggregationSort, resourceSort, totalAggregationSort };
|
|
10
|
+
//# sourceMappingURL=sort.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sort.esm.js","sources":["../../src/utils/sort.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ResourceData } from '../types';\nimport { DateAggregation } from '@backstage-community/plugin-cost-insights-common';\nimport { ProductState } from './loading';\n\nexport const aggregationSort = (\n a: DateAggregation,\n b: DateAggregation,\n): number => a.date.localeCompare(b.date);\n\nexport const resourceSort = (a: ResourceData, b: ResourceData) =>\n b.previous + b.current - (a.previous + a.current);\n\nexport function totalAggregationSort(a: ProductState, b: ProductState): number {\n const [prevA, currA] = a.entity?.aggregation ?? [0, 0];\n const [prevB, currB] = b.entity?.aggregation ?? [0, 0];\n return prevB + currB - (prevA + currA);\n}\n"],"names":[],"mappings":"AAmBa,MAAA,eAAA,GAAkB,CAC7B,CACA,EAAA,CAAA,KACW,EAAE,IAAK,CAAA,aAAA,CAAc,EAAE,IAAI,EAAA;AAE3B,MAAA,YAAA,GAAe,CAAC,CAAA,EAAiB,CAC5C,KAAA,CAAA,CAAE,WAAW,CAAE,CAAA,OAAA,IAAW,CAAE,CAAA,QAAA,GAAW,CAAE,CAAA,OAAA,EAAA;AAE3B,SAAA,oBAAA,CAAqB,GAAiB,CAAyB,EAAA;AAC7E,EAAM,MAAA,CAAC,OAAO,KAAK,CAAA,GAAI,EAAE,MAAQ,EAAA,WAAA,IAAe,CAAC,CAAA,EAAG,CAAC,CAAA,CAAA;AACrD,EAAM,MAAA,CAAC,OAAO,KAAK,CAAA,GAAI,EAAE,MAAQ,EAAA,WAAA,IAAe,CAAC,CAAA,EAAG,CAAC,CAAA,CAAA;AACrD,EAAO,OAAA,KAAA,GAAQ,SAAS,KAAQ,GAAA,KAAA,CAAA,CAAA;AAClC;;;;"}
|