@backstage-community/plugin-cost-insights 0.27.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/alerts/ProjectGrowthAlert.esm.js.map +1 -1
- package/dist/alerts/UnlabeledDataflowAlert.esm.js.map +1 -1
- package/dist/alpha/plugin.esm.js +1 -1
- package/dist/alpha/plugin.esm.js.map +1 -1
- package/dist/alpha/router.esm.js.map +1 -1
- package/dist/alpha.d.ts +31 -10
- package/dist/api/CostInsightsApi.esm.js.map +1 -1
- package/dist/components/ActionItems/ActionItemCard.esm.js.map +1 -1
- package/dist/components/ActionItems/ActionItems.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertDialog.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsights.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsightsHeader.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsightsSection.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsightsSectionHeader.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertStatusSummary.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertStatusSummaryButton.esm.js.map +1 -1
- package/dist/components/AlertInstructionsLayout/AlertInstructionsLayout.esm.js.map +1 -1
- package/dist/components/BarChart/BarChart.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartLabel.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartLegend.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartStepper.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartStepperButton.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartSteps.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartTick.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartTooltip.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartTooltipItem.esm.js.map +1 -1
- package/dist/components/CopyUrlToClipboard/CopyUrlToClipboard.esm.js.map +1 -1
- package/dist/components/CostGrowth/CostGrowth.esm.js.map +1 -1
- package/dist/components/CostGrowth/CostGrowthIndicator.esm.js.map +1 -1
- package/dist/components/CostInsightsHeader/CostInsightsHeader.esm.js.map +1 -1
- package/dist/components/CostInsightsLayout/CostInsightsLayout.esm.js.map +1 -1
- package/dist/components/CostInsightsNavigation/CostInsightsNavigation.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/CostInsightsPage.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/CostInsightsPageRoot.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/CostInsightsThemeProvider.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/index.esm.js +5 -1
- package/dist/components/CostInsightsPage/index.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/selector.esm.js +1 -1
- package/dist/components/CostInsightsPage/selector.esm.js.map +1 -1
- package/dist/components/CostInsightsTabs/CostInsightsTabs.esm.js.map +1 -1
- package/dist/components/CostInsightsTabs/selector.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewBreakdownChart.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewCard.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewChart.esm.js +1 -1
- package/dist/components/CostOverviewCard/CostOverviewChart.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewHeader.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewLegend.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/selector.esm.js.map +1 -1
- package/dist/components/CurrencySelect/CurrencySelect.esm.js.map +1 -1
- package/dist/components/EntityCosts/EntityCosts.esm.js.map +1 -1
- package/dist/components/EntityCosts/index.esm.js +5 -1
- package/dist/components/EntityCosts/index.esm.js.map +1 -1
- package/dist/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.esm.js.map +1 -1
- package/dist/components/LabelDataflowInstructionsPage/index.esm.js +5 -1
- package/dist/components/LabelDataflowInstructionsPage/index.esm.js.map +1 -1
- package/dist/components/LegendItem/LegendItem.esm.js.map +1 -1
- package/dist/components/MetricSelect/MetricSelect.esm.js.map +1 -1
- package/dist/components/PeriodSelect/DateRangePicker.esm.js.map +1 -1
- package/dist/components/ProductInsights/ProductInsights.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductEntityDialog.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductEntityTable.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductInsightsCard.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductInsightsCardList.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductInsightsChart.esm.js.map +1 -1
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.esm.js.map +1 -1
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertChart.esm.js.map +1 -1
- package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js +0 -1
- package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js.map +1 -1
- package/dist/components/ProjectGrowthInstructionsPage/index.esm.js +5 -1
- package/dist/components/ProjectGrowthInstructionsPage/index.esm.js.map +1 -1
- package/dist/components/ProjectSelect/ProjectSelect.esm.js.map +1 -1
- package/dist/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.esm.js.map +1 -1
- package/dist/components/WhyCostsMatter/WhyCostsMatter.esm.js.map +1 -1
- package/dist/example/alerts/KubernetesMigrationAlert.esm.js.map +1 -1
- package/dist/example/client.esm.js +1 -1
- package/dist/example/client.esm.js.map +1 -1
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.esm.js.map +1 -1
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.esm.js.map +1 -1
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.esm.js.map +1 -1
- package/dist/example/forms/KubernetesMigrationDismissForm.esm.js.map +1 -1
- package/dist/forms/AlertAcceptForm.esm.js.map +1 -1
- package/dist/forms/AlertDismissForm.esm.js.map +1 -1
- package/dist/forms/AlertSnoozeForm.esm.js.map +1 -1
- package/dist/hooks/useConfig.esm.js +2 -2
- package/dist/hooks/useConfig.esm.js.map +1 -1
- package/dist/hooks/useCurrency.esm.js +1 -1
- package/dist/hooks/useCurrency.esm.js.map +1 -1
- package/dist/hooks/useFilters.esm.js +1 -1
- package/dist/hooks/useFilters.esm.js.map +1 -1
- package/dist/hooks/useGroups.esm.js +1 -1
- package/dist/hooks/useGroups.esm.js.map +1 -1
- package/dist/hooks/useLastCompleteBillingDate.esm.js +1 -1
- package/dist/hooks/useLastCompleteBillingDate.esm.js.map +1 -1
- package/dist/hooks/useLoading.esm.js +1 -1
- package/dist/hooks/useLoading.esm.js.map +1 -1
- package/dist/hooks/useScroll.esm.js +1 -1
- package/dist/hooks/useScroll.esm.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/plugin.esm.js +1 -1
- package/dist/plugin.esm.js.map +1 -1
- package/dist/routes.esm.js.map +1 -1
- package/dist/testUtils/filters.esm.js.map +1 -1
- package/dist/testUtils/loading.esm.js.map +1 -1
- package/dist/testUtils/mockData.esm.js.map +1 -1
- package/dist/testUtils/products.esm.js.map +1 -1
- package/dist/testUtils/providers.esm.js.map +1 -1
- package/dist/testUtils/testUtils.esm.js.map +1 -1
- package/dist/types/Alert.esm.js.map +1 -1
- package/dist/types/ChangeStatistic.esm.js.map +1 -1
- package/dist/types/CurrencyType.esm.js.map +1 -1
- package/dist/types/DateFormat.esm.js.map +1 -1
- package/dist/types/Duration.esm.js.map +1 -1
- package/dist/types/Icon.esm.js.map +1 -1
- package/dist/utils/alerts.esm.js.map +1 -1
- package/dist/utils/assert.esm.js.map +1 -1
- package/dist/utils/change.esm.js.map +1 -1
- package/dist/utils/charts.esm.js.map +1 -1
- package/dist/utils/config.esm.js.map +1 -1
- package/dist/utils/currency.esm.js.map +1 -1
- package/dist/utils/duration.esm.js.map +1 -1
- package/dist/utils/filters.esm.js.map +1 -1
- package/dist/utils/formatters.esm.js.map +1 -1
- package/dist/utils/grammar.esm.js.map +1 -1
- package/dist/utils/graphs.esm.js +1 -1
- package/dist/utils/graphs.esm.js.map +1 -1
- package/dist/utils/history.esm.js.map +1 -1
- package/dist/utils/loading.esm.js.map +1 -1
- package/dist/utils/navigation.esm.js.map +1 -1
- package/dist/utils/scroll.esm.js.map +1 -1
- package/dist/utils/sort.esm.js.map +1 -1
- package/dist/utils/styles.esm.js.map +1 -1
- package/dist/utils/sum.esm.js.map +1 -1
- package/package.json +14 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KubernetesMigrationAlert.esm.js","sources":["../../../src/example/alerts/KubernetesMigrationAlert.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport pluralize from 'pluralize';\nimport Typography from '@material-ui/core/Typography';\nimport { KubernetesMigrationAlertCard } from '../components';\nimport { CostInsightsApi } from '../../api';\nimport {\n Alert,\n AlertForm,\n AlertOptions,\n AlertStatus,\n AlertSnoozeFormData,\n} from '../../types';\nimport {\n ChangeStatistic,\n Entity,\n} from '@backstage-community/plugin-cost-insights-common';\nimport {\n KubernetesMigrationDismissForm,\n KubernetesMigrationDismissFormData,\n} from '../forms';\nimport { Lifecycle } from '@backstage/core-components';\n\nexport interface KubernetesMigrationData {\n startDate: string;\n endDate: string;\n change: ChangeStatistic;\n services: Array<Entity>;\n}\n\nexport interface KubernetesMigrationApi extends Alert {\n api: CostInsightsApi;\n data: KubernetesMigrationData;\n}\n\n/**\n * This is an example of an Alert implementation using optional event hooks.\n *\n * Event hooks can be used to enable users to dismiss, snooze, or accept an action item\n * - or any combination thereof. Defining a hook will generate default UI - button, dialog and\n * form. Cost Insights does not preserve client side alert state - each hook is expected to return a new set of alerts.\n *\n * Snoozed, accepted, etc. alerts should define a corresponding status property. Alerts will be aggregated\n * by status in a collapsed view below Alert Insights section and a badge will appear in Action Items\n * showing the total alerts of that status.\n *\n * Customizing Alerts\n * Default forms can be overridden in two ways - by setting a form property to null or defining a custom component.\n *\n * If a form property is set to null, the Dialog will not render a form. This can be useful in scenarios\n * where data isn't needed from the user such as when a user accepts an action item's recommendation.\n *\n * If a form property is set to a React component, the Dialog will render the form component in place of the default form.\n * Form components must return valid form elements, and accept a ref and onSubmit event handler.\n * Custom forms must implement the corresponding event hook. See /forms for example implementations.\n */\n\nexport class KubernetesMigrationAlert implements KubernetesMigrationApi {\n api: CostInsightsApi;\n data: KubernetesMigrationData;\n\n subtitle =\n 'Services running on Kubernetes are estimated to save 50% or more compared to Compute Engine.';\n\n // Dialog will not render a form if form property set to null.\n AcceptForm = null;\n // Overrides default Dismiss form with a custom form component.\n DismissForm: AlertForm<\n KubernetesMigrationAlert,\n KubernetesMigrationDismissFormData\n > = KubernetesMigrationDismissForm;\n\n constructor(api: CostInsightsApi, data: KubernetesMigrationData) {\n this.api = api;\n this.data = data;\n }\n\n get title() {\n return (\n <Typography component=\"span\">\n Consider migrating{' '}\n {pluralize('service', this.data.services.length, true)} to Kubernetes{' '}\n <Lifecycle shorthand />\n </Typography>\n );\n }\n\n get element() {\n const subheader = `${pluralize(\n 'Service',\n this.data.services.length,\n true,\n )}, sorted by cost`;\n return (\n <KubernetesMigrationAlertCard\n data={this.data}\n title=\"Migrate to Kubernetes\"\n subheader={subheader}\n currentProduct=\"Compute Engine\"\n comparedProduct=\"Kubernetes\"\n />\n );\n }\n\n /* Fires when the onSubmit event is raised on a Dismiss form. Displays custom dismiss form. */\n async onDismissed(\n options: AlertOptions<KubernetesMigrationDismissFormData>,\n ): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Dismissed,\n },\n ]),\n );\n }\n\n /* Fires when the onSubmit event is raised on a Snooze form. Displays default snooze form. */\n async onSnoozed(\n options: AlertOptions<AlertSnoozeFormData>,\n ): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Snoozed,\n },\n ]),\n );\n }\n\n /* Fires when the Accept button is clicked. Dialog does not render a form. See KubernetesMigrationAlert.AcceptForm */\n async onAccepted(options: AlertOptions<null>): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Accepted,\n },\n ]),\n );\n }\n}\n"],"names":[],"mappings":";;;;;;;;AAuEO,MAAM,
|
|
1
|
+
{"version":3,"file":"KubernetesMigrationAlert.esm.js","sources":["../../../src/example/alerts/KubernetesMigrationAlert.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport pluralize from 'pluralize';\nimport Typography from '@material-ui/core/Typography';\nimport { KubernetesMigrationAlertCard } from '../components';\nimport { CostInsightsApi } from '../../api';\nimport {\n Alert,\n AlertForm,\n AlertOptions,\n AlertStatus,\n AlertSnoozeFormData,\n} from '../../types';\nimport {\n ChangeStatistic,\n Entity,\n} from '@backstage-community/plugin-cost-insights-common';\nimport {\n KubernetesMigrationDismissForm,\n KubernetesMigrationDismissFormData,\n} from '../forms';\nimport { Lifecycle } from '@backstage/core-components';\n\nexport interface KubernetesMigrationData {\n startDate: string;\n endDate: string;\n change: ChangeStatistic;\n services: Array<Entity>;\n}\n\nexport interface KubernetesMigrationApi extends Alert {\n api: CostInsightsApi;\n data: KubernetesMigrationData;\n}\n\n/**\n * This is an example of an Alert implementation using optional event hooks.\n *\n * Event hooks can be used to enable users to dismiss, snooze, or accept an action item\n * - or any combination thereof. Defining a hook will generate default UI - button, dialog and\n * form. Cost Insights does not preserve client side alert state - each hook is expected to return a new set of alerts.\n *\n * Snoozed, accepted, etc. alerts should define a corresponding status property. Alerts will be aggregated\n * by status in a collapsed view below Alert Insights section and a badge will appear in Action Items\n * showing the total alerts of that status.\n *\n * Customizing Alerts\n * Default forms can be overridden in two ways - by setting a form property to null or defining a custom component.\n *\n * If a form property is set to null, the Dialog will not render a form. This can be useful in scenarios\n * where data isn't needed from the user such as when a user accepts an action item's recommendation.\n *\n * If a form property is set to a React component, the Dialog will render the form component in place of the default form.\n * Form components must return valid form elements, and accept a ref and onSubmit event handler.\n * Custom forms must implement the corresponding event hook. See /forms for example implementations.\n */\n\nexport class KubernetesMigrationAlert implements KubernetesMigrationApi {\n api: CostInsightsApi;\n data: KubernetesMigrationData;\n\n subtitle =\n 'Services running on Kubernetes are estimated to save 50% or more compared to Compute Engine.';\n\n // Dialog will not render a form if form property set to null.\n AcceptForm = null;\n // Overrides default Dismiss form with a custom form component.\n DismissForm: AlertForm<\n KubernetesMigrationAlert,\n KubernetesMigrationDismissFormData\n > = KubernetesMigrationDismissForm;\n\n constructor(api: CostInsightsApi, data: KubernetesMigrationData) {\n this.api = api;\n this.data = data;\n }\n\n get title() {\n return (\n <Typography component=\"span\">\n Consider migrating{' '}\n {pluralize('service', this.data.services.length, true)} to Kubernetes{' '}\n <Lifecycle shorthand />\n </Typography>\n );\n }\n\n get element() {\n const subheader = `${pluralize(\n 'Service',\n this.data.services.length,\n true,\n )}, sorted by cost`;\n return (\n <KubernetesMigrationAlertCard\n data={this.data}\n title=\"Migrate to Kubernetes\"\n subheader={subheader}\n currentProduct=\"Compute Engine\"\n comparedProduct=\"Kubernetes\"\n />\n );\n }\n\n /* Fires when the onSubmit event is raised on a Dismiss form. Displays custom dismiss form. */\n async onDismissed(\n options: AlertOptions<KubernetesMigrationDismissFormData>,\n ): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Dismissed,\n },\n ]),\n );\n }\n\n /* Fires when the onSubmit event is raised on a Snooze form. Displays default snooze form. */\n async onSnoozed(\n options: AlertOptions<AlertSnoozeFormData>,\n ): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Snoozed,\n },\n ]),\n );\n }\n\n /* Fires when the Accept button is clicked. Dialog does not render a form. See KubernetesMigrationAlert.AcceptForm */\n async onAccepted(options: AlertOptions<null>): Promise<Alert[]> {\n const alerts = await this.api.getAlerts(options.group);\n return new Promise(resolve =>\n setTimeout(resolve, 750, [\n ...alerts.filter(a => a.title !== this.title),\n {\n title: this.title,\n subtitle: this.subtitle,\n status: AlertStatus.Accepted,\n },\n ]),\n );\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ import '../hooks/useLoading.esm.js';
|
|
|
16
16
|
import '../hooks/useScroll.esm.js';
|
|
17
17
|
import '../hooks/useLastCompleteBillingDate.esm.js';
|
|
18
18
|
import '../utils/currency.esm.js';
|
|
19
|
-
import { aggregationFor, changeOf,
|
|
19
|
+
import { aggregationFor, trendlineOf, changeOf, getGroupedProjects, getGroupedProducts, entityOf } from '../testUtils/testUtils.esm.js';
|
|
20
20
|
|
|
21
21
|
class ExampleCostInsightsClient {
|
|
22
22
|
request(_, res) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.esm.js","sources":["../../src/example/client.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/* eslint-disable no-restricted-imports */\n\nimport { DateTime } from 'luxon';\nimport { CostInsightsApi, ProductInsightsOptions } from '../api';\nimport {\n Alert,\n DEFAULT_DATE_FORMAT,\n ProjectGrowthData,\n UnlabeledDataflowData,\n} from '../types';\nimport {\n Entity,\n Group,\n MetricData,\n Project,\n Cost,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { KubernetesMigrationAlert } from './alerts';\nimport { ProjectGrowthAlert, UnlabeledDataflowAlert } from '../alerts';\nimport {\n aggregationFor,\n changeOf,\n entityOf,\n getGroupedProducts,\n getGroupedProjects,\n trendlineOf,\n} from '../testUtils';\n\n/** @public */\nexport class ExampleCostInsightsClient implements CostInsightsApi {\n private request(_: any, res: any): Promise<any> {\n return new Promise(resolve => setTimeout(resolve, 0, res));\n }\n\n getLastCompleteBillingDate(): Promise<string> {\n return Promise.resolve(\n DateTime.now().minus({ days: 1 }).toFormat(DEFAULT_DATE_FORMAT),\n );\n }\n\n async getUserGroups(userId: string): Promise<Group[]> {\n const groups: Group[] = await this.request({ userId }, [\n { id: 'group-a', name: 'Group A' },\n { id: 'group-b', name: 'Group B' },\n ]);\n\n return groups;\n }\n\n async getGroupProjects(group: string): Promise<Project[]> {\n const projects: Project[] = await this.request({ group }, [\n { id: 'project-a' },\n { id: 'project-b' },\n { id: 'project-c' },\n ]);\n\n return projects;\n }\n\n async getDailyMetricData(\n metric: string,\n intervals: string,\n ): Promise<MetricData> {\n const aggregation = aggregationFor(intervals, 100_000).map(entry => ({\n ...entry,\n amount: Math.round(entry.amount),\n }));\n\n const cost: MetricData = await this.request(\n { metric, intervals },\n {\n format: 'number',\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n },\n );\n\n return cost;\n }\n\n async getCatalogEntityDailyCost(\n entityRef: string,\n intervals: string,\n ): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 8_000);\n const groupDailyCost: Cost = await this.request(\n { entityRef, intervals },\n {\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily cost grouped by cloud product OR by project / billing account.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n project: getGroupedProjects(intervals),\n },\n },\n );\n\n return groupDailyCost;\n }\n\n async getGroupDailyCost(group: string, intervals: string): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 8_000);\n const groupDailyCost: Cost = await this.request(\n { group, intervals },\n {\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily cost grouped by cloud product OR by project / billing account.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n project: getGroupedProjects(intervals),\n },\n },\n );\n\n return groupDailyCost;\n }\n\n async getProjectDailyCost(project: string, intervals: string): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 1_500);\n const projectDailyCost: Cost = await this.request(\n { project, intervals },\n {\n id: 'project-a',\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily project cost grouped by cloud product.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n },\n },\n );\n\n return projectDailyCost;\n }\n\n async getProductInsights(options: ProductInsightsOptions): Promise<Entity> {\n const productInsights: Entity = await this.request(\n options,\n entityOf(options.product),\n );\n\n return productInsights;\n }\n\n async getAlerts(group: string): Promise<Alert[]> {\n const projectGrowthData: ProjectGrowthData = {\n project: 'example-project',\n periodStart: '2020-Q2',\n periodEnd: '2020-Q3',\n aggregation: [60_000, 120_000],\n change: {\n ratio: 1,\n amount: 60_000,\n },\n products: [\n { id: 'Compute Engine', aggregation: [58_000, 118_000] },\n { id: 'Cloud Dataflow', aggregation: [1200, 1500] },\n { id: 'Cloud Storage', aggregation: [800, 500] },\n ],\n };\n\n const unlabeledDataflowData: UnlabeledDataflowData = {\n periodStart: '2020-09-01',\n periodEnd: '2020-09-30',\n labeledCost: 6_200,\n unlabeledCost: 7_000,\n projects: [\n {\n id: 'example-project-1',\n unlabeledCost: 5_000,\n labeledCost: 3_000,\n },\n {\n id: 'example-project-2',\n unlabeledCost: 2_000,\n labeledCost: 3_200,\n },\n ],\n };\n\n const today = DateTime.now();\n const alerts: Alert[] = await this.request({ group }, [\n new ProjectGrowthAlert(projectGrowthData),\n new UnlabeledDataflowAlert(unlabeledDataflowData),\n new KubernetesMigrationAlert(this, {\n startDate: today.minus({ days: 30 }).toFormat(DEFAULT_DATE_FORMAT),\n endDate: today.toFormat(DEFAULT_DATE_FORMAT),\n change: {\n ratio: 0,\n amount: 0,\n },\n services: [\n {\n id: 'service-a',\n aggregation: [20_000, 10_000],\n change: {\n ratio: -0.5,\n amount: -10_000,\n },\n entities: {},\n },\n {\n id: 'service-b',\n aggregation: [30_000, 15_000],\n change: {\n ratio: -0.5,\n amount: -15_000,\n },\n entities: {},\n },\n ],\n }),\n ]);\n\n return alerts;\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AA4CO,MAAM,yBAAqD,CAAA;AAAA,EACxD,OAAA,CAAQ,GAAQ,GAAwB,EAAA;AAC9C,IAAA,OAAO,IAAI,OAAQ,CAAA,CAAA,OAAA,KAAW,WAAW,OAAS,EAAA,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA;AAC3D,EAEA,0BAA8C,GAAA;AAC5C,IAAA,OAAO,OAAQ,CAAA,OAAA;AAAA,MACb,QAAA,CAAS,GAAI,EAAA,CAAE,KAAM,CAAA,EAAE,MAAM,CAAE,EAAC,CAAE,CAAA,QAAA,CAAS,mBAAmB;AAAA,KAChE;AAAA;AACF,EAEA,MAAM,cAAc,MAAkC,EAAA;AACpD,IAAA,MAAM,SAAkB,MAAM,IAAA,CAAK,OAAQ,CAAA,EAAE,QAAU,EAAA;AAAA,MACrD,EAAE,EAAA,EAAI,SAAW,EAAA,IAAA,EAAM,SAAU,EAAA;AAAA,MACjC,EAAE,EAAA,EAAI,SAAW,EAAA,IAAA,EAAM,SAAU;AAAA,KAClC,CAAA;AAED,IAAO,OAAA,MAAA;AAAA;AACT,EAEA,MAAM,iBAAiB,KAAmC,EAAA;AACxD,IAAA,MAAM,WAAsB,MAAM,IAAA,CAAK,OAAQ,CAAA,EAAE,OAAS,EAAA;AAAA,MACxD,EAAE,IAAI,WAAY,EAAA;AAAA,MAClB,EAAE,IAAI,WAAY,EAAA;AAAA,MAClB,EAAE,IAAI,WAAY;AAAA,KACnB,CAAA;AAED,IAAO,OAAA,QAAA;AAAA;AACT,EAEA,MAAM,kBACJ,CAAA,MAAA,EACA,SACqB,EAAA;AACrB,IAAA,MAAM,cAAc,cAAe,CAAA,SAAA,EAAW,GAAO,CAAA,CAAE,IAAI,CAAU,KAAA,MAAA;AAAA,MACnE,GAAG,KAAA;AAAA,MACH,MAAQ,EAAA,IAAA,CAAK,KAAM,CAAA,KAAA,CAAM,MAAM;AAAA,KAC/B,CAAA,CAAA;AAEF,IAAM,MAAA,IAAA,GAAmB,MAAM,IAAK,CAAA,OAAA;AAAA,MAClC,EAAE,QAAQ,SAAU,EAAA;AAAA,MACpB;AAAA,QACE,MAAQ,EAAA,QAAA;AAAA,QACR,WAAA;AAAA,QACA,MAAA,EAAQ,SAAS,WAAW,CAAA;AAAA,QAC5B,SAAA,EAAW,YAAY,WAAW;AAAA;AACpC,KACF;AAEA,IAAO,OAAA,IAAA;AAAA;AACT,EAEA,MAAM,yBACJ,CAAA,SAAA,EACA,SACe,EAAA;AACf,IAAM,MAAA,WAAA,GAAc,cAAe,CAAA,SAAA,EAAW,GAAK,CAAA;AACnD,IAAM,MAAA,cAAA,GAAuB,MAAM,IAAK,CAAA,OAAA;AAAA,MACtC,EAAE,WAAW,SAAU,EAAA;AAAA,MACvB;AAAA,QACE,WAAA;AAAA,QACA,MAAA,EAAQ,SAAS,WAAW,CAAA;AAAA,QAC5B,SAAA,EAAW,YAAY,WAAW,CAAA;AAAA;AAAA;AAAA,QAGlC,YAAc,EAAA;AAAA,UACZ,OAAA,EAAS,mBAAmB,SAAS,CAAA;AAAA,UACrC,OAAA,EAAS,mBAAmB,SAAS;AAAA;AACvC;AACF,KACF;AAEA,IAAO,OAAA,cAAA;AAAA;AACT,EAEA,MAAM,iBAAkB,CAAA,KAAA,EAAe,SAAkC,EAAA;AACvE,IAAM,MAAA,WAAA,GAAc,cAAe,CAAA,SAAA,EAAW,GAAK,CAAA;AACnD,IAAM,MAAA,cAAA,GAAuB,MAAM,IAAK,CAAA,OAAA;AAAA,MACtC,EAAE,OAAO,SAAU,EAAA;AAAA,MACnB;AAAA,QACE,WAAA;AAAA,QACA,MAAA,EAAQ,SAAS,WAAW,CAAA;AAAA,QAC5B,SAAA,EAAW,YAAY,WAAW,CAAA;AAAA;AAAA;AAAA,QAGlC,YAAc,EAAA;AAAA,UACZ,OAAA,EAAS,mBAAmB,SAAS,CAAA;AAAA,UACrC,OAAA,EAAS,mBAAmB,SAAS;AAAA;AACvC;AACF,KACF;AAEA,IAAO,OAAA,cAAA;AAAA;AACT,EAEA,MAAM,mBAAoB,CAAA,OAAA,EAAiB,SAAkC,EAAA;AAC3E,IAAM,MAAA,WAAA,GAAc,cAAe,CAAA,SAAA,EAAW,IAAK,CAAA;AACnD,IAAM,MAAA,gBAAA,GAAyB,MAAM,IAAK,CAAA,OAAA;AAAA,MACxC,EAAE,SAAS,SAAU,EAAA;AAAA,MACrB;AAAA,QACE,EAAI,EAAA,WAAA;AAAA,QACJ,WAAA;AAAA,QACA,MAAA,EAAQ,SAAS,WAAW,CAAA;AAAA,QAC5B,SAAA,EAAW,YAAY,WAAW,CAAA;AAAA;AAAA;AAAA,QAGlC,YAAc,EAAA;AAAA,UACZ,OAAA,EAAS,mBAAmB,SAAS;AAAA;AACvC;AACF,KACF;AAEA,IAAO,OAAA,gBAAA;AAAA;AACT,EAEA,MAAM,mBAAmB,OAAkD,EAAA;AACzE,IAAM,MAAA,eAAA,GAA0B,MAAM,IAAK,CAAA,OAAA;AAAA,MACzC,OAAA;AAAA,MACA,QAAA,CAAS,QAAQ,OAAO;AAAA,KAC1B;AAEA,IAAO,OAAA,eAAA;AAAA;AACT,EAEA,MAAM,UAAU,KAAiC,EAAA;AAC/C,IAAA,MAAM,iBAAuC,GAAA;AAAA,MAC3C,OAAS,EAAA,iBAAA;AAAA,MACT,WAAa,EAAA,SAAA;AAAA,MACb,SAAW,EAAA,SAAA;AAAA,MACX,WAAA,EAAa,CAAC,GAAA,EAAQ,IAAO,CAAA;AAAA,MAC7B,MAAQ,EAAA;AAAA,QACN,KAAO,EAAA,CAAA;AAAA,QACP,MAAQ,EAAA;AAAA,OACV;AAAA,MACA,QAAU,EAAA;AAAA,QACR,EAAE,EAAI,EAAA,gBAAA,EAAkB,aAAa,CAAC,IAAA,EAAQ,KAAO,CAAE,EAAA;AAAA,QACvD,EAAE,EAAI,EAAA,gBAAA,EAAkB,aAAa,CAAC,IAAA,EAAM,IAAI,CAAE,EAAA;AAAA,QAClD,EAAE,EAAI,EAAA,eAAA,EAAiB,aAAa,CAAC,GAAA,EAAK,GAAG,CAAE;AAAA;AACjD,KACF;AAEA,IAAA,MAAM,qBAA+C,GAAA;AAAA,MACnD,WAAa,EAAA,YAAA;AAAA,MACb,SAAW,EAAA,YAAA;AAAA,MACX,WAAa,EAAA,IAAA;AAAA,MACb,aAAe,EAAA,GAAA;AAAA,MACf,QAAU,EAAA;AAAA,QACR;AAAA,UACE,EAAI,EAAA,mBAAA;AAAA,UACJ,aAAe,EAAA,GAAA;AAAA,UACf,WAAa,EAAA;AAAA,SACf;AAAA,QACA;AAAA,UACE,EAAI,EAAA,mBAAA;AAAA,UACJ,aAAe,EAAA,GAAA;AAAA,UACf,WAAa,EAAA;AAAA;AACf;AACF,KACF;AAEA,IAAM,MAAA,KAAA,GAAQ,SAAS,GAAI,EAAA;AAC3B,IAAA,MAAM,SAAkB,MAAM,IAAA,CAAK,OAAQ,CAAA,EAAE,OAAS,EAAA;AAAA,MACpD,IAAI,mBAAmB,iBAAiB,CAAA;AAAA,MACxC,IAAI,uBAAuB,qBAAqB,CAAA;AAAA,MAChD,IAAI,yBAAyB,IAAM,EAAA;AAAA,QACjC,SAAA,EAAW,MAAM,KAAM,CAAA,EAAE,MAAM,EAAG,EAAC,CAAE,CAAA,QAAA,CAAS,mBAAmB,CAAA;AAAA,QACjE,OAAA,EAAS,KAAM,CAAA,QAAA,CAAS,mBAAmB,CAAA;AAAA,QAC3C,MAAQ,EAAA;AAAA,UACN,KAAO,EAAA,CAAA;AAAA,UACP,MAAQ,EAAA;AAAA,SACV;AAAA,QACA,QAAU,EAAA;AAAA,UACR;AAAA,YACE,EAAI,EAAA,WAAA;AAAA,YACJ,WAAA,EAAa,CAAC,GAAA,EAAQ,GAAM,CAAA;AAAA,YAC5B,MAAQ,EAAA;AAAA,cACN,KAAO,EAAA,CAAA,GAAA;AAAA,cACP,MAAQ,EAAA,CAAA;AAAA,aACV;AAAA,YACA,UAAU;AAAC,WACb;AAAA,UACA;AAAA,YACE,EAAI,EAAA,WAAA;AAAA,YACJ,WAAA,EAAa,CAAC,GAAA,EAAQ,IAAM,CAAA;AAAA,YAC5B,MAAQ,EAAA;AAAA,cACN,KAAO,EAAA,CAAA,GAAA;AAAA,cACP,MAAQ,EAAA,CAAA;AAAA,aACV;AAAA,YACA,UAAU;AAAC;AACb;AACF,OACD;AAAA,KACF,CAAA;AAED,IAAO,OAAA,MAAA;AAAA;AAEX;;;;"}
|
|
1
|
+
{"version":3,"file":"client.esm.js","sources":["../../src/example/client.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/* eslint-disable no-restricted-imports */\n\nimport { DateTime } from 'luxon';\nimport { CostInsightsApi, ProductInsightsOptions } from '../api';\nimport {\n Alert,\n DEFAULT_DATE_FORMAT,\n ProjectGrowthData,\n UnlabeledDataflowData,\n} from '../types';\nimport {\n Entity,\n Group,\n MetricData,\n Project,\n Cost,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { KubernetesMigrationAlert } from './alerts';\nimport { ProjectGrowthAlert, UnlabeledDataflowAlert } from '../alerts';\nimport {\n aggregationFor,\n changeOf,\n entityOf,\n getGroupedProducts,\n getGroupedProjects,\n trendlineOf,\n} from '../testUtils';\n\n/** @public */\nexport class ExampleCostInsightsClient implements CostInsightsApi {\n private request(_: any, res: any): Promise<any> {\n return new Promise(resolve => setTimeout(resolve, 0, res));\n }\n\n getLastCompleteBillingDate(): Promise<string> {\n return Promise.resolve(\n DateTime.now().minus({ days: 1 }).toFormat(DEFAULT_DATE_FORMAT),\n );\n }\n\n async getUserGroups(userId: string): Promise<Group[]> {\n const groups: Group[] = await this.request({ userId }, [\n { id: 'group-a', name: 'Group A' },\n { id: 'group-b', name: 'Group B' },\n ]);\n\n return groups;\n }\n\n async getGroupProjects(group: string): Promise<Project[]> {\n const projects: Project[] = await this.request({ group }, [\n { id: 'project-a' },\n { id: 'project-b' },\n { id: 'project-c' },\n ]);\n\n return projects;\n }\n\n async getDailyMetricData(\n metric: string,\n intervals: string,\n ): Promise<MetricData> {\n const aggregation = aggregationFor(intervals, 100_000).map(entry => ({\n ...entry,\n amount: Math.round(entry.amount),\n }));\n\n const cost: MetricData = await this.request(\n { metric, intervals },\n {\n format: 'number',\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n },\n );\n\n return cost;\n }\n\n async getCatalogEntityDailyCost(\n entityRef: string,\n intervals: string,\n ): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 8_000);\n const groupDailyCost: Cost = await this.request(\n { entityRef, intervals },\n {\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily cost grouped by cloud product OR by project / billing account.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n project: getGroupedProjects(intervals),\n },\n },\n );\n\n return groupDailyCost;\n }\n\n async getGroupDailyCost(group: string, intervals: string): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 8_000);\n const groupDailyCost: Cost = await this.request(\n { group, intervals },\n {\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily cost grouped by cloud product OR by project / billing account.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n project: getGroupedProjects(intervals),\n },\n },\n );\n\n return groupDailyCost;\n }\n\n async getProjectDailyCost(project: string, intervals: string): Promise<Cost> {\n const aggregation = aggregationFor(intervals, 1_500);\n const projectDailyCost: Cost = await this.request(\n { project, intervals },\n {\n id: 'project-a',\n aggregation: aggregation,\n change: changeOf(aggregation),\n trendline: trendlineOf(aggregation),\n // Optional field providing cost groupings / breakdowns keyed by the type. In this example,\n // daily project cost grouped by cloud product.\n groupedCosts: {\n product: getGroupedProducts(intervals),\n },\n },\n );\n\n return projectDailyCost;\n }\n\n async getProductInsights(options: ProductInsightsOptions): Promise<Entity> {\n const productInsights: Entity = await this.request(\n options,\n entityOf(options.product),\n );\n\n return productInsights;\n }\n\n async getAlerts(group: string): Promise<Alert[]> {\n const projectGrowthData: ProjectGrowthData = {\n project: 'example-project',\n periodStart: '2020-Q2',\n periodEnd: '2020-Q3',\n aggregation: [60_000, 120_000],\n change: {\n ratio: 1,\n amount: 60_000,\n },\n products: [\n { id: 'Compute Engine', aggregation: [58_000, 118_000] },\n { id: 'Cloud Dataflow', aggregation: [1200, 1500] },\n { id: 'Cloud Storage', aggregation: [800, 500] },\n ],\n };\n\n const unlabeledDataflowData: UnlabeledDataflowData = {\n periodStart: '2020-09-01',\n periodEnd: '2020-09-30',\n labeledCost: 6_200,\n unlabeledCost: 7_000,\n projects: [\n {\n id: 'example-project-1',\n unlabeledCost: 5_000,\n labeledCost: 3_000,\n },\n {\n id: 'example-project-2',\n unlabeledCost: 2_000,\n labeledCost: 3_200,\n },\n ],\n };\n\n const today = DateTime.now();\n const alerts: Alert[] = await this.request({ group }, [\n new ProjectGrowthAlert(projectGrowthData),\n new UnlabeledDataflowAlert(unlabeledDataflowData),\n new KubernetesMigrationAlert(this, {\n startDate: today.minus({ days: 30 }).toFormat(DEFAULT_DATE_FORMAT),\n endDate: today.toFormat(DEFAULT_DATE_FORMAT),\n change: {\n ratio: 0,\n amount: 0,\n },\n services: [\n {\n id: 'service-a',\n aggregation: [20_000, 10_000],\n change: {\n ratio: -0.5,\n amount: -10_000,\n },\n entities: {},\n },\n {\n id: 'service-b',\n aggregation: [30_000, 15_000],\n change: {\n ratio: -0.5,\n amount: -15_000,\n },\n entities: {},\n },\n ],\n }),\n ]);\n\n return alerts;\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KubernetesMigrationAlertCard.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Box from '@material-ui/core/Box';\nimport { KubernetesMigrationBarChartLegend } from './KubernetesMigrationBarChartLegend';\nimport { KubernetesMigrationBarChart } from './KubernetesMigrationBarChart';\nimport { KubernetesMigrationData } from '../../alerts';\nimport { InfoCard } from '@backstage/core-components';\n\ntype KubernetesMigrationAlertProps = {\n data: KubernetesMigrationData;\n title: string;\n subheader: string;\n currentProduct: string;\n comparedProduct: string;\n};\n\nexport const KubernetesMigrationAlertCard = ({\n data,\n title,\n subheader,\n currentProduct,\n comparedProduct,\n}: KubernetesMigrationAlertProps) => {\n return (\n <InfoCard title={title} subheader={subheader}>\n <Box display=\"flex\" flexDirection=\"column\">\n <Box paddingY={1}>\n <KubernetesMigrationBarChartLegend\n startDate={data.startDate}\n change={data.change}\n currentProduct={currentProduct}\n comparedProduct={comparedProduct}\n />\n </Box>\n <Box paddingY={1}>\n <KubernetesMigrationBarChart\n services={data.services}\n currentProduct={currentProduct}\n comparedProduct={comparedProduct}\n />\n </Box>\n </Box>\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;AA8BO,MAAM,+BAA+B,CAAC;AAAA,EAC3C,IAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,
|
|
1
|
+
{"version":3,"file":"KubernetesMigrationAlertCard.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Box from '@material-ui/core/Box';\nimport { KubernetesMigrationBarChartLegend } from './KubernetesMigrationBarChartLegend';\nimport { KubernetesMigrationBarChart } from './KubernetesMigrationBarChart';\nimport { KubernetesMigrationData } from '../../alerts';\nimport { InfoCard } from '@backstage/core-components';\n\ntype KubernetesMigrationAlertProps = {\n data: KubernetesMigrationData;\n title: string;\n subheader: string;\n currentProduct: string;\n comparedProduct: string;\n};\n\nexport const KubernetesMigrationAlertCard = ({\n data,\n title,\n subheader,\n currentProduct,\n comparedProduct,\n}: KubernetesMigrationAlertProps) => {\n return (\n <InfoCard title={title} subheader={subheader}>\n <Box display=\"flex\" flexDirection=\"column\">\n <Box paddingY={1}>\n <KubernetesMigrationBarChartLegend\n startDate={data.startDate}\n change={data.change}\n currentProduct={currentProduct}\n comparedProduct={comparedProduct}\n />\n </Box>\n <Box paddingY={1}>\n <KubernetesMigrationBarChart\n services={data.services}\n currentProduct={currentProduct}\n comparedProduct={comparedProduct}\n />\n </Box>\n </Box>\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;AA8BO,MAAM,+BAA+B,CAAC;AAAA,EAC3C,IAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA,KAAqC;AACnC,EAAA,uBACE,GAAA,CAAC,YAAS,KAAA,EAAc,SAAA,EACtB,+BAAC,GAAA,EAAA,EAAI,OAAA,EAAQ,MAAA,EAAO,aAAA,EAAc,QAAA,EAChC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,GAAA,EAAA,EAAI,UAAU,CAAA,EACb,QAAA,kBAAA,GAAA;AAAA,MAAC,iCAAA;AAAA,MAAA;AAAA,QACC,WAAW,IAAA,CAAK,SAAA;AAAA,QAChB,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,cAAA;AAAA,QACA;AAAA;AAAA,KACF,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,GAAA,EAAA,EAAI,QAAA,EAAU,CAAA,EACb,QAAA,kBAAA,GAAA;AAAA,MAAC,2BAAA;AAAA,MAAA;AAAA,QACC,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,cAAA;AAAA,QACA;AAAA;AAAA,KACF,EACF;AAAA,GAAA,EACF,CAAA,EACF,CAAA;AAEJ;;;;"}
|
package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KubernetesMigrationBarChart.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BarChart } from '../../../components';\nimport {\n BarChartOptions,\n CostInsightsTheme,\n ResourceData,\n} from '../../../types';\nimport { Entity } from '@backstage-community/plugin-cost-insights-common';\nimport { useTheme } from '@material-ui/core/styles';\n\ntype MigrationBarChartProps = {\n currentProduct: string;\n comparedProduct: string;\n services: Array<Entity>;\n};\n\nexport const KubernetesMigrationBarChart = ({\n currentProduct,\n comparedProduct,\n services,\n}: MigrationBarChartProps) => {\n const theme = useTheme<CostInsightsTheme>();\n\n const options: BarChartOptions = {\n previousFill: theme.palette.magenta,\n currentFill: theme.palette.yellow,\n previousName: comparedProduct,\n currentName: currentProduct,\n };\n\n const resources: ResourceData[] = services.map(service => ({\n name: service.id,\n previous: service.aggregation[0],\n current: service.aggregation[1],\n }));\n\n return <BarChart resources={resources} options={options} />;\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BO,MAAM,8BAA8B,CAAC;AAAA,EAC1C,cAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,
|
|
1
|
+
{"version":3,"file":"KubernetesMigrationBarChart.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BarChart } from '../../../components';\nimport {\n BarChartOptions,\n CostInsightsTheme,\n ResourceData,\n} from '../../../types';\nimport { Entity } from '@backstage-community/plugin-cost-insights-common';\nimport { useTheme } from '@material-ui/core/styles';\n\ntype MigrationBarChartProps = {\n currentProduct: string;\n comparedProduct: string;\n services: Array<Entity>;\n};\n\nexport const KubernetesMigrationBarChart = ({\n currentProduct,\n comparedProduct,\n services,\n}: MigrationBarChartProps) => {\n const theme = useTheme<CostInsightsTheme>();\n\n const options: BarChartOptions = {\n previousFill: theme.palette.magenta,\n currentFill: theme.palette.yellow,\n previousName: comparedProduct,\n currentName: currentProduct,\n };\n\n const resources: ResourceData[] = services.map(service => ({\n name: service.id,\n previous: service.aggregation[0],\n current: service.aggregation[1],\n }));\n\n return <BarChart resources={resources} options={options} />;\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BO,MAAM,8BAA8B,CAAC;AAAA,EAC1C,cAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,CAAA,KAA8B;AAC5B,EAAA,MAAM,QAAQ,QAAA,EAA4B;AAE1C,EAAA,MAAM,OAAA,GAA2B;AAAA,IAC/B,YAAA,EAAc,MAAM,OAAA,CAAQ,OAAA;AAAA,IAC5B,WAAA,EAAa,MAAM,OAAA,CAAQ,MAAA;AAAA,IAC3B,YAAA,EAAc,eAAA;AAAA,IACd,WAAA,EAAa;AAAA,GACf;AAEA,EAAA,MAAM,SAAA,GAA4B,QAAA,CAAS,GAAA,CAAI,CAAA,OAAA,MAAY;AAAA,IACzD,MAAM,OAAA,CAAQ,EAAA;AAAA,IACd,QAAA,EAAU,OAAA,CAAQ,WAAA,CAAY,CAAC,CAAA;AAAA,IAC/B,OAAA,EAAS,OAAA,CAAQ,WAAA,CAAY,CAAC;AAAA,GAChC,CAAE,CAAA;AAEF,EAAA,uBAAO,GAAA,CAAC,QAAA,EAAA,EAAS,SAAA,EAAsB,OAAA,EAAkB,CAAA;AAC3D;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KubernetesMigrationBarChartLegend.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Box from '@material-ui/core/Box';\nimport { useTheme } from '@material-ui/core/styles';\nimport { CostGrowth, LegendItem } from '../../../components';\nimport { CostInsightsTheme, Duration } from '../../../types';\nimport { ChangeStatistic } from '@backstage-community/plugin-cost-insights-common';\nimport { monthOf } from '../../../utils/formatters';\n\nexport type MigrationBarChartLegendProps = {\n change: ChangeStatistic;\n startDate: string;\n currentProduct: string;\n comparedProduct: string;\n};\n\nexport const KubernetesMigrationBarChartLegend = ({\n currentProduct,\n comparedProduct,\n change,\n startDate,\n}: MigrationBarChartLegendProps) => {\n const theme = useTheme<CostInsightsTheme>();\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n <Box marginRight={2}>\n <LegendItem\n title={monthOf(startDate)}\n markerColor={theme.palette.magenta}\n >\n {currentProduct}\n </LegendItem>\n </Box>\n <Box marginRight={2}>\n <LegendItem title=\"Estimated Cost\" markerColor={theme.palette.yellow}>\n {comparedProduct}\n </LegendItem>\n </Box>\n <LegendItem title=\"Total Savings\">\n <CostGrowth change={change} duration={Duration.P30D} />\n </LegendItem>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BO,MAAM,oCAAoC,CAAC;AAAA,EAChD,cAAA;AAAA,EACA,eAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,
|
|
1
|
+
{"version":3,"file":"KubernetesMigrationBarChartLegend.esm.js","sources":["../../../../src/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Box from '@material-ui/core/Box';\nimport { useTheme } from '@material-ui/core/styles';\nimport { CostGrowth, LegendItem } from '../../../components';\nimport { CostInsightsTheme, Duration } from '../../../types';\nimport { ChangeStatistic } from '@backstage-community/plugin-cost-insights-common';\nimport { monthOf } from '../../../utils/formatters';\n\nexport type MigrationBarChartLegendProps = {\n change: ChangeStatistic;\n startDate: string;\n currentProduct: string;\n comparedProduct: string;\n};\n\nexport const KubernetesMigrationBarChartLegend = ({\n currentProduct,\n comparedProduct,\n change,\n startDate,\n}: MigrationBarChartLegendProps) => {\n const theme = useTheme<CostInsightsTheme>();\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n <Box marginRight={2}>\n <LegendItem\n title={monthOf(startDate)}\n markerColor={theme.palette.magenta}\n >\n {currentProduct}\n </LegendItem>\n </Box>\n <Box marginRight={2}>\n <LegendItem title=\"Estimated Cost\" markerColor={theme.palette.yellow}>\n {comparedProduct}\n </LegendItem>\n </Box>\n <LegendItem title=\"Total Savings\">\n <CostGrowth change={change} duration={Duration.P30D} />\n </LegendItem>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BO,MAAM,oCAAoC,CAAC;AAAA,EAChD,cAAA;AAAA,EACA,eAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,KAAoC;AAClC,EAAA,MAAM,QAAQ,QAAA,EAA4B;AAC1C,EAAA,uBACE,IAAA,CAAC,GAAA,EAAA,EAAI,OAAA,EAAQ,MAAA,EAAO,eAAc,KAAA,EAChC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,GAAA,EAAA,EAAI,aAAa,CAAA,EAChB,QAAA,kBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,QAAQ,SAAS,CAAA;AAAA,QACxB,WAAA,EAAa,MAAM,OAAA,CAAQ,OAAA;AAAA,QAE1B,QAAA,EAAA;AAAA;AAAA,KACH,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,GAAA,EAAA,EAAI,WAAA,EAAa,CAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAM,gBAAA,EAAiB,WAAA,EAAa,KAAA,CAAM,OAAA,CAAQ,MAAA,EAC3D,2BACH,CAAA,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAM,eAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,cAAW,MAAA,EAAgB,QAAA,EAAU,QAAA,CAAS,IAAA,EAAM,CAAA,EACvD;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KubernetesMigrationDismissForm.esm.js","sources":["../../../src/example/forms/KubernetesMigrationDismissForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n ChangeEvent,\n} from 'react';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport FormGroup from '@material-ui/core/FormGroup';\nimport Typography from '@material-ui/core/Typography';\nimport { AlertFormProps } from '../../types';\nimport { Entity } from '@backstage-community/plugin-cost-insights-common';\nimport { KubernetesMigrationAlert } from '../alerts';\nimport { findAlways } from '../../utils/assert';\n\nexport type KubernetesMigrationDismissFormData = {\n services: Entity[];\n};\n\nexport type KubernetesMigrationDismissFormProps = AlertFormProps<\n KubernetesMigrationAlert,\n KubernetesMigrationDismissFormData\n>;\n\nexport const KubernetesMigrationDismissForm = forwardRef<\n HTMLFormElement,\n KubernetesMigrationDismissFormProps\n>(({ onSubmit, disableSubmit, alert }, ref) => {\n const [services, setServices] = useState<Entity[]>(alert.data.services);\n\n const onFormSubmit: FormEventHandler = e => {\n /* Remember to prevent default form behavior */\n e.preventDefault();\n onSubmit({ services: services });\n };\n\n const onCheckboxChange = (\n e: ChangeEvent<HTMLInputElement>,\n checked: boolean,\n ) => {\n if (checked) {\n const service = findAlways(\n alert.data.services,\n s => s.id === e.target.value,\n );\n setServices(prevServices => prevServices.concat(service));\n } else {\n setServices(prevServices =>\n prevServices.filter(p => p.id !== e.target.value),\n );\n }\n };\n\n /* Submit button is disabled by default. Use props.disableSubmit to toggle disabled state. */\n useEffect(() => {\n if (services.length) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n }, [services, disableSubmit]);\n\n return (\n /* All custom forms must accept a ref and implement an onSubmit handler. */\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>Or choose which services to dismiss this alert for.</b>\n </Typography>\n <FormGroup>\n {alert.data.services.map((service, index) => (\n <FormControlLabel\n key={`example-option-${index}`}\n label={service.id}\n value={service.id}\n control={\n <Checkbox\n color=\"primary\"\n checked={services.some(p => p.id === service.id)}\n onChange={onCheckboxChange}\n />\n }\n />\n ))}\n </FormGroup>\n </FormControl>\n </form>\n );\n});\n"],"names":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"KubernetesMigrationDismissForm.esm.js","sources":["../../../src/example/forms/KubernetesMigrationDismissForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n ChangeEvent,\n} from 'react';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport FormGroup from '@material-ui/core/FormGroup';\nimport Typography from '@material-ui/core/Typography';\nimport { AlertFormProps } from '../../types';\nimport { Entity } from '@backstage-community/plugin-cost-insights-common';\nimport { KubernetesMigrationAlert } from '../alerts';\nimport { findAlways } from '../../utils/assert';\n\nexport type KubernetesMigrationDismissFormData = {\n services: Entity[];\n};\n\nexport type KubernetesMigrationDismissFormProps = AlertFormProps<\n KubernetesMigrationAlert,\n KubernetesMigrationDismissFormData\n>;\n\nexport const KubernetesMigrationDismissForm = forwardRef<\n HTMLFormElement,\n KubernetesMigrationDismissFormProps\n>(({ onSubmit, disableSubmit, alert }, ref) => {\n const [services, setServices] = useState<Entity[]>(alert.data.services);\n\n const onFormSubmit: FormEventHandler = e => {\n /* Remember to prevent default form behavior */\n e.preventDefault();\n onSubmit({ services: services });\n };\n\n const onCheckboxChange = (\n e: ChangeEvent<HTMLInputElement>,\n checked: boolean,\n ) => {\n if (checked) {\n const service = findAlways(\n alert.data.services,\n s => s.id === e.target.value,\n );\n setServices(prevServices => prevServices.concat(service));\n } else {\n setServices(prevServices =>\n prevServices.filter(p => p.id !== e.target.value),\n );\n }\n };\n\n /* Submit button is disabled by default. Use props.disableSubmit to toggle disabled state. */\n useEffect(() => {\n if (services.length) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n }, [services, disableSubmit]);\n\n return (\n /* All custom forms must accept a ref and implement an onSubmit handler. */\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>Or choose which services to dismiss this alert for.</b>\n </Typography>\n <FormGroup>\n {alert.data.services.map((service, index) => (\n <FormControlLabel\n key={`example-option-${index}`}\n label={service.id}\n value={service.id}\n control={\n <Checkbox\n color=\"primary\"\n checked={services.some(p => p.id === service.id)}\n onChange={onCheckboxChange}\n />\n }\n />\n ))}\n </FormGroup>\n </FormControl>\n </form>\n );\n});\n"],"names":[],"mappings":";;;;;;;;;AA0CO,MAAM,8BAAA,GAAiC,WAG5C,CAAC,EAAE,UAAU,aAAA,EAAe,KAAA,IAAS,GAAA,KAAQ;AAC7C,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,IAAI,QAAA,CAAmB,KAAA,CAAM,KAAK,QAAQ,CAAA;AAEtE,EAAA,MAAM,eAAiC,CAAA,CAAA,KAAK;AAE1C,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,QAAA,CAAS,EAAE,UAAoB,CAAA;AAAA,EACjC,CAAA;AAEA,EAAA,MAAM,gBAAA,GAAmB,CACvB,CAAA,EACA,OAAA,KACG;AACH,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,OAAA,GAAU,UAAA;AAAA,QACd,MAAM,IAAA,CAAK,QAAA;AAAA,QACX,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,KAAO,CAAA,CAAE,MAAA,CAAO;AAAA,OACzB;AACA,MAAA,WAAA,CAAY,CAAA,YAAA,KAAgB,YAAA,CAAa,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA,IAC1D,CAAA,MAAO;AACL,MAAA,WAAA;AAAA,QAAY,CAAA,YAAA,KACV,aAAa,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,EAAA,KAAO,CAAA,CAAE,OAAO,KAAK;AAAA,OAClD;AAAA,IACF;AAAA,EACF,CAAA;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,MAAA,aAAA,CAAc,KAAK,CAAA;AAAA,IACrB,CAAA,MAAO;AACL,MAAA,aAAA,CAAc,IAAI,CAAA;AAAA,IACpB;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,aAAa,CAAC,CAAA;AAE5B,EAAA;AAAA;AAAA,oBAEE,GAAA,CAAC,MAAA,EAAA,EAAK,GAAA,EAAU,QAAA,EAAU,YAAA,EACxB,+BAAC,WAAA,EAAA,EAAY,SAAA,EAAU,UAAA,EAAW,SAAA,EAAS,IAAA,EACzC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,cAAW,KAAA,EAAM,aAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,iEAAmD,CAAA,EACxD,CAAA;AAAA,sBACA,GAAA,CAAC,aACE,QAAA,EAAA,KAAA,CAAM,IAAA,CAAK,SAAS,GAAA,CAAI,CAAC,SAAS,KAAA,qBACjC,GAAA;AAAA,QAAC,gBAAA;AAAA,QAAA;AAAA,UAEC,OAAO,OAAA,CAAQ,EAAA;AAAA,UACf,OAAO,OAAA,CAAQ,EAAA;AAAA,UACf,OAAA,kBACE,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,KAAA,EAAM,SAAA;AAAA,cACN,SAAS,QAAA,CAAS,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,QAAQ,EAAE,CAAA;AAAA,cAC/C,QAAA,EAAU;AAAA;AAAA;AACZ,SAAA;AAAA,QARG,kBAAkB,KAAK,CAAA;AAAA,OAW/B,CAAA,EACH;AAAA,KAAA,EACF,CAAA,EACF;AAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlertAcceptForm.esm.js","sources":["../../src/forms/AlertAcceptForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useState, forwardRef, ChangeEvent, FormEventHandler } from 'react';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport { Alert, AlertFormProps } from '../types';\n\nexport type AlertAcceptFormProps = AlertFormProps<Alert, null>;\n\nexport const AlertAcceptForm = forwardRef<\n HTMLFormElement,\n AlertAcceptFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const [checked, setChecked] = useState(false);\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n onSubmit(null);\n };\n\n const onChecked = (_: ChangeEvent<HTMLInputElement>, isChecked: boolean) => {\n setChecked(isChecked);\n disableSubmit(!isChecked);\n };\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <FormControlLabel\n label=\"My team can commit to making this change soon, or has already.\"\n value={checked}\n control={\n <Checkbox color=\"primary\" checked={checked} onChange={onChecked} />\n }\n />\n </FormControl>\n </form>\n );\n});\n"],"names":[],"mappings":";;;;;;AAwBO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"AlertAcceptForm.esm.js","sources":["../../src/forms/AlertAcceptForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useState, forwardRef, ChangeEvent, FormEventHandler } from 'react';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport { Alert, AlertFormProps } from '../types';\n\nexport type AlertAcceptFormProps = AlertFormProps<Alert, null>;\n\nexport const AlertAcceptForm = forwardRef<\n HTMLFormElement,\n AlertAcceptFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const [checked, setChecked] = useState(false);\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n onSubmit(null);\n };\n\n const onChecked = (_: ChangeEvent<HTMLInputElement>, isChecked: boolean) => {\n setChecked(isChecked);\n disableSubmit(!isChecked);\n };\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <FormControlLabel\n label=\"My team can commit to making this change soon, or has already.\"\n value={checked}\n control={\n <Checkbox color=\"primary\" checked={checked} onChange={onChecked} />\n }\n />\n </FormControl>\n </form>\n );\n});\n"],"names":[],"mappings":";;;;;;AAwBO,MAAM,kBAAkB,UAAA,CAG7B,CAAC,EAAE,QAAA,EAAU,aAAA,IAAiB,GAAA,KAAQ;AACtC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAE5C,EAAA,MAAM,eAAiC,CAAA,CAAA,KAAK;AAC1C,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,QAAA,CAAS,IAAI,CAAA;AAAA,EACf,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,CAAC,CAAA,EAAkC,SAAA,KAAuB;AAC1E,IAAA,UAAA,CAAW,SAAS,CAAA;AACpB,IAAA,aAAA,CAAc,CAAC,SAAS,CAAA;AAAA,EAC1B,CAAA;AAEA,EAAA,uBACE,GAAA,CAAC,MAAA,EAAA,EAAK,GAAA,EAAU,QAAA,EAAU,YAAA,EACxB,8BAAC,WAAA,EAAA,EAAY,SAAA,EAAU,UAAA,EAAW,SAAA,EAAS,IAAA,EACzC,QAAA,kBAAA,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,gEAAA;AAAA,MACN,KAAA,EAAO,OAAA;AAAA,MACP,yBACE,GAAA,CAAC,QAAA,EAAA,EAAS,OAAM,SAAA,EAAU,OAAA,EAAkB,UAAU,SAAA,EAAW;AAAA;AAAA,KAGvE,CAAA,EACF,CAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlertDismissForm.esm.js","sources":["../../src/forms/AlertDismissForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ChangeEvent,\n useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n} from 'react';\nimport Box from '@material-ui/core/Box';\nimport Collapse from '@material-ui/core/Collapse';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport TextField from '@material-ui/core/TextField';\nimport Typography from '@material-ui/core/Typography';\nimport Radio from '@material-ui/core/Radio';\nimport RadioGroup from '@material-ui/core/RadioGroup';\nimport {\n Alert,\n AlertFormProps,\n AlertDismissReason,\n AlertDismissOptions,\n AlertDismissFormData,\n} from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useAlertDialogStyles as useStyles } from '../utils/styles';\n\nexport type AlertDismissFormProps = AlertFormProps<Alert, AlertDismissFormData>;\n\nexport const AlertDismissForm = forwardRef<\n HTMLFormElement,\n AlertDismissFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const classes = useStyles();\n const [other, setOther] = useState<Maybe<string>>(null);\n const [feedback, setFeedback] = useState<Maybe<string>>(null);\n const [reason, setReason] = useState<AlertDismissReason>(\n AlertDismissReason.Resolved,\n );\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n if (reason) {\n onSubmit({\n other: other,\n reason: reason,\n feedback: feedback,\n });\n }\n };\n\n const onReasonChange = (_: ChangeEvent<HTMLInputElement>, value: string) => {\n if (other) {\n setOther(null);\n }\n setReason(value as AlertDismissReason);\n };\n\n const onOtherChange = (e: ChangeEvent<HTMLInputElement>) => {\n return e.target.value\n ? setOther(e.target.value as AlertDismissReason)\n : setOther(null);\n };\n\n const onFeedbackChange = (e: ChangeEvent<HTMLInputElement>) => {\n return e.target.value\n ? setFeedback(e.target.value as AlertDismissReason)\n : setFeedback(null);\n };\n\n useEffect(() => {\n function validateDismissForm() {\n if (reason === AlertDismissReason.Other) {\n if (other) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n } else if (reason) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n }\n\n validateDismissForm();\n }, [reason, other, disableSubmit]);\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>Reason for dismissing?</b>\n </Typography>\n <Box mb={1}>\n <RadioGroup\n name=\"dismiss-alert-reasons\"\n value={reason}\n onChange={onReasonChange}\n >\n {AlertDismissOptions.map(option => (\n <FormControlLabel\n key={`dismiss-alert-option-${option.reason}`}\n label={option.label}\n value={option.reason}\n control={<Radio className={classes.radio} />}\n />\n ))}\n </RadioGroup>\n <Collapse in={reason === AlertDismissReason.Other}>\n <Box ml={4}>\n <TextField\n id=\"dismiss-alert-option-other\"\n variant=\"outlined\"\n multiline\n fullWidth\n rows={4}\n value={other ?? ''}\n onChange={onOtherChange}\n />\n </Box>\n </Collapse>\n </Box>\n <Typography gutterBottom>\n <b>Any other feedback you can provide?</b>\n </Typography>\n <TextField\n id=\"dismiss-alert-feedback\"\n variant=\"outlined\"\n multiline\n rows={4}\n fullWidth\n value={feedback ?? ''}\n onChange={onFeedbackChange}\n />\n </FormControl>\n </form>\n );\n});\n"],"names":["useStyles"],"mappings":";;;;;;;;;;;;;AA2CO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"AlertDismissForm.esm.js","sources":["../../src/forms/AlertDismissForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ChangeEvent,\n useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n} from 'react';\nimport Box from '@material-ui/core/Box';\nimport Collapse from '@material-ui/core/Collapse';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport TextField from '@material-ui/core/TextField';\nimport Typography from '@material-ui/core/Typography';\nimport Radio from '@material-ui/core/Radio';\nimport RadioGroup from '@material-ui/core/RadioGroup';\nimport {\n Alert,\n AlertFormProps,\n AlertDismissReason,\n AlertDismissOptions,\n AlertDismissFormData,\n} from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useAlertDialogStyles as useStyles } from '../utils/styles';\n\nexport type AlertDismissFormProps = AlertFormProps<Alert, AlertDismissFormData>;\n\nexport const AlertDismissForm = forwardRef<\n HTMLFormElement,\n AlertDismissFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const classes = useStyles();\n const [other, setOther] = useState<Maybe<string>>(null);\n const [feedback, setFeedback] = useState<Maybe<string>>(null);\n const [reason, setReason] = useState<AlertDismissReason>(\n AlertDismissReason.Resolved,\n );\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n if (reason) {\n onSubmit({\n other: other,\n reason: reason,\n feedback: feedback,\n });\n }\n };\n\n const onReasonChange = (_: ChangeEvent<HTMLInputElement>, value: string) => {\n if (other) {\n setOther(null);\n }\n setReason(value as AlertDismissReason);\n };\n\n const onOtherChange = (e: ChangeEvent<HTMLInputElement>) => {\n return e.target.value\n ? setOther(e.target.value as AlertDismissReason)\n : setOther(null);\n };\n\n const onFeedbackChange = (e: ChangeEvent<HTMLInputElement>) => {\n return e.target.value\n ? setFeedback(e.target.value as AlertDismissReason)\n : setFeedback(null);\n };\n\n useEffect(() => {\n function validateDismissForm() {\n if (reason === AlertDismissReason.Other) {\n if (other) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n } else if (reason) {\n disableSubmit(false);\n } else {\n disableSubmit(true);\n }\n }\n\n validateDismissForm();\n }, [reason, other, disableSubmit]);\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>Reason for dismissing?</b>\n </Typography>\n <Box mb={1}>\n <RadioGroup\n name=\"dismiss-alert-reasons\"\n value={reason}\n onChange={onReasonChange}\n >\n {AlertDismissOptions.map(option => (\n <FormControlLabel\n key={`dismiss-alert-option-${option.reason}`}\n label={option.label}\n value={option.reason}\n control={<Radio className={classes.radio} />}\n />\n ))}\n </RadioGroup>\n <Collapse in={reason === AlertDismissReason.Other}>\n <Box ml={4}>\n <TextField\n id=\"dismiss-alert-option-other\"\n variant=\"outlined\"\n multiline\n fullWidth\n rows={4}\n value={other ?? ''}\n onChange={onOtherChange}\n />\n </Box>\n </Collapse>\n </Box>\n <Typography gutterBottom>\n <b>Any other feedback you can provide?</b>\n </Typography>\n <TextField\n id=\"dismiss-alert-feedback\"\n variant=\"outlined\"\n multiline\n rows={4}\n fullWidth\n value={feedback ?? ''}\n onChange={onFeedbackChange}\n />\n </FormControl>\n </form>\n );\n});\n"],"names":["useStyles"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlertSnoozeForm.esm.js","sources":["../../src/forms/AlertSnoozeForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ChangeEvent,\n useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n} from 'react';\nimport { DateTime } from 'luxon';\nimport Box from '@material-ui/core/Box';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport RadioGroup from '@material-ui/core/RadioGroup';\nimport Radio from '@material-ui/core/Radio';\nimport Typography from '@material-ui/core/Typography';\nimport {\n Alert,\n AlertFormProps,\n Duration,\n DEFAULT_DATE_FORMAT,\n AlertSnoozeFormData,\n AlertSnoozeOptions,\n} from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useAlertDialogStyles as useStyles } from '../utils/styles';\nimport { intervalsOf } from '../utils/duration';\n\nexport type AlertSnoozeFormProps = AlertFormProps<Alert, AlertSnoozeFormData>;\n\nexport const AlertSnoozeForm = forwardRef<\n HTMLFormElement,\n AlertSnoozeFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const classes = useStyles();\n const [duration, setDuration] = useState<Maybe<Duration>>(Duration.P7D);\n\n useEffect(() => disableSubmit(false), [disableSubmit]);\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n if (duration) {\n const repeatInterval = 1;\n const today = DateTime.now().toFormat(DEFAULT_DATE_FORMAT);\n onSubmit({\n intervals: intervalsOf(duration, today, repeatInterval),\n });\n }\n };\n\n const onSnoozeDurationChange = (\n _: ChangeEvent<HTMLInputElement>,\n value: string,\n ) => {\n setDuration(value as Duration);\n };\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>For how long?</b>\n </Typography>\n <Box mb={1}>\n <RadioGroup\n name=\"snooze-alert-options\"\n value={duration}\n onChange={onSnoozeDurationChange}\n >\n {AlertSnoozeOptions.map(option => (\n <FormControlLabel\n key={`snooze-alert-option-${option.duration}`}\n label={option.label}\n value={option.duration}\n control={<Radio className={classes.radio} />}\n />\n ))}\n </RadioGroup>\n </Box>\n </FormControl>\n </form>\n );\n});\n"],"names":["useStyles"],"mappings":";;;;;;;;;;;;;;;AA4CO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"AlertSnoozeForm.esm.js","sources":["../../src/forms/AlertSnoozeForm.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ChangeEvent,\n useEffect,\n useState,\n forwardRef,\n FormEventHandler,\n} from 'react';\nimport { DateTime } from 'luxon';\nimport Box from '@material-ui/core/Box';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport RadioGroup from '@material-ui/core/RadioGroup';\nimport Radio from '@material-ui/core/Radio';\nimport Typography from '@material-ui/core/Typography';\nimport {\n Alert,\n AlertFormProps,\n Duration,\n DEFAULT_DATE_FORMAT,\n AlertSnoozeFormData,\n AlertSnoozeOptions,\n} from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useAlertDialogStyles as useStyles } from '../utils/styles';\nimport { intervalsOf } from '../utils/duration';\n\nexport type AlertSnoozeFormProps = AlertFormProps<Alert, AlertSnoozeFormData>;\n\nexport const AlertSnoozeForm = forwardRef<\n HTMLFormElement,\n AlertSnoozeFormProps\n>(({ onSubmit, disableSubmit }, ref) => {\n const classes = useStyles();\n const [duration, setDuration] = useState<Maybe<Duration>>(Duration.P7D);\n\n useEffect(() => disableSubmit(false), [disableSubmit]);\n\n const onFormSubmit: FormEventHandler = e => {\n e.preventDefault();\n if (duration) {\n const repeatInterval = 1;\n const today = DateTime.now().toFormat(DEFAULT_DATE_FORMAT);\n onSubmit({\n intervals: intervalsOf(duration, today, repeatInterval),\n });\n }\n };\n\n const onSnoozeDurationChange = (\n _: ChangeEvent<HTMLInputElement>,\n value: string,\n ) => {\n setDuration(value as Duration);\n };\n\n return (\n <form ref={ref} onSubmit={onFormSubmit}>\n <FormControl component=\"fieldset\" fullWidth>\n <Typography color=\"textPrimary\">\n <b>For how long?</b>\n </Typography>\n <Box mb={1}>\n <RadioGroup\n name=\"snooze-alert-options\"\n value={duration}\n onChange={onSnoozeDurationChange}\n >\n {AlertSnoozeOptions.map(option => (\n <FormControlLabel\n key={`snooze-alert-option-${option.duration}`}\n label={option.label}\n value={option.duration}\n control={<Radio className={classes.radio} />}\n />\n ))}\n </RadioGroup>\n </Box>\n </FormControl>\n </form>\n );\n});\n"],"names":["useStyles"],"mappings":";;;;;;;;;;;;;;;AA4CO,MAAM,kBAAkB,UAAA,CAG7B,CAAC,EAAE,QAAA,EAAU,aAAA,IAAiB,GAAA,KAAQ;AACtC,EAAA,MAAM,UAAUA,oBAAA,EAAU;AAC1B,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,QAAA,CAA0B,SAAS,GAAG,CAAA;AAEtE,EAAA,SAAA,CAAU,MAAM,aAAA,CAAc,KAAK,CAAA,EAAG,CAAC,aAAa,CAAC,CAAA;AAErD,EAAA,MAAM,eAAiC,CAAA,CAAA,KAAK;AAC1C,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,cAAA,GAAiB,CAAA;AACvB,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,EAAI,CAAE,SAAS,mBAAmB,CAAA;AACzD,MAAA,QAAA,CAAS;AAAA,QACP,SAAA,EAAW,WAAA,CAAY,QAAA,EAAU,KAAA,EAAO,cAAc;AAAA,OACvD,CAAA;AAAA,IACH;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,sBAAA,GAAyB,CAC7B,CAAA,EACA,KAAA,KACG;AACH,IAAA,WAAA,CAAY,KAAiB,CAAA;AAAA,EAC/B,CAAA;AAEA,EAAA,uBACE,GAAA,CAAC,MAAA,EAAA,EAAK,GAAA,EAAU,QAAA,EAAU,YAAA,EACxB,+BAAC,WAAA,EAAA,EAAY,SAAA,EAAU,UAAA,EAAW,SAAA,EAAS,IAAA,EACzC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,cAAW,KAAA,EAAM,aAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,2BAAa,CAAA,EAClB,CAAA;AAAA,oBACA,GAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAI,CAAA,EACP,QAAA,kBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,sBAAA;AAAA,QACL,KAAA,EAAO,QAAA;AAAA,QACP,QAAA,EAAU,sBAAA;AAAA,QAET,QAAA,EAAA,kBAAA,CAAmB,IAAI,CAAA,MAAA,qBACtB,GAAA;AAAA,UAAC,gBAAA;AAAA,UAAA;AAAA,YAEC,OAAO,MAAA,CAAO,KAAA;AAAA,YACd,OAAO,MAAA,CAAO,QAAA;AAAA,YACd,OAAA,kBAAS,GAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAW,QAAQ,KAAA,EAAO;AAAA,WAAA;AAAA,UAHrC,CAAA,oBAAA,EAAuB,OAAO,QAAQ,CAAA;AAAA,SAK9C;AAAA;AAAA,KACH,EACF;AAAA,GAAA,EACF,CAAA,EACF,CAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { useState, useEffect, createContext, useContext } from 'react';
|
|
3
3
|
import '../types/Alert.esm.js';
|
|
4
4
|
import { EngineerThreshold } from '../types/ChangeStatistic.esm.js';
|
|
5
5
|
import { getIcon } from '../utils/navigation.esm.js';
|
|
6
6
|
import { validateMetrics, validateCurrencies } from '../utils/config.esm.js';
|
|
7
|
-
import {
|
|
7
|
+
import { defaultCurrencies, createCurrencyFormat } from '../utils/currency.esm.js';
|
|
8
8
|
import { useApi, configApiRef } from '@backstage/core-plugin-api';
|
|
9
9
|
|
|
10
10
|
const ConfigContext = createContext(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useConfig.esm.js","sources":["../../src/hooks/useConfig.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport { Config as BackstageConfig } from '@backstage/config';\nimport { Currency, EngineerThreshold, Icon } from '../types';\nimport {\n Metric,\n Product,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { getIcon } from '../utils/navigation';\nimport { validateCurrencies, validateMetrics } from '../utils/config';\nimport { createCurrencyFormat, defaultCurrencies } from '../utils/currency';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\n/*\n * Config schema 2021-08-05\n *\n * costInsights:\n * engineerCost: 200000\n * products:\n * productA:\n * name: Product A\n * icon: storage\n * productB:\n * name: Product B\n * icon: data\n * metrics:\n * metricA:\n * name: Metric A\n * default: true\n * metricB:\n * name: Metric B\n * baseCurrency:\n * locale: nl-NL\n * options:\n * currency: EUR\n * minimumFractionDigits: 3\n * currencies:\n * currencyA:\n * label: Currency A\n * unit: Unit A\n * currencyB:\n * label: Currency B\n * kind: CURRENCY_B\n * unit: Unit B\n * prefix: B\n * rate: 3.5\n */\n\n/** @public */\nexport type ConfigContextProps = {\n baseCurrency: Intl.NumberFormat;\n metrics: Metric[];\n products: Product[];\n icons: Icon[];\n engineerCost: number;\n engineerThreshold: number;\n hideTrendLine: boolean;\n currencies: Currency[];\n};\n\nexport const ConfigContext = createContext<ConfigContextProps | undefined>(\n undefined,\n);\n\nconst defaultState: ConfigContextProps = {\n baseCurrency: createCurrencyFormat(),\n metrics: [],\n products: [],\n icons: [],\n engineerCost: 0,\n engineerThreshold: EngineerThreshold,\n hideTrendLine: false,\n currencies: defaultCurrencies,\n};\n\nexport const ConfigProvider = ({ children }: PropsWithChildren<{}>) => {\n const c: BackstageConfig = useApi(configApiRef);\n const [config, setConfig] = useState(defaultState);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n function getProducts(): Product[] {\n const products = c.getOptionalConfig('costInsights.products');\n if (products) {\n return products.keys().map(key => ({\n kind: key,\n name: products.getString(`${key}.name`),\n aggregation: [0, 0],\n }));\n }\n return [];\n }\n\n function getMetrics(): Metric[] {\n const metrics = c.getOptionalConfig('costInsights.metrics');\n if (metrics) {\n return metrics.keys().map(key => ({\n kind: key,\n name: metrics.getString(`${key}.name`),\n default: metrics.getOptionalBoolean(`${key}.default`) ?? false,\n }));\n }\n\n return [];\n }\n\n function getBaseCurrency(): Intl.NumberFormat {\n const baseCurrency = c.getOptionalConfig('costInsights.baseCurrency');\n if (baseCurrency) {\n const options = baseCurrency.getOptionalConfig('options');\n return new Intl.NumberFormat(\n baseCurrency.getOptionalString('locale'),\n options\n ? {\n localeMatcher: options.getOptionalString('localeMatcher'),\n style: 'currency',\n currency: options.getOptionalString('currency'),\n currencySign: options.getOptionalString('currencySign'),\n useGrouping: options.getOptionalBoolean('useGrouping'),\n minimumIntegerDigits: options.getOptionalNumber(\n 'minimumIntegerDigits',\n ),\n minimumFractionDigits: options.getOptionalNumber(\n 'minimumFractionDigits',\n ),\n maximumFractionDigits: options.getOptionalNumber(\n 'maximumFractionDigits',\n ),\n minimumSignificantDigits: options.getOptionalNumber(\n 'minimumSignificantDigits',\n ),\n maximumSignificantDigits: options.getOptionalNumber(\n 'maximumSignificantDigits',\n ),\n }\n : undefined,\n );\n }\n\n return defaultState.baseCurrency;\n }\n\n function getCurrencies(): Currency[] {\n const currencies = c.getOptionalConfig('costInsights.currencies');\n if (currencies) {\n return currencies.keys().map(key => ({\n label: currencies.getString(`${key}.label`),\n unit: currencies.getString(`${key}.unit`),\n kind: currencies.getOptionalString(`${key}.kind`) || null,\n prefix: currencies.getOptionalString(`${key}.prefix`),\n rate: currencies.getOptionalNumber(`${key}.rate`),\n }));\n }\n\n return defaultCurrencies;\n }\n\n function getIcons(): Icon[] {\n const products = c.getOptionalConfig('costInsights.products');\n if (products) {\n return products.keys().map(k => ({\n kind: k,\n component: getIcon(products.getOptionalString(`${k}.icon`)),\n }));\n }\n return [];\n }\n\n function getEngineerCost(): number {\n return c.getNumber('costInsights.engineerCost');\n }\n\n function getEngineerThreshold(): number {\n return (\n c.getOptionalNumber('costInsights.engineerThreshold') ??\n defaultState.engineerThreshold\n );\n }\n\n function getHideTrendLine(): boolean {\n return (\n c.getOptionalBoolean('costInsights.hideTrendLine') ??\n defaultState.hideTrendLine\n );\n }\n\n function getConfig() {\n const baseCurrency = getBaseCurrency();\n const products = getProducts();\n const metrics = getMetrics();\n const engineerCost = getEngineerCost();\n const engineerThreshold = getEngineerThreshold();\n const hideTrendLine = getHideTrendLine();\n const icons = getIcons();\n const currencies = getCurrencies();\n\n validateMetrics(metrics);\n validateCurrencies(currencies);\n\n setConfig(prevState => ({\n ...prevState,\n baseCurrency,\n metrics,\n products,\n engineerCost,\n engineerThreshold,\n hideTrendLine,\n icons,\n currencies,\n }));\n\n setLoading(false);\n }\n\n getConfig();\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (loading) {\n return null;\n }\n\n return (\n <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>\n );\n};\n\nexport function useConfig(): ConfigContextProps {\n const config = useContext(ConfigContext);\n return config ? config : assertNever();\n}\n\nfunction assertNever(): never {\n throw new Error('Cannot use useConfig outside of ConfigProvider');\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useConfig.esm.js","sources":["../../src/hooks/useConfig.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport { Config as BackstageConfig } from '@backstage/config';\nimport { Currency, EngineerThreshold, Icon } from '../types';\nimport {\n Metric,\n Product,\n} from '@backstage-community/plugin-cost-insights-common';\nimport { getIcon } from '../utils/navigation';\nimport { validateCurrencies, validateMetrics } from '../utils/config';\nimport { createCurrencyFormat, defaultCurrencies } from '../utils/currency';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\n/*\n * Config schema 2021-08-05\n *\n * costInsights:\n * engineerCost: 200000\n * products:\n * productA:\n * name: Product A\n * icon: storage\n * productB:\n * name: Product B\n * icon: data\n * metrics:\n * metricA:\n * name: Metric A\n * default: true\n * metricB:\n * name: Metric B\n * baseCurrency:\n * locale: nl-NL\n * options:\n * currency: EUR\n * minimumFractionDigits: 3\n * currencies:\n * currencyA:\n * label: Currency A\n * unit: Unit A\n * currencyB:\n * label: Currency B\n * kind: CURRENCY_B\n * unit: Unit B\n * prefix: B\n * rate: 3.5\n */\n\n/** @public */\nexport type ConfigContextProps = {\n baseCurrency: Intl.NumberFormat;\n metrics: Metric[];\n products: Product[];\n icons: Icon[];\n engineerCost: number;\n engineerThreshold: number;\n hideTrendLine: boolean;\n currencies: Currency[];\n};\n\nexport const ConfigContext = createContext<ConfigContextProps | undefined>(\n undefined,\n);\n\nconst defaultState: ConfigContextProps = {\n baseCurrency: createCurrencyFormat(),\n metrics: [],\n products: [],\n icons: [],\n engineerCost: 0,\n engineerThreshold: EngineerThreshold,\n hideTrendLine: false,\n currencies: defaultCurrencies,\n};\n\nexport const ConfigProvider = ({ children }: PropsWithChildren<{}>) => {\n const c: BackstageConfig = useApi(configApiRef);\n const [config, setConfig] = useState(defaultState);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n function getProducts(): Product[] {\n const products = c.getOptionalConfig('costInsights.products');\n if (products) {\n return products.keys().map(key => ({\n kind: key,\n name: products.getString(`${key}.name`),\n aggregation: [0, 0],\n }));\n }\n return [];\n }\n\n function getMetrics(): Metric[] {\n const metrics = c.getOptionalConfig('costInsights.metrics');\n if (metrics) {\n return metrics.keys().map(key => ({\n kind: key,\n name: metrics.getString(`${key}.name`),\n default: metrics.getOptionalBoolean(`${key}.default`) ?? false,\n }));\n }\n\n return [];\n }\n\n function getBaseCurrency(): Intl.NumberFormat {\n const baseCurrency = c.getOptionalConfig('costInsights.baseCurrency');\n if (baseCurrency) {\n const options = baseCurrency.getOptionalConfig('options');\n return new Intl.NumberFormat(\n baseCurrency.getOptionalString('locale'),\n options\n ? ({\n localeMatcher: options.getOptionalString('localeMatcher'),\n style: 'currency',\n currency: options.getOptionalString('currency'),\n currencySign: options.getOptionalString('currencySign'),\n useGrouping: options.getOptionalBoolean('useGrouping'),\n minimumIntegerDigits: options.getOptionalNumber(\n 'minimumIntegerDigits',\n ),\n minimumFractionDigits: options.getOptionalNumber(\n 'minimumFractionDigits',\n ),\n maximumFractionDigits: options.getOptionalNumber(\n 'maximumFractionDigits',\n ),\n minimumSignificantDigits: options.getOptionalNumber(\n 'minimumSignificantDigits',\n ),\n maximumSignificantDigits: options.getOptionalNumber(\n 'maximumSignificantDigits',\n ),\n } as Intl.NumberFormatOptions)\n : undefined,\n );\n }\n\n return defaultState.baseCurrency;\n }\n\n function getCurrencies(): Currency[] {\n const currencies = c.getOptionalConfig('costInsights.currencies');\n if (currencies) {\n return currencies.keys().map(key => ({\n label: currencies.getString(`${key}.label`),\n unit: currencies.getString(`${key}.unit`),\n kind: currencies.getOptionalString(`${key}.kind`) || null,\n prefix: currencies.getOptionalString(`${key}.prefix`),\n rate: currencies.getOptionalNumber(`${key}.rate`),\n }));\n }\n\n return defaultCurrencies;\n }\n\n function getIcons(): Icon[] {\n const products = c.getOptionalConfig('costInsights.products');\n if (products) {\n return products.keys().map(k => ({\n kind: k,\n component: getIcon(products.getOptionalString(`${k}.icon`)),\n }));\n }\n return [];\n }\n\n function getEngineerCost(): number {\n return c.getNumber('costInsights.engineerCost');\n }\n\n function getEngineerThreshold(): number {\n return (\n c.getOptionalNumber('costInsights.engineerThreshold') ??\n defaultState.engineerThreshold\n );\n }\n\n function getHideTrendLine(): boolean {\n return (\n c.getOptionalBoolean('costInsights.hideTrendLine') ??\n defaultState.hideTrendLine\n );\n }\n\n function getConfig() {\n const baseCurrency = getBaseCurrency();\n const products = getProducts();\n const metrics = getMetrics();\n const engineerCost = getEngineerCost();\n const engineerThreshold = getEngineerThreshold();\n const hideTrendLine = getHideTrendLine();\n const icons = getIcons();\n const currencies = getCurrencies();\n\n validateMetrics(metrics);\n validateCurrencies(currencies);\n\n setConfig(prevState => ({\n ...prevState,\n baseCurrency,\n metrics,\n products,\n engineerCost,\n engineerThreshold,\n hideTrendLine,\n icons,\n currencies,\n }));\n\n setLoading(false);\n }\n\n getConfig();\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (loading) {\n return null;\n }\n\n return (\n <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>\n );\n};\n\nexport function useConfig(): ConfigContextProps {\n const config = useContext(ConfigContext);\n return config ? config : assertNever();\n}\n\nfunction assertNever(): never {\n throw new Error('Cannot use useConfig outside of ConfigProvider');\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCurrency.esm.js","sources":["../../src/hooks/useCurrency.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n createContext,\n Dispatch,\n SetStateAction,\n useState,\n useContext,\n PropsWithChildren,\n} from 'react';\nimport { Currency } from '../types';\nimport { useConfig } from './useConfig';\n\n/** @public */\nexport type CurrencyContextProps = {\n currency: Currency;\n setCurrency: Dispatch<SetStateAction<Currency>>;\n};\n\nexport const CurrencyContext = createContext<CurrencyContextProps | undefined>(\n undefined,\n);\n\nexport const CurrencyProvider = ({ children }: PropsWithChildren<{}>) => {\n const config = useConfig();\n const currencies = config.currencies;\n const engineers = currencies.find(currency => currency.kind === null);\n const [currency, setCurrency] = useState<Currency>(\n engineers || currencies[0],\n );\n return (\n <CurrencyContext.Provider value={{ currency, setCurrency }}>\n {children}\n </CurrencyContext.Provider>\n );\n};\n\nexport function useCurrency(): [Currency, Dispatch<SetStateAction<Currency>>] {\n const context = useContext(CurrencyContext);\n\n if (!context) {\n assertNever();\n }\n\n return [context.currency, context.setCurrency];\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useCurrency outside of CurrencyProvider');\n}\n"],"names":["currency"],"mappings":";;;;AAgCO,MAAM,
|
|
1
|
+
{"version":3,"file":"useCurrency.esm.js","sources":["../../src/hooks/useCurrency.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n createContext,\n Dispatch,\n SetStateAction,\n useState,\n useContext,\n PropsWithChildren,\n} from 'react';\nimport { Currency } from '../types';\nimport { useConfig } from './useConfig';\n\n/** @public */\nexport type CurrencyContextProps = {\n currency: Currency;\n setCurrency: Dispatch<SetStateAction<Currency>>;\n};\n\nexport const CurrencyContext = createContext<CurrencyContextProps | undefined>(\n undefined,\n);\n\nexport const CurrencyProvider = ({ children }: PropsWithChildren<{}>) => {\n const config = useConfig();\n const currencies = config.currencies;\n const engineers = currencies.find(currency => currency.kind === null);\n const [currency, setCurrency] = useState<Currency>(\n engineers || currencies[0],\n );\n return (\n <CurrencyContext.Provider value={{ currency, setCurrency }}>\n {children}\n </CurrencyContext.Provider>\n );\n};\n\nexport function useCurrency(): [Currency, Dispatch<SetStateAction<Currency>>] {\n const context = useContext(CurrencyContext);\n\n if (!context) {\n assertNever();\n }\n\n return [context.currency, context.setCurrency];\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useCurrency outside of CurrencyProvider');\n}\n"],"names":["currency"],"mappings":";;;;AAgCO,MAAM,eAAA,GAAkB,aAAA;AAAA,EAC7B;AACF;AAEO,MAAM,gBAAA,GAAmB,CAAC,EAAE,QAAA,EAAS,KAA6B;AACvE,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,aAAa,MAAA,CAAO,UAAA;AAC1B,EAAA,MAAM,YAAY,UAAA,CAAW,IAAA,CAAK,CAAAA,SAAAA,KAAYA,SAAAA,CAAS,SAAS,IAAI,CAAA;AACpE,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,QAAA;AAAA,IAC9B,SAAA,IAAa,WAAW,CAAC;AAAA,GAC3B;AACA,EAAA,uBACE,GAAA,CAAC,gBAAgB,QAAA,EAAhB,EAAyB,OAAO,EAAE,QAAA,EAAU,WAAA,EAAY,EACtD,QAAA,EACH,CAAA;AAEJ;AAEO,SAAS,WAAA,GAA8D;AAC5E,EAAA,MAAM,OAAA,GAAU,WAAW,eAAe,CAAA;AAE1C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,WAAA,EAAY;AAAA,EACd;AAEA,EAAA,OAAO,CAAC,OAAA,CAAQ,QAAA,EAAU,OAAA,CAAQ,WAAW,CAAA;AAC/C;AAEA,SAAS,WAAA,GAAqB;AAC5B,EAAA,MAAM,MAAM,oDAAoD,CAAA;AAClE;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { useState, useEffect, createContext, useContext } from 'react';
|
|
3
3
|
import Alert from '@material-ui/lab/Alert';
|
|
4
4
|
import { useNavigate, useLocation } from 'react-router-dom';
|
|
5
5
|
import { validate, getInitialPageState, getInitialProductState, stringify } from '../utils/history.esm.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFilters.esm.js","sources":["../../src/hooks/useFilters.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createContext,\n Dispatch,\n PropsWithChildren,\n SetStateAction,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport { PageFilters, ProductFilters } from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport {\n stringify,\n validate,\n getInitialPageState,\n getInitialProductState,\n} from '../utils/history';\nimport { useGroups } from './useGroups';\nimport { useConfig } from './useConfig';\n\nexport type FilterContextProps = {\n pageFilters: PageFilters;\n productFilters: ProductFilters;\n setPageFilters: Dispatch<SetStateAction<Maybe<PageFilters>>>;\n setProductFilters: Dispatch<SetStateAction<Maybe<ProductFilters>>>;\n};\n\nexport type MapFiltersToProps<T> = (props: FilterContextProps) => T;\n\nexport const FilterContext = createContext<FilterContextProps | undefined>(\n undefined,\n);\n\nexport const FilterProvider = ({ children }: PropsWithChildren<{}>) => {\n const config = useConfig();\n const navigate = useNavigate();\n const location = useLocation();\n const groups = useGroups();\n const [error, setError] = useState<Maybe<Error>>(null);\n const [pageFilters, setPageFilters] = useState<Maybe<PageFilters>>(null);\n const [productFilters, setProductFilters] =\n useState<Maybe<ProductFilters>>(null);\n\n useEffect(() => {\n async function setPageFiltersFromLocation() {\n try {\n // strip extraneous parameters, validate and transform\n const queryParams = await validate(location.search);\n const defaultMetric = config.metrics.find(m => m.default)?.kind ?? null;\n\n // Group or project parameters should override defaults\n const initialPageState = getInitialPageState(groups, queryParams);\n const initialProductState = getInitialProductState(config);\n\n setProductFilters(initialProductState);\n setPageFilters({ ...initialPageState, metric: defaultMetric });\n } catch (e) {\n setError(e);\n }\n }\n\n setPageFiltersFromLocation();\n }, [groups]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n function setLocationFromPageFilters(filters: PageFilters) {\n const queryString = stringify({\n group: filters.group,\n ...(filters.project ? { project: filters.project } : {}),\n });\n // TODO Remove workaround once issue is resolved in react-router\n // (https://github.com/ReactTraining/react-router/issues/7496)\n // navigate({ ...location, search: queryString });\n navigate({ ...location, search: `?${queryString}` });\n }\n\n if (pageFilters) {\n setLocationFromPageFilters(pageFilters);\n }\n }, [pageFilters]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n // Wait for filters to load\n if (!pageFilters || !productFilters) {\n return null;\n }\n\n return (\n <FilterContext.Provider\n value={{ pageFilters, productFilters, setPageFilters, setProductFilters }}\n >\n {children}\n </FilterContext.Provider>\n );\n};\n\nexport function useFilters<T>(mapFiltersToProps: MapFiltersToProps<T>): T {\n const context = useContext(FilterContext);\n return context ? mapFiltersToProps(context) : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useFilters outside of FilterProvider');\n}\n"],"names":[],"mappings":";;;;;;;;AA+CO,MAAM,
|
|
1
|
+
{"version":3,"file":"useFilters.esm.js","sources":["../../src/hooks/useFilters.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createContext,\n Dispatch,\n PropsWithChildren,\n SetStateAction,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport { PageFilters, ProductFilters } from '../types';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport {\n stringify,\n validate,\n getInitialPageState,\n getInitialProductState,\n} from '../utils/history';\nimport { useGroups } from './useGroups';\nimport { useConfig } from './useConfig';\n\nexport type FilterContextProps = {\n pageFilters: PageFilters;\n productFilters: ProductFilters;\n setPageFilters: Dispatch<SetStateAction<Maybe<PageFilters>>>;\n setProductFilters: Dispatch<SetStateAction<Maybe<ProductFilters>>>;\n};\n\nexport type MapFiltersToProps<T> = (props: FilterContextProps) => T;\n\nexport const FilterContext = createContext<FilterContextProps | undefined>(\n undefined,\n);\n\nexport const FilterProvider = ({ children }: PropsWithChildren<{}>) => {\n const config = useConfig();\n const navigate = useNavigate();\n const location = useLocation();\n const groups = useGroups();\n const [error, setError] = useState<Maybe<Error>>(null);\n const [pageFilters, setPageFilters] = useState<Maybe<PageFilters>>(null);\n const [productFilters, setProductFilters] =\n useState<Maybe<ProductFilters>>(null);\n\n useEffect(() => {\n async function setPageFiltersFromLocation() {\n try {\n // strip extraneous parameters, validate and transform\n const queryParams = await validate(location.search);\n const defaultMetric = config.metrics.find(m => m.default)?.kind ?? null;\n\n // Group or project parameters should override defaults\n const initialPageState = getInitialPageState(groups, queryParams);\n const initialProductState = getInitialProductState(config);\n\n setProductFilters(initialProductState);\n setPageFilters({ ...initialPageState, metric: defaultMetric });\n } catch (e) {\n setError(e);\n }\n }\n\n setPageFiltersFromLocation();\n }, [groups]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n function setLocationFromPageFilters(filters: PageFilters) {\n const queryString = stringify({\n group: filters.group,\n ...(filters.project ? { project: filters.project } : {}),\n });\n // TODO Remove workaround once issue is resolved in react-router\n // (https://github.com/ReactTraining/react-router/issues/7496)\n // navigate({ ...location, search: queryString });\n navigate({ ...location, search: `?${queryString}` });\n }\n\n if (pageFilters) {\n setLocationFromPageFilters(pageFilters);\n }\n }, [pageFilters]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n // Wait for filters to load\n if (!pageFilters || !productFilters) {\n return null;\n }\n\n return (\n <FilterContext.Provider\n value={{ pageFilters, productFilters, setPageFilters, setProductFilters }}\n >\n {children}\n </FilterContext.Provider>\n );\n};\n\nexport function useFilters<T>(mapFiltersToProps: MapFiltersToProps<T>): T {\n const context = useContext(FilterContext);\n return context ? mapFiltersToProps(context) : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useFilters outside of FilterProvider');\n}\n"],"names":[],"mappings":";;;;;;;;AA+CO,MAAM,aAAA,GAAgB,aAAA;AAAA,EAC3B;AACF;AAEO,MAAM,cAAA,GAAiB,CAAC,EAAE,QAAA,EAAS,KAA6B;AACrE,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAA6B,IAAI,CAAA;AACvE,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GACtC,SAAgC,IAAI,CAAA;AAEtC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,eAAe,0BAAA,GAA6B;AAC1C,MAAA,IAAI;AAEF,QAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA;AAClD,QAAA,MAAM,aAAA,GAAgB,OAAO,OAAA,CAAQ,IAAA,CAAK,OAAK,CAAA,CAAE,OAAO,GAAG,IAAA,IAAQ,IAAA;AAGnE,QAAA,MAAM,gBAAA,GAAmB,mBAAA,CAAoB,MAAA,EAAQ,WAAW,CAAA;AAChE,QAAA,MAAM,mBAAA,GAAsB,uBAAuB,MAAM,CAAA;AAEzD,QAAA,iBAAA,CAAkB,mBAAmB,CAAA;AACrC,QAAA,cAAA,CAAe,EAAE,GAAG,gBAAA,EAAkB,MAAA,EAAQ,eAAe,CAAA;AAAA,MAC/D,SAAS,CAAA,EAAG;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AAAA,MACZ;AAAA,IACF;AAEA,IAAA,0BAAA,EAA2B;AAAA,EAC7B,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,SAAS,2BAA2B,OAAA,EAAsB;AACxD,MAAA,MAAM,cAAc,SAAA,CAAU;AAAA,QAC5B,OAAO,OAAA,CAAQ,KAAA;AAAA,QACf,GAAI,QAAQ,OAAA,GAAU,EAAE,SAAS,OAAA,CAAQ,OAAA,KAAY;AAAC,OACvD,CAAA;AAID,MAAA,QAAA,CAAS,EAAE,GAAG,QAAA,EAAU,QAAQ,CAAA,CAAA,EAAI,WAAW,IAAI,CAAA;AAAA,IACrD;AAEA,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,0BAAA,CAA2B,WAAW,CAAA;AAAA,IACxC;AAAA,EACF,CAAA,EAAG,CAAC,WAAW,CAAC,CAAA;AAEhB,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAS,OAAA,EAAS,gBAAM,OAAA,EAAQ,CAAA;AAAA,EAChD;AAGA,EAAA,IAAI,CAAC,WAAA,IAAe,CAAC,cAAA,EAAgB;AACnC,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,aAAA,CAAc,QAAA;AAAA,IAAd;AAAA,MACC,KAAA,EAAO,EAAE,WAAA,EAAa,cAAA,EAAgB,gBAAgB,iBAAA,EAAkB;AAAA,MAEvE;AAAA;AAAA,GACH;AAEJ;AAEO,SAAS,WAAc,iBAAA,EAA4C;AACxE,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAA,OAAO,OAAA,GAAU,iBAAA,CAAkB,OAAO,CAAA,GAAI,WAAA,EAAY;AAC5D;AAEA,SAAS,WAAA,GAAqB;AAC5B,EAAA,MAAM,MAAM,iDAAiD,CAAA;AAC/D;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { useState, useEffect, createContext, useContext } from 'react';
|
|
3
3
|
import Alert from '@material-ui/lab/Alert';
|
|
4
4
|
import { costInsightsApiRef } from '../api/CostInsightsApi.esm.js';
|
|
5
5
|
import { useLoading } from './useLoading.esm.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGroups.esm.js","sources":["../../src/hooks/useGroups.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport { costInsightsApiRef } from '../api';\nimport { MapLoadingToProps, useLoading } from './useLoading';\nimport { Group, Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { DefaultLoadingAction } from '../utils/loading';\nimport { useApi, identityApiRef } from '@backstage/core-plugin-api';\nimport { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model';\n\ntype GroupsProviderLoadingProps = {\n dispatchLoadingGroups: (isLoading: boolean) => void;\n};\n\nconst mapLoadingToProps: MapLoadingToProps<GroupsProviderLoadingProps> = ({\n dispatch,\n}) => ({\n dispatchLoadingGroups: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.UserGroups]: isLoading }),\n});\n\nexport type GroupsContextProps = {\n groups: Group[];\n};\n\nexport const GroupsContext = createContext<GroupsContextProps | undefined>(\n undefined,\n);\n\nexport const GroupsProvider = ({ children }: PropsWithChildren<{}>) => {\n const identityApi = useApi(identityApiRef);\n const client = useApi(costInsightsApiRef);\n const [error, setError] = useState<Maybe<Error>>(null);\n const { dispatchLoadingGroups } = useLoading(mapLoadingToProps);\n\n const [groups, setGroups] = useState<Maybe<Group[]>>(null);\n\n useEffect(() => {\n dispatchLoadingGroups(true);\n\n async function getUserGroups() {\n try {\n const { userEntityRef } = await identityApi.getBackstageIdentity();\n const { name: userId } = parseEntityRef(userEntityRef, {\n defaultKind: 'User',\n defaultNamespace: DEFAULT_NAMESPACE,\n });\n const g = await client.getUserGroups(userId);\n setGroups(g);\n } catch (e) {\n setError(e);\n } finally {\n dispatchLoadingGroups(false);\n }\n }\n\n getUserGroups();\n }, [client]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n if (!groups) return null;\n\n return (\n <GroupsContext.Provider value={{ groups: groups }}>\n {children}\n </GroupsContext.Provider>\n );\n};\n\nexport function useGroups(): Group[] {\n const context = useContext(GroupsContext);\n return context ? context.groups : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useGroups outside of GroupsProvider');\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCA,MAAM,oBAAmE,CAAC;AAAA,EACxE;AACF,
|
|
1
|
+
{"version":3,"file":"useGroups.esm.js","sources":["../../src/hooks/useGroups.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport { costInsightsApiRef } from '../api';\nimport { MapLoadingToProps, useLoading } from './useLoading';\nimport { Group, Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { DefaultLoadingAction } from '../utils/loading';\nimport { useApi, identityApiRef } from '@backstage/core-plugin-api';\nimport { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model';\n\ntype GroupsProviderLoadingProps = {\n dispatchLoadingGroups: (isLoading: boolean) => void;\n};\n\nconst mapLoadingToProps: MapLoadingToProps<GroupsProviderLoadingProps> = ({\n dispatch,\n}) => ({\n dispatchLoadingGroups: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.UserGroups]: isLoading }),\n});\n\nexport type GroupsContextProps = {\n groups: Group[];\n};\n\nexport const GroupsContext = createContext<GroupsContextProps | undefined>(\n undefined,\n);\n\nexport const GroupsProvider = ({ children }: PropsWithChildren<{}>) => {\n const identityApi = useApi(identityApiRef);\n const client = useApi(costInsightsApiRef);\n const [error, setError] = useState<Maybe<Error>>(null);\n const { dispatchLoadingGroups } = useLoading(mapLoadingToProps);\n\n const [groups, setGroups] = useState<Maybe<Group[]>>(null);\n\n useEffect(() => {\n dispatchLoadingGroups(true);\n\n async function getUserGroups() {\n try {\n const { userEntityRef } = await identityApi.getBackstageIdentity();\n const { name: userId } = parseEntityRef(userEntityRef, {\n defaultKind: 'User',\n defaultNamespace: DEFAULT_NAMESPACE,\n });\n const g = await client.getUserGroups(userId);\n setGroups(g);\n } catch (e) {\n setError(e);\n } finally {\n dispatchLoadingGroups(false);\n }\n }\n\n getUserGroups();\n }, [client]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n if (!groups) return null;\n\n return (\n <GroupsContext.Provider value={{ groups: groups }}>\n {children}\n </GroupsContext.Provider>\n );\n};\n\nexport function useGroups(): Group[] {\n const context = useContext(GroupsContext);\n return context ? context.groups : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error('Cannot use useGroups outside of GroupsProvider');\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCA,MAAM,oBAAmE,CAAC;AAAA,EACxE;AACF,CAAA,MAAO;AAAA,EACL,qBAAA,EAAuB,CAAC,SAAA,KACtB,QAAA,CAAS,EAAE,CAAC,oBAAA,CAAqB,UAAU,GAAG,SAAA,EAAW;AAC7D,CAAA,CAAA;AAMO,MAAM,aAAA,GAAgB,aAAA;AAAA,EAC3B;AACF;AAEO,MAAM,cAAA,GAAiB,CAAC,EAAE,QAAA,EAAS,KAA6B;AACrE,EAAA,MAAM,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAA,MAAM,MAAA,GAAS,OAAO,kBAAkB,CAAA;AACxC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,EAAE,qBAAA,EAAsB,GAAI,UAAA,CAAW,iBAAiB,CAAA;AAE9D,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAyB,IAAI,CAAA;AAEzD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,qBAAA,CAAsB,IAAI,CAAA;AAE1B,IAAA,eAAe,aAAA,GAAgB;AAC7B,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,YAAY,oBAAA,EAAqB;AACjE,QAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAO,GAAI,eAAe,aAAA,EAAe;AAAA,UACrD,WAAA,EAAa,MAAA;AAAA,UACb,gBAAA,EAAkB;AAAA,SACnB,CAAA;AACD,QAAA,MAAM,CAAA,GAAI,MAAM,MAAA,CAAO,aAAA,CAAc,MAAM,CAAA;AAC3C,QAAA,SAAA,CAAU,CAAC,CAAA;AAAA,MACb,SAAS,CAAA,EAAG;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AAAA,MACZ,CAAA,SAAE;AACA,QAAA,qBAAA,CAAsB,KAAK,CAAA;AAAA,MAC7B;AAAA,IACF;AAEA,IAAA,aAAA,EAAc;AAAA,EAChB,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAS,OAAA,EAAS,gBAAM,OAAA,EAAQ,CAAA;AAAA,EAChD;AAEA,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAEpB,EAAA,uBACE,GAAA,CAAC,cAAc,QAAA,EAAd,EAAuB,OAAO,EAAE,MAAA,IAC9B,QAAA,EACH,CAAA;AAEJ;AAEO,SAAS,SAAA,GAAqB;AACnC,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAA,OAAO,OAAA,GAAU,OAAA,CAAQ,MAAA,GAAS,WAAA,EAAY;AAChD;AAEA,SAAS,WAAA,GAAqB;AAC5B,EAAA,MAAM,MAAM,gDAAgD,CAAA;AAC9D;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { useState, useEffect, createContext, useContext } from 'react';
|
|
3
3
|
import * as yup from 'yup';
|
|
4
4
|
import Alert from '@material-ui/lab/Alert';
|
|
5
5
|
import { costInsightsApiRef } from '../api/CostInsightsApi.esm.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLastCompleteBillingDate.esm.js","sources":["../../src/hooks/useLastCompleteBillingDate.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport * as yup from 'yup';\nimport Alert from '@material-ui/lab/Alert';\nimport { costInsightsApiRef } from '../api';\nimport { MapLoadingToProps, useLoading } from './useLoading';\nimport { DefaultLoadingAction } from '../utils/loading';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useApi } from '@backstage/core-plugin-api';\n\ntype BillingDateProviderLoadingProps = {\n dispatchLoadingBillingDate: (isLoading: boolean) => void;\n};\n\nconst mapLoadingToProps: MapLoadingToProps<BillingDateProviderLoadingProps> = ({\n dispatch,\n}) => ({\n dispatchLoadingBillingDate: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.LastCompleteBillingDate]: isLoading }),\n});\n\nexport type BillingDateContextProps = {\n lastCompleteBillingDate: string; // YYYY-MM-DD\n};\n\nexport const BillingDateContext = createContext<\n BillingDateContextProps | undefined\n>(undefined);\n\nexport const dateRegex: RegExp = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst dateFormatSchema = yup.string().matches(dateRegex, {\n message:\n 'Unsupported billing date format: ${value}. Date should be in YYYY-MM-DD format.',\n excludeEmptyString: true,\n});\n\nexport const BillingDateProvider = ({ children }: PropsWithChildren<{}>) => {\n const client = useApi(costInsightsApiRef);\n const [error, setError] = useState<Maybe<Error>>(null);\n const { dispatchLoadingBillingDate } = useLoading(mapLoadingToProps);\n\n const [lastCompleteBillingDate, setLastCompeteBillingDate] =\n useState<Maybe<string>>(null);\n\n useEffect(() => {\n dispatchLoadingBillingDate(true);\n\n async function getLastCompleteBillingDate() {\n try {\n const d = await client.getLastCompleteBillingDate();\n const validDate = await dateFormatSchema.validate(d);\n if (validDate) setLastCompeteBillingDate(validDate);\n } catch (e) {\n setError(e);\n } finally {\n dispatchLoadingBillingDate(false);\n }\n }\n\n getLastCompleteBillingDate();\n }, [client]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n if (!lastCompleteBillingDate) return null;\n\n return (\n <BillingDateContext.Provider\n value={\n {\n lastCompleteBillingDate: lastCompleteBillingDate,\n } as BillingDateContextProps\n }\n >\n {children}\n </BillingDateContext.Provider>\n );\n};\n\nexport function useLastCompleteBillingDate(): string {\n const context = useContext(BillingDateContext);\n return context ? context.lastCompleteBillingDate : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error(\n 'Cannot use useLastCompleteBillingDate outside of BillingDateProvider',\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCA,MAAM,oBAAwE,CAAC;AAAA,EAC7E;AACF,
|
|
1
|
+
{"version":3,"file":"useLastCompleteBillingDate.esm.js","sources":["../../src/hooks/useLastCompleteBillingDate.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport * as yup from 'yup';\nimport Alert from '@material-ui/lab/Alert';\nimport { costInsightsApiRef } from '../api';\nimport { MapLoadingToProps, useLoading } from './useLoading';\nimport { DefaultLoadingAction } from '../utils/loading';\nimport { Maybe } from '@backstage-community/plugin-cost-insights-common';\nimport { useApi } from '@backstage/core-plugin-api';\n\ntype BillingDateProviderLoadingProps = {\n dispatchLoadingBillingDate: (isLoading: boolean) => void;\n};\n\nconst mapLoadingToProps: MapLoadingToProps<BillingDateProviderLoadingProps> = ({\n dispatch,\n}) => ({\n dispatchLoadingBillingDate: (isLoading: boolean) =>\n dispatch({ [DefaultLoadingAction.LastCompleteBillingDate]: isLoading }),\n});\n\nexport type BillingDateContextProps = {\n lastCompleteBillingDate: string; // YYYY-MM-DD\n};\n\nexport const BillingDateContext = createContext<\n BillingDateContextProps | undefined\n>(undefined);\n\nexport const dateRegex: RegExp = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst dateFormatSchema = yup.string().matches(dateRegex, {\n message:\n 'Unsupported billing date format: ${value}. Date should be in YYYY-MM-DD format.',\n excludeEmptyString: true,\n});\n\nexport const BillingDateProvider = ({ children }: PropsWithChildren<{}>) => {\n const client = useApi(costInsightsApiRef);\n const [error, setError] = useState<Maybe<Error>>(null);\n const { dispatchLoadingBillingDate } = useLoading(mapLoadingToProps);\n\n const [lastCompleteBillingDate, setLastCompeteBillingDate] =\n useState<Maybe<string>>(null);\n\n useEffect(() => {\n dispatchLoadingBillingDate(true);\n\n async function getLastCompleteBillingDate() {\n try {\n const d = await client.getLastCompleteBillingDate();\n const validDate = await dateFormatSchema.validate(d);\n if (validDate) setLastCompeteBillingDate(validDate);\n } catch (e) {\n setError(e);\n } finally {\n dispatchLoadingBillingDate(false);\n }\n }\n\n getLastCompleteBillingDate();\n }, [client]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n if (!lastCompleteBillingDate) return null;\n\n return (\n <BillingDateContext.Provider\n value={\n {\n lastCompleteBillingDate: lastCompleteBillingDate,\n } as BillingDateContextProps\n }\n >\n {children}\n </BillingDateContext.Provider>\n );\n};\n\nexport function useLastCompleteBillingDate(): string {\n const context = useContext(BillingDateContext);\n return context ? context.lastCompleteBillingDate : assertNever();\n}\n\nfunction assertNever(): never {\n throw Error(\n 'Cannot use useLastCompleteBillingDate outside of BillingDateProvider',\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCA,MAAM,oBAAwE,CAAC;AAAA,EAC7E;AACF,CAAA,MAAO;AAAA,EACL,0BAAA,EAA4B,CAAC,SAAA,KAC3B,QAAA,CAAS,EAAE,CAAC,oBAAA,CAAqB,uBAAuB,GAAG,SAAA,EAAW;AAC1E,CAAA,CAAA;AAMO,MAAM,kBAAA,GAAqB,cAEhC,MAAS;AAEJ,MAAM,SAAA,GAAoB;AACjC,MAAM,gBAAA,GAAmB,GAAA,CAAI,MAAA,EAAO,CAAE,QAAQ,SAAA,EAAW;AAAA,EACvD,OAAA,EACE,iFAAA;AAAA,EACF,kBAAA,EAAoB;AACtB,CAAC,CAAA;AAEM,MAAM,mBAAA,GAAsB,CAAC,EAAE,QAAA,EAAS,KAA6B;AAC1E,EAAA,MAAM,MAAA,GAAS,OAAO,kBAAkB,CAAA;AACxC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,EAAE,0BAAA,EAA2B,GAAI,UAAA,CAAW,iBAAiB,CAAA;AAEnE,EAAA,MAAM,CAAC,uBAAA,EAAyB,yBAAyB,CAAA,GACvD,SAAwB,IAAI,CAAA;AAE9B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,0BAAA,CAA2B,IAAI,CAAA;AAE/B,IAAA,eAAe,0BAAA,GAA6B;AAC1C,MAAA,IAAI;AACF,QAAA,MAAM,CAAA,GAAI,MAAM,MAAA,CAAO,0BAAA,EAA2B;AAClD,QAAA,MAAM,SAAA,GAAY,MAAM,gBAAA,CAAiB,QAAA,CAAS,CAAC,CAAA;AACnD,QAAA,IAAI,SAAA,4BAAqC,SAAS,CAAA;AAAA,MACpD,SAAS,CAAA,EAAG;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AAAA,MACZ,CAAA,SAAE;AACA,QAAA,0BAAA,CAA2B,KAAK,CAAA;AAAA,MAClC;AAAA,IACF;AAEA,IAAA,0BAAA,EAA2B;AAAA,EAC7B,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAS,OAAA,EAAS,gBAAM,OAAA,EAAQ,CAAA;AAAA,EAChD;AAEA,EAAA,IAAI,CAAC,yBAAyB,OAAO,IAAA;AAErC,EAAA,uBACE,GAAA;AAAA,IAAC,kBAAA,CAAmB,QAAA;AAAA,IAAnB;AAAA,MACC,KAAA,EACE;AAAA,QACE;AAAA,OACF;AAAA,MAGD;AAAA;AAAA,GACH;AAEJ;AAEO,SAAS,0BAAA,GAAqC;AACnD,EAAA,MAAM,OAAA,GAAU,WAAW,kBAAkB,CAAA;AAC7C,EAAA,OAAO,OAAA,GAAU,OAAA,CAAQ,uBAAA,GAA0B,WAAA,EAAY;AACjE;AAEA,SAAS,WAAA,GAAqB;AAC5B,EAAA,MAAM,KAAA;AAAA,IACJ;AAAA,GACF;AACF;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { useMemo, useReducer, useState, useEffect, createContext, useContext } from 'react';
|
|
3
3
|
import Backdrop from '@material-ui/core/Backdrop';
|
|
4
4
|
import CircularProgress from '@material-ui/core/CircularProgress';
|
|
5
5
|
import { INITIAL_LOADING_ACTIONS, DefaultLoadingAction, getDefaultState } from '../utils/loading.esm.js';
|