From 474345a484b6b780ee8a9a750403c143739fa54a Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Wed, 28 Oct 2020 10:38:34 -0400 Subject: [PATCH 01/20] migrate currency utils --- .../components/CostGrowth/CostGrowth.test.tsx | 11 ++- .../ProjectGrowthAlertCard.test.tsx | 3 +- plugins/cost-insights/src/hooks/useConfig.tsx | 3 +- .../cost-insights/src/hooks/useCurrency.tsx | 3 +- plugins/cost-insights/src/hooks/useGroups.tsx | 2 + plugins/cost-insights/src/types/Currency.ts | 55 --------------- plugins/cost-insights/src/types/Loading.ts | 47 ------------- plugins/cost-insights/src/utils/currency.ts | 69 +++++++++++++++++++ plugins/cost-insights/src/utils/loading.ts | 48 +++++++++++++ 9 files changed, 130 insertions(+), 111 deletions(-) create mode 100644 plugins/cost-insights/src/utils/currency.ts create mode 100644 plugins/cost-insights/src/utils/loading.ts diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx index ed81f657c5..2cefcbba1e 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx @@ -18,13 +18,12 @@ import React, { PropsWithChildren } from 'react'; import { renderInTestApp } from '@backstage/test-utils'; import { CostGrowth } from './CostGrowth'; import { - defaultCurrencies, Currency, - CurrencyType, Duration, findAlways, } from '../../types'; import { MockConfigProvider, MockCurrencyProvider } from '../../utils/tests'; +import { defaultCurrencies, CurrencyType } from '../../utils/currency'; const engineers = findAlways(defaultCurrencies, c => c.kind === null); const usd = findAlways(defaultCurrencies, c => c.kind === CurrencyType.USD); @@ -41,10 +40,10 @@ const MockContext = ({ currency: Currency; engineerCost: number; }>) => ( - - {children} - -); + + {children} + + ); describe.each` engineerCost | ratio | amount | expected diff --git a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx index 4b5da409a4..3e2fc8d32e 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx @@ -23,7 +23,8 @@ import { MockConfigProvider, MockBillingDateProvider, } from '../../utils/tests'; -import { AlertCost, defaultCurrencies, findAlways } from '../../types'; +import { AlertCost, findAlways } from '../../types'; +import { defaultCurrencies } from '../../utils/currency'; const engineers = findAlways(defaultCurrencies, c => c.kind === null); diff --git a/plugins/cost-insights/src/hooks/useConfig.tsx b/plugins/cost-insights/src/hooks/useConfig.tsx index f63b9228a9..450ab545ac 100644 --- a/plugins/cost-insights/src/hooks/useConfig.tsx +++ b/plugins/cost-insights/src/hooks/useConfig.tsx @@ -23,9 +23,10 @@ import React, { } from 'react'; import { configApiRef, useApi } from '@backstage/core'; import { Config as BackstageConfig } from '@backstage/config'; -import { Currency, defaultCurrencies, Icon, Metric, Product } from '../types'; +import { Currency, Icon, Metric, Product } from '../types'; import { getIcon } from '../utils/navigation'; import { validateMetrics } from '../utils/config'; +import { defaultCurrencies } from '../utils/currency'; /* * Config schema 2020-10-15 diff --git a/plugins/cost-insights/src/hooks/useCurrency.tsx b/plugins/cost-insights/src/hooks/useCurrency.tsx index 34a4f54d5f..b5079d37f1 100644 --- a/plugins/cost-insights/src/hooks/useCurrency.tsx +++ b/plugins/cost-insights/src/hooks/useCurrency.tsx @@ -20,7 +20,8 @@ import React, { useContext, PropsWithChildren, } from 'react'; -import { Currency, defaultCurrencies, findAlways } from '../types'; +import { Currency, findAlways } from '../types'; +import { defaultCurrencies } from '../utils/currency'; export type CurrencyContextProps = { currency: Currency; diff --git a/plugins/cost-insights/src/hooks/useGroups.tsx b/plugins/cost-insights/src/hooks/useGroups.tsx index 13cec25017..f7adc84a57 100644 --- a/plugins/cost-insights/src/hooks/useGroups.tsx +++ b/plugins/cost-insights/src/hooks/useGroups.tsx @@ -26,6 +26,8 @@ import { costInsightsApiRef } from '../api'; import { MapLoadingToProps, useLoading } from './useLoading'; import { DefaultLoadingAction, Group, Maybe } from '../types'; +console.log(DefaultLoadingAction) + type GroupsProviderLoadingProps = { dispatchLoadingGroups: (isLoading: boolean) => void; }; diff --git a/plugins/cost-insights/src/types/Currency.ts b/plugins/cost-insights/src/types/Currency.ts index 633e405893..16ba432be8 100644 --- a/plugins/cost-insights/src/types/Currency.ts +++ b/plugins/cost-insights/src/types/Currency.ts @@ -13,15 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Duration } from './Duration'; -import { assertNever } from './Maybe'; - -export enum CurrencyType { - USD = 'USD', - CarbonOffsetTons = 'CARBON_OFFSET_TONS', - Beers = 'BEERS', - IceCream = 'PINTS_OF_ICE_CREAM', -} export interface Currency { kind: string | null; @@ -30,49 +21,3 @@ export interface Currency { prefix?: string; rate?: number; } - -export const rateOf = (cost: number, duration: Duration) => { - switch (duration) { - case Duration.P1M: - case Duration.P30D: - return cost / 12; - case Duration.P90D: - case Duration.P3M: - return cost / 4; - default: - return assertNever(duration); - } -}; - -export const defaultCurrencies: Currency[] = [ - { - kind: null, - label: 'Engineers 🛠', - unit: 'engineer', - }, - { - kind: CurrencyType.USD, - label: 'US Dollars 💵', - unit: 'dollar', - prefix: '$', - rate: 1, - }, - { - kind: CurrencyType.CarbonOffsetTons, - label: 'Carbon Offset Tons ♻️⚖️s', - unit: 'carbon offset ton', - rate: 3.5, - }, - { - kind: CurrencyType.Beers, - label: 'Beers 🍺', - unit: 'beer', - rate: 4.5, - }, - { - kind: CurrencyType.IceCream, - label: 'Pints of Ice Cream 🍦', - unit: 'ice cream pint', - rate: 5.5, - }, -]; diff --git a/plugins/cost-insights/src/types/Loading.ts b/plugins/cost-insights/src/types/Loading.ts index 8bc0c4eaef..741453369c 100644 --- a/plugins/cost-insights/src/types/Loading.ts +++ b/plugins/cost-insights/src/types/Loading.ts @@ -15,50 +15,3 @@ */ export type Loading = Record; - -export enum DefaultLoadingAction { - UserGroups = 'user-groups', - LastCompleteBillingDate = 'billing-date', - CostInsightsInitial = 'cost-insights-initial', - CostInsightsPage = 'cost-insights-page', -} - -export const INITIAL_LOADING_ACTIONS = [ - DefaultLoadingAction.UserGroups, - DefaultLoadingAction.CostInsightsInitial, -]; - -export const getDefaultState = (loadingActions: string[]): Loading => { - return loadingActions.reduce( - (defaultState, action) => ({ ...defaultState, [action]: true }), - {}, - ); -}; - -export const getResetState = (loadingActions: string[]): Loading => { - return loadingActions.reduce( - (defaultState, action) => ({ ...defaultState, [action]: false }), - {}, - ); -}; - -export const getResetStateWithoutInitial = ( - loadingActions: string[], -): Loading => { - return loadingActions.reduce((defaultState, action) => { - const loadingActionState = (INITIAL_LOADING_ACTIONS as string[]).includes( - action, - ) - ? false - : true; - return { ...defaultState, [action]: loadingActionState }; - }, {}); -}; - -export function getLoadingActions(products: string[]): string[] { - return ([ - DefaultLoadingAction.UserGroups, - DefaultLoadingAction.CostInsightsInitial, - DefaultLoadingAction.CostInsightsPage, - ] as string[]).concat(products); -} diff --git a/plugins/cost-insights/src/utils/currency.ts b/plugins/cost-insights/src/utils/currency.ts new file mode 100644 index 0000000000..c15af4d80d --- /dev/null +++ b/plugins/cost-insights/src/utils/currency.ts @@ -0,0 +1,69 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { assertNever, Currency, Duration } from '../types'; + +export enum CurrencyType { + USD = 'USD', + CarbonOffsetTons = 'CARBON_OFFSET_TONS', + Beers = 'BEERS', + IceCream = 'PINTS_OF_ICE_CREAM', +} + +export const rateOf = (cost: number, duration: Duration) => { + switch (duration) { + case Duration.P1M: + case Duration.P30D: + return cost / 12; + case Duration.P90D: + case Duration.P3M: + return cost / 4; + default: + return assertNever(duration); + } +}; + +export const defaultCurrencies: Currency[] = [ + { + kind: null, + label: 'Engineers 🛠', + unit: 'engineer', + }, + { + kind: CurrencyType.USD, + label: 'US Dollars 💵', + unit: 'dollar', + prefix: '$', + rate: 1, + }, + { + kind: CurrencyType.CarbonOffsetTons, + label: 'Carbon Offset Tons ♻️⚖️s', + unit: 'carbon offset ton', + rate: 3.5, + }, + { + kind: CurrencyType.Beers, + label: 'Beers 🍺', + unit: 'beer', + rate: 4.5, + }, + { + kind: CurrencyType.IceCream, + label: 'Pints of Ice Cream 🍦', + unit: 'ice cream pint', + rate: 5.5, + }, +]; diff --git a/plugins/cost-insights/src/utils/loading.ts b/plugins/cost-insights/src/utils/loading.ts new file mode 100644 index 0000000000..7a0225154f --- /dev/null +++ b/plugins/cost-insights/src/utils/loading.ts @@ -0,0 +1,48 @@ +import { Loading } from '../types'; + +export enum DefaultLoadingAction { + UserGroups = 'user-groups', + LastCompleteBillingDate = 'billing-date', + CostInsightsInitial = 'cost-insights-initial', + CostInsightsPage = 'cost-insights-page', +} + +export const INITIAL_LOADING_ACTIONS = [ + DefaultLoadingAction.UserGroups, + DefaultLoadingAction.CostInsightsInitial, +]; + +export const getDefaultState = (loadingActions: string[]): Loading => { + return loadingActions.reduce( + (defaultState, action) => ({ ...defaultState, [action]: true }), + {}, + ); +}; + +export const getResetState = (loadingActions: string[]): Loading => { + return loadingActions.reduce( + (defaultState, action) => ({ ...defaultState, [action]: false }), + {}, + ); +}; + +export const getResetStateWithoutInitial = ( + loadingActions: string[], +): Loading => { + return loadingActions.reduce((defaultState, action) => { + const loadingActionState = (INITIAL_LOADING_ACTIONS as string[]).includes( + action, + ) + ? false + : true; + return { ...defaultState, [action]: loadingActionState }; + }, {}); +}; + +export function getLoadingActions(products: string[]): string[] { + return ([ + DefaultLoadingAction.UserGroups, + DefaultLoadingAction.CostInsightsInitial, + DefaultLoadingAction.CostInsightsPage, + ] as string[]).concat(products); +} From d20428775c7b3800dbf846afcd6154747465379e Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Wed, 28 Oct 2020 10:51:05 -0400 Subject: [PATCH 02/20] migrate loading utils --- .../src/components/CostInsightsPage/selector.tsx | 2 +- .../src/components/CostInsightsTabs/selector.ts | 3 ++- plugins/cost-insights/src/hooks/useGroups.tsx | 5 ++--- .../cost-insights/src/hooks/useLastCompleteBillingDate.tsx | 3 ++- plugins/cost-insights/src/hooks/useLoading.tsx | 6 +++--- plugins/cost-insights/src/utils/mockData.ts | 6 ++++-- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/plugins/cost-insights/src/components/CostInsightsPage/selector.tsx b/plugins/cost-insights/src/components/CostInsightsPage/selector.tsx index a73c0ff975..664c90726a 100644 --- a/plugins/cost-insights/src/components/CostInsightsPage/selector.tsx +++ b/plugins/cost-insights/src/components/CostInsightsPage/selector.tsx @@ -18,7 +18,7 @@ import { getResetState, DefaultLoadingAction, getResetStateWithoutInitial, -} from '../../types'; +} from '../../utils/loading'; type CostInsightsPageLoadingProps = { loadingActions: Array; diff --git a/plugins/cost-insights/src/components/CostInsightsTabs/selector.ts b/plugins/cost-insights/src/components/CostInsightsTabs/selector.ts index 3aa53cce21..35100338ac 100644 --- a/plugins/cost-insights/src/components/CostInsightsTabs/selector.ts +++ b/plugins/cost-insights/src/components/CostInsightsTabs/selector.ts @@ -16,7 +16,8 @@ import { MapFiltersToProps } from '../../hooks/useFilters'; import { MapLoadingToProps } from '../../hooks/useLoading'; -import { Group, PageFilters, getResetStateWithoutInitial } from '../../types'; +import { Group, PageFilters } from '../../types'; +import { getResetStateWithoutInitial } from '../../utils/loading'; type CostInsightsTabsFilterProps = PageFilters & { setGroup: (group: Group) => void; diff --git a/plugins/cost-insights/src/hooks/useGroups.tsx b/plugins/cost-insights/src/hooks/useGroups.tsx index f7adc84a57..50444f2915 100644 --- a/plugins/cost-insights/src/hooks/useGroups.tsx +++ b/plugins/cost-insights/src/hooks/useGroups.tsx @@ -24,9 +24,8 @@ import { Alert } from '@material-ui/lab'; import { useApi, identityApiRef } from '@backstage/core'; import { costInsightsApiRef } from '../api'; import { MapLoadingToProps, useLoading } from './useLoading'; -import { DefaultLoadingAction, Group, Maybe } from '../types'; - -console.log(DefaultLoadingAction) +import { Group, Maybe } from '../types'; +import { DefaultLoadingAction } from '../utils/loading'; type GroupsProviderLoadingProps = { dispatchLoadingGroups: (isLoading: boolean) => void; diff --git a/plugins/cost-insights/src/hooks/useLastCompleteBillingDate.tsx b/plugins/cost-insights/src/hooks/useLastCompleteBillingDate.tsx index 33d037267d..d2ee43980f 100644 --- a/plugins/cost-insights/src/hooks/useLastCompleteBillingDate.tsx +++ b/plugins/cost-insights/src/hooks/useLastCompleteBillingDate.tsx @@ -25,7 +25,8 @@ import { Alert } from '@material-ui/lab'; import { useApi } from '@backstage/core'; import { costInsightsApiRef } from '../api'; import { MapLoadingToProps, useLoading } from './useLoading'; -import { DefaultLoadingAction, Maybe } from '../types'; +import { DefaultLoadingAction } from '../utils/loading'; +import { Maybe } from '../types'; type BillingDateProviderLoadingProps = { dispatchLoadingBillingDate: (isLoading: boolean) => void; diff --git a/plugins/cost-insights/src/hooks/useLoading.tsx b/plugins/cost-insights/src/hooks/useLoading.tsx index 31402ba0d1..261f1e4077 100644 --- a/plugins/cost-insights/src/hooks/useLoading.tsx +++ b/plugins/cost-insights/src/hooks/useLoading.tsx @@ -26,12 +26,12 @@ import React, { useState, } from 'react'; import { Backdrop, CircularProgress } from '@material-ui/core'; +import { Loading } from '../types'; import { DefaultLoadingAction, getDefaultState, getLoadingActions, - Loading, -} from '../types'; +} from '../utils/loading'; import { useBackdropStyles as useStyles } from '../utils/styles'; import { useConfig } from './useConfig'; @@ -68,7 +68,7 @@ export const LoadingProvider = ({ children }: PropsWithChildren<{}>) => { // Initial page loading is handled by progress bar setBackdropVisible( !state[DefaultLoadingAction.CostInsightsInitial] && - Object.values(state).some(l => l), + Object.values(state).some(l => l), ); } displayLoadingBackdrop(); diff --git a/plugins/cost-insights/src/utils/mockData.ts b/plugins/cost-insights/src/utils/mockData.ts index 11c70eee25..c070f07e29 100644 --- a/plugins/cost-insights/src/utils/mockData.ts +++ b/plugins/cost-insights/src/utils/mockData.ts @@ -15,11 +15,9 @@ */ import { - DefaultLoadingAction, Duration, Entity, findAlways, - getDefaultState as getDefaultLoadingState, Product, ProductCost, ProductFilters, @@ -27,6 +25,10 @@ import { UnlabeledDataflowAlertProject, UnlabeledDataflowData, } from '../types'; +import { + DefaultLoadingAction, + getDefaultState as getDefaultLoadingState, +} from '../utils/loading'; import { Config } from '@backstage/config'; import { ConfigApi } from '@backstage/core'; From 86baf0327401b51969cb3b5ded11e86a9bfa29c7 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Wed, 28 Oct 2020 11:02:48 -0400 Subject: [PATCH 03/20] migrate assertion utils --- .../src/components/BarChart/BarChart.tsx | 2 +- .../components/CostGrowth/CostGrowth.test.tsx | 7 +-- .../CostInsightsNavigation.tsx | 10 ++--- .../CostOverviewCard/CostOverviewCard.tsx | 2 +- .../CurrencySelect/CurrencySelect.tsx | 4 +- .../components/PeriodSelect/PeriodSelect.tsx | 3 +- .../ProductInsightsCard/selector.ts | 3 +- .../ProjectGrowthAlertCard.test.tsx | 3 +- .../ResourceGrowthBarChartLegend.test.tsx | 4 +- .../cost-insights/src/hooks/useCurrency.tsx | 3 +- plugins/cost-insights/src/types/Duration.ts | 2 +- plugins/cost-insights/src/types/Maybe.ts | 30 +------------ plugins/cost-insights/src/utils/assert.ts | 44 +++++++++++++++++++ plugins/cost-insights/src/utils/currency.ts | 3 +- plugins/cost-insights/src/utils/mockData.ts | 2 +- 15 files changed, 72 insertions(+), 50 deletions(-) create mode 100644 plugins/cost-insights/src/utils/assert.ts diff --git a/plugins/cost-insights/src/components/BarChart/BarChart.tsx b/plugins/cost-insights/src/components/BarChart/BarChart.tsx index 65e7e39c64..aa1fd5c601 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChart.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChart.tsx @@ -36,11 +36,11 @@ import { currencyFormatter } from '../../utils/formatters'; import { BarChartData, Maybe, - notEmpty, ResourceData, DataKey, CostInsightsTheme, } from '../../types'; +import { notEmpty } from '../../utils/assert'; import { useBarChartStyles } from '../../utils/styles'; import { resourceSort } from '../../utils/sort'; diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx index 2cefcbba1e..9dff164fdf 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx @@ -17,11 +17,8 @@ import React, { PropsWithChildren } from 'react'; import { renderInTestApp } from '@backstage/test-utils'; import { CostGrowth } from './CostGrowth'; -import { - Currency, - Duration, - findAlways, -} from '../../types'; +import { Currency, Duration } from '../../types'; +import { findAlways } from '../../utils/assert'; import { MockConfigProvider, MockCurrencyProvider } from '../../utils/tests'; import { defaultCurrencies, CurrencyType } from '../../utils/currency'; diff --git a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx index f190fa88bb..20c7f4ec46 100644 --- a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx +++ b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx @@ -25,7 +25,7 @@ import { } from '@material-ui/core'; import { useNavigationStyles } from '../../utils/styles'; import { useConfig, useScroll } from '../../hooks'; -import { findAlways } from '../../types'; +import { findAlways } from '../../utils/assert'; import { DefaultNavigation, NavigationItem, @@ -66,10 +66,10 @@ export const CostInsightsNavigation = ({ })} ) : ( - React.cloneElement(item.icon, { - className: classes.navigationIcon, - }) - ) + React.cloneElement(item.icon, { + className: classes.navigationIcon, + }) + ) } title={item.title} /> diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx index c6269f7dc6..528cb1663d 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx @@ -26,11 +26,11 @@ import { useScroll, useFilters, useConfig } from '../../hooks'; import { mapFiltersToProps } from './selector'; import { DefaultNavigation } from '../../utils/navigation'; import { formatPercent } from '../../utils/formatters'; +import { findAlways } from '../../utils/assert'; import { Cost, CostInsightsTheme, MetricData, - findAlways, getComparedChange, } from '../../types'; diff --git a/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx b/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx index 413426e9af..2780c728f3 100644 --- a/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx +++ b/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx @@ -16,7 +16,9 @@ import React from 'react'; import { MenuItem, Select, SelectProps } from '@material-ui/core'; -import { Currency, CurrencyType, findAlways } from '../../types'; +import { Currency } from '../../types'; +import { CurrencyType } from '../../utils/currency'; +import { findAlways } from '../../utils/assert'; import { useSelectStyles as useStyles } from '../../utils/styles'; const NULL_VALUE = 'engineers'; diff --git a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx index 07365c32eb..918200471f 100644 --- a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx +++ b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx @@ -20,7 +20,8 @@ import { formatLastTwoLookaheadQuarters, formatLastTwoMonths, } from '../../utils/formatters'; -import { Duration, findAlways } from '../../types'; +import { Duration } from '../../types'; +import { findAlways } from '../../utils/assert'; import { useSelectStyles as useStyles } from '../../utils/styles'; import { useLastCompleteBillingDate } from '../../hooks'; diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts b/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts index 001ff717bd..efc8448034 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts +++ b/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts @@ -16,7 +16,8 @@ import { MapFiltersToProps } from '../../hooks/useFilters'; import { MapLoadingToProps } from '../../hooks/useLoading'; -import { Duration, PageFilters, ProductPeriod, findAlways } from '../../types'; +import { Duration, PageFilters, ProductPeriod } from '../../types'; +import { findAlways } from '../../utils/assert'; type ProductInsightsCardFilterProps = PageFilters & { product: ProductPeriod; diff --git a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx index 3e2fc8d32e..db3f2f9bf6 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.test.tsx @@ -23,8 +23,9 @@ import { MockConfigProvider, MockBillingDateProvider, } from '../../utils/tests'; -import { AlertCost, findAlways } from '../../types'; +import { AlertCost } from '../../types'; import { defaultCurrencies } from '../../utils/currency'; +import { findAlways } from '../../utils/assert'; const engineers = findAlways(defaultCurrencies, c => c.kind === null); diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx index 2bc998d9df..9599b3cca1 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx @@ -17,7 +17,9 @@ import React, { PropsWithChildren } from 'react'; import { renderInTestApp } from '@backstage/test-utils'; import { ResourceGrowthBarChartLegend } from './ResourceGrowthBarChartLegend'; -import { defaultCurrencies, Duration, findAlways } from '../../types'; +import { Duration } from '../../types'; +import { defaultCurrencies } from '../../utils/currency'; +import { findAlways } from '../../utils/assert'; import { MockConfigProvider, MockCurrencyProvider } from '../../utils/tests'; const engineers = findAlways(defaultCurrencies, c => c.kind === null); diff --git a/plugins/cost-insights/src/hooks/useCurrency.tsx b/plugins/cost-insights/src/hooks/useCurrency.tsx index b5079d37f1..ff41b033e4 100644 --- a/plugins/cost-insights/src/hooks/useCurrency.tsx +++ b/plugins/cost-insights/src/hooks/useCurrency.tsx @@ -20,7 +20,8 @@ import React, { useContext, PropsWithChildren, } from 'react'; -import { Currency, findAlways } from '../types'; +import { Currency } from '../types'; +import { findAlways } from '../utils/assert'; import { defaultCurrencies } from '../utils/currency'; export type CurrencyContextProps = { diff --git a/plugins/cost-insights/src/types/Duration.ts b/plugins/cost-insights/src/types/Duration.ts index 72501d46d5..09034ae9df 100644 --- a/plugins/cost-insights/src/types/Duration.ts +++ b/plugins/cost-insights/src/types/Duration.ts @@ -15,7 +15,7 @@ */ import moment from 'moment'; -import { assertNever } from './Maybe'; +import { assertNever } from '../utils/assert'; /** * Time periods for cost comparison; slight abuse of ISO 8601 periods. We take P1M and P3M to mean diff --git a/plugins/cost-insights/src/types/Maybe.ts b/plugins/cost-insights/src/types/Maybe.ts index d721f28d75..a01a658382 100644 --- a/plugins/cost-insights/src/types/Maybe.ts +++ b/plugins/cost-insights/src/types/Maybe.ts @@ -13,33 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export type Maybe = T | null; - -export function notEmpty( - value: TValue | null | undefined, -): value is TValue { - return value !== null && value !== undefined; -} - -// Utility for exhaustiveness checking in switch statements -export function assertNever(x: never): never { - throw new Error(`Exhaustiveness check failed: ${x}`); -} - -export function assertAlways(argument: T | undefined): T { - if (argument === undefined) { - throw new TypeError( - 'Expected to always find a value but received undefined', - ); - } - return argument; -} - -// Utility for working with static lists; asserts a value will always be found or -// throws an error -export function findAlways( - collection: T[], - callback: (el: T) => boolean, -): T { - return assertAlways(collection.find(callback)); -} diff --git a/plugins/cost-insights/src/utils/assert.ts b/plugins/cost-insights/src/utils/assert.ts new file mode 100644 index 0000000000..8f7caef0fa --- /dev/null +++ b/plugins/cost-insights/src/utils/assert.ts @@ -0,0 +1,44 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function notEmpty( + value: TValue | null | undefined, +): value is TValue { + return value !== null && value !== undefined; +} + +// Utility for exhaustiveness checking in switch statements +export function assertNever(x: never): never { + throw new Error(`Exhaustiveness check failed: ${x}`); +} + +export function assertAlways(argument: T | undefined): T { + if (argument === undefined) { + throw new TypeError( + 'Expected to always find a value but received undefined', + ); + } + return argument; +} + +// Utility for working with static lists; asserts a value will always be found or +// throws an error +export function findAlways( + collection: T[], + callback: (el: T) => boolean, +): T { + return assertAlways(collection.find(callback)); +} diff --git a/plugins/cost-insights/src/utils/currency.ts b/plugins/cost-insights/src/utils/currency.ts index c15af4d80d..439dbb70c3 100644 --- a/plugins/cost-insights/src/utils/currency.ts +++ b/plugins/cost-insights/src/utils/currency.ts @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { assertNever, Currency, Duration } from '../types'; +import { Currency, Duration } from '../types'; +import { assertNever } from '../utils/assert'; export enum CurrencyType { USD = 'USD', diff --git a/plugins/cost-insights/src/utils/mockData.ts b/plugins/cost-insights/src/utils/mockData.ts index c070f07e29..9609da6ce8 100644 --- a/plugins/cost-insights/src/utils/mockData.ts +++ b/plugins/cost-insights/src/utils/mockData.ts @@ -17,7 +17,6 @@ import { Duration, Entity, - findAlways, Product, ProductCost, ProductFilters, @@ -29,6 +28,7 @@ import { DefaultLoadingAction, getDefaultState as getDefaultLoadingState, } from '../utils/loading'; +import { findAlways } from '../utils/assert'; import { Config } from '@backstage/config'; import { ConfigApi } from '@backstage/core'; From 78ffb124dcfb6343fb0118e259ddcf63e2975931 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Wed, 28 Oct 2020 11:15:42 -0400 Subject: [PATCH 04/20] migrate change utils --- .../src/components/CostGrowth/CostGrowth.tsx | 16 ++---- .../CostOverviewCard/CostOverviewCard.tsx | 8 +-- .../src/types/ChangeStatistic.ts | 43 -------------- plugins/cost-insights/src/utils/change.ts | 57 +++++++++++++++++++ 4 files changed, 64 insertions(+), 60 deletions(-) create mode 100644 plugins/cost-insights/src/utils/change.ts diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx index a43cae9720..3dad0e780a 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx @@ -16,15 +16,9 @@ import React from 'react'; import classnames from 'classnames'; -import { - ChangeStatistic, - CurrencyType, - Duration, - EngineerThreshold, - Growth, - growthOf, - rateOf, -} from '../../types'; +import { ChangeStatistic, Duration } from '../../types'; +import { rateOf, CurrencyType } from '../../utils/currency'; +import { growthOf, GrowthType, EngineerThreshold } from '../../utils/change'; import { useCostGrowthStyles as useStyles } from '../../utils/styles'; import { formatPercent, formatCurrency } from '../../utils/formatters'; import { indefiniteArticleOf } from '../../utils/grammar'; @@ -51,8 +45,8 @@ export const CostGrowth = ({ change, duration }: CostGrowthProps) => { // Determine if growth is significant enough to highlight const growth = growthOf(engineers, change.ratio); const classes = classnames({ - [styles.excess]: growth === Growth.Excess, - [styles.savings]: growth === Growth.Savings, + [styles.excess]: growth === GrowthType.Excess, + [styles.savings]: growth === GrowthType.Savings, }); const percent = formatPercent(ratio); diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx index 528cb1663d..7d55026be8 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.tsx @@ -27,12 +27,8 @@ import { mapFiltersToProps } from './selector'; import { DefaultNavigation } from '../../utils/navigation'; import { formatPercent } from '../../utils/formatters'; import { findAlways } from '../../utils/assert'; -import { - Cost, - CostInsightsTheme, - MetricData, - getComparedChange, -} from '../../types'; +import { getComparedChange } from '../../utils/change'; +import { Cost, CostInsightsTheme, MetricData } from '../../types'; export type CostOverviewCardProps = { dailyCostData: Cost; diff --git a/plugins/cost-insights/src/types/ChangeStatistic.ts b/plugins/cost-insights/src/types/ChangeStatistic.ts index cdd2e02da6..e60d47a0e6 100644 --- a/plugins/cost-insights/src/types/ChangeStatistic.ts +++ b/plugins/cost-insights/src/types/ChangeStatistic.ts @@ -14,52 +14,9 @@ * limitations under the License. */ -import { Cost } from './Cost'; -import { MetricData } from './MetricData'; -import { aggregationSort } from '../utils/sort'; - export interface ChangeStatistic { // The ratio of change from one duration to another, expressed as: (newSum - oldSum) / oldSum ratio: number; // The actual USD change between time periods (can be negative if costs decreased) amount: number; } - -export const EngineerThreshold = 0.5; - -export enum ChangeThreshold { - upper = 0.05, - lower = -0.05, -} - -export enum Growth { - Negligible, - Savings, - Excess, -} - -// Used by for displaying status colors -export function growthOf(amount: number, ratio: number) { - if (amount >= EngineerThreshold && ratio >= ChangeThreshold.upper) { - return Growth.Excess; - } - - if (amount >= EngineerThreshold && ratio <= ChangeThreshold.lower) { - return Growth.Savings; - } - - return Growth.Negligible; -} - -// Used by for displaying engineer totals -export function getComparedChange( - dailyCost: Cost, - metricData: MetricData, -): ChangeStatistic { - const ratio = dailyCost.change.ratio - metricData.change.ratio; - const amount = dailyCost.aggregation.slice().sort(aggregationSort)[0].amount; - return { - ratio: ratio, - amount: amount * ratio, - }; -} diff --git a/plugins/cost-insights/src/utils/change.ts b/plugins/cost-insights/src/utils/change.ts new file mode 100644 index 0000000000..f5c6570b36 --- /dev/null +++ b/plugins/cost-insights/src/utils/change.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Cost, ChangeStatistic, MetricData } from '../types'; +import { aggregationSort } from '../utils/sort'; + +export const EngineerThreshold = 0.5; + +export enum ChangeThreshold { + upper = 0.05, + lower = -0.05, +} + +export enum GrowthType { + Negligible, + Savings, + Excess, +} + +// Used by for displaying status colors +export function growthOf(amount: number, ratio: number) { + if (amount >= EngineerThreshold && ratio >= ChangeThreshold.upper) { + return GrowthType.Excess; + } + + if (amount >= EngineerThreshold && ratio <= ChangeThreshold.lower) { + return GrowthType.Savings; + } + + return GrowthType.Negligible; +} + +// Used by for displaying engineer totals +export function getComparedChange( + dailyCost: Cost, + metricData: MetricData, +): ChangeStatistic { + const ratio = dailyCost.change.ratio - metricData.change.ratio; + const amount = dailyCost.aggregation.slice().sort(aggregationSort)[0].amount; + return { + ratio: ratio, + amount: amount * ratio, + }; +} From cb4568f6653e8346418282555881ec282c16a875 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Wed, 28 Oct 2020 11:34:40 -0400 Subject: [PATCH 05/20] migration duration utils --- plugins/cost-insights/src/api/CostInsightsApi.ts | 2 +- .../cost-insights/src/api/ExampleCostInsightsClient.ts | 5 +---- .../src/components/CostGrowth/CostGrowth.test.tsx | 3 ++- .../src/components/CostGrowth/CostGrowth.tsx | 3 ++- .../components/CostOverviewCard/CostOverviewTooltip.tsx | 2 +- .../src/components/CostOverviewCard/selector.tsx | 3 ++- .../src/components/PeriodSelect/PeriodSelect.test.tsx | 3 ++- .../src/components/PeriodSelect/PeriodSelect.tsx | 2 +- .../ProductInsightsCard/ProductInsightsCard.test.tsx | 3 ++- .../ProductInsightsCard/ProductInsightsCard.tsx | 3 ++- .../src/components/ProductInsightsCard/selector.ts | 3 ++- .../ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx | 8 ++++---- .../ProjectGrowthInstructionsPage.tsx | 2 +- .../ResourceGrowthBarChartLegend.test.tsx | 2 +- .../ResourceGrowthBarChartLegend.tsx | 3 ++- plugins/cost-insights/src/index.ts | 1 + plugins/cost-insights/src/types/Filters.ts | 2 +- plugins/cost-insights/src/types/index.ts | 1 - plugins/cost-insights/src/utils/currency.ts | 3 ++- .../{types/Duration.test.ts => utils/duration.test.ts} | 2 +- .../src/{types/Duration.ts => utils/duration.ts} | 0 plugins/cost-insights/src/utils/formatters.test.ts | 2 +- plugins/cost-insights/src/utils/formatters.ts | 2 +- plugins/cost-insights/src/utils/history.ts | 3 ++- plugins/cost-insights/src/utils/mockData.ts | 6 +++--- plugins/cost-insights/src/utils/tests.tsx | 3 ++- 26 files changed, 40 insertions(+), 32 deletions(-) rename plugins/cost-insights/src/{types/Duration.test.ts => utils/duration.test.ts} (98%) rename plugins/cost-insights/src/{types/Duration.ts => utils/duration.ts} (100%) diff --git a/plugins/cost-insights/src/api/CostInsightsApi.ts b/plugins/cost-insights/src/api/CostInsightsApi.ts index be5cd54fdb..8e165ba72a 100644 --- a/plugins/cost-insights/src/api/CostInsightsApi.ts +++ b/plugins/cost-insights/src/api/CostInsightsApi.ts @@ -18,13 +18,13 @@ import { createApiRef } from '@backstage/core'; import { Alert, Cost, - Duration, Group, Project, ProductCost, Maybe, MetricData, } from '../types'; +import { Duration } from '../utils/duration'; export type CostInsightsApi = { /** diff --git a/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts b/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts index 35bff86f7f..8f116afb65 100644 --- a/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts +++ b/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts @@ -23,11 +23,7 @@ import { ChangeStatistic, Cost, DateAggregation, - DEFAULT_DATE_FORMAT, - Duration, - exclusiveEndDateOf, Group, - inclusiveStartDateOf, Maybe, MetricData, ProductCost, @@ -38,6 +34,7 @@ import { UnlabeledDataflowAlert, UnlabeledDataflowData, } from '../types'; +import { DEFAULT_DATE_FORMAT, Duration, exclusiveEndDateOf, inclusiveStartDateOf } from '../utils/duration'; type IntervalFields = { duration: Duration; diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx index 9dff164fdf..8744c5c6e7 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx @@ -17,7 +17,8 @@ import React, { PropsWithChildren } from 'react'; import { renderInTestApp } from '@backstage/test-utils'; import { CostGrowth } from './CostGrowth'; -import { Currency, Duration } from '../../types'; +import { Currency } from '../../types'; +import { Duration } from '../../utils/duration'; import { findAlways } from '../../utils/assert'; import { MockConfigProvider, MockCurrencyProvider } from '../../utils/tests'; import { defaultCurrencies, CurrencyType } from '../../utils/currency'; diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx index 3dad0e780a..bdb4e00394 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx @@ -16,8 +16,9 @@ import React from 'react'; import classnames from 'classnames'; -import { ChangeStatistic, Duration } from '../../types'; +import { ChangeStatistic } from '../../types'; import { rateOf, CurrencyType } from '../../utils/currency'; +import { Duration } from '../../utils/duration'; import { growthOf, GrowthType, EngineerThreshold } from '../../utils/change'; import { useCostGrowthStyles as useStyles } from '../../utils/styles'; import { formatPercent, formatCurrency } from '../../utils/formatters'; diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx index e0a9b9a9ea..51f2f12bdb 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx @@ -17,7 +17,7 @@ import React from 'react'; import moment from 'moment'; import { TooltipPayload, TooltipProps } from 'recharts'; import { Tooltip, TooltipItemProps } from '../../components/Tooltip'; -import { DEFAULT_DATE_FORMAT } from '../../types'; +import { DEFAULT_DATE_FORMAT } from '../../utils/duration'; export type CostOverviewTooltipProps = TooltipProps & { dataKeys: Array; diff --git a/plugins/cost-insights/src/components/CostOverviewCard/selector.tsx b/plugins/cost-insights/src/components/CostOverviewCard/selector.tsx index ef65f38dbb..3440500215 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/selector.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/selector.tsx @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Duration, Maybe, PageFilters } from '../../types'; +import { Maybe, PageFilters } from '../../types'; +import { Duration } from '../../utils/duration'; import { MapFiltersToProps } from '../../hooks/useFilters'; type CostOverviewFilterProps = PageFilters & { diff --git a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx index e2cf1b7480..628046f921 100644 --- a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx +++ b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx @@ -19,7 +19,8 @@ import { getByRole, waitFor } from '@testing-library/react'; import { renderInTestApp } from '@backstage/test-utils'; import UserEvent from '@testing-library/user-event'; import { PeriodSelect, getDefaultOptions } from './PeriodSelect'; -import { Duration, getDefaultPageFilters, Group } from '../../types'; +import { getDefaultPageFilters, Group } from '../../types'; +import { Duration } from '../../utils/duration'; import { MockBillingDateProvider } from '../../utils/tests'; const DefaultPageFilters = getDefaultPageFilters([{ id: 'tools' }] as Group[]); diff --git a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx index 918200471f..f1a80a55f5 100644 --- a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx +++ b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx @@ -20,7 +20,7 @@ import { formatLastTwoLookaheadQuarters, formatLastTwoMonths, } from '../../utils/formatters'; -import { Duration } from '../../types'; +import { Duration } from '../../utils/duration'; import { findAlways } from '../../utils/assert'; import { useSelectStyles as useStyles } from '../../utils/styles'; import { useLastCompleteBillingDate } from '../../hooks'; diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx index 9d1610e298..f27d7349a3 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx @@ -35,7 +35,8 @@ import { MockScrollProvider, MockLoadingProvider, } from '../../utils/tests'; -import { Duration, Product, ProductCost, ProductPeriod } from '../../types'; +import { Duration } from '../../utils/duration'; +import { Product, ProductCost, ProductPeriod } from '../../types'; const costInsightsApi = ( productCost: ProductCost, diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx index 840c99522a..fec73f0c06 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx @@ -28,9 +28,10 @@ import { useLoading, useScroll, } from '../../hooks'; +import { Duration } from '../../utils/duration'; import { useProductInsightsCardStyles as useStyles } from '../../utils/styles'; import { mapFiltersToProps, mapLoadingToProps } from './selector'; -import { Duration, Maybe, Product, ProductCost } from '../../types'; +import { Maybe, Product, ProductCost } from '../../types'; import { pluralOf } from '../../utils/grammar'; import { formatPeriod } from '../../utils/formatters'; diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts b/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts index efc8448034..6007070707 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts +++ b/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts @@ -16,7 +16,8 @@ import { MapFiltersToProps } from '../../hooks/useFilters'; import { MapLoadingToProps } from '../../hooks/useLoading'; -import { Duration, PageFilters, ProductPeriod } from '../../types'; +import { PageFilters, ProductPeriod } from '../../types'; +import { Duration } from '../../utils/duration'; import { findAlways } from '../../utils/assert'; type ProductInsightsCardFilterProps = PageFilters & { diff --git a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx index 4311bcc1bf..28e7948ca4 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx @@ -20,7 +20,8 @@ import { Box } from '@material-ui/core'; import { InfoCard } from '@backstage/core'; import { ResourceGrowthBarChart } from '../ResourceGrowthBarChart'; import { ResourceGrowthBarChartLegend } from '../ResourceGrowthBarChartLegend'; -import { Duration, ProjectGrowthData } from '../../types'; +import { ProjectGrowthData } from '../../types'; +import { Duration } from '../../utils/duration'; import { pluralOf } from '../../utils/grammar'; type ProjectGrowthAlertProps = { @@ -31,9 +32,8 @@ export const ProjectGrowthAlertCard = ({ alert }: ProjectGrowthAlertProps) => { const [costStart, costEnd] = alert.aggregation; const subheader = ` - ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${ - alert.products.length > 1 ? ', sorted by cost' : '' - }`; + ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${alert.products.length > 1 ? ', sorted by cost' : '' + }`; const previousName = moment(alert.periodStart, 'YYYY-[Q]Q').format( '[Q]Q YYYY', ); diff --git a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx index 3c2d241222..074d3e2b92 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx @@ -18,9 +18,9 @@ import React from 'react'; import { Box, Typography } from '@material-ui/core'; import { InfoCard } from '@backstage/core'; import { AlertInstructionsLayout } from '../AlertInstructionsLayout'; +import { Duration } from '../../utils/duration'; import { Alert, - Duration, Entity, Product, ProjectGrowthAlert, diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx index 9599b3cca1..bf5c1021cc 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx @@ -17,7 +17,7 @@ import React, { PropsWithChildren } from 'react'; import { renderInTestApp } from '@backstage/test-utils'; import { ResourceGrowthBarChartLegend } from './ResourceGrowthBarChartLegend'; -import { Duration } from '../../types'; +import { Duration } from '../../utils/duration'; import { defaultCurrencies } from '../../utils/currency'; import { findAlways } from '../../utils/assert'; import { MockConfigProvider, MockCurrencyProvider } from '../../utils/tests'; diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx index 6b5ce17c95..0c281e6266 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx @@ -19,7 +19,8 @@ import { Box, useTheme } from '@material-ui/core'; import { LegendItem } from '../LegendItem'; import { CostGrowth } from '../CostGrowth'; import { currencyFormatter } from '../../utils/formatters'; -import { ChangeStatistic, CostInsightsTheme, Duration } from '../../types'; +import { Duration } from '../../utils/duration'; +import { ChangeStatistic, CostInsightsTheme } from '../../types'; export type ResourceGrowthBarChartLegendProps = { change: ChangeStatistic; diff --git a/plugins/cost-insights/src/index.ts b/plugins/cost-insights/src/index.ts index 71cc66dba6..661aa01db3 100644 --- a/plugins/cost-insights/src/index.ts +++ b/plugins/cost-insights/src/index.ts @@ -19,4 +19,5 @@ export * from './api'; export * from './components'; export { useCurrency } from './hooks'; export * from './types'; +export { Duration } from './utils/duration'; export * from './utils/tests'; diff --git a/plugins/cost-insights/src/types/Filters.ts b/plugins/cost-insights/src/types/Filters.ts index b1fbbb2848..e72e850c61 100644 --- a/plugins/cost-insights/src/types/Filters.ts +++ b/plugins/cost-insights/src/types/Filters.ts @@ -15,8 +15,8 @@ */ import { Maybe } from './Maybe'; -import { Duration } from './Duration'; import { Group } from './Group'; +import { Duration } from '../utils/duration'; export interface PageFilters { group: Maybe; diff --git a/plugins/cost-insights/src/types/index.ts b/plugins/cost-insights/src/types/index.ts index 398110ec80..cced505f86 100644 --- a/plugins/cost-insights/src/types/index.ts +++ b/plugins/cost-insights/src/types/index.ts @@ -19,7 +19,6 @@ export * from './ChangeStatistic'; export * from './ChartData'; export * from './Cost'; export * from './DateAggregation'; -export * from './Duration'; export * from './Currency'; export * from './Entity'; export * from './Icon'; diff --git a/plugins/cost-insights/src/utils/currency.ts b/plugins/cost-insights/src/utils/currency.ts index 439dbb70c3..7f43acc66b 100644 --- a/plugins/cost-insights/src/utils/currency.ts +++ b/plugins/cost-insights/src/utils/currency.ts @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Currency, Duration } from '../types'; +import { Currency } from '../types'; +import { Duration } from '../utils/duration'; import { assertNever } from '../utils/assert'; export enum CurrencyType { diff --git a/plugins/cost-insights/src/types/Duration.test.ts b/plugins/cost-insights/src/utils/duration.test.ts similarity index 98% rename from plugins/cost-insights/src/types/Duration.test.ts rename to plugins/cost-insights/src/utils/duration.test.ts index 4ab84de974..675a90b54a 100644 --- a/plugins/cost-insights/src/types/Duration.test.ts +++ b/plugins/cost-insights/src/utils/duration.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { Duration, inclusiveEndDateOf, inclusiveStartDateOf } from './Duration'; +import { Duration, inclusiveEndDateOf, inclusiveStartDateOf } from './duration'; const lastCompleteBillingDate = '2020-06-05'; diff --git a/plugins/cost-insights/src/types/Duration.ts b/plugins/cost-insights/src/utils/duration.ts similarity index 100% rename from plugins/cost-insights/src/types/Duration.ts rename to plugins/cost-insights/src/utils/duration.ts diff --git a/plugins/cost-insights/src/utils/formatters.test.ts b/plugins/cost-insights/src/utils/formatters.test.ts index 69e9086be1..7be6e1dffb 100644 --- a/plugins/cost-insights/src/utils/formatters.test.ts +++ b/plugins/cost-insights/src/utils/formatters.test.ts @@ -19,7 +19,7 @@ import { lengthyCurrencyFormatter, quarterOf, } from './formatters'; -import { Duration } from '../types'; +import { Duration } from '../utils/duration'; Date.now = jest.fn(() => new Date(Date.parse('2019-12-07')).valueOf()); diff --git a/plugins/cost-insights/src/utils/formatters.ts b/plugins/cost-insights/src/utils/formatters.ts index 44c7517351..48b0b77188 100644 --- a/plugins/cost-insights/src/utils/formatters.ts +++ b/plugins/cost-insights/src/utils/formatters.ts @@ -19,7 +19,7 @@ import { Duration, inclusiveEndDateOf, inclusiveStartDateOf, -} from '../types/Duration'; +} from '../utils/duration'; import { pluralOf } from '../utils/grammar'; export type Period = { diff --git a/plugins/cost-insights/src/utils/history.ts b/plugins/cost-insights/src/utils/history.ts index 90df574acf..3b55aeebce 100644 --- a/plugins/cost-insights/src/utils/history.ts +++ b/plugins/cost-insights/src/utils/history.ts @@ -16,7 +16,8 @@ import qs from 'qs'; import * as yup from 'yup'; -import { Group, PageFilters, getDefaultPageFilters, Duration } from '../types'; +import { Group, PageFilters, getDefaultPageFilters } from '../types'; +import { Duration } from '../utils/duration'; import { ConfigContextProps } from '../hooks/useConfig'; const schema = yup diff --git a/plugins/cost-insights/src/utils/mockData.ts b/plugins/cost-insights/src/utils/mockData.ts index 9609da6ce8..91cd2f8ad2 100644 --- a/plugins/cost-insights/src/utils/mockData.ts +++ b/plugins/cost-insights/src/utils/mockData.ts @@ -14,8 +14,9 @@ * limitations under the License. */ +import { Config } from '@backstage/config'; +import { ConfigApi } from '@backstage/core'; import { - Duration, Entity, Product, ProductCost, @@ -29,8 +30,7 @@ import { getDefaultState as getDefaultLoadingState, } from '../utils/loading'; import { findAlways } from '../utils/assert'; -import { Config } from '@backstage/config'; -import { ConfigApi } from '@backstage/core'; +import { Duration } from '../utils/duration'; type mockAlertRenderer = (alert: T) => T; type mockEntityRenderer = (entity: T) => T; diff --git a/plugins/cost-insights/src/utils/tests.tsx b/plugins/cost-insights/src/utils/tests.tsx index db47bd72bd..09eab89139 100644 --- a/plugins/cost-insights/src/utils/tests.tsx +++ b/plugins/cost-insights/src/utils/tests.tsx @@ -32,7 +32,8 @@ import { BillingDateContextProps, } from '../hooks/useLastCompleteBillingDate'; import { ScrollContext, ScrollContextProps } from '../hooks/useScroll'; -import { Duration, Group } from '../types'; +import { Duration } from '../utils/duration'; +import { Group } from '../types'; /* Mock Providers and types are exposed publicly to allow users to test custom implementations From dbaefe6e57690b4e27d7d92f04c914bc3cae05d8 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Wed, 28 Oct 2020 11:41:29 -0400 Subject: [PATCH 06/20] migrate filters and icon utils --- .../PeriodSelect/PeriodSelect.test.tsx | 3 ++- plugins/cost-insights/src/types/Filters.ts | 10 ------- plugins/cost-insights/src/types/Icon.ts | 9 ------- plugins/cost-insights/src/utils/filters.ts | 27 +++++++++++++++++++ plugins/cost-insights/src/utils/history.ts | 3 ++- plugins/cost-insights/src/utils/icon.ts | 24 +++++++++++++++++ .../cost-insights/src/utils/navigation.tsx | 2 +- 7 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 plugins/cost-insights/src/utils/filters.ts create mode 100644 plugins/cost-insights/src/utils/icon.ts diff --git a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx index 628046f921..67f40550f2 100644 --- a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx +++ b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx @@ -19,9 +19,10 @@ import { getByRole, waitFor } from '@testing-library/react'; import { renderInTestApp } from '@backstage/test-utils'; import UserEvent from '@testing-library/user-event'; import { PeriodSelect, getDefaultOptions } from './PeriodSelect'; -import { getDefaultPageFilters, Group } from '../../types'; +import { getDefaultPageFilters } from '../../utils/filters'; import { Duration } from '../../utils/duration'; import { MockBillingDateProvider } from '../../utils/tests'; +import { Group } from '../../types'; const DefaultPageFilters = getDefaultPageFilters([{ id: 'tools' }] as Group[]); const lastCompleteBillingDate = '2020-05-01'; diff --git a/plugins/cost-insights/src/types/Filters.ts b/plugins/cost-insights/src/types/Filters.ts index e72e850c61..da71471f50 100644 --- a/plugins/cost-insights/src/types/Filters.ts +++ b/plugins/cost-insights/src/types/Filters.ts @@ -15,7 +15,6 @@ */ import { Maybe } from './Maybe'; -import { Group } from './Group'; import { Duration } from '../utils/duration'; export interface PageFilters { @@ -31,12 +30,3 @@ export interface ProductPeriod { duration: Duration; productType: string; } - -export function getDefaultPageFilters(groups: Group[]): PageFilters { - return { - group: groups.length ? groups[0].id : null, - project: null, - duration: Duration.P90D, - metric: null, - }; -} diff --git a/plugins/cost-insights/src/types/Icon.ts b/plugins/cost-insights/src/types/Icon.ts index 70f43a6813..db5520ca15 100644 --- a/plugins/cost-insights/src/types/Icon.ts +++ b/plugins/cost-insights/src/types/Icon.ts @@ -18,12 +18,3 @@ export type Icon = { kind: string; component: JSX.Element; }; - -export enum IconType { - Compute = 'compute', - Data = 'data', - Database = 'database', - Storage = 'storage', - Search = 'search', - ML = 'ml', -} diff --git a/plugins/cost-insights/src/utils/filters.ts b/plugins/cost-insights/src/utils/filters.ts new file mode 100644 index 0000000000..26d2bc6cf3 --- /dev/null +++ b/plugins/cost-insights/src/utils/filters.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Group, PageFilters } from '../types'; +import { Duration } from './duration'; + +export function getDefaultPageFilters(groups: Group[]): PageFilters { + return { + group: groups.length ? groups[0].id : null, + project: null, + duration: Duration.P90D, + metric: null, + }; +} diff --git a/plugins/cost-insights/src/utils/history.ts b/plugins/cost-insights/src/utils/history.ts index 3b55aeebce..36f4e9a5b0 100644 --- a/plugins/cost-insights/src/utils/history.ts +++ b/plugins/cost-insights/src/utils/history.ts @@ -16,8 +16,9 @@ import qs from 'qs'; import * as yup from 'yup'; -import { Group, PageFilters, getDefaultPageFilters } from '../types'; +import { Group, PageFilters } from '../types'; import { Duration } from '../utils/duration'; +import { getDefaultPageFilters } from '../utils/filters'; import { ConfigContextProps } from '../hooks/useConfig'; const schema = yup diff --git a/plugins/cost-insights/src/utils/icon.ts b/plugins/cost-insights/src/utils/icon.ts new file mode 100644 index 0000000000..de957743ba --- /dev/null +++ b/plugins/cost-insights/src/utils/icon.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export enum IconType { + Compute = 'compute', + Data = 'data', + Database = 'database', + Storage = 'storage', + Search = 'search', + ML = 'ml', +} diff --git a/plugins/cost-insights/src/utils/navigation.tsx b/plugins/cost-insights/src/utils/navigation.tsx index d2cb1d20bb..39016f6092 100644 --- a/plugins/cost-insights/src/utils/navigation.tsx +++ b/plugins/cost-insights/src/utils/navigation.tsx @@ -23,7 +23,7 @@ import Search from '@material-ui/icons/Search'; import CloudQueue from '@material-ui/icons/CloudQueue'; import School from '@material-ui/icons/School'; import ViewHeadline from '@material-ui/icons/ViewHeadline'; -import { IconType } from '../types'; +import { IconType } from '../utils/icon'; export enum DefaultNavigation { CostOverviewCard = 'cost-overview-card', From bf3bce32be3ca6e778bef94c01f1f1c2eebcdd0a Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Wed, 28 Oct 2020 12:27:41 -0400 Subject: [PATCH 07/20] use correct import for intervalsOf --- .../src/components/CostInsightsPage/CostInsightsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx b/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx index 638f6fef00..21dfef63fb 100644 --- a/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx +++ b/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx @@ -44,13 +44,13 @@ import { import { Alert, Cost, - intervalsOf, Maybe, MetricData, Project, } from '../../types'; import { mapLoadingToProps } from './selector'; import { ProjectSelect } from '../ProjectSelect'; +import { intervalsOf } from '../../utils/duration'; import { useSubtleTypographyStyles } from '../../utils/styles'; export const CostInsightsPage = () => { From ec884c9d28c058a111840d5ee3d1e8e4b792cad1 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Wed, 28 Oct 2020 12:28:38 -0400 Subject: [PATCH 08/20] formatting --- .../cost-insights/src/api/ExampleCostInsightsClient.ts | 7 ++++++- .../src/components/CostGrowth/CostGrowth.test.tsx | 8 ++++---- .../CostInsightsNavigation/CostInsightsNavigation.tsx | 8 ++++---- .../src/components/CostInsightsPage/CostInsightsPage.tsx | 8 +------- .../ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx | 5 +++-- plugins/cost-insights/src/hooks/useLoading.tsx | 2 +- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts b/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts index 8f116afb65..159e2a2e7d 100644 --- a/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts +++ b/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts @@ -34,7 +34,12 @@ import { UnlabeledDataflowAlert, UnlabeledDataflowData, } from '../types'; -import { DEFAULT_DATE_FORMAT, Duration, exclusiveEndDateOf, inclusiveStartDateOf } from '../utils/duration'; +import { + DEFAULT_DATE_FORMAT, + Duration, + exclusiveEndDateOf, + inclusiveStartDateOf, +} from '../utils/duration'; type IntervalFields = { duration: Duration; diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx index 8744c5c6e7..7c319354aa 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx @@ -38,10 +38,10 @@ const MockContext = ({ currency: Currency; engineerCost: number; }>) => ( - - {children} - - ); + + {children} + +); describe.each` engineerCost | ratio | amount | expected diff --git a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx index 20c7f4ec46..810fc767a7 100644 --- a/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx +++ b/plugins/cost-insights/src/components/CostInsightsNavigation/CostInsightsNavigation.tsx @@ -66,10 +66,10 @@ export const CostInsightsNavigation = ({ })} ) : ( - React.cloneElement(item.icon, { - className: classes.navigationIcon, - }) - ) + React.cloneElement(item.icon, { + className: classes.navigationIcon, + }) + ) } title={item.title} /> diff --git a/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx b/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx index 21dfef63fb..150195fe0a 100644 --- a/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx +++ b/plugins/cost-insights/src/components/CostInsightsPage/CostInsightsPage.tsx @@ -41,13 +41,7 @@ import { useLastCompleteBillingDate, useLoading, } from '../../hooks'; -import { - Alert, - Cost, - Maybe, - MetricData, - Project, -} from '../../types'; +import { Alert, Cost, Maybe, MetricData, Project } from '../../types'; import { mapLoadingToProps } from './selector'; import { ProjectSelect } from '../ProjectSelect'; import { intervalsOf } from '../../utils/duration'; diff --git a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx index 28e7948ca4..c32afcd257 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx @@ -32,8 +32,9 @@ export const ProjectGrowthAlertCard = ({ alert }: ProjectGrowthAlertProps) => { const [costStart, costEnd] = alert.aggregation; const subheader = ` - ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${alert.products.length > 1 ? ', sorted by cost' : '' - }`; + ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${ + alert.products.length > 1 ? ', sorted by cost' : '' + }`; const previousName = moment(alert.periodStart, 'YYYY-[Q]Q').format( '[Q]Q YYYY', ); diff --git a/plugins/cost-insights/src/hooks/useLoading.tsx b/plugins/cost-insights/src/hooks/useLoading.tsx index 261f1e4077..420ac7ed56 100644 --- a/plugins/cost-insights/src/hooks/useLoading.tsx +++ b/plugins/cost-insights/src/hooks/useLoading.tsx @@ -68,7 +68,7 @@ export const LoadingProvider = ({ children }: PropsWithChildren<{}>) => { // Initial page loading is handled by progress bar setBackdropVisible( !state[DefaultLoadingAction.CostInsightsInitial] && - Object.values(state).some(l => l), + Object.values(state).some(l => l), ); } displayLoadingBackdrop(); From 51032212fee3a39cb2595d2ac9dff3bc2b8c29d4 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Wed, 28 Oct 2020 12:58:11 -0400 Subject: [PATCH 09/20] add explicit export for public utils --- plugins/cost-insights/src/index.ts | 3 +-- .../cost-insights/src/utils/public/index.ts | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 plugins/cost-insights/src/utils/public/index.ts diff --git a/plugins/cost-insights/src/index.ts b/plugins/cost-insights/src/index.ts index 661aa01db3..119fc2035c 100644 --- a/plugins/cost-insights/src/index.ts +++ b/plugins/cost-insights/src/index.ts @@ -19,5 +19,4 @@ export * from './api'; export * from './components'; export { useCurrency } from './hooks'; export * from './types'; -export { Duration } from './utils/duration'; -export * from './utils/tests'; +export * from './utils/public'; diff --git a/plugins/cost-insights/src/utils/public/index.ts b/plugins/cost-insights/src/utils/public/index.ts new file mode 100644 index 0000000000..ffc2d5c882 --- /dev/null +++ b/plugins/cost-insights/src/utils/public/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from '../tests'; +export { Duration } from '../duration'; +export { CurrencyType } from '../currency'; +export { IconType } from '../icon'; From 0ee9e9f6683a5f9bb4fb9a22e98951d98b849789 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Wed, 28 Oct 2020 13:22:55 -0400 Subject: [PATCH 10/20] changeset --- .changeset/cost-insights-kind-trees-occur.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/cost-insights-kind-trees-occur.md diff --git a/.changeset/cost-insights-kind-trees-occur.md b/.changeset/cost-insights-kind-trees-occur.md new file mode 100644 index 0000000000..600cc3b3b4 --- /dev/null +++ b/.changeset/cost-insights-kind-trees-occur.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cost-insights': patch +--- + +migrate type utilities out of type definition files From 59e42b4ca77d7458ebf8648b5fdcb17be17424f4 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Thu, 29 Oct 2020 14:28:42 -0400 Subject: [PATCH 11/20] preserve enums in types --- .../cost-insights/src/api/CostInsightsApi.ts | 2 +- .../src/api/ExampleCostInsightsClient.ts | 8 ++-- .../AlertActionCard.test.tsx | 3 +- .../components/CostGrowth/CostGrowth.test.tsx | 13 +++-- .../src/components/CostGrowth/CostGrowth.tsx | 5 +- .../components/CostOverviewCard/selector.tsx | 3 +- .../CurrencySelect/CurrencySelect.tsx | 3 +- .../PeriodSelect/PeriodSelect.test.tsx | 3 +- .../components/PeriodSelect/PeriodSelect.tsx | 2 +- .../ProductInsightsCard.test.tsx | 3 +- .../ProductInsightsCard.tsx | 3 +- .../ProductInsightsCard/selector.ts | 3 +- .../ProjectGrowthAlertCard.tsx | 8 ++-- .../ProjectGrowthInstructionsPage.tsx | 4 +- .../ResourceGrowthBarChartLegend.test.tsx | 2 +- .../ResourceGrowthBarChartLegend.tsx | 3 +- plugins/cost-insights/src/index.ts | 3 +- .../src/types/{Alert.tsx => Alert.ts} | 45 ------------------ plugins/cost-insights/src/types/Currency.ts | 7 +++ .../src/{utils/icon.ts => types/Duration.ts} | 18 ++++--- plugins/cost-insights/src/types/Filters.ts | 2 +- plugins/cost-insights/src/types/Icon.ts | 9 ++++ plugins/cost-insights/src/types/index.ts | 1 + plugins/cost-insights/src/utils/alerts.tsx | 47 +++++++++++++++++++ plugins/cost-insights/src/utils/currency.ts | 10 +--- .../cost-insights/src/utils/duration.test.ts | 3 +- plugins/cost-insights/src/utils/duration.ts | 16 +------ plugins/cost-insights/src/utils/filters.ts | 3 +- .../src/utils/formatters.test.ts | 2 +- plugins/cost-insights/src/utils/formatters.ts | 2 +- plugins/cost-insights/src/utils/history.ts | 3 +- plugins/cost-insights/src/utils/loading.ts | 16 +++++++ plugins/cost-insights/src/utils/mockData.ts | 2 +- .../cost-insights/src/utils/navigation.tsx | 2 +- .../cost-insights/src/utils/public/index.ts | 20 -------- plugins/cost-insights/src/utils/tests.tsx | 3 +- 36 files changed, 136 insertions(+), 146 deletions(-) rename plugins/cost-insights/src/types/{Alert.tsx => Alert.ts} (59%) rename plugins/cost-insights/src/{utils/icon.ts => types/Duration.ts} (59%) create mode 100644 plugins/cost-insights/src/utils/alerts.tsx delete mode 100644 plugins/cost-insights/src/utils/public/index.ts diff --git a/plugins/cost-insights/src/api/CostInsightsApi.ts b/plugins/cost-insights/src/api/CostInsightsApi.ts index 8e165ba72a..be5cd54fdb 100644 --- a/plugins/cost-insights/src/api/CostInsightsApi.ts +++ b/plugins/cost-insights/src/api/CostInsightsApi.ts @@ -18,13 +18,13 @@ import { createApiRef } from '@backstage/core'; import { Alert, Cost, + Duration, Group, Project, ProductCost, Maybe, MetricData, } from '../types'; -import { Duration } from '../utils/duration'; export type CostInsightsApi = { /** diff --git a/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts b/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts index 159e2a2e7d..70695beb25 100644 --- a/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts +++ b/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts @@ -23,20 +23,22 @@ import { ChangeStatistic, Cost, DateAggregation, + Duration, Group, Maybe, MetricData, ProductCost, Project, - ProjectGrowthAlert, ProjectGrowthData, Trendline, - UnlabeledDataflowAlert, UnlabeledDataflowData, } from '../types'; +import { + ProjectGrowthAlert, + UnlabeledDataflowAlert +} from '../utils/alerts'; import { DEFAULT_DATE_FORMAT, - Duration, exclusiveEndDateOf, inclusiveStartDateOf, } from '../utils/duration'; diff --git a/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.test.tsx b/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.test.tsx index 3e2ca4f8c8..d896bf0d47 100644 --- a/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.test.tsx +++ b/plugins/cost-insights/src/components/AlertActionCardList/AlertActionCard.test.tsx @@ -17,8 +17,9 @@ import React from 'react'; import { renderInTestApp } from '@backstage/test-utils'; import { AlertActionCard } from './AlertActionCard'; -import { ProjectGrowthAlert, ProjectGrowthData } from '../../types'; import { MockScrollProvider } from '../../utils/tests'; +import { ProjectGrowthAlert } from '../../utils/alerts'; +import { ProjectGrowthData } from '../../types'; const data: ProjectGrowthData = { aggregation: [500000.8, 970502.8], diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx index 7c319354aa..046394ca7a 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx @@ -17,11 +17,10 @@ import React, { PropsWithChildren } from 'react'; import { renderInTestApp } from '@backstage/test-utils'; import { CostGrowth } from './CostGrowth'; -import { Currency } from '../../types'; -import { Duration } from '../../utils/duration'; +import { Currency, CurrencyType, Duration } from '../../types'; import { findAlways } from '../../utils/assert'; import { MockConfigProvider, MockCurrencyProvider } from '../../utils/tests'; -import { defaultCurrencies, CurrencyType } from '../../utils/currency'; +import { defaultCurrencies } from '../../utils/currency'; const engineers = findAlways(defaultCurrencies, c => c.kind === null); const usd = findAlways(defaultCurrencies, c => c.kind === CurrencyType.USD); @@ -38,10 +37,10 @@ const MockContext = ({ currency: Currency; engineerCost: number; }>) => ( - - {children} - -); + + {children} + + ); describe.each` engineerCost | ratio | amount | expected diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx index bdb4e00394..3f5e0f55eb 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx @@ -16,9 +16,8 @@ import React from 'react'; import classnames from 'classnames'; -import { ChangeStatistic } from '../../types'; -import { rateOf, CurrencyType } from '../../utils/currency'; -import { Duration } from '../../utils/duration'; +import { ChangeStatistic, CurrencyType, Duration } from '../../types'; +import { rateOf } from '../../utils/currency'; import { growthOf, GrowthType, EngineerThreshold } from '../../utils/change'; import { useCostGrowthStyles as useStyles } from '../../utils/styles'; import { formatPercent, formatCurrency } from '../../utils/formatters'; diff --git a/plugins/cost-insights/src/components/CostOverviewCard/selector.tsx b/plugins/cost-insights/src/components/CostOverviewCard/selector.tsx index 3440500215..ef65f38dbb 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/selector.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/selector.tsx @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Maybe, PageFilters } from '../../types'; -import { Duration } from '../../utils/duration'; +import { Duration, Maybe, PageFilters } from '../../types'; import { MapFiltersToProps } from '../../hooks/useFilters'; type CostOverviewFilterProps = PageFilters & { diff --git a/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx b/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx index 2780c728f3..1b5920ffcb 100644 --- a/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx +++ b/plugins/cost-insights/src/components/CurrencySelect/CurrencySelect.tsx @@ -16,8 +16,7 @@ import React from 'react'; import { MenuItem, Select, SelectProps } from '@material-ui/core'; -import { Currency } from '../../types'; -import { CurrencyType } from '../../utils/currency'; +import { Currency, CurrencyType } from '../../types'; import { findAlways } from '../../utils/assert'; import { useSelectStyles as useStyles } from '../../utils/styles'; diff --git a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx index 67f40550f2..a3519ff61b 100644 --- a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx +++ b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.test.tsx @@ -20,9 +20,8 @@ import { renderInTestApp } from '@backstage/test-utils'; import UserEvent from '@testing-library/user-event'; import { PeriodSelect, getDefaultOptions } from './PeriodSelect'; import { getDefaultPageFilters } from '../../utils/filters'; -import { Duration } from '../../utils/duration'; import { MockBillingDateProvider } from '../../utils/tests'; -import { Group } from '../../types'; +import { Group, Duration } from '../../types'; const DefaultPageFilters = getDefaultPageFilters([{ id: 'tools' }] as Group[]); const lastCompleteBillingDate = '2020-05-01'; diff --git a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx index f1a80a55f5..4908641d6f 100644 --- a/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx +++ b/plugins/cost-insights/src/components/PeriodSelect/PeriodSelect.tsx @@ -16,11 +16,11 @@ import React from 'react'; import { MenuItem, Select, SelectProps } from '@material-ui/core'; +import { Duration } from '../../types'; import { formatLastTwoLookaheadQuarters, formatLastTwoMonths, } from '../../utils/formatters'; -import { Duration } from '../../utils/duration'; import { findAlways } from '../../utils/assert'; import { useSelectStyles as useStyles } from '../../utils/styles'; import { useLastCompleteBillingDate } from '../../hooks'; diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx index f27d7349a3..9d1610e298 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.test.tsx @@ -35,8 +35,7 @@ import { MockScrollProvider, MockLoadingProvider, } from '../../utils/tests'; -import { Duration } from '../../utils/duration'; -import { Product, ProductCost, ProductPeriod } from '../../types'; +import { Duration, Product, ProductCost, ProductPeriod } from '../../types'; const costInsightsApi = ( productCost: ProductCost, diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx index fec73f0c06..840c99522a 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx +++ b/plugins/cost-insights/src/components/ProductInsightsCard/ProductInsightsCard.tsx @@ -28,10 +28,9 @@ import { useLoading, useScroll, } from '../../hooks'; -import { Duration } from '../../utils/duration'; import { useProductInsightsCardStyles as useStyles } from '../../utils/styles'; import { mapFiltersToProps, mapLoadingToProps } from './selector'; -import { Maybe, Product, ProductCost } from '../../types'; +import { Duration, Maybe, Product, ProductCost } from '../../types'; import { pluralOf } from '../../utils/grammar'; import { formatPeriod } from '../../utils/formatters'; diff --git a/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts b/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts index 6007070707..efc8448034 100644 --- a/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts +++ b/plugins/cost-insights/src/components/ProductInsightsCard/selector.ts @@ -16,8 +16,7 @@ import { MapFiltersToProps } from '../../hooks/useFilters'; import { MapLoadingToProps } from '../../hooks/useLoading'; -import { PageFilters, ProductPeriod } from '../../types'; -import { Duration } from '../../utils/duration'; +import { Duration, PageFilters, ProductPeriod } from '../../types'; import { findAlways } from '../../utils/assert'; type ProductInsightsCardFilterProps = PageFilters & { diff --git a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx index c32afcd257..18f7fa151d 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx @@ -20,8 +20,7 @@ import { Box } from '@material-ui/core'; import { InfoCard } from '@backstage/core'; import { ResourceGrowthBarChart } from '../ResourceGrowthBarChart'; import { ResourceGrowthBarChartLegend } from '../ResourceGrowthBarChartLegend'; -import { ProjectGrowthData } from '../../types'; -import { Duration } from '../../utils/duration'; +import { Duration, ProjectGrowthData } from '../../types'; import { pluralOf } from '../../utils/grammar'; type ProjectGrowthAlertProps = { @@ -32,9 +31,8 @@ export const ProjectGrowthAlertCard = ({ alert }: ProjectGrowthAlertProps) => { const [costStart, costEnd] = alert.aggregation; const subheader = ` - ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${ - alert.products.length > 1 ? ', sorted by cost' : '' - }`; + ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${alert.products.length > 1 ? ', sorted by cost' : '' + }`; const previousName = moment(alert.periodStart, 'YYYY-[Q]Q').format( '[Q]Q YYYY', ); diff --git a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx index 074d3e2b92..f2083388ae 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx @@ -18,14 +18,14 @@ import React from 'react'; import { Box, Typography } from '@material-ui/core'; import { InfoCard } from '@backstage/core'; import { AlertInstructionsLayout } from '../AlertInstructionsLayout'; -import { Duration } from '../../utils/duration'; import { Alert, + Duration, Entity, Product, - ProjectGrowthAlert, ProjectGrowthData, } from '../../types'; +import { ProjectGrowthAlert } from '../../utils/alerts'; import { ResourceGrowthBarChartLegend } from '../ResourceGrowthBarChartLegend'; import { ResourceGrowthBarChart } from '../ResourceGrowthBarChart'; diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx index bf5c1021cc..47285a2363 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.test.tsx @@ -17,10 +17,10 @@ import React, { PropsWithChildren } from 'react'; import { renderInTestApp } from '@backstage/test-utils'; import { ResourceGrowthBarChartLegend } from './ResourceGrowthBarChartLegend'; -import { Duration } from '../../utils/duration'; import { defaultCurrencies } from '../../utils/currency'; import { findAlways } from '../../utils/assert'; import { MockConfigProvider, MockCurrencyProvider } from '../../utils/tests'; +import { Duration } from '../../types'; const engineers = findAlways(defaultCurrencies, c => c.kind === null); diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx index 0c281e6266..2e8e0f07a1 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx @@ -19,8 +19,7 @@ import { Box, useTheme } from '@material-ui/core'; import { LegendItem } from '../LegendItem'; import { CostGrowth } from '../CostGrowth'; import { currencyFormatter } from '../../utils/formatters'; -import { Duration } from '../../utils/duration'; -import { ChangeStatistic, CostInsightsTheme } from '../../types'; +import { ChangeStatistic, Duration, CostInsightsTheme } from '../../types'; export type ResourceGrowthBarChartLegendProps = { change: ChangeStatistic; diff --git a/plugins/cost-insights/src/index.ts b/plugins/cost-insights/src/index.ts index 119fc2035c..48b2425946 100644 --- a/plugins/cost-insights/src/index.ts +++ b/plugins/cost-insights/src/index.ts @@ -19,4 +19,5 @@ export * from './api'; export * from './components'; export { useCurrency } from './hooks'; export * from './types'; -export * from './utils/public'; +export * from './utils/tests'; +export * from './utils/duration'; diff --git a/plugins/cost-insights/src/types/Alert.tsx b/plugins/cost-insights/src/types/Alert.ts similarity index 59% rename from plugins/cost-insights/src/types/Alert.tsx rename to plugins/cost-insights/src/types/Alert.ts index 4ed55a844c..d6046e3241 100644 --- a/plugins/cost-insights/src/types/Alert.tsx +++ b/plugins/cost-insights/src/types/Alert.ts @@ -14,11 +14,8 @@ * limitations under the License. */ -import React from 'react'; import { ChangeStatistic } from './ChangeStatistic'; import { Maybe } from './Maybe'; -import { UnlabeledDataflowAlertCard } from '../components/UnlabeledDataflowAlertCard'; -import { ProjectGrowthAlertCard } from '../components/ProjectGrowthAlertCard'; /** * Generic alert type with required fields for display. The `element` field will be rendered in @@ -57,11 +54,6 @@ export enum DataKey { Name = 'name', } -/** - * The alerts below are examples of Alert implementation; the CostInsightsApi permits returning - * any implementation of the Alert type, so adopters can create their own. The CostInsightsApi - * fetches alert data from the backend, then creates Alert classes with the data. - */ export interface ProjectGrowthData { project: string; periodStart: string; @@ -71,26 +63,6 @@ export interface ProjectGrowthData { products: Array; } -export class ProjectGrowthAlert implements Alert { - data: ProjectGrowthData; - - constructor(data: ProjectGrowthData) { - this.data = data; - } - - get title() { - return `Investigate cost growth in project ${this.data.project}`; - } - - subtitle = - 'Cost growth outpacing business growth is unsustainable long-term.'; - url = '/cost-insights/investigating-growth'; - - get element() { - return ; - } -} - export interface UnlabeledDataflowData { periodStart: string; periodEnd: string; @@ -99,23 +71,6 @@ export interface UnlabeledDataflowData { labeledCost: number; } -export class UnlabeledDataflowAlert implements Alert { - data: UnlabeledDataflowData; - - constructor(data: UnlabeledDataflowData) { - this.data = data; - } - - title = 'Add labels to workflows'; - subtitle = - 'Labels show in billing data, enabling cost insights for each workflow.'; - url = '/cost-insights/labeling-jobs'; - - get element() { - return ; - } -} - export interface UnlabeledDataflowAlertProject { id: string; unlabeledCost: number; diff --git a/plugins/cost-insights/src/types/Currency.ts b/plugins/cost-insights/src/types/Currency.ts index 16ba432be8..8a8af81b0e 100644 --- a/plugins/cost-insights/src/types/Currency.ts +++ b/plugins/cost-insights/src/types/Currency.ts @@ -21,3 +21,10 @@ export interface Currency { prefix?: string; rate?: number; } + +export enum CurrencyType { + USD = 'USD', + CarbonOffsetTons = 'CARBON_OFFSET_TONS', + Beers = 'BEERS', + IceCream = 'PINTS_OF_ICE_CREAM', +} diff --git a/plugins/cost-insights/src/utils/icon.ts b/plugins/cost-insights/src/types/Duration.ts similarity index 59% rename from plugins/cost-insights/src/utils/icon.ts rename to plugins/cost-insights/src/types/Duration.ts index de957743ba..a1eb9aa31e 100644 --- a/plugins/cost-insights/src/utils/icon.ts +++ b/plugins/cost-insights/src/types/Duration.ts @@ -14,11 +14,15 @@ * limitations under the License. */ -export enum IconType { - Compute = 'compute', - Data = 'data', - Database = 'database', - Storage = 'storage', - Search = 'search', - ML = 'ml', +/** + * Time periods for cost comparison; slight abuse of ISO 8601 periods. We take P1M and P3M to mean + * 'last completed [month|quarter]', and P30D/P90D to be '[month|quarter] relative to today'. So if + * it's September 15, P1M represents costs for the month of August and P30D represents August 16 - + * September 15. + */ +export enum Duration { + P30D = 'P30D', + P90D = 'P90D', + P1M = 'P1M', + P3M = 'P3M', } diff --git a/plugins/cost-insights/src/types/Filters.ts b/plugins/cost-insights/src/types/Filters.ts index da71471f50..120738fcc7 100644 --- a/plugins/cost-insights/src/types/Filters.ts +++ b/plugins/cost-insights/src/types/Filters.ts @@ -15,7 +15,7 @@ */ import { Maybe } from './Maybe'; -import { Duration } from '../utils/duration'; +import { Duration } from './Duration'; export interface PageFilters { group: Maybe; diff --git a/plugins/cost-insights/src/types/Icon.ts b/plugins/cost-insights/src/types/Icon.ts index db5520ca15..70f43a6813 100644 --- a/plugins/cost-insights/src/types/Icon.ts +++ b/plugins/cost-insights/src/types/Icon.ts @@ -18,3 +18,12 @@ export type Icon = { kind: string; component: JSX.Element; }; + +export enum IconType { + Compute = 'compute', + Data = 'data', + Database = 'database', + Storage = 'storage', + Search = 'search', + ML = 'ml', +} diff --git a/plugins/cost-insights/src/types/index.ts b/plugins/cost-insights/src/types/index.ts index cced505f86..398110ec80 100644 --- a/plugins/cost-insights/src/types/index.ts +++ b/plugins/cost-insights/src/types/index.ts @@ -19,6 +19,7 @@ export * from './ChangeStatistic'; export * from './ChartData'; export * from './Cost'; export * from './DateAggregation'; +export * from './Duration'; export * from './Currency'; export * from './Entity'; export * from './Icon'; diff --git a/plugins/cost-insights/src/utils/alerts.tsx b/plugins/cost-insights/src/utils/alerts.tsx new file mode 100644 index 0000000000..fcb41f1e3b --- /dev/null +++ b/plugins/cost-insights/src/utils/alerts.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { Alert, UnlabeledDataflowData, ProjectGrowthData } from '../types'; +import { UnlabeledDataflowAlertCard } from '../components/UnlabeledDataflowAlertCard'; +import { ProjectGrowthAlertCard } from '../components/ProjectGrowthAlertCard'; + +/** + * The alerts below are examples of Alert implementation; the CostInsightsApi permits returning + * any implementation of the Alert type, so adopters can create their own. The CostInsightsApi + * fetches alert data from the backend, then creates Alert classes with the data. + */ + +export class UnlabeledDataflowAlert implements Alert { + data: UnlabeledDataflowData; + + constructor(data: UnlabeledDataflowData) { + this.data = data; + } + + title = 'Add labels to workflows'; + subtitle = + 'Labels show in billing data, enabling cost insights for each workflow.'; + url = '/cost-insights/labeling-jobs'; + + get element() { + return ; + } +} + +export class ProjectGrowthAlert implements Alert { + data: ProjectGrowthData; + + constructor(data: ProjectGrowthData) { + this.data = data; + } + + get title() { + return `Investigate cost growth in project ${this.data.project}`; + } + + subtitle = + 'Cost growth outpacing business growth is unsustainable long-term.'; + url = '/cost-insights/investigating-growth'; + + get element() { + return ; + } +} diff --git a/plugins/cost-insights/src/utils/currency.ts b/plugins/cost-insights/src/utils/currency.ts index 7f43acc66b..663a29a112 100644 --- a/plugins/cost-insights/src/utils/currency.ts +++ b/plugins/cost-insights/src/utils/currency.ts @@ -13,17 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Currency } from '../types'; -import { Duration } from '../utils/duration'; +import { Currency, CurrencyType, Duration } from '../types'; import { assertNever } from '../utils/assert'; -export enum CurrencyType { - USD = 'USD', - CarbonOffsetTons = 'CARBON_OFFSET_TONS', - Beers = 'BEERS', - IceCream = 'PINTS_OF_ICE_CREAM', -} - export const rateOf = (cost: number, duration: Duration) => { switch (duration) { case Duration.P1M: diff --git a/plugins/cost-insights/src/utils/duration.test.ts b/plugins/cost-insights/src/utils/duration.test.ts index 675a90b54a..a5509eda07 100644 --- a/plugins/cost-insights/src/utils/duration.test.ts +++ b/plugins/cost-insights/src/utils/duration.test.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { Duration, inclusiveEndDateOf, inclusiveStartDateOf } from './duration'; +import { Duration } from '../types'; +import { inclusiveEndDateOf, inclusiveStartDateOf } from './duration'; const lastCompleteBillingDate = '2020-06-05'; diff --git a/plugins/cost-insights/src/utils/duration.ts b/plugins/cost-insights/src/utils/duration.ts index 09034ae9df..d90e78dc5f 100644 --- a/plugins/cost-insights/src/utils/duration.ts +++ b/plugins/cost-insights/src/utils/duration.ts @@ -15,20 +15,8 @@ */ import moment from 'moment'; -import { assertNever } from '../utils/assert'; - -/** - * Time periods for cost comparison; slight abuse of ISO 8601 periods. We take P1M and P3M to mean - * 'last completed [month|quarter]', and P30D/P90D to be '[month|quarter] relative to today'. So if - * it's September 15, P1M represents costs for the month of August and P30D represents August 16 - - * September 15. - */ -export enum Duration { - P30D = 'P30D', - P90D = 'P90D', - P1M = 'P1M', - P3M = 'P3M', -} +import { Duration } from '../types'; +import { assertNever } from './assert'; export const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD'; diff --git a/plugins/cost-insights/src/utils/filters.ts b/plugins/cost-insights/src/utils/filters.ts index 26d2bc6cf3..fbe1bf46cc 100644 --- a/plugins/cost-insights/src/utils/filters.ts +++ b/plugins/cost-insights/src/utils/filters.ts @@ -14,8 +14,7 @@ * limitations under the License. */ -import { Group, PageFilters } from '../types'; -import { Duration } from './duration'; +import { Duration, Group, PageFilters } from '../types'; export function getDefaultPageFilters(groups: Group[]): PageFilters { return { diff --git a/plugins/cost-insights/src/utils/formatters.test.ts b/plugins/cost-insights/src/utils/formatters.test.ts index 7be6e1dffb..69e9086be1 100644 --- a/plugins/cost-insights/src/utils/formatters.test.ts +++ b/plugins/cost-insights/src/utils/formatters.test.ts @@ -19,7 +19,7 @@ import { lengthyCurrencyFormatter, quarterOf, } from './formatters'; -import { Duration } from '../utils/duration'; +import { Duration } from '../types'; Date.now = jest.fn(() => new Date(Date.parse('2019-12-07')).valueOf()); diff --git a/plugins/cost-insights/src/utils/formatters.ts b/plugins/cost-insights/src/utils/formatters.ts index 48b0b77188..fc563bf836 100644 --- a/plugins/cost-insights/src/utils/formatters.ts +++ b/plugins/cost-insights/src/utils/formatters.ts @@ -15,8 +15,8 @@ */ import moment from 'moment'; +import { Duration } from '../types'; import { - Duration, inclusiveEndDateOf, inclusiveStartDateOf, } from '../utils/duration'; diff --git a/plugins/cost-insights/src/utils/history.ts b/plugins/cost-insights/src/utils/history.ts index 36f4e9a5b0..7d45cfdad2 100644 --- a/plugins/cost-insights/src/utils/history.ts +++ b/plugins/cost-insights/src/utils/history.ts @@ -16,8 +16,7 @@ import qs from 'qs'; import * as yup from 'yup'; -import { Group, PageFilters } from '../types'; -import { Duration } from '../utils/duration'; +import { Duration, Group, PageFilters } from '../types'; import { getDefaultPageFilters } from '../utils/filters'; import { ConfigContextProps } from '../hooks/useConfig'; diff --git a/plugins/cost-insights/src/utils/loading.ts b/plugins/cost-insights/src/utils/loading.ts index 7a0225154f..4652603926 100644 --- a/plugins/cost-insights/src/utils/loading.ts +++ b/plugins/cost-insights/src/utils/loading.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Loading } from '../types'; export enum DefaultLoadingAction { diff --git a/plugins/cost-insights/src/utils/mockData.ts b/plugins/cost-insights/src/utils/mockData.ts index 91cd2f8ad2..58ba4a4251 100644 --- a/plugins/cost-insights/src/utils/mockData.ts +++ b/plugins/cost-insights/src/utils/mockData.ts @@ -17,6 +17,7 @@ import { Config } from '@backstage/config'; import { ConfigApi } from '@backstage/core'; import { + Duration, Entity, Product, ProductCost, @@ -30,7 +31,6 @@ import { getDefaultState as getDefaultLoadingState, } from '../utils/loading'; import { findAlways } from '../utils/assert'; -import { Duration } from '../utils/duration'; type mockAlertRenderer = (alert: T) => T; type mockEntityRenderer = (entity: T) => T; diff --git a/plugins/cost-insights/src/utils/navigation.tsx b/plugins/cost-insights/src/utils/navigation.tsx index 39016f6092..d2cb1d20bb 100644 --- a/plugins/cost-insights/src/utils/navigation.tsx +++ b/plugins/cost-insights/src/utils/navigation.tsx @@ -23,7 +23,7 @@ import Search from '@material-ui/icons/Search'; import CloudQueue from '@material-ui/icons/CloudQueue'; import School from '@material-ui/icons/School'; import ViewHeadline from '@material-ui/icons/ViewHeadline'; -import { IconType } from '../utils/icon'; +import { IconType } from '../types'; export enum DefaultNavigation { CostOverviewCard = 'cost-overview-card', diff --git a/plugins/cost-insights/src/utils/public/index.ts b/plugins/cost-insights/src/utils/public/index.ts deleted file mode 100644 index ffc2d5c882..0000000000 --- a/plugins/cost-insights/src/utils/public/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export * from '../tests'; -export { Duration } from '../duration'; -export { CurrencyType } from '../currency'; -export { IconType } from '../icon'; diff --git a/plugins/cost-insights/src/utils/tests.tsx b/plugins/cost-insights/src/utils/tests.tsx index 09eab89139..852330acc3 100644 --- a/plugins/cost-insights/src/utils/tests.tsx +++ b/plugins/cost-insights/src/utils/tests.tsx @@ -32,8 +32,7 @@ import { BillingDateContextProps, } from '../hooks/useLastCompleteBillingDate'; import { ScrollContext, ScrollContextProps } from '../hooks/useScroll'; -import { Duration } from '../utils/duration'; -import { Group } from '../types'; +import { Group, Duration } from '../types'; /* Mock Providers and types are exposed publicly to allow users to test custom implementations From bbf52b659570988c6d9f0b2cdddaba9a16981750 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Thu, 29 Oct 2020 14:43:02 -0400 Subject: [PATCH 12/20] fix alert link --- plugins/cost-insights/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cost-insights/README.md b/plugins/cost-insights/README.md index 8c2fd11761..3b6e1e4fd5 100644 --- a/plugins/cost-insights/README.md +++ b/plugins/cost-insights/README.md @@ -106,7 +106,7 @@ costInsights: ## Alerts -The CostInsightsApi `getAlerts` method may return any type of alert or recommendation (called collectively "Action Items" in Cost Insights) that implements the [Alert type](https://github.com/spotify/backstage/blob/master/plugins/cost-insights/src/types/Alert.tsx). This allows you to deliver any alerts or recommendations specific to your infrastructure or company migrations. +The CostInsightsApi `getAlerts` method may return any type of alert or recommendation (called collectively "Action Items" in Cost Insights) that implements the [Alert type](https://github.com/spotify/backstage/blob/master/plugins/cost-insights/src/types/Alert.ts). This allows you to deliver any alerts or recommendations specific to your infrastructure or company migrations. The Alert type includes an `element` field to supply the JSX Element that will be rendered in the Cost Insights "Action Items" section; we recommend using Backstage's [InfoCard](https://backstage.io/storybook/?path=/story/layout-information-card--default) and [Recharts](http://recharts.org/en-US/) to show actionable visualizations. From 3f5ef4ac1617c152daf3312d2280f34bf8f738ac Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Thu, 29 Oct 2020 15:52:18 -0400 Subject: [PATCH 13/20] formatting --- .../src/api/ExampleCostInsightsClient.ts | 5 +---- .../components/CostGrowth/CostGrowth.test.tsx | 8 ++++---- .../ProjectGrowthAlertCard.tsx | 5 +++-- plugins/cost-insights/src/utils/alerts.tsx | 16 ++++++++++++++++ plugins/cost-insights/src/utils/formatters.ts | 5 +---- 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts b/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts index 70695beb25..8cc66e626f 100644 --- a/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts +++ b/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts @@ -33,10 +33,7 @@ import { Trendline, UnlabeledDataflowData, } from '../types'; -import { - ProjectGrowthAlert, - UnlabeledDataflowAlert -} from '../utils/alerts'; +import { ProjectGrowthAlert, UnlabeledDataflowAlert } from '../utils/alerts'; import { DEFAULT_DATE_FORMAT, exclusiveEndDateOf, diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx index 046394ca7a..9c76d6d998 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.test.tsx @@ -37,10 +37,10 @@ const MockContext = ({ currency: Currency; engineerCost: number; }>) => ( - - {children} - - ); + + {children} + +); describe.each` engineerCost | ratio | amount | expected diff --git a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx index 18f7fa151d..4311bcc1bf 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.tsx @@ -31,8 +31,9 @@ export const ProjectGrowthAlertCard = ({ alert }: ProjectGrowthAlertProps) => { const [costStart, costEnd] = alert.aggregation; const subheader = ` - ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${alert.products.length > 1 ? ', sorted by cost' : '' - }`; + ${alert.products.length} ${pluralOf(alert.products.length, 'product')}${ + alert.products.length > 1 ? ', sorted by cost' : '' + }`; const previousName = moment(alert.periodStart, 'YYYY-[Q]Q').format( '[Q]Q YYYY', ); diff --git a/plugins/cost-insights/src/utils/alerts.tsx b/plugins/cost-insights/src/utils/alerts.tsx index fcb41f1e3b..fbb148f38a 100644 --- a/plugins/cost-insights/src/utils/alerts.tsx +++ b/plugins/cost-insights/src/utils/alerts.tsx @@ -1,3 +1,19 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import React from 'react'; import { Alert, UnlabeledDataflowData, ProjectGrowthData } from '../types'; import { UnlabeledDataflowAlertCard } from '../components/UnlabeledDataflowAlertCard'; diff --git a/plugins/cost-insights/src/utils/formatters.ts b/plugins/cost-insights/src/utils/formatters.ts index fc563bf836..bf8e26ef5f 100644 --- a/plugins/cost-insights/src/utils/formatters.ts +++ b/plugins/cost-insights/src/utils/formatters.ts @@ -16,10 +16,7 @@ import moment from 'moment'; import { Duration } from '../types'; -import { - inclusiveEndDateOf, - inclusiveStartDateOf, -} from '../utils/duration'; +import { inclusiveEndDateOf, inclusiveStartDateOf } from '../utils/duration'; import { pluralOf } from '../utils/grammar'; export type Period = { From a40536a24ba9deba68c784a63cf094790fd68ff7 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Thu, 29 Oct 2020 17:31:05 -0400 Subject: [PATCH 14/20] move example client out of src to break import cycles --- plugins/cost-insights/dev/index.tsx | 4 ++-- plugins/cost-insights/src/api/index.ts | 1 - .../src/{api/ExampleCostInsightsClient.ts => client.ts} | 8 ++++---- plugins/cost-insights/src/index.ts | 1 + 4 files changed, 7 insertions(+), 7 deletions(-) rename plugins/cost-insights/src/{api/ExampleCostInsightsClient.ts => client.ts} (97%) diff --git a/plugins/cost-insights/dev/index.tsx b/plugins/cost-insights/dev/index.tsx index 836aea0edb..fe208d5bb8 100644 --- a/plugins/cost-insights/dev/index.tsx +++ b/plugins/cost-insights/dev/index.tsx @@ -15,8 +15,8 @@ */ import { createDevApp } from '@backstage/dev-utils'; import { createPlugin, createApiFactory } from '@backstage/core'; -import { ExampleCostInsightsClient } from '../src/api'; -import { costInsightsApiRef } from '../src'; +import { costInsightsApiRef } from '../src/api'; +import { ExampleCostInsightsClient } from '../src/client'; import { pluginConfig } from '../src/plugin'; const devPlugin = createPlugin({ diff --git a/plugins/cost-insights/src/api/index.ts b/plugins/cost-insights/src/api/index.ts index a367df9487..d231570e9b 100644 --- a/plugins/cost-insights/src/api/index.ts +++ b/plugins/cost-insights/src/api/index.ts @@ -15,4 +15,3 @@ */ export * from './CostInsightsApi'; -export * from './ExampleCostInsightsClient'; diff --git a/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts b/plugins/cost-insights/src/client.ts similarity index 97% rename from plugins/cost-insights/src/api/ExampleCostInsightsClient.ts rename to plugins/cost-insights/src/client.ts index 8cc66e626f..b73e824031 100644 --- a/plugins/cost-insights/src/api/ExampleCostInsightsClient.ts +++ b/plugins/cost-insights/src/client.ts @@ -17,7 +17,7 @@ import dayjs from 'dayjs'; import regression, { DataPoint } from 'regression'; -import { CostInsightsApi } from './CostInsightsApi'; +import { CostInsightsApi } from './api'; import { Alert, ChangeStatistic, @@ -32,13 +32,13 @@ import { ProjectGrowthData, Trendline, UnlabeledDataflowData, -} from '../types'; -import { ProjectGrowthAlert, UnlabeledDataflowAlert } from '../utils/alerts'; +} from './types'; +import { ProjectGrowthAlert, UnlabeledDataflowAlert } from './utils/alerts'; import { DEFAULT_DATE_FORMAT, exclusiveEndDateOf, inclusiveStartDateOf, -} from '../utils/duration'; +} from './utils/duration'; type IntervalFields = { duration: Duration; diff --git a/plugins/cost-insights/src/index.ts b/plugins/cost-insights/src/index.ts index 48b2425946..795d4e14a6 100644 --- a/plugins/cost-insights/src/index.ts +++ b/plugins/cost-insights/src/index.ts @@ -15,6 +15,7 @@ */ export { plugin } from './plugin'; +export * from './ExampleCostInsightsClient'; export * from './api'; export * from './components'; export { useCurrency } from './hooks'; From f454f0eecca9dd35f60b4f47f9ccc1b30a5020f1 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Thu, 29 Oct 2020 17:34:01 -0400 Subject: [PATCH 15/20] make thresholds and growth enums public --- .../src/components/CostGrowth/CostGrowth.tsx | 4 ++-- plugins/cost-insights/src/types/ChangeStatistic.ts | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx index 3f5e0f55eb..da2f3e3c1b 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx @@ -16,9 +16,9 @@ import React from 'react'; import classnames from 'classnames'; -import { ChangeStatistic, CurrencyType, Duration } from '../../types'; +import { ChangeStatistic, CurrencyType, Duration, EngineerThreshold, GrowthType } from '../../types'; import { rateOf } from '../../utils/currency'; -import { growthOf, GrowthType, EngineerThreshold } from '../../utils/change'; +import { growthOf } from '../../utils/change'; import { useCostGrowthStyles as useStyles } from '../../utils/styles'; import { formatPercent, formatCurrency } from '../../utils/formatters'; import { indefiniteArticleOf } from '../../utils/grammar'; diff --git a/plugins/cost-insights/src/types/ChangeStatistic.ts b/plugins/cost-insights/src/types/ChangeStatistic.ts index e60d47a0e6..a47640411a 100644 --- a/plugins/cost-insights/src/types/ChangeStatistic.ts +++ b/plugins/cost-insights/src/types/ChangeStatistic.ts @@ -20,3 +20,16 @@ export interface ChangeStatistic { // The actual USD change between time periods (can be negative if costs decreased) amount: number; } + +export const EngineerThreshold = 0.5; + +export enum ChangeThreshold { + upper = 0.05, + lower = -0.05, +} + +export enum GrowthType { + Negligible, + Savings, + Excess, +} From 24b8f78d5fdd8d71096f6c0427942fee052fec1b Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Thu, 29 Oct 2020 17:36:52 -0400 Subject: [PATCH 16/20] make client public --- plugins/cost-insights/src/client.ts | 8 ++++---- plugins/cost-insights/src/index.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/cost-insights/src/client.ts b/plugins/cost-insights/src/client.ts index b73e824031..979a7a44ef 100644 --- a/plugins/cost-insights/src/client.ts +++ b/plugins/cost-insights/src/client.ts @@ -17,7 +17,7 @@ import dayjs from 'dayjs'; import regression, { DataPoint } from 'regression'; -import { CostInsightsApi } from './api'; +import { CostInsightsApi } from '../src/api'; import { Alert, ChangeStatistic, @@ -32,13 +32,13 @@ import { ProjectGrowthData, Trendline, UnlabeledDataflowData, -} from './types'; -import { ProjectGrowthAlert, UnlabeledDataflowAlert } from './utils/alerts'; +} from '../src/types'; +import { ProjectGrowthAlert, UnlabeledDataflowAlert } from '../src/utils/alerts'; import { DEFAULT_DATE_FORMAT, exclusiveEndDateOf, inclusiveStartDateOf, -} from './utils/duration'; +} from '../src/utils/duration'; type IntervalFields = { duration: Duration; diff --git a/plugins/cost-insights/src/index.ts b/plugins/cost-insights/src/index.ts index 795d4e14a6..1e6172d568 100644 --- a/plugins/cost-insights/src/index.ts +++ b/plugins/cost-insights/src/index.ts @@ -15,7 +15,7 @@ */ export { plugin } from './plugin'; -export * from './ExampleCostInsightsClient'; +export * from './client'; export * from './api'; export * from './components'; export { useCurrency } from './hooks'; From c894503435f36712d10da018d582f1ec1ae0c2d3 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Thu, 29 Oct 2020 17:38:24 -0400 Subject: [PATCH 17/20] revert order --- .../ResourceGrowthBarChartLegend.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx index 2e8e0f07a1..6b5ce17c95 100644 --- a/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx +++ b/plugins/cost-insights/src/components/ResourceGrowthBarChartLegend/ResourceGrowthBarChartLegend.tsx @@ -19,7 +19,7 @@ import { Box, useTheme } from '@material-ui/core'; import { LegendItem } from '../LegendItem'; import { CostGrowth } from '../CostGrowth'; import { currencyFormatter } from '../../utils/formatters'; -import { ChangeStatistic, Duration, CostInsightsTheme } from '../../types'; +import { ChangeStatistic, CostInsightsTheme, Duration } from '../../types'; export type ResourceGrowthBarChartLegendProps = { change: ChangeStatistic; From 7926f07735514f2fe6d76f5dad8f09597742ea61 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Thu, 29 Oct 2020 17:39:02 -0400 Subject: [PATCH 18/20] make default date format public --- plugins/cost-insights/src/types/Duration.ts | 2 ++ plugins/cost-insights/src/utils/duration.ts | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/cost-insights/src/types/Duration.ts b/plugins/cost-insights/src/types/Duration.ts index a1eb9aa31e..acf707dd1e 100644 --- a/plugins/cost-insights/src/types/Duration.ts +++ b/plugins/cost-insights/src/types/Duration.ts @@ -26,3 +26,5 @@ export enum Duration { P1M = 'P1M', P3M = 'P3M', } + +export const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD'; diff --git a/plugins/cost-insights/src/utils/duration.ts b/plugins/cost-insights/src/utils/duration.ts index d90e78dc5f..6a880b382c 100644 --- a/plugins/cost-insights/src/utils/duration.ts +++ b/plugins/cost-insights/src/utils/duration.ts @@ -15,11 +15,9 @@ */ import moment from 'moment'; -import { Duration } from '../types'; +import { Duration, DEFAULT_DATE_FORMAT } from '../types'; import { assertNever } from './assert'; -export const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD'; - /** * Derive the start date of a given period, assuming two repeating intervals. * From ce0e0f12c5d9cf991e980d91ec6da7ab50424b2c Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Thu, 29 Oct 2020 17:41:38 -0400 Subject: [PATCH 19/20] formatting --- plugins/cost-insights/src/client.ts | 5 ++++- .../src/components/CostGrowth/CostGrowth.tsx | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/cost-insights/src/client.ts b/plugins/cost-insights/src/client.ts index 979a7a44ef..914fdb7b64 100644 --- a/plugins/cost-insights/src/client.ts +++ b/plugins/cost-insights/src/client.ts @@ -33,7 +33,10 @@ import { Trendline, UnlabeledDataflowData, } from '../src/types'; -import { ProjectGrowthAlert, UnlabeledDataflowAlert } from '../src/utils/alerts'; +import { + ProjectGrowthAlert, + UnlabeledDataflowAlert, +} from '../src/utils/alerts'; import { DEFAULT_DATE_FORMAT, exclusiveEndDateOf, diff --git a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx index da2f3e3c1b..89e44ee185 100644 --- a/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx +++ b/plugins/cost-insights/src/components/CostGrowth/CostGrowth.tsx @@ -16,7 +16,13 @@ import React from 'react'; import classnames from 'classnames'; -import { ChangeStatistic, CurrencyType, Duration, EngineerThreshold, GrowthType } from '../../types'; +import { + ChangeStatistic, + CurrencyType, + Duration, + EngineerThreshold, + GrowthType, +} from '../../types'; import { rateOf } from '../../utils/currency'; import { growthOf } from '../../utils/change'; import { useCostGrowthStyles as useStyles } from '../../utils/styles'; From 94d351d605ae26cf06aa9c4e3646bf9d85eca48c Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Thu, 29 Oct 2020 18:46:17 -0400 Subject: [PATCH 20/20] fix imports --- plugins/cost-insights/src/client.ts | 2 +- .../CostOverviewCard/CostOverviewTooltip.tsx | 2 +- plugins/cost-insights/src/utils/change.ts | 22 +++++++------------ 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/plugins/cost-insights/src/client.ts b/plugins/cost-insights/src/client.ts index 914fdb7b64..f7671bcce0 100644 --- a/plugins/cost-insights/src/client.ts +++ b/plugins/cost-insights/src/client.ts @@ -23,6 +23,7 @@ import { ChangeStatistic, Cost, DateAggregation, + DEFAULT_DATE_FORMAT, Duration, Group, Maybe, @@ -38,7 +39,6 @@ import { UnlabeledDataflowAlert, } from '../src/utils/alerts'; import { - DEFAULT_DATE_FORMAT, exclusiveEndDateOf, inclusiveStartDateOf, } from '../src/utils/duration'; diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx index 51f2f12bdb..e0a9b9a9ea 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewTooltip.tsx @@ -17,7 +17,7 @@ import React from 'react'; import moment from 'moment'; import { TooltipPayload, TooltipProps } from 'recharts'; import { Tooltip, TooltipItemProps } from '../../components/Tooltip'; -import { DEFAULT_DATE_FORMAT } from '../../utils/duration'; +import { DEFAULT_DATE_FORMAT } from '../../types'; export type CostOverviewTooltipProps = TooltipProps & { dataKeys: Array; diff --git a/plugins/cost-insights/src/utils/change.ts b/plugins/cost-insights/src/utils/change.ts index f5c6570b36..1fe3662537 100644 --- a/plugins/cost-insights/src/utils/change.ts +++ b/plugins/cost-insights/src/utils/change.ts @@ -14,22 +14,16 @@ * limitations under the License. */ -import { Cost, ChangeStatistic, MetricData } from '../types'; +import { + Cost, + ChangeStatistic, + ChangeThreshold, + EngineerThreshold, + GrowthType, + MetricData, +} from '../types'; import { aggregationSort } from '../utils/sort'; -export const EngineerThreshold = 0.5; - -export enum ChangeThreshold { - upper = 0.05, - lower = -0.05, -} - -export enum GrowthType { - Negligible, - Savings, - Excess, -} - // Used by for displaying status colors export function growthOf(amount: number, ratio: number) { if (amount >= EngineerThreshold && ratio >= ChangeThreshold.upper) {