@backstage-community/plugin-cost-insights 0.15.1 → 0.16.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 +18 -0
- package/dist/alerts/ProjectGrowthAlert.esm.js +2 -2
- package/dist/alerts/ProjectGrowthAlert.esm.js.map +1 -1
- package/dist/alerts/UnlabeledDataflowAlert.esm.js +2 -2
- package/dist/alerts/UnlabeledDataflowAlert.esm.js.map +1 -1
- package/dist/components/ActionItems/ActionItemCard.esm.js +3 -3
- package/dist/components/ActionItems/ActionItemCard.esm.js.map +1 -1
- package/dist/components/ActionItems/ActionItems.esm.js +52 -41
- package/dist/components/ActionItems/ActionItems.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertDialog.esm.js +79 -58
- package/dist/components/AlertInsights/AlertDialog.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsights.esm.js +57 -44
- package/dist/components/AlertInsights/AlertInsights.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsightsHeader.esm.js +10 -2
- package/dist/components/AlertInsights/AlertInsightsHeader.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsightsSection.esm.js +42 -34
- package/dist/components/AlertInsights/AlertInsightsSection.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertInsightsSectionHeader.esm.js +23 -12
- package/dist/components/AlertInsights/AlertInsightsSectionHeader.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertStatusSummary.esm.js +63 -55
- package/dist/components/AlertInsights/AlertStatusSummary.esm.js.map +1 -1
- package/dist/components/AlertInsights/AlertStatusSummaryButton.esm.js +7 -6
- package/dist/components/AlertInsights/AlertStatusSummaryButton.esm.js.map +1 -1
- package/dist/components/AlertInstructionsLayout/AlertInstructionsLayout.esm.js +23 -17
- package/dist/components/AlertInstructionsLayout/AlertInstructionsLayout.esm.js.map +1 -1
- package/dist/components/BarChart/BarChart.esm.js +83 -78
- package/dist/components/BarChart/BarChart.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartLabel.esm.js +8 -5
- package/dist/components/BarChart/BarChartLabel.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartLegend.esm.js +20 -16
- package/dist/components/BarChart/BarChartLegend.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartStepper.esm.js +51 -48
- package/dist/components/BarChart/BarChartStepper.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartStepperButton.esm.js +6 -5
- package/dist/components/BarChart/BarChartStepperButton.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartSteps.esm.js +3 -3
- package/dist/components/BarChart/BarChartSteps.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartTick.esm.js +5 -5
- package/dist/components/BarChart/BarChartTick.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartTooltip.esm.js +27 -14
- package/dist/components/BarChart/BarChartTooltip.esm.js.map +1 -1
- package/dist/components/BarChart/BarChartTooltipItem.esm.js +11 -6
- package/dist/components/BarChart/BarChartTooltipItem.esm.js.map +1 -1
- package/dist/components/CopyUrlToClipboard/CopyUrlToClipboard.esm.js +3 -2
- package/dist/components/CopyUrlToClipboard/CopyUrlToClipboard.esm.js.map +1 -1
- package/dist/components/CostGrowth/CostGrowth.esm.js +26 -7
- package/dist/components/CostGrowth/CostGrowth.esm.js.map +1 -1
- package/dist/components/CostGrowth/CostGrowthIndicator.esm.js +6 -2
- package/dist/components/CostGrowth/CostGrowthIndicator.esm.js.map +1 -1
- package/dist/components/CostInsightsHeader/CostInsightsHeader.esm.js +77 -8
- package/dist/components/CostInsightsHeader/CostInsightsHeader.esm.js.map +1 -1
- package/dist/components/CostInsightsLayout/CostInsightsLayout.esm.js +16 -10
- package/dist/components/CostInsightsLayout/CostInsightsLayout.esm.js.map +1 -1
- package/dist/components/CostInsightsNavigation/CostInsightsNavigation.esm.js +41 -35
- package/dist/components/CostInsightsNavigation/CostInsightsNavigation.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/CostInsightsPage.esm.js +116 -79
- package/dist/components/CostInsightsPage/CostInsightsPage.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/CostInsightsPageRoot.esm.js +2 -2
- package/dist/components/CostInsightsPage/CostInsightsPageRoot.esm.js.map +1 -1
- package/dist/components/CostInsightsPage/CostInsightsThemeProvider.esm.js +5 -5
- package/dist/components/CostInsightsPage/CostInsightsThemeProvider.esm.js.map +1 -1
- package/dist/components/CostInsightsTabs/CostInsightsTabs.esm.js +58 -51
- package/dist/components/CostInsightsTabs/CostInsightsTabs.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewBreakdownChart.esm.js +74 -59
- package/dist/components/CostOverviewCard/CostOverviewBreakdownChart.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewCard.esm.js +45 -35
- package/dist/components/CostOverviewCard/CostOverviewCard.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewChart.esm.js +86 -73
- package/dist/components/CostOverviewCard/CostOverviewChart.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewHeader.esm.js +11 -6
- package/dist/components/CostOverviewCard/CostOverviewHeader.esm.js.map +1 -1
- package/dist/components/CostOverviewCard/CostOverviewLegend.esm.js +21 -15
- package/dist/components/CostOverviewCard/CostOverviewLegend.esm.js.map +1 -1
- package/dist/components/CurrencySelect/CurrencySelect.esm.js +24 -21
- package/dist/components/CurrencySelect/CurrencySelect.esm.js.map +1 -1
- package/dist/components/EntityCosts/EntityCosts.esm.js +8 -7
- package/dist/components/EntityCosts/EntityCosts.esm.js.map +1 -1
- package/dist/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.esm.js +65 -20
- package/dist/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.esm.js.map +1 -1
- package/dist/components/LegendItem/LegendItem.esm.js +34 -29
- package/dist/components/LegendItem/LegendItem.esm.js.map +1 -1
- package/dist/components/MetricSelect/MetricSelect.esm.js +19 -14
- package/dist/components/MetricSelect/MetricSelect.esm.js.map +1 -1
- package/dist/components/PeriodSelect/PeriodSelect.esm.js +15 -15
- package/dist/components/PeriodSelect/PeriodSelect.esm.js.map +1 -1
- package/dist/components/ProductInsights/ProductInsights.esm.js +12 -8
- package/dist/components/ProductInsights/ProductInsights.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductEntityDialog.esm.js +20 -15
- package/dist/components/ProductInsightsCard/ProductEntityDialog.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductEntityTable.esm.js +9 -9
- package/dist/components/ProductInsightsCard/ProductEntityTable.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductInsightsCard.esm.js +25 -15
- package/dist/components/ProductInsightsCard/ProductInsightsCard.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductInsightsCardList.esm.js +14 -14
- package/dist/components/ProductInsightsCard/ProductInsightsCardList.esm.js.map +1 -1
- package/dist/components/ProductInsightsCard/ProductInsightsChart.esm.js +43 -35
- package/dist/components/ProductInsightsCard/ProductInsightsChart.esm.js.map +1 -1
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.esm.js +5 -5
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertCard.esm.js.map +1 -1
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertChart.esm.js +5 -2
- package/dist/components/ProjectGrowthAlertCard/ProjectGrowthAlertChart.esm.js.map +1 -1
- package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js +55 -9
- package/dist/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.esm.js.map +1 -1
- package/dist/components/ProjectSelect/ProjectSelect.esm.js +15 -15
- package/dist/components/ProjectSelect/ProjectSelect.esm.js.map +1 -1
- package/dist/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.esm.js +12 -9
- package/dist/components/UnlabeledDataflowAlertCard/UnlabeledDataflowAlertCard.esm.js.map +1 -1
- package/dist/components/WhyCostsMatter/WhyCostsMatter.esm.js +40 -10
- package/dist/components/WhyCostsMatter/WhyCostsMatter.esm.js.map +1 -1
- package/dist/example/alerts/KubernetesMigrationAlert.esm.js +10 -3
- package/dist/example/alerts/KubernetesMigrationAlert.esm.js.map +1 -1
- package/dist/example/client.esm.js +1 -1
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.esm.js +20 -17
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationAlertCard.esm.js.map +1 -1
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.esm.js +3 -2
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChart.esm.js.map +1 -1
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.esm.js +14 -9
- package/dist/example/components/KubernetesMigrationAlertCard/KubernetesMigrationBarChartLegend.esm.js.map +1 -1
- package/dist/example/forms/KubernetesMigrationDismissForm.esm.js +21 -17
- package/dist/example/forms/KubernetesMigrationDismissForm.esm.js.map +1 -1
- package/dist/forms/AlertAcceptForm.esm.js +5 -4
- package/dist/forms/AlertAcceptForm.esm.js.map +1 -1
- package/dist/forms/AlertDismissForm.esm.js +47 -38
- package/dist/forms/AlertDismissForm.esm.js.map +1 -1
- package/dist/forms/AlertSnoozeForm.esm.js +20 -16
- package/dist/forms/AlertSnoozeForm.esm.js.map +1 -1
- package/dist/hooks/useConfig.esm.js +3 -2
- package/dist/hooks/useConfig.esm.js.map +1 -1
- package/dist/hooks/useCurrency.esm.js +6 -3
- package/dist/hooks/useCurrency.esm.js.map +1 -1
- package/dist/hooks/useFilters.esm.js +10 -7
- package/dist/hooks/useFilters.esm.js.map +1 -1
- package/dist/hooks/useGroups.esm.js +7 -4
- package/dist/hooks/useGroups.esm.js.map +1 -1
- package/dist/hooks/useLastCompleteBillingDate.esm.js +8 -7
- package/dist/hooks/useLastCompleteBillingDate.esm.js.map +1 -1
- package/dist/hooks/useLoading.esm.js +6 -2
- package/dist/hooks/useLoading.esm.js.map +1 -1
- package/dist/hooks/useScroll.esm.js +6 -3
- package/dist/hooks/useScroll.esm.js.map +1 -1
- package/dist/index.d.ts +17 -17
- package/dist/index.esm.js +2 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/testUtils/providers.esm.js +3 -3
- package/dist/testUtils/providers.esm.js.map +1 -1
- package/dist/utils/navigation.esm.js +10 -10
- package/dist/utils/navigation.esm.js.map +1 -1
- package/dist/utils/scroll.esm.js +3 -2
- package/dist/utils/scroll.esm.js.map +1 -1
- package/package.json +18 -11
|
@@ -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
|
|
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":";;;;;;;;;AA0Ca,MAAA,8BAAA,GAAiC,WAG5C,CAAC,EAAE,UAAU,aAAe,EAAA,KAAA,IAAS,GAAQ,KAAA;AAC7C,EAAA,MAAM,CAAC,QAAU,EAAA,WAAW,IAAI,QAAmB,CAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAEtE,EAAA,MAAM,eAAiC,CAAK,CAAA,KAAA;AAE1C,IAAA,CAAA,CAAE,cAAe,EAAA;AACjB,IAAS,QAAA,CAAA,EAAE,UAAoB,CAAA;AAAA,GACjC;AAEA,EAAM,MAAA,gBAAA,GAAmB,CACvB,CAAA,EACA,OACG,KAAA;AACH,IAAA,IAAI,OAAS,EAAA;AACX,MAAA,MAAM,OAAU,GAAA,UAAA;AAAA,QACd,MAAM,IAAK,CAAA,QAAA;AAAA,QACX,CAAK,CAAA,KAAA,CAAA,CAAE,EAAO,KAAA,CAAA,CAAE,MAAO,CAAA;AAAA,OACzB;AACA,MAAA,WAAA,CAAY,CAAgB,YAAA,KAAA,YAAA,CAAa,MAAO,CAAA,OAAO,CAAC,CAAA;AAAA,KACnD,MAAA;AACL,MAAA,WAAA;AAAA,QAAY,CAAA,YAAA,KACV,aAAa,MAAO,CAAA,CAAA,CAAA,KAAK,EAAE,EAAO,KAAA,CAAA,CAAE,OAAO,KAAK;AAAA,OAClD;AAAA;AACF,GACF;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAS,MAAQ,EAAA;AACnB,MAAA,aAAA,CAAc,KAAK,CAAA;AAAA,KACd,MAAA;AACL,MAAA,aAAA,CAAc,IAAI,CAAA;AAAA;AACpB,GACC,EAAA,CAAC,QAAU,EAAA,aAAa,CAAC,CAAA;AAE5B,EAAA;AAAA;AAAA,oBAEE,GAAA,CAAC,MAAK,EAAA,EAAA,GAAA,EAAU,QAAU,EAAA,YAAA,EACxB,+BAAC,WAAY,EAAA,EAAA,SAAA,EAAU,UAAW,EAAA,SAAA,EAAS,IACzC,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,cAAW,KAAM,EAAA,aAAA,EAChB,QAAC,kBAAA,GAAA,CAAA,GAAA,EAAA,EAAE,iEAAmD,CACxD,EAAA,CAAA;AAAA,sBACA,GAAA,CAAC,aACE,QAAM,EAAA,KAAA,CAAA,IAAA,CAAK,SAAS,GAAI,CAAA,CAAC,SAAS,KACjC,qBAAA,GAAA;AAAA,QAAC,gBAAA;AAAA,QAAA;AAAA,UAEC,OAAO,OAAQ,CAAA,EAAA;AAAA,UACf,OAAO,OAAQ,CAAA,EAAA;AAAA,UACf,OACE,kBAAA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,KAAM,EAAA,SAAA;AAAA,cACN,SAAS,QAAS,CAAA,IAAA,CAAK,OAAK,CAAE,CAAA,EAAA,KAAO,QAAQ,EAAE,CAAA;AAAA,cAC/C,QAAU,EAAA;AAAA;AAAA;AACZ,SAAA;AAAA,QARG,kBAAkB,KAAK,CAAA;AAAA,OAW/B,CACH,EAAA;AAAA,KAAA,EACF,CACF,EAAA;AAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef, useState } from 'react';
|
|
2
3
|
import Checkbox from '@material-ui/core/Checkbox';
|
|
3
4
|
import FormControl from '@material-ui/core/FormControl';
|
|
4
5
|
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
|
@@ -13,14 +14,14 @@ const AlertAcceptForm = forwardRef(({ onSubmit, disableSubmit }, ref) => {
|
|
|
13
14
|
setChecked(isChecked);
|
|
14
15
|
disableSubmit(!isChecked);
|
|
15
16
|
};
|
|
16
|
-
return /* @__PURE__ */
|
|
17
|
+
return /* @__PURE__ */ jsx("form", { ref, onSubmit: onFormSubmit, children: /* @__PURE__ */ jsx(FormControl, { component: "fieldset", fullWidth: true, children: /* @__PURE__ */ jsx(
|
|
17
18
|
FormControlLabel,
|
|
18
19
|
{
|
|
19
20
|
label: "My team can commit to making this change soon, or has already.",
|
|
20
21
|
value: checked,
|
|
21
|
-
control: /* @__PURE__ */
|
|
22
|
+
control: /* @__PURE__ */ jsx(Checkbox, { color: "primary", checked, onChange: onChecked })
|
|
22
23
|
}
|
|
23
|
-
)));
|
|
24
|
+
) }) });
|
|
24
25
|
});
|
|
25
26
|
|
|
26
27
|
export { AlertAcceptForm };
|
|
@@ -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
|
|
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,UAG7B,CAAA,CAAC,EAAE,QAAU,EAAA,aAAA,IAAiB,GAAQ,KAAA;AACtC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAE5C,EAAA,MAAM,eAAiC,CAAK,CAAA,KAAA;AAC1C,IAAA,CAAA,CAAE,cAAe,EAAA;AACjB,IAAA,QAAA,CAAS,IAAI,CAAA;AAAA,GACf;AAEA,EAAM,MAAA,SAAA,GAAY,CAAC,CAAA,EAAkC,SAAuB,KAAA;AAC1E,IAAA,UAAA,CAAW,SAAS,CAAA;AACpB,IAAA,aAAA,CAAc,CAAC,SAAS,CAAA;AAAA,GAC1B;AAEA,EACE,uBAAA,GAAA,CAAC,MAAK,EAAA,EAAA,GAAA,EAAU,QAAU,EAAA,YAAA,EACxB,8BAAC,WAAY,EAAA,EAAA,SAAA,EAAU,UAAW,EAAA,SAAA,EAAS,IACzC,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,KAAM,EAAA,gEAAA;AAAA,MACN,KAAO,EAAA,OAAA;AAAA,MACP,yBACG,GAAA,CAAA,QAAA,EAAA,EAAS,OAAM,SAAU,EAAA,OAAA,EAAkB,UAAU,SAAW,EAAA;AAAA;AAAA,KAGvE,CACF,EAAA,CAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef, useState, useEffect } from 'react';
|
|
2
3
|
import Box from '@material-ui/core/Box';
|
|
3
4
|
import Collapse from '@material-ui/core/Collapse';
|
|
4
5
|
import FormControl from '@material-ui/core/FormControl';
|
|
@@ -55,45 +56,53 @@ const AlertDismissForm = forwardRef(({ onSubmit, disableSubmit }, ref) => {
|
|
|
55
56
|
}
|
|
56
57
|
validateDismissForm();
|
|
57
58
|
}, [reason, other, disableSubmit]);
|
|
58
|
-
return /* @__PURE__ */
|
|
59
|
-
|
|
60
|
-
{
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
return /* @__PURE__ */ jsx("form", { ref, onSubmit: onFormSubmit, children: /* @__PURE__ */ jsxs(FormControl, { component: "fieldset", fullWidth: true, children: [
|
|
60
|
+
/* @__PURE__ */ jsx(Typography, { color: "textPrimary", children: /* @__PURE__ */ jsx("b", { children: "Reason for dismissing?" }) }),
|
|
61
|
+
/* @__PURE__ */ jsxs(Box, { mb: 1, children: [
|
|
62
|
+
/* @__PURE__ */ jsx(
|
|
63
|
+
RadioGroup,
|
|
64
|
+
{
|
|
65
|
+
name: "dismiss-alert-reasons",
|
|
66
|
+
value: reason,
|
|
67
|
+
onChange: onReasonChange,
|
|
68
|
+
children: AlertDismissOptions.map((option) => /* @__PURE__ */ jsx(
|
|
69
|
+
FormControlLabel,
|
|
70
|
+
{
|
|
71
|
+
label: option.label,
|
|
72
|
+
value: option.reason,
|
|
73
|
+
control: /* @__PURE__ */ jsx(Radio, { className: classes.radio })
|
|
74
|
+
},
|
|
75
|
+
`dismiss-alert-option-${option.reason}`
|
|
76
|
+
))
|
|
77
|
+
}
|
|
78
|
+
),
|
|
79
|
+
/* @__PURE__ */ jsx(Collapse, { in: reason === AlertDismissReason.Other, children: /* @__PURE__ */ jsx(Box, { ml: 4, children: /* @__PURE__ */ jsx(
|
|
80
|
+
TextField,
|
|
81
|
+
{
|
|
82
|
+
id: "dismiss-alert-option-other",
|
|
83
|
+
variant: "outlined",
|
|
84
|
+
multiline: true,
|
|
85
|
+
fullWidth: true,
|
|
86
|
+
rows: 4,
|
|
87
|
+
value: other ?? "",
|
|
88
|
+
onChange: onOtherChange
|
|
89
|
+
}
|
|
90
|
+
) }) })
|
|
91
|
+
] }),
|
|
92
|
+
/* @__PURE__ */ jsx(Typography, { gutterBottom: true, children: /* @__PURE__ */ jsx("b", { children: "Any other feedback you can provide?" }) }),
|
|
93
|
+
/* @__PURE__ */ jsx(
|
|
94
|
+
TextField,
|
|
67
95
|
{
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
96
|
+
id: "dismiss-alert-feedback",
|
|
97
|
+
variant: "outlined",
|
|
98
|
+
multiline: true,
|
|
99
|
+
rows: 4,
|
|
100
|
+
fullWidth: true,
|
|
101
|
+
value: feedback ?? "",
|
|
102
|
+
onChange: onFeedbackChange
|
|
72
103
|
}
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
TextField,
|
|
76
|
-
{
|
|
77
|
-
id: "dismiss-alert-option-other",
|
|
78
|
-
variant: "outlined",
|
|
79
|
-
multiline: true,
|
|
80
|
-
fullWidth: true,
|
|
81
|
-
rows: 4,
|
|
82
|
-
value: other ?? "",
|
|
83
|
-
onChange: onOtherChange
|
|
84
|
-
}
|
|
85
|
-
)))), /* @__PURE__ */ React.createElement(Typography, { gutterBottom: true }, /* @__PURE__ */ React.createElement("b", null, "Any other feedback you can provide?")), /* @__PURE__ */ React.createElement(
|
|
86
|
-
TextField,
|
|
87
|
-
{
|
|
88
|
-
id: "dismiss-alert-feedback",
|
|
89
|
-
variant: "outlined",
|
|
90
|
-
multiline: true,
|
|
91
|
-
rows: 4,
|
|
92
|
-
fullWidth: true,
|
|
93
|
-
value: feedback ?? "",
|
|
94
|
-
onChange: onFeedbackChange
|
|
95
|
-
}
|
|
96
|
-
)));
|
|
104
|
+
)
|
|
105
|
+
] }) });
|
|
97
106
|
});
|
|
98
107
|
|
|
99
108
|
export { AlertDismissForm };
|
|
@@ -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
|
|
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,UAG9B,CAAA,CAAC,EAAE,QAAU,EAAA,aAAA,IAAiB,GAAQ,KAAA;AACtC,EAAA,MAAM,UAAUA,oBAAU,EAAA;AAC1B,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AACtD,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAwB,IAAI,CAAA;AAC5D,EAAM,MAAA,CAAC,MAAQ,EAAA,SAAS,CAAI,GAAA,QAAA;AAAA,IAC1B,kBAAmB,CAAA;AAAA,GACrB;AAEA,EAAA,MAAM,eAAiC,CAAK,CAAA,KAAA;AAC1C,IAAA,CAAA,CAAE,cAAe,EAAA;AACjB,IAAA,IAAI,MAAQ,EAAA;AACV,MAAS,QAAA,CAAA;AAAA,QACP,KAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA;AACH,GACF;AAEA,EAAM,MAAA,cAAA,GAAiB,CAAC,CAAA,EAAkC,KAAkB,KAAA;AAC1E,IAAA,IAAI,KAAO,EAAA;AACT,MAAA,QAAA,CAAS,IAAI,CAAA;AAAA;AAEf,IAAA,SAAA,CAAU,KAA2B,CAAA;AAAA,GACvC;AAEA,EAAM,MAAA,aAAA,GAAgB,CAAC,CAAqC,KAAA;AAC1D,IAAO,OAAA,CAAA,CAAE,OAAO,KACZ,GAAA,QAAA,CAAS,EAAE,MAAO,CAAA,KAA2B,CAC7C,GAAA,QAAA,CAAS,IAAI,CAAA;AAAA,GACnB;AAEA,EAAM,MAAA,gBAAA,GAAmB,CAAC,CAAqC,KAAA;AAC7D,IAAO,OAAA,CAAA,CAAE,OAAO,KACZ,GAAA,WAAA,CAAY,EAAE,MAAO,CAAA,KAA2B,CAChD,GAAA,WAAA,CAAY,IAAI,CAAA;AAAA,GACtB;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,SAAS,mBAAsB,GAAA;AAC7B,MAAI,IAAA,MAAA,KAAW,mBAAmB,KAAO,EAAA;AACvC,QAAA,IAAI,KAAO,EAAA;AACT,UAAA,aAAA,CAAc,KAAK,CAAA;AAAA,SACd,MAAA;AACL,UAAA,aAAA,CAAc,IAAI,CAAA;AAAA;AACpB,iBACS,MAAQ,EAAA;AACjB,QAAA,aAAA,CAAc,KAAK,CAAA;AAAA,OACd,MAAA;AACL,QAAA,aAAA,CAAc,IAAI,CAAA;AAAA;AACpB;AAGF,IAAoB,mBAAA,EAAA;AAAA,GACnB,EAAA,CAAC,MAAQ,EAAA,KAAA,EAAO,aAAa,CAAC,CAAA;AAEjC,EACE,uBAAA,GAAA,CAAC,MAAK,EAAA,EAAA,GAAA,EAAU,QAAU,EAAA,YAAA,EACxB,+BAAC,WAAY,EAAA,EAAA,SAAA,EAAU,UAAW,EAAA,SAAA,EAAS,IACzC,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,cAAW,KAAM,EAAA,aAAA,EAChB,QAAC,kBAAA,GAAA,CAAA,GAAA,EAAA,EAAE,oCAAsB,CAC3B,EAAA,CAAA;AAAA,oBACA,IAAA,CAAC,GAAI,EAAA,EAAA,EAAA,EAAI,CACP,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,IAAK,EAAA,uBAAA;AAAA,UACL,KAAO,EAAA,MAAA;AAAA,UACP,QAAU,EAAA,cAAA;AAAA,UAET,QAAA,EAAA,mBAAA,CAAoB,IAAI,CACvB,MAAA,qBAAA,GAAA;AAAA,YAAC,gBAAA;AAAA,YAAA;AAAA,cAEC,OAAO,MAAO,CAAA,KAAA;AAAA,cACd,OAAO,MAAO,CAAA,MAAA;AAAA,cACd,OAAS,kBAAA,GAAA,CAAC,KAAM,EAAA,EAAA,SAAA,EAAW,QAAQ,KAAO,EAAA;AAAA,aAAA;AAAA,YAHrC,CAAA,qBAAA,EAAwB,OAAO,MAAM,CAAA;AAAA,WAK7C;AAAA;AAAA,OACH;AAAA,sBACA,GAAA,CAAC,YAAS,EAAI,EAAA,MAAA,KAAW,mBAAmB,KAC1C,EAAA,QAAA,kBAAA,GAAA,CAAC,GAAI,EAAA,EAAA,EAAA,EAAI,CACP,EAAA,QAAA,kBAAA,GAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACC,EAAG,EAAA,4BAAA;AAAA,UACH,OAAQ,EAAA,UAAA;AAAA,UACR,SAAS,EAAA,IAAA;AAAA,UACT,SAAS,EAAA,IAAA;AAAA,UACT,IAAM,EAAA,CAAA;AAAA,UACN,OAAO,KAAS,IAAA,EAAA;AAAA,UAChB,QAAU,EAAA;AAAA;AAAA,SAEd,CACF,EAAA;AAAA,KACF,EAAA,CAAA;AAAA,wBACC,UAAW,EAAA,EAAA,YAAA,EAAY,MACtB,QAAC,kBAAA,GAAA,CAAA,GAAA,EAAA,EAAE,iDAAmC,CACxC,EAAA,CAAA;AAAA,oBACA,GAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,EAAG,EAAA,wBAAA;AAAA,QACH,OAAQ,EAAA,UAAA;AAAA,QACR,SAAS,EAAA,IAAA;AAAA,QACT,IAAM,EAAA,CAAA;AAAA,QACN,SAAS,EAAA,IAAA;AAAA,QACT,OAAO,QAAY,IAAA,EAAA;AAAA,QACnB,QAAU,EAAA;AAAA;AAAA;AACZ,GAAA,EACF,CACF,EAAA,CAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef, useState, useEffect } from 'react';
|
|
2
3
|
import { DateTime } from 'luxon';
|
|
3
4
|
import Box from '@material-ui/core/Box';
|
|
4
5
|
import FormControl from '@material-ui/core/FormControl';
|
|
@@ -29,23 +30,26 @@ const AlertSnoozeForm = forwardRef(({ onSubmit, disableSubmit }, ref) => {
|
|
|
29
30
|
const onSnoozeDurationChange = (_, value) => {
|
|
30
31
|
setDuration(value);
|
|
31
32
|
};
|
|
32
|
-
return /* @__PURE__ */
|
|
33
|
-
|
|
34
|
-
{
|
|
35
|
-
|
|
36
|
-
value: duration,
|
|
37
|
-
onChange: onSnoozeDurationChange
|
|
38
|
-
},
|
|
39
|
-
AlertSnoozeOptions.map((option) => /* @__PURE__ */ React.createElement(
|
|
40
|
-
FormControlLabel,
|
|
33
|
+
return /* @__PURE__ */ jsx("form", { ref, onSubmit: onFormSubmit, children: /* @__PURE__ */ jsxs(FormControl, { component: "fieldset", fullWidth: true, children: [
|
|
34
|
+
/* @__PURE__ */ jsx(Typography, { color: "textPrimary", children: /* @__PURE__ */ jsx("b", { children: "For how long?" }) }),
|
|
35
|
+
/* @__PURE__ */ jsx(Box, { mb: 1, children: /* @__PURE__ */ jsx(
|
|
36
|
+
RadioGroup,
|
|
41
37
|
{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
name: "snooze-alert-options",
|
|
39
|
+
value: duration,
|
|
40
|
+
onChange: onSnoozeDurationChange,
|
|
41
|
+
children: AlertSnoozeOptions.map((option) => /* @__PURE__ */ jsx(
|
|
42
|
+
FormControlLabel,
|
|
43
|
+
{
|
|
44
|
+
label: option.label,
|
|
45
|
+
value: option.duration,
|
|
46
|
+
control: /* @__PURE__ */ jsx(Radio, { className: classes.radio })
|
|
47
|
+
},
|
|
48
|
+
`snooze-alert-option-${option.duration}`
|
|
49
|
+
))
|
|
46
50
|
}
|
|
47
|
-
))
|
|
48
|
-
))
|
|
51
|
+
) })
|
|
52
|
+
] }) });
|
|
49
53
|
});
|
|
50
54
|
|
|
51
55
|
export { AlertSnoozeForm };
|
|
@@ -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
|
|
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,UAG7B,CAAA,CAAC,EAAE,QAAU,EAAA,aAAA,IAAiB,GAAQ,KAAA;AACtC,EAAA,MAAM,UAAUA,oBAAU,EAAA;AAC1B,EAAA,MAAM,CAAC,QAAU,EAAA,WAAW,CAAI,GAAA,QAAA,CAA0B,SAAS,GAAG,CAAA;AAEtE,EAAA,SAAA,CAAU,MAAM,aAAc,CAAA,KAAK,CAAG,EAAA,CAAC,aAAa,CAAC,CAAA;AAErD,EAAA,MAAM,eAAiC,CAAK,CAAA,KAAA;AAC1C,IAAA,CAAA,CAAE,cAAe,EAAA;AACjB,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,MAAM,cAAiB,GAAA,CAAA;AACvB,MAAA,MAAM,KAAQ,GAAA,QAAA,CAAS,GAAI,EAAA,CAAE,SAAS,mBAAmB,CAAA;AACzD,MAAS,QAAA,CAAA;AAAA,QACP,SAAW,EAAA,WAAA,CAAY,QAAU,EAAA,KAAA,EAAO,cAAc;AAAA,OACvD,CAAA;AAAA;AACH,GACF;AAEA,EAAM,MAAA,sBAAA,GAAyB,CAC7B,CAAA,EACA,KACG,KAAA;AACH,IAAA,WAAA,CAAY,KAAiB,CAAA;AAAA,GAC/B;AAEA,EACE,uBAAA,GAAA,CAAC,MAAK,EAAA,EAAA,GAAA,EAAU,QAAU,EAAA,YAAA,EACxB,+BAAC,WAAY,EAAA,EAAA,SAAA,EAAU,UAAW,EAAA,SAAA,EAAS,IACzC,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,cAAW,KAAM,EAAA,aAAA,EAChB,QAAC,kBAAA,GAAA,CAAA,GAAA,EAAA,EAAE,2BAAa,CAClB,EAAA,CAAA;AAAA,oBACA,GAAA,CAAC,GAAI,EAAA,EAAA,EAAA,EAAI,CACP,EAAA,QAAA,kBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,IAAK,EAAA,sBAAA;AAAA,QACL,KAAO,EAAA,QAAA;AAAA,QACP,QAAU,EAAA,sBAAA;AAAA,QAET,QAAA,EAAA,kBAAA,CAAmB,IAAI,CACtB,MAAA,qBAAA,GAAA;AAAA,UAAC,gBAAA;AAAA,UAAA;AAAA,YAEC,OAAO,MAAO,CAAA,KAAA;AAAA,YACd,OAAO,MAAO,CAAA,QAAA;AAAA,YACd,OAAS,kBAAA,GAAA,CAAC,KAAM,EAAA,EAAA,SAAA,EAAW,QAAQ,KAAO,EAAA;AAAA,WAAA;AAAA,UAHrC,CAAA,oBAAA,EAAuB,OAAO,QAAQ,CAAA;AAAA,SAK9C;AAAA;AAAA,KAEL,EAAA;AAAA,GAAA,EACF,CACF,EAAA,CAAA;AAEJ,CAAC;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useState, useEffect, useContext } from 'react';
|
|
2
3
|
import '../types/Alert.esm.js';
|
|
3
4
|
import { EngineerThreshold } from '../types/ChangeStatistic.esm.js';
|
|
4
5
|
import { getIcon } from '../utils/navigation.esm.js';
|
|
@@ -139,7 +140,7 @@ const ConfigProvider = ({ children }) => {
|
|
|
139
140
|
if (loading) {
|
|
140
141
|
return null;
|
|
141
142
|
}
|
|
142
|
-
return /* @__PURE__ */
|
|
143
|
+
return /* @__PURE__ */ jsx(ConfigContext.Provider, { value: config, children });
|
|
143
144
|
};
|
|
144
145
|
function useConfig() {
|
|
145
146
|
const config = useContext(ConfigContext);
|
|
@@ -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 React, {\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 }\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,7 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useState, useContext } from 'react';
|
|
2
3
|
import { useConfig } from './useConfig.esm.js';
|
|
3
4
|
|
|
4
|
-
const CurrencyContext =
|
|
5
|
+
const CurrencyContext = createContext(
|
|
6
|
+
void 0
|
|
7
|
+
);
|
|
5
8
|
const CurrencyProvider = ({ children }) => {
|
|
6
9
|
const config = useConfig();
|
|
7
10
|
const currencies = config.currencies;
|
|
@@ -9,7 +12,7 @@ const CurrencyProvider = ({ children }) => {
|
|
|
9
12
|
const [currency, setCurrency] = useState(
|
|
10
13
|
engineers || currencies[0]
|
|
11
14
|
);
|
|
12
|
-
return /* @__PURE__ */
|
|
15
|
+
return /* @__PURE__ */ jsx(CurrencyContext.Provider, { value: { currency, setCurrency }, children });
|
|
13
16
|
};
|
|
14
17
|
function useCurrency() {
|
|
15
18
|
const context = useContext(CurrencyContext);
|
|
@@ -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
|
|
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,eAAkB,GAAA,aAAA;AAAA,EAC7B,KAAA;AACF;AAEO,MAAM,gBAAmB,GAAA,CAAC,EAAE,QAAA,EAAsC,KAAA;AACvE,EAAA,MAAM,SAAS,SAAU,EAAA;AACzB,EAAA,MAAM,aAAa,MAAO,CAAA,UAAA;AAC1B,EAAA,MAAM,YAAY,UAAW,CAAA,IAAA,CAAK,CAAAA,SAAYA,KAAAA,SAAAA,CAAS,SAAS,IAAI,CAAA;AACpE,EAAM,MAAA,CAAC,QAAU,EAAA,WAAW,CAAI,GAAA,QAAA;AAAA,IAC9B,SAAA,IAAa,WAAW,CAAC;AAAA,GAC3B;AACA,EACE,uBAAA,GAAA,CAAC,gBAAgB,QAAhB,EAAA,EAAyB,OAAO,EAAE,QAAA,EAAU,WAAY,EAAA,EACtD,QACH,EAAA,CAAA;AAEJ;AAEO,SAAS,WAA8D,GAAA;AAC5E,EAAM,MAAA,OAAA,GAAU,WAAW,eAAe,CAAA;AAE1C,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAY,WAAA,EAAA;AAAA;AAGd,EAAA,OAAO,CAAC,OAAA,CAAQ,QAAU,EAAA,OAAA,CAAQ,WAAW,CAAA;AAC/C;AAEA,SAAS,WAAqB,GAAA;AAC5B,EAAA,MAAM,MAAM,oDAAoD,CAAA;AAClE;;;;"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useState, useEffect, useContext } from 'react';
|
|
2
3
|
import Alert from '@material-ui/lab/Alert';
|
|
3
4
|
import { useNavigate, useLocation } from 'react-router-dom';
|
|
4
5
|
import { validate, getInitialPageState, getInitialProductState, stringify } from '../utils/history.esm.js';
|
|
5
6
|
import { useGroups } from './useGroups.esm.js';
|
|
6
7
|
import { useConfig } from './useConfig.esm.js';
|
|
7
8
|
|
|
8
|
-
const FilterContext =
|
|
9
|
+
const FilterContext = createContext(
|
|
10
|
+
void 0
|
|
11
|
+
);
|
|
9
12
|
const FilterProvider = ({ children }) => {
|
|
10
13
|
const config = useConfig();
|
|
11
14
|
const navigate = useNavigate();
|
|
@@ -42,17 +45,17 @@ const FilterProvider = ({ children }) => {
|
|
|
42
45
|
}
|
|
43
46
|
}, [pageFilters]);
|
|
44
47
|
if (error) {
|
|
45
|
-
return /* @__PURE__ */
|
|
48
|
+
return /* @__PURE__ */ jsx(Alert, { severity: "error", children: error.message });
|
|
46
49
|
}
|
|
47
50
|
if (!pageFilters || !productFilters) {
|
|
48
51
|
return null;
|
|
49
52
|
}
|
|
50
|
-
return /* @__PURE__ */
|
|
53
|
+
return /* @__PURE__ */ jsx(
|
|
51
54
|
FilterContext.Provider,
|
|
52
55
|
{
|
|
53
|
-
value: { pageFilters, productFilters, setPageFilters, setProductFilters }
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
value: { pageFilters, productFilters, setPageFilters, setProductFilters },
|
|
57
|
+
children
|
|
58
|
+
}
|
|
56
59
|
);
|
|
57
60
|
};
|
|
58
61
|
function useFilters(mapFiltersToProps) {
|
|
@@ -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
|
|
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,aAAgB,GAAA,aAAA;AAAA,EAC3B,KAAA;AACF;AAEO,MAAM,cAAiB,GAAA,CAAC,EAAE,QAAA,EAAsC,KAAA;AACrE,EAAA,MAAM,SAAS,SAAU,EAAA;AACzB,EAAA,MAAM,WAAW,WAAY,EAAA;AAC7B,EAAA,MAAM,WAAW,WAAY,EAAA;AAC7B,EAAA,MAAM,SAAS,SAAU,EAAA;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,0BAA6B,GAAA;AAC1C,MAAI,IAAA;AAEF,QAAA,MAAM,WAAc,GAAA,MAAM,QAAS,CAAA,QAAA,CAAS,MAAM,CAAA;AAClD,QAAM,MAAA,aAAA,GAAgB,OAAO,OAAQ,CAAA,IAAA,CAAK,OAAK,CAAE,CAAA,OAAO,GAAG,IAAQ,IAAA,IAAA;AAGnE,QAAM,MAAA,gBAAA,GAAmB,mBAAoB,CAAA,MAAA,EAAQ,WAAW,CAAA;AAChE,QAAM,MAAA,mBAAA,GAAsB,uBAAuB,MAAM,CAAA;AAEzD,QAAA,iBAAA,CAAkB,mBAAmB,CAAA;AACrC,QAAA,cAAA,CAAe,EAAE,GAAG,gBAAkB,EAAA,MAAA,EAAQ,eAAe,CAAA;AAAA,eACtD,CAAG,EAAA;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AAAA;AACZ;AAGF,IAA2B,0BAAA,EAAA;AAAA,GAC7B,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,SAAS,2BAA2B,OAAsB,EAAA;AACxD,MAAA,MAAM,cAAc,SAAU,CAAA;AAAA,QAC5B,OAAO,OAAQ,CAAA,KAAA;AAAA,QACf,GAAI,QAAQ,OAAU,GAAA,EAAE,SAAS,OAAQ,CAAA,OAAA,KAAY;AAAC,OACvD,CAAA;AAID,MAAA,QAAA,CAAS,EAAE,GAAG,QAAA,EAAU,QAAQ,CAAI,CAAA,EAAA,WAAW,IAAI,CAAA;AAAA;AAGrD,IAAA,IAAI,WAAa,EAAA;AACf,MAAA,0BAAA,CAA2B,WAAW,CAAA;AAAA;AACxC,GACF,EAAG,CAAC,WAAW,CAAC,CAAA;AAEhB,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,uBAAQ,GAAA,CAAA,KAAA,EAAA,EAAM,QAAS,EAAA,OAAA,EAAS,gBAAM,OAAQ,EAAA,CAAA;AAAA;AAIhD,EAAI,IAAA,CAAC,WAAe,IAAA,CAAC,cAAgB,EAAA;AACnC,IAAO,OAAA,IAAA;AAAA;AAGT,EACE,uBAAA,GAAA;AAAA,IAAC,aAAc,CAAA,QAAA;AAAA,IAAd;AAAA,MACC,KAAO,EAAA,EAAE,WAAa,EAAA,cAAA,EAAgB,gBAAgB,iBAAkB,EAAA;AAAA,MAEvE;AAAA;AAAA,GACH;AAEJ;AAEO,SAAS,WAAc,iBAA4C,EAAA;AACxE,EAAM,MAAA,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAA,OAAO,OAAU,GAAA,iBAAA,CAAkB,OAAO,CAAA,GAAI,WAAY,EAAA;AAC5D;AAEA,SAAS,WAAqB,GAAA;AAC5B,EAAA,MAAM,MAAM,iDAAiD,CAAA;AAC/D;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useState, useEffect, useContext } from 'react';
|
|
2
3
|
import Alert from '@material-ui/lab/Alert';
|
|
3
4
|
import { costInsightsApiRef } from '../api/CostInsightsApi.esm.js';
|
|
4
5
|
import { useLoading } from './useLoading.esm.js';
|
|
@@ -11,7 +12,9 @@ const mapLoadingToProps = ({
|
|
|
11
12
|
}) => ({
|
|
12
13
|
dispatchLoadingGroups: (isLoading) => dispatch({ [DefaultLoadingAction.UserGroups]: isLoading })
|
|
13
14
|
});
|
|
14
|
-
const GroupsContext =
|
|
15
|
+
const GroupsContext = createContext(
|
|
16
|
+
void 0
|
|
17
|
+
);
|
|
15
18
|
const GroupsProvider = ({ children }) => {
|
|
16
19
|
const identityApi = useApi(identityApiRef);
|
|
17
20
|
const client = useApi(costInsightsApiRef);
|
|
@@ -38,10 +41,10 @@ const GroupsProvider = ({ children }) => {
|
|
|
38
41
|
getUserGroups();
|
|
39
42
|
}, [client]);
|
|
40
43
|
if (error) {
|
|
41
|
-
return /* @__PURE__ */
|
|
44
|
+
return /* @__PURE__ */ jsx(Alert, { severity: "error", children: error.message });
|
|
42
45
|
}
|
|
43
46
|
if (!groups) return null;
|
|
44
|
-
return /* @__PURE__ */
|
|
47
|
+
return /* @__PURE__ */ jsx(GroupsContext.Provider, { value: { groups }, children });
|
|
45
48
|
};
|
|
46
49
|
function useGroups() {
|
|
47
50
|
const context = useContext(GroupsContext);
|
|
@@ -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
|
|
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,CAAO,MAAA;AAAA,EACL,qBAAA,EAAuB,CAAC,SAAA,KACtB,QAAS,CAAA,EAAE,CAAC,oBAAqB,CAAA,UAAU,GAAG,SAAA,EAAW;AAC7D,CAAA,CAAA;AAMO,MAAM,aAAgB,GAAA,aAAA;AAAA,EAC3B,KAAA;AACF;AAEO,MAAM,cAAiB,GAAA,CAAC,EAAE,QAAA,EAAsC,KAAA;AACrE,EAAM,MAAA,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAM,MAAA,MAAA,GAAS,OAAO,kBAAkB,CAAA;AACxC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,EAAE,qBAAA,EAA0B,GAAA,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,aAAgB,GAAA;AAC7B,MAAI,IAAA;AACF,QAAA,MAAM,EAAE,aAAA,EAAkB,GAAA,MAAM,YAAY,oBAAqB,EAAA;AACjE,QAAA,MAAM,EAAE,IAAA,EAAM,MAAO,EAAA,GAAI,eAAe,aAAe,EAAA;AAAA,UACrD,WAAa,EAAA,MAAA;AAAA,UACb,gBAAkB,EAAA;AAAA,SACnB,CAAA;AACD,QAAA,MAAM,CAAI,GAAA,MAAM,MAAO,CAAA,aAAA,CAAc,MAAM,CAAA;AAC3C,QAAA,SAAA,CAAU,CAAC,CAAA;AAAA,eACJ,CAAG,EAAA;AACV,QAAA,QAAA,CAAS,CAAC,CAAA;AAAA,OACV,SAAA;AACA,QAAA,qBAAA,CAAsB,KAAK,CAAA;AAAA;AAC7B;AAGF,IAAc,aAAA,EAAA;AAAA,GAChB,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,uBAAQ,GAAA,CAAA,KAAA,EAAA,EAAM,QAAS,EAAA,OAAA,EAAS,gBAAM,OAAQ,EAAA,CAAA;AAAA;AAGhD,EAAI,IAAA,CAAC,QAAe,OAAA,IAAA;AAEpB,EACE,uBAAA,GAAA,CAAC,cAAc,QAAd,EAAA,EAAuB,OAAO,EAAE,MAAA,IAC9B,QACH,EAAA,CAAA;AAEJ;AAEO,SAAS,SAAqB,GAAA;AACnC,EAAM,MAAA,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAO,OAAA,OAAA,GAAU,OAAQ,CAAA,MAAA,GAAS,WAAY,EAAA;AAChD;AAEA,SAAS,WAAqB,GAAA;AAC5B,EAAA,MAAM,MAAM,gDAAgD,CAAA;AAC9D;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useState, useEffect, useContext } from 'react';
|
|
2
3
|
import * as yup from 'yup';
|
|
3
4
|
import Alert from '@material-ui/lab/Alert';
|
|
4
5
|
import { costInsightsApiRef } from '../api/CostInsightsApi.esm.js';
|
|
@@ -11,7 +12,7 @@ const mapLoadingToProps = ({
|
|
|
11
12
|
}) => ({
|
|
12
13
|
dispatchLoadingBillingDate: (isLoading) => dispatch({ [DefaultLoadingAction.LastCompleteBillingDate]: isLoading })
|
|
13
14
|
});
|
|
14
|
-
const BillingDateContext =
|
|
15
|
+
const BillingDateContext = createContext(void 0);
|
|
15
16
|
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
|
|
16
17
|
const dateFormatSchema = yup.string().matches(dateRegex, {
|
|
17
18
|
message: "Unsupported billing date format: ${value}. Date should be in YYYY-MM-DD format.",
|
|
@@ -38,17 +39,17 @@ const BillingDateProvider = ({ children }) => {
|
|
|
38
39
|
getLastCompleteBillingDate();
|
|
39
40
|
}, [client]);
|
|
40
41
|
if (error) {
|
|
41
|
-
return /* @__PURE__ */
|
|
42
|
+
return /* @__PURE__ */ jsx(Alert, { severity: "error", children: error.message });
|
|
42
43
|
}
|
|
43
44
|
if (!lastCompleteBillingDate) return null;
|
|
44
|
-
return /* @__PURE__ */
|
|
45
|
+
return /* @__PURE__ */ jsx(
|
|
45
46
|
BillingDateContext.Provider,
|
|
46
47
|
{
|
|
47
48
|
value: {
|
|
48
49
|
lastCompleteBillingDate
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
},
|
|
51
|
+
children
|
|
52
|
+
}
|
|
52
53
|
);
|
|
53
54
|
};
|
|
54
55
|
function useLastCompleteBillingDate() {
|