@electrolux-oss/plugin-infrawallet 0.1.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.
Files changed (27) hide show
  1. package/README.md +258 -0
  2. package/dist/api/InfraWalletApi.esm.js +8 -0
  3. package/dist/api/InfraWalletApi.esm.js.map +1 -0
  4. package/dist/api/InfraWalletApiClient.esm.js +89 -0
  5. package/dist/api/InfraWalletApiClient.esm.js.map +1 -0
  6. package/dist/api/functions.esm.js +100 -0
  7. package/dist/api/functions.esm.js.map +1 -0
  8. package/dist/components/ColumnsChartComponent/ColumnsChartComponent.esm.js +168 -0
  9. package/dist/components/ColumnsChartComponent/ColumnsChartComponent.esm.js.map +1 -0
  10. package/dist/components/CostReportsTableComponent/CostReportsTableComponent.esm.js +144 -0
  11. package/dist/components/CostReportsTableComponent/CostReportsTableComponent.esm.js.map +1 -0
  12. package/dist/components/CostReportsTableComponent/TrendBarComponent.esm.js +48 -0
  13. package/dist/components/CostReportsTableComponent/TrendBarComponent.esm.js.map +1 -0
  14. package/dist/components/PieChartComponent/PieChartComponent.esm.js +134 -0
  15. package/dist/components/PieChartComponent/PieChartComponent.esm.js.map +1 -0
  16. package/dist/components/ReportsComponent/ReportsComponent.esm.js +126 -0
  17. package/dist/components/ReportsComponent/ReportsComponent.esm.js.map +1 -0
  18. package/dist/components/TopbarComponent/TopbarComponent.esm.js +93 -0
  19. package/dist/components/TopbarComponent/TopbarComponent.esm.js.map +1 -0
  20. package/dist/index.d.ts +10 -0
  21. package/dist/index.esm.js +2 -0
  22. package/dist/index.esm.js.map +1 -0
  23. package/dist/plugin.esm.js +28 -0
  24. package/dist/plugin.esm.js.map +1 -0
  25. package/dist/routes.esm.js +12 -0
  26. package/dist/routes.esm.js.map +1 -0
  27. package/package.json +78 -0
