@backstage-community/plugin-cost-insights 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/alerts/ProjectGrowthAlert.esm.js.map +1 -1
- package/dist/alerts/UnlabeledDataflowAlert.esm.js.map +1 -1
- package/dist/alpha/plugin.esm.js +1 -1
- package/dist/alpha/plugin.esm.js.map +1 -1
- package/dist/alpha/router.esm.js.map +1 -1
- package/dist/alpha.d.ts +31 -10
- package/dist/api/CostInsightsApi.esm.js.map +1 -1
- package/dist/components/ActionItems/ActionItemCard.esm.js.map +1 -1
- package/dist/components/ActionItems/ActionItems.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertDialog.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsights.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsightsHeader.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsightsSection.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsightsSectionHeader.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertStatusSummary.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertStatusSummaryButton.esm.js.map +1 -1
- package/dist/components/AlertInstructionsLayout/AlertInstructionsLayout.esm.js.map +1 -1
- package/dist/components/BarChart/BarChart.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartLabel.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartLegend.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartStepper.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartStepperButton.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartSteps.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartTick.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartTooltip.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartTooltipItem.esm.js.map +1 -1
- package/dist/components/CopyUrlToClipboard/CopyUrlToClipboard.esm.js.map +1 -1
- package/dist/components/CostGrowth/CostGrowth.esm.js.map +1 -1
- package/dist/components/CostGrowth/CostGrowthIndicator.esm.js.map +1 -1
- package/dist/components/CostInsightsHeader/CostInsightsHeader.esm.js.map +1 -1
- package/dist/components/CostInsightsLayout/CostInsightsLayout.esm.js.map +1 -1
- package/dist/components/CostInsightsNavigation/CostInsightsNavigation.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/CostInsightsPage.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/CostInsightsPageRoot.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/CostInsightsThemeProvider.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/index.esm.js +5 -1
- package/dist/components/CostInsightsPage/index.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/selector.esm.js +1 -1
- package/dist/components/CostInsightsPage/selector.esm.js.map +1 -1
- package/dist/components/CostInsightsTabs/CostInsightsTabs.esm.js.map +1 -1
- package/dist/components/CostInsightsTabs/selector.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewBreakdownChart.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewCard.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewChart.esm.js +1 -1
- package/dist/components/CostOverviewCard/CostOverviewChart.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewHeader.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewLegend.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/selector.esm.js.map +1 -1
- package/dist/components/CurrencySelect/CurrencySelect.esm.js.map +1 -1
- package/dist/components/EntityCosts/EntityCosts.esm.js.map +1 -1
- package/dist/components/EntityCosts/index.esm.js +5 -1
- package/dist/components/EntityCosts/index.esm.js.map +1 -1
- package/dist/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.esm.js.map +1 -1
- package/dist/components/LabelDataflowInstructionsPage/index.esm.js +5 -1
- package/dist/components/LabelDataflowInstructionsPage/index.esm.js.map +1 -1
- package/dist/components/LegendItem/LegendItem.esm.js.map +1 -1
- package/dist/components/MetricSelect/MetricSelect.esm.js.map +1 -1
- package/dist/components/PeriodSelect/DateRangePicker.esm.js.map +1 -1
- package/dist/components/ProductInsights/ProductInsights.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductEntityDialog.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductEntityTable.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductInsightsCard.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductInsightsCardList.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductInsightsChart.esm.js.map +1 -1
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.esm.js.map +1 -1
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertChart.esm.js.map +1 -1
- package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js +0 -1
- package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js.map +1 -1
- package/dist/components/ProjectGrowthInstructionsPage/index.esm.js +5 -1
- package/dist/components/ProjectGrowthInstructionsPage/index.esm.js.map +1 -1
- package/dist/components/ProjectSelect/ProjectSelect.esm.js.map +1 -1
- package/dist/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.esm.js.map +1 -1
- package/dist/components/WhyCostsMatter/WhyCostsMatter.esm.js.map +1 -1
- package/dist/example/alerts/KubernetesMigrationAlert.esm.js.map +1 -1
- package/dist/example/client.esm.js +1 -1
- package/dist/example/client.esm.js.map +1 -1
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.esm.js.map +1 -1
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.esm.js.map +1 -1
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.esm.js.map +1 -1
- package/dist/example/forms/KubernetesMigrationDismissForm.esm.js.map +1 -1
- package/dist/forms/AlertAcceptForm.esm.js.map +1 -1
- package/dist/forms/AlertDismissForm.esm.js.map +1 -1
- package/dist/forms/AlertSnoozeForm.esm.js.map +1 -1
- package/dist/hooks/useConfig.esm.js +2 -2
- package/dist/hooks/useConfig.esm.js.map +1 -1
- package/dist/hooks/useCurrency.esm.js +1 -1
- package/dist/hooks/useCurrency.esm.js.map +1 -1
- package/dist/hooks/useFilters.esm.js +1 -1
- package/dist/hooks/useFilters.esm.js.map +1 -1
- package/dist/hooks/useGroups.esm.js +1 -1
- package/dist/hooks/useGroups.esm.js.map +1 -1
- package/dist/hooks/useLastCompleteBillingDate.esm.js +1 -1
- package/dist/hooks/useLastCompleteBillingDate.esm.js.map +1 -1
- package/dist/hooks/useLoading.esm.js +1 -1
- package/dist/hooks/useLoading.esm.js.map +1 -1
- package/dist/hooks/useScroll.esm.js +1 -1
- package/dist/hooks/useScroll.esm.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/plugin.esm.js +1 -1
- package/dist/plugin.esm.js.map +1 -1
- package/dist/routes.esm.js.map +1 -1
- package/dist/testUtils/filters.esm.js.map +1 -1
- package/dist/testUtils/loading.esm.js.map +1 -1
- package/dist/testUtils/mockData.esm.js.map +1 -1
- package/dist/testUtils/products.esm.js.map +1 -1
- package/dist/testUtils/providers.esm.js.map +1 -1
- package/dist/testUtils/testUtils.esm.js.map +1 -1
- package/dist/types/Alert.esm.js.map +1 -1
- package/dist/types/ChangeStatistic.esm.js.map +1 -1
- package/dist/types/CurrencyType.esm.js.map +1 -1
- package/dist/types/DateFormat.esm.js.map +1 -1
- package/dist/types/Duration.esm.js.map +1 -1
- package/dist/types/Icon.esm.js.map +1 -1
- package/dist/utils/alerts.esm.js.map +1 -1
- package/dist/utils/assert.esm.js.map +1 -1
- package/dist/utils/change.esm.js.map +1 -1
- package/dist/utils/charts.esm.js.map +1 -1
- package/dist/utils/config.esm.js.map +1 -1
- package/dist/utils/currency.esm.js.map +1 -1
- package/dist/utils/duration.esm.js.map +1 -1
- package/dist/utils/filters.esm.js.map +1 -1
- package/dist/utils/formatters.esm.js.map +1 -1
- package/dist/utils/grammar.esm.js.map +1 -1
- package/dist/utils/graphs.esm.js +1 -1
- package/dist/utils/graphs.esm.js.map +1 -1
- package/dist/utils/history.esm.js.map +1 -1
- package/dist/utils/loading.esm.js.map +1 -1
- package/dist/utils/navigation.esm.js.map +1 -1
- package/dist/utils/scroll.esm.js.map +1 -1
- package/dist/utils/sort.esm.js.map +1 -1
- package/dist/utils/styles.esm.js.map +1 -1
- package/dist/utils/sum.esm.js.map +1 -1
- package/package.json +13 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CostInsightsThemeProvider.esm.js","sources":["../../../src/components/CostInsightsPage/CostInsightsThemeProvider.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 { PropsWithChildren } from 'react';\nimport {\n ThemeProvider,\n createTheme as createMuiTheme,\n} from '@material-ui/core/styles';\nimport { Theme } from '@material-ui/core/styles';\nimport {\n costInsightsDarkTheme,\n costInsightsLightTheme,\n} from '../../utils/styles';\nimport { CostInsightsTheme } from '../../types';\n\nexport const CostInsightsThemeProvider = ({\n children,\n}: PropsWithChildren<{}>) => {\n return (\n <ThemeProvider\n theme={(theme: Theme) =>\n createMuiTheme({\n ...theme,\n palette: {\n ...theme.palette,\n ...(theme.palette.type === 'dark'\n ? costInsightsDarkTheme.palette\n : costInsightsLightTheme.palette),\n },\n }) as CostInsightsTheme\n }\n >\n {children}\n </ThemeProvider>\n );\n};\n"],"names":["createMuiTheme"],"mappings":";;;;AA4BO,MAAM,4BAA4B,CAAC;AAAA,EACxC;AACF,
|
|
1
|
+
{"version":3,"file":"CostInsightsThemeProvider.esm.js","sources":["../../../src/components/CostInsightsPage/CostInsightsThemeProvider.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 { PropsWithChildren } from 'react';\nimport {\n ThemeProvider,\n createTheme as createMuiTheme,\n} from '@material-ui/core/styles';\nimport { Theme } from '@material-ui/core/styles';\nimport {\n costInsightsDarkTheme,\n costInsightsLightTheme,\n} from '../../utils/styles';\nimport { CostInsightsTheme } from '../../types';\n\nexport const CostInsightsThemeProvider = ({\n children,\n}: PropsWithChildren<{}>) => {\n return (\n <ThemeProvider\n theme={(theme: Theme) =>\n createMuiTheme({\n ...theme,\n palette: {\n ...theme.palette,\n ...(theme.palette.type === 'dark'\n ? costInsightsDarkTheme.palette\n : costInsightsLightTheme.palette),\n },\n }) as CostInsightsTheme\n }\n >\n {children}\n </ThemeProvider>\n );\n};\n"],"names":["createMuiTheme"],"mappings":";;;;AA4BO,MAAM,4BAA4B,CAAC;AAAA,EACxC;AACF,CAAA,KAA6B;AAC3B,EAAA,uBACE,GAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,CAAC,KAAA,KACNA,WAAA,CAAe;AAAA,QACb,GAAG,KAAA;AAAA,QACH,OAAA,EAAS;AAAA,UACP,GAAG,KAAA,CAAM,OAAA;AAAA,UACT,GAAI,KAAA,CAAM,OAAA,CAAQ,SAAS,MAAA,GACvB,qBAAA,CAAsB,UACtB,sBAAA,CAAuB;AAAA;AAC7B,OACD,CAAA;AAAA,MAGF;AAAA;AAAA,GACH;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getResetStateWithoutInitial, getResetState, DefaultLoadingAction } from '../../utils/loading.esm.js';
|
|
2
2
|
|
|
3
3
|
const mapLoadingToProps = ({ state, actions, dispatch }) => ({
|
|
4
4
|
loadingActions: actions,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selector.esm.js","sources":["../../../src/components/CostInsightsPage/selector.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 { MapLoadingToProps } from '../../hooks';\nimport {\n getResetState,\n DefaultLoadingAction,\n getResetStateWithoutInitial,\n} from '../../utils/loading';\n\ntype CostInsightsPageLoadingProps = {\n loadingActions: Array<string>;\n loadingGroups: boolean;\n loadingBillingDate: boolean;\n loadingInitial: boolean;\n dispatchInitial: (isLoading: boolean) => void;\n dispatchInsights: (isLoading: boolean) => void;\n dispatchNone: (loadingActions: string[]) => void;\n dispatchReset: (loadingActions: string[]) => void;\n};\n\nexport const mapLoadingToProps: MapLoadingToProps<\n CostInsightsPageLoadingProps\n> = ({ state, actions, dispatch }) => ({\n loadingActions: actions,\n loadingGroups: state[DefaultLoadingAction.UserGroups],\n loadingBillingDate: state[DefaultLoadingAction.LastCompleteBillingDate],\n loadingInitial: state[DefaultLoadingAction.CostInsightsInitial],\n dispatchInitial: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.CostInsightsInitial]: isLoading }),\n dispatchInsights: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.CostInsightsPage]: isLoading }),\n dispatchNone: (loadingActions: string[]) =>\n dispatch(getResetState(loadingActions)),\n dispatchReset: (loadingActions: string[]) =>\n dispatch(getResetStateWithoutInitial(loadingActions)),\n});\n"],"names":[],"mappings":";;AAiCO,MAAM,oBAET,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"selector.esm.js","sources":["../../../src/components/CostInsightsPage/selector.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 { MapLoadingToProps } from '../../hooks';\nimport {\n getResetState,\n DefaultLoadingAction,\n getResetStateWithoutInitial,\n} from '../../utils/loading';\n\ntype CostInsightsPageLoadingProps = {\n loadingActions: Array<string>;\n loadingGroups: boolean;\n loadingBillingDate: boolean;\n loadingInitial: boolean;\n dispatchInitial: (isLoading: boolean) => void;\n dispatchInsights: (isLoading: boolean) => void;\n dispatchNone: (loadingActions: string[]) => void;\n dispatchReset: (loadingActions: string[]) => void;\n};\n\nexport const mapLoadingToProps: MapLoadingToProps<\n CostInsightsPageLoadingProps\n> = ({ state, actions, dispatch }) => ({\n loadingActions: actions,\n loadingGroups: state[DefaultLoadingAction.UserGroups],\n loadingBillingDate: state[DefaultLoadingAction.LastCompleteBillingDate],\n loadingInitial: state[DefaultLoadingAction.CostInsightsInitial],\n dispatchInitial: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.CostInsightsInitial]: isLoading }),\n dispatchInsights: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.CostInsightsPage]: isLoading }),\n dispatchNone: (loadingActions: string[]) =>\n dispatch(getResetState(loadingActions)),\n dispatchReset: (loadingActions: string[]) =>\n dispatch(getResetStateWithoutInitial(loadingActions)),\n});\n"],"names":[],"mappings":";;AAiCO,MAAM,oBAET,CAAC,EAAE,KAAA,EAAO,OAAA,EAAS,UAAS,MAAO;AAAA,EACrC,cAAA,EAAgB,OAAA;AAAA,EAChB,aAAA,EAAe,KAAA,CAAM,oBAAA,CAAqB,UAAU,CAAA;AAAA,EACpD,kBAAA,EAAoB,KAAA,CAAM,oBAAA,CAAqB,uBAAuB,CAAA;AAAA,EACtE,cAAA,EAAgB,KAAA,CAAM,oBAAA,CAAqB,mBAAmB,CAAA;AAAA,EAC9D,eAAA,EAAiB,CAAC,SAAA,KAChB,QAAA,CAAS,EAAE,CAAC,oBAAA,CAAqB,mBAAmB,GAAG,SAAA,EAAW,CAAA;AAAA,EACpE,gBAAA,EAAkB,CAAC,SAAA,KACjB,QAAA,CAAS,EAAE,CAAC,oBAAA,CAAqB,gBAAgB,GAAG,SAAA,EAAW,CAAA;AAAA,EACjE,cAAc,CAAC,cAAA,KACb,QAAA,CAAS,aAAA,CAAc,cAAc,CAAC,CAAA;AAAA,EACxC,eAAe,CAAC,cAAA,KACd,QAAA,CAAS,2BAAA,CAA4B,cAAc,CAAC;AACxD,CAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CostInsightsTabs.esm.js","sources":["../../../src/components/CostInsightsTabs/CostInsightsTabs.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useState } from 'react';\nimport Menu from '@material-ui/core/Menu';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Tab from '@material-ui/core/Tab';\nimport Tabs from '@material-ui/core/Tabs';\nimport Typography from '@material-ui/core/Typography';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { mapLoadingToProps, mapFiltersToProps } from './selector';\nimport { Group } from '@backstage-community/plugin-cost-insights-common';\nimport { useFilters, useLoading } from '../../hooks';\nimport { useCostInsightsTabsStyles as useStyles } from '../../utils/styles';\n\nexport type CostInsightsTabsProps = {\n groups: Group[];\n};\n\nexport const CostInsightsTabs = ({ groups }: CostInsightsTabsProps) => {\n const classes = useStyles();\n const [index] = useState(0); // index is fixed for now until other tabs are added\n const [groupMenuEl, setGroupMenuEl] = useState<Element | null>(null);\n const { group, setGroup } = useFilters(mapFiltersToProps);\n const { loadingActions, dispatchReset } = useLoading(mapLoadingToProps);\n\n const openGroupMenu = (e: any) => setGroupMenuEl(e.currentTarget as Element);\n\n const closeGroupMenu = () => setGroupMenuEl(null);\n\n const updateGroupFilterAndCloseMenu = (g: Group) => () => {\n dispatchReset(loadingActions);\n closeGroupMenu();\n setGroup(g);\n };\n\n const renderTabLabel = () => (\n <div className={classes.tabLabel}>\n <Typography className={classes.tabLabelText} variant=\"overline\">\n {`${groups.length} teams`}\n </Typography>\n <ExpandMoreIcon fontSize=\"small\" />\n </div>\n );\n\n const hasAtLeastTwoGroups = groups.length >= 2;\n\n if (!hasAtLeastTwoGroups) return null;\n\n return (\n <>\n <Tabs\n className={`cost-insights-tabs ${classes.tabs}`}\n data-testid=\"cost-insights-tabs\"\n classes={{ indicator: classes.indicator }}\n value={index}\n >\n <Tab\n className={classes.tab}\n data-testid=\"cost-insights-groups-tab\"\n key=\"cost-insights-groups-tab\"\n label={renderTabLabel()}\n onClick={openGroupMenu}\n component=\"button\"\n />\n </Tabs>\n <Menu\n id=\"group-menu\"\n data-testid=\"group-menu\"\n className={classes.menu}\n getContentAnchorEl={null}\n anchorEl={groupMenuEl}\n keepMounted\n open={Boolean(groupMenuEl)}\n onClose={closeGroupMenu}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'left',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'left',\n }}\n >\n {groups.map((g: Group) => (\n <MenuItem\n className={classes.menuItem}\n classes={{ selected: classes.menuItemSelected }}\n selected={g.id === group}\n key={g.id}\n data-testid={g.id}\n onClick={updateGroupFilterAndCloseMenu(g)}\n >\n {g.name ?? g.id}\n </MenuItem>\n ))}\n </Menu>\n </>\n );\n};\n"],"names":["useStyles"],"mappings":";;;;;;;;;;;;;;;;;;AAgCO,MAAM,
|
|
1
|
+
{"version":3,"file":"CostInsightsTabs.esm.js","sources":["../../../src/components/CostInsightsTabs/CostInsightsTabs.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useState } from 'react';\nimport Menu from '@material-ui/core/Menu';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Tab from '@material-ui/core/Tab';\nimport Tabs from '@material-ui/core/Tabs';\nimport Typography from '@material-ui/core/Typography';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { mapLoadingToProps, mapFiltersToProps } from './selector';\nimport { Group } from '@backstage-community/plugin-cost-insights-common';\nimport { useFilters, useLoading } from '../../hooks';\nimport { useCostInsightsTabsStyles as useStyles } from '../../utils/styles';\n\nexport type CostInsightsTabsProps = {\n groups: Group[];\n};\n\nexport const CostInsightsTabs = ({ groups }: CostInsightsTabsProps) => {\n const classes = useStyles();\n const [index] = useState(0); // index is fixed for now until other tabs are added\n const [groupMenuEl, setGroupMenuEl] = useState<Element | null>(null);\n const { group, setGroup } = useFilters(mapFiltersToProps);\n const { loadingActions, dispatchReset } = useLoading(mapLoadingToProps);\n\n const openGroupMenu = (e: any) => setGroupMenuEl(e.currentTarget as Element);\n\n const closeGroupMenu = () => setGroupMenuEl(null);\n\n const updateGroupFilterAndCloseMenu = (g: Group) => () => {\n dispatchReset(loadingActions);\n closeGroupMenu();\n setGroup(g);\n };\n\n const renderTabLabel = () => (\n <div className={classes.tabLabel}>\n <Typography className={classes.tabLabelText} variant=\"overline\">\n {`${groups.length} teams`}\n </Typography>\n <ExpandMoreIcon fontSize=\"small\" />\n </div>\n );\n\n const hasAtLeastTwoGroups = groups.length >= 2;\n\n if (!hasAtLeastTwoGroups) return null;\n\n return (\n <>\n <Tabs\n className={`cost-insights-tabs ${classes.tabs}`}\n data-testid=\"cost-insights-tabs\"\n classes={{ indicator: classes.indicator }}\n value={index}\n >\n <Tab\n className={classes.tab}\n data-testid=\"cost-insights-groups-tab\"\n key=\"cost-insights-groups-tab\"\n label={renderTabLabel()}\n onClick={openGroupMenu}\n component=\"button\"\n />\n </Tabs>\n <Menu\n id=\"group-menu\"\n data-testid=\"group-menu\"\n className={classes.menu}\n getContentAnchorEl={null}\n anchorEl={groupMenuEl}\n keepMounted\n open={Boolean(groupMenuEl)}\n onClose={closeGroupMenu}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'left',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'left',\n }}\n >\n {groups.map((g: Group) => (\n <MenuItem\n className={classes.menuItem}\n classes={{ selected: classes.menuItemSelected }}\n selected={g.id === group}\n key={g.id}\n data-testid={g.id}\n onClick={updateGroupFilterAndCloseMenu(g)}\n >\n {g.name ?? g.id}\n </MenuItem>\n ))}\n </Menu>\n </>\n );\n};\n"],"names":["useStyles"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selector.esm.js","sources":["../../../src/components/CostInsightsTabs/selector.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 { MapFiltersToProps } from '../../hooks/useFilters';\nimport { MapLoadingToProps } from '../../hooks/useLoading';\nimport { PageFilters } from '../../types';\nimport { Group } from '@backstage-community/plugin-cost-insights-common';\nimport { getResetStateWithoutInitial } from '../../utils/loading';\n\ntype CostInsightsTabsFilterProps = PageFilters & {\n setGroup: (group: Group) => void;\n};\n\ntype CostInsightsTabsLoadingProps = {\n loadingActions: Array<string>;\n dispatchReset: (loadingActions: string[]) => void;\n};\n\nexport const mapFiltersToProps: MapFiltersToProps<\n CostInsightsTabsFilterProps\n> = ({ pageFilters, setPageFilters }) => ({\n ...pageFilters,\n setGroup: (group: Group) =>\n setPageFilters({\n ...pageFilters,\n group: group.id,\n project: null,\n }),\n});\n\nexport const mapLoadingToProps: MapLoadingToProps<\n CostInsightsTabsLoadingProps\n> = ({ actions, dispatch }) => ({\n loadingActions: actions,\n dispatchReset: (loadingActions: string[]) =>\n dispatch(getResetStateWithoutInitial(loadingActions)),\n});\n"],"names":[],"mappings":";;AA+BO,MAAM,
|
|
1
|
+
{"version":3,"file":"selector.esm.js","sources":["../../../src/components/CostInsightsTabs/selector.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 { MapFiltersToProps } from '../../hooks/useFilters';\nimport { MapLoadingToProps } from '../../hooks/useLoading';\nimport { PageFilters } from '../../types';\nimport { Group } from '@backstage-community/plugin-cost-insights-common';\nimport { getResetStateWithoutInitial } from '../../utils/loading';\n\ntype CostInsightsTabsFilterProps = PageFilters & {\n setGroup: (group: Group) => void;\n};\n\ntype CostInsightsTabsLoadingProps = {\n loadingActions: Array<string>;\n dispatchReset: (loadingActions: string[]) => void;\n};\n\nexport const mapFiltersToProps: MapFiltersToProps<\n CostInsightsTabsFilterProps\n> = ({ pageFilters, setPageFilters }) => ({\n ...pageFilters,\n setGroup: (group: Group) =>\n setPageFilters({\n ...pageFilters,\n group: group.id,\n project: null,\n }),\n});\n\nexport const mapLoadingToProps: MapLoadingToProps<\n CostInsightsTabsLoadingProps\n> = ({ actions, dispatch }) => ({\n loadingActions: actions,\n dispatchReset: (loadingActions: string[]) =>\n dispatch(getResetStateWithoutInitial(loadingActions)),\n});\n"],"names":[],"mappings":";;AA+BO,MAAM,iBAAA,GAET,CAAC,EAAE,WAAA,EAAa,gBAAe,MAAO;AAAA,EACxC,GAAG,WAAA;AAAA,EACH,QAAA,EAAU,CAAC,KAAA,KACT,cAAA,CAAe;AAAA,IACb,GAAG,WAAA;AAAA,IACH,OAAO,KAAA,CAAM,EAAA;AAAA,IACb,OAAA,EAAS;AAAA,GACV;AACL,CAAA;AAEO,MAAM,iBAAA,GAET,CAAC,EAAE,OAAA,EAAS,UAAS,MAAO;AAAA,EAC9B,cAAA,EAAgB,OAAA;AAAA,EAChB,eAAe,CAAC,cAAA,KACd,QAAA,CAAS,2BAAA,CAA4B,cAAc,CAAC;AACxD,CAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CostOverviewBreakdownChart.esm.js","sources":["../../../src/components/CostOverviewCard/CostOverviewBreakdownChart.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 { useState } from 'react';\nimport { DateTime } from 'luxon';\nimport Box from '@material-ui/core/Box';\nimport Divider from '@material-ui/core/Divider';\nimport { emphasize } from '@material-ui/core/styles/colorManipulator';\nimport Typography from '@material-ui/core/Typography';\nimport { useTheme } from '@material-ui/core/styles';\nimport { default as FullScreenIcon } from '@material-ui/icons/Fullscreen';\nimport {\n Area,\n AreaChart,\n CartesianGrid,\n ResponsiveContainer,\n Tooltip as RechartsTooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport { DEFAULT_DATE_FORMAT, CostInsightsTheme, Duration } from '../../types';\nimport { Cost } from '@backstage-community/plugin-cost-insights-common';\nimport {\n BarChartLegend,\n BarChartTooltip as Tooltip,\n BarChartTooltipItem as TooltipItem,\n} from '../BarChart';\nimport {\n formatGraphValue,\n isInvalid,\n overviewGraphTickFormatter,\n} from '../../utils/graphs';\nimport { useCostOverviewStyles as useStyles } from '../../utils/styles';\nimport { useConfig, useFilters, useLastCompleteBillingDate } from '../../hooks';\nimport { mapFiltersToProps } from './selector';\nimport { getPreviousPeriodTotalCost } from '../../utils/change';\nimport { formatPeriod } from '../../utils/formatters';\nimport { aggregationSum } from '../../utils/sum';\nimport { BarChartLegendOptions } from '../BarChart';\nimport { TooltipRenderer } from '../../types';\n\nexport type CostOverviewBreakdownChartProps = {\n costBreakdown: Cost[];\n responsive?: boolean;\n};\n\nconst LOW_COST_THRESHOLD = 0.1;\n\nexport const CostOverviewBreakdownChart = ({\n costBreakdown,\n responsive = true,\n}: CostOverviewBreakdownChartProps) => {\n const theme = useTheme<CostInsightsTheme>();\n const classes = useStyles(theme);\n const { baseCurrency } = useConfig();\n const lastCompleteBillingDate = useLastCompleteBillingDate();\n const { duration, customDateRange } = useFilters(mapFiltersToProps);\n const [isExpanded, setExpanded] = useState(false);\n\n if (!costBreakdown) {\n return null;\n }\n\n const flattenedAggregation = costBreakdown\n .map(cost => cost.aggregation)\n .flat();\n\n const totalCost = aggregationSum(flattenedAggregation);\n\n const previousPeriodTotal = getPreviousPeriodTotalCost(\n flattenedAggregation,\n duration,\n lastCompleteBillingDate,\n customDateRange,\n );\n const currentPeriodTotal = totalCost - previousPeriodTotal;\n const canExpand = costBreakdown.length >= 8;\n const otherCategoryIds: string[] = [];\n\n const breakdownsByDate = costBreakdown.reduce(\n (breakdownByDate, breakdown) => {\n const breakdownTotal = aggregationSum(breakdown.aggregation);\n // Group breakdown items with less than 10% of the total cost into \"Other\" category if needed\n const isOtherCategory =\n canExpand && breakdownTotal < totalCost * LOW_COST_THRESHOLD;\n\n const updatedBreakdownByDate = { ...breakdownByDate };\n if (isOtherCategory) {\n otherCategoryIds.push(breakdown.id);\n }\n breakdown.aggregation.forEach(curAggregation => {\n const costsForDate = updatedBreakdownByDate[curAggregation.date] || {};\n\n updatedBreakdownByDate[curAggregation.date] = {\n ...costsForDate,\n [breakdown.id]:\n (costsForDate[breakdown.id] || 0) + curAggregation.amount,\n };\n });\n\n return updatedBreakdownByDate;\n },\n {} as Record<string, Record<string, number>>,\n );\n\n const chartData: Record<string, number>[] = Object.keys(breakdownsByDate)\n .map(date => {\n const costsForDate = Object.keys(breakdownsByDate[date]).reduce(\n (dateCosts, breakdown) => {\n // Group costs for items that belong to 'Other' in the chart.\n const cost = breakdownsByDate[date][breakdown];\n const breakdownCost =\n !isExpanded && otherCategoryIds.includes(breakdown)\n ? { Other: (dateCosts.Other || 0) + cost }\n : { [breakdown]: cost };\n return { ...dateCosts, ...breakdownCost };\n },\n {} as Record<string, number>,\n );\n return {\n ...costsForDate,\n date: Date.parse(date),\n };\n })\n .sort((a, b) => a.date - b.date);\n\n const sortedBreakdowns = costBreakdown.sort(\n (a, b) => aggregationSum(a.aggregation) - aggregationSum(b.aggregation),\n );\n\n const renderAreas = () => {\n const separatedBreakdowns = sortedBreakdowns\n // Check that the breakdown is a separate group and hasn't been added to 'Other'\n .filter(\n breakdown =>\n breakdown.id !== 'Other' && !otherCategoryIds.includes(breakdown.id),\n )\n .map(breakdown => breakdown.id);\n // Keep 'Other' category at the bottom of the stack\n const breakdownsToDisplay = isExpanded\n ? sortedBreakdowns.map(breakdown => breakdown.id)\n : ['Other', ...separatedBreakdowns];\n\n return breakdownsToDisplay.map((breakdown, i) => {\n // Logic to handle case where there are more items than data viz colors.\n const color =\n theme.palette.dataViz[\n (breakdownsToDisplay.length - 1 - i) %\n (theme.palette.dataViz.length - 1)\n ];\n return (\n <Area\n key={breakdown}\n dataKey={breakdown}\n isAnimationActive={false}\n stackId=\"1\"\n stroke={color}\n fill={color}\n onClick={() => setExpanded(true)}\n style={{\n cursor:\n breakdown === 'Other' && !isExpanded ? 'pointer' : undefined,\n }}\n />\n );\n });\n };\n\n const tooltipRenderer: TooltipRenderer = ({ label, payload = [] }) => {\n if (isInvalid({ label, payload })) return null;\n\n const date =\n typeof label === 'number'\n ? DateTime.fromMillis(label)\n : DateTime.fromISO(label!);\n const dateTitle = date.toUTC().toFormat(DEFAULT_DATE_FORMAT);\n const formatGraphValueWith = formatGraphValue(baseCurrency);\n const items = payload.map((p, i) => ({\n label: p.dataKey as string,\n value: formatGraphValueWith(Number(p.value), i),\n fill: p.color!,\n }));\n const expandText = (\n <Box>\n <Divider\n style={{\n backgroundColor: emphasize(theme.palette.divider, 1),\n margin: '10px 0',\n }}\n />\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\">\n <FullScreenIcon />\n <Typography>Click to expand</Typography>\n </Box>\n </Box>\n );\n return (\n <Tooltip title={dateTitle}>\n {items.reverse().map((item, index) => (\n <TooltipItem key={`${item.label}-${index}`} item={item} />\n ))}\n {canExpand && !isExpanded ? expandText : null}\n </Tooltip>\n );\n };\n\n const options: Partial<BarChartLegendOptions> = {\n previousName: formatPeriod(\n duration,\n lastCompleteBillingDate,\n false,\n customDateRange,\n ),\n currentName: formatPeriod(\n duration,\n lastCompleteBillingDate,\n true,\n customDateRange,\n ),\n hideMarker: true,\n };\n\n // For custom date ranges, only show total cost (no previous/current split)\n const legendCostStart =\n duration === Duration.CUSTOM ? 0 : previousPeriodTotal;\n const legendCostEnd =\n duration === Duration.CUSTOM ? totalCost : currentPeriodTotal;\n\n return (\n <Box display=\"flex\" flexDirection=\"column\">\n <Box display=\"flex\" flexDirection=\"row\">\n <BarChartLegend\n costStart={legendCostStart}\n costEnd={legendCostEnd}\n options={options}\n />\n </Box>\n <ResponsiveContainer\n width={responsive ? '100%' : classes.container.width}\n height={classes.container.height}\n >\n <AreaChart\n data={chartData}\n margin={{\n top: 16,\n right: 30,\n bottom: 40,\n }}\n >\n <CartesianGrid stroke={classes.cartesianGrid.stroke} />\n <XAxis\n dataKey=\"date\"\n domain={['dataMin', 'dataMax']}\n tickFormatter={overviewGraphTickFormatter}\n tickCount={6}\n type=\"number\"\n stroke={classes.axis.fill}\n />\n <YAxis\n domain={[() => 0, 'dataMax']}\n tick={{ fill: classes.axis.fill }}\n tickFormatter={formatGraphValue(baseCurrency)}\n width={classes.yAxis.width}\n />\n {renderAreas()}\n <RechartsTooltip content={tooltipRenderer} animationDuration={100} />\n </AreaChart>\n </ResponsiveContainer>\n </Box>\n );\n};\n"],"names":["useStyles","Tooltip","TooltipItem","RechartsTooltip"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CostOverviewBreakdownChart.esm.js","sources":["../../../src/components/CostOverviewCard/CostOverviewBreakdownChart.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 { useState } from 'react';\nimport { DateTime } from 'luxon';\nimport Box from '@material-ui/core/Box';\nimport Divider from '@material-ui/core/Divider';\nimport { emphasize } from '@material-ui/core/styles/colorManipulator';\nimport Typography from '@material-ui/core/Typography';\nimport { useTheme } from '@material-ui/core/styles';\nimport { default as FullScreenIcon } from '@material-ui/icons/Fullscreen';\nimport {\n Area,\n AreaChart,\n CartesianGrid,\n ResponsiveContainer,\n Tooltip as RechartsTooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport { DEFAULT_DATE_FORMAT, CostInsightsTheme, Duration } from '../../types';\nimport { Cost } from '@backstage-community/plugin-cost-insights-common';\nimport {\n BarChartLegend,\n BarChartTooltip as Tooltip,\n BarChartTooltipItem as TooltipItem,\n} from '../BarChart';\nimport {\n formatGraphValue,\n isInvalid,\n overviewGraphTickFormatter,\n} from '../../utils/graphs';\nimport { useCostOverviewStyles as useStyles } from '../../utils/styles';\nimport { useConfig, useFilters, useLastCompleteBillingDate } from '../../hooks';\nimport { mapFiltersToProps } from './selector';\nimport { getPreviousPeriodTotalCost } from '../../utils/change';\nimport { formatPeriod } from '../../utils/formatters';\nimport { aggregationSum } from '../../utils/sum';\nimport { BarChartLegendOptions } from '../BarChart';\nimport { TooltipRenderer } from '../../types';\n\nexport type CostOverviewBreakdownChartProps = {\n costBreakdown: Cost[];\n responsive?: boolean;\n};\n\nconst LOW_COST_THRESHOLD = 0.1;\n\nexport const CostOverviewBreakdownChart = ({\n costBreakdown,\n responsive = true,\n}: CostOverviewBreakdownChartProps) => {\n const theme = useTheme<CostInsightsTheme>();\n const classes = useStyles(theme);\n const { baseCurrency } = useConfig();\n const lastCompleteBillingDate = useLastCompleteBillingDate();\n const { duration, customDateRange } = useFilters(mapFiltersToProps);\n const [isExpanded, setExpanded] = useState(false);\n\n if (!costBreakdown) {\n return null;\n }\n\n const flattenedAggregation = costBreakdown\n .map(cost => cost.aggregation)\n .flat();\n\n const totalCost = aggregationSum(flattenedAggregation);\n\n const previousPeriodTotal = getPreviousPeriodTotalCost(\n flattenedAggregation,\n duration,\n lastCompleteBillingDate,\n customDateRange,\n );\n const currentPeriodTotal = totalCost - previousPeriodTotal;\n const canExpand = costBreakdown.length >= 8;\n const otherCategoryIds: string[] = [];\n\n const breakdownsByDate = costBreakdown.reduce(\n (breakdownByDate, breakdown) => {\n const breakdownTotal = aggregationSum(breakdown.aggregation);\n // Group breakdown items with less than 10% of the total cost into \"Other\" category if needed\n const isOtherCategory =\n canExpand && breakdownTotal < totalCost * LOW_COST_THRESHOLD;\n\n const updatedBreakdownByDate = { ...breakdownByDate };\n if (isOtherCategory) {\n otherCategoryIds.push(breakdown.id);\n }\n breakdown.aggregation.forEach(curAggregation => {\n const costsForDate = updatedBreakdownByDate[curAggregation.date] || {};\n\n updatedBreakdownByDate[curAggregation.date] = {\n ...costsForDate,\n [breakdown.id]:\n (costsForDate[breakdown.id] || 0) + curAggregation.amount,\n };\n });\n\n return updatedBreakdownByDate;\n },\n {} as Record<string, Record<string, number>>,\n );\n\n const chartData: Record<string, number>[] = Object.keys(breakdownsByDate)\n .map(date => {\n const costsForDate = Object.keys(breakdownsByDate[date]).reduce(\n (dateCosts, breakdown) => {\n // Group costs for items that belong to 'Other' in the chart.\n const cost = breakdownsByDate[date][breakdown];\n const breakdownCost =\n !isExpanded && otherCategoryIds.includes(breakdown)\n ? { Other: (dateCosts.Other || 0) + cost }\n : { [breakdown]: cost };\n return { ...dateCosts, ...breakdownCost };\n },\n {} as Record<string, number>,\n );\n return {\n ...costsForDate,\n date: Date.parse(date),\n };\n })\n .sort((a, b) => a.date - b.date);\n\n const sortedBreakdowns = costBreakdown.sort(\n (a, b) => aggregationSum(a.aggregation) - aggregationSum(b.aggregation),\n );\n\n const renderAreas = () => {\n const separatedBreakdowns = sortedBreakdowns\n // Check that the breakdown is a separate group and hasn't been added to 'Other'\n .filter(\n breakdown =>\n breakdown.id !== 'Other' && !otherCategoryIds.includes(breakdown.id),\n )\n .map(breakdown => breakdown.id);\n // Keep 'Other' category at the bottom of the stack\n const breakdownsToDisplay = isExpanded\n ? sortedBreakdowns.map(breakdown => breakdown.id)\n : ['Other', ...separatedBreakdowns];\n\n return breakdownsToDisplay.map((breakdown, i) => {\n // Logic to handle case where there are more items than data viz colors.\n const color =\n theme.palette.dataViz[\n (breakdownsToDisplay.length - 1 - i) %\n (theme.palette.dataViz.length - 1)\n ];\n return (\n <Area\n key={breakdown}\n dataKey={breakdown}\n isAnimationActive={false}\n stackId=\"1\"\n stroke={color}\n fill={color}\n onClick={() => setExpanded(true)}\n style={{\n cursor:\n breakdown === 'Other' && !isExpanded ? 'pointer' : undefined,\n }}\n />\n );\n });\n };\n\n const tooltipRenderer: TooltipRenderer = ({ label, payload = [] }) => {\n if (isInvalid({ label, payload })) return null;\n\n const date =\n typeof label === 'number'\n ? DateTime.fromMillis(label)\n : DateTime.fromISO(label!);\n const dateTitle = date.toUTC().toFormat(DEFAULT_DATE_FORMAT);\n const formatGraphValueWith = formatGraphValue(baseCurrency);\n const items = payload.map((p, i) => ({\n label: p.dataKey as string,\n value: formatGraphValueWith(Number(p.value), i),\n fill: p.color!,\n }));\n const expandText = (\n <Box>\n <Divider\n style={{\n backgroundColor: emphasize(theme.palette.divider, 1),\n margin: '10px 0',\n }}\n />\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\">\n <FullScreenIcon />\n <Typography>Click to expand</Typography>\n </Box>\n </Box>\n );\n return (\n <Tooltip title={dateTitle}>\n {items.reverse().map((item, index) => (\n <TooltipItem key={`${item.label}-${index}`} item={item} />\n ))}\n {canExpand && !isExpanded ? expandText : null}\n </Tooltip>\n );\n };\n\n const options: Partial<BarChartLegendOptions> = {\n previousName: formatPeriod(\n duration,\n lastCompleteBillingDate,\n false,\n customDateRange,\n ),\n currentName: formatPeriod(\n duration,\n lastCompleteBillingDate,\n true,\n customDateRange,\n ),\n hideMarker: true,\n };\n\n // For custom date ranges, only show total cost (no previous/current split)\n const legendCostStart =\n duration === Duration.CUSTOM ? 0 : previousPeriodTotal;\n const legendCostEnd =\n duration === Duration.CUSTOM ? totalCost : currentPeriodTotal;\n\n return (\n <Box display=\"flex\" flexDirection=\"column\">\n <Box display=\"flex\" flexDirection=\"row\">\n <BarChartLegend\n costStart={legendCostStart}\n costEnd={legendCostEnd}\n options={options}\n />\n </Box>\n <ResponsiveContainer\n width={responsive ? '100%' : classes.container.width}\n height={classes.container.height}\n >\n <AreaChart\n data={chartData}\n margin={{\n top: 16,\n right: 30,\n bottom: 40,\n }}\n >\n <CartesianGrid stroke={classes.cartesianGrid.stroke} />\n <XAxis\n dataKey=\"date\"\n domain={['dataMin', 'dataMax']}\n tickFormatter={overviewGraphTickFormatter}\n tickCount={6}\n type=\"number\"\n stroke={classes.axis.fill}\n />\n <YAxis\n domain={[() => 0, 'dataMax']}\n tick={{ fill: classes.axis.fill }}\n tickFormatter={formatGraphValue(baseCurrency)}\n width={classes.yAxis.width}\n />\n {renderAreas()}\n <RechartsTooltip content={tooltipRenderer} animationDuration={100} />\n </AreaChart>\n </ResponsiveContainer>\n </Box>\n );\n};\n"],"names":["useStyles","Tooltip","TooltipItem","RechartsTooltip"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CostOverviewCard.esm.js","sources":["../../../src/components/CostOverviewCard/CostOverviewCard.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 { useEffect, useState } from 'react';\nimport Box from '@material-ui/core/Box';\nimport { capitalize } from '@material-ui/core/utils';\nimport Card from '@material-ui/core/Card';\nimport CardContent from '@material-ui/core/CardContent';\nimport Divider from '@material-ui/core/Divider';\nimport Tab from '@material-ui/core/Tab';\nimport Tabs from '@material-ui/core/Tabs';\nimport { useTheme } from '@material-ui/core/styles';\nimport { CostOverviewChart } from './CostOverviewChart';\nimport { CostOverviewBreakdownChart } from './CostOverviewBreakdownChart';\nimport { CostOverviewHeader } from './CostOverviewHeader';\nimport { MetricSelect } from '../MetricSelect';\nimport { DateRangePicker } from '../PeriodSelect';\nimport { useConfig, useFilters } from '../../hooks';\nimport { mapFiltersToProps } from './selector';\nimport { DefaultNavigation } from '../../utils/navigation';\nimport { findAlways } from '../../utils/assert';\nimport { CostInsightsTheme } from '../../types';\nimport {\n Cost,\n Maybe,\n MetricData,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { useOverviewTabsStyles } from '../../utils/styles';\nimport { ScrollAnchor } from '../../utils/scroll';\n\nexport type CostOverviewCardProps = {\n dailyCostData: Cost;\n metricData: Maybe<MetricData>;\n};\n\nexport const CostOverviewCard = ({\n dailyCostData,\n metricData,\n}: CostOverviewCardProps) => {\n const theme = useTheme<CostInsightsTheme>();\n const styles = useOverviewTabsStyles(theme);\n const config = useConfig();\n const [tabIndex, setTabIndex] = useState(0);\n const { setDuration, setProject, setMetric, ...filters } =\n useFilters(mapFiltersToProps);\n\n // Reset tabIndex if breakdowns available change\n useEffect(() => {\n // Intentionally off-by-one to account for the overview tab\n const lastIndex = Object.keys(dailyCostData.groupedCosts ?? {}).length;\n if (tabIndex > lastIndex) {\n setTabIndex(0);\n }\n }, [dailyCostData, tabIndex, setTabIndex]);\n\n const metric = filters.metric\n ? findAlways(config.metrics, m => m.kind === filters.metric)\n : null;\n\n const breakdownTabs = Object.keys(dailyCostData.groupedCosts ?? {}).map(\n key => ({\n id: key,\n label: `Breakdown by ${key}`,\n title: `Cloud Cost By ${capitalize(key)}`,\n }),\n );\n const tabs = [\n { id: 'overview', label: 'Total cost', title: 'Cloud Cost' },\n ].concat(breakdownTabs);\n // tabIndex can temporarily be invalid while the useEffect above processes\n const safeTabIndex = tabIndex > tabs.length - 1 ? 0 : tabIndex;\n\n const OverviewTabs = () => {\n return (\n <>\n <Tabs\n indicatorColor=\"primary\"\n onChange={(_, index) => setTabIndex(index)}\n value={safeTabIndex}\n variant=\"scrollable\"\n scrollButtons=\"auto\"\n >\n {tabs.map((tab, index) => (\n <Tab\n className={styles.default}\n label={tab.label}\n key={tab.id}\n value={index}\n classes={{ selected: styles.selected }}\n />\n ))}\n </Tabs>\n </>\n );\n };\n\n // Metrics can only be selected on the total cost graph\n const showMetricSelect = config.metrics.length && safeTabIndex === 0;\n\n return (\n <Card style={{ position: 'relative', overflow: 'visible' }}>\n <ScrollAnchor id={DefaultNavigation.CostOverviewCard} />\n <CardContent>\n {dailyCostData.groupedCosts && <OverviewTabs />}\n <CostOverviewHeader title={tabs[safeTabIndex].title}>\n <DateRangePicker\n duration={filters.duration}\n onSelect={setDuration}\n customDateRange={filters.customDateRange}\n />\n </CostOverviewHeader>\n <Divider />\n <Box ml={2} my={1} display=\"flex\" flexDirection=\"column\">\n {safeTabIndex === 0 ? (\n <CostOverviewChart\n dailyCostData={dailyCostData}\n metric={metric}\n metricData={metricData}\n />\n ) : (\n <CostOverviewBreakdownChart\n costBreakdown={dailyCostData.groupedCosts![tabs[safeTabIndex].id]}\n />\n )}\n </Box>\n <Box display=\"flex\" justifyContent=\"flex-end\" alignItems=\"center\">\n {showMetricSelect && (\n <MetricSelect\n metric={filters.metric}\n metrics={config.metrics}\n onSelect={setMetric}\n />\n )}\n </Box>\n </CardContent>\n </Card>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDO,MAAM,mBAAmB,CAAC;AAAA,EAC/B,aAAA;AAAA,EACA;AACF,
|
|
1
|
+
{"version":3,"file":"CostOverviewCard.esm.js","sources":["../../../src/components/CostOverviewCard/CostOverviewCard.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 { useEffect, useState } from 'react';\nimport Box from '@material-ui/core/Box';\nimport { capitalize } from '@material-ui/core/utils';\nimport Card from '@material-ui/core/Card';\nimport CardContent from '@material-ui/core/CardContent';\nimport Divider from '@material-ui/core/Divider';\nimport Tab from '@material-ui/core/Tab';\nimport Tabs from '@material-ui/core/Tabs';\nimport { useTheme } from '@material-ui/core/styles';\nimport { CostOverviewChart } from './CostOverviewChart';\nimport { CostOverviewBreakdownChart } from './CostOverviewBreakdownChart';\nimport { CostOverviewHeader } from './CostOverviewHeader';\nimport { MetricSelect } from '../MetricSelect';\nimport { DateRangePicker } from '../PeriodSelect';\nimport { useConfig, useFilters } from '../../hooks';\nimport { mapFiltersToProps } from './selector';\nimport { DefaultNavigation } from '../../utils/navigation';\nimport { findAlways } from '../../utils/assert';\nimport { CostInsightsTheme } from '../../types';\nimport {\n Cost,\n Maybe,\n MetricData,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { useOverviewTabsStyles } from '../../utils/styles';\nimport { ScrollAnchor } from '../../utils/scroll';\n\nexport type CostOverviewCardProps = {\n dailyCostData: Cost;\n metricData: Maybe<MetricData>;\n};\n\nexport const CostOverviewCard = ({\n dailyCostData,\n metricData,\n}: CostOverviewCardProps) => {\n const theme = useTheme<CostInsightsTheme>();\n const styles = useOverviewTabsStyles(theme);\n const config = useConfig();\n const [tabIndex, setTabIndex] = useState(0);\n const { setDuration, setProject, setMetric, ...filters } =\n useFilters(mapFiltersToProps);\n\n // Reset tabIndex if breakdowns available change\n useEffect(() => {\n // Intentionally off-by-one to account for the overview tab\n const lastIndex = Object.keys(dailyCostData.groupedCosts ?? {}).length;\n if (tabIndex > lastIndex) {\n setTabIndex(0);\n }\n }, [dailyCostData, tabIndex, setTabIndex]);\n\n const metric = filters.metric\n ? findAlways(config.metrics, m => m.kind === filters.metric)\n : null;\n\n const breakdownTabs = Object.keys(dailyCostData.groupedCosts ?? {}).map(\n key => ({\n id: key,\n label: `Breakdown by ${key}`,\n title: `Cloud Cost By ${capitalize(key)}`,\n }),\n );\n const tabs = [\n { id: 'overview', label: 'Total cost', title: 'Cloud Cost' },\n ].concat(breakdownTabs);\n // tabIndex can temporarily be invalid while the useEffect above processes\n const safeTabIndex = tabIndex > tabs.length - 1 ? 0 : tabIndex;\n\n const OverviewTabs = () => {\n return (\n <>\n <Tabs\n indicatorColor=\"primary\"\n onChange={(_, index) => setTabIndex(index)}\n value={safeTabIndex}\n variant=\"scrollable\"\n scrollButtons=\"auto\"\n >\n {tabs.map((tab, index) => (\n <Tab\n className={styles.default}\n label={tab.label}\n key={tab.id}\n value={index}\n classes={{ selected: styles.selected }}\n />\n ))}\n </Tabs>\n </>\n );\n };\n\n // Metrics can only be selected on the total cost graph\n const showMetricSelect = config.metrics.length && safeTabIndex === 0;\n\n return (\n <Card style={{ position: 'relative', overflow: 'visible' }}>\n <ScrollAnchor id={DefaultNavigation.CostOverviewCard} />\n <CardContent>\n {dailyCostData.groupedCosts && <OverviewTabs />}\n <CostOverviewHeader title={tabs[safeTabIndex].title}>\n <DateRangePicker\n duration={filters.duration}\n onSelect={setDuration}\n customDateRange={filters.customDateRange}\n />\n </CostOverviewHeader>\n <Divider />\n <Box ml={2} my={1} display=\"flex\" flexDirection=\"column\">\n {safeTabIndex === 0 ? (\n <CostOverviewChart\n dailyCostData={dailyCostData}\n metric={metric}\n metricData={metricData}\n />\n ) : (\n <CostOverviewBreakdownChart\n costBreakdown={dailyCostData.groupedCosts![tabs[safeTabIndex].id]}\n />\n )}\n </Box>\n <Box display=\"flex\" justifyContent=\"flex-end\" alignItems=\"center\">\n {showMetricSelect && (\n <MetricSelect\n metric={filters.metric}\n metrics={config.metrics}\n onSelect={setMetric}\n />\n )}\n </Box>\n </CardContent>\n </Card>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,7 @@ import { BarChartTooltipItem } from '../BarChart/BarChartTooltipItem.esm.js';
|
|
|
19
19
|
import 'pluralize';
|
|
20
20
|
import '../../utils/duration.esm.js';
|
|
21
21
|
import { aggregationSort } from '../../utils/sort.esm.js';
|
|
22
|
-
import { overviewGraphTickFormatter,
|
|
22
|
+
import { overviewGraphTickFormatter, formatGraphValue, isInvalid } from '../../utils/graphs.esm.js';
|
|
23
23
|
import { useConfig } from '../../hooks/useConfig.esm.js';
|
|
24
24
|
import '../../hooks/useCurrency.esm.js';
|
|
25
25
|
import '../../hooks/useFilters.esm.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CostOverviewChart.esm.js","sources":["../../../src/components/CostOverviewCard/CostOverviewChart.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 { DateTime } from 'luxon';\nimport Box from '@material-ui/core/Box';\nimport { useTheme } from '@material-ui/core/styles';\nimport {\n ComposedChart,\n XAxis,\n YAxis,\n Tooltip as RechartsTooltip,\n CartesianGrid,\n Area,\n Line,\n ResponsiveContainer,\n} from 'recharts';\nimport { ChartData, DEFAULT_DATE_FORMAT, CostInsightsTheme } from '../../types';\nimport {\n Cost,\n Maybe,\n Metric,\n MetricData,\n} from '@backstage-community/plugin-cost-insights-common';\nimport {\n BarChartTooltip as Tooltip,\n BarChartTooltipItem as TooltipItem,\n} from '../BarChart';\nimport {\n overviewGraphTickFormatter,\n formatGraphValue,\n isInvalid,\n} from '../../utils/graphs';\nimport { useCostOverviewStyles as useStyles } from '../../utils/styles';\nimport { groupByDate, trendFrom } from '../../utils/charts';\nimport { aggregationSort } from '../../utils/sort';\nimport { CostOverviewLegend } from './CostOverviewLegend';\nimport { TooltipRenderer } from '../../types';\nimport { useConfig } from '../../hooks';\n\ntype CostOverviewChartProps = {\n metric: Maybe<Metric>;\n metricData: Maybe<MetricData>;\n dailyCostData: Cost;\n responsive?: boolean;\n};\n\nexport const CostOverviewChart = ({\n dailyCostData,\n metric,\n metricData,\n responsive = true,\n}: CostOverviewChartProps) => {\n const theme = useTheme<CostInsightsTheme>();\n const styles = useStyles(theme);\n const { baseCurrency, hideTrendLine } = useConfig();\n\n const data = {\n dailyCost: {\n dataKey: 'dailyCost',\n name: `Daily Cost`,\n format: 'currency',\n data: dailyCostData,\n },\n metric: {\n dataKey: metric?.kind ?? 'Unknown',\n name: metric?.name ?? 'Unknown',\n format: metricData?.format ?? 'number',\n data: metricData,\n },\n };\n\n const metricsByDate = data.metric.data\n ? data.metric.data.aggregation.reduce(groupByDate, {})\n : {};\n\n const chartData: ChartData[] = data.dailyCost.data.aggregation\n .slice()\n .sort(aggregationSort)\n .map(entry => ({\n date: Date.parse(entry.date),\n trend: trendFrom(data.dailyCost.data.trendline!, Date.parse(entry.date)),\n dailyCost: entry.amount,\n ...(metric && data.metric.data\n ? { [data.metric.dataKey]: metricsByDate[`${entry.date}`] }\n : {}),\n }));\n\n const tooltipRenderer: TooltipRenderer = ({ label, payload = [] }) => {\n if (isInvalid({ label, payload })) return null;\n\n const dataKeys = [data.dailyCost.dataKey, data.metric.dataKey];\n const date =\n typeof label === 'number'\n ? DateTime.fromMillis(label)\n : DateTime.fromISO(label!);\n const title = date.toUTC().toFormat(DEFAULT_DATE_FORMAT);\n const formatGraphValueWith = formatGraphValue(baseCurrency);\n const items = payload\n .filter(p => dataKeys.includes(p.dataKey as string))\n .map((p, i) => ({\n label:\n p.dataKey === data.dailyCost.dataKey\n ? data.dailyCost.name\n : data.metric.name,\n value:\n p.dataKey === data.dailyCost.dataKey\n ? formatGraphValueWith(Number(p.value), i, data.dailyCost.format)\n : formatGraphValueWith(Number(p.value), i, data.metric.format),\n fill:\n p.dataKey === data.dailyCost.dataKey\n ? theme.palette.blue\n : theme.palette.magenta,\n }));\n\n return (\n <Tooltip title={title}>\n {items.map((item, index) => (\n <TooltipItem key={`${item.label}-${index}`} item={item} />\n ))}\n </Tooltip>\n );\n };\n\n const localizedTickFormatter = formatGraphValue(baseCurrency);\n\n return (\n <Box display=\"flex\" flexDirection=\"column\">\n <CostOverviewLegend\n dailyCostData={dailyCostData}\n metric={metric}\n metricData={metricData}\n />\n <ResponsiveContainer\n width={responsive ? '100%' : styles.container.width}\n height={styles.container.height}\n className=\"cost-overview-chart\"\n >\n <ComposedChart margin={styles.chart.margin} data={chartData}>\n <CartesianGrid stroke={styles.cartesianGrid.stroke} />\n <XAxis\n dataKey=\"date\"\n domain={['dataMin', 'dataMax']}\n tickFormatter={overviewGraphTickFormatter}\n tickCount={6}\n type=\"number\"\n stroke={styles.axis.fill}\n />\n <YAxis\n domain={[() => 0, 'dataMax']}\n tick={{ fill: styles.axis.fill }}\n tickFormatter={localizedTickFormatter}\n width={styles.yAxis.width}\n yAxisId={data.dailyCost.dataKey}\n />\n {metric && (\n <YAxis\n domain={['auto', 'auto']}\n width={styles.yAxis.width}\n yAxisId={data.metric.dataKey}\n tickFormatter={(value: any, index: number) =>\n localizedTickFormatter(value, index, data.metric.format)\n }\n orientation=\"right\"\n />\n )}\n <Area\n dataKey={data.dailyCost.dataKey}\n isAnimationActive={false}\n fill={theme.palette.blue}\n fillOpacity={0.4}\n stroke=\"none\"\n yAxisId={data.dailyCost.dataKey}\n />\n {!hideTrendLine && (\n <Line\n activeDot={false}\n dataKey=\"trend\"\n dot={false}\n isAnimationActive={false}\n strokeWidth={2}\n stroke={theme.palette.blue}\n yAxisId={data.dailyCost.dataKey}\n />\n )}\n {metric && (\n <Line\n dataKey={data.metric.dataKey}\n dot={false}\n isAnimationActive={false}\n strokeWidth={2}\n stroke={theme.palette.magenta}\n yAxisId={data.metric.dataKey}\n />\n )}\n <RechartsTooltip content={tooltipRenderer} animationDuration={100} />\n </ComposedChart>\n </ResponsiveContainer>\n </Box>\n );\n};\n"],"names":["useStyles","Tooltip","TooltipItem","RechartsTooltip"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CostOverviewChart.esm.js","sources":["../../../src/components/CostOverviewCard/CostOverviewChart.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 { DateTime } from 'luxon';\nimport Box from '@material-ui/core/Box';\nimport { useTheme } from '@material-ui/core/styles';\nimport {\n ComposedChart,\n XAxis,\n YAxis,\n Tooltip as RechartsTooltip,\n CartesianGrid,\n Area,\n Line,\n ResponsiveContainer,\n} from 'recharts';\nimport { ChartData, DEFAULT_DATE_FORMAT, CostInsightsTheme } from '../../types';\nimport {\n Cost,\n Maybe,\n Metric,\n MetricData,\n} from '@backstage-community/plugin-cost-insights-common';\nimport {\n BarChartTooltip as Tooltip,\n BarChartTooltipItem as TooltipItem,\n} from '../BarChart';\nimport {\n overviewGraphTickFormatter,\n formatGraphValue,\n isInvalid,\n} from '../../utils/graphs';\nimport { useCostOverviewStyles as useStyles } from '../../utils/styles';\nimport { groupByDate, trendFrom } from '../../utils/charts';\nimport { aggregationSort } from '../../utils/sort';\nimport { CostOverviewLegend } from './CostOverviewLegend';\nimport { TooltipRenderer } from '../../types';\nimport { useConfig } from '../../hooks';\n\ntype CostOverviewChartProps = {\n metric: Maybe<Metric>;\n metricData: Maybe<MetricData>;\n dailyCostData: Cost;\n responsive?: boolean;\n};\n\nexport const CostOverviewChart = ({\n dailyCostData,\n metric,\n metricData,\n responsive = true,\n}: CostOverviewChartProps) => {\n const theme = useTheme<CostInsightsTheme>();\n const styles = useStyles(theme);\n const { baseCurrency, hideTrendLine } = useConfig();\n\n const data = {\n dailyCost: {\n dataKey: 'dailyCost',\n name: `Daily Cost`,\n format: 'currency',\n data: dailyCostData,\n },\n metric: {\n dataKey: metric?.kind ?? 'Unknown',\n name: metric?.name ?? 'Unknown',\n format: metricData?.format ?? 'number',\n data: metricData,\n },\n };\n\n const metricsByDate = data.metric.data\n ? data.metric.data.aggregation.reduce(groupByDate, {})\n : {};\n\n const chartData: ChartData[] = data.dailyCost.data.aggregation\n .slice()\n .sort(aggregationSort)\n .map(entry => ({\n date: Date.parse(entry.date),\n trend: trendFrom(data.dailyCost.data.trendline!, Date.parse(entry.date)),\n dailyCost: entry.amount,\n ...(metric && data.metric.data\n ? { [data.metric.dataKey]: metricsByDate[`${entry.date}`] }\n : {}),\n }));\n\n const tooltipRenderer: TooltipRenderer = ({ label, payload = [] }) => {\n if (isInvalid({ label, payload })) return null;\n\n const dataKeys = [data.dailyCost.dataKey, data.metric.dataKey];\n const date =\n typeof label === 'number'\n ? DateTime.fromMillis(label)\n : DateTime.fromISO(label!);\n const title = date.toUTC().toFormat(DEFAULT_DATE_FORMAT);\n const formatGraphValueWith = formatGraphValue(baseCurrency);\n const items = payload\n .filter(p => dataKeys.includes(p.dataKey as string))\n .map((p, i) => ({\n label:\n p.dataKey === data.dailyCost.dataKey\n ? data.dailyCost.name\n : data.metric.name,\n value:\n p.dataKey === data.dailyCost.dataKey\n ? formatGraphValueWith(Number(p.value), i, data.dailyCost.format)\n : formatGraphValueWith(Number(p.value), i, data.metric.format),\n fill:\n p.dataKey === data.dailyCost.dataKey\n ? theme.palette.blue\n : theme.palette.magenta,\n }));\n\n return (\n <Tooltip title={title}>\n {items.map((item, index) => (\n <TooltipItem key={`${item.label}-${index}`} item={item} />\n ))}\n </Tooltip>\n );\n };\n\n const localizedTickFormatter = formatGraphValue(baseCurrency);\n\n return (\n <Box display=\"flex\" flexDirection=\"column\">\n <CostOverviewLegend\n dailyCostData={dailyCostData}\n metric={metric}\n metricData={metricData}\n />\n <ResponsiveContainer\n width={responsive ? '100%' : styles.container.width}\n height={styles.container.height}\n className=\"cost-overview-chart\"\n >\n <ComposedChart margin={styles.chart.margin} data={chartData}>\n <CartesianGrid stroke={styles.cartesianGrid.stroke} />\n <XAxis\n dataKey=\"date\"\n domain={['dataMin', 'dataMax']}\n tickFormatter={overviewGraphTickFormatter}\n tickCount={6}\n type=\"number\"\n stroke={styles.axis.fill}\n />\n <YAxis\n domain={[() => 0, 'dataMax']}\n tick={{ fill: styles.axis.fill }}\n tickFormatter={localizedTickFormatter}\n width={styles.yAxis.width}\n yAxisId={data.dailyCost.dataKey}\n />\n {metric && (\n <YAxis\n domain={['auto', 'auto']}\n width={styles.yAxis.width}\n yAxisId={data.metric.dataKey}\n tickFormatter={(value: any, index: number) =>\n localizedTickFormatter(value, index, data.metric.format)\n }\n orientation=\"right\"\n />\n )}\n <Area\n dataKey={data.dailyCost.dataKey}\n isAnimationActive={false}\n fill={theme.palette.blue}\n fillOpacity={0.4}\n stroke=\"none\"\n yAxisId={data.dailyCost.dataKey}\n />\n {!hideTrendLine && (\n <Line\n activeDot={false}\n dataKey=\"trend\"\n dot={false}\n isAnimationActive={false}\n strokeWidth={2}\n stroke={theme.palette.blue}\n yAxisId={data.dailyCost.dataKey}\n />\n )}\n {metric && (\n <Line\n dataKey={data.metric.dataKey}\n dot={false}\n isAnimationActive={false}\n strokeWidth={2}\n stroke={theme.palette.magenta}\n yAxisId={data.metric.dataKey}\n />\n )}\n <RechartsTooltip content={tooltipRenderer} animationDuration={100} />\n </ComposedChart>\n </ResponsiveContainer>\n </Box>\n );\n};\n"],"names":["useStyles","Tooltip","TooltipItem","RechartsTooltip"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CostOverviewHeader.esm.js","sources":["../../../src/components/CostOverviewCard/CostOverviewHeader.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 { PropsWithChildren } from 'react';\nimport Box from '@material-ui/core/Box';\nimport Typography from '@material-ui/core/Typography';\n\ntype CostOverviewHeaderProps = {\n title: string;\n subtitle?: string;\n};\n\nexport const CostOverviewHeader = ({\n title,\n subtitle,\n children,\n}: PropsWithChildren<CostOverviewHeaderProps>) => (\n <Box\n mt={2}\n ml={1}\n mb={1}\n display=\"flex\"\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n >\n <Box minHeight={40} paddingRight={5}>\n <Typography variant=\"h5\" gutterBottom>\n {title}\n </Typography>\n {!!subtitle && (\n <Typography variant=\"subtitle2\" color=\"textSecondary\" component=\"div\">\n {subtitle}\n </Typography>\n )}\n </Box>\n <Box minHeight={40} maxHeight={60} display=\"flex\">\n {children}\n </Box>\n </Box>\n);\n"],"names":[],"mappings":";;;;AAwBO,MAAM,qBAAqB,CAAC;AAAA,EACjC,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,
|
|
1
|
+
{"version":3,"file":"CostOverviewHeader.esm.js","sources":["../../../src/components/CostOverviewCard/CostOverviewHeader.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 { PropsWithChildren } from 'react';\nimport Box from '@material-ui/core/Box';\nimport Typography from '@material-ui/core/Typography';\n\ntype CostOverviewHeaderProps = {\n title: string;\n subtitle?: string;\n};\n\nexport const CostOverviewHeader = ({\n title,\n subtitle,\n children,\n}: PropsWithChildren<CostOverviewHeaderProps>) => (\n <Box\n mt={2}\n ml={1}\n mb={1}\n display=\"flex\"\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n >\n <Box minHeight={40} paddingRight={5}>\n <Typography variant=\"h5\" gutterBottom>\n {title}\n </Typography>\n {!!subtitle && (\n <Typography variant=\"subtitle2\" color=\"textSecondary\" component=\"div\">\n {subtitle}\n </Typography>\n )}\n </Box>\n <Box minHeight={40} maxHeight={60} display=\"flex\">\n {children}\n </Box>\n </Box>\n);\n"],"names":[],"mappings":";;;;AAwBO,MAAM,qBAAqB,CAAC;AAAA,EACjC,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,qBACE,IAAA;AAAA,EAAC,GAAA;AAAA,EAAA;AAAA,IACC,EAAA,EAAI,CAAA;AAAA,IACJ,EAAA,EAAI,CAAA;AAAA,IACJ,EAAA,EAAI,CAAA;AAAA,IACJ,OAAA,EAAQ,MAAA;AAAA,IACR,aAAA,EAAc,KAAA;AAAA,IACd,cAAA,EAAe,eAAA;AAAA,IACf,UAAA,EAAW,QAAA;AAAA,IAEX,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,EAAA,EAAI,YAAA,EAAc,CAAA,EAChC,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,IAAA,EAAK,YAAA,EAAY,MAClC,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,QACC,CAAC,CAAC,QAAA,oBACD,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,WAAA,EAAY,KAAA,EAAM,eAAA,EAAgB,SAAA,EAAU,KAAA,EAC7D,QAAA,EAAA,QAAA,EACH;AAAA,OAAA,EAEJ,CAAA;AAAA,sBACA,GAAA,CAAC,OAAI,SAAA,EAAW,EAAA,EAAI,WAAW,EAAA,EAAI,OAAA,EAAQ,QACxC,QAAA,EACH;AAAA;AAAA;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CostOverviewLegend.esm.js","sources":["../../../src/components/CostOverviewCard/CostOverviewLegend.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 { PropsWithChildren } from 'react';\nimport Box from '@material-ui/core/Box';\nimport { useTheme } from '@material-ui/core/styles';\nimport { LegendItem } from '../LegendItem';\nimport { CostInsightsTheme } from '../../types';\nimport {\n MetricData,\n Maybe,\n Cost,\n Metric,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { useLastCompleteBillingDate, useFilters } from '../../hooks';\nimport { getComparedChange, choose } from '../../utils/change';\nimport { mapFiltersToProps } from './selector';\nimport { formatChange } from '../../utils/formatters';\nimport { CostGrowth } from '../CostGrowth';\n\ntype CostOverviewLegendProps = {\n metric: Maybe<Metric>;\n metricData: Maybe<MetricData>;\n dailyCostData: Cost;\n};\n\nexport const CostOverviewLegend = ({\n dailyCostData,\n metric,\n metricData,\n}: PropsWithChildren<CostOverviewLegendProps>) => {\n const theme = useTheme<CostInsightsTheme>();\n const { duration, customDateRange } = useFilters(mapFiltersToProps);\n const lastCompleteBillingDate = useLastCompleteBillingDate();\n\n const comparedChange = metricData\n ? getComparedChange(\n dailyCostData,\n metricData,\n duration,\n lastCompleteBillingDate,\n customDateRange,\n )\n : null;\n\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n {dailyCostData.change && (\n <Box mr={2}>\n <LegendItem title=\"Cost Trend\" markerColor={theme.palette.blue}>\n {formatChange(dailyCostData.change)}\n </LegendItem>\n </Box>\n )}\n {metricData && metric && comparedChange && (\n <>\n <Box mr={2}>\n <LegendItem\n title={`${metric.name} Trend`}\n markerColor={theme.palette.magenta}\n >\n {formatChange(metricData.change)}\n </LegendItem>\n </Box>\n <LegendItem\n title={choose(['Your Savings', 'Your Excess'], comparedChange)}\n >\n <CostGrowth\n change={comparedChange}\n duration={duration}\n customDateRange={customDateRange}\n />\n </LegendItem>\n </>\n )}\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuCO,MAAM,qBAAqB,CAAC;AAAA,EACjC,aAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,
|
|
1
|
+
{"version":3,"file":"CostOverviewLegend.esm.js","sources":["../../../src/components/CostOverviewCard/CostOverviewLegend.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 { PropsWithChildren } from 'react';\nimport Box from '@material-ui/core/Box';\nimport { useTheme } from '@material-ui/core/styles';\nimport { LegendItem } from '../LegendItem';\nimport { CostInsightsTheme } from '../../types';\nimport {\n MetricData,\n Maybe,\n Cost,\n Metric,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { useLastCompleteBillingDate, useFilters } from '../../hooks';\nimport { getComparedChange, choose } from '../../utils/change';\nimport { mapFiltersToProps } from './selector';\nimport { formatChange } from '../../utils/formatters';\nimport { CostGrowth } from '../CostGrowth';\n\ntype CostOverviewLegendProps = {\n metric: Maybe<Metric>;\n metricData: Maybe<MetricData>;\n dailyCostData: Cost;\n};\n\nexport const CostOverviewLegend = ({\n dailyCostData,\n metric,\n metricData,\n}: PropsWithChildren<CostOverviewLegendProps>) => {\n const theme = useTheme<CostInsightsTheme>();\n const { duration, customDateRange } = useFilters(mapFiltersToProps);\n const lastCompleteBillingDate = useLastCompleteBillingDate();\n\n const comparedChange = metricData\n ? getComparedChange(\n dailyCostData,\n metricData,\n duration,\n lastCompleteBillingDate,\n customDateRange,\n )\n : null;\n\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n {dailyCostData.change && (\n <Box mr={2}>\n <LegendItem title=\"Cost Trend\" markerColor={theme.palette.blue}>\n {formatChange(dailyCostData.change)}\n </LegendItem>\n </Box>\n )}\n {metricData && metric && comparedChange && (\n <>\n <Box mr={2}>\n <LegendItem\n title={`${metric.name} Trend`}\n markerColor={theme.palette.magenta}\n >\n {formatChange(metricData.change)}\n </LegendItem>\n </Box>\n <LegendItem\n title={choose(['Your Savings', 'Your Excess'], comparedChange)}\n >\n <CostGrowth\n change={comparedChange}\n duration={duration}\n customDateRange={customDateRange}\n />\n </LegendItem>\n </>\n )}\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuCO,MAAM,qBAAqB,CAAC;AAAA,EACjC,aAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,KAAkD;AAChD,EAAA,MAAM,QAAQ,QAAA,EAA4B;AAC1C,EAAA,MAAM,EAAE,QAAA,EAAU,eAAA,EAAgB,GAAI,WAAW,iBAAiB,CAAA;AAClE,EAAA,MAAM,0BAA0B,0BAAA,EAA2B;AAE3D,EAAA,MAAM,iBAAiB,UAAA,GACnB,iBAAA;AAAA,IACE,aAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,uBAAA;AAAA,IACA;AAAA,GACF,GACA,IAAA;AAEJ,EAAA,uBACE,IAAA,CAAC,GAAA,EAAA,EAAI,OAAA,EAAQ,MAAA,EAAO,eAAc,KAAA,EAC/B,QAAA,EAAA;AAAA,IAAA,aAAA,CAAc,0BACb,GAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAI,CAAA,EACP,8BAAC,UAAA,EAAA,EAAW,KAAA,EAAM,YAAA,EAAa,WAAA,EAAa,MAAM,OAAA,CAAQ,IAAA,EACvD,uBAAa,aAAA,CAAc,MAAM,GACpC,CAAA,EACF,CAAA;AAAA,IAED,UAAA,IAAc,MAAA,IAAU,cAAA,oBACvB,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,GAAA,EAAA,EAAI,IAAI,CAAA,EACP,QAAA,kBAAA,GAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,MAAA,CAAA;AAAA,UACrB,WAAA,EAAa,MAAM,OAAA,CAAQ,OAAA;AAAA,UAE1B,QAAA,EAAA,YAAA,CAAa,WAAW,MAAM;AAAA;AAAA,OACjC,EACF,CAAA;AAAA,sBACA,GAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,OAAO,MAAA,CAAO,CAAC,cAAA,EAAgB,aAAa,GAAG,cAAc,CAAA;AAAA,UAE7D,QAAA,kBAAA,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,MAAA,EAAQ,cAAA;AAAA,cACR,QAAA;AAAA,cACA;AAAA;AAAA;AACF;AAAA;AACF,KAAA,EACF;AAAA,GAAA,EAEJ,CAAA;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selector.esm.js","sources":["../../../src/components/CostOverviewCard/selector.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 { Duration, PageFilters } from '../../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { MapFiltersToProps } from '../../hooks/useFilters';\n\ntype CostOverviewFilterProps = PageFilters & {\n setDuration: (\n duration: Duration,\n customDateRange?: { start: string; end: string },\n ) => void;\n setProject: (project: Maybe<string>) => void;\n setMetric: (metric: Maybe<string>) => void;\n};\n\nexport const mapFiltersToProps: MapFiltersToProps<CostOverviewFilterProps> = ({\n pageFilters,\n setPageFilters,\n}) => ({\n ...pageFilters,\n project: pageFilters.project || 'all',\n setDuration: (\n duration: Duration,\n customDateRange?: { start: string; end: string },\n ) =>\n setPageFilters({\n ...pageFilters,\n duration,\n customDateRange,\n }),\n setProject: (project: Maybe<string>) =>\n setPageFilters({\n ...pageFilters,\n project: project === 'all' ? null : project,\n }),\n setMetric: (metric: Maybe<string>) =>\n setPageFilters({\n ...pageFilters,\n metric: metric,\n }),\n});\n"],"names":[],"mappings":"AA4BO,MAAM,oBAAgE,CAAC;AAAA,EAC5E,WAAA;AAAA,EACA;AACF,
|
|
1
|
+
{"version":3,"file":"selector.esm.js","sources":["../../../src/components/CostOverviewCard/selector.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 { Duration, PageFilters } from '../../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { MapFiltersToProps } from '../../hooks/useFilters';\n\ntype CostOverviewFilterProps = PageFilters & {\n setDuration: (\n duration: Duration,\n customDateRange?: { start: string; end: string },\n ) => void;\n setProject: (project: Maybe<string>) => void;\n setMetric: (metric: Maybe<string>) => void;\n};\n\nexport const mapFiltersToProps: MapFiltersToProps<CostOverviewFilterProps> = ({\n pageFilters,\n setPageFilters,\n}) => ({\n ...pageFilters,\n project: pageFilters.project || 'all',\n setDuration: (\n duration: Duration,\n customDateRange?: { start: string; end: string },\n ) =>\n setPageFilters({\n ...pageFilters,\n duration,\n customDateRange,\n }),\n setProject: (project: Maybe<string>) =>\n setPageFilters({\n ...pageFilters,\n project: project === 'all' ? null : project,\n }),\n setMetric: (metric: Maybe<string>) =>\n setPageFilters({\n ...pageFilters,\n metric: metric,\n }),\n});\n"],"names":[],"mappings":"AA4BO,MAAM,oBAAgE,CAAC;AAAA,EAC5E,WAAA;AAAA,EACA;AACF,CAAA,MAAO;AAAA,EACL,GAAG,WAAA;AAAA,EACH,OAAA,EAAS,YAAY,OAAA,IAAW,KAAA;AAAA,EAChC,WAAA,EAAa,CACX,QAAA,EACA,eAAA,KAEA,cAAA,CAAe;AAAA,IACb,GAAG,WAAA;AAAA,IACH,QAAA;AAAA,IACA;AAAA,GACD,CAAA;AAAA,EACH,UAAA,EAAY,CAAC,OAAA,KACX,cAAA,CAAe;AAAA,IACb,GAAG,WAAA;AAAA,IACH,OAAA,EAAS,OAAA,KAAY,KAAA,GAAQ,IAAA,GAAO;AAAA,GACrC,CAAA;AAAA,EACH,SAAA,EAAW,CAAC,MAAA,KACV,cAAA,CAAe;AAAA,IACb,GAAG,WAAA;AAAA,IACH;AAAA,GACD;AACL,CAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CurrencySelect.esm.js","sources":["../../../src/components/CurrencySelect/CurrencySelect.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 InputLabel from '@material-ui/core/InputLabel';\nimport Select, { SelectProps } from '@material-ui/core/Select';\nimport FormControl from '@material-ui/core/FormControl';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Typography from '@material-ui/core/Typography';\nimport { Currency, CurrencyType } from '../../types';\nimport { findAlways } from '../../utils/assert';\nimport { useSelectStyles as useStyles } from '../../utils/styles';\n\nconst NULL_VALUE = 'engineers';\n\ntype CurrencySelectProps = {\n currency: Currency;\n currencies: Currency[];\n onSelect: (currency: Currency) => void;\n};\n\nexport const CurrencySelect = ({\n currency,\n currencies,\n onSelect,\n}: CurrencySelectProps) => {\n const classes = useStyles();\n\n const getOption = (value: unknown) => {\n const kind = (value === NULL_VALUE ? null : value) as CurrencyType;\n return findAlways(currencies, c => c.kind === kind);\n };\n\n const handleOnChange: SelectProps['onChange'] = e => {\n const option = getOption(e.target.value);\n onSelect(option);\n };\n\n const renderValue: SelectProps['renderValue'] = value => {\n const option = getOption(value);\n return <b>{option.label}</b>;\n };\n\n return (\n <FormControl variant=\"outlined\">\n <InputLabel shrink>Convert to:</InputLabel>\n <Select\n className={classes.select}\n variant=\"outlined\"\n labelWidth={100}\n onChange={handleOnChange}\n value={currency.kind || NULL_VALUE}\n renderValue={renderValue}\n >\n {currencies.map((c: Currency) => (\n <MenuItem\n className={classes.menuItem}\n key={c.kind || NULL_VALUE}\n value={c.kind || NULL_VALUE}\n >\n <Typography component=\"span\" role=\"img\" aria-label={c.label}>\n {c.label}\n </Typography>\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n );\n};\n"],"names":["useStyles"],"mappings":";;;;;;;;;AAyBA,MAAM,
|
|
1
|
+
{"version":3,"file":"CurrencySelect.esm.js","sources":["../../../src/components/CurrencySelect/CurrencySelect.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 InputLabel from '@material-ui/core/InputLabel';\nimport Select, { SelectProps } from '@material-ui/core/Select';\nimport FormControl from '@material-ui/core/FormControl';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Typography from '@material-ui/core/Typography';\nimport { Currency, CurrencyType } from '../../types';\nimport { findAlways } from '../../utils/assert';\nimport { useSelectStyles as useStyles } from '../../utils/styles';\n\nconst NULL_VALUE = 'engineers';\n\ntype CurrencySelectProps = {\n currency: Currency;\n currencies: Currency[];\n onSelect: (currency: Currency) => void;\n};\n\nexport const CurrencySelect = ({\n currency,\n currencies,\n onSelect,\n}: CurrencySelectProps) => {\n const classes = useStyles();\n\n const getOption = (value: unknown) => {\n const kind = (value === NULL_VALUE ? null : value) as CurrencyType;\n return findAlways(currencies, c => c.kind === kind);\n };\n\n const handleOnChange: SelectProps['onChange'] = e => {\n const option = getOption(e.target.value);\n onSelect(option);\n };\n\n const renderValue: SelectProps['renderValue'] = value => {\n const option = getOption(value);\n return <b>{option.label}</b>;\n };\n\n return (\n <FormControl variant=\"outlined\">\n <InputLabel shrink>Convert to:</InputLabel>\n <Select\n className={classes.select}\n variant=\"outlined\"\n labelWidth={100}\n onChange={handleOnChange}\n value={currency.kind || NULL_VALUE}\n renderValue={renderValue}\n >\n {currencies.map((c: Currency) => (\n <MenuItem\n className={classes.menuItem}\n key={c.kind || NULL_VALUE}\n value={c.kind || NULL_VALUE}\n >\n <Typography component=\"span\" role=\"img\" aria-label={c.label}>\n {c.label}\n </Typography>\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n );\n};\n"],"names":["useStyles"],"mappings":";;;;;;;;;AAyBA,MAAM,UAAA,GAAa,WAAA;AAQZ,MAAM,iBAAiB,CAAC;AAAA,EAC7B,QAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,KAA2B;AACzB,EAAA,MAAM,UAAUA,eAAA,EAAU;AAE1B,EAAA,MAAM,SAAA,GAAY,CAAC,KAAA,KAAmB;AACpC,IAAA,MAAM,IAAA,GAAQ,KAAA,KAAU,UAAA,GAAa,IAAA,GAAO,KAAA;AAC5C,IAAA,OAAO,UAAA,CAAW,UAAA,EAAY,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,IAAI,CAAA;AAAA,EACpD,CAAA;AAEA,EAAA,MAAM,iBAA0C,CAAA,CAAA,KAAK;AACnD,IAAA,MAAM,MAAA,GAAS,SAAA,CAAU,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AACvC,IAAA,QAAA,CAAS,MAAM,CAAA;AAAA,EACjB,CAAA;AAEA,EAAA,MAAM,cAA0C,CAAA,KAAA,KAAS;AACvD,IAAA,MAAM,MAAA,GAAS,UAAU,KAAK,CAAA;AAC9B,IAAA,uBAAO,GAAA,CAAC,GAAA,EAAA,EAAG,QAAA,EAAA,MAAA,CAAO,KAAA,EAAM,CAAA;AAAA,EAC1B,CAAA;AAEA,EAAA,uBACE,IAAA,CAAC,WAAA,EAAA,EAAY,OAAA,EAAQ,UAAA,EACnB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,MAAA,EAAM,IAAA,EAAC,QAAA,EAAA,aAAA,EAAW,CAAA;AAAA,oBAC9B,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,WAAW,OAAA,CAAQ,MAAA;AAAA,QACnB,OAAA,EAAQ,UAAA;AAAA,QACR,UAAA,EAAY,GAAA;AAAA,QACZ,QAAA,EAAU,cAAA;AAAA,QACV,KAAA,EAAO,SAAS,IAAA,IAAQ,UAAA;AAAA,QACxB,WAAA;AAAA,QAEC,QAAA,EAAA,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,qBACf,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,WAAW,OAAA,CAAQ,QAAA;AAAA,YAEnB,KAAA,EAAO,EAAE,IAAA,IAAQ,UAAA;AAAA,YAEjB,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAU,MAAA,EAAO,IAAA,EAAK,OAAM,YAAA,EAAY,CAAA,CAAE,KAAA,EACnD,QAAA,EAAA,CAAA,CAAE,KAAA,EACL;AAAA,WAAA;AAAA,UALK,EAAE,IAAA,IAAQ;AAAA,SAOlB;AAAA;AAAA;AACH,GAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityCosts.esm.js","sources":["../../../src/components/EntityCosts/EntityCosts.tsx"],"sourcesContent":["/*\n * Copyright 2022 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 { useCallback, useEffect, useState } from 'react';\nimport { CostOverviewCard } from '../CostOverviewCard';\nimport {\n BillingDateProvider,\n ConfigProvider,\n CurrencyProvider,\n FilterProvider,\n GroupsProvider,\n LoadingProvider,\n ScrollProvider,\n useFilters,\n useLastCompleteBillingDate,\n useLoading,\n} from '../../hooks';\nimport { CostInsightsThemeProvider } from '../CostInsightsPage/CostInsightsThemeProvider';\nimport { Progress, WarningPanel } from '@backstage/core-components';\nimport { default as MaterialAlert } from '@material-ui/lab/Alert';\nimport { mapLoadingToProps } from '../CostInsightsPage/selector';\nimport { intervalsOf } from '../../utils/duration';\nimport { costInsightsApiRef } from '../../api';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { Cost, Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\n\nexport const EntityCostsCard = () => {\n const client = useApi(costInsightsApiRef);\n const { entity } = useEntity();\n\n const {\n loadingActions,\n loadingGroups,\n loadingBillingDate,\n loadingInitial,\n dispatchInitial,\n dispatchInsights,\n dispatchNone,\n } = useLoading(mapLoadingToProps);\n\n /* eslint-disable react-hooks/exhaustive-deps */\n // The dispatchLoading functions are derived from loading state using mapLoadingToProps, to\n // provide nicer props for the component. These are re-derived whenever loading state changes,\n // which causes an infinite loop as product panels load and re-trigger the useEffect below.\n // Since the functions don't change, we can memoize - but we trigger the same loop if we satisfy\n // exhaustive-deps by including the function itself in dependencies.\n\n const dispatchLoadingInitial = useCallback(dispatchInitial, []);\n const dispatchLoadingInsights = useCallback(dispatchInsights, []);\n const dispatchLoadingNone = useCallback(dispatchNone, []);\n /* eslint-enable react-hooks/exhaustive-deps */\n\n const lastCompleteBillingDate = useLastCompleteBillingDate();\n const [dailyCost, setDailyCost] = useState<Maybe<Cost>>(null);\n const [error, setError] = useState<Maybe<Error>>(null);\n const { pageFilters } = useFilters(p => p);\n\n useEffect(() => {\n async function getInsights() {\n setError(null);\n try {\n dispatchLoadingInsights(true);\n const intervals = intervalsOf(\n pageFilters.duration,\n lastCompleteBillingDate,\n 2,\n pageFilters.customDateRange,\n false, // Don't use comparison mode for entity costs\n );\n\n const fetchedDailyCost = await client.getCatalogEntityDailyCost!(\n stringifyEntityRef(entity),\n intervals,\n );\n setDailyCost(fetchedDailyCost);\n } catch (e) {\n setError(e);\n dispatchLoadingNone(loadingActions);\n } finally {\n dispatchLoadingNone(loadingActions);\n dispatchLoadingInitial(false);\n dispatchLoadingInsights(false);\n }\n }\n\n // Wait for metadata to finish loading\n if (!loadingBillingDate) {\n getInsights();\n }\n }, [\n client,\n entity,\n pageFilters,\n loadingActions,\n loadingGroups,\n loadingBillingDate,\n dispatchLoadingInsights,\n dispatchLoadingInitial,\n dispatchLoadingNone,\n lastCompleteBillingDate,\n ]);\n\n if (loadingInitial) {\n return <Progress />;\n }\n\n if (error) {\n return <MaterialAlert severity=\"error\">{error.message}</MaterialAlert>;\n }\n\n if (!dailyCost || !dailyCost.aggregation.length) {\n return <MaterialAlert severity=\"error\">No daily costs</MaterialAlert>;\n }\n\n return <CostOverviewCard dailyCostData={dailyCost} metricData={null} />;\n};\n\nexport const EntityCosts = () => {\n const client = useApi(costInsightsApiRef);\n\n if (!client.getCatalogEntityDailyCost) {\n return (\n <WarningPanel\n title=\"Could display costs for entity\"\n message=\"The getCatalogEntityDailyCost() method is not implemented by the costInsightsApi.\"\n />\n );\n }\n\n return (\n <CostInsightsThemeProvider>\n <ConfigProvider>\n <LoadingProvider>\n <GroupsProvider>\n <BillingDateProvider>\n <FilterProvider>\n <ScrollProvider>\n <CurrencyProvider>\n <EntityCostsCard />\n </CurrencyProvider>\n </ScrollProvider>\n </FilterProvider>\n </BillingDateProvider>\n </GroupsProvider>\n </LoadingProvider>\n </ConfigProvider>\n </CostInsightsThemeProvider>\n );\n};\n"],"names":["MaterialAlert"],"mappings":";;;;;;;;;;;;;;;;;;;;AAyCO,MAAM,kBAAkB,MAAM;AACnC,
|
|
1
|
+
{"version":3,"file":"EntityCosts.esm.js","sources":["../../../src/components/EntityCosts/EntityCosts.tsx"],"sourcesContent":["/*\n * Copyright 2022 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 { useCallback, useEffect, useState } from 'react';\nimport { CostOverviewCard } from '../CostOverviewCard';\nimport {\n BillingDateProvider,\n ConfigProvider,\n CurrencyProvider,\n FilterProvider,\n GroupsProvider,\n LoadingProvider,\n ScrollProvider,\n useFilters,\n useLastCompleteBillingDate,\n useLoading,\n} from '../../hooks';\nimport { CostInsightsThemeProvider } from '../CostInsightsPage/CostInsightsThemeProvider';\nimport { Progress, WarningPanel } from '@backstage/core-components';\nimport { default as MaterialAlert } from '@material-ui/lab/Alert';\nimport { mapLoadingToProps } from '../CostInsightsPage/selector';\nimport { intervalsOf } from '../../utils/duration';\nimport { costInsightsApiRef } from '../../api';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { Cost, Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\n\nexport const EntityCostsCard = () => {\n const client = useApi(costInsightsApiRef);\n const { entity } = useEntity();\n\n const {\n loadingActions,\n loadingGroups,\n loadingBillingDate,\n loadingInitial,\n dispatchInitial,\n dispatchInsights,\n dispatchNone,\n } = useLoading(mapLoadingToProps);\n\n /* eslint-disable react-hooks/exhaustive-deps */\n // The dispatchLoading functions are derived from loading state using mapLoadingToProps, to\n // provide nicer props for the component. These are re-derived whenever loading state changes,\n // which causes an infinite loop as product panels load and re-trigger the useEffect below.\n // Since the functions don't change, we can memoize - but we trigger the same loop if we satisfy\n // exhaustive-deps by including the function itself in dependencies.\n\n const dispatchLoadingInitial = useCallback(dispatchInitial, []);\n const dispatchLoadingInsights = useCallback(dispatchInsights, []);\n const dispatchLoadingNone = useCallback(dispatchNone, []);\n /* eslint-enable react-hooks/exhaustive-deps */\n\n const lastCompleteBillingDate = useLastCompleteBillingDate();\n const [dailyCost, setDailyCost] = useState<Maybe<Cost>>(null);\n const [error, setError] = useState<Maybe<Error>>(null);\n const { pageFilters } = useFilters(p => p);\n\n useEffect(() => {\n async function getInsights() {\n setError(null);\n try {\n dispatchLoadingInsights(true);\n const intervals = intervalsOf(\n pageFilters.duration,\n lastCompleteBillingDate,\n 2,\n pageFilters.customDateRange,\n false, // Don't use comparison mode for entity costs\n );\n\n const fetchedDailyCost = await client.getCatalogEntityDailyCost!(\n stringifyEntityRef(entity),\n intervals,\n );\n setDailyCost(fetchedDailyCost);\n } catch (e) {\n setError(e);\n dispatchLoadingNone(loadingActions);\n } finally {\n dispatchLoadingNone(loadingActions);\n dispatchLoadingInitial(false);\n dispatchLoadingInsights(false);\n }\n }\n\n // Wait for metadata to finish loading\n if (!loadingBillingDate) {\n getInsights();\n }\n }, [\n client,\n entity,\n pageFilters,\n loadingActions,\n loadingGroups,\n loadingBillingDate,\n dispatchLoadingInsights,\n dispatchLoadingInitial,\n dispatchLoadingNone,\n lastCompleteBillingDate,\n ]);\n\n if (loadingInitial) {\n return <Progress />;\n }\n\n if (error) {\n return <MaterialAlert severity=\"error\">{error.message}</MaterialAlert>;\n }\n\n if (!dailyCost || !dailyCost.aggregation.length) {\n return <MaterialAlert severity=\"error\">No daily costs</MaterialAlert>;\n }\n\n return <CostOverviewCard dailyCostData={dailyCost} metricData={null} />;\n};\n\nexport const EntityCosts = () => {\n const client = useApi(costInsightsApiRef);\n\n if (!client.getCatalogEntityDailyCost) {\n return (\n <WarningPanel\n title=\"Could display costs for entity\"\n message=\"The getCatalogEntityDailyCost() method is not implemented by the costInsightsApi.\"\n />\n );\n }\n\n return (\n <CostInsightsThemeProvider>\n <ConfigProvider>\n <LoadingProvider>\n <GroupsProvider>\n <BillingDateProvider>\n <FilterProvider>\n <ScrollProvider>\n <CurrencyProvider>\n <EntityCostsCard />\n </CurrencyProvider>\n </ScrollProvider>\n </FilterProvider>\n </BillingDateProvider>\n </GroupsProvider>\n </LoadingProvider>\n </ConfigProvider>\n </CostInsightsThemeProvider>\n );\n};\n"],"names":["MaterialAlert"],"mappings":";;;;;;;;;;;;;;;;;;;;AAyCO,MAAM,kBAAkB,MAAM;AACnC,EAAA,MAAM,MAAA,GAAS,OAAO,kBAAkB,CAAA;AACxC,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,SAAA,EAAU;AAE7B,EAAA,MAAM;AAAA,IACJ,cAAA;AAAA,IACA,aAAA;AAAA,IACA,kBAAA;AAAA,IACA,cAAA;AAAA,IACA,eAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACF,GAAI,WAAW,iBAAiB,CAAA;AAShC,EAAA,MAAM,sBAAA,GAAyB,WAAA,CAAY,eAAA,EAAiB,EAAE,CAAA;AAC9D,EAAA,MAAM,uBAAA,GAA0B,WAAA,CAAY,gBAAA,EAAkB,EAAE,CAAA;AAChE,EAAA,MAAM,mBAAA,GAAsB,WAAA,CAAY,YAAA,EAAc,EAAE,CAAA;AAGxD,EAAA,MAAM,0BAA0B,0BAAA,EAA2B;AAC3D,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAsB,IAAI,CAAA;AAC5D,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,EAAE,WAAA,EAAY,GAAI,UAAA,CAAW,OAAK,CAAC,CAAA;AAEzC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,eAAe,WAAA,GAAc;AAC3B,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA,IAAI;AACF,QAAA,uBAAA,CAAwB,IAAI,CAAA;AAC5B,QAAA,MAAM,SAAA,GAAY,WAAA;AAAA,UAChB,WAAA,CAAY,QAAA;AAAA,UACZ,uBAAA;AAAA,UACA,CAAA;AAAA,UACA,WAAA,CAAY,eAAA;AAAA,UACZ;AAAA;AAAA,SACF;AAEA,QAAA,MAAM,gBAAA,GAAmB,MAAM,MAAA,CAAO,yBAAA;AAAA,UACpC,mBAAmB,MAAM,CAAA;AAAA,UACzB;AAAA,SACF;AACA,QAAA,YAAA,CAAa,gBAAgB,CAAA;AAAA,MAC/B,SAAS,CAAA,EAAG;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AACV,QAAA,mBAAA,CAAoB,cAAc,CAAA;AAAA,MACpC,CAAA,SAAE;AACA,QAAA,mBAAA,CAAoB,cAAc,CAAA;AAClC,QAAA,sBAAA,CAAuB,KAAK,CAAA;AAC5B,QAAA,uBAAA,CAAwB,KAAK,CAAA;AAAA,MAC/B;AAAA,IACF;AAGA,IAAA,IAAI,CAAC,kBAAA,EAAoB;AACvB,MAAA,WAAA,EAAY;AAAA,IACd;AAAA,EACF,CAAA,EAAG;AAAA,IACD,MAAA;AAAA,IACA,MAAA;AAAA,IACA,WAAA;AAAA,IACA,cAAA;AAAA,IACA,aAAA;AAAA,IACA,kBAAA;AAAA,IACA,uBAAA;AAAA,IACA,sBAAA;AAAA,IACA,mBAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,2BAAQ,QAAA,EAAA,EAAS,CAAA;AAAA,EACnB;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBAAO,GAAA,CAACA,KAAA,EAAA,EAAc,QAAA,EAAS,OAAA,EAAS,gBAAM,OAAA,EAAQ,CAAA;AAAA,EACxD;AAEA,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,SAAA,CAAU,YAAY,MAAA,EAAQ;AAC/C,IAAA,uBAAO,GAAA,CAACA,KAAA,EAAA,EAAc,QAAA,EAAS,OAAA,EAAQ,QAAA,EAAA,gBAAA,EAAc,CAAA;AAAA,EACvD;AAEA,EAAA,uBAAO,GAAA,CAAC,gBAAA,EAAA,EAAiB,aAAA,EAAe,SAAA,EAAW,YAAY,IAAA,EAAM,CAAA;AACvE;AAEO,MAAM,cAAc,MAAM;AAC/B,EAAA,MAAM,MAAA,GAAS,OAAO,kBAAkB,CAAA;AAExC,EAAA,IAAI,CAAC,OAAO,yBAAA,EAA2B;AACrC,IAAA,uBACE,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAM,gCAAA;AAAA,QACN,OAAA,EAAQ;AAAA;AAAA,KACV;AAAA,EAEJ;AAEA,EAAA,uBACE,GAAA,CAAC,yBAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,cAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,mBACC,QAAA,kBAAA,GAAA,CAAC,cAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,mBAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,cAAA,EAAA,EACC,8BAAC,cAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,gBAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,eAAA,EAAA,EAAgB,CAAA,EACnB,CAAA,EACF,CAAA,EACF,CAAA,EACF,CAAA,EACF,CAAA,EACF,CAAA,EACF,CAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
package/dist/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LabelDataflowInstructionsPage.esm.js","sources":["../../../src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.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 Typography from '@material-ui/core/Typography';\nimport { AlertInstructionsLayout } from '../AlertInstructionsLayout';\nimport { CodeSnippet, Link } from '@backstage/core-components';\n\nexport const LabelDataflowInstructionsPage = () => {\n return (\n <AlertInstructionsLayout title=\"Investigating Growth\">\n <Typography variant=\"h1\">Labeling Dataflow Jobs</Typography>\n <Typography paragraph>\n Labels in Google Cloud Platform are key-value pairs that can be added to\n most types of cloud resources. Since these labels are also exported in\n billing data, adding labels allows a granular breakdown of cloud cost by\n software entity.\n </Typography>\n <Typography paragraph>\n In Cloud Dataflow, labels can be added to a job either programmatically\n or via the command-line when launching a job. Note that GCP has{' '}\n <Link to=\"https://cloud.google.com/compute/docs/labeling-resources#restrictions\">\n restrictions\n </Link>{' '}\n on the length and characters that can be used in labels.\n </Typography>\n <Typography paragraph>\n Labels are not retroactive, so cost tracking is only possible from when\n the labels are first added to a Dataflow job.\n </Typography>\n\n <Box mt={4}>\n <Typography variant=\"h3\">DataflowPipelineOptions</Typography>\n <Typography paragraph>\n Dataflow jobs using Beam's{' '}\n <Link to=\"https://beam.apache.org/releases/javadoc/2.3.0/org/apache/beam/runners/dataflow/options/DataflowPipelineOptions.html\">\n DataflowPipelineOptions\n </Link>{' '}\n directly can use the <b>setLabels</b> function to add one or more\n labels:\n <CodeSnippet\n language=\"java\"\n text={`private DataflowPipelineOptions options = PipelineOptionsFactory.fromArgs(args).as(DataflowPipelineOptionsImpl.class); \noptions.setLabels(ImmutableMap.of(\"job-id\", \"my-dataflow-job\"));`}\n />\n </Typography>\n <Typography paragraph>\n Dataflow jobs using Scio can similarly set options on the ScioContext:\n <CodeSnippet\n language=\"scala\"\n text={`val (sc: ScioContext, args: Args) = ContextAndArgs(cmdLineArgs)\nsc.optionsAs[DataflowPipelineOptions].setLabels(Map(\"job-id\" -> \"my-dataflow-job\").asJava)`}\n />\n </Typography>\n </Box>\n\n <Box mt={4}>\n <Typography variant=\"h3\">Command-line</Typography>\n <Typography paragraph>\n Dataflow jobs launched from the command-line can add labels as an\n argument:\n <CodeSnippet\n language=\"shell\"\n text={`--labels={\"job-id\": \"my-dataflow-job\", \"date-argument\": \"2020-09-16\"}`}\n />\n </Typography>\n <Typography paragraph>\n For more information on specifying options, see the{' '}\n <Link to=\"https://cloud.google.com/dataflow/docs/guides/specifying-exec-params\">\n Dataflow documentation\n </Link>{' '}\n or{' '}\n <Link to=\"https://spotify.github.io/scio/api/com/spotify/scio/ScioContext.html\">\n Scio Scaladoc\n </Link>\n .\n </Typography>\n </Box>\n </AlertInstructionsLayout>\n );\n};\n"],"names":[],"mappings":";;;;;;AAqBO,MAAM,gCAAgC,MAAM;AACjD,
|
|
1
|
+
{"version":3,"file":"LabelDataflowInstructionsPage.esm.js","sources":["../../../src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.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 Typography from '@material-ui/core/Typography';\nimport { AlertInstructionsLayout } from '../AlertInstructionsLayout';\nimport { CodeSnippet, Link } from '@backstage/core-components';\n\nexport const LabelDataflowInstructionsPage = () => {\n return (\n <AlertInstructionsLayout title=\"Investigating Growth\">\n <Typography variant=\"h1\">Labeling Dataflow Jobs</Typography>\n <Typography paragraph>\n Labels in Google Cloud Platform are key-value pairs that can be added to\n most types of cloud resources. Since these labels are also exported in\n billing data, adding labels allows a granular breakdown of cloud cost by\n software entity.\n </Typography>\n <Typography paragraph>\n In Cloud Dataflow, labels can be added to a job either programmatically\n or via the command-line when launching a job. Note that GCP has{' '}\n <Link to=\"https://cloud.google.com/compute/docs/labeling-resources#restrictions\">\n restrictions\n </Link>{' '}\n on the length and characters that can be used in labels.\n </Typography>\n <Typography paragraph>\n Labels are not retroactive, so cost tracking is only possible from when\n the labels are first added to a Dataflow job.\n </Typography>\n\n <Box mt={4}>\n <Typography variant=\"h3\">DataflowPipelineOptions</Typography>\n <Typography paragraph>\n Dataflow jobs using Beam's{' '}\n <Link to=\"https://beam.apache.org/releases/javadoc/2.3.0/org/apache/beam/runners/dataflow/options/DataflowPipelineOptions.html\">\n DataflowPipelineOptions\n </Link>{' '}\n directly can use the <b>setLabels</b> function to add one or more\n labels:\n <CodeSnippet\n language=\"java\"\n text={`private DataflowPipelineOptions options = PipelineOptionsFactory.fromArgs(args).as(DataflowPipelineOptionsImpl.class); \noptions.setLabels(ImmutableMap.of(\"job-id\", \"my-dataflow-job\"));`}\n />\n </Typography>\n <Typography paragraph>\n Dataflow jobs using Scio can similarly set options on the ScioContext:\n <CodeSnippet\n language=\"scala\"\n text={`val (sc: ScioContext, args: Args) = ContextAndArgs(cmdLineArgs)\nsc.optionsAs[DataflowPipelineOptions].setLabels(Map(\"job-id\" -> \"my-dataflow-job\").asJava)`}\n />\n </Typography>\n </Box>\n\n <Box mt={4}>\n <Typography variant=\"h3\">Command-line</Typography>\n <Typography paragraph>\n Dataflow jobs launched from the command-line can add labels as an\n argument:\n <CodeSnippet\n language=\"shell\"\n text={`--labels={\"job-id\": \"my-dataflow-job\", \"date-argument\": \"2020-09-16\"}`}\n />\n </Typography>\n <Typography paragraph>\n For more information on specifying options, see the{' '}\n <Link to=\"https://cloud.google.com/dataflow/docs/guides/specifying-exec-params\">\n Dataflow documentation\n </Link>{' '}\n or{' '}\n <Link to=\"https://spotify.github.io/scio/api/com/spotify/scio/ScioContext.html\">\n Scio Scaladoc\n </Link>\n .\n </Typography>\n </Box>\n </AlertInstructionsLayout>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LegendItem.esm.js","sources":["../../../src/components/LegendItem/LegendItem.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 { PropsWithChildren } from 'react';\nimport Box from '@material-ui/core/Box';\nimport Typography from '@material-ui/core/Typography';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport LensIcon from '@material-ui/icons/Lens';\nimport HelpOutlineOutlinedIcon from '@material-ui/icons/HelpOutlineOutlined';\nimport { useCostGrowthLegendStyles } from '../../utils/styles';\n\n/** @public */\nexport type LegendItemProps = {\n title: string;\n tooltipText?: string;\n markerColor?: string;\n};\n\n/** @public */\nexport const LegendItem = (props: PropsWithChildren<LegendItemProps>) => {\n const { title, tooltipText, markerColor, children } = props;\n\n const classes = useCostGrowthLegendStyles();\n\n return (\n <Box display=\"flex\" flexDirection=\"column\">\n <Box\n minHeight={25}\n display=\"flex\"\n flexDirection=\"row\"\n alignItems=\"center\"\n >\n {markerColor && (\n <div className={classes.marker}>\n <LensIcon style={{ fontSize: '1em', fill: markerColor }} />\n </div>\n )}\n <Typography className={classes.title} variant=\"overline\">\n {title}\n </Typography>\n {tooltipText && (\n <Tooltip\n classes={{ tooltip: classes.tooltip }}\n title={\n <Typography className={classes.tooltipText}>\n {tooltipText}\n </Typography>\n }\n placement=\"top-start\"\n >\n <Typography\n component=\"span\"\n role=\"img\"\n aria-label=\"help\"\n className={classes.helpIcon}\n >\n <HelpOutlineOutlinedIcon fontSize=\"small\" />\n </Typography>\n </Tooltip>\n )}\n </Box>\n <Box marginLeft={markerColor ? '1.5em' : 0}>\n <Typography className={classes.h5} variant=\"h5\">\n {children}\n </Typography>\n </Box>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"LegendItem.esm.js","sources":["../../../src/components/LegendItem/LegendItem.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 { PropsWithChildren } from 'react';\nimport Box from '@material-ui/core/Box';\nimport Typography from '@material-ui/core/Typography';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport LensIcon from '@material-ui/icons/Lens';\nimport HelpOutlineOutlinedIcon from '@material-ui/icons/HelpOutlineOutlined';\nimport { useCostGrowthLegendStyles } from '../../utils/styles';\n\n/** @public */\nexport type LegendItemProps = {\n title: string;\n tooltipText?: string;\n markerColor?: string;\n};\n\n/** @public */\nexport const LegendItem = (props: PropsWithChildren<LegendItemProps>) => {\n const { title, tooltipText, markerColor, children } = props;\n\n const classes = useCostGrowthLegendStyles();\n\n return (\n <Box display=\"flex\" flexDirection=\"column\">\n <Box\n minHeight={25}\n display=\"flex\"\n flexDirection=\"row\"\n alignItems=\"center\"\n >\n {markerColor && (\n <div className={classes.marker}>\n <LensIcon style={{ fontSize: '1em', fill: markerColor }} />\n </div>\n )}\n <Typography className={classes.title} variant=\"overline\">\n {title}\n </Typography>\n {tooltipText && (\n <Tooltip\n classes={{ tooltip: classes.tooltip }}\n title={\n <Typography className={classes.tooltipText}>\n {tooltipText}\n </Typography>\n }\n placement=\"top-start\"\n >\n <Typography\n component=\"span\"\n role=\"img\"\n aria-label=\"help\"\n className={classes.helpIcon}\n >\n <HelpOutlineOutlinedIcon fontSize=\"small\" />\n </Typography>\n </Tooltip>\n )}\n </Box>\n <Box marginLeft={markerColor ? '1.5em' : 0}>\n <Typography className={classes.h5} variant=\"h5\">\n {children}\n </Typography>\n </Box>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAgCO,MAAM,UAAA,GAAa,CAAC,KAAA,KAA8C;AACvE,EAAA,MAAM,EAAE,KAAA,EAAO,WAAA,EAAa,WAAA,EAAa,UAAS,GAAI,KAAA;AAEtD,EAAA,MAAM,UAAU,yBAAA,EAA0B;AAE1C,EAAA,uBACE,IAAA,CAAC,GAAA,EAAA,EAAI,OAAA,EAAQ,MAAA,EAAO,eAAc,QAAA,EAChC,QAAA,EAAA;AAAA,oBAAA,IAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,EAAA;AAAA,QACX,OAAA,EAAQ,MAAA;AAAA,QACR,aAAA,EAAc,KAAA;AAAA,QACd,UAAA,EAAW,QAAA;AAAA,QAEV,QAAA,EAAA;AAAA,UAAA,WAAA,oBACC,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,QACtB,QAAA,kBAAA,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAO,EAAE,QAAA,EAAU,KAAA,EAAO,IAAA,EAAM,WAAA,IAAe,CAAA,EAC3D,CAAA;AAAA,8BAED,UAAA,EAAA,EAAW,SAAA,EAAW,QAAQ,KAAA,EAAO,OAAA,EAAQ,YAC3C,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,UACC,WAAA,oBACC,GAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAS,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ;AAAA,cACpC,uBACE,GAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,OAAA,CAAQ,aAC5B,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,cAEF,SAAA,EAAU,WAAA;AAAA,cAEV,QAAA,kBAAA,GAAA;AAAA,gBAAC,UAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAU,MAAA;AAAA,kBACV,IAAA,EAAK,KAAA;AAAA,kBACL,YAAA,EAAW,MAAA;AAAA,kBACX,WAAW,OAAA,CAAQ,QAAA;AAAA,kBAEnB,QAAA,kBAAA,GAAA,CAAC,uBAAA,EAAA,EAAwB,QAAA,EAAS,OAAA,EAAQ;AAAA;AAAA;AAC5C;AAAA;AACF;AAAA;AAAA,KAEJ;AAAA,oBACA,GAAA,CAAC,GAAA,EAAA,EAAI,UAAA,EAAY,WAAA,GAAc,UAAU,CAAA,EACvC,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,OAAA,CAAQ,EAAA,EAAI,OAAA,EAAQ,IAAA,EACxC,UACH,CAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
|