From 59e42b4ca77d7458ebf8648b5fdcb17be17424f4 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Thu, 29 Oct 2020 14:28:42 -0400 Subject: [PATCH] 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