@@ -0,0 +1,144 @@
1
+ import Typography from '@material-ui/core/Typography';
2
+ import { makeStyles } from '@material-ui/core/styles';
3
+ import Box from '@mui/material/Box';
4
+ import { DataGrid } from '@mui/x-data-grid';
5
+ import humanFormat from 'human-format';
6
+ import React from 'react';
7
+ import { getPreviousMonth } from '../../api/functions.esm.js';
8
+ import { TrendBarComponent } from './TrendBarComponent.esm.js';
9
+
10
+ const useStyles = makeStyles({
11
+ increase: {
12
+ color: "red"
13
+ },
14
+ decrease: {
15
+ color: "green"
16
+ }
17
+ });
18
+ const CostReportsTableComponent = ({
19
+ reports,
20
+ aggregatedBy
21
+ }) => {
22
+ const classes = useStyles();
23
+ const customScale = humanFormat.Scale.create(["", "K", "M", "B"], 1e3);
24
+ const periods = Object.keys(reports[0].reports);
25
+ const columns = [
26
+ {
27
+ field: aggregatedBy,
28
+ headerName: aggregatedBy.toLocaleUpperCase("en-US"),
29
+ minWidth: 200,
30
+ flex: 2,
31
+ renderCell: (params) => {
32
+ return /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, params.formattedValue);
33
+ }
34
+ },
35
+ {
36
+ field: "TREND",
37
+ headerName: "TREND",
38
+ width: 100,
39
+ renderCell: (params) => {
40
+ return /* @__PURE__ */ React.createElement(
41
+ TrendBarComponent,
42
+ {
43
+ categories: Object.keys(params.row.reports),
44
+ series: [
45
+ {
46
+ name: params.row.id,
47
+ data: periods.map(
48
+ (period) => params.row.reports[period] !== void 0 ? params.row.reports[period] : null
49
+ )
50
+ }
51
+ ]
52
+ }
53
+ );
54
+ }
55
+ }
56
+ ];
57
+ periods.forEach((period) => {
58
+ columns.push({
59
+ field: period,
60
+ headerName: period,
61
+ type: "number",
62
+ minWidth: 150,
63
+ flex: 1,
64
+ valueGetter: (_, row) => {
65
+ return row.reports[period] ? row.reports[period] : null;
66
+ },
67
+ valueFormatter: (value, row, column) => {
68
+ if (typeof value === "number") {
69
+ const previousPeriod = getPreviousMonth(column.field);
70
+ const formattedValue = humanFormat(value, {
71
+ scale: customScale,
72
+ separator: ""
73
+ });
74
+ if (previousPeriod in row.reports && row.reports[previousPeriod] > 0) {
75
+ const diff = row.reports[column.field] - row.reports[previousPeriod];
76
+ const percentage = diff / row.reports[previousPeriod] * 100;
77
+ const mark = diff > 0 ? "+" : "";
78
+ return `$${formattedValue} (${mark}${percentage.toFixed(2)}%)`;
79
+ }
80
+ return `$${formattedValue}`;
81
+ }
82
+ return "-";
83
+ },
84
+ renderCell: (params) => {
85
+ let className = "";
86
+ const percentageIndex = params.formattedValue.indexOf("(");
87
+ const costStr = percentageIndex === -1 ? params.formattedValue : params.formattedValue.substring(0, percentageIndex);
88
+ const percentageStr = percentageIndex === -1 ? "" : params.formattedValue.substring(percentageIndex);
89
+ if (percentageStr.includes("-")) {
90
+ className = classes.decrease;
91
+ } else if (percentageStr.includes("+")) {
92
+ className = classes.increase;
93
+ }
94
+ return /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, costStr, /* @__PURE__ */ React.createElement(Typography, { variant: "inherit", className }, percentageStr));
95
+ }
96
+ });
97
+ });
98
+ columns.push({
99
+ field: "TOTAL",
100
+ headerName: "TOTAL",
101
+ type: "number",
102
+ minWidth: 150,
103
+ flex: 1,
104
+ valueGetter: (_, row) => {
105
+ let total = 0;
106
+ periods.forEach((period) => {
107
+ total += row.reports[period] ? row.reports[period] : 0;
108
+ });
109
+ return total;
110
+ },
111
+ valueFormatter: (value) => {
112
+ if (typeof value === "number") {
113
+ return `$${humanFormat(value, { scale: customScale, separator: "" })}`;
114
+ }
115
+ return "-";
116
+ },
117
+ renderCell: (params) => {
118
+ return /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, params.formattedValue);
119
+ }
120
+ });
121
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(
122
+ DataGrid,
123
+ {
124
+ rows: reports,
125
+ rowHeight: 35,
126
+ columns,
127
+ initialState: {
128
+ sorting: {
129
+ sortModel: [{ field: "TOTAL", sort: "desc" }]
130
+ },
131
+ pagination: {
132
+ paginationModel: {
133
+ pageSize: 15
134
+ }
135
+ }
136
+ },
137
+ pageSizeOptions: [5, 15],
138
+ disableRowSelectionOnClick: true
139
+ }
140
+ ));
141
+ };
142
+
143
+ export { CostReportsTableComponent };
144
+ //# sourceMappingURL=CostReportsTableComponent.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CostReportsTableComponent.esm.js","sources":["../../../src/components/CostReportsTableComponent/CostReportsTableComponent.tsx"],"sourcesContent":["import Typography from '@material-ui/core/Typography';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Box from '@mui/material/Box';\nimport { DataGrid, GridColDef, GridRenderCellParams } from '@mui/x-data-grid';\nimport humanFormat from 'human-format';\nimport React, { FC } from 'react';\nimport { getPreviousMonth } from '../../api/functions';\nimport { CostReportsTableComponentProps } from '../types';\nimport { TrendBarComponent } from './TrendBarComponent';\n\nconst useStyles = makeStyles({\n increase: {\n color: 'red',\n },\n decrease: {\n color: 'green',\n },\n});\n\nexport const CostReportsTableComponent: FC<CostReportsTableComponentProps> = ({\n reports,\n aggregatedBy,\n}) => {\n const classes = useStyles();\n const customScale = humanFormat.Scale.create(['', 'K', 'M', 'B'], 1000);\n const periods = Object.keys(reports[0].reports);\n const columns: GridColDef[] = [\n {\n field: aggregatedBy,\n headerName: aggregatedBy.toLocaleUpperCase('en-US'),\n minWidth: 200,\n flex: 2,\n renderCell: (params: GridRenderCellParams): React.ReactNode => {\n return <Typography variant=\"body2\">{params.formattedValue}</Typography>;\n },\n },\n {\n field: 'TREND',\n headerName: 'TREND',\n width: 100,\n renderCell: (params: GridRenderCellParams): React.ReactNode => {\n return (\n <TrendBarComponent\n categories={Object.keys(params.row.reports)}\n series={[\n {\n name: params.row.id,\n data: periods.map(period =>\n params.row.reports[period] !== undefined\n ? params.row.reports[period]\n : null,\n ),\n },\n ]}\n />\n );\n },\n },\n ];\n\n periods.forEach(period => {\n columns.push({\n field: period,\n headerName: period,\n type: 'number',\n minWidth: 150,\n flex: 1,\n valueGetter: (_, row) => {\n return row.reports[period] ? row.reports[period] : null;\n },\n valueFormatter: (value, row, column) => {\n if (typeof value === 'number') {\n const previousPeriod = getPreviousMonth(column.field);\n const formattedValue = humanFormat(value, {\n scale: customScale,\n separator: '',\n });\n if (\n previousPeriod in row.reports &&\n row.reports[previousPeriod] > 0\n ) {\n const diff =\n row.reports[column.field] - row.reports[previousPeriod];\n const percentage = (diff / row.reports[previousPeriod]) * 100;\n const mark = diff > 0 ? '+' : '';\n return `$${formattedValue} (${mark}${percentage.toFixed(2)}%)`;\n }\n return `$${formattedValue}`;\n }\n return '-';\n },\n renderCell: (params: GridRenderCellParams): React.ReactNode => {\n let className = '';\n const percentageIndex = params.formattedValue.indexOf('(');\n const costStr =\n percentageIndex === -1\n ? params.formattedValue\n : params.formattedValue.substring(0, percentageIndex);\n const percentageStr =\n percentageIndex === -1\n ? ''\n : params.formattedValue.substring(percentageIndex);\n if (percentageStr.includes('-')) {\n className = classes.decrease;\n } else if (percentageStr.includes('+')) {\n className = classes.increase;\n }\n\n return (\n <Typography variant=\"body2\">\n {costStr}\n <Typography variant=\"inherit\" className={className}>\n {percentageStr}\n </Typography>\n </Typography>\n );\n },\n });\n });\n\n columns.push({\n field: 'TOTAL',\n headerName: 'TOTAL',\n type: 'number',\n minWidth: 150,\n flex: 1,\n valueGetter: (_, row) => {\n let total = 0;\n periods.forEach(period => {\n total += row.reports[period] ? row.reports[period] : 0;\n });\n return total;\n },\n valueFormatter: value => {\n if (typeof value === 'number') {\n return `$${humanFormat(value, { scale: customScale, separator: '' })}`;\n }\n return '-';\n },\n renderCell: (params: GridRenderCellParams): React.ReactNode => {\n return <Typography variant=\"body2\">{params.formattedValue}</Typography>;\n },\n });\n\n return (\n <Box>\n <DataGrid\n rows={reports}\n rowHeight={35}\n columns={columns}\n initialState={{\n sorting: {\n sortModel: [{ field: 'TOTAL', sort: 'desc' }],\n },\n pagination: {\n paginationModel: {\n pageSize: 15,\n },\n },\n }}\n pageSizeOptions={[5, 15]}\n disableRowSelectionOnClick\n />\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import { Box } from '@material-ui/core';
3
+ import { makeStyles } from '@material-ui/core/styles';
4
+ import Chart from 'react-apexcharts';
5
+
6
+ const TrendBarComponent = ({
7
+ categories,
8
+ series,
9
+ height,
10
+ width
11
+ }) => {
12
+ const useStyles = makeStyles({
13
+ fixedBox: {
14
+ display: "flex",
15
+ height: height ? height : 25,
16
+ width: width ? width : 100
17
+ }
18
+ });
19
+ const classes = useStyles();
20
+ const options = {
21
+ chart: {
22
+ width: width ? width : 100,
23
+ type: "bar",
24
+ animations: {
25
+ enabled: false
26
+ },
27
+ zoom: {
28
+ enabled: false
29
+ },
30
+ toolbar: {
31
+ show: false
32
+ },
33
+ sparkline: {
34
+ enabled: true
35
+ }
36
+ },
37
+ tooltip: {
38
+ enabled: false
39
+ },
40
+ xaxis: {
41
+ categories
42
+ }
43
+ };
44
+ return /* @__PURE__ */ React.createElement(Box, { className: classes.fixedBox }, /* @__PURE__ */ React.createElement(Chart, { options, series, type: "bar", height: "100%" }));
45
+ };
46
+
47
+ export { TrendBarComponent };
48
+ //# sourceMappingURL=TrendBarComponent.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TrendBarComponent.esm.js","sources":["../../../src/components/CostReportsTableComponent/TrendBarComponent.tsx"],"sourcesContent":["import React, { FC } from 'react';\nimport { Box } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { TrendBarComponentProps } from '../types';\nimport Chart from 'react-apexcharts';\nimport { ApexOptions } from 'apexcharts';\n\nexport const TrendBarComponent: FC<TrendBarComponentProps> = ({\n categories,\n series,\n height,\n width,\n}) => {\n const useStyles = makeStyles({\n fixedBox: {\n display: 'flex',\n height: height ? height : 25,\n width: width ? width : 100,\n },\n });\n const classes = useStyles();\n\n const options: ApexOptions = {\n chart: {\n width: width ? width : 100,\n type: 'bar',\n animations: {\n enabled: false,\n },\n zoom: {\n enabled: false,\n },\n toolbar: {\n show: false,\n },\n sparkline: {\n enabled: true,\n },\n },\n tooltip: {\n enabled: false,\n },\n xaxis: {\n categories: categories,\n },\n };\n\n return (\n <Box className={classes.fixedBox}>\n <Chart options={options} series={series} type=\"bar\" height=\"100%\" />\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;AAOO,MAAM,oBAAgD,CAAC;AAAA,EAC5D,UAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AACF,CAAM,KAAA;AACJ,EAAA,MAAM,YAAY,UAAW,CAAA;AAAA,IAC3B,QAAU,EAAA;AAAA,MACR,OAAS,EAAA,MAAA;AAAA,MACT,MAAA,EAAQ,SAAS,MAAS,GAAA,EAAA;AAAA,MAC1B,KAAA,EAAO,QAAQ,KAAQ,GAAA,GAAA;AAAA,KACzB;AAAA,GACD,CAAA,CAAA;AACD,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAE1B,EAAA,MAAM,OAAuB,GAAA;AAAA,IAC3B,KAAO,EAAA;AAAA,MACL,KAAA,EAAO,QAAQ,KAAQ,GAAA,GAAA;AAAA,MACvB,IAAM,EAAA,KAAA;AAAA,MACN,UAAY,EAAA;AAAA,QACV,OAAS,EAAA,KAAA;AAAA,OACX;AAAA,MACA,IAAM,EAAA;AAAA,QACJ,OAAS,EAAA,KAAA;AAAA,OACX;AAAA,MACA,OAAS,EAAA;AAAA,QACP,IAAM,EAAA,KAAA;AAAA,OACR;AAAA,MACA,SAAW,EAAA;AAAA,QACT,OAAS,EAAA,IAAA;AAAA,OACX;AAAA,KACF;AAAA,IACA,OAAS,EAAA;AAAA,MACP,OAAS,EAAA,KAAA;AAAA,KACX;AAAA,IACA,KAAO,EAAA;AAAA,MACL,UAAA;AAAA,KACF;AAAA,GACF,CAAA;AAEA,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,SAAW,EAAA,OAAA,CAAQ,QACtB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,KAAM,EAAA,EAAA,OAAA,EAAkB,MAAgB,EAAA,IAAA,EAAK,KAAM,EAAA,MAAA,EAAO,QAAO,CACpE,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,134 @@
1
+ import { Paper } from '@material-ui/core';
2
+ import { makeStyles } from '@material-ui/core/styles';
3
+ import humanFormat from 'human-format';
4
+ import React from 'react';
5
+ import Chart from 'react-apexcharts';
6
+
7
+ const PieChartComponent = ({
8
+ categories,
9
+ series,
10
+ height
11
+ }) => {
12
+ const useStyles = makeStyles({
13
+ fixedHeightPaper: {
14
+ paddingTop: "10px",
15
+ overflow: "hidden",
16
+ height: height ? height : 300
17
+ }
18
+ });
19
+ const classes = useStyles();
20
+ const customScale = humanFormat.Scale.create(["", "K", "M", "B"], 1e3);
21
+ const state = {
22
+ options: {
23
+ chart: {
24
+ animations: {
25
+ enabled: false
26
+ }
27
+ },
28
+ legend: {
29
+ show: false
30
+ },
31
+ labels: categories,
32
+ dataLabels: {
33
+ enabled: true,
34
+ formatter: (value, { seriesIndex, dataPointIndex, w }) => {
35
+ return `${w.config.labels[seriesIndex]} (${value.toFixed(0)}%)`;
36
+ }
37
+ },
38
+ tooltip: {
39
+ y: {
40
+ formatter: (value) => {
41
+ return `$${humanFormat(value, {
42
+ scale: customScale,
43
+ separator: ""
44
+ })}`;
45
+ }
46
+ }
47
+ },
48
+ plotOptions: {
49
+ pie: {
50
+ donut: {
51
+ labels: {
52
+ show: true,
53
+ value: {
54
+ formatter: (val) => {
55
+ const floatVal = parseFloat(val);
56
+ return `$${humanFormat(floatVal, {
57
+ scale: customScale,
58
+ separator: ""
59
+ })}`;
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
65
+ },
66
+ // there are only 5 colors by default, here we extend it to 50 different colors
67
+ colors: [
68
+ "#008FFB",
69
+ "#00E396",
70
+ "#FEB019",
71
+ "#FF4560",
72
+ "#775DD0",
73
+ "#3F51B5",
74
+ "#03A9F4",
75
+ "#4CAF50",
76
+ "#F9CE1D",
77
+ "#FF9800",
78
+ "#33B2DF",
79
+ "#546E7A",
80
+ "#D4526E",
81
+ "#13D8AA",
82
+ "#A5978B",
83
+ "#4ECDC4",
84
+ "#C7F464",
85
+ "#81D4FA",
86
+ "#546E7A",
87
+ "#FD6A6A",
88
+ "#2B908F",
89
+ "#F9A3A4",
90
+ "#90EE7E",
91
+ "#FA4443",
92
+ "#69D2E7",
93
+ "#449DD1",
94
+ "#F86624",
95
+ "#EA3546",
96
+ "#662E9B",
97
+ "#C5D86D",
98
+ "#D7263D",
99
+ "#1B998B",
100
+ "#2E294E",
101
+ "#F46036",
102
+ "#E2C044",
103
+ "#662E9B",
104
+ "#F86624",
105
+ "#F9C80E",
106
+ "#EA3546",
107
+ "#43BCCD",
108
+ "#5C4742",
109
+ "#A5978B",
110
+ "#8D5B4C",
111
+ "#5A2A27",
112
+ "#C4BBAF",
113
+ "#A300D6",
114
+ "#7D02EB",
115
+ "#5653FE",
116
+ "#2983FF",
117
+ "#00B1F2"
118
+ ]
119
+ },
120
+ series
121
+ };
122
+ return /* @__PURE__ */ React.createElement(Paper, { className: classes.fixedHeightPaper }, /* @__PURE__ */ React.createElement(
123
+ Chart,
124
+ {
125
+ options: state.options,
126
+ series: state.series,
127
+ type: "donut",
128
+ height: height ? height : 300
129
+ }
130
+ ));
131
+ };
132
+
133
+ export { PieChartComponent };
134
+ //# sourceMappingURL=PieChartComponent.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PieChartComponent.esm.js","sources":["../../../src/components/PieChartComponent/PieChartComponent.tsx"],"sourcesContent":["import { Paper } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport humanFormat from 'human-format';\nimport React, { FC } from 'react';\nimport Chart from 'react-apexcharts';\nimport { PieChartComponentProps } from '../types';\n\nexport const PieChartComponent: FC<PieChartComponentProps> = ({\n categories,\n series,\n height,\n}) => {\n const useStyles = makeStyles({\n fixedHeightPaper: {\n paddingTop: '10px',\n overflow: 'hidden',\n height: height ? height : 300,\n },\n });\n const classes = useStyles();\n const customScale = humanFormat.Scale.create(['', 'K', 'M', 'B'], 1000);\n\n const state = {\n options: {\n chart: {\n animations: {\n enabled: false,\n },\n },\n legend: {\n show: false,\n },\n labels: categories,\n dataLabels: {\n enabled: true,\n formatter: (value, { seriesIndex, dataPointIndex, w }) => {\n return `${w.config.labels[seriesIndex]} (${value.toFixed(0)}%)`;\n },\n },\n tooltip: {\n y: {\n formatter: (value: number) => {\n return `$${humanFormat(value, {\n scale: customScale,\n separator: '',\n })}`;\n },\n },\n },\n plotOptions: {\n pie: {\n donut: {\n labels: {\n show: true,\n value: {\n formatter: (val: string) => {\n const floatVal = parseFloat(val);\n return `$${humanFormat(floatVal, {\n scale: customScale,\n separator: '',\n })}`;\n },\n },\n },\n },\n },\n },\n // there are only 5 colors by default, here we extend it to 50 different colors\n colors: [\n '#008FFB',\n '#00E396',\n '#FEB019',\n '#FF4560',\n '#775DD0',\n '#3F51B5',\n '#03A9F4',\n '#4CAF50',\n '#F9CE1D',\n '#FF9800',\n '#33B2DF',\n '#546E7A',\n '#D4526E',\n '#13D8AA',\n '#A5978B',\n '#4ECDC4',\n '#C7F464',\n '#81D4FA',\n '#546E7A',\n '#FD6A6A',\n '#2B908F',\n '#F9A3A4',\n '#90EE7E',\n '#FA4443',\n '#69D2E7',\n '#449DD1',\n '#F86624',\n '#EA3546',\n '#662E9B',\n '#C5D86D',\n '#D7263D',\n '#1B998B',\n '#2E294E',\n '#F46036',\n '#E2C044',\n '#662E9B',\n '#F86624',\n '#F9C80E',\n '#EA3546',\n '#43BCCD',\n '#5C4742',\n '#A5978B',\n '#8D5B4C',\n '#5A2A27',\n '#C4BBAF',\n '#A300D6',\n '#7D02EB',\n '#5653FE',\n '#2983FF',\n '#00B1F2',\n ],\n },\n series: series,\n };\n\n return (\n <Paper className={classes.fixedHeightPaper}>\n <Chart\n options={state.options}\n series={state.series}\n type=\"donut\"\n height={height ? height : 300}\n />\n </Paper>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ import { Page, Header, Content, Progress } from '@backstage/core-components';
2
+ import { useApi, alertApiRef } from '@backstage/core-plugin-api';
3
+ import { Grid } from '@material-ui/core';
4
+ import { startOfMonth, addMonths, endOfMonth } from 'date-fns';
5
+ import React, { useState, useCallback, useEffect } from 'react';
6
+ import { infraWalletApiRef } from '../../api/InfraWalletApi.esm.js';
7
+ import { aggregateCostReports, mergeCostReports, getAllReportTags } from '../../api/functions.esm.js';
8
+ import { ColumnsChartComponent } from '../ColumnsChartComponent/ColumnsChartComponent.esm.js';
9
+ import { CostReportsTableComponent } from '../CostReportsTableComponent/CostReportsTableComponent.esm.js';
10
+ import { PieChartComponent } from '../PieChartComponent/PieChartComponent.esm.js';
11
+ import { TopbarComponent } from '../TopbarComponent/TopbarComponent.esm.js';
12
+
13
+ const getTotalCost = (report) => {
14
+ let total = 0;
15
+ Object.keys(report.reports).forEach((s) => {
16
+ total += report.reports[s];
17
+ });
18
+ return total;
19
+ };
20
+ const rearrangeData = (report, periods) => {
21
+ const costs = [];
22
+ periods.forEach((s) => {
23
+ if (report.reports[s] !== void 0) {
24
+ costs.push(report.reports[s]);
25
+ } else {
26
+ costs.push(null);
27
+ }
28
+ });
29
+ return costs;
30
+ };
31
+ const ReportsComponent = () => {
32
+ const MERGE_THRESHOLD = 8;
33
+ const [submittingState, setSubmittingState] = useState(false);
34
+ const [reports, setReports] = useState([]);
35
+ const [reportsAggregated, setReportsAggregated] = useState([]);
36
+ const [reportsAggregatedAndMerged, setReportsAggregatedAndMerged] = useState([]);
37
+ const [reportTags, setReportTags] = useState([]);
38
+ const [granularity, setGranularity] = useState("monthly");
39
+ const [aggregatedBy, setAggregatedBy] = useState("none");
40
+ const [filters, setFilters] = useState("");
41
+ const [groups, setGroups] = useState("");
42
+ const [monthRangeState, setMonthRangeState] = React.useState({
43
+ startMonth: startOfMonth(addMonths(/* @__PURE__ */ new Date(), -2)),
44
+ endMonth: endOfMonth(/* @__PURE__ */ new Date())
45
+ });
46
+ const alertApi = useApi(alertApiRef);
47
+ const infraWalletApi = useApi(infraWalletApiRef);
48
+ const fetchCostReportsCallback = useCallback(async () => {
49
+ setSubmittingState(true);
50
+ await infraWalletApi.getCostReports(
51
+ filters,
52
+ groups,
53
+ granularity,
54
+ monthRangeState.startMonth,
55
+ monthRangeState.endMonth
56
+ ).then((reportsResponse) => {
57
+ if (reportsResponse.data && reportsResponse.data.length > 0) {
58
+ setReports(reportsResponse.data);
59
+ }
60
+ }).catch(
61
+ (e) => alertApi.post({ message: `${e.message}`, severity: "error" })
62
+ );
63
+ setSubmittingState(false);
64
+ }, [filters, groups, monthRangeState, granularity, infraWalletApi, alertApi]);
65
+ useEffect(() => {
66
+ if (reports.length !== 0) {
67
+ const arrgegatedReports = aggregateCostReports(reports, aggregatedBy);
68
+ const aggregatedAndMergedReports = mergeCostReports(
69
+ arrgegatedReports,
70
+ MERGE_THRESHOLD
71
+ );
72
+ const allTags = getAllReportTags(reports);
73
+ setReportsAggregated(arrgegatedReports);
74
+ setReportsAggregatedAndMerged(aggregatedAndMergedReports);
75
+ setReportTags(allTags);
76
+ }
77
+ }, [reports, aggregatedBy]);
78
+ useEffect(() => {
79
+ fetchCostReportsCallback();
80
+ }, [fetchCostReportsCallback]);
81
+ return /* @__PURE__ */ React.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React.createElement(Header, { title: "InfraWallet" }), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 3 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
82
+ TopbarComponent,
83
+ {
84
+ aggregatedBy,
85
+ aggregatedBySetter: setAggregatedBy,
86
+ tags: reportTags,
87
+ granularity,
88
+ granularitySetter: setGranularity,
89
+ monthRange: monthRangeState,
90
+ monthRangeSetter: setMonthRangeState
91
+ }
92
+ )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, submittingState ? /* @__PURE__ */ React.createElement(Progress, null) : null), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12, md: 4, lg: 3 }, reportsAggregatedAndMerged.length > 0 && /* @__PURE__ */ React.createElement(
93
+ PieChartComponent,
94
+ {
95
+ categories: reportsAggregatedAndMerged.map(
96
+ (item) => item.id
97
+ ),
98
+ series: reportsAggregatedAndMerged.map(
99
+ (item) => getTotalCost(item)
100
+ ),
101
+ height: 350
102
+ }
103
+ )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12, md: 8, lg: 9 }, reportsAggregatedAndMerged.length > 0 && /* @__PURE__ */ React.createElement(
104
+ ColumnsChartComponent,
105
+ {
106
+ categories: Object.keys(reportsAggregatedAndMerged[0].reports),
107
+ series: reportsAggregatedAndMerged.map((item) => ({
108
+ name: item.id,
109
+ data: rearrangeData(
110
+ item,
111
+ Object.keys(reportsAggregatedAndMerged[0].reports)
112
+ )
113
+ })),
114
+ height: 350
115
+ }
116
+ )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, reportsAggregated.length > 0 && /* @__PURE__ */ React.createElement(
117
+ CostReportsTableComponent,
118
+ {
119
+ reports: reportsAggregated,
120
+ aggregatedBy
121
+ }
122
+ )))));
123
+ };
124
+
125
+ export { ReportsComponent };
126
+ //# sourceMappingURL=ReportsComponent.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReportsComponent.esm.js","sources":["../../../src/components/ReportsComponent/ReportsComponent.tsx"],"sourcesContent":["import {\n Content,\n Header,\n HeaderLabel,\n Page,\n Progress,\n} from '@backstage/core-components';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\nimport { Grid } from '@material-ui/core';\nimport { addMonths, endOfMonth, startOfMonth } from 'date-fns';\nimport React, { useCallback, useEffect, useState } from 'react';\nimport { infraWalletApiRef } from '../../api/InfraWalletApi';\nimport {\n aggregateCostReports,\n mergeCostReports,\n getAllReportTags,\n} from '../../api/functions';\nimport { Report } from '../../api/types';\nimport { ColumnsChartComponent } from '../ColumnsChartComponent';\nimport { CostReportsTableComponent } from '../CostReportsTableComponent';\nimport { PieChartComponent } from '../PieChartComponent';\nimport { TopbarComponent } from '../TopbarComponent';\nimport { MonthRange } from '../types';\n\nconst getTotalCost = (report: Report): number => {\n let total = 0;\n Object.keys(report.reports).forEach((s: string) => {\n total += report.reports[s];\n });\n return total;\n};\n\nconst rearrangeData = (report: Report, periods: string[]): any[] => {\n const costs: any[] = [];\n periods.forEach((s: string) => {\n if (report.reports[s] !== undefined) {\n costs.push(report.reports[s]);\n } else {\n costs.push(null);\n }\n });\n return costs;\n};\n\nexport const ReportsComponent = () => {\n const MERGE_THRESHOLD = 8;\n const [submittingState, setSubmittingState] = useState<Boolean>(false);\n const [reports, setReports] = useState<Report[]>([]);\n const [reportsAggregated, setReportsAggregated] = useState<Report[]>([]);\n const [reportsAggregatedAndMerged, setReportsAggregatedAndMerged] = useState<\n Report[]\n >([]);\n const [reportTags, setReportTags] = useState<string[]>([]);\n const [granularity, setGranularity] = useState<string>('monthly');\n const [aggregatedBy, setAggregatedBy] = useState<string>('none');\n const [filters, setFilters] = useState<string>('');\n const [groups, setGroups] = useState<string>('');\n const [monthRangeState, setMonthRangeState] = React.useState<MonthRange>({\n startMonth: startOfMonth(addMonths(new Date(), -2)),\n endMonth: endOfMonth(new Date()),\n });\n\n const alertApi = useApi(alertApiRef);\n const infraWalletApi = useApi(infraWalletApiRef);\n\n const fetchCostReportsCallback = useCallback(async () => {\n setSubmittingState(true);\n await infraWalletApi\n .getCostReports(\n filters,\n groups,\n granularity,\n monthRangeState.startMonth,\n monthRangeState.endMonth,\n )\n .then(reportsResponse => {\n if (reportsResponse.data && reportsResponse.data.length > 0) {\n setReports(reportsResponse.data);\n }\n })\n .catch(e =>\n alertApi.post({ message: `${e.message}`, severity: 'error' }),\n );\n setSubmittingState(false);\n }, [filters, groups, monthRangeState, granularity, infraWalletApi, alertApi]);\n\n useEffect(() => {\n if (reports.length !== 0) {\n const arrgegatedReports = aggregateCostReports(reports, aggregatedBy);\n const aggregatedAndMergedReports = mergeCostReports(\n arrgegatedReports,\n MERGE_THRESHOLD,\n );\n const allTags = getAllReportTags(reports);\n setReportsAggregated(arrgegatedReports);\n setReportsAggregatedAndMerged(aggregatedAndMergedReports);\n setReportTags(allTags);\n }\n }, [reports, aggregatedBy]);\n\n useEffect(() => {\n fetchCostReportsCallback();\n }, [fetchCostReportsCallback]);\n\n return (\n <Page themeId=\"tool\">\n <Header title=\"InfraWallet\" />\n <Content>\n <Grid container spacing={3}>\n <Grid item xs={12}>\n <TopbarComponent\n aggregatedBy={aggregatedBy}\n aggregatedBySetter={setAggregatedBy}\n tags={reportTags}\n granularity={granularity}\n granularitySetter={setGranularity}\n monthRange={monthRangeState}\n monthRangeSetter={setMonthRangeState}\n />\n </Grid>\n <Grid item xs={12}>\n {submittingState ? <Progress /> : null}\n </Grid>\n <Grid item xs={12} md={4} lg={3}>\n {reportsAggregatedAndMerged.length > 0 && (\n <PieChartComponent\n categories={reportsAggregatedAndMerged.map(\n (item: any) => item.id,\n )}\n series={reportsAggregatedAndMerged.map((item: any) =>\n getTotalCost(item),\n )}\n height={350}\n />\n )}\n </Grid>\n <Grid item xs={12} md={8} lg={9}>\n {reportsAggregatedAndMerged.length > 0 && (\n <ColumnsChartComponent\n categories={Object.keys(reportsAggregatedAndMerged[0].reports)}\n series={reportsAggregatedAndMerged.map((item: any) => ({\n name: item.id,\n data: rearrangeData(\n item,\n Object.keys(reportsAggregatedAndMerged[0].reports),\n ),\n }))}\n height={350}\n />\n )}\n </Grid>\n <Grid item xs={12}>\n {reportsAggregated.length > 0 && (\n <CostReportsTableComponent\n reports={reportsAggregated}\n aggregatedBy={aggregatedBy}\n />\n )}\n </Grid>\n </Grid>\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ import { Box, FormControl, Select, MenuItem, FormHelperText, Grid, Button } from '@material-ui/core';
2
+ import Divider from '@material-ui/core/Divider';
3
+ import InputLabel from '@material-ui/core/InputLabel';
4
+ import ListSubheader from '@material-ui/core/ListSubheader';
5
+ import { makeStyles } from '@material-ui/core/styles';
6
+ import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
7
+ import { DatePicker } from '@mui/x-date-pickers/DatePicker';
8
+ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
9
+ import { startOfMonth, endOfMonth, addMonths } from 'date-fns';
10
+ import React from 'react';
11
+
12
+ const useStyles = makeStyles((theme) => ({
13
+ formControl: {
14
+ marginLeft: theme.spacing(1),
15
+ marginRight: theme.spacing(3),
16
+ minWidth: 120
17
+ }
18
+ }));
19
+ const TopbarComponent = ({
20
+ aggregatedBy,
21
+ aggregatedBySetter,
22
+ tags,
23
+ granularity,
24
+ granularitySetter,
25
+ monthRange,
26
+ monthRangeSetter
27
+ }) => {
28
+ const classes = useStyles();
29
+ const setPreDefinedMonthRange = (lastXMonth) => {
30
+ monthRangeSetter({
31
+ startMonth: startOfMonth(addMonths(/* @__PURE__ */ new Date(), lastXMonth * -1)),
32
+ endMonth: endOfMonth(/* @__PURE__ */ new Date())
33
+ });
34
+ };
35
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(FormControl, { className: classes.formControl }, /* @__PURE__ */ React.createElement(InputLabel, { shrink: true }, "Group by"), /* @__PURE__ */ React.createElement(
36
+ Select,
37
+ {
38
+ value: aggregatedBy,
39
+ onChange: (event) => aggregatedBySetter(event.target.value)
40
+ },
41
+ /* @__PURE__ */ React.createElement(MenuItem, { value: "none" }, /* @__PURE__ */ React.createElement("em", null, "None")),
42
+ /* @__PURE__ */ React.createElement(MenuItem, { value: "name" }, "Name"),
43
+ /* @__PURE__ */ React.createElement(MenuItem, { value: "provider" }, "Provider"),
44
+ /* @__PURE__ */ React.createElement(MenuItem, { value: "category" }, "Category"),
45
+ /* @__PURE__ */ React.createElement(MenuItem, { value: "service" }, "Cloud Service"),
46
+ /* @__PURE__ */ React.createElement(Divider, { light: true }),
47
+ /* @__PURE__ */ React.createElement(ListSubheader, { onClickCapture: (e) => e.stopPropagation() }, "Tags"),
48
+ tags.map((tag) => /* @__PURE__ */ React.createElement(MenuItem, { key: tag, value: tag }, `tag:${tag}`))
49
+ )), /* @__PURE__ */ React.createElement(FormControl, { className: classes.formControl, style: { display: "none" } }, /* @__PURE__ */ React.createElement(
50
+ Select,
51
+ {
52
+ value: granularity,
53
+ onChange: (event) => granularitySetter(event.target.value)
54
+ },
55
+ /* @__PURE__ */ React.createElement(MenuItem, { value: "daily" }, "Daily"),
56
+ /* @__PURE__ */ React.createElement(MenuItem, { value: "monthly" }, "Monthly")
57
+ ), /* @__PURE__ */ React.createElement(FormHelperText, null, "Granularity")), /* @__PURE__ */ React.createElement(FormControl, { className: classes.formControl }, /* @__PURE__ */ React.createElement(LocalizationProvider, { dateAdapter: AdapterDateFns }, /* @__PURE__ */ React.createElement(
58
+ DatePicker,
59
+ {
60
+ value: monthRange.startMonth,
61
+ label: "From",
62
+ views: ["year", "month"],
63
+ slotProps: { textField: { variant: "standard" } },
64
+ onAccept: (value) => {
65
+ if (value) {
66
+ monthRangeSetter({
67
+ startMonth: startOfMonth(value),
68
+ endMonth: endOfMonth(monthRange.endMonth)
69
+ });
70
+ }
71
+ }
72
+ }
73
+ ))), /* @__PURE__ */ React.createElement(FormControl, { className: classes.formControl }, /* @__PURE__ */ React.createElement(LocalizationProvider, { dateAdapter: AdapterDateFns }, /* @__PURE__ */ React.createElement(
74
+ DatePicker,
75
+ {
76
+ value: monthRange.endMonth,
77
+ label: "To",
78
+ views: ["year", "month"],
79
+ slotProps: { textField: { variant: "standard" } },
80
+ onAccept: (value) => {
81
+ if (value) {
82
+ monthRangeSetter({
83
+ startMonth: startOfMonth(monthRange.startMonth),
84
+ endMonth: endOfMonth(value)
85
+ });
86
+ }
87
+ }
88
+ }
89
+ ))), /* @__PURE__ */ React.createElement(FormControl, { className: classes.formControl }, /* @__PURE__ */ React.createElement(FormHelperText, null, "Quick selections for month ranges"), /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 3 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Button, { color: "primary", onClick: () => setPreDefinedMonthRange(2) }, "Last 3 Months"), /* @__PURE__ */ React.createElement(Button, { color: "primary", onClick: () => setPreDefinedMonthRange(5) }, "Last 6 Months"), /* @__PURE__ */ React.createElement(Button, { color: "primary", onClick: () => setPreDefinedMonthRange(11) }, "Last 12 Months")))));
90
+ };
91
+
92
+ export { TopbarComponent };
93
+ //# sourceMappingURL=TopbarComponent.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TopbarComponent.esm.js","sources":["../../../src/components/TopbarComponent/TopbarComponent.tsx"],"sourcesContent":["import {\n Box,\n Button,\n FormControl,\n FormHelperText,\n Grid,\n MenuItem,\n Select,\n} from '@material-ui/core';\nimport Divider from '@material-ui/core/Divider';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport ListSubheader from '@material-ui/core/ListSubheader';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';\nimport { DatePicker } from '@mui/x-date-pickers/DatePicker';\nimport { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';\nimport { addMonths, endOfMonth, startOfMonth } from 'date-fns';\nimport React, { FC } from 'react';\nimport { TopbarComponentProps } from '../types';\n\nconst useStyles = makeStyles(theme => ({\n formControl: {\n marginLeft: theme.spacing(1),\n marginRight: theme.spacing(3),\n minWidth: 120,\n },\n}));\n\nexport const TopbarComponent: FC<TopbarComponentProps> = ({\n aggregatedBy,\n aggregatedBySetter,\n tags,\n granularity,\n granularitySetter,\n monthRange,\n monthRangeSetter,\n}) => {\n const classes = useStyles();\n\n const setPreDefinedMonthRange = (lastXMonth: number) => {\n monthRangeSetter({\n startMonth: startOfMonth(addMonths(new Date(), lastXMonth * -1)),\n endMonth: endOfMonth(new Date()),\n });\n };\n\n return (\n <Box>\n <FormControl className={classes.formControl}>\n <InputLabel shrink>Group by</InputLabel>\n <Select\n value={aggregatedBy}\n onChange={event => aggregatedBySetter(event.target.value)}\n >\n <MenuItem value=\"none\">\n <em>None</em>\n </MenuItem>\n <MenuItem value=\"name\">Name</MenuItem>\n <MenuItem value=\"provider\">Provider</MenuItem>\n <MenuItem value=\"category\">Category</MenuItem>\n <MenuItem value=\"service\">Cloud Service</MenuItem>\n <Divider light />\n <ListSubheader onClickCapture={e => e.stopPropagation()}>\n Tags\n </ListSubheader>\n {tags.map(tag => (\n <MenuItem key={tag} value={tag}>\n {`tag:${tag}`}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n\n <FormControl className={classes.formControl} style={{ display: 'none' }}>\n <Select\n value={granularity}\n onChange={event => granularitySetter(event.target.value)}\n >\n <MenuItem value=\"daily\">Daily</MenuItem>\n <MenuItem value=\"monthly\">Monthly</MenuItem>\n </Select>\n <FormHelperText>Granularity</FormHelperText>\n </FormControl>\n\n <FormControl className={classes.formControl}>\n <LocalizationProvider dateAdapter={AdapterDateFns}>\n <DatePicker\n value={monthRange.startMonth}\n label=\"From\"\n views={['year', 'month']}\n slotProps={{ textField: { variant: 'standard' } }}\n onAccept={value => {\n if (value) {\n monthRangeSetter({\n startMonth: startOfMonth(value),\n endMonth: endOfMonth(monthRange.endMonth),\n });\n }\n }}\n />\n </LocalizationProvider>\n </FormControl>\n\n <FormControl className={classes.formControl}>\n <LocalizationProvider dateAdapter={AdapterDateFns}>\n <DatePicker\n value={monthRange.endMonth}\n label=\"To\"\n views={['year', 'month']}\n slotProps={{ textField: { variant: 'standard' } }}\n onAccept={value => {\n if (value) {\n monthRangeSetter({\n startMonth: startOfMonth(monthRange.startMonth),\n endMonth: endOfMonth(value),\n });\n }\n }}\n />\n </LocalizationProvider>\n </FormControl>\n\n <FormControl className={classes.formControl}>\n <FormHelperText>Quick selections for month ranges</FormHelperText>\n <Grid container spacing={3}>\n <Grid item xs={12}>\n <Button color=\"primary\" onClick={() => setPreDefinedMonthRange(2)}>\n Last 3 Months\n </Button>\n <Button color=\"primary\" onClick={() => setPreDefinedMonthRange(5)}>\n Last 6 Months\n </Button>\n <Button color=\"primary\" onClick={() => setPreDefinedMonthRange(11)}>\n Last 12 Months\n </Button>\n </Grid>\n </Grid>\n </FormControl>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ import * as react from 'react';
3
+ import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
4
+
5
+ declare const infraWalletPlugin: _backstage_core_plugin_api.BackstagePlugin<{
6
+ root: _backstage_core_plugin_api.RouteRef<undefined>;
7
+ }, {}, {}>;
8
+ declare const InfraWalletPage: () => react.JSX.Element;
9
+
10
+ export { InfraWalletPage, infraWalletPlugin };
@@ -0,0 +1,2 @@
1
+ export { InfraWalletPage, infraWalletPlugin } from './plugin.esm.js';
2
+ //# sourceMappingURL=index.esm.js.